0

I am trying to read package name from a jar file. My probem is that when I get URL, it contains unrecognized form to be recognized by windows file.

I read this solution. But this did not helped me. Convert URL to normal windows filename Java.

directoryURL.toURI().getSchemeSpecificPart() does not convert windows style.

This is my code.

// Get a File object for the package
URL directoryURL = Thread.currentThread().getContextClassLoader()
            .getResource(packageNameSlashed);

logger.info("URI" + directoryURL.toURI());
logger.info("Windows file Name" + directoryURL.toURI().getSchemeSpecificPart());

// build jar file name, then loop through zipped entries
jarFileName = URLDecoder.decode(directoryURL.getFile(), "UTF-8");
jarFileName = jarFileName.substring(0, jarFileName.indexOf(".jar"));

// HERE Throws exception"
jf = new JarFile(jarFileName + ".jar");

while (jarEntries.hasMoreElements()) {
                entryName = jarEntries.nextElement().getName();
                logger.info("Entry name: " + entryName);
                if (entryName.startsWith(packageNameSlashed)
                        && entryName.length() > packageNameSlashed.length() + 5
                        && entryName.endsWith(".class")) {
                    entryName = entryName.substring(packageNameSlashed.length() + 1);
                    packageClassNames.put(entryName, packageName);
                }
            }

This is log.

16-02-2015 14:02:15 INFO  - URI jar:file:/C:/SVN/AAA/trunk/aaa/client/target/server-1.0.jar!/packageName
16-02-2015 14:02:15 INFO  Windows file Name file:/C:/SVN/AAA/trunk/aaa/client/target/server-1.0.jar!/packageName
Community
  • 1
  • 1
user725455
  • 465
  • 10
  • 36
  • 1
    What do you expect as output? – WeSt Feb 16 '15 at 12:10
  • What do you mean by reading package name from jar file? Do you want to list content of the jar? Do you want to access particual file in you jar? Your example codes, resolves package name to a jar that was loaded with this package. As the jar itself is a zip file, its content will never be resolved to a normal windows path (as you are inside archive). That is why you have a method, getResourceAsStream, so you can read the content from within the jar. – Zielu Feb 16 '15 at 12:22
  • West . O wxpect ro remove file: from beginning. This is my expectation :C:/SVN/AAA/trunk/aaa/client/target/server-1.0.jar!/packageName – user725455 Feb 16 '15 at 12:25
  • @Zielu. I have added some code to understand my aim. I want to read class names for some special packages. So I can use reflection Class.ForName() later. So getResourceAsStream is not proper for me. This code worked before for EJB server project. But Now I have added server jar as a seperate dependency jar., it does not work. – user725455 Feb 16 '15 at 12:30

2 Answers2

1

A "jar:..." URL does not identify a file. Rather, it identifies a member of a JAR file.

The syntax is (roughly speaking) "jar:<jar-url>!<path-within-jar>", where the is itself a URL; e.g. a "file:" URL in your example.

If you are going to open the JAR file and iterate entries like that, you need to:

  1. Extract the schemeSpecificPart of the original URL

  2. Split the schemeSpecificPart on the "!" character.

  3. Parse the part before the "!" as a URI, then use File(URI) to get the File.

  4. Use the File to open the ZipFile.

  5. Lookup the part after the "!" in the ZipFile ...

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • What do you mean by original URL? URL containing package name?(jar:file:/C:/SVN/AAA/trunk/aaa/client/target/server-1.0.jar!/packageName or jar:file:/C:/SVN/AAA/trunk/aaa/client/target/server-1.0.jar!/).If you mean second one, I do not know how to do it. Only getResorce.. methods returns URL. – user725455 Feb 16 '15 at 13:37
  • How can I do third step?. new URL(schemeSpecificPart ) will do job? – user725455 Feb 16 '15 at 13:48
  • `new File (new URI ( part of schemeSpecificPart that is before the "!" ) )` – Stephen C Feb 17 '15 at 02:06
1

The answer by Stephen has all the elements you need.

  1. With the getResource(package).getURI() or getResoucer(package).toFile you are getting the path to the resource.
  2. Do substring on it to extract the part between file:// and ! this is the path to physical location of your jar of interest.
  3. De new File on this sub-path and you have handle to your jar.
  4. Jar is normal zip file, and process it as such (java.util.zip and there are manuals on the web).
  5. List content of your zip file (now you may need to navigate using the bits behind ! sign in your original path), and you get your classes name.

I am not sure if this is the best way to achieve your goal, I would check how classes discovery (which is what you are trying to do, are implemented in some open source framework (for example tomcat uses it, JPA impelementation to find the entitities). There is also discovery project on apache but it seems to be dead for a while.

Zielu
  • 8,312
  • 4
  • 28
  • 41