11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.nio.zipfs;
27
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.lang.Runtime.Version;
31 import java.nio.file.Path;
32 import java.util.Arrays;
33 import java.util.HashMap;
34 import java.util.Map;
35 import java.util.TreeMap;
36 import java.util.function.Consumer;
37 import java.util.function.Function;
38 import java.util.jar.Attributes;
39 import java.util.jar.Manifest;
40
41 /**
42 * Adds aliasing to ZipFileSystem to support multi-release jar files. An alias map
43 * is created by {@link JarFileSystem#createVersionedLinks(int)}. The map is then
44 * consulted when an entry is looked up in {@link JarFileSystem#getEntry(byte[])}
45 * to determine if the entry has a corresponding versioned entry. If so, the
46 * versioned entry is returned.
47 *
48 * @author Steve Drach
49 */
50
51 class JarFileSystem extends ZipFileSystem {
52 private Function<byte[],byte[]> lookup;
53
54 @Override
69 if (o instanceof String) {
70 String s = (String)o;
71 if (s.equals("runtime")) {
72 version = Runtime.version().major();
73 } else {
74 version = Integer.parseInt(s);
75 }
76 } else if (o instanceof Integer) {
77 version = (Integer)o;
78 } else if (o instanceof Version) {
79 version = ((Version)o).major();
80 } else {
81 throw new IllegalArgumentException("env parameter must be String, Integer, "
82 + "or Version");
83 }
84 lookup = createVersionedLinks(version < 0 ? 0 : version);
85 setReadOnly();
86 }
87 }
88
89 private boolean isMultiReleaseJar() {
90 try (InputStream is = newInputStream(getBytes("/META-INF/MANIFEST.MF"))) {
91 return (new Manifest(is)).getMainAttributes()
92 .containsKey(new Attributes.Name("Multi-Release"));
93 // fixme change line above after JarFile integration to contain Attributes.Name.MULTI_RELEASE
94 } catch (IOException x) {
95 return false;
96 }
97 }
98
99 /**
100 * create a map of aliases for versioned entries, for example:
101 * version/PackagePrivate.class -> META-INF/versions/9/version/PackagePrivate.class
102 * version/PackagePrivate.java -> META-INF/versions/9/version/PackagePrivate.java
103 * version/Version.class -> META-INF/versions/10/version/Version.class
104 * version/Version.java -> META-INF/versions/10/version/Version.java
105 *
106 * then wrap the map in a function that getEntry can use to override root
107 * entry lookup for entries that have corresponding versioned entries
108 */
109 private Function<byte[],byte[]> createVersionedLinks(int version) {
110 HashMap<IndexNode,byte[]> aliasMap = new HashMap<>();
111 getVersionMap(version, getInode(getBytes("/META-INF/versions"))).values()
112 .forEach(versionNode -> { // for each META-INF/versions/{n} directory
113 // put all the leaf inodes, i.e. entries, into the alias map
114 // possibly shadowing lower versioned entries
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.nio.zipfs;
27
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.lang.Runtime.Version;
31 import java.nio.file.NoSuchFileException;
32 import java.nio.file.Path;
33 import java.util.Arrays;
34 import java.util.HashMap;
35 import java.util.Map;
36 import java.util.Objects;
37 import java.util.TreeMap;
38 import java.util.function.Consumer;
39 import java.util.function.Function;
40 import java.util.jar.Attributes;
41 import java.util.jar.Manifest;
42
43 /**
44 * Adds aliasing to ZipFileSystem to support multi-release jar files. An alias map
45 * is created by {@link JarFileSystem#createVersionedLinks(int)}. The map is then
46 * consulted when an entry is looked up in {@link JarFileSystem#getEntry(byte[])}
47 * to determine if the entry has a corresponding versioned entry. If so, the
48 * versioned entry is returned.
49 *
50 * @author Steve Drach
51 */
52
53 class JarFileSystem extends ZipFileSystem {
54 private Function<byte[],byte[]> lookup;
55
56 @Override
71 if (o instanceof String) {
72 String s = (String)o;
73 if (s.equals("runtime")) {
74 version = Runtime.version().major();
75 } else {
76 version = Integer.parseInt(s);
77 }
78 } else if (o instanceof Integer) {
79 version = (Integer)o;
80 } else if (o instanceof Version) {
81 version = ((Version)o).major();
82 } else {
83 throw new IllegalArgumentException("env parameter must be String, Integer, "
84 + "or Version");
85 }
86 lookup = createVersionedLinks(version < 0 ? 0 : version);
87 setReadOnly();
88 }
89 }
90
91 private boolean isMultiReleaseJar() throws IOException {
92 try (InputStream is = newInputStream(getBytes("/META-INF/MANIFEST.MF"))) {
93 String multiRelease = new Manifest(is).getMainAttributes()
94 .getValue(Attributes.Name.MULTI_RELEASE);
95 return "true".equalsIgnoreCase(multiRelease);
96 } catch (NoSuchFileException x) {
97 return false;
98 }
99 }
100
101 /**
102 * create a map of aliases for versioned entries, for example:
103 * version/PackagePrivate.class -> META-INF/versions/9/version/PackagePrivate.class
104 * version/PackagePrivate.java -> META-INF/versions/9/version/PackagePrivate.java
105 * version/Version.class -> META-INF/versions/10/version/Version.class
106 * version/Version.java -> META-INF/versions/10/version/Version.java
107 *
108 * then wrap the map in a function that getEntry can use to override root
109 * entry lookup for entries that have corresponding versioned entries
110 */
111 private Function<byte[],byte[]> createVersionedLinks(int version) {
112 HashMap<IndexNode,byte[]> aliasMap = new HashMap<>();
113 getVersionMap(version, getInode(getBytes("/META-INF/versions"))).values()
114 .forEach(versionNode -> { // for each META-INF/versions/{n} directory
115 // put all the leaf inodes, i.e. entries, into the alias map
116 // possibly shadowing lower versioned entries
|