web-dev-qa-db-fra.com

lecture du fichier MANIFEST.MF à partir du fichier jar à l'aide de JAVA

Existe-t-il un moyen de lire le contenu d'un fichier jar? comme je veux lire le fichier manifeste afin de trouver le créateur du fichier jar et de sa version. Est-il possible d'atteindre le même objectif?.

25
M.J.

Le code suivant devrait aider:

JarInputStream jarStream = new JarInputStream(stream);
Manifest mf = jarStream.getManifest();

Le traitement des exceptions est laissé pour vous :) 

39
Oleg Iavorskyi

Vous pouvez utiliser quelque chose comme ceci:

public static String getManifestInfo() {
    Enumeration resEnum;
    try {
        resEnum = Thread.currentThread().getContextClassLoader().getResources(JarFile.MANIFEST_NAME);
        while (resEnum.hasMoreElements()) {
            try {
                URL url = (URL)resEnum.nextElement();
                InputStream is = url.openStream();
                if (is != null) {
                    Manifest manifest = new Manifest(is);
                    Attributes mainAttribs = manifest.getMainAttributes();
                    String version = mainAttribs.getValue("Implementation-Version");
                    if(version != null) {
                        return version;
                    }
                }
            }
            catch (Exception e) {
                // Silently ignore wrong manifests on classpath?
            }
        }
    } catch (IOException e1) {
        // Silently ignore wrong manifests on classpath?
    }
    return null; 
}

Pour obtenir les attributs de manifeste, vous pouvez parcourir la variable "mainAttribs" ou récupérer directement l'attribut requis si vous connaissez la clé.

Ce code parcourt chaque fichier jar du chemin de classe et lit le MANIFEST de chacun. Si vous connaissez le nom du fichier jar, vous pouvez ne regarder l'URL que si elle contient () le nom du fichier qui vous intéresse.

34
flash

Je suggérerais de faire ce qui suit:

Package aPackage = MyClassName.class.getPackage();
String implementationVersion = aPackage.getImplementationVersion();
String implementationVendor = aPackage.getImplementationVendor();

Où MyClassName peut être n'importe quelle classe de votre application écrite par vous.

29
stviper

J'ai implémenté une classe AppVersion selon certaines idées de stackoverflow, ici je viens de partager la classe entière:

import Java.io.File;
import Java.net.URL;
import Java.util.jar.Attributes;
import Java.util.jar.Manifest;

import org.Apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AppVersion {
  private static final Logger log = LoggerFactory.getLogger(AppVersion.class);

  private static String version;

  public static String get() {
    if (StringUtils.isBlank(version)) {
      Class<?> clazz = AppVersion.class;
      String className = clazz.getSimpleName() + ".class";
      String classPath = clazz.getResource(className).toString();
      if (!classPath.startsWith("jar")) {
        // Class not from JAR
        String relativePath = clazz.getName().replace('.', File.separatorChar) + ".class";
        String classFolder = classPath.substring(0, classPath.length() - relativePath.length() - 1);
        String manifestPath = classFolder + "/META-INF/MANIFEST.MF";
        log.debug("manifestPath={}", manifestPath);
        version = readVersionFrom(manifestPath);
      } else {
        String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";
        log.debug("manifestPath={}", manifestPath);
        version = readVersionFrom(manifestPath);
      }
    }
    return version;
  }

  private static String readVersionFrom(String manifestPath) {
    Manifest manifest = null;
    try {
      manifest = new Manifest(new URL(manifestPath).openStream());
      Attributes attrs = manifest.getMainAttributes();

      String implementationVersion = attrs.getValue("Implementation-Version");
      implementationVersion = StringUtils.replace(implementationVersion, "-SNAPSHOT", "");
      log.debug("Read Implementation-Version: {}", implementationVersion);

      String implementationBuild = attrs.getValue("Implementation-Build");
      log.debug("Read Implementation-Build: {}", implementationBuild);

      String version = implementationVersion;
      if (StringUtils.isNotBlank(implementationBuild)) {
        version = StringUtils.join(new String[] { implementationVersion, implementationBuild }, '.');
      }
      return version;
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }
    return StringUtils.EMPTY;
  }
}

Fondamentalement, cette classe peut lire les informations de version à partir du manifeste de son propre fichier JAR ou du manifeste de son dossier de classes. Et j'espère que cela fonctionne sur différentes plates-formes, mais je ne l'ai testé que sur Mac OS X jusqu'à présent.

J'espère que cela serait utile pour quelqu'un d'autre.

9
Jake W

Vous pouvez utiliser une classe d’utilitaire Manifests from jcabi-manifestests :

final String value = Manifests.read("My-Version");

La classe trouvera tous les fichiers MANIFEST.MF disponibles dans classpath et lira l’attribut recherché dans l’un d’eux. Lisez également ceci: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

3
yegor256

Atteindre les attributs de cette manière simple

    public static String  getMainClasFromJarFile(String jarFilePath) throws Exception{
    // Path example: "C:\\Users\\GIGABYTE\\.m2\\repository\\domolin\\DeviceTest\\1.0-SNAPSHOT\\DeviceTest-1.0-SNAPSHOT.jar";
    JarInputStream jarStream = new JarInputStream(new FileInputStream(jarFilePath));
    Manifest mf = jarStream.getManifest();
    Attributes attributes = mf.getMainAttributes();
    // Manifest-Version: 1.0
    // Built-By: GIGABYTE
    // Created-By: Apache Maven 3.0.5
    // Build-Jdk: 1.8.0_144
    // Main-Class: domolin.devicetest.DeviceTest
    String mainClass = attributes.getValue("Main-Class");
    //String mainClass = attributes.getValue("Created-By");
    //  Output: domolin.devicetest.DeviceTest
    return mainClass;
}
0
Ronald

Rester simple. Une JAR est également une Zip afin que tout code Zip puisse être utilisé pour lire le MAINFEST.MF:

public static String readManifest(String sourceJARFile) throws IOException
{
    ZipFile zipFile = new ZipFile(sourceJARFile);
    Enumeration entries = zipFile.entries();

    while (entries.hasMoreElements())
    {
        ZipEntry zipEntry = (ZipEntry) entries.nextElement();
        if (zipEntry.getName().equals("META-INF/MANIFEST.MF"))
        {
            return toString(zipFile.getInputStream(zipEntry));
        }
    }

    throw new IllegalStateException("Manifest not found");
}

private static String toString(InputStream inputStream) throws IOException
{
    StringBuilder stringBuilder = new StringBuilder();
    try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)))
    {
        String line;
        while ((line = bufferedReader.readLine()) != null)
        {
            stringBuilder.append(line);
            stringBuilder.append(System.lineSeparator());
        }
    }

    return stringBuilder.toString().trim() + System.lineSeparator();
}

Malgré la flexibilité, il suffit de lire les données ceci réponse est la meilleure.

0
BullyWiiPlaza