8066272: pack200 must support Multi-Release Jars
Reviewed-by: jrose, sdrach
This commit is contained in:
parent
bd8942b7a1
commit
138d45b476
@ -272,22 +272,6 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
|
||||
// (Done collecting options from props.)
|
||||
|
||||
boolean isClassFile(String name) {
|
||||
if (!name.endsWith(".class")) return false;
|
||||
for (String prefix = name; ; ) {
|
||||
if (passFiles.contains(prefix)) return false;
|
||||
int chop = prefix.lastIndexOf('/');
|
||||
if (chop < 0) break;
|
||||
prefix = prefix.substring(0, chop);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean isMetaInfFile(String name) {
|
||||
return name.startsWith("/" + Utils.METAINF) ||
|
||||
name.startsWith(Utils.METAINF);
|
||||
}
|
||||
|
||||
// Get a new package, based on the old one.
|
||||
private void makeNextPackage() {
|
||||
pkg.reset();
|
||||
@ -332,6 +316,29 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
InFile(JarEntry je) {
|
||||
this(null, je);
|
||||
}
|
||||
boolean isClassFile() {
|
||||
if (!name.endsWith(".class")) {
|
||||
return false;
|
||||
}
|
||||
for (String prefix = name;;) {
|
||||
if (passFiles.contains(prefix)) {
|
||||
return false;
|
||||
}
|
||||
int chop = prefix.lastIndexOf('/');
|
||||
if (chop < 0) {
|
||||
break;
|
||||
}
|
||||
prefix = prefix.substring(0, chop);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
boolean isMetaInfFile() {
|
||||
return name.startsWith("/" + Utils.METAINF)
|
||||
|| name.startsWith(Utils.METAINF);
|
||||
}
|
||||
boolean mustProcess() {
|
||||
return !isMetaInfFile() && isClassFile();
|
||||
}
|
||||
long getInputLength() {
|
||||
long len = (je != null)? je.getSize(): f.length();
|
||||
assert(len >= 0) : this+".len="+len;
|
||||
@ -391,7 +398,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
Package.File file = null;
|
||||
// (5078608) : discount the resource files in META-INF
|
||||
// from segment computation.
|
||||
long inflen = (isMetaInfFile(name))
|
||||
long inflen = (inFile.isMetaInfFile())
|
||||
? 0L
|
||||
: inFile.getInputLength();
|
||||
|
||||
@ -406,7 +413,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
|
||||
assert(je.isDirectory() == name.endsWith("/"));
|
||||
|
||||
if (isClassFile(name)) {
|
||||
if (inFile.mustProcess()) {
|
||||
file = readClass(name, bits.getInputStream());
|
||||
}
|
||||
if (file == null) {
|
||||
@ -429,7 +436,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
for (InFile inFile : inFiles) {
|
||||
String name = inFile.name;
|
||||
// (5078608) : discount the resource files completely from segmenting
|
||||
long inflen = (isMetaInfFile(name))
|
||||
long inflen = (inFile.isMetaInfFile())
|
||||
? 0L
|
||||
: inFile.getInputLength() ;
|
||||
if ((segmentSize += inflen) > segmentLimit) {
|
||||
@ -447,7 +454,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
if (verbose > 1)
|
||||
Utils.log.fine("Reading " + name);
|
||||
Package.File file = null;
|
||||
if (isClassFile(name)) {
|
||||
if (inFile.mustProcess()) {
|
||||
file = readClass(name, strm);
|
||||
if (file == null) {
|
||||
strm.close();
|
||||
|
257
jdk/test/tools/pack200/MultiRelease.java
Normal file
257
jdk/test/tools/pack200/MultiRelease.java
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* 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).
|
||||
*
|
||||
r 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.
|
||||
*/
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8066272
|
||||
* @summary tests a simple multi-versioned jar file
|
||||
* @compile -XDignore.symbol.file Utils.java MultiRelease.java
|
||||
* @run main MultiRelease
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
public class MultiRelease {
|
||||
private static final File cwd = new File(".");
|
||||
private static int pass = 0;
|
||||
private static int fail = 0;
|
||||
// specify alternate name via arguments to verify
|
||||
// if permanent fix works
|
||||
|
||||
private static final String PropKey = "pack200.MultiRelease.META-INF";
|
||||
private static final String MetaInfName = System.getProperty(PropKey, "META-INF");
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
new MultiRelease().run();
|
||||
}
|
||||
|
||||
void run() throws Exception {
|
||||
List<TestCase> testCases = new ArrayList<>();
|
||||
testCases.add(new TestCase1());
|
||||
testCases.add(new TestCase2());
|
||||
for (TestCase tc : testCases) {
|
||||
tc.run();
|
||||
}
|
||||
if (fail > 0) {
|
||||
throw new Exception(fail + "/" + testCases.size() + " tests fails");
|
||||
} else {
|
||||
System.out.println("All tests(" + pass + ") passes");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* An abstract class to eliminate test boiler plating.
|
||||
*/
|
||||
static abstract class TestCase {
|
||||
final File tcwd;
|
||||
final File metaInfDir;
|
||||
final File versionsDir;
|
||||
final File manifestFile;
|
||||
|
||||
TestCase(String directory) throws IOException {
|
||||
System.out.println("initializing directories");
|
||||
tcwd = new File(cwd, directory);
|
||||
metaInfDir = mkdir(new File(tcwd, MetaInfName));
|
||||
versionsDir = mkdir(new File(metaInfDir, "versions"));
|
||||
manifestFile = new File(tcwd, "manifest.tmp");
|
||||
List<String> scratch = new ArrayList<>();
|
||||
scratch.add("Multi-Release: true");
|
||||
Utils.createFile(manifestFile, scratch);
|
||||
}
|
||||
|
||||
File mkdir(File f) throws IOException {
|
||||
if (f.exists() && f.isDirectory() && f.canRead() && f.canWrite()) {
|
||||
return f;
|
||||
}
|
||||
if (!f.mkdirs()) {
|
||||
throw new IOException("mkdirs failed: " + f.getAbsolutePath());
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
abstract void emitClassFiles() throws Exception;
|
||||
|
||||
void run() {
|
||||
try {
|
||||
emitClassFiles();
|
||||
// jar the file up
|
||||
File testFile = new File(tcwd, "test" + Utils.JAR_FILE_EXT);
|
||||
Utils.jar("cvfm",
|
||||
testFile.getAbsolutePath(),
|
||||
manifestFile.getAbsolutePath(),
|
||||
"-C",
|
||||
tcwd.getAbsolutePath(),
|
||||
".");
|
||||
File outFile = new File(tcwd, "test-repacked" + Utils.JAR_FILE_EXT);
|
||||
List<String> cmdsList = new ArrayList<>();
|
||||
|
||||
cmdsList.add(Utils.getPack200Cmd());
|
||||
cmdsList.add("-J-ea");
|
||||
cmdsList.add("-J-esa");
|
||||
cmdsList.add("-v");
|
||||
cmdsList.add("--repack");
|
||||
cmdsList.add(outFile.getAbsolutePath());
|
||||
cmdsList.add(testFile.getAbsolutePath());
|
||||
List<String> output = Utils.runExec(cmdsList);
|
||||
Utils.doCompareVerify(testFile.getAbsoluteFile(), outFile.getAbsoluteFile());
|
||||
pass++;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(System.err);
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class TestCase1 extends TestCase {
|
||||
private TestCase1(String directory) throws IOException {
|
||||
super(directory);
|
||||
}
|
||||
|
||||
public TestCase1() throws Exception {
|
||||
this("case1");
|
||||
}
|
||||
|
||||
@Override
|
||||
void emitClassFiles() throws Exception {
|
||||
emitClassFile("");
|
||||
emitClassFile("7");
|
||||
emitClassFile("8");
|
||||
emitClassFile("9");
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds different variants of types
|
||||
*/
|
||||
void emitClassFile(String version) throws IOException {
|
||||
final File outDir = mkdir(version.isEmpty()
|
||||
? tcwd
|
||||
: new File(versionsDir, version));
|
||||
|
||||
final File srcDir = mkdir(version.isEmpty()
|
||||
? new File(tcwd, "src")
|
||||
: new File(new File(versionsDir, version), "src"));
|
||||
|
||||
final String fname = "Foo";
|
||||
final File srcFile = new File(srcDir, fname + Utils.JAVA_FILE_EXT);
|
||||
List<String> scratch = new ArrayList<>();
|
||||
|
||||
scratch.add("package pkg;");
|
||||
switch (version) {
|
||||
case "7":
|
||||
scratch.add("public class Foo {");
|
||||
scratch.add("public static final class Bar {}");
|
||||
break;
|
||||
case "8":
|
||||
scratch.add("public abstract class Foo {");
|
||||
scratch.add("public final class Bar {}");
|
||||
break;
|
||||
case "9":
|
||||
scratch.add("public interface Foo {");
|
||||
scratch.add("public final class Bar {}");
|
||||
break;
|
||||
default:
|
||||
scratch.add("public class Foo {");
|
||||
scratch.add("public final class Bar {}");
|
||||
break;
|
||||
}
|
||||
scratch.add("}");
|
||||
|
||||
Utils.createFile(srcFile, scratch);
|
||||
Utils.compiler("-d",
|
||||
outDir.getAbsolutePath(),
|
||||
srcFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
static class TestCase2 extends TestCase {
|
||||
private TestCase2(String directory) throws IOException {
|
||||
super(directory);
|
||||
}
|
||||
|
||||
TestCase2() throws Exception {
|
||||
this("case2");
|
||||
}
|
||||
|
||||
@Override
|
||||
void emitClassFiles() throws Exception {
|
||||
emitClassFile("");
|
||||
emitClassFile("8");
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds different variants of types and tries to invoke an
|
||||
* interface or concrete method defined by them.
|
||||
*/
|
||||
void emitClassFile(String version) throws IOException {
|
||||
|
||||
final File outDir = mkdir(version.isEmpty()
|
||||
? tcwd
|
||||
: new File(versionsDir, version));
|
||||
|
||||
final File srcDir = mkdir(version.isEmpty()
|
||||
? new File(tcwd, "src")
|
||||
: new File(new File(versionsDir, version), "src"));
|
||||
|
||||
List<String> scratch = new ArrayList<>();
|
||||
final String fname1 = "Ab";
|
||||
final File srcFile1 = new File(srcDir, fname1 + Utils.JAVA_FILE_EXT);
|
||||
|
||||
final String fname2 = "AbNormal";
|
||||
final File srcFile2 = new File(srcDir, fname2 + Utils.JAVA_FILE_EXT);
|
||||
switch (version) {
|
||||
case "8":
|
||||
scratch.clear();
|
||||
scratch.add("import java.io.IOException;");
|
||||
scratch.add("public interface " + fname1 + "{");
|
||||
scratch.add(" public abstract void close() throws IOException ;");
|
||||
scratch.add("}");
|
||||
Utils.createFile(srcFile1, scratch);
|
||||
break;
|
||||
default:
|
||||
scratch.clear();
|
||||
scratch.add("import java.io.IOException;");
|
||||
scratch.add("public abstract class " + fname1 + "{");
|
||||
scratch.add(" public abstract void close() throws IOException ;");
|
||||
scratch.add("}");
|
||||
Utils.createFile(srcFile1, scratch);
|
||||
}
|
||||
|
||||
scratch.clear();
|
||||
scratch.add("import java.io.IOException;");
|
||||
scratch.add("public class " + fname2 + "{");
|
||||
scratch.add(" public void doSomething(Ab ab) throws IOException {");
|
||||
scratch.add(" ab.close();");
|
||||
scratch.add(" }");
|
||||
scratch.add("}");
|
||||
|
||||
Utils.createFile(srcFile2, scratch);
|
||||
Utils.compiler("-d",
|
||||
outDir.getAbsolutePath(),
|
||||
srcFile1.getAbsolutePath(),
|
||||
srcFile2.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user