当前位置:  开发笔记 > 编程语言 > 正文

读我自己的Jar's Manifest

如何解决《读我自己的Jar'sManifest》经验,为你挑选了8个好方法。

我需要读取Manifest传递我的课程的文件,但是当我使用时:

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

MANIFEST从第一次.jar加载到Java Runtime.
我的应用程序将从小程序或webstart运行,
因此.jar我猜我无法访问自己的文件.

我实际上想要读取启动Felix OSGi 的Export-package属性.jar,所以我可以将这些包暴露给Felix.有任何想法吗?



1> ZZ Coder..:

您可以先找到您班级的URL.如果它是JAR,那么从那里加载清单.例如,

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");


您需要关闭流,清单构造函数不需要.
谁关闭了流?

2> ChssPly76..:

你可以做以下两件事之一:

    调用getResources()并遍历返回的URL集合,将其作为清单读取,直到找到您的URL:

    Enumeration 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()已知的 - 至少对于applet - 直接返回所需的清单:

    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
    }
    


这是**良好的做法**,为每个人制作**单独的答案,而不是在一个答案中包括2个答案.单独的答案可以独立投票.
完善!我从来不知道你可以迭代同名的资源.

3> yegor256..:

您可以使用Manifests从jcabi-清单和读取任何可用的MANIFEST.MF文件的任何属性只用一行:

String value = Manifests.read("My-Attribute");

您需要的唯一依赖是:


  com.jcabi
  jcabi-manifests
  0.7.5

此外,请参阅此博客文章了解更多详情:http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html



4> Anthony Juck..:

我认为获取任何bundle的清单(包括加载给定类的bundle)的最合适的方法是使用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();

请注意,Bundle对象还提供getEntry(String path)查找特定包中包含的资源,而不是搜索该包的整个类路径.

通常,如果您需要特定于包的信息,请不要依赖关于类加载器的假设,只需直接使用OSGi API.



5> 小智..:

以下代码适用于多种类型的存档(jar,war)和多种类型的类加载器(jar,url,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);
    }
  }



6> Steven W. Kl..:

我将首先承认这个答案不能回答最初的问题,即通常能够访问清单的问题。但是,如果真正需要读取多个“标准”清单属性之一,则以下解决方案比上面发布的解决方案简单得多。因此,我希望主持人允许。请注意,此解决方案是在Kotlin中而不是Java中进行的,但是我希望通向Java的端口很简单。(尽管我承认我不知道Java的“ .`package`”。

在我的情况下,我想读取属性“ Implementation-Version”,因此我从上面给出的解决方案开始获取流,然后对其进行读取以获取值。在此解决方案有效的同时,一位同事检查了我的代码,向我展示了一种更轻松的方法来完成我想要的事情。请注意,此解决方案位于Kotlin中,而不是Java中。

val myPackage = MyApplication::class.java.`package`
val implementationVersion = myPackage.implementationVersion

再次注意,这并不能回答原始问题,特别是“ Export-package”似乎不是受支持的属性之一。也就是说,有一个myPackage.name返回一个值。也许有人比我理解得更多,但我无法评论它是否返回原始海报所要求的值。


确实,Java端口很简单:字符串实现版本= MyApplication.class.getPackage()。getImplementationVersion();。

7> ayurchuk..:

最简单的方法是使用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:/,所以这应该另外处理.



8> 小智..:

您可以像这样使用getProtectionDomain().getCodeSource():

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中.
推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有