146

Manifestクラスを配信したファイルを読み取る必要がありますが、使用する場合:

getClass().getClassLoader().getResources(...)

MANIFEST最初.jarにJavaランタイムにロードされたものから取得します。
私のアプリはアプレットまたはWebスタートから実行される
ため、自分の.jarファイルにアクセスできないと思います。

私は実際にFelixOSGiを開始したExport-package属性を読み取りたい.jarので、それらのパッケージをFelixに公開できます。何か案は?

4

13 に答える 13

125

次の 2 つのいずれかを行うことができます。

  1. 返された URL のコレクションを呼び出し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
        }
    }
    
  2. 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
    }
    
于 2009-08-13T16:46:28.060 に答える
122

最初にクラスの 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");
于 2009-08-13T17:27:02.420 に答える
21

Manifestsfrom jcabi-manifestsを使用して、利用可能な任意の MANIFEST.MF ファイルから任意の属性を 1 行で読み取ることができます。

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

于 2012-12-30T11:02:19.353 に答える
11

任意のバンドル (特定のクラスをロードしたバンドルを含む) のマニフェストを取得する最も適切な方法は、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 を直接使用してください。

于 2009-08-16T05:15:43.103 に答える
11

次のコードは、複数のタイプのアーカイブ (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);
    }
  }
于 2015-03-17T15:23:15.137 に答える
6

次のように getProtectionDomain().getCodeSource() を使用できます。

URL url = Menu.class.getProtectionDomain().getCodeSource().getLocation();
File file = DataUtilities.urlToFile(url);
JarFile jar = null;
try {
    jar = new JarFile(file);
    Manifest manifest = jar.getManifest();
    Attributes attributes = manifest.getMainAttributes();
    return attributes.getValue("Built-By");
} finally {
    jar.close();
}
于 2013-03-29T09:12:23.087 に答える
1

getClassLoader ステップを含めているのはなぜですか? 「this.getClass().getResource()」と言うと、呼び出し元のクラスに関連するリソースを取得する必要があります。ClassLoader.getResource() を使用したことはありませんが、Java Docs をざっと見てみると、現在のクラスパスで見つかったその名前の最初のリソースが取得されるように思えます。

于 2009-08-13T16:48:57.507 に答える