8339810: Clean up the code in sun.tools.jar.Main to properly close resources and use ZipFile during extract

Reviewed-by: yan, andrew
Backport-of: 8fce5275fc94ebc404a6a37f5ea0407140de63c1
This commit is contained in:
Martin Balao 2025-03-27 22:14:04 +00:00
parent b256b1a1ac
commit af6e57b719

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2024, 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
@ -150,7 +150,7 @@ class Main {
/** /**
* Starts main program with the specified arguments. * Starts main program with the specified arguments.
*/ */
public synchronized boolean run(String args[]) { public synchronized boolean run(String[] args) {
ok = true; ok = true;
if (!parseArgs(args)) { if (!parseArgs(args)) {
return false; return false;
@ -293,25 +293,19 @@ class Main {
if (fname != null) { if (fname != null) {
list(fname, files); list(fname, files);
} else { } else {
InputStream in = new FileInputStream(FileDescriptor.in); try (InputStream in = new FileInputStream(FileDescriptor.in);
try { BufferedInputStream bis = new BufferedInputStream(in)) {
list(new BufferedInputStream(in), files); list(bis, files);
} finally {
in.close();
} }
} }
} else if (xflag) { } else if (xflag) {
replaceFSC(files); replaceFSC(files);
if (fname != null && files != null) { if (fname != null) {
extract(fname, files); extract(fname, files);
} else { } else {
InputStream in = (fname == null) try (InputStream in = new FileInputStream(FileDescriptor.in);
? new FileInputStream(FileDescriptor.in) BufferedInputStream bis = new BufferedInputStream(in)) {
: new FileInputStream(fname); extract(bis, files);
try {
extract(new BufferedInputStream(in), files);
} finally {
in.close();
} }
} }
} else if (iflag) { } else if (iflag) {
@ -335,7 +329,7 @@ class Main {
/** /**
* Parses command line arguments. * Parses command line arguments.
*/ */
boolean parseArgs(String args[]) { boolean parseArgs(String[] args) {
/* Preprocess and expand @file arguments */ /* Preprocess and expand @file arguments */
try { try {
args = CommandLine.parse(args); args = CommandLine.parse(args);
@ -586,92 +580,90 @@ class Main {
InputStream newManifest, InputStream newManifest,
JarIndex jarIndex) throws IOException JarIndex jarIndex) throws IOException
{ {
ZipInputStream zis = new ZipInputStream(in);
ZipOutputStream zos = new JarOutputStream(out);
ZipEntry e = null;
boolean foundManifest = false;
boolean updateOk = true; boolean updateOk = true;
try (ZipInputStream zis = new ZipInputStream(in);
ZipOutputStream zos = new JarOutputStream(out)) {
if (jarIndex != null) { if (jarIndex != null) {
addIndex(jarIndex, zos); addIndex(jarIndex, zos);
} }
ZipEntry e = null;
boolean foundManifest = false;
// put the old entries first, replace if necessary // put the old entries first, replace if necessary
while ((e = zis.getNextEntry()) != null) { while ((e = zis.getNextEntry()) != null) {
String name = e.getName(); String name = e.getName();
boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME); boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME);
if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME)) if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME))
|| (Mflag && isManifestEntry)) { || (Mflag && isManifestEntry)) {
continue; continue;
} else if (isManifestEntry && ((newManifest != null) || } else if (isManifestEntry && ((newManifest != null) ||
(ename != null))) { (ename != null))) {
foundManifest = true; foundManifest = true;
if (newManifest != null) { if (newManifest != null) {
// Don't read from the newManifest InputStream, as we // Don't read from the newManifest InputStream, as we
// might need it below, and we can't re-read the same data // might need it below, and we can't re-read the same data
// twice. // twice.
FileInputStream fis = new FileInputStream(mname); try (FileInputStream fis = new FileInputStream(mname)) {
boolean ambiguous = isAmbiguousMainClass(new Manifest(fis)); if (isAmbiguousMainClass(new Manifest(fis))) {
fis.close(); return false;
if (ambiguous) { }
}
}
// Update the manifest.
Manifest old = new Manifest(zis);
if (newManifest != null) {
old.read(newManifest);
}
if (!updateManifest(old, zos)) {
return false; return false;
} }
} } else {
if (!entryMap.containsKey(name)) { // copy the old stuff
// Update the manifest. // do our own compression
Manifest old = new Manifest(zis); ZipEntry e2 = new ZipEntry(name);
if (newManifest != null) { e2.setMethod(e.getMethod());
old.read(newManifest); e2.setTime(e.getTime());
} e2.setComment(e.getComment());
if (!updateManifest(old, zos)) { e2.setExtra(e.getExtra());
return false; if (e.getMethod() == ZipEntry.STORED) {
} e2.setSize(e.getSize());
} else { e2.setCrc(e.getCrc());
if (!entryMap.containsKey(name)) { // copy the old stuff }
// do our own compression zos.putNextEntry(e2);
ZipEntry e2 = new ZipEntry(name); copy(zis, zos);
e2.setMethod(e.getMethod()); } else { // replace with the new files
e2.setTime(e.getTime()); File f = entryMap.get(name);
e2.setComment(e.getComment()); addFile(zos, f);
e2.setExtra(e.getExtra()); entryMap.remove(name);
if (e.getMethod() == ZipEntry.STORED) { entries.remove(f);
e2.setSize(e.getSize());
e2.setCrc(e.getCrc());
} }
zos.putNextEntry(e2);
copy(zis, zos);
} else { // replace with the new files
File f = entryMap.get(name);
addFile(zos, f);
entryMap.remove(name);
entries.remove(f);
} }
} }
}
// add the remaining new files // add the remaining new files
for (File f: entries) { for (File f : entries) {
addFile(zos, f); addFile(zos, f);
} }
if (!foundManifest) { if (!foundManifest) {
if (newManifest != null) { if (newManifest != null) {
Manifest m = new Manifest(newManifest); Manifest m = new Manifest(newManifest);
updateOk = !isAmbiguousMainClass(m); updateOk = !isAmbiguousMainClass(m);
if (updateOk) { if (updateOk) {
if (!updateManifest(m, zos)) { if (!updateManifest(m, zos)) {
updateOk = false;
}
}
} else if (ename != null) {
if (!updateManifest(new Manifest(), zos)) {
updateOk = false; updateOk = false;
} }
} }
} else if (ename != null) {
if (!updateManifest(new Manifest(), zos)) {
updateOk = false;
}
} }
} }
zis.close();
zos.close();
return updateOk; return updateOk;
} }
@ -978,11 +970,9 @@ class Main {
/** /**
* Extracts specified entries from JAR file. * Extracts specified entries from JAR file.
*/ */
void extract(InputStream in, String files[]) throws IOException { void extract(InputStream in, String[] files) throws IOException {
ZipInputStream zis = new ZipInputStream(in); ZipInputStream zis = new ZipInputStream(in);
ZipEntry e; ZipEntry e;
// Set of all directory entries specified in archive. Disallows
// null entries. Disallows all entries if using pre-6.0 behavior.
Set<ZipEntry> dirs = newDirSet(); Set<ZipEntry> dirs = newDirSet();
while ((e = zis.getNextEntry()) != null) { while ((e = zis.getNextEntry()) != null) {
if (files == null) { if (files == null) {
@ -1008,25 +998,26 @@ class Main {
/** /**
* Extracts specified entries from JAR file, via ZipFile. * Extracts specified entries from JAR file, via ZipFile.
*/ */
void extract(String fname, String files[]) throws IOException { void extract(String fname, String[] files) throws IOException {
ZipFile zf = new ZipFile(fname); final Set<ZipEntry> dirs;
Set<ZipEntry> dirs = newDirSet(); try (ZipFile zf = new ZipFile(fname)) {
Enumeration<? extends ZipEntry> zes = zf.entries(); dirs = newDirSet();
while (zes.hasMoreElements()) { Enumeration<? extends ZipEntry> zes = zf.entries();
ZipEntry e = zes.nextElement(); while (zes.hasMoreElements()) {
if (files == null) { ZipEntry e = zes.nextElement();
dirs.add(extractFile(zf.getInputStream(e), e)); if (files == null) {
} else { dirs.add(extractFile(zf.getInputStream(e), e));
String name = e.getName(); } else {
for (String file : files) { String name = e.getName();
if (name.startsWith(file)) { for (String file : files) {
dirs.add(extractFile(zf.getInputStream(e), e)); if (name.startsWith(file)) {
break; dirs.add(extractFile(zf.getInputStream(e), e));
break;
}
} }
} }
} }
} }
zf.close();
updateLastModifiedTime(dirs); updateLastModifiedTime(dirs);
} }
@ -1107,7 +1098,7 @@ class Main {
/** /**
* Lists contents of JAR file. * Lists contents of JAR file.
*/ */
void list(InputStream in, String files[]) throws IOException { void list(InputStream in, String[] files) throws IOException {
ZipInputStream zis = new ZipInputStream(in); ZipInputStream zis = new ZipInputStream(in);
ZipEntry e; ZipEntry e;
while ((e = zis.getNextEntry()) != null) { while ((e = zis.getNextEntry()) != null) {
@ -1125,13 +1116,13 @@ class Main {
/** /**
* Lists contents of JAR file, via ZipFile. * Lists contents of JAR file, via ZipFile.
*/ */
void list(String fname, String files[]) throws IOException { void list(String fname, String[] files) throws IOException {
ZipFile zf = new ZipFile(fname); try (ZipFile zf = new ZipFile(fname)) {
Enumeration<? extends ZipEntry> zes = zf.entries(); Enumeration<? extends ZipEntry> zes = zf.entries();
while (zes.hasMoreElements()) { while (zes.hasMoreElements()) {
printEntry(zes.nextElement(), files); printEntry(zes.nextElement(), files);
}
} }
zf.close();
} }
/** /**
@ -1174,10 +1165,8 @@ class Main {
// class path attribute will give us jar file name with // class path attribute will give us jar file name with
// '/' as separators, so we need to change them to the // '/' as separators, so we need to change them to the
// appropriate one before we open the jar file. // appropriate one before we open the jar file.
JarFile rf = new JarFile(jar.replace('/', File.separatorChar)); try (JarFile jarFile = new JarFile(jar.replace('/', File.separatorChar))) {
Manifest man = jarFile.getManifest();
if (rf != null) {
Manifest man = rf.getManifest();
if (man != null) { if (man != null) {
Attributes attr = man.getMainAttributes(); Attributes attr = man.getMainAttributes();
if (attr != null) { if (attr != null) {
@ -1198,7 +1187,6 @@ class Main {
} }
} }
} }
rf.close();
return files; return files;
} }
@ -1304,7 +1292,7 @@ class Main {
/** /**
* Main routine to start program. * Main routine to start program.
*/ */
public static void main(String args[]) { public static void main(String[] args) {
Main jartool = new Main(System.out, System.err, "jar"); Main jartool = new Main(System.out, System.err, "jar");
System.exit(jartool.run(args) ? 0 : 1); System.exit(jartool.run(args) ? 0 : 1);
} }