阅读我自己的罐子清单采取 2
Posted
技术标签:
【中文标题】阅读我自己的罐子清单采取 2【英文标题】:Reading My Own Jar's Manifest Take 2 【发布时间】:2016-09-15 13:05:55 【问题描述】:这是对near-universally accepted answer 对old question 的回应。由于答案相当陈旧(2009 年)并且对我不起作用,我想我会问是否有人知道原因。
我的用例是开发一个内部使用的 gradle 插件。每当应用插件时,我都非常希望能够打印出正在使用的插件版本。因此,我在构建插件时将版本写入插件的清单,并尝试在应用插件时使用链接答案中的技术从清单中读取它。
我根据答案编写了一些代码,但它不起作用。我加了一堆调试代码,可以看到代码首先找到了JDK自己提供的Manifest:
Manifest-Version: 1.0
Created-By: 1.7.0_07 (Oracle Corporation)
然后它找到我的清单,我正在寻找的那个,但抛出一个 FileNotFoundException:
java.io.FileNotFoundException: JAR entry META-INF/MANIFEST.MF not found in path to my plugin jar in my local maven repository。怎么可能
Enumeration<URL> resources = getClass().getClassLoader()
.getResources("META-INF/MANIFEST.MF");
找到清单,然后在尝试读取时抛出 FileNotFoundException:
Manifest manifest = new Manifest(resources.nextElement().openStream());
这是引发异常的行。
有人可以解释这种奇怪的行为,或者想出另一种可能更新的方式来阅读清单吗?
顺便说一句,这是在 Eclipse 下,在 Windows 中运行的。还没有在 Linux 上尝试过,它可能确实可以工作,但我希望它在这两种情况下都可以工作。
【问题讨论】:
您打算读取清单的哪些属性?许多与版本相关的清单属性可用作java.lang.Package 类的方法。 是的,我刚刚找到了同样的东西,谢谢。请参阅我刚刚发布的答案。 【参考方案1】:如果是我,我会在构建时生成一个包含版本的 java 文件:
例如:将以下文件放入src/template/java/com/foo/MyPluginProperties.java
package com.foo;
public class MyPluginProperties
public static String getVersion()
return "@version@";
然后在build.gradle
def generatedJava = file("$buildDir/generated/java")
task generateSource(type:Copy)
def tokens = [version: project.version]
// configure task inputs for gradle's up-to-date checks
inputs.property "tokens", tokens
from "src/template/java"
filter(ReplaceTokens, tokens: tokens)
into generatedJava
// wire the task into the gradle DAG
compileJava.dependsOn generateSource
// add the generated directory to the main source set so it's compiled
sourceSets.main.java
srcDir generatedJava
然后,在您的插件中,您可以调用以下内容:
com.foo.MyPluginProperties.getVersion()
【讨论】:
谢谢。这对我的特定用例很有用。我仍然想知道为什么 FileNotFoundException 在我的原始方法中发生。 不知道,也许你没有关闭之前的输入流? Tapestry IOC 做了类似的事情here 不是这样的。我想到了这一点,并确保我确实关闭了以前的输入流,但这没有任何帮助..【参考方案2】:我们可以利用 Java 类加载器已经在 java.lang 中提供的东西,而不是尝试读取清单,因为奇怪的 IO 问题(我仍然想了解) 。包裹。当从 jar 加载包时,会调用 private Package(String name, Manifest man, URL url, ClassLoader loader)
构造函数。它读取 Manifest 的标准属性并将它们存储在 Package 成员变量中:
private final String pkgName;
private final String specTitle;
private final String specVersion;
private final String specVendor;
private final String implTitle;
private final String implVersion;
private final String implVendor;
这些清单条目必须具有正确的键,例如“Implementation-Version”等,在java.util.jar.Attributes.Name
中找到
使用根据这些标准构建的清单,无需再次读取即可获得这些值。帽子提示https://***.com/a/23280647/811299
【讨论】:
以上是关于阅读我自己的罐子清单采取 2的主要内容,如果未能解决你的问题,请参考以下文章