views:

1178

answers:

4

Hi,

i need to read the Manifest file, which delivered my class. but it seems that when i use

 getClass().getClassLoader().getResources(...)

i end up getting the MANIFEST from the first Jar loaded into the Java Runtime. My app will be running from applet or webstart, so i will not have access to my own .jar file i guess

i actually want to read the 'Export-package' attribute from the jar which started the Felix OSGi, so that i can expose those packages to Felix.

does anybody have an idea? Thanks

+8  A: 

You can do one of two things:

1) Call getResources() and iterate through the returned collection of URLs, reading them as manifests until you find yours:

Enumeration<URL> resources = getClass().getClassLoader()
  .getResources("META-INF/MANIFEST.MF");
while (resources.hasMoreElements()) {
    try {
      Manifest manifest = new Manifest(resources.nextElement().openStream());
      // check that this is your manifest and do what you need or get the next one
      ...
    } catch (IOException E) {
      // handle
    }
}

2) You can try checking whether getClass().getClassLoader() is an instance of java.net.URLClassLoader. Majority of Sun classloaders are, including AppletClassLoader. You can then cast it and call findResource() which has been known - for applets, at least - to return the needed manifest directly:

URLClassLoader cl = (URLClassLoader) getClass().getClassLoader();
try {
  URL url = cl.findResource("META-INF/MANIFEST.MF");
  Manifest manifest = new Manifest(url.openStream());
  // do stuff with it
  ...
} catch (IOException E) {
  // handle
}
ChssPly76
Perfect! I never knew you could iterate through resources with the same name.
Houtman
How do you know the classloader is only aware of a single .jar file? (true in many cases I suppose) I would much rather use something associated directly with the class in question.
Jason S
A: 

Why are you including the getClassLoader step? If you say "this.getClass().getResource()" you should be getting resources relative to the calling class. I've never used ClassLoader.getResource(), though from a quick look at the Java Docs it sounds like that will get you the first resource of that name found in any current classpath.

Jay
If your class is named "com.mypackage.MyClass", calling `class.getResource("myresource.txt")` will try to load that resource from `com/mypackage/myresource.txt`. How exactly are you going to use this approach to get the manifest?
ChssPly76
Okay, I have to backtrack. That's what comes of not testing. I was thinking that you could say this.getClass().getResource("../../META-INF/MANIFEST.MF") (However many ".."'s are necessary given your package name.) But while that works for class files in a directory to work your way up a directory tree, it apparently doesn't work for JARs. I don't see why not, but that's how it is. Nor does this.getClass().getResource("/META-INF/MANIFEST.MF") work -- that gets me the manifest for rt.jar. (To be continued ...)
Jay
What you can do is use getResource to find the path to your own class file, then strip off everything after the "!" to get the path to the jar, then append "/META-INF/MANIFEST.MF". Like Zhihong suggested, so I'm voting his up.
Jay
+4  A: 

You can find the URL for your class first. If it's a JAR, then you load the manifest from there. For example,

Class clazz = MyClass.class;
String className = clazz.getSimpleName() + ".class";
String classPath = clazz.getResource(className).toString();
if (!classPath.startWith("jar")) {
  // Class not from JAR
  return;
}
String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + 
    "/META-INF/MANIFEST.MF";
Manifest manifest = new Manifest(new URL(manifestPath).openStream());
Attributes attr = manifest.getMainAttributes();
String value = attr.get(name);
ZZ Coder
I like this solution as it gets your own manifest directly rather than having to search for it.
Jay
Works very nicely! thanks! This saved me a lot of hassle.
Jason S
+3  A: 
Anthony Juckel