8234089: (zipfs) Remove classes JarFileSystemProvider and JarFileSystem
Reviewed-by: lancea, alanb
This commit is contained in:
parent
3600213f1d
commit
b240008ba2
@ -1,202 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jdk.nio.zipfs;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.lang.Runtime.Version;
|
|
||||||
import java.nio.file.NoSuchFileException;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.jar.Attributes;
|
|
||||||
import java.util.jar.Manifest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds aliasing to ZipFileSystem to support multi-release jar files. An alias map
|
|
||||||
* is created by {@link JarFileSystem#createVersionedLinks(int)}. The map is then
|
|
||||||
* consulted when an entry is looked up in {@link JarFileSystem#getInode(byte[])}
|
|
||||||
* to determine if the entry has a corresponding versioned entry. If so, the
|
|
||||||
* versioned entry is returned.
|
|
||||||
*
|
|
||||||
* @author Steve Drach
|
|
||||||
*/
|
|
||||||
class JarFileSystem extends ZipFileSystem {
|
|
||||||
// lookup needs to be initialized because isMultiReleaseJar is called before createVersionedLinks
|
|
||||||
private Function<byte[], byte[]> lookup = path -> path;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
IndexNode getInode(byte[] path) {
|
|
||||||
// check for an alias to a versioned entry
|
|
||||||
return super.getInode(lookup.apply(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
JarFileSystem(ZipFileSystemProvider provider, Path zfpath, Map<String,?> env) throws IOException {
|
|
||||||
super(provider, zfpath, env);
|
|
||||||
Object o = getRuntimeVersion(env);
|
|
||||||
if (isMultiReleaseJar() && (o != null)) {
|
|
||||||
int version;
|
|
||||||
if (o instanceof String) {
|
|
||||||
String s = (String)o;
|
|
||||||
if (s.equals("runtime")) {
|
|
||||||
version = Runtime.version().feature();
|
|
||||||
} else if (s.matches("^[1-9][0-9]*$")) {
|
|
||||||
version = Version.parse(s).feature();
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Invalid runtime version");
|
|
||||||
}
|
|
||||||
} else if (o instanceof Integer) {
|
|
||||||
version = Version.parse(((Integer)o).toString()).feature();
|
|
||||||
} else if (o instanceof Version) {
|
|
||||||
version = ((Version)o).feature();
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("env parameter must be String, Integer, "
|
|
||||||
+ "or Version");
|
|
||||||
}
|
|
||||||
createVersionedLinks(version < 0 ? 0 : version);
|
|
||||||
setReadOnly();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility method to get the release version for a multi-release JAR. It
|
|
||||||
* first checks the documented property {@code releaseVersion} and if not
|
|
||||||
* found checks the original property {@code multi-release}
|
|
||||||
* @param env ZIP FS map
|
|
||||||
* @return release version or null if it is not specified
|
|
||||||
*/
|
|
||||||
private Object getRuntimeVersion(Map<String, ?> env) {
|
|
||||||
Object o = null;
|
|
||||||
if (env.containsKey(ZipFileSystemProvider.PROPERTY_RELEASE_VERSION)) {
|
|
||||||
o = env.get(ZipFileSystemProvider.PROPERTY_RELEASE_VERSION);
|
|
||||||
} else {
|
|
||||||
o = env.get(ZipFileSystemProvider.PROPERTY_MULTI_RELEASE);
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isMultiReleaseJar() throws IOException {
|
|
||||||
try (InputStream is = newInputStream(getBytes("/META-INF/MANIFEST.MF"))) {
|
|
||||||
String multiRelease = new Manifest(is).getMainAttributes()
|
|
||||||
.getValue(Attributes.Name.MULTI_RELEASE);
|
|
||||||
return "true".equalsIgnoreCase(multiRelease);
|
|
||||||
} catch (NoSuchFileException x) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create a map of aliases for versioned entries, for example:
|
|
||||||
* version/PackagePrivate.class -> META-INF/versions/9/version/PackagePrivate.class
|
|
||||||
* version/PackagePrivate.java -> META-INF/versions/9/version/PackagePrivate.java
|
|
||||||
* version/Version.class -> META-INF/versions/10/version/Version.class
|
|
||||||
* version/Version.java -> META-INF/versions/10/version/Version.java
|
|
||||||
*
|
|
||||||
* then wrap the map in a function that getEntry can use to override root
|
|
||||||
* entry lookup for entries that have corresponding versioned entries
|
|
||||||
*/
|
|
||||||
private void createVersionedLinks(int version) {
|
|
||||||
IndexNode verdir = getInode(getBytes("/META-INF/versions"));
|
|
||||||
// nothing to do, if no /META-INF/versions
|
|
||||||
if (verdir == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// otherwise, create a map and for each META-INF/versions/{n} directory
|
|
||||||
// put all the leaf inodes, i.e. entries, into the alias map
|
|
||||||
// possibly shadowing lower versioned entries
|
|
||||||
HashMap<IndexNode, byte[]> aliasMap = new HashMap<>();
|
|
||||||
getVersionMap(version, verdir).values().forEach(versionNode ->
|
|
||||||
walk(versionNode.child, entryNode ->
|
|
||||||
aliasMap.put(
|
|
||||||
getOrCreateInode(getRootName(entryNode, versionNode), entryNode.isdir),
|
|
||||||
entryNode.name))
|
|
||||||
);
|
|
||||||
lookup = path -> {
|
|
||||||
byte[] entry = aliasMap.get(IndexNode.keyOf(path));
|
|
||||||
return entry == null ? path : entry;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create a sorted version map of version -> inode, for inodes <= max version
|
|
||||||
* 9 -> META-INF/versions/9
|
|
||||||
* 10 -> META-INF/versions/10
|
|
||||||
*/
|
|
||||||
private TreeMap<Integer, IndexNode> getVersionMap(int version, IndexNode metaInfVersions) {
|
|
||||||
TreeMap<Integer,IndexNode> map = new TreeMap<>();
|
|
||||||
IndexNode child = metaInfVersions.child;
|
|
||||||
while (child != null) {
|
|
||||||
Integer key = getVersion(child, metaInfVersions);
|
|
||||||
if (key != null && key <= version) {
|
|
||||||
map.put(key, child);
|
|
||||||
}
|
|
||||||
child = child.sibling;
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* extract the integer version number -- META-INF/versions/9 returns 9
|
|
||||||
*/
|
|
||||||
private Integer getVersion(IndexNode inode, IndexNode metaInfVersions) {
|
|
||||||
try {
|
|
||||||
byte[] fullName = inode.name;
|
|
||||||
return Integer.parseInt(getString(Arrays
|
|
||||||
.copyOfRange(fullName, metaInfVersions.name.length + 1, fullName.length)));
|
|
||||||
} catch (NumberFormatException x) {
|
|
||||||
// ignore this even though it might indicate issues with the JAR structure
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* walk the IndexNode tree processing all leaf nodes
|
|
||||||
*/
|
|
||||||
private void walk(IndexNode inode, Consumer<IndexNode> consumer) {
|
|
||||||
if (inode == null) return;
|
|
||||||
if (inode.isDir()) {
|
|
||||||
walk(inode.child, consumer);
|
|
||||||
} else {
|
|
||||||
consumer.accept(inode);
|
|
||||||
}
|
|
||||||
walk(inode.sibling, consumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* extract the root name from a versioned entry name
|
|
||||||
* given inode for META-INF/versions/9/foo/bar.class
|
|
||||||
* and prefix META-INF/versions/9/
|
|
||||||
* returns foo/bar.class
|
|
||||||
*/
|
|
||||||
private byte[] getRootName(IndexNode inode, IndexNode prefix) {
|
|
||||||
byte[] fullName = inode.name;
|
|
||||||
return Arrays.copyOfRange(fullName, prefix.name.length, fullName.length);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jdk.nio.zipfs;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.nio.file.FileSystem;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
class JarFileSystemProvider extends ZipFileSystemProvider {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getScheme() {
|
|
||||||
return "jar";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Path uriToPath(URI uri) {
|
|
||||||
String scheme = uri.getScheme();
|
|
||||||
if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
|
|
||||||
throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
String uristr = uri.toString();
|
|
||||||
int end = uristr.indexOf("!/");
|
|
||||||
uristr = uristr.substring(4, (end == -1) ? uristr.length() : end);
|
|
||||||
uri = new URI(uristr);
|
|
||||||
return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null))
|
|
||||||
.toAbsolutePath();
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
throw new AssertionError(e); //never thrown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Path getPath(URI uri) {
|
|
||||||
FileSystem fs = getFileSystem(uri);
|
|
||||||
String path = uri.getFragment();
|
|
||||||
if (path == null) {
|
|
||||||
String uristr = uri.toString();
|
|
||||||
int off = uristr.indexOf("!/");
|
|
||||||
if (off != -1)
|
|
||||||
path = uristr.substring(off + 2);
|
|
||||||
}
|
|
||||||
if (path != null)
|
|
||||||
return fs.getPath(path);
|
|
||||||
throw new IllegalArgumentException("URI: "
|
|
||||||
+ uri
|
|
||||||
+ " does not contain path fragment ex. jar:///c:/foo.zip!/BAR");
|
|
||||||
}
|
|
||||||
}
|
|
@ -33,6 +33,7 @@ import java.io.FilterOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.lang.Runtime.Version;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.MappedByteBuffer;
|
import java.nio.MappedByteBuffer;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
@ -50,6 +51,10 @@ import java.security.PrivilegedExceptionAction;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.jar.Attributes;
|
||||||
|
import java.util.jar.Manifest;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
import java.util.zip.Deflater;
|
import java.util.zip.Deflater;
|
||||||
@ -85,6 +90,11 @@ class ZipFileSystem extends FileSystem {
|
|||||||
private static final String PROPERTY_DEFAULT_OWNER = "defaultOwner";
|
private static final String PROPERTY_DEFAULT_OWNER = "defaultOwner";
|
||||||
private static final String PROPERTY_DEFAULT_GROUP = "defaultGroup";
|
private static final String PROPERTY_DEFAULT_GROUP = "defaultGroup";
|
||||||
private static final String PROPERTY_DEFAULT_PERMISSIONS = "defaultPermissions";
|
private static final String PROPERTY_DEFAULT_PERMISSIONS = "defaultPermissions";
|
||||||
|
// Property used to specify the entry version to use for a multi-release JAR
|
||||||
|
private static final String PROPERTY_RELEASE_VERSION = "releaseVersion";
|
||||||
|
// Original property used to specify the entry version to use for a
|
||||||
|
// multi-release JAR which is kept for backwards compatibility.
|
||||||
|
private static final String PROPERTY_MULTI_RELEASE = "multi-release";
|
||||||
|
|
||||||
private static final Set<PosixFilePermission> DEFAULT_PERMISSIONS =
|
private static final Set<PosixFilePermission> DEFAULT_PERMISSIONS =
|
||||||
PosixFilePermissions.fromString("rwxrwxrwx");
|
PosixFilePermissions.fromString("rwxrwxrwx");
|
||||||
@ -112,6 +122,9 @@ class ZipFileSystem extends FileSystem {
|
|||||||
private final int defaultCompressionMethod; // METHOD_STORED if "noCompression=true"
|
private final int defaultCompressionMethod; // METHOD_STORED if "noCompression=true"
|
||||||
// METHOD_DEFLATED otherwise
|
// METHOD_DEFLATED otherwise
|
||||||
|
|
||||||
|
// entryLookup is identity by default, will be overridden for multi-release jars
|
||||||
|
private Function<byte[], byte[]> entryLookup = Function.identity();
|
||||||
|
|
||||||
// POSIX support
|
// POSIX support
|
||||||
final boolean supportPosix;
|
final boolean supportPosix;
|
||||||
private final UserPrincipal defaultOwner;
|
private final UserPrincipal defaultOwner;
|
||||||
@ -167,6 +180,8 @@ class ZipFileSystem extends FileSystem {
|
|||||||
}
|
}
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.zfpath = zfpath;
|
this.zfpath = zfpath;
|
||||||
|
|
||||||
|
initializeReleaseVersion(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1349,6 +1364,142 @@ class ZipFileSystem extends FileSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a version property has been specified and the file represents a multi-release JAR,
|
||||||
|
* determine the requested runtime version and initialize the ZipFileSystem instance accordingly.
|
||||||
|
*
|
||||||
|
* Checks if the Zip File System property "releaseVersion" has been specified. If it has,
|
||||||
|
* use its value to determine the requested version. If not use the value of the "multi-release" property.
|
||||||
|
*/
|
||||||
|
private void initializeReleaseVersion(Map<String, ?> env) throws IOException {
|
||||||
|
Object o = env.containsKey(PROPERTY_RELEASE_VERSION) ?
|
||||||
|
env.get(PROPERTY_RELEASE_VERSION) :
|
||||||
|
env.get(PROPERTY_MULTI_RELEASE);
|
||||||
|
|
||||||
|
if (o != null && isMultiReleaseJar()) {
|
||||||
|
int version;
|
||||||
|
if (o instanceof String) {
|
||||||
|
String s = (String)o;
|
||||||
|
if (s.equals("runtime")) {
|
||||||
|
version = Runtime.version().feature();
|
||||||
|
} else if (s.matches("^[1-9][0-9]*$")) {
|
||||||
|
version = Version.parse(s).feature();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Invalid runtime version");
|
||||||
|
}
|
||||||
|
} else if (o instanceof Integer) {
|
||||||
|
version = Version.parse(((Integer)o).toString()).feature();
|
||||||
|
} else if (o instanceof Version) {
|
||||||
|
version = ((Version)o).feature();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("env parameter must be String, " +
|
||||||
|
"Integer, or Version");
|
||||||
|
}
|
||||||
|
createVersionedLinks(version < 0 ? 0 : version);
|
||||||
|
setReadOnly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the Manifest main attribute "Multi-Release" is set to true; false otherwise.
|
||||||
|
*/
|
||||||
|
private boolean isMultiReleaseJar() throws IOException {
|
||||||
|
try (InputStream is = newInputStream(getBytes("/META-INF/MANIFEST.MF"))) {
|
||||||
|
String multiRelease = new Manifest(is).getMainAttributes()
|
||||||
|
.getValue(Attributes.Name.MULTI_RELEASE);
|
||||||
|
return "true".equalsIgnoreCase(multiRelease);
|
||||||
|
} catch (NoSuchFileException x) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a map of aliases for versioned entries, for example:
|
||||||
|
* version/PackagePrivate.class -> META-INF/versions/9/version/PackagePrivate.class
|
||||||
|
* version/PackagePrivate.java -> META-INF/versions/9/version/PackagePrivate.java
|
||||||
|
* version/Version.class -> META-INF/versions/10/version/Version.class
|
||||||
|
* version/Version.java -> META-INF/versions/10/version/Version.java
|
||||||
|
*
|
||||||
|
* Then wrap the map in a function that getEntry can use to override root
|
||||||
|
* entry lookup for entries that have corresponding versioned entries.
|
||||||
|
*/
|
||||||
|
private void createVersionedLinks(int version) {
|
||||||
|
IndexNode verdir = getInode(getBytes("/META-INF/versions"));
|
||||||
|
// nothing to do, if no /META-INF/versions
|
||||||
|
if (verdir == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// otherwise, create a map and for each META-INF/versions/{n} directory
|
||||||
|
// put all the leaf inodes, i.e. entries, into the alias map
|
||||||
|
// possibly shadowing lower versioned entries
|
||||||
|
HashMap<IndexNode, byte[]> aliasMap = new HashMap<>();
|
||||||
|
getVersionMap(version, verdir).values().forEach(versionNode ->
|
||||||
|
walk(versionNode.child, entryNode ->
|
||||||
|
aliasMap.put(
|
||||||
|
getOrCreateInode(getRootName(entryNode, versionNode), entryNode.isdir),
|
||||||
|
entryNode.name))
|
||||||
|
);
|
||||||
|
entryLookup = path -> {
|
||||||
|
byte[] entry = aliasMap.get(IndexNode.keyOf(path));
|
||||||
|
return entry == null ? path : entry;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a sorted version map of version -> inode, for inodes <= max version.
|
||||||
|
* 9 -> META-INF/versions/9
|
||||||
|
* 10 -> META-INF/versions/10
|
||||||
|
*/
|
||||||
|
private TreeMap<Integer, IndexNode> getVersionMap(int version, IndexNode metaInfVersions) {
|
||||||
|
TreeMap<Integer,IndexNode> map = new TreeMap<>();
|
||||||
|
IndexNode child = metaInfVersions.child;
|
||||||
|
while (child != null) {
|
||||||
|
Integer key = getVersion(child, metaInfVersions);
|
||||||
|
if (key != null && key <= version) {
|
||||||
|
map.put(key, child);
|
||||||
|
}
|
||||||
|
child = child.sibling;
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the integer version number -- META-INF/versions/9 returns 9.
|
||||||
|
*/
|
||||||
|
private Integer getVersion(IndexNode inode, IndexNode metaInfVersions) {
|
||||||
|
try {
|
||||||
|
byte[] fullName = inode.name;
|
||||||
|
return Integer.parseInt(getString(Arrays
|
||||||
|
.copyOfRange(fullName, metaInfVersions.name.length + 1, fullName.length)));
|
||||||
|
} catch (NumberFormatException x) {
|
||||||
|
// ignore this even though it might indicate issues with the JAR structure
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Walk the IndexNode tree processing all leaf nodes.
|
||||||
|
*/
|
||||||
|
private void walk(IndexNode inode, Consumer<IndexNode> consumer) {
|
||||||
|
if (inode == null) return;
|
||||||
|
if (inode.isDir()) {
|
||||||
|
walk(inode.child, consumer);
|
||||||
|
} else {
|
||||||
|
consumer.accept(inode);
|
||||||
|
}
|
||||||
|
walk(inode.sibling, consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the root name from a versioned entry name.
|
||||||
|
* E.g. given inode 'META-INF/versions/9/foo/bar.class'
|
||||||
|
* and prefix 'META-INF/versions/9/' returns 'foo/bar.class'.
|
||||||
|
*/
|
||||||
|
private byte[] getRootName(IndexNode inode, IndexNode prefix) {
|
||||||
|
byte[] fullName = inode.name;
|
||||||
|
return Arrays.copyOfRange(fullName, prefix.name.length, fullName.length);
|
||||||
|
}
|
||||||
|
|
||||||
// Reads zip file central directory. Returns the file position of first
|
// Reads zip file central directory. Returns the file position of first
|
||||||
// CEN header, otherwise returns -1 if an error occurred. If zip->msg != NULL
|
// CEN header, otherwise returns -1 if an error occurred. If zip->msg != NULL
|
||||||
// then the error was a zip format error and zip->msg has the error text.
|
// then the error was a zip format error and zip->msg has the error text.
|
||||||
@ -1644,15 +1795,15 @@ class ZipFileSystem extends FileSystem {
|
|||||||
hasUpdate = false; // clear
|
hasUpdate = false; // clear
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexNode getInode(byte[] path) {
|
private IndexNode getInode(byte[] path) {
|
||||||
return inodes.get(IndexNode.keyOf(Objects.requireNonNull(path, "path")));
|
return inodes.get(IndexNode.keyOf(Objects.requireNonNull(entryLookup.apply(path), "path")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the IndexNode from the root tree. If it doesn't exist,
|
* Return the IndexNode from the root tree. If it doesn't exist,
|
||||||
* it gets created along with all parent directory IndexNodes.
|
* it gets created along with all parent directory IndexNodes.
|
||||||
*/
|
*/
|
||||||
IndexNode getOrCreateInode(byte[] path, boolean isdir) {
|
private IndexNode getOrCreateInode(byte[] path, boolean isdir) {
|
||||||
IndexNode node = getInode(path);
|
IndexNode node = getInode(path);
|
||||||
// if node exists, return it
|
// if node exists, return it
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
@ -2248,7 +2399,7 @@ class ZipFileSystem extends FileSystem {
|
|||||||
|
|
||||||
private static final ThreadLocal<IndexNode> cachedKey = new ThreadLocal<>();
|
private static final ThreadLocal<IndexNode> cachedKey = new ThreadLocal<>();
|
||||||
|
|
||||||
final static IndexNode keyOf(byte[] name) { // get a lookup key;
|
static final IndexNode keyOf(byte[] name) { // get a lookup key;
|
||||||
IndexNode key = cachedKey.get();
|
IndexNode key = cachedKey.get();
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
key = new IndexNode(name, -1);
|
key = new IndexNode(name, -1);
|
||||||
|
@ -52,12 +52,6 @@ import java.util.zip.ZipException;
|
|||||||
* @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
|
* @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
|
||||||
*/
|
*/
|
||||||
public class ZipFileSystemProvider extends FileSystemProvider {
|
public class ZipFileSystemProvider extends FileSystemProvider {
|
||||||
|
|
||||||
// Property used to specify the entry version to use for a multi-release JAR
|
|
||||||
static final String PROPERTY_RELEASE_VERSION = "releaseVersion";
|
|
||||||
// Original property used to specify the entry version to use for a
|
|
||||||
// multi-release JAR which is kept for backwards compatibility.
|
|
||||||
static final String PROPERTY_MULTI_RELEASE = "multi-release";
|
|
||||||
private final Map<Path, ZipFileSystem> filesystems = new HashMap<>();
|
private final Map<Path, ZipFileSystem> filesystems = new HashMap<>();
|
||||||
|
|
||||||
public ZipFileSystemProvider() {}
|
public ZipFileSystemProvider() {}
|
||||||
@ -127,21 +121,14 @@ public class ZipFileSystemProvider extends FileSystemProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ZipFileSystem getZipFileSystem(Path path, Map<String, ?> env) throws IOException {
|
private ZipFileSystem getZipFileSystem(Path path, Map<String, ?> env) throws IOException {
|
||||||
ZipFileSystem zipfs;
|
|
||||||
try {
|
try {
|
||||||
if (env.containsKey(PROPERTY_RELEASE_VERSION) ||
|
return new ZipFileSystem(this, path, env);
|
||||||
env.containsKey(PROPERTY_MULTI_RELEASE)) {
|
|
||||||
zipfs = new JarFileSystem(this, path, env);
|
|
||||||
} else {
|
|
||||||
zipfs = new ZipFileSystem(this, path, env);
|
|
||||||
}
|
|
||||||
} catch (ZipException ze) {
|
} catch (ZipException ze) {
|
||||||
String pname = path.toString();
|
String pname = path.toString();
|
||||||
if (pname.endsWith(".zip") || pname.endsWith(".jar"))
|
if (pname.endsWith(".zip") || pname.endsWith(".jar"))
|
||||||
throw ze;
|
throw ze;
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
return zipfs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -54,9 +54,9 @@ public class ModulesInCustomFileSystem {
|
|||||||
private static final Path HERE = Paths.get("");
|
private static final Path HERE = Paths.get("");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test exploded modules in a JAR file system.
|
* Test exploded modules in a Zip file system.
|
||||||
*/
|
*/
|
||||||
public void testExplodedModulesInJarFileSystem() throws Exception {
|
public void testExplodedModulesInZipFileSystem() throws Exception {
|
||||||
Path m1 = findModuleDirectory("m1");
|
Path m1 = findModuleDirectory("m1");
|
||||||
Path m2 = findModuleDirectory("m2");
|
Path m2 = findModuleDirectory("m2");
|
||||||
Path mlib = m1.getParent();
|
Path mlib = m1.getParent();
|
||||||
@ -65,13 +65,13 @@ public class ModulesInCustomFileSystem {
|
|||||||
// create JAR file containing m1/** and m2/**
|
// create JAR file containing m1/** and m2/**
|
||||||
Path jar = Files.createTempDirectory(HERE, "mlib").resolve("modules.jar");
|
Path jar = Files.createTempDirectory(HERE, "mlib").resolve("modules.jar");
|
||||||
JarUtils.createJarFile(jar, mlib);
|
JarUtils.createJarFile(jar, mlib);
|
||||||
testJarFileSystem(jar);
|
testZipFileSystem(jar);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test modular JARs in a JAR file system
|
* Test modular JARs in a Zip file system.
|
||||||
*/
|
*/
|
||||||
public void testModularJARsInJarFileSystem() throws Exception {
|
public void testModularJARsInZipFileSystem() throws Exception {
|
||||||
Path m1 = findModuleDirectory("m1");
|
Path m1 = findModuleDirectory("m1");
|
||||||
Path m2 = findModuleDirectory("m2");
|
Path m2 = findModuleDirectory("m2");
|
||||||
Path contents = Files.createTempDirectory(HERE, "contents");
|
Path contents = Files.createTempDirectory(HERE, "contents");
|
||||||
@ -81,15 +81,14 @@ public class ModulesInCustomFileSystem {
|
|||||||
// create JAR file containing m1.jar and m2.jar
|
// create JAR file containing m1.jar and m2.jar
|
||||||
Path jar = Files.createTempDirectory(HERE, "mlib").resolve("modules.jar");
|
Path jar = Files.createTempDirectory(HERE, "mlib").resolve("modules.jar");
|
||||||
JarUtils.createJarFile(jar, contents);
|
JarUtils.createJarFile(jar, contents);
|
||||||
testJarFileSystem(jar);
|
testZipFileSystem(jar);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a JAR file as a file system
|
* Opens a JAR file as a file system
|
||||||
*/
|
*/
|
||||||
private void testJarFileSystem(Path jar) throws Exception {
|
private void testZipFileSystem(Path zip) throws Exception {
|
||||||
ClassLoader scl = ClassLoader.getSystemClassLoader();
|
try (FileSystem fs = FileSystems.newFileSystem(zip)) {
|
||||||
try (FileSystem fs = FileSystems.newFileSystem(jar, scl)) {
|
|
||||||
// ModuleFinder to find modules in top-level directory
|
// ModuleFinder to find modules in top-level directory
|
||||||
Path top = fs.getPath("/");
|
Path top = fs.getPath("/");
|
||||||
ModuleFinder finder = ModuleFinder.of(top);
|
ModuleFinder finder = ModuleFinder.of(top);
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8164389 8222440
|
* @bug 8164389 8222440
|
||||||
* @summary walk entries in a jdk.nio.zipfs.JarFileSystem
|
* @summary walk entries in a multi-release jar file via jdk.zipfs
|
||||||
* @library /lib/testlibrary/java/util/jar
|
* @library /lib/testlibrary/java/util/jar
|
||||||
* @modules jdk.jartool
|
* @modules jdk.jartool
|
||||||
* jdk.zipfs
|
* jdk.zipfs
|
||||||
|
@ -50,6 +50,8 @@ import org.testng.annotations.*;
|
|||||||
|
|
||||||
public class MultiReleaseJarTest {
|
public class MultiReleaseJarTest {
|
||||||
final private int MAJOR_VERSION = Runtime.version().feature();
|
final private int MAJOR_VERSION = Runtime.version().feature();
|
||||||
|
private static final String PROPERTY_RELEASE_VERSION = "releaseVersion";
|
||||||
|
private static final String PROPERTY_MULTI_RELEASE = "multi-release";
|
||||||
|
|
||||||
final private String userdir = System.getProperty("user.dir",".");
|
final private String userdir = System.getProperty("user.dir",".");
|
||||||
final private CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
|
final private CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
|
||||||
@ -88,56 +90,56 @@ public class MultiReleaseJarTest {
|
|||||||
@DataProvider(name="strings")
|
@DataProvider(name="strings")
|
||||||
public Object[][] createStrings() {
|
public Object[][] createStrings() {
|
||||||
return new Object[][]{
|
return new Object[][]{
|
||||||
{"runtime", MAJOR_VERSION},
|
{"runtime", MAJOR_VERSION, "8"},
|
||||||
{null, 8},
|
{null, 8, Integer.toString(MAJOR_VERSION)},
|
||||||
{"8", 8},
|
{"8", 8, "9"},
|
||||||
{"9", 9},
|
{"9", 9, null},
|
||||||
{Integer.toString(MAJOR_VERSION), MAJOR_VERSION},
|
{Integer.toString(MAJOR_VERSION), MAJOR_VERSION, "8"},
|
||||||
{Integer.toString(MAJOR_VERSION+1), MAJOR_VERSION},
|
{Integer.toString(MAJOR_VERSION+1), MAJOR_VERSION, "8"},
|
||||||
{"50", MAJOR_VERSION}
|
{"50", MAJOR_VERSION, "9"}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@DataProvider(name="integers")
|
@DataProvider(name="integers")
|
||||||
public Object[][] createIntegers() {
|
public Object[][] createIntegers() {
|
||||||
return new Object[][] {
|
return new Object[][] {
|
||||||
{null, 8},
|
{null, 8, Integer.valueOf(9)},
|
||||||
{Integer.valueOf(8), 8},
|
{Integer.valueOf(8), 8, Integer.valueOf(9)},
|
||||||
{Integer.valueOf(9), 9},
|
{Integer.valueOf(9), 9, Integer.valueOf(MAJOR_VERSION)},
|
||||||
{Integer.valueOf(MAJOR_VERSION), MAJOR_VERSION},
|
{Integer.valueOf(MAJOR_VERSION), MAJOR_VERSION, Integer.valueOf(8)},
|
||||||
{Integer.valueOf(MAJOR_VERSION + 1), MAJOR_VERSION},
|
{Integer.valueOf(MAJOR_VERSION + 1), MAJOR_VERSION, null},
|
||||||
{Integer.valueOf(100), MAJOR_VERSION}
|
{Integer.valueOf(100), MAJOR_VERSION, Integer.valueOf(8)}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@DataProvider(name="versions")
|
@DataProvider(name="versions")
|
||||||
public Object[][] createVersions() {
|
public Object[][] createVersions() {
|
||||||
return new Object[][] {
|
return new Object[][] {
|
||||||
{null, 8},
|
{null, 8, Version.parse("14")},
|
||||||
{Version.parse("8"), 8},
|
{Version.parse("8"), 8, Version.parse("7")},
|
||||||
{Version.parse("9"), 9},
|
{Version.parse("9"), 9, null},
|
||||||
{Version.parse(Integer.toString(MAJOR_VERSION)), MAJOR_VERSION},
|
{Version.parse(Integer.toString(MAJOR_VERSION)), MAJOR_VERSION, Version.parse("8")},
|
||||||
{Version.parse(Integer.toString(MAJOR_VERSION) + 1), MAJOR_VERSION},
|
{Version.parse(Integer.toString(MAJOR_VERSION) + 1), MAJOR_VERSION, Version.parse("9")},
|
||||||
{Version.parse("100"), MAJOR_VERSION}
|
{Version.parse("100"), MAJOR_VERSION, Version.parse("14")}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@DataProvider(name="invalidVersions")
|
@DataProvider(name="invalidVersions")
|
||||||
public Object[][] invalidVersions() {
|
public Object[][] invalidVersions() {
|
||||||
return new Object[][] {
|
return new Object[][] {
|
||||||
{Map.of("releaseVersion", "")},
|
{Map.of(PROPERTY_RELEASE_VERSION, "")},
|
||||||
{Map.of("releaseVersion", "invalid")},
|
{Map.of(PROPERTY_RELEASE_VERSION, "invalid")},
|
||||||
{Map.of("releaseVersion", "0")},
|
{Map.of(PROPERTY_RELEASE_VERSION, "0")},
|
||||||
{Map.of("releaseVersion", "-1")},
|
{Map.of(PROPERTY_RELEASE_VERSION, "-1")},
|
||||||
{Map.of("releaseVersion", "11.0.1")},
|
{Map.of(PROPERTY_RELEASE_VERSION, "11.0.1")},
|
||||||
{Map.of("releaseVersion", new ArrayList<Long>())},
|
{Map.of(PROPERTY_RELEASE_VERSION, new ArrayList<Long>())},
|
||||||
{Map.of("releaseVersion", Integer.valueOf(0))},
|
{Map.of(PROPERTY_RELEASE_VERSION, Integer.valueOf(0))},
|
||||||
{Map.of("releaseVersion", Integer.valueOf(-1))}
|
{Map.of(PROPERTY_RELEASE_VERSION, Integer.valueOf(-1))}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not the best test but all I can do since ZipFileSystem and JarFileSystem
|
// Not the best test but all I can do since ZipFileSystem
|
||||||
// are not public, so I can't use (fs instanceof ...)
|
// is not public, so I can't use (fs instanceof ...)
|
||||||
@Test
|
@Test
|
||||||
public void testNewFileSystem() throws Exception {
|
public void testNewFileSystem() throws Exception {
|
||||||
Map<String,String> env = new HashMap<>();
|
Map<String,String> env = new HashMap<>();
|
||||||
@ -145,7 +147,7 @@ public class MultiReleaseJarTest {
|
|||||||
try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
|
try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
|
||||||
Assert.assertTrue(readAndCompare(fs, 8));
|
Assert.assertTrue(readAndCompare(fs, 8));
|
||||||
}
|
}
|
||||||
env.put("releaseVersion", "runtime");
|
env.put(PROPERTY_RELEASE_VERSION, "runtime");
|
||||||
// a configuration and jar file is multi-release
|
// a configuration and jar file is multi-release
|
||||||
try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
|
try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
|
||||||
Assert.assertTrue(readAndCompare(fs, MAJOR_VERSION));
|
Assert.assertTrue(readAndCompare(fs, MAJOR_VERSION));
|
||||||
@ -163,28 +165,38 @@ public class MultiReleaseJarTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test(dataProvider="strings")
|
@Test(dataProvider="strings")
|
||||||
public void testStrings(String value, int expected) throws Throwable {
|
public void testStrings(String value, int expected, String ignorable) throws Throwable {
|
||||||
stringEnv.put("releaseVersion", value);
|
stringEnv.clear();
|
||||||
|
stringEnv.put(PROPERTY_RELEASE_VERSION, value);
|
||||||
|
// we check, that values for "multi-release" are ignored
|
||||||
|
stringEnv.put(PROPERTY_MULTI_RELEASE, ignorable);
|
||||||
runTest(stringEnv, expected);
|
runTest(stringEnv, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dataProvider="integers")
|
@Test(dataProvider="integers")
|
||||||
public void testIntegers(Integer value, int expected) throws Throwable {
|
public void testIntegers(Integer value, int expected, Integer ignorable) throws Throwable {
|
||||||
integerEnv.put("releaseVersion", value);
|
integerEnv.clear();
|
||||||
|
integerEnv.put(PROPERTY_RELEASE_VERSION, value);
|
||||||
|
// we check, that values for "multi-release" are ignored
|
||||||
|
integerEnv.put(PROPERTY_MULTI_RELEASE, value);
|
||||||
runTest(integerEnv, expected);
|
runTest(integerEnv, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dataProvider="versions")
|
@Test(dataProvider="versions")
|
||||||
public void testVersions(Version value, int expected) throws Throwable {
|
public void testVersions(Version value, int expected, Version ignorable) throws Throwable {
|
||||||
versionEnv.put("releaseVersion", value);
|
versionEnv.clear();
|
||||||
|
versionEnv.put(PROPERTY_RELEASE_VERSION, value);
|
||||||
|
// we check, that values for "multi-release" are ignored
|
||||||
|
versionEnv.put(PROPERTY_MULTI_RELEASE, ignorable);
|
||||||
runTest(versionEnv, expected);
|
runTest(versionEnv, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testShortJar() throws Throwable {
|
public void testShortJar() throws Throwable {
|
||||||
integerEnv.put("releaseVersion", Integer.valueOf(MAJOR_VERSION));
|
integerEnv.clear();
|
||||||
|
integerEnv.put(PROPERTY_RELEASE_VERSION, Integer.valueOf(MAJOR_VERSION));
|
||||||
runTest(smruri, integerEnv, MAJOR_VERSION);
|
runTest(smruri, integerEnv, MAJOR_VERSION);
|
||||||
integerEnv.put("releaseVersion", Integer.valueOf(9));
|
integerEnv.put(PROPERTY_RELEASE_VERSION, Integer.valueOf(9));
|
||||||
runTest(smruri, integerEnv, 8);
|
runTest(smruri, integerEnv, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,23 +217,23 @@ public class MultiReleaseJarTest {
|
|||||||
// The following tests are for backwards compatibility to validate that
|
// The following tests are for backwards compatibility to validate that
|
||||||
// the original property still works
|
// the original property still works
|
||||||
@Test(dataProvider="strings")
|
@Test(dataProvider="strings")
|
||||||
public void testMRStrings(String value, int expected) throws Throwable {
|
public void testMRStrings(String value, int expected, String ignorable) throws Throwable {
|
||||||
stringEnv.clear();
|
stringEnv.clear();
|
||||||
stringEnv.put("multi-release", value);
|
stringEnv.put(PROPERTY_MULTI_RELEASE, value);
|
||||||
runTest(stringEnv, expected);
|
runTest(stringEnv, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dataProvider="integers")
|
@Test(dataProvider="integers")
|
||||||
public void testMRIntegers(Integer value, int expected) throws Throwable {
|
public void testMRIntegers(Integer value, int expected, Integer ignorable) throws Throwable {
|
||||||
integerEnv.clear();
|
integerEnv.clear();
|
||||||
integerEnv.put("multi-release", value);
|
integerEnv.put(PROPERTY_MULTI_RELEASE, value);
|
||||||
runTest(integerEnv, expected);
|
runTest(integerEnv, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dataProvider="versions")
|
@Test(dataProvider="versions")
|
||||||
public void testMRVersions(Version value, int expected) throws Throwable {
|
public void testMRVersions(Version value, int expected, Version ignorable) throws Throwable {
|
||||||
versionEnv.clear();
|
versionEnv.clear();
|
||||||
versionEnv.put("multi-release", value);
|
versionEnv.put(PROPERTY_MULTI_RELEASE, value);
|
||||||
runTest(versionEnv, expected);
|
runTest(versionEnv, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +276,7 @@ public class MultiReleaseJarTest {
|
|||||||
JarBuilder jb = new JarBuilder(jfname);
|
JarBuilder jb = new JarBuilder(jfname);
|
||||||
jb.addAttribute("Multi-Release", "true");
|
jb.addAttribute("Multi-Release", "true");
|
||||||
jb.build();
|
jb.build();
|
||||||
Map<String,String> env = Map.of("releaseVersion", "runtime");
|
Map<String,String> env = Map.of(PROPERTY_RELEASE_VERSION, "runtime");
|
||||||
try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
|
try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
|
||||||
Assert.assertTrue(true);
|
Assert.assertTrue(true);
|
||||||
}
|
}
|
||||||
@ -279,7 +291,7 @@ public class MultiReleaseJarTest {
|
|||||||
creator.buildCustomMultiReleaseJar(fileName, value, Map.of(),
|
creator.buildCustomMultiReleaseJar(fileName, value, Map.of(),
|
||||||
/*addEntries*/true);
|
/*addEntries*/true);
|
||||||
|
|
||||||
Map<String,String> env = Map.of("releaseVersion", "runtime");
|
Map<String,String> env = Map.of(PROPERTY_RELEASE_VERSION, "runtime");
|
||||||
Path filePath = Paths.get(userdir, fileName);
|
Path filePath = Paths.get(userdir, fileName);
|
||||||
String ssp = filePath.toUri().toString();
|
String ssp = filePath.toUri().toString();
|
||||||
URI customJar = new URI("jar", ssp , null);
|
URI customJar = new URI("jar", ssp , null);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user