8234089: (zipfs) Remove classes JarFileSystemProvider and JarFileSystem

Reviewed-by: lancea, alanb
This commit is contained in:
Christoph Langer 2019-11-22 09:25:09 +01:00
parent 3600213f1d
commit b240008ba2
7 changed files with 224 additions and 352 deletions

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -33,6 +33,7 @@ import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.Runtime.Version;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
@ -50,6 +51,10 @@ import java.security.PrivilegedExceptionAction;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
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.zip.CRC32;
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_GROUP = "defaultGroup";
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 =
PosixFilePermissions.fromString("rwxrwxrwx");
@ -112,6 +122,9 @@ class ZipFileSystem extends FileSystem {
private final int defaultCompressionMethod; // METHOD_STORED if "noCompression=true"
// METHOD_DEFLATED otherwise
// entryLookup is identity by default, will be overridden for multi-release jars
private Function<byte[], byte[]> entryLookup = Function.identity();
// POSIX support
final boolean supportPosix;
private final UserPrincipal defaultOwner;
@ -167,6 +180,8 @@ class ZipFileSystem extends FileSystem {
}
this.provider = provider;
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
// 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.
@ -1644,15 +1795,15 @@ class ZipFileSystem extends FileSystem {
hasUpdate = false; // clear
}
IndexNode getInode(byte[] path) {
return inodes.get(IndexNode.keyOf(Objects.requireNonNull(path, "path")));
private IndexNode getInode(byte[] path) {
return inodes.get(IndexNode.keyOf(Objects.requireNonNull(entryLookup.apply(path), "path")));
}
/**
* Return the IndexNode from the root tree. If it doesn't exist,
* 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);
// if node exists, return it
if (node != null) {
@ -2248,7 +2399,7 @@ class ZipFileSystem extends FileSystem {
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();
if (key == null) {
key = new IndexNode(name, -1);

View File

@ -52,12 +52,6 @@ import java.util.zip.ZipException;
* @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
*/
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<>();
public ZipFileSystemProvider() {}
@ -127,21 +121,14 @@ public class ZipFileSystemProvider extends FileSystemProvider {
}
private ZipFileSystem getZipFileSystem(Path path, Map<String, ?> env) throws IOException {
ZipFileSystem zipfs;
try {
if (env.containsKey(PROPERTY_RELEASE_VERSION) ||
env.containsKey(PROPERTY_MULTI_RELEASE)) {
zipfs = new JarFileSystem(this, path, env);
} else {
zipfs = new ZipFileSystem(this, path, env);
}
return new ZipFileSystem(this, path, env);
} catch (ZipException ze) {
String pname = path.toString();
if (pname.endsWith(".zip") || pname.endsWith(".jar"))
throw ze;
throw new UnsupportedOperationException();
}
return zipfs;
}
@Override

View File

@ -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.
*
* 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("");
/**
* 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 m2 = findModuleDirectory("m2");
Path mlib = m1.getParent();
@ -65,13 +65,13 @@ public class ModulesInCustomFileSystem {
// create JAR file containing m1/** and m2/**
Path jar = Files.createTempDirectory(HERE, "mlib").resolve("modules.jar");
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 m2 = findModuleDirectory("m2");
Path contents = Files.createTempDirectory(HERE, "contents");
@ -81,15 +81,14 @@ public class ModulesInCustomFileSystem {
// create JAR file containing m1.jar and m2.jar
Path jar = Files.createTempDirectory(HERE, "mlib").resolve("modules.jar");
JarUtils.createJarFile(jar, contents);
testJarFileSystem(jar);
testZipFileSystem(jar);
}
/**
* Opens a JAR file as a file system
*/
private void testJarFileSystem(Path jar) throws Exception {
ClassLoader scl = ClassLoader.getSystemClassLoader();
try (FileSystem fs = FileSystems.newFileSystem(jar, scl)) {
private void testZipFileSystem(Path zip) throws Exception {
try (FileSystem fs = FileSystems.newFileSystem(zip)) {
// ModuleFinder to find modules in top-level directory
Path top = fs.getPath("/");
ModuleFinder finder = ModuleFinder.of(top);

View File

@ -24,7 +24,7 @@
/*
* @test
* @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
* @modules jdk.jartool
* jdk.zipfs

View File

@ -50,6 +50,8 @@ import org.testng.annotations.*;
public class MultiReleaseJarTest {
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 CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
@ -88,56 +90,56 @@ public class MultiReleaseJarTest {
@DataProvider(name="strings")
public Object[][] createStrings() {
return new Object[][]{
{"runtime", MAJOR_VERSION},
{null, 8},
{"8", 8},
{"9", 9},
{Integer.toString(MAJOR_VERSION), MAJOR_VERSION},
{Integer.toString(MAJOR_VERSION+1), MAJOR_VERSION},
{"50", MAJOR_VERSION}
{"runtime", MAJOR_VERSION, "8"},
{null, 8, Integer.toString(MAJOR_VERSION)},
{"8", 8, "9"},
{"9", 9, null},
{Integer.toString(MAJOR_VERSION), MAJOR_VERSION, "8"},
{Integer.toString(MAJOR_VERSION+1), MAJOR_VERSION, "8"},
{"50", MAJOR_VERSION, "9"}
};
}
@DataProvider(name="integers")
public Object[][] createIntegers() {
return new Object[][] {
{null, 8},
{Integer.valueOf(8), 8},
{Integer.valueOf(9), 9},
{Integer.valueOf(MAJOR_VERSION), MAJOR_VERSION},
{Integer.valueOf(MAJOR_VERSION + 1), MAJOR_VERSION},
{Integer.valueOf(100), MAJOR_VERSION}
{null, 8, Integer.valueOf(9)},
{Integer.valueOf(8), 8, Integer.valueOf(9)},
{Integer.valueOf(9), 9, Integer.valueOf(MAJOR_VERSION)},
{Integer.valueOf(MAJOR_VERSION), MAJOR_VERSION, Integer.valueOf(8)},
{Integer.valueOf(MAJOR_VERSION + 1), MAJOR_VERSION, null},
{Integer.valueOf(100), MAJOR_VERSION, Integer.valueOf(8)}
};
}
@DataProvider(name="versions")
public Object[][] createVersions() {
return new Object[][] {
{null, 8},
{Version.parse("8"), 8},
{Version.parse("9"), 9},
{Version.parse(Integer.toString(MAJOR_VERSION)), MAJOR_VERSION},
{Version.parse(Integer.toString(MAJOR_VERSION) + 1), MAJOR_VERSION},
{Version.parse("100"), MAJOR_VERSION}
{null, 8, Version.parse("14")},
{Version.parse("8"), 8, Version.parse("7")},
{Version.parse("9"), 9, null},
{Version.parse(Integer.toString(MAJOR_VERSION)), MAJOR_VERSION, Version.parse("8")},
{Version.parse(Integer.toString(MAJOR_VERSION) + 1), MAJOR_VERSION, Version.parse("9")},
{Version.parse("100"), MAJOR_VERSION, Version.parse("14")}
};
}
@DataProvider(name="invalidVersions")
public Object[][] invalidVersions() {
return new Object[][] {
{Map.of("releaseVersion", "")},
{Map.of("releaseVersion", "invalid")},
{Map.of("releaseVersion", "0")},
{Map.of("releaseVersion", "-1")},
{Map.of("releaseVersion", "11.0.1")},
{Map.of("releaseVersion", new ArrayList<Long>())},
{Map.of("releaseVersion", Integer.valueOf(0))},
{Map.of("releaseVersion", Integer.valueOf(-1))}
{Map.of(PROPERTY_RELEASE_VERSION, "")},
{Map.of(PROPERTY_RELEASE_VERSION, "invalid")},
{Map.of(PROPERTY_RELEASE_VERSION, "0")},
{Map.of(PROPERTY_RELEASE_VERSION, "-1")},
{Map.of(PROPERTY_RELEASE_VERSION, "11.0.1")},
{Map.of(PROPERTY_RELEASE_VERSION, new ArrayList<Long>())},
{Map.of(PROPERTY_RELEASE_VERSION, Integer.valueOf(0))},
{Map.of(PROPERTY_RELEASE_VERSION, Integer.valueOf(-1))}
};
}
// Not the best test but all I can do since ZipFileSystem and JarFileSystem
// are not public, so I can't use (fs instanceof ...)
// Not the best test but all I can do since ZipFileSystem
// is not public, so I can't use (fs instanceof ...)
@Test
public void testNewFileSystem() throws Exception {
Map<String,String> env = new HashMap<>();
@ -145,7 +147,7 @@ public class MultiReleaseJarTest {
try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
Assert.assertTrue(readAndCompare(fs, 8));
}
env.put("releaseVersion", "runtime");
env.put(PROPERTY_RELEASE_VERSION, "runtime");
// a configuration and jar file is multi-release
try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
Assert.assertTrue(readAndCompare(fs, MAJOR_VERSION));
@ -163,28 +165,38 @@ public class MultiReleaseJarTest {
}
@Test(dataProvider="strings")
public void testStrings(String value, int expected) throws Throwable {
stringEnv.put("releaseVersion", value);
public void testStrings(String value, int expected, String ignorable) throws Throwable {
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);
}
@Test(dataProvider="integers")
public void testIntegers(Integer value, int expected) throws Throwable {
integerEnv.put("releaseVersion", value);
public void testIntegers(Integer value, int expected, Integer ignorable) throws Throwable {
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);
}
@Test(dataProvider="versions")
public void testVersions(Version value, int expected) throws Throwable {
versionEnv.put("releaseVersion", value);
public void testVersions(Version value, int expected, Version ignorable) throws Throwable {
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);
}
@Test
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);
integerEnv.put("releaseVersion", Integer.valueOf(9));
integerEnv.put(PROPERTY_RELEASE_VERSION, Integer.valueOf(9));
runTest(smruri, integerEnv, 8);
}
@ -205,23 +217,23 @@ public class MultiReleaseJarTest {
// The following tests are for backwards compatibility to validate that
// the original property still works
@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.put("multi-release", value);
stringEnv.put(PROPERTY_MULTI_RELEASE, value);
runTest(stringEnv, expected);
}
@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.put("multi-release", value);
integerEnv.put(PROPERTY_MULTI_RELEASE, value);
runTest(integerEnv, expected);
}
@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.put("multi-release", value);
versionEnv.put(PROPERTY_MULTI_RELEASE, value);
runTest(versionEnv, expected);
}
@ -264,7 +276,7 @@ public class MultiReleaseJarTest {
JarBuilder jb = new JarBuilder(jfname);
jb.addAttribute("Multi-Release", "true");
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)) {
Assert.assertTrue(true);
}
@ -279,7 +291,7 @@ public class MultiReleaseJarTest {
creator.buildCustomMultiReleaseJar(fileName, value, Map.of(),
/*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);
String ssp = filePath.toUri().toString();
URI customJar = new URI("jar", ssp , null);