我需要读取Manifest
文件,该文件包含我的类信息。但是当我使用以下代码:
getClass().getClassLoader().getResources(...)
我从Java Runtime中加载第一个.jar文件获取MANIFEST。
我的应用将会在applet或者webstart中运行,
所以我猜我无法访问自己的.jar文件。
我实际上想要读取启动Felix OSGi的.jar文件中的Export-package属性,这样我就可以将这些包暴露给Felix。有什么想法吗?我需要读取Manifest
文件,该文件包含我的类信息。但是当我使用以下代码:
getClass().getClassLoader().getResources(...)
我从Java Runtime中加载第一个.jar文件获取MANIFEST。
我的应用将会在applet或者webstart中运行,
所以我猜我无法访问自己的.jar文件。
我实际上想要读取启动Felix OSGi的.jar文件中的Export-package属性,这样我就可以将这些包暴露给Felix。有什么想法吗?你可以选择以下两种方式之一:
调用 getResources()
并遍历返回的 URL 集合,将其作为清单文件读取,直到找到你的清单文件为止:
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
}
}
你可以尝试检查 getClass().getClassLoader()
是否是 java.net.URLClassLoader
的实例。大多数 Sun 的类加载器都是,包括 AppletClassLoader
。然后你可以将其强制转换并调用 findResource()
方法,这个方法已经被知道 - 至少对于 applets 来说 - 直接返回所需的清单: 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
}
java.util.jar.Manifest
周围添加连线。在阅读了那篇文章之前,我不知道这个类。我可能会愚蠢地/手动解析 Manifest 文件... - kevinarpe首先你需要找到你的类所在的URL地址。如果是一个JAR文件,那么你可以从中加载manifest文件。例如:
Class clazz = MyClass.class;
String className = clazz.getSimpleName() + ".class";
String classPath = clazz.getResource(className).toString();
if (!classPath.startsWith("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.getValue("Manifest-Version");
classPath.replace("org/example/MyClass.class", "META-INF/MANIFEST.MF"
来稍微改进一下。 - JaygetSimpleName
会删除外部类的名称。下面的方法可用于内部类:clazz.getName().replace(".", "/") + ".class"
。 - cevingManifests
从jcabi-manifests。String value = Manifests.read("My-Attribute");
你需要的唯一依赖是:
<dependency>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-manifests</artifactId>
<version>0.7.5</version>
</dependency>
另外,查看此博客文章获取更多细节:http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html
<logger name="com.jcabi.manifests" level="OFF"/>
。 - floer32val myPackage = MyApplication::class.java.`package`
val implementationVersion = myPackage.implementationVersion
String implementationVersion = MyApplication.class.getPackage().getImplementationVersion();
- Ian Robertson最简单的方法是使用JarURLConnection类:
String className = getClass().getSimpleName() + ".class";
String classPath = getClass().getResource(className).toString();
if (!classPath.startsWith("jar")) {
return DEFAULT_PROPERTY_VALUE;
}
URL url = new URL(classPath);
JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
Manifest manifest = jarConnection.getManifest();
Attributes attributes = manifest.getMainAttributes();
return attributes.getValue(PROPERTY_NAME);
由于在某些情况下,...class.getProtectionDomain().getCodeSource().getLocation();
会返回带有vfs:/
的路径,因此需要进行额外处理。
public static Manifest getManifest(Class<?> clz) {
String resource = "/" + clz.getName().replace(".", "/") + ".class";
String fullPath = clz.getResource(resource).toString();
String archivePath = fullPath.substring(0, fullPath.length() - resource.length());
if (archivePath.endsWith("\\WEB-INF\\classes") || archivePath.endsWith("/WEB-INF/classes")) {
archivePath = archivePath.substring(0, archivePath.length() - "/WEB-INF/classes".length()); // Required for wars
}
try (InputStream input = new URL(archivePath + "/META-INF/MANIFEST.MF").openStream()) {
return new Manifest(input);
} catch (Exception e) {
throw new RuntimeException("Loading MANIFEST for class " + clz + " failed!", e);
}
}
clz.getResource(resource).toString()
的结果可能会有反斜杠吗? - basin我认为获取任何捆绑包的清单(包括加载给定类的捆绑包)的最合适方法是使用Bundle或BundleContext对象。
// If you have a BundleContext
Dictionary headers = bundleContext.getBundle().getHeaders();
// If you don't have a context, and are running in 4.2
Bundle bundle = FrameworkUtil.getBundle(this.getClass());
bundle.getHeaders();
getEntry(String path)
方法来查找特定bundle中包含的资源,而不是搜索该bundle的整个类路径。URL url = Menu.class.getProtectionDomain().getCodeSource().getLocation();
File file = DataUtilities.urlToFile(url);
JarFile jar = null;
try {
jar = new JarFile(file);
Manifest manifest = jar.getManifest();
Attributes attributes = manifest.getMainAttributes();
return attributes.getValue("Built-By");
} finally {
jar.close();
}
DataUtilities
是从哪里导入的?它似乎不在 JDK 中。 - JoltaApplication.class.getPackage().getImplementationVersion()
public static Manifest getManifest( Class<?> cl ) {
InputStream inputStream = null;
try {
URLClassLoader classLoader = (URLClassLoader)cl.getClassLoader();
String classFilePath = cl.getName().replace('.','/')+".class";
URL classUrl = classLoader.getResource(classFilePath);
if ( classUrl==null ) return null;
String classUri = classUrl.toString();
if ( !classUri.startsWith("jar:") ) return null;
int separatorIndex = classUri.lastIndexOf('!');
if ( separatorIndex<=0 ) return null;
String manifestUri = classUri.substring(0,separatorIndex+2)+"META-INF/MANIFEST.MF";
URL url = new URL(manifestUri);
inputStream = url.openStream();
return new Manifest( inputStream );
} catch ( Throwable e ) {
// handle errors
...
return null;
} finally {
if ( inputStream!=null ) {
try {
inputStream.close();
} catch ( Throwable e ) {
// ignore
}
}
}
}
cl.getResourceAsStream("META-INF/MANIFEST.MF")
。 - RobertclassLoader.getResource(..)
和url.openStream()
之间的所有代码都是完全无关紧要且容易出错的,因为它试图做与classLoader.getResourceAsStream(..)
相同的事情。 - RobertClassLoader classLoader = cl.getClassLoader();
return new Manifest(classLoader.getResourceAsStream("/META-INF/MANIFEST.MF"));
- Robert