8165944: jar utility doesn't process more than one -C argument
Reviewed-by: psandoz
This commit is contained in:
parent
84bd07e175
commit
3d6de648b9
@ -103,6 +103,18 @@ class Main {
|
||||
basename = en.baseName;
|
||||
entryname = en.entryName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Entry)) return false;
|
||||
return this.file.equals(((Entry)o).file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return file.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
class EntryName {
|
||||
@ -124,10 +136,10 @@ class Main {
|
||||
if (name.startsWith("./")) {
|
||||
name = name.substring(2);
|
||||
}
|
||||
this.baseName = name;
|
||||
this.entryName = (version > BASE_VERSION)
|
||||
? VERSIONS_DIR + version + "/" + this.baseName
|
||||
: this.baseName;
|
||||
baseName = name;
|
||||
entryName = (version > BASE_VERSION)
|
||||
? VERSIONS_DIR + version + "/" + baseName
|
||||
: baseName;
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +149,7 @@ class Main {
|
||||
Map<String, Entry> entryMap = new HashMap<>();
|
||||
|
||||
// All entries need to be added/updated.
|
||||
Map<String, Entry> entries = new LinkedHashMap<>();
|
||||
Set<Entry> entries = new LinkedHashSet<>();
|
||||
|
||||
// All packages.
|
||||
Set<String> packages = new HashSet<>();
|
||||
@ -855,8 +867,7 @@ class Main {
|
||||
moduleInfoPaths.put(entryName, f.toPath());
|
||||
if (isUpdate)
|
||||
entryMap.put(entryName, entry);
|
||||
} else if (!entries.containsKey(entryName)) {
|
||||
entries.put(entryName, entry);
|
||||
} else if (entries.add(entry)) {
|
||||
jarEntries.add(entryName);
|
||||
if (entry.basename.endsWith(".class") && !entryName.startsWith(VERSIONS_DIR))
|
||||
packages.add(toPackageName(entry.basename));
|
||||
@ -864,8 +875,7 @@ class Main {
|
||||
entryMap.put(entryName, entry);
|
||||
}
|
||||
} else if (f.isDirectory()) {
|
||||
if (!entries.containsKey(entryName)) {
|
||||
entries.put(entryName, entry);
|
||||
if (entries.add(entry)) {
|
||||
if (isUpdate) {
|
||||
entryMap.put(entryName, entry);
|
||||
}
|
||||
@ -923,8 +933,7 @@ class Main {
|
||||
in.transferTo(zos);
|
||||
zos.closeEntry();
|
||||
}
|
||||
for (String entryname : entries.keySet()) {
|
||||
Entry entry = entries.get(entryname);
|
||||
for (Entry entry : entries) {
|
||||
addFile(zos, entry);
|
||||
}
|
||||
zos.close();
|
||||
@ -1049,7 +1058,7 @@ class Main {
|
||||
Entry ent = entryMap.get(name);
|
||||
addFile(zos, ent);
|
||||
entryMap.remove(name);
|
||||
entries.remove(name);
|
||||
entries.remove(ent);
|
||||
}
|
||||
|
||||
jarEntries.add(name);
|
||||
@ -1059,8 +1068,8 @@ class Main {
|
||||
}
|
||||
|
||||
// add the remaining new files
|
||||
for (String entryname : entries.keySet()) {
|
||||
addFile(zos, entries.get(entryname));
|
||||
for (Entry entry : entries) {
|
||||
addFile(zos, entry);
|
||||
}
|
||||
if (!foundManifest) {
|
||||
if (newManifest != null) {
|
||||
@ -1248,6 +1257,9 @@ class Main {
|
||||
* Adds a new file entry to the ZIP output stream.
|
||||
*/
|
||||
void addFile(ZipOutputStream zos, Entry entry) throws IOException {
|
||||
// skip the generation of directory entries for META-INF/versions/*/
|
||||
if (entry.basename.isEmpty()) return;
|
||||
|
||||
File file = entry.file;
|
||||
String name = entry.entryname;
|
||||
boolean isDir = entry.isDir;
|
||||
|
212
jdk/test/tools/jar/InputFilesTest.java
Normal file
212
jdk/test/tools/jar/InputFilesTest.java
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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).
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8165944
|
||||
* @summary test several jar tool input file scenarios with variations on -C
|
||||
* options with/without a --release option. Some input files are
|
||||
* duplicates that sometimes cause exceptions and other times do not,
|
||||
* demonstrating identical behavior to JDK 8 jar tool.
|
||||
* @library /lib/testlibrary
|
||||
* @modules jdk.jartool/sun.tools.jar
|
||||
* @build jdk.testlibrary.FileUtils
|
||||
* @run testng InputFilesTest
|
||||
*/
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
import jdk.testlibrary.FileUtils;
|
||||
|
||||
public class InputFilesTest {
|
||||
private final String nl = System.lineSeparator();
|
||||
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
private final PrintStream out = new PrintStream(baos);
|
||||
private Runnable onCompletion;
|
||||
|
||||
@BeforeMethod
|
||||
public void reset() {
|
||||
onCompletion = null;
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
public void run() {
|
||||
if (onCompletion != null) {
|
||||
onCompletion.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1() throws IOException {
|
||||
mkdir("test1 test2");
|
||||
touch("test1/testfile1 test2/testfile2");
|
||||
jar("cf test.jar -C test1 . -C test2 .");
|
||||
jar("tf test.jar");
|
||||
println();
|
||||
String output = "META-INF/" + nl +
|
||||
"META-INF/MANIFEST.MF" + nl +
|
||||
"testfile1" + nl +
|
||||
"testfile2" + nl;
|
||||
rm("test.jar test1 test2");
|
||||
Assert.assertEquals(baos.toByteArray(), output.getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() throws IOException {
|
||||
mkdir("test1 test2 test3 test4");
|
||||
touch("test1/testfile1 test2/testfile2 test3/testfile3 test4/testfile4");
|
||||
jar("cf test.jar -C test1 . -C test2 . --release 9 -C test3 . -C test4 .");
|
||||
jar("tf test.jar");
|
||||
println();
|
||||
String output = "META-INF/" + nl +
|
||||
"META-INF/MANIFEST.MF" + nl +
|
||||
"testfile1" + nl +
|
||||
"testfile2" + nl +
|
||||
"META-INF/versions/9/testfile3" + nl +
|
||||
"META-INF/versions/9/testfile4" + nl;
|
||||
rm("test.jar test1 test2 test3 test4");
|
||||
Assert.assertEquals(baos.toByteArray(), output.getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test3() throws IOException {
|
||||
touch("test");
|
||||
jar("cf test.jar test test");
|
||||
jar("tf test.jar");
|
||||
println();
|
||||
String output = "META-INF/" + nl +
|
||||
"META-INF/MANIFEST.MF" + nl +
|
||||
"test" + nl;
|
||||
rm("test.jar test");
|
||||
Assert.assertEquals(baos.toByteArray(), output.getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test4() throws IOException {
|
||||
mkdir("a");
|
||||
touch("a/test");
|
||||
jar("cf test.jar -C a test -C a test");
|
||||
jar("tf test.jar");
|
||||
println();
|
||||
String output = "META-INF/" + nl +
|
||||
"META-INF/MANIFEST.MF" + nl +
|
||||
"test" + nl;
|
||||
rm("test.jar a");
|
||||
Assert.assertEquals(baos.toByteArray(), output.getBytes());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = {ZipException.class})
|
||||
public void test5() throws IOException {
|
||||
mkdir("a");
|
||||
touch("test a/test");
|
||||
onCompletion = () -> rm("test a");
|
||||
jar("cf test.jar -C a test test");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = {ZipException.class})
|
||||
public void test6() throws IOException {
|
||||
mkdir("test1 test2");
|
||||
touch("test1/a test2/a");
|
||||
onCompletion = () -> rm("test1 test2");
|
||||
jar("cf test.jar --release 9 -C test1 a -C test2 a");
|
||||
}
|
||||
|
||||
private Stream<Path> mkpath(String... args) {
|
||||
return Arrays.stream(args).map(d -> Paths.get(".", d.split("/")));
|
||||
}
|
||||
|
||||
private void mkdir(String cmdline) {
|
||||
System.out.println("mkdir -p " + cmdline);
|
||||
mkpath(cmdline.split(" +")).forEach(p -> {
|
||||
try {
|
||||
Files.createDirectories(p);
|
||||
} catch (IOException x) {
|
||||
throw new UncheckedIOException(x);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void touch(String cmdline) {
|
||||
System.out.println("touch " + cmdline);
|
||||
mkpath(cmdline.split(" +")).forEach(p -> {
|
||||
try {
|
||||
Files.createFile(p);
|
||||
} catch (IOException x) {
|
||||
throw new UncheckedIOException(x);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void rm(String cmdline) {
|
||||
System.out.println("rm -rf " + cmdline);
|
||||
mkpath(cmdline.split(" +")).forEach(p -> {
|
||||
try {
|
||||
if (Files.isDirectory(p)) {
|
||||
FileUtils.deleteFileTreeWithRetry(p);
|
||||
} else {
|
||||
FileUtils.deleteFileIfExistsWithRetry(p);
|
||||
}
|
||||
} catch (IOException x) {
|
||||
throw new UncheckedIOException(x);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void jar(String cmdline) throws IOException {
|
||||
System.out.println("jar " + cmdline);
|
||||
baos.reset();
|
||||
|
||||
// the run method catches IOExceptions, we need to expose them
|
||||
ByteArrayOutputStream baes = new ByteArrayOutputStream();
|
||||
PrintStream err = new PrintStream(baes);
|
||||
PrintStream saveErr = System.err;
|
||||
System.setErr(err);
|
||||
boolean ok = new sun.tools.jar.Main(out, err, "jar").run(cmdline.split(" +"));
|
||||
System.setErr(saveErr);
|
||||
if (!ok) {
|
||||
String s = baes.toString();
|
||||
if (s.startsWith("java.util.zip.ZipException: duplicate entry: ")) {
|
||||
throw new ZipException(s);
|
||||
}
|
||||
throw new IOException(s);
|
||||
}
|
||||
}
|
||||
|
||||
private void println() throws IOException {
|
||||
System.out.println(new String(baos.toByteArray()));
|
||||
}
|
||||
}
|
@ -195,6 +195,8 @@ public class Basic {
|
||||
new String[] {"v10", "version", "Version.class"}
|
||||
);
|
||||
|
||||
compare(jarfile, names);
|
||||
|
||||
delete(jarfile);
|
||||
deleteDir(Paths.get(usr, "classes"));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user