src/java.base/share/classes/java/util/jar/JarFile.java
changeset 48327 d2a837cf9ff1
parent 48067 6c4bdbf90897
child 50048 1c4fb292447c
equal deleted inserted replaced
48326:e1eb12343774 48327:d2a837cf9ff1
     1 /*
     1 /*
     2  * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
   110  * properties are available.
   110  * properties are available.
   111  * <ul>
   111  * <ul>
   112  * <li>
   112  * <li>
   113  * {@code jdk.util.jar.version} can be assigned a value that is the
   113  * {@code jdk.util.jar.version} can be assigned a value that is the
   114  * {@code String} representation of a non-negative integer
   114  * {@code String} representation of a non-negative integer
   115  * {@code <= Runtime.version().major()}.  The value is used to set the effective
   115  * {@code <= Runtime.version().feature()}.  The value is used to set the effective
   116  * runtime version to something other than the default value obtained by
   116  * runtime version to something other than the default value obtained by
   117  * evaluating {@code Runtime.version().major()}. The effective runtime version
   117  * evaluating {@code Runtime.version().feature()}. The effective runtime version
   118  * is the version that the {@link JarFile#JarFile(File, boolean, int, Runtime.Version)}
   118  * is the version that the {@link JarFile#JarFile(File, boolean, int, Runtime.Version)}
   119  * constructor uses when the value of the last argument is
   119  * constructor uses when the value of the last argument is
   120  * {@code JarFile.runtimeVersion()}.
   120  * {@code JarFile.runtimeVersion()}.
   121  * </li>
   121  * </li>
   122  * <li>
   122  * <li>
   141  * @since   1.2
   141  * @since   1.2
   142  */
   142  */
   143 public
   143 public
   144 class JarFile extends ZipFile {
   144 class JarFile extends ZipFile {
   145     private final static Runtime.Version BASE_VERSION;
   145     private final static Runtime.Version BASE_VERSION;
   146     private final static int BASE_VERSION_MAJOR;
   146     private final static int BASE_VERSION_FEATURE;
   147     private final static Runtime.Version RUNTIME_VERSION;
   147     private final static Runtime.Version RUNTIME_VERSION;
   148     private final static boolean MULTI_RELEASE_ENABLED;
   148     private final static boolean MULTI_RELEASE_ENABLED;
   149     private final static boolean MULTI_RELEASE_FORCED;
   149     private final static boolean MULTI_RELEASE_FORCED;
   150     private SoftReference<Manifest> manRef;
   150     private SoftReference<Manifest> manRef;
   151     private JarEntry manEntry;
   151     private JarEntry manEntry;
   152     private JarVerifier jv;
   152     private JarVerifier jv;
   153     private boolean jvInitialized;
   153     private boolean jvInitialized;
   154     private boolean verify;
   154     private boolean verify;
   155     private final Runtime.Version version;  // current version
   155     private final Runtime.Version version;  // current version
   156     private final int versionMajor;         // version.major()
   156     private final int versionFeature;         // version.feature()
   157     private boolean isMultiRelease;         // is jar multi-release?
   157     private boolean isMultiRelease;         // is jar multi-release?
   158 
   158 
   159     // indicates if Class-Path attribute present
   159     // indicates if Class-Path attribute present
   160     private boolean hasClassPathAttribute;
   160     private boolean hasClassPathAttribute;
   161     // true if manifest checked for special attributes
   161     // true if manifest checked for special attributes
   168         SharedSecrets.setJavaUtilJarAccess(new JavaUtilJarAccessImpl());
   168         SharedSecrets.setJavaUtilJarAccess(new JavaUtilJarAccessImpl());
   169         // Get JavaUtilZipFileAccess from SharedSecrets
   169         // Get JavaUtilZipFileAccess from SharedSecrets
   170         JUZFA = jdk.internal.misc.SharedSecrets.getJavaUtilZipFileAccess();
   170         JUZFA = jdk.internal.misc.SharedSecrets.getJavaUtilZipFileAccess();
   171         // multi-release jar file versions >= 9
   171         // multi-release jar file versions >= 9
   172         BASE_VERSION = Runtime.Version.parse(Integer.toString(8));
   172         BASE_VERSION = Runtime.Version.parse(Integer.toString(8));
   173         BASE_VERSION_MAJOR = BASE_VERSION.major();
   173         BASE_VERSION_FEATURE = BASE_VERSION.feature();
   174         String jarVersion = GetPropertyAction.privilegedGetProperty("jdk.util.jar.version");
   174         String jarVersion = GetPropertyAction.privilegedGetProperty("jdk.util.jar.version");
   175         int runtimeVersion = Runtime.version().major();
   175         int runtimeVersion = Runtime.version().feature();
   176         if (jarVersion != null) {
   176         if (jarVersion != null) {
   177             int jarVer = Integer.parseInt(jarVersion);
   177             int jarVer = Integer.parseInt(jarVersion);
   178             runtimeVersion = (jarVer > runtimeVersion)
   178             runtimeVersion = (jarVer > runtimeVersion)
   179                     ? runtimeVersion
   179                     ? runtimeVersion
   180                     : Math.max(jarVer, BASE_VERSION_MAJOR);
   180                     : Math.max(jarVer, BASE_VERSION_FEATURE);
   181         }
   181         }
   182         RUNTIME_VERSION = Runtime.Version.parse(Integer.toString(runtimeVersion));
   182         RUNTIME_VERSION = Runtime.Version.parse(Integer.toString(runtimeVersion));
   183         String enableMultiRelease = GetPropertyAction
   183         String enableMultiRelease = GetPropertyAction
   184                 .privilegedGetProperty("jdk.util.jar.enableMultiRelease", "true");
   184                 .privilegedGetProperty("jdk.util.jar.enableMultiRelease", "true");
   185         switch (enableMultiRelease) {
   185         switch (enableMultiRelease) {
   222 
   222 
   223     /**
   223     /**
   224      * Returns the version that represents the effective runtime versioned
   224      * Returns the version that represents the effective runtime versioned
   225      * configuration of a multi-release jar file.
   225      * configuration of a multi-release jar file.
   226      * <p>
   226      * <p>
   227      * By default the major version number of the returned {@code Version} will
   227      * By default the feature version number of the returned {@code Version} will
   228      * be equal to the major version number of {@code Runtime.version()}.
   228      * be equal to the feature version number of {@code Runtime.version()}.
   229      * However, if the {@code jdk.util.jar.version} property is set, the
   229      * However, if the {@code jdk.util.jar.version} property is set, the
   230      * returned {@code Version} is derived from that property and major version
   230      * returned {@code Version} is derived from that property and feature version
   231      * numbers may not be equal.
   231      * numbers may not be equal.
   232      *
   232      *
   233      * @return the version that represents the runtime versioned configuration
   233      * @return the version that represents the runtime versioned configuration
   234      *
   234      *
   235      * @since 9
   235      * @since 9
   320      * used to configure the {@code JarFile} for processing
   320      * used to configure the {@code JarFile} for processing
   321      * multi-release jar files.
   321      * multi-release jar files.
   322      * <p>
   322      * <p>
   323      * The canonical form derived from the version parameter is
   323      * The canonical form derived from the version parameter is
   324      * {@code Runtime.Version.parse(Integer.toString(n))} where {@code n} is
   324      * {@code Runtime.Version.parse(Integer.toString(n))} where {@code n} is
   325      * {@code Math.max(version.major(), JarFile.baseVersion().major())}.
   325      * {@code Math.max(version.feature(), JarFile.baseVersion().feature())}.
   326      *
   326      *
   327      * @param file the jar file to be opened for reading
   327      * @param file the jar file to be opened for reading
   328      * @param verify whether or not to verify the jar file if
   328      * @param verify whether or not to verify the jar file if
   329      * it is signed.
   329      * it is signed.
   330      * @param mode the mode in which the file is to be opened
   330      * @param mode the mode in which the file is to be opened
   339      */
   339      */
   340     public JarFile(File file, boolean verify, int mode, Runtime.Version version) throws IOException {
   340     public JarFile(File file, boolean verify, int mode, Runtime.Version version) throws IOException {
   341         super(file, mode);
   341         super(file, mode);
   342         this.verify = verify;
   342         this.verify = verify;
   343         Objects.requireNonNull(version);
   343         Objects.requireNonNull(version);
   344         if (MULTI_RELEASE_FORCED || version.major() == RUNTIME_VERSION.major()) {
   344         if (MULTI_RELEASE_FORCED || version.feature() == RUNTIME_VERSION.feature()) {
   345             // This deals with the common case where the value from JarFile.runtimeVersion() is passed
   345             // This deals with the common case where the value from JarFile.runtimeVersion() is passed
   346             this.version = RUNTIME_VERSION;
   346             this.version = RUNTIME_VERSION;
   347         } else if (version.major() <= BASE_VERSION_MAJOR) {
   347         } else if (version.feature() <= BASE_VERSION_FEATURE) {
   348             // This also deals with the common case where the value from JarFile.baseVersion() is passed
   348             // This also deals with the common case where the value from JarFile.baseVersion() is passed
   349             this.version = BASE_VERSION;
   349             this.version = BASE_VERSION;
   350         } else {
   350         } else {
   351             // Canonicalize
   351             // Canonicalize
   352             this.version = Runtime.Version.parse(Integer.toString(version.major()));
   352             this.version = Runtime.Version.parse(Integer.toString(version.feature()));
   353         }
   353         }
   354         this.versionMajor = this.version.major();
   354         this.versionFeature = this.version.feature();
   355     }
   355     }
   356 
   356 
   357     /**
   357     /**
   358      * Returns the maximum version used when searching for versioned entries.
   358      * Returns the maximum version used when searching for versioned entries.
   359      * <p>
   359      * <p>
   577             int index = name.indexOf('/', off);
   577             int index = name.indexOf('/', off);
   578             try {
   578             try {
   579                 // filter out dir META-INF/versions/ and META-INF/versions/*/
   579                 // filter out dir META-INF/versions/ and META-INF/versions/*/
   580                 // and any entry with version > 'version'
   580                 // and any entry with version > 'version'
   581                 if (index == -1 || index == (name.length() - 1) ||
   581                 if (index == -1 || index == (name.length() - 1) ||
   582                     Integer.parseInt(name, off, index, 10) > versionMajor) {
   582                     Integer.parseInt(name, off, index, 10) > versionFeature) {
   583                     return null;
   583                     return null;
   584                 }
   584                 }
   585             } catch (NumberFormatException x) {
   585             } catch (NumberFormatException x) {
   586                 return null; // remove malformed entries silently
   586                 return null; // remove malformed entries silently
   587             }
   587             }
   590         }
   590         }
   591         return name;
   591         return name;
   592     }
   592     }
   593 
   593 
   594     private JarEntry getVersionedEntry(String name, JarEntry je) {
   594     private JarEntry getVersionedEntry(String name, JarEntry je) {
   595         if (BASE_VERSION_MAJOR < versionMajor) {
   595         if (BASE_VERSION_FEATURE < versionFeature) {
   596             if (!name.startsWith(META_INF)) {
   596             if (!name.startsWith(META_INF)) {
   597                 // search for versioned entry
   597                 // search for versioned entry
   598                 int v = versionMajor;
   598                 int v = versionFeature;
   599                 while (v > BASE_VERSION_MAJOR) {
   599                 while (v > BASE_VERSION_FEATURE) {
   600                     JarFileEntry vje = getEntry0(META_INF_VERSIONS + v + "/" + name);
   600                     JarFileEntry vje = getEntry0(META_INF_VERSIONS + v + "/" + name);
   601                     if (vje != null) {
   601                     if (vje != null) {
   602                         return vje.withBasename(name);
   602                         return vje.withBasename(name);
   603                     }
   603                     }
   604                     v--;
   604                     v--;
   671         public String getName() {
   671         public String getName() {
   672             return basename;
   672             return basename;
   673         }
   673         }
   674 
   674 
   675         JarFileEntry realEntry() {
   675         JarFileEntry realEntry() {
   676             if (isMultiRelease() && versionMajor != BASE_VERSION_MAJOR) {
   676             if (isMultiRelease() && versionFeature != BASE_VERSION_FEATURE) {
   677                 String entryName = super.getName();
   677                 String entryName = super.getName();
   678                 return entryName == basename || entryName.equals(basename) ?
   678                 return entryName == basename || entryName.equals(basename) ?
   679                         this : new JarFileEntry(entryName, this);
   679                         this : new JarFileEntry(entryName, this);
   680             }
   680             }
   681             return this;
   681             return this;