【问题标题】:Read the jar version for a class读取一个类的 jar 版本
【发布时间】:2019-11-08 15:38:51
【问题描述】:

对于 web 服务客户端,我想使用 jar 文件中的 Implementation-Title 和 Implementation-Version 作为用户代理字符串。问题是如何读取 jar 的清单。

这个问题已被多次询问,但答案似乎不适用于我。 (例如Reading my own Jar's Manifest

问题在于,简单地阅读 /META-INF/MANIFEST.MF 几乎总是会给出错误的结果。就我而言,它几乎总是指 JBoss。

https://stackoverflow.com/a/1273196/4222206提出的解决方案 对我来说是有问题的,因为您必须对库名称进行硬编码以停止迭代,然后仍然可能意味着同一库的两个版本在类路径上,您只需返回第一个 - 不一定是正确的 - 命中。

https://stackoverflow.com/a/1273432/4222206中的解决方案 似乎只与 jar:// urls 一起工作,它在应用程序类加载器生成 vfs:// urls 的 JBoss 中完全失败。

有没有办法让类中的代码找到它自己的清单?

我尝试了上述项目,这些项目似乎在从 java 命令行运行的小型应用程序中运行良好,但后来我想要一个可移植的解决方案,因为我无法预测以后会在哪里使用我的库。

public static Manifest getManifest() {
    log.debug("getManifest()");
    synchronized(Version.class) {
        if(manifest==null) {
            try {
                // this works wrongly in JBoss
                //ClassLoader cl = Version.class.getProtectionDomain().getClassLoader();
                //log.debug("found classloader={}", cl);
                //URL manifesturl = cl.getResource("/META-INF/MANIFEST.MF");

                URL jar = Version.class.getProtectionDomain().getCodeSource().getLocation();
                log.debug("Class loaded from {}", jar);

                URL manifesturl = null;
                switch(jar.getProtocol()) {
                    case "file":
                        manifesturl = new URL(jar.toString()+"META-INF/MANIFEST.MF");
                        break;
                    default:
                        manifesturl = new URL(jar.toString()+"!/META-INF/MANIFEST.MF");
                }


                log.debug("Expecting manifest at {}", manifesturl);
                manifest = new Manifest(manifesturl.openStream());
            }
            catch(Exception e) {
                log.info("Could not read version", e);
            }
        }
    }

代码将检测正确的 jar 路径。我假设通过修改 url 指向清单会给出所需的结果,但是我得到了这个:

Class loaded from vfs:/C:/Users/user/Documents/JavaLibs/wildfly-18.0.0.Final/bin/content/webapp.war/WEB-INF/lib/library-1.0-18.jar
Expecting manifest at vfs:/C:/Users/user/Documents/JavaLibs/wildfly-18.0.0.Final/bin/content/webapp.war/WEB-INF/lib/library-1.0-18.jar!/META-INF/MANIFEST.MF
Could not read version: java.io.FileNotFoundException: C:\Users\hiran\Documents\JavaLibs\wildfly-18.0.0.Final\standalone\tmp\vfs\temp\tempfc75b13f07296e98\content-e4d5ca96cbe6b35e\WEB-INF\lib\library-1.0-18.jar!\META-INF\MANIFEST.MF (The system cannot find the path specified)

我检查了该路径,似乎 jar 的第一个 URL(通过 Version.class.getProtectionDomain().getCodeSource().getLocation() 获得)已经错了。它应该是 C:\Users\user\Documents\JavaLibs\wildfly-18.0.0.Final\standalone\tmp\vfs\temp\tempfc75b13f07296e98\content-e4d5ca96cbe6b35e\WEB-INF\lib\library-1.0.18.jar .

所以这甚至可能表明 Wildfly 存在问题?

【问题讨论】:

  • 如果您的代码在.jar 中而在.war 中怎么办?在.war 中的.jar.ear 中怎么样?如果它在不是 Wildfly 的服务器中,所以有一个完全不同的类加载设置,或者根本不在 .jar 中怎么办?我用git-commit-id-plugin 做了类似的事情。
  • 如果您建议的场景都可能有问题,那么函数是什么 class.getProtectionDomain().getCodeSource().getLocation();然后意味着返回?不知何故,我相信它的实现中有一个错误,因为我希望它指向加载类的源,而不是其他路径。这是我的误解还是 Wildfly 的错误行为?不过我会仔细看看你的插件。感谢分享。 :-)

标签: java jar version wildfly manifest


【解决方案1】:

看来我在这里找到了一些合适的解决方案: https://stackoverflow.com/a/37325538/4222206

所以最后这段代码可以(至少)在 JBoss 中显示正确版本的 jar:

this.getClass().getPackage().getImplementationTitle();
this.getClass().getPackage().getImplementationVersion();

希望我下次搜索时能找到这个答案...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-04
    • 2011-10-18
    • 2013-08-03
    • 1970-01-01
    • 2017-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多