Manifest
클래스를 전달한 파일 을 읽어야 하지만 다음을 사용할 때 :
getClass().getClassLoader().getResources(...)
Java Runtime에 MANIFEST
처음 .jar
로드 된 것을 얻습니다 .
내 응용 프로그램이 애플릿 또는 웹 스타트에서 실행
되므로 내 .jar
파일에 액세스 할 수 없습니다 .
실제로 Felix OSGi를 시작한 Export-package
속성 을 읽고 싶습니다 .jar
. 따라서 해당 패키지를 Felix에 공개 할 수 있습니다. 어떤 아이디어?
답변
다음 두 가지 중 하나를 수행 할 수 있습니다.
-
getResources()
반환 된 URL 모음을 호출 하고 반복하여 찾을 때까지 매니페스트로 읽습니다.Enumeration<URL> 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()
애플릿에 대해 알려진 매니페스트를 직접 반환하기 위해 알려진 것을 호출 할 수 있습니다 .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 }
답변
수업의 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");
답변
jcabi-manifestsManifests
에서 사용할 수 있으며 사용 가능한 MANIFEST.MF 파일에서 한 줄만으로 모든 속성을 읽을 수 있습니다.
String value = Manifests.read("My-Attribute");
필요한 유일한 종속성은 다음과 같습니다.
<dependency>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-manifests</artifactId>
<version>0.7.5</version>
</dependency>
또한 자세한 내용은이 블로그 게시물을 참조하십시오. http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html
답변
이 답변이 원래 질문, 일반적으로 매니페스트에 액세스 할 수있는 질문에 답변하지 않는다는 점을 인정합니다. 그러나 실제로 필요한 것이 많은 “표준”매니페스트 속성 중 하나를 읽는 것이라면 다음 솔루션은 위에 게시 된 것보다 훨씬 간단합니다. 그래서 중재자가 허락하기를 바랍니다. 이 솔루션은 Java가 아닌 Kotlin에 있지만 Java 포트는 사소한 것으로 예상합니다. (나는 “.`package`”와 같은 Java를 모른다는 것을 인정하지만.
필자의 경우 “Implementation-Version”속성을 읽고 스트림을 얻기 위해 위에서 주어진 솔루션으로 시작한 다음 값을 얻기 위해 읽었습니다. 이 솔루션이 작동하는 동안 내 코드를 검토하는 동료가 원하는 것을 쉽게 수행 할 수있는 방법을 보여주었습니다. 이 솔루션은 Java가 아닌 Kotlin에 있습니다.
val myPackage = MyApplication::class.java.`package`
val implementationVersion = myPackage.implementationVersion
다시 한 번 이것은 원래 질문에 대한 답변이 아니며 특히 “내보내기 패키지”는 지원되는 속성 중 하나가 아닌 것 같습니다. 즉, 값을 반환하는 myPackage.name이 있습니다. 어쩌면 이것을 이해하는 사람은 원래 포스터가 요구하는 가치를 반환하는지 여부에 대해 언급 할 수 있습니다.
답변
특정 번들을로드 한 번들을 포함하여 모든 번들의 매니페스트를 얻는 가장 적절한 방법은 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를 직접 사용하십시오.
답변
다음 코드는 여러 유형의 아카이브 (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);
}
}
답변
가장 쉬운 방법은 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:/
하므로 추가로 처리해야합니다.