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
55 IndexNode getInode(byte[] path) {
56 // check for an alias to a versioned entry
57 byte[] versionedPath = lookup.apply(path);
58 return versionedPath == null ? super.getInode(path) : super.getInode(versionedPath);
59 }
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
|
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 jdk.internal.util.jar.JarAttributes;
39
40 /**
41 * Adds aliasing to ZipFileSystem to support multi-release jar files. An alias map
42 * is created by {@link JarFileSystem#createVersionedLinks(int)}. The map is then
43 * consulted when an entry is looked up in {@link JarFileSystem#getEntry(byte[])}
44 * to determine if the entry has a corresponding versioned entry. If so, the
45 * versioned entry is returned.
46 *
47 * @author Steve Drach
48 */
49
50 class JarFileSystem extends ZipFileSystem {
51 private Function<byte[],byte[]> lookup;
52
53 @Override
54 IndexNode getInode(byte[] path) {
55 // check for an alias to a versioned entry
56 byte[] versionedPath = lookup.apply(path);
57 return versionedPath == null ? super.getInode(path) : super.getInode(versionedPath);
58 }
70 if (s.equals("runtime")) {
71 version = Runtime.version().major();
72 } else {
73 version = Integer.parseInt(s);
74 }
75 } else if (o instanceof Integer) {
76 version = (Integer)o;
77 } else if (o instanceof Version) {
78 version = ((Version)o).major();
79 } else {
80 throw new IllegalArgumentException("env parameter must be String, Integer, "
81 + "or Version");
82 }
83 lookup = createVersionedLinks(version < 0 ? 0 : version);
84 setReadOnly();
85 }
86 }
87
88 private boolean isMultiReleaseJar() {
89 try (InputStream is = newInputStream(getBytes("/META-INF/MANIFEST.MF"))) {
90 byte[] manifest = is.readAllBytes();
91 return JarAttributes.isMultiRelease(manifest);
92 } catch (IOException x) {
93 return false;
94 }
95 }
96
97 /**
98 * create a map of aliases for versioned entries, for example:
99 * version/PackagePrivate.class -> META-INF/versions/9/version/PackagePrivate.class
100 * version/PackagePrivate.java -> META-INF/versions/9/version/PackagePrivate.java
101 * version/Version.class -> META-INF/versions/10/version/Version.class
102 * version/Version.java -> META-INF/versions/10/version/Version.java
103 *
104 * then wrap the map in a function that getEntry can use to override root
105 * entry lookup for entries that have corresponding versioned entries
106 */
107 private Function<byte[],byte[]> createVersionedLinks(int version) {
108 HashMap<IndexNode,byte[]> aliasMap = new HashMap<>();
109 getVersionMap(version, getInode(getBytes("/META-INF/versions"))).values()
110 .forEach(versionNode -> { // for each META-INF/versions/{n} directory
111 // put all the leaf inodes, i.e. entries, into the alias map
|