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; |