--- old/src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java 2018-06-12 14:49:26.000000000 -0700 +++ new/src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java 2018-06-12 14:49:26.000000000 -0700 @@ -54,6 +54,7 @@ * Define the structure and ordering of "bands" in a packed file. * @author John Rose */ +@SuppressWarnings({"removal"}) abstract class BandStructure { static final int MAX_EFFORT = 9; --- old/src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java 2018-06-12 14:49:28.000000000 -0700 +++ new/src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java 2018-06-12 14:49:27.000000000 -0700 @@ -56,9 +56,12 @@ /** Command line interface for Pack200. */ + +@SuppressWarnings({"removal"}) class Driver { - private static final ResourceBundle RESOURCE = - ResourceBundle.getBundle("com.sun.java.util.jar.pack.DriverResource"); + private static final ResourceBundle RESOURCE = + ResourceBundle.getBundle("com.sun.java.util.jar.pack.DriverResource"); + private static boolean suppressDeprecateMsg = false; public static void main(String[] ava) throws IOException { List av = new ArrayList<>(Arrays.asList(ava)); @@ -67,6 +70,7 @@ boolean doUnpack = false; boolean doRepack = false; boolean doZip = true; + suppressDeprecateMsg = av.remove("-XDsuppress-tool-removal-message"); String logFile = null; String verboseProp = Utils.DEBUG_VERBOSE; @@ -85,6 +89,10 @@ } } + if (!suppressDeprecateMsg) { + printDeprecateWarning(doPack, System.out); + } + // Collect engine properties here: Map engProps = new HashMap<>(); engProps.put(verboseProp, System.getProperty(verboseProp)); @@ -395,6 +403,12 @@ } private static + void printDeprecateWarning(boolean doPack, PrintStream out) { + String prog = doPack ? "pack200" : "unpack200"; + out.println(MessageFormat.format(RESOURCE.getString(DriverResource.DEPRECATED), prog)); + } + + private static void printUsage(boolean doPack, boolean full, PrintStream out) { String prog = doPack ? "pack200" : "unpack200"; String[] packUsage = (String[])RESOURCE.getObject(DriverResource.PACK_HELP); @@ -407,6 +421,11 @@ break; } } + // Print a warning at the end + // The full help page is long, the beginning warning could be out of sight + if (full && !suppressDeprecateMsg) { + printDeprecateWarning(doPack, out); + } } private static --- old/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java 2018-06-12 14:49:29.000000000 -0700 +++ new/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java 2018-06-12 14:49:29.000000000 -0700 @@ -42,6 +42,7 @@ public static final String MORE_INFO = "MORE_INFO"; public static final String DUPLICATE_OPTION = "DUPLICATE_OPTION"; public static final String BAD_SPEC = "BAD_SPEC"; + public static final String DEPRECATED = "DEPRECATED"; /* * The following are the output of 'pack200' and 'unpack200' commands. @@ -126,6 +127,7 @@ {MORE_INFO, "(For more information, run {0} --help .)"}, // parameter 0:command name {DUPLICATE_OPTION, "duplicate option: {0}"}, // parameter 0:option {BAD_SPEC, "bad spec for {0}: {1}"}, // parameter 0:option;parameter 1:specifier + {DEPRECATED, "\nWarning: The {0} tool is deprecated, and is planned for removal in a future JDK release.\n"} // parameter 0:command name }; protected Object[][] getContents() { --- old/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java 2018-06-12 14:49:30.000000000 -0700 +++ new/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java 2018-06-12 14:49:30.000000000 -0700 @@ -39,6 +39,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +@SuppressWarnings({"removal"}) class NativeUnpack { // Pointer to the native unpacker obj private long unpackerPtr; --- old/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java 2018-06-12 14:49:32.000000000 -0700 +++ new/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java 2018-06-12 14:49:31.000000000 -0700 @@ -55,7 +55,7 @@ * @author Kumar Srinivasan */ - +@SuppressWarnings({"removal"}) public class PackerImpl extends TLGlobals implements Pack200.Packer { /** --- old/src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java 2018-06-12 14:49:33.000000000 -0700 +++ new/src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java 2018-06-12 14:49:33.000000000 -0700 @@ -47,6 +47,7 @@ * Control block for publishing Pack200 options to the other classes. */ +@SuppressWarnings({"removal"}) final class PropMap implements SortedMap { private final TreeMap theMap = new TreeMap<>();; --- old/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java 2018-06-12 14:49:34.000000000 -0700 +++ new/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java 2018-06-12 14:49:34.000000000 -0700 @@ -53,6 +53,7 @@ */ +@SuppressWarnings({"removal"}) public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { public UnpackerImpl() {} --- old/src/java.base/share/classes/java/util/jar/Pack200.java 2018-06-12 14:49:36.000000000 -0700 +++ new/src/java.base/share/classes/java/util/jar/Pack200.java 2018-06-12 14:49:36.000000000 -0700 @@ -101,7 +101,9 @@ * @author John Rose * @author Kumar Srinivasan * @since 1.5 + * @deprecated This class has been deprecated */ +@Deprecated(since="11", forRemoval=true) public abstract class Pack200 { private Pack200() {} //prevent instantiation @@ -226,6 +228,7 @@ * * @since 1.5 */ + @Deprecated(since="11", forRemoval=true) public interface Packer { /** * This property is a numeral giving the estimated target size N @@ -585,6 +588,7 @@ * This version of the unpacker is compatible with all previous versions. * @since 1.5 */ + @Deprecated(since="11", forRemoval=true) public interface Unpacker { /** The string "keep", a possible value for certain properties. --- old/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java 2018-06-12 14:49:37.000000000 -0700 +++ new/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java 2018-06-12 14:49:37.000000000 -0700 @@ -26,15 +26,12 @@ package sun.tools.jar; import java.io.File; -import java.io.PrintStream; import java.io.PrintWriter; -import java.lang.module.ModuleFinder; import java.lang.module.ModuleDescriptor.Version; import java.nio.file.Path; import java.nio.file.Paths; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; - import jdk.internal.module.ModulePath; import jdk.internal.module.ModuleResolution; @@ -292,6 +289,10 @@ break; String name = args[count]; + if (name.equals("-XDsuppress-tool-removal-message")) { + jartool.suppressDeprecateMsg = true; + continue; + } Option option = getOption(name); String param = null; if (option.hasArg) { --- old/src/jdk.jartool/share/classes/sun/tools/jar/Main.java 2018-06-12 14:49:39.000000000 -0700 +++ new/src/jdk.jartool/share/classes/sun/tools/jar/Main.java 2018-06-12 14:49:38.000000000 -0700 @@ -31,33 +31,34 @@ import java.lang.module.InvalidModuleDescriptorException; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Exports; -import java.lang.module.ModuleDescriptor.Provides; import java.lang.module.ModuleDescriptor.Opens; -import java.lang.module.ModuleDescriptor.Requires; +import java.lang.module.ModuleDescriptor.Provides; import java.lang.module.ModuleDescriptor.Version; import java.lang.module.ModuleFinder; import java.lang.module.ModuleReader; import java.lang.module.ModuleReference; -import java.lang.module.ResolutionException; import java.lang.module.ResolvedModule; import java.net.URI; import java.nio.ByteBuffer; -import java.nio.file.Path; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.text.MessageFormat; import java.util.*; import java.util.function.Consumer; -import java.util.function.Supplier; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -import java.util.zip.*; -import java.util.jar.*; -import java.util.jar.Pack200.*; -import java.util.jar.Manifest; -import java.text.MessageFormat; - +import java.util.zip.CRC32; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; import jdk.internal.module.Checks; import jdk.internal.module.ModuleHashes; import jdk.internal.module.ModuleHashesBuilder; @@ -67,10 +68,10 @@ import jdk.internal.module.ModuleTarget; import jdk.internal.util.jar.JarIndex; -import static jdk.internal.util.jar.JarIndex.INDEX_NAME; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import static java.util.jar.JarFile.MANIFEST_NAME; import static java.util.stream.Collectors.joining; -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static jdk.internal.util.jar.JarIndex.INDEX_NAME; /** * This class implements a simple utility for creating files in the JAR @@ -151,6 +152,8 @@ */ boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag, dflag; + boolean suppressDeprecateMsg = false; + /* To support additional GNU Style informational options */ Consumer info; @@ -238,6 +241,7 @@ /** * Starts main program with the specified arguments. */ + @SuppressWarnings({"removal"}) public synchronized boolean run(String args[]) { ok = true; if (!parseArgs(args)) { @@ -315,11 +319,14 @@ create(new BufferedOutputStream(out, 4096), manifest); } if (nflag) { + if (!suppressDeprecateMsg) { + warn(formatMsg("warn.flag.is.deprecated", "-n")); + } File packFile = createTemporaryFile(tmpbase, ".pack"); try { - Packer packer = Pack200.newPacker(); + java.util.jar.Pack200.Packer packer = java.util.jar.Pack200.newPacker(); Map p = packer.properties(); - p.put(Packer.EFFORT, "1"); // Minimal effort to conserve CPU + p.put(java.util.jar.Pack200.Packer.EFFORT, "1"); // Minimal effort to conserve CPU try (JarFile jarFile = new JarFile(tmpFile.getCanonicalPath()); OutputStream pack = new FileOutputStream(packFile)) { @@ -332,7 +339,7 @@ try (OutputStream out = new FileOutputStream(tmpFile); JarOutputStream jos = new JarOutputStream(out)) { - Unpacker unpacker = Pack200.newUnpacker(); + java.util.jar.Pack200.Unpacker unpacker = java.util.jar.Pack200.newUnpacker(); unpacker.unpack(packFile, jos); } } finally { --- old/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties 2018-06-12 14:49:40.000000000 -0700 +++ new/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties 2018-06-12 14:49:40.000000000 -0700 @@ -131,6 +131,8 @@ in incompatible public interfaces warn.release.unexpected.versioned.entry=\ unexpected versioned entry {0} +warn.flag.is.deprecated=\ + Warning: The {0} option is deprecated, and is planned for removal in a future JDK release\n out.added.manifest=\ added manifest out.added.module-info=\ @@ -170,7 +172,8 @@ \ \ -v generate verbose output on standard output\n\ \ \ -f specify archive file name\n\ \ \ -m include manifest information from specified manifest file\n\ -\ \ -n perform Pack200 normalization after creating a new archive\n\ +\ \ -n perform Pack200 normalization after creating a new archive,\n\ +\ \ this option is deprecated, and is planned for removal in a future JDK release\n\ \ \ -e specify application entry point for stand-alone application \n\ \ \ bundled into an executable jar file\n\ \ \ -0 store only; use no ZIP compression\n\ @@ -250,7 +253,8 @@ \ Operation modifiers valid only in create mode:\n main.help.opt.create.normalize=\ \ -n, --normalize Normalize information in the new jar archive\n\ -\ after creation +\ after creation. This option is deprecated, and is\n\ +\ planned for removal in a future JDK release main.help.opt.create.update=\ \ Operation modifiers valid only in create and update mode:\n main.help.opt.create.update.main-class=\ --- old/src/jdk.pack/share/classes/module-info.java 2018-06-12 14:49:42.000000000 -0700 +++ new/src/jdk.pack/share/classes/module-info.java 2018-06-12 14:49:41.000000000 -0700 @@ -38,5 +38,6 @@ * @moduleGraph * @since 9 */ +@Deprecated(since="11", forRemoval=true) module jdk.pack { } --- old/src/jdk.pack/share/native/common-unpack/defines.h 2018-06-12 14:49:43.000000000 -0700 +++ new/src/jdk.pack/share/native/common-unpack/defines.h 2018-06-12 14:49:43.000000000 -0700 @@ -118,6 +118,7 @@ #define tempname _tempname #define sleep Sleep #define snprintf _snprintf +#define PATH_SEPARATOR '\\' #else typedef signed char byte; #ifdef _LP64 @@ -128,6 +129,7 @@ typedef long long unsigned julong; #endif #define MKDIR(dir) mkdir(dir, 0777); +#define PATH_SEPARATOR '/' #endif #ifdef OLDCC --- old/src/jdk.pack/share/native/unpack200/main.cpp 2018-06-12 14:49:44.000000000 -0700 +++ new/src/jdk.pack/share/native/unpack200/main.cpp 2018-06-12 14:49:44.000000000 -0700 @@ -139,7 +139,7 @@ } static const char* nbasename(const char* progname) { - const char* slash = strrchr(progname, '/'); + const char* slash = strrchr(progname, PATH_SEPARATOR); if (slash != null) progname = ++slash; return progname; } @@ -161,6 +161,13 @@ "Exit Status:\n" \ " 0 if successful, >0 if an error occurred\n" +#define DEPRECATE_WARNING \ + "\nWarning: The %s tool is deprecated, and is planned for removal in a future JDK release.\n\n" + +#define SUPPRESS_DEPRECATE_MSG "-XDsuppress-tool-removal-message" + +static bool suppress_warning = false; + static void usage(unpacker* u, const char* progname, bool full = false) { // WinMain does not set argv[0] to the progrname progname = (progname != null) ? nbasename(progname) : "unpack200"; @@ -182,7 +189,11 @@ char* buf = (char*) strdup(env); const char* delim = "\n\t "; for (char* p = strtok(buf, delim); p != null; p = strtok(null, delim)) { - envargs.add(p); + if (!strcmp(p, SUPPRESS_DEPRECATE_MSG)) { + suppress_warning = true; + } else { + envargs.add(p); + } } } // allocate extra margin at both head and tail @@ -194,7 +205,11 @@ } for (i = 1; i < argc; i++) { // note: skip argv[0] (program name) - *argp++ = (char*) strdup(argv[i]); // make a scratch copy + if (!strcmp(argv[i], SUPPRESS_DEPRECATE_MSG)) { + suppress_warning = true; + } else { + *argp++ = (char*) strdup(argv[i]); // make a scratch copy + } } *argp = null; // sentinel envargc = envargs.length(); // report this count to next_arg @@ -293,6 +308,10 @@ int verbose = 0; char* logfile = null; + if (!suppress_warning) { + fprintf(u.errstrm, DEPRECATE_WARNING, nbasename(argv[0])); + } + for (;;) { const char* arg = (*argp == null)? "": u.saveStr(*argp); bool isenvarg = (argp < arg0); --- old/test/jdk/tools/pack200/Utils.java 2018-06-12 14:49:46.000000000 -0700 +++ new/test/jdk/tools/pack200/Utils.java 2018-06-12 14:49:45.000000000 -0700 @@ -497,6 +497,10 @@ } static List runExec(List cmdsList, Map penv) { + return runExec(cmdsList, penv, false); + } + + static List runExec(List cmdsList, Map penv, boolean ignoreReturnValue) { ArrayList alist = new ArrayList(); ProcessBuilder pb = new ProcessBuilder(cmdsList); @@ -529,7 +533,7 @@ in = rd.readLine(); } retval = p.waitFor(); - if (retval != 0) { + if (!ignoreReturnValue && retval != 0) { throw new RuntimeException("process failed with non-zero exit"); } } catch (Exception ex) { --- /dev/null 2018-06-12 14:49:47.000000000 -0700 +++ new/test/jdk/tools/jar/DeprecateOptionN.java 2018-06-12 14:49:47.000000000 -0700 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 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. + * + * 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 8199871 + * @modules jdk.jartool + * @summary jar -n should print out deprecation warning + * @run testng DeprecateOptionN + */ + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.spi.ToolProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +public class DeprecateOptionN { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + + protected static String jar(String... options) { + StringWriter writer = new StringWriter(); + PrintWriter pw = new PrintWriter(writer); + + JAR_TOOL.run(pw, pw, options); + String output = writer.toString(); + System.err.println(output); + return output; + } + + @Test + public void helpCompatWithWarning() { + String output = jar("--help:compat"); + assertTrue(output.contains("this option is deprecated, and is planned for removal in a future JDK release")); + } + + @Test + public void helpExtraWithWarning() { + String output = jar("--help-extra"); + assertTrue(output.contains("This option is deprecated, and is")); + assertTrue(output.contains("planned for removal in a future JDK release")); + } + + @Test + public void normalizeWithWarning() throws IOException { + File tmp = File.createTempFile("test", null); + String output = jar("cnf", "test.jar", tmp.getAbsolutePath()); + tmp.delete(); + assertTrue(output.contains("Warning: The -n option is deprecated, and is planned for removal in a future JDK release")); + } + + @Test + public void NoWarningWithoutN() throws IOException { + File tmp = File.createTempFile("test", null); + String output = jar("cf", "test.jar", tmp.getAbsolutePath()); + tmp.delete(); + assertFalse(output.contains("Warning: The -n option is deprecated, and is planned for removal in a future JDK release")); + } + + + @Test + public void SuppressWarning() throws IOException { + File tmp = File.createTempFile("test", null); + String output = jar("-c", "-n", "-XDsuppress-tool-removal-message", + "-f", "test.jar", tmp.getAbsolutePath()); + tmp.delete(); + assertFalse(output.contains("Warning: The -n option is deprecated, and is planned for removal in a future JDK release")); + } +} --- /dev/null 2018-06-12 14:49:49.000000000 -0700 +++ new/test/jdk/tools/pack200/DeprecatePack200.java 2018-06-12 14:49:48.000000000 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 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. + * + * 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 8199871 + * @summary pack200 and unpack200 should print out deprecate warning + * @modules jdk.pack + * @compile -XDignore.symbol.file Utils.java + * @run testng DeprecatePack200 + */ + +import java.util.List; +import java.util.function.Predicate; +import java.util.regex.Pattern; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +public class DeprecatePack200 { + final static String PACK200_CMD = Utils.getPack200Cmd(); + final static String UNPACK200_CMD = Utils.getUnpack200Cmd(); + final static Predicate PACK200_MSG = Pattern.compile( + "Warning: The pack200(\\.exe)?? tool is deprecated, and is planned for removal in a future JDK release.") + .asMatchPredicate(); + final static Predicate UNPACK200_MSG = Pattern.compile( + "Warning: The unpack200(\\.exe)?? tool is deprecated, and is planned for removal in a future JDK release.") + .asMatchPredicate(); + + @DataProvider(name="tools") + public static final Object[][] provide() { return cases; } + + private static final Object[][] cases = { + { PACK200_MSG, 1, List.of(PACK200_CMD) }, + { PACK200_MSG, 1, List.of(PACK200_CMD, "-V") }, + { PACK200_MSG, 2, List.of(PACK200_CMD, "--help") }, + { PACK200_MSG, 0, List.of(PACK200_CMD, "-XDsuppress-tool-removal-message") }, + { PACK200_MSG, 0, List.of(PACK200_CMD, "--version", "-XDsuppress-tool-removal-message") }, + { PACK200_MSG, 0, List.of(PACK200_CMD, "-h", "-XDsuppress-tool-removal-message") }, + + { UNPACK200_MSG, 1, List.of(UNPACK200_CMD) }, + { UNPACK200_MSG, 1, List.of(UNPACK200_CMD, "-V") }, + { UNPACK200_MSG, 1, List.of(UNPACK200_CMD, "--help") }, + { UNPACK200_MSG, 0, List.of(UNPACK200_CMD, "-XDsuppress-tool-removal-message") }, + { UNPACK200_MSG, 0, List.of(UNPACK200_CMD, "--version", "-XDsuppress-tool-removal-message") }, + { UNPACK200_MSG, 0, List.of(UNPACK200_CMD, "-h", "-XDsuppress-tool-removal-message") } + }; + + @Test(dataProvider = "tools") + public void CheckWarnings(Predicate msg, long count, List cmd) { + List output = Utils.runExec(cmd, null, true); + assertEquals(output.stream().filter(msg).count(), count); + } +}