Java - Get list of file names in the current JAR - java

I need to get the file names of each file that is in a particular folder inside my program's JAR while it is running. Is it possible to do this? I'm not sure where to start.
It needs to be done programmatically and be platform independent.

To list the contents of a jar file, simply run:
$jar tf MyJar.jar
Are you looking to do this programmatically from within java?
To do it programmatically, see this example.

You are asking for something that isn't available in general. Classes are loaded via ClassLoader instances, which may get class bytecode from many different places (network, jar file, .class files in a directory, dynamically generated).
The most you can know is the package hierarchy, which you can get from
myObject.getClass().getClassLoader().getPackages()
which returns a list of packages available at the point of invocation. For a given package you probably won't be able to tell where it came from.

Related

Referencing wrong jar file in java build-path

In my project we are referencing lot of dependency .jar files.
/lib/xxx.jar
/lib/abc.jar
The xxx.jar file having some (com.search.hit) packages. The same packages are available in abc.jar file.But the problem comes into picture now, where accessing xxx.jar file it doesn't referencing their package(com.search.hit) instead it is referencing abc.jar package.
Could anyone tell how to redirect the flow?
The class from whichever jar comes first on the classpath is the one that is used. The other one might not even exist as far as the classloader is concerned. It's a good idea to avoid conflicts like this.
In Eclipse go to your project build path configuration and click on the Libraries tab.
Then remove the package that you don't want to be accessed from your list and add it again.
This will cause the package to be lower in the priority list and it'll check the other package before the one you just re-added.
This will create problems for you. My suggestion would be to create 2 extra classes for writing getter and setter wrappers for these jar files. Write 2 seperate classes, each one of them will reference just one of them and your project file will use these wrapper classes to invoke functions from these jars. It would be a lot easier that way.
You have to change the package name it can not be same file name with same package in single JVM. JVM will take load randomly one jar class using class loader and ignore the rest.

Java Game refering to files

I have started getting into game programming.
My question is, that when I am working with files, either parsing data, writing to files, etc. Should I be using relative path names, or absolute pathnames, or something else which is better. I've heard about using jar files, but I am not sure
1. how that works
2. if it is a good way to do it.
So when developing a game that will be cross platform, what is the best method for managing files that the program will need to read from and write to.
there are several ways in which you can ship your code as a product. the most common are
packaging everything in one executable jar file.
having a set of folders where you place all necessary resources.
minecraft, for example, is written in java and distributed as a single executable jar file that contains all necessary class files and resources. to run the game (assuming you have java installed) all you need to do is double-click the jar file.
read this short tutorial about how to add a main class to a jar file.
either way, always treat classes and resources in your code as if they're in your classpath. for example, if you have a my.properties file on the root of the source tree then load it by using 'my.properties'. if you put it under a 'conf' folder then use 'conf/my.properties'.
i think it is the safest way not to get lost.
are you using maven?
The jar file is a zip of all your compiled *.class files and your resources. You can safely load your resources and even default data FROM a jar if you package your program, but you can NOT safely write data back to the jar. This detail is answered in depth already at
How can an app use files inside the JAR for read and write?
For information on how to package a jar see
http://docs.oracle.com/javase/tutorial/deployment/jar/

Java packages and compilation (why, not how)

I'm working on some Java code in eclipse. Code is contained in a single class called Adder, which in Eclipse is in the package org.processing. The first thing in the class file is the line
package org.processing
Q1) What, exactly is this line doing? Why is there, what's it's role.
The code runs fine in eclipse, however, when I move into the workspace if I go to the src/org/processing/ folder in src, compile with javac Adder.class when I try and run using java Adder I get the following error
java.lang.NoClassDefFoundError: Adder (wrong name: org/processing/Adder)
On the other hand, if I compile from src using
javac org/processing/Adder.java
and I can run it from src using java org.processing.Adder but STILL not from within the processing directory.
Q2) Does this mean that compilation is always relative to directory structure?
Finally, if I remove the package org.processing line from the start are the .class file I can compile and run from within the .class file's directory.
Q3) Why is all this the way it is? I can fully understand enforcing a directory structure for code development, but once you're in bytecode this seems a bit over the top, because now I can (apparently) only run the bytecode from one director (src) using java org.processing.Adder. Now, I'm sure I'm missing the point here, so if someone could point out what it is, that would be great.
The compiler has to be able to find related source code files when compiling. This is why the package and directory structure must agree for source code. Similarly, the JVM must be able to find referenced .class files. So the same directory structure is required at runtime. It's no more complex than that.
Q1) The issue here is that once you got into the folders that represent your package hierarchy, you set that as the working directory. It's gonna look inside of org/processing/Adder for the path org/processing/Adder (essentially looking from the root for org/processing/Adder/org/processing/Adder). You need to call it from the root with the full path. The purpose of packages is A: to organize related classes into groups. And B: Along with A, classes in package Foo.bar can't view private classes in other packages, as they are like internal classes for that package, only the package they're in can use them
Q2) Yes
Q3) The paths are used as a basic structure for the JVM to know where exactly the class files (each containing their bytecode) are. If you change where you call it from, your basically trying to change the location for the JVM to look for the class files, but their true location hasn't changed.
The short answer - Packages help keep your project structure well-organized, allow you to reuse names (try having two classes named Account), and are a general convention for very large projects. They're nothing more than folder structures, but why they're used can burn beginners pretty badly. Funnily enough, with a project less than 5 classes, you probably won't need it.
What, exactly is this line doing? Why is there, what's it's role.
The line
package org.processing
is telling Java that this class file lives in a folder called /org/processing. This allows you to have a class which is fully defined as org.processing.Processor here, and in another folder - let's say /org/account/processing, you can have a class that's fully defined as org.account.processing.Processor. Yes, both use the same name, but they won't collide - they're in different packages. If you do decide to use them in the same class, you would have to be explicit about which one you want to use, either through the use of either import statements or the fully qualified object name.
Does this mean that compilation is always relative to directory structure?
Yes. Java and most other languages have a concept known as a classpath. Anything on this classpath can be compiled and run, and by default, the current directory you're in is on the classpath for compilation and execution. To place other files on the classpath, you would have to use another command-line invocation to your compilation:
javac -sourcepath /path/to/source MainClass.java
...and this would compile everything in your source path to your current directory, neatly organized in the folder structure specified by your package statements.
To run them, as you've already established, you would need to include the compiled source in your classpath, and then execute via the fully qualified object name:
java -cp /path/to/source org.main.MainClass
Why is all this the way it is?
Like I said before, this is mostly useful for very large projects, or projects that involve a lot of other classes and demand structure/organization, such as Android. It does a few things:
It keeps source organized in an easy-to-locate structure. You don't have objects scattered all over the place.
It keeps the scope of your objects clear. If I had a package named org.music.db, then it's pretty clear that I'm messing with objects that deal with the database and persistence. If I had a package named org.music.gui, then it's clear that this package deals with the presentation side. This can help when you want to create a new feature, or update/refactor an existing one; you can remember what it does, but you can't recall its name exactly.
It allows you to have objects with the same name. There is more than one type of Map out there, and if you're using projects that pull that in, you'd want to be able to specify which Map you get - again, accomplished through either imports or the fully qualified object name.
For Q1: The package declaration allows you to guarantee that your class will never be mistaken for another class with the same name. This is why most programmers put their company's name in the package; it's unlikely that there will be a conflict.
For Q2: There is a one-to-one correspondence between the package structure and the directory structure. The short of it is that directories and packages must be the same, excepting the package is usually rooted under a folder called src.
For Q3: Once it's compiled, the class files will probably be in the appropriate folders in a jar file. Your ant or maven tasks will build the jar file so you won't really have to bother with it beyond getting the ant task set up the first time.

How to list all class names in the current package with Java?

In my Java project I need to list all class names in the current package, I usually run my app in two different modes : <1> From NetBeans, <2> From an executable jar file packaged by the NetBeans.
My question is : How to write my program so that no matter which mode it is running, it can list all the class names in my app. Because when I run it in the NetBeans mode I can look into the src/ directory to list the class names, but when run in the packaged executable jar file mode on another machine, the src/ dir isn't there, so if in my program I try to list jar entries and find the class names that way, it won't work when run in NetBeans, because it isn't jared yet.
I know I can try to detect which mode it is running under and handle differently, but is there a better way to do it without knowing which mode it is running under ?
I wonder if the following approach would solve my problem :
http://snippets.dzone.com/posts/show/4831
I tried : getClasses(".") to get current package's classes, it didn't work, why ?
Frank
Provided you are not using any dynamic class loaders you can search the classpath and for each entry search the directory or JAR file.
You can not tell which classes are in a package. This is because everyone can add other classes to your packages (for instance from other jar files).
However there are functions in the java API to look into jar files. It wouldn't be entirely independent of the way of running though.

Programmatically compile Java class in a package stored in an arbitrary sub folder

I am looking to compile an application in Java, made up of a various number of java classes in a certain number of packages. At the command line, I can change to the folder containing the root package and type:
javac rootpackage/subpackage/*.java
or
javac rootpackage/*/*.java
to compile all the java classes in all the primary subpackages of my rootpackage.
However I would like to be able to do this within a Java application. (The idea is that we provide an application to students which contains unit tests. The unit tests need to be run against their code, the application then creates a JAR file containing their source files which have been 'watermarked' with the test results. All this works ok, but we would like to make sure that the class files tested are created from the source files submitted, hence the idea to compile programmatically the java sources).
The problem comes in that each student stores their root package in an arbitrary position, and I cannot seem to pass the location of the file to JavaCompiler (javax.tools).
Is it possible, and if so, can someone give some hints on how to have an arbitrary placed root package compiled properly.
Cheers
Richard
More Info:
a student has a folder structure:
/home/student/work/java/myproject/
which contains the root package. They launch the application (possibly stored in this folder - and thus no problems- however more than likely stored elsewhere) which asks them for the folder that contains the root package. After entering, the students click a create JAR button, that compiles the files in their packages, runs the tests on the newly compiled files and then creates the JAR.
Whilst thinking through this problem, it is possible that the solution is to tell the students to install our 'create JAR' application in the folder containing their root package.
Could you peek at the top of each .java file for the line beginning:
package com.blah.blah.assignment;
i.e. look for the start of the package name and then look for the first directory in your search path beginning com (in this example), and then give this path to the JavaCompiler object, or have I misunderstood your question?
Having just looked at the javax.tools package, why not create a composite wrapper for the javaFilemanager which wraps a ForwardingjavaFileManager which will forward all requests for the methods such as getFileForInput or getJavaFileForInput down to the appropriate starting directory in the student's source directory (as decided by your preliminary bit of parsing of the first .java file to determine the root of their sourcepath)
The last argument to JavaCompiler.getTask() is an Iterable<? extends JavaFileObject> containing the compilation units to pass to the compiler. One of the provided implementations of JavaFileObject is SimpleFileJavaObject (http://java.sun.com/javase/6/docs/api/javax/tools/SimpleJavaFileObject.html). This is constructed with a java.net.URI object, which can be created easily from a File object. Putting it all together, do something like this:
List<JavaFileObject> javaFiles = new ArrayList<JavaFileObject>();
File javaFile = new File(rootPackageDirFromUser, fileNameInRootDir);
URI javaURI = javaFile.toURI();
javaFiles.add(new SimpleJavaFileObject(javaURI, JavaFileObject.Kind.SOURCE));
JavaCompiler.CompilationTask task =
ToolProvider.getSystemJavaCompiler().getTask(..., javaFiles);
where rootPackageDirFromUser is given by the user, who tells you where they stored the files, and fileNameInRootDir is the name of a java source file in that dir. If you don't know the file names in advance, you'll need to iterate over the rootPackageDirFromUser to construct a list.
I haven't tested this, but that should give you the general idea.

Categories