【问题标题】:Programmatically read Manifest.MF from JAR in an EAR以编程方式从 EAR 中的 JAR 读取 Manifest.MF
【发布时间】:2016-06-06 21:52:35
【问题描述】:

我必须通过阅读清单来扫描 EAR 以确定其中一个 JAR 的版本...

我碰巧有这样的东西要读:MyApplication.ear/MyLibrary.jar/META-INF/Manifest.MF

我不知道如何以最简单的方式做到这一点...我一直在为 JarFile、JarInputStream、JarURLConnection 苦苦挣扎,到目前为止还没有运气。

这是我当时拥有的:

JarFile myEAR = new JarFile(urlOfMyEAR);
JarEntry myJAR = myEAR.getJarEntry(libname);
Attributes m = myJAR.getAttributes();
System.out.println(m.getValue("Implementation-Version"));

但是getAttributes() 返回null...

我认为肯定有一种复杂/彻底的方法(通过提取文件或其他方式),但我希望有一个更简单的...

感谢您的帮助。

编辑:下面是我自己的答案...

【问题讨论】:

  • 罐子在你的控制之下吗?你使用 Maven 吗?您可以使用 maven“过滤”将您的版本号注入您需要的任何文件...
  • 这不在我的控制范围内,我想在我设法集成到仪表板的多个环境中读取应用程序的版本......指定的 JAR 是我们的框架,我需要展示我的用户以及应用程序版本号它所基于的框架版本号......
  • 如果您使用 Maven(或任何复杂的构建工具),例如,您可以在构建时将您正在使用的各种版本号直接注入到 html 模板中......因此不需要读取 jar ,因此不将您的范围限制在嵌入式依赖项 - 例如,您可以注入(预期的)JDBC驱动程序版本号,它不应该在您的耳中提供。如果没有Maven,您应该尝试定位jar,将其作为ZipFile打开, 循环查找正确的条目,然后在内存中解压缩,最后解析清单......但这很棘手
  • thx spi,不幸的是,我改变现有流程的可能性很小(大公司中的大型应用程序),所以如果我想要一个快速的结果,我必须自己解决它(到目前为止不是很开发^^)。最后使用 maven 是一个可行的选择,已被考虑...

标签: java jar


【解决方案1】:

我设法通过使用此代码解决了我的问题:

JarFile myEAR = new JarFile(urlOfMyEAR);

File f = File.createTempFile("jar", null);
FileOutputStream resourceOS = new FileOutputStream(f);
byte[] byteArray = new byte[1024];
int i;

InputStream jarIS = myEAR.getInputStream(myEAR.getEntry(libname));
while ((i = jarIS.read(byteArray)) > 0) {
    //Write the bytes to the output stream
    resourceOS.write(byteArray, 0, i);
}
//Close streams to prevent errors
jarIS.close();
resourceOS.close();

JarFile myJAR = new JarFile(f);

Attributes m = myJAR.getManifest().getMainAttributes();

System.out.println(m.getValue("Implementation-Version"));

(感谢这篇帖子https://stackoverflow.com/a/17902842/2454970

一个 7MB 的 jar 在将近 200MB 的耳朵里,整个解压缩只需要 7 秒...

谢谢你的想法,伙计们。

【讨论】:

    【解决方案2】:

    如果您的扫描仪与您的应用程序在同一个 JVM 中运行,您可以获得如下清单文件:

    Enumeration<URL> resources = this.getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
    while(resources.hasMoreElements()){
        URL u = resources.nextElement();
        try(InputStream is = u.openStream()){
            if(is!=null){
                Manifest manifest = new Manifest(is);
                //do something blabla
            }
        }
    }
    

    如果没有,我认为向您的应用程序添加一个简单的 jar 来收集这些数据,然后将结果上传到您的仪表板会是一个更好的解决方案。

    【讨论】:

    • 它不在同一个JVM上,遗憾的是......我不确定通过“添加一个简单的jar......”来理解
    • @Pataluc 正如您所提到的,JAR 是您的框架。您可以在框架中添加扫描仪,在启动时运行并上传结果。
    • 我在一家大公司,我无权访问框架来修改它... ;(
    • @pataluc 如果你的所有项目都使用了maven,你可以考虑开发一个maven插件,通过扫描pom文件来获取结果。您可以将插件集成到 CI 工具中,而无需更改您的应用程序。或框架。
    猜你喜欢
    • 2020-09-30
    • 2012-06-23
    • 2018-07-23
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 2011-04-16
    相关资源
    最近更新 更多