I need to get all the .class files located in a .jar file which in turn is located within another .ear file.
I am trying to use the JarInputStream to get access to the .ear. This is working ok. However, when I iterate the JarEntry elements inside the JarInputStream, I can't seem to be able to open it as a Jar file in order to read any .class elements within it.
JarInputStream jarFile = new JarInputStream(new FileInputStream("c:/path/to/my/.ear"));
JarEntry jarEntry = null;
while(true) {
jarEntry = jarFile.getNextJarEntry();
if(jarEntry == null) {
break;
}
if((jarEntry.getName().endsWith(".jar"))) {
//Access to the nested jar?
}
}
Edited: worth mentioning that the code above is in the same jar as the classes I am trying to find programmatically.
You should first extract the .jar file from the .ear file and then try to read the class file.
In fact, that's how even the Application Servers do. They extract the EAR file into a temporary directory and then load the classes from there.
Did you try this?
[...]
if((jarEntry.getName().endsWith(".jar"))) {
JarInputStream subJarStream = new JarInputStream(jarFile);
// the same search again
}
Related
I want to access file on my classpath called reports/invoiceSweetChoice.jasper in jar on production server. Whatever I do I get null.
I have tried this.getClass().getResourceAsStream("reports/invoiceSweetChoice.jasper"), tried via InputStream etc. I have printed out content of System.getProperty("java.class.path") and it is empty. Not sure how is that possible. Do you have any suggestion how to resolve this ?
In manifest.mf, the classpath is defined using the class-path key and a space-delimited list of files, as follows:
MANIFEST.MF at root of jarfile.
Class-Path: hd1.jar path/to/label007.jar path/to/foo.jar
If there are spaces in the jar filename, you should enclose them in quotes.
If it's a webapp, the reports path should be in your BOOT-INF subdirectory of your classpath -- this is automatically performed by maven if you put it in src/main/resources in the standard layout.
EDIT:
Now that you've clarified what you're trying to do, you have 2 approaches. Like I said above, you can grab the file from the BOOT-INF subdirectory of your webapp or you can enumerate the entries in the jar until you find the one you want:
JarInputStream is = new JarInputStream(new FileInputStream("your/jar/file.jar"));
JarEntry obj = null
while ((obj = is.getNextJarEntry()) != null) {
JarEntry entry = (JarEntry)obj;
if (entry.getName().equals("file.abc")) {
ByteArrayOutputStream baos = new ByetArrayOutputStream();
IOUtils.copy(jarFile.getInputStream(entry), baos);
String contents = new String(baos.toByteArray(), "utf-8");
// your entry is now read into contents
}
}
#Autowired private ResourceLoader resLoad;
void someMethod() {
Resource r = resLoad.getResource("classpath:reports/file.abc");
r.getInputStream()...
...
Right now I'm manually writing song file names into a String array, then sending the strings to InputStream is = this.getClass().getResourceAsStream(filename); to play the song.
I would rather loop through all the song names in my resources folder and load them into the array so that each time I add a song, I don't need to manually type it into the array.
All of my songs are located in resources folder:
Is there a java method or something to grab these names?
The files need to work when I export as .jar.
I thought I could use something like this?
InputStream is = this.getClass().getClassLoader().getResourceAsStream("resources/");
Is there a listFiles() or something for that?
Thanks
No, because the classpath is dynamic in Java. Any additional Jar could contribute to a package, a classloader can be as dynamic as imaginable and could even dynamically create classes or resources on demand.
If you have a specific JAR file and you know the path within that JAR file then you could simply treat that file as archive and access it via java.util.jar.JarFile which lets you list all entries in the file.
JarFile jar = new JarFile("res.jar");
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
System.out.println(entry.getName());
}
If you want to do this without knowing the JAR filename and path (e.g. by a class within the JAR itself) you need to get the filename dynamically as Evgeniy suggested; just use your own class name (including package; your screenshot looks like you are in default package, which is a bad idea).
You can try something like this
Enumeration<URL> e = ClassLoader.getSystemResources("org/apache/log4j");
while (e.hasMoreElements()) {
URL u = e.nextElement();
String file = u.getFile();
...
file:/D:/.repository/log4j/log4j/1.2.14/log4j-1.2.14.jar!/org/apache/log4j
extract jar path from here and use JarFile class to know org/apache/log4j contents.
If it is unpacked, you will get straight path and use File.listFIles
I am trying to access a directory inside my jar file. I want to go through every of the files inside the directory itself. I tried using the following:
File[] files = new File("ressources").listFiles();
for (File file : files) {
XMLParser parser = new XMLParser(file.getAbsolutePath());
// some work
}
If I test this, it works well. But once I put the contents into the jar, it doesn't because of several reasons. If I use this code, the URL always points outside the jar.
structure of my project :
src
controllers
models
class that containt traitement
views
ressources
See this:
How do I list the files inside a JAR file?
Basically, you just use a ZipInputStream to find a list of files (a .jar is the same as a .zip)
Once you know the names of the files, you can use getClass().getResource(String path) to get the URL to the file.
I presume this jar is on your classpath.
You can list all the files in a directory using the ClassLoader.
First you can get a list of the file names then you can get URLs from the ClassLoader for individual files:
public static void main(String[] args) throws Exception {
final String base = "/path/to/folder/inside/jar";
final List<URL> urls = new LinkedList<>();
try (final Scanner s = new Scanner(MyClass.class.getResourceAsStream(base))) {
while (s.hasNext()) {
urls.add(MyClass.class.getResource(base + "/" + s.nextLine()));
}
}
System.out.println(urls);
}
You can do whatever you want with the URL - either read and InputStream into memory or copy the InputStream into a File on your hard disc.
Note that this definitely works with the URLClassLoader which is the default, if you are using an applet or a custom ClassLoader then this approach may not work.
NB:
You have a typo - its resources not ressources.
You should use reverse domain name notation for your project, this is the convention.
I'm trying to figure out how to add a lot of images into my Java program without having to add every file name in the code.
So I want to take all the .png images in the correct folder and make them into an IconImage and then place them in an ArrayList.
What I've got right now is this.
private void fillList()
{
File[] files = new File("C:/Users/marre/Google Drive/Java/lek/imageplay/src/img").listFiles();
for (File f : files)
{
if (f.isFile())
{
ImageIcon tempIcon = new ImageIcon(getClass().getResource("/img/"+f.getName()));
List.add(tempIcon);
}
}
}
This works the way I want it to regarding getting the names of all images. But the file only reads from absolute file path.
What can I use instead to get the same result, but that works within .jar file (so it reads from src/img/ and not the whole c:/ bla bla..)?
I'm not sure if this will be helpful but I had a similar issue in attempting to obtain files within a jar file. In the case this can be useful to you, my approach was to obtain the URL for the files inside the jar using the ClassLoader:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url = classLoader.getResource("src/img/");
Check inside your jar to make sure of the directory structure for the images so you can specify the correct relative path.
Keep in mind, a jar is a packaged form, so this will most likely return a zipped file (and not a simple File object). You might have to dabble in ZipFile.
ZipFile folderInsideJar = new ZipFile(new File(url.getPath());
Enumeration<? extends ZipEntry> entries = folderInsideJar.entries();
while (entries.hasMoreElements()) {
// ideally this would be your image file, zipped
ZipEntry childFile = entries.nextElement();
// ... etc ...
}
For environments such as JBoss, etc, you might also get virtual files (vfsfile/vfszip). Point being, you can determine what you are dealing with by looking at the result URL.getProtocol().
It would also appear ImageIcon has a constructor that takes a URL. You might try giving this a shot to see if it handles the "resource inside jar" case before manually attempting to retrieve the zip file.
Assume the file name is in this URL:
URL file = new URL("jar:file:/path/to/foo.jar!/META-INF/file.txt");
This operation leads to IOException if there is no foo.jar or there is no file.txt inside the existing jar:
import org.apache.commons.io.FileUtils;
FileUtils.copyURLToFile(file, /* some other file */);
Is it possible to validate file existence without exception catching?
You can use the java.util.jar.JarFile class, and use the getJarEntry method to see if the file exists.
JarFile jar = new JarFile("foo.jar");
JarEntry entry = jar.getJarEntry("META-INF/file.txt");
if (entry != null) {
// META-INF/file.txt exists in foo.jar
}
You can examine the CLASSPATH and search for the jar yourself. Then you can inspect the jar yourself. I guess it will not be faster than your way, nor will it be more easy to understand, so why do you want to avoid the Exception?
I don't see something wrong in using the exception.