这是对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条目META-INF / MANIFEST.MF找不到{我的本地maven存储库中的插件jar的路径}。怎么可能
Enumeration<URL> resources = getClass().getClassLoader()
.getResources("META-INF/MANIFEST.MF");
找到清单,然后在尝试使用以下内容时抛出FileNotFoundException:
Manifest manifest = new Manifest(resources.nextElement().openStream());
这是抛出异常的行。
有人可以解释这种奇怪的行为,或者想出另一种可能更新的阅读清单的方法吗?
顺便说一句,这是在Windows下运行的。还没有在Linux上尝试它,它可能实际工作,但我希望它在两种情况下都能工作。
答案 0 :(得分:2)
如果是我,我会在构建时生成一个包含版本的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()
答案 1 :(得分:1)
我们可以利用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;
这些清单条目必须具有正确的密钥,例如“实施版本”等,可在java.util.jar.Attributes.Name
根据这些标准构建清单,可以在不执行其他读取的情况下获取这些值 。帽子提示到https://stackoverflow.com/a/23280647/811299