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.nio.file.Path; 31 import java.util.Arrays; 32 import java.util.HashMap; 33 import java.util.Map; 34 import java.util.TreeMap; 35 import java.util.function.Consumer; 36 import java.util.function.Function; 37 import java.util.jar.Attributes; 38 import java.util.jar.Manifest; 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 Entry getEntry(byte[] path) throws IOException { 55 // check for an alias to a versioned entry 56 byte[] versionedPath = lookup.apply(path); 57 return versionedPath == null ? super.getEntry(path) : super.getEntry(versionedPath); 58 } 59 60 JarFileSystem(ZipFileSystemProvider provider, Path zfpath, Map<String,?> env) 61 throws IOException { 62 super(provider, zfpath, env); 63 lookup = path -> path; // lookup needs to be set before isMultiReleaseJar is called 64 // because it eventually calls getEntry 65 if (isMultiReleaseJar()) { 66 int version; 67 Object o = env.get("multi-release"); 68 if (o instanceof String) { 69 String s = (String)o; 70 if (s.equals("runtime")) { 71 version = sun.misc.Version.jdkMajorVersion(); // fixme waiting for jdk.util.Version 72 } else { 73 version = Integer.parseInt(s); 74 } 75 } else if (o instanceof Integer) { 76 version = (Integer)o; 77 } else if (false /*o instanceof Version*/) { // fixme waiting for jdk.util.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 return (new Manifest(is)).getMainAttributes() 91 .containsKey(new Attributes.Name("Multi-Release")); 92 // fixme change line above after JarFile integration to contain Attributes.Name.MULTI_RELEASE 93 } catch (IOException x) { 94 return false; 95 } 96 } 97 98 /** | 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.nio.file.Path; 31 import java.util.Arrays; 32 import java.util.HashMap; 33 import java.util.Map; 34 import java.util.TreeMap; 35 import java.util.function.Consumer; 36 import java.util.function.Function; 37 import java.util.jar.Attributes; 38 import java.util.jar.Manifest; 39 import jdk.Version; 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 Entry getEntry(byte[] path) throws IOException { 56 // check for an alias to a versioned entry 57 byte[] versionedPath = lookup.apply(path); 58 return versionedPath == null ? super.getEntry(path) : super.getEntry(versionedPath); 59 } 60 61 JarFileSystem(ZipFileSystemProvider provider, Path zfpath, Map<String,?> env) 62 throws IOException { 63 super(provider, zfpath, env); 64 lookup = path -> path; // lookup needs to be set before isMultiReleaseJar is called 65 // because it eventually calls getEntry 66 if (isMultiReleaseJar()) { 67 int version; 68 Object o = env.get("multi-release"); 69 if (o instanceof String) { 70 String s = (String)o; 71 if (s.equals("runtime")) { 72 version = jdk.Version.current().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 /** |