--- a/src/jdk.rmic/share/classes/sun/rmi/rmic/newrmic/Main.java Fri Nov 03 09:56:02 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,689 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, 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 sun.rmi.rmic.newrmic;
-
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.RootDoc;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import sun.rmi.rmic.newrmic.jrmp.JrmpGenerator;
-import sun.tools.util.CommandLine;
-
-/**
- * The rmic front end. This class contains the "main" method for rmic
- * command line invocation.
- *
- * A Main instance contains the stream to output error messages and
- * other diagnostics to.
- *
- * An rmic compilation batch (for example, one rmic command line
- * invocation) is executed by invoking the "compile" method of a Main
- * instance.
- *
- * WARNING: The contents of this source file are not part of any
- * supported API. Code that depends on them does so at its own risk:
- * they are subject to change or removal without notice.
- *
- * NOTE: If and when there is a J2SE API for invoking SDK tools, this
- * class should be updated to support that API.
- *
- * NOTE: This class is the front end for a "new" rmic implementation,
- * which uses javadoc and the doclet API for reading class files and
- * javac for compiling generated source files. This implementation is
- * incomplete: it lacks any CORBA-based back end implementations, and
- * thus the command line options "-idl", "-iiop", and their related
- * options are not yet supported. The front end for the "old",
- * oldjavac-based rmic implementation is sun.rmi.rmic.Main.
- *
- * @author Peter Jones
- **/
-public class Main {
-
- /*
- * Implementation note:
- *
- * In order to use the doclet API to read class files, much of
- * this implementation of rmic executes as a doclet within an
- * invocation of javadoc. This class is used as the doclet class
- * for such javadoc invocations, via its static "start" and
- * "optionLength" methods. There is one javadoc invocation per
- * rmic compilation batch.
- *
- * The only guaranteed way to pass data to a doclet through a
- * javadoc invocation is through doclet-specific options on the
- * javadoc "command line". Rather than passing numerous pieces of
- * individual data in string form as javadoc options, we use a
- * single doclet-specific option ("-batchID") to pass a numeric
- * identifier that uniquely identifies the rmic compilation batch
- * that the javadoc invocation is for, and that identifier can
- * then be used as a key in a global table to retrieve an object
- * containing all of batch-specific data (rmic command line
- * arguments, etc.).
- */
-
- /** guards "batchCount" */
- private static final Object batchCountLock = new Object();
-
- /** number of batches run; used to generated batch IDs */
- private static long batchCount = 0;
-
- /** maps batch ID to batch data */
- private static final Map<Long,Batch> batchTable =
- Collections.synchronizedMap(new HashMap<Long,Batch>());
-
- /** stream to output error messages and other diagnostics to */
- private final PrintStream out;
-
- /** name of this program, to use in error messages */
- private final String program;
-
- /**
- * Command line entry point.
- **/
- public static void main(String[] args) {
- Main rmic = new Main(System.err, "rmic");
- System.exit(rmic.compile(args) ? 0 : 1);
- }
-
- /**
- * Creates a Main instance that writes output to the specified
- * stream. The specified program name is used in error messages.
- **/
- public Main(OutputStream out, String program) {
- this.out = out instanceof PrintStream ?
- (PrintStream) out : new PrintStream(out);
- this.program = program;
- }
-
- /**
- * Compiles a batch of input classes, as given by the specified
- * command line arguments. Protocol-specific generators are
- * determined by the choice options on the command line. Returns
- * true if successful, or false if an error occurred.
- *
- * NOTE: This method is retained for transitional consistency with
- * previous implementations.
- **/
- public boolean compile(String[] args) {
- long startTime = System.currentTimeMillis();
-
- long batchID;
- synchronized (batchCountLock) {
- batchID = batchCount++; // assign batch ID
- }
-
- // process command line
- Batch batch = parseArgs(args);
- if (batch == null) {
- return false; // terminate if error occurred
- }
-
- /*
- * With the batch data retrievable in the global table, run
- * javadoc to continue the rest of the batch's compliation as
- * a doclet.
- */
- boolean status;
- try {
- batchTable.put(batchID, batch);
- status = invokeJavadoc(batch, batchID);
- } finally {
- batchTable.remove(batchID);
- }
-
- if (batch.verbose) {
- long deltaTime = System.currentTimeMillis() - startTime;
- output(Resources.getText("rmic.done_in",
- Long.toString(deltaTime)));
- }
-
- return status;
- }
-
- /**
- * Prints the specified string to the output stream of this Main
- * instance.
- **/
- public void output(String msg) {
- out.println(msg);
- }
-
- /**
- * Prints an error message to the output stream of this Main
- * instance. The first argument is used as a key in rmic's
- * resource bundle, and the rest of the arguments are used as
- * arguments in the formatting of the resource string.
- **/
- public void error(String msg, String... args) {
- output(Resources.getText(msg, args));
- }
-
- /**
- * Prints rmic's usage message to the output stream of this Main
- * instance.
- *
- * This method is public so that it can be used by the "parseArgs"
- * methods of Generator implementations.
- **/
- public void usage() {
- error("rmic.usage", program);
- }
-
- /**
- * Processes rmic command line arguments. Returns a Batch object
- * representing the command line arguments if successful, or null
- * if an error occurred. Processed elements of the args array are
- * set to null.
- **/
- private Batch parseArgs(String[] args) {
- Batch batch = new Batch();
-
- /*
- * Pre-process command line for @file arguments.
- */
- try {
- args = CommandLine.parse(args);
- } catch (FileNotFoundException e) {
- error("rmic.cant.read", e.getMessage());
- return null;
- } catch (IOException e) {
- e.printStackTrace(out);
- return null;
- }
-
- for (int i = 0; i < args.length; i++) {
-
- if (args[i] == null) {
- // already processed by a generator
- continue;
-
- } else if (args[i].equals("-Xnew")) {
- // we're already using the "new" implementation
- args[i] = null;
-
- } else if (args[i].equals("-show")) {
- // obselete: fail
- error("rmic.option.unsupported", args[i]);
- usage();
- return null;
-
- } else if (args[i].equals("-O")) {
- // obselete: warn but tolerate
- error("rmic.option.unsupported", args[i]);
- args[i] = null;
-
- } else if (args[i].equals("-debug")) {
- // obselete: warn but tolerate
- error("rmic.option.unsupported", args[i]);
- args[i] = null;
-
- } else if (args[i].equals("-depend")) {
- // obselete: warn but tolerate
- // REMIND: should this fail instead?
- error("rmic.option.unsupported", args[i]);
- args[i] = null;
-
- } else if (args[i].equals("-keep") ||
- args[i].equals("-keepgenerated"))
- {
- batch.keepGenerated = true;
- args[i] = null;
-
- } else if (args[i].equals("-g")) {
- batch.debug = true;
- args[i] = null;
-
- } else if (args[i].equals("-nowarn")) {
- batch.noWarn = true;
- args[i] = null;
-
- } else if (args[i].equals("-nowrite")) {
- batch.noWrite = true;
- args[i] = null;
-
- } else if (args[i].equals("-verbose")) {
- batch.verbose = true;
- args[i] = null;
-
- } else if (args[i].equals("-Xnocompile")) {
- batch.noCompile = true;
- batch.keepGenerated = true;
- args[i] = null;
-
- } else if (args[i].equals("-bootclasspath")) {
- if ((i + 1) >= args.length) {
- error("rmic.option.requires.argument", args[i]);
- usage();
- return null;
- }
- if (batch.bootClassPath != null) {
- error("rmic.option.already.seen", args[i]);
- usage();
- return null;
- }
- args[i] = null;
- batch.bootClassPath = args[++i];
- assert batch.bootClassPath != null;
- args[i] = null;
-
- } else if (args[i].equals("-extdirs")) {
- if ((i + 1) >= args.length) {
- error("rmic.option.requires.argument", args[i]);
- usage();
- return null;
- }
- if (batch.extDirs != null) {
- error("rmic.option.already.seen", args[i]);
- usage();
- return null;
- }
- args[i] = null;
- batch.extDirs = args[++i];
- assert batch.extDirs != null;
- args[i] = null;
-
- } else if (args[i].equals("-classpath")) {
- if ((i + 1) >= args.length) {
- error("rmic.option.requires.argument", args[i]);
- usage();
- return null;
- }
- if (batch.classPath != null) {
- error("rmic.option.already.seen", args[i]);
- usage();
- return null;
- }
- args[i] = null;
- batch.classPath = args[++i];
- assert batch.classPath != null;
- args[i] = null;
-
- } else if (args[i].equals("-d")) {
- if ((i + 1) >= args.length) {
- error("rmic.option.requires.argument", args[i]);
- usage();
- return null;
- }
- if (batch.destDir != null) {
- error("rmic.option.already.seen", args[i]);
- usage();
- return null;
- }
- args[i] = null;
- batch.destDir = new File(args[++i]);
- assert batch.destDir != null;
- args[i] = null;
- if (!batch.destDir.exists()) {
- error("rmic.no.such.directory", batch.destDir.getPath());
- usage();
- return null;
- }
-
- } else if (args[i].equals("-v1.1") ||
- args[i].equals("-vcompat") ||
- args[i].equals("-v1.2"))
- {
- Generator gen = new JrmpGenerator();
- batch.generators.add(gen);
- // JrmpGenerator only requires base BatchEnvironment class
- if (!gen.parseArgs(args, this)) {
- return null;
- }
-
- } else if (args[i].equalsIgnoreCase("-iiop")) {
- error("rmic.option.unimplemented", args[i]);
- return null;
-
- // Generator gen = new IiopGenerator();
- // batch.generators.add(gen);
- // if (!batch.envClass.isAssignableFrom(gen.envClass())) {
- // error("rmic.cannot.use.both",
- // batch.envClass.getName(), gen.envClass().getName());
- // return null;
- // }
- // batch.envClass = gen.envClass();
- // if (!gen.parseArgs(args, this)) {
- // return null;
- // }
-
- } else if (args[i].equalsIgnoreCase("-idl")) {
- error("rmic.option.unimplemented", args[i]);
- return null;
-
- // see implementation sketch above
-
- } else if (args[i].equalsIgnoreCase("-xprint")) {
- error("rmic.option.unimplemented", args[i]);
- return null;
-
- // see implementation sketch above
- }
- }
-
- /*
- * At this point, all that remains non-null in the args
- * array are input class names or illegal options.
- */
- for (int i = 0; i < args.length; i++) {
- if (args[i] != null) {
- if (args[i].startsWith("-")) {
- error("rmic.no.such.option", args[i]);
- usage();
- return null;
- } else {
- batch.classes.add(args[i]);
- }
- }
- }
- if (batch.classes.isEmpty()) {
- usage();
- return null;
- }
-
- /*
- * If options did not specify at least one protocol-specific
- * generator, then JRMP is the default.
- */
- if (batch.generators.isEmpty()) {
- batch.generators.add(new JrmpGenerator());
- }
- return batch;
- }
-
- /**
- * Doclet class entry point.
- **/
- public static boolean start(RootDoc rootDoc) {
-
- /*
- * Find batch ID among javadoc options, and retrieve
- * corresponding batch data from global table.
- */
- long batchID = -1;
- for (String[] option : rootDoc.options()) {
- if (option[0].equals("-batchID")) {
- try {
- batchID = Long.parseLong(option[1]);
- } catch (NumberFormatException e) {
- throw new AssertionError(e);
- }
- }
- }
- Batch batch = batchTable.get(batchID);
- assert batch != null;
-
- /*
- * Construct batch environment using class agreed upon by
- * generator implementations.
- */
- BatchEnvironment env;
- try {
- Constructor<? extends BatchEnvironment> cons =
- batch.envClass.getConstructor(new Class<?>[] { RootDoc.class });
- env = cons.newInstance(rootDoc);
- } catch (NoSuchMethodException e) {
- throw new AssertionError(e);
- } catch (IllegalAccessException e) {
- throw new AssertionError(e);
- } catch (InstantiationException e) {
- throw new AssertionError(e);
- } catch (InvocationTargetException e) {
- throw new AssertionError(e);
- }
-
- env.setVerbose(batch.verbose);
-
- /*
- * Determine the destination directory (the top of the package
- * hierarchy) for the output of this batch; if no destination
- * directory was specified on the command line, then the
- * default is the current working directory.
- */
- File destDir = batch.destDir;
- if (destDir == null) {
- destDir = new File(System.getProperty("user.dir"));
- }
-
- /*
- * Run each input class through each generator.
- */
- for (String inputClassName : batch.classes) {
- ClassDoc inputClass = rootDoc.classNamed(inputClassName);
- try {
- for (Generator gen : batch.generators) {
- gen.generate(env, inputClass, destDir);
- }
- } catch (NullPointerException e) {
- /*
- * We assume that this means that some class that was
- * needed (perhaps even a bootstrap class) was not
- * found, and that javadoc has already reported this
- * as an error. There is nothing for us to do here
- * but try to continue with the next input class.
- *
- * REMIND: More explicit error checking throughout
- * would be preferable, however.
- */
- }
- }
-
- /*
- * Compile any generated source files, if configured to do so.
- */
- boolean status = true;
- List<File> generatedFiles = env.generatedFiles();
- if (!batch.noCompile && !batch.noWrite && !generatedFiles.isEmpty()) {
- status = batch.enclosingMain().invokeJavac(batch, generatedFiles);
- }
-
- /*
- * Delete any generated source files, if configured to do so.
- */
- if (!batch.keepGenerated) {
- for (File file : generatedFiles) {
- file.delete();
- }
- }
-
- return status;
- }
-
- /**
- * Doclet class method that indicates that this doclet class
- * recognizes (only) the "-batchID" option on the javadoc command
- * line, and that the "-batchID" option comprises two arguments on
- * the javadoc command line.
- **/
- public static int optionLength(String option) {
- if (option.equals("-batchID")) {
- return 2;
- } else {
- return 0;
- }
- }
-
- /**
- * Runs the javadoc tool to invoke this class as a doclet, passing
- * command line options derived from the specified batch data and
- * indicating the specified batch ID.
- *
- * NOTE: This method currently uses a J2SE-internal API to run
- * javadoc. If and when there is a J2SE API for invoking SDK
- * tools, this method should be updated to use that API instead.
- **/
- private boolean invokeJavadoc(Batch batch, long batchID) {
- List<String> javadocArgs = new ArrayList<String>();
-
- // include all types, regardless of language-level access
- javadocArgs.add("-private");
-
- // inputs are class names, not source files
- javadocArgs.add("-Xclasses");
-
- // reproduce relevant options from rmic invocation
- if (batch.verbose) {
- javadocArgs.add("-verbose");
- }
- if (batch.bootClassPath != null) {
- javadocArgs.add("-bootclasspath");
- javadocArgs.add(batch.bootClassPath);
- }
- if (batch.extDirs != null) {
- javadocArgs.add("-extdirs");
- javadocArgs.add(batch.extDirs);
- }
- if (batch.classPath != null) {
- javadocArgs.add("-classpath");
- javadocArgs.add(batch.classPath);
- }
-
- // specify batch ID
- javadocArgs.add("-batchID");
- javadocArgs.add(Long.toString(batchID));
-
- /*
- * Run javadoc on union of rmic input classes and all
- * generators' bootstrap classes, so that they will all be
- * available to the doclet code.
- */
- Set<String> classNames = new HashSet<String>();
- for (Generator gen : batch.generators) {
- classNames.addAll(gen.bootstrapClassNames());
- }
- classNames.addAll(batch.classes);
- for (String s : classNames) {
- javadocArgs.add(s);
- }
-
- // run javadoc with our program name and output stream
- int status = com.sun.tools.javadoc.Main.execute(
- program,
- new PrintWriter(out, true),
- new PrintWriter(out, true),
- new PrintWriter(out, true),
- this.getClass().getName(), // doclet class is this class
- javadocArgs.toArray(new String[javadocArgs.size()]));
- return status == 0;
- }
-
- /**
- * Runs the javac tool to compile the specified source files,
- * passing command line options derived from the specified batch
- * data.
- *
- * NOTE: This method currently uses a J2SE-internal API to run
- * javac. If and when there is a J2SE API for invoking SDK tools,
- * this method should be updated to use that API instead.
- **/
- private boolean invokeJavac(Batch batch, List<File> files) {
- List<String> javacArgs = new ArrayList<String>();
-
- // rmic never wants to display javac warnings
- javacArgs.add("-nowarn");
-
- // reproduce relevant options from rmic invocation
- if (batch.debug) {
- javacArgs.add("-g");
- }
- if (batch.verbose) {
- javacArgs.add("-verbose");
- }
- if (batch.bootClassPath != null) {
- javacArgs.add("-bootclasspath");
- javacArgs.add(batch.bootClassPath);
- }
- if (batch.extDirs != null) {
- javacArgs.add("-extdirs");
- javacArgs.add(batch.extDirs);
- }
- if (batch.classPath != null) {
- javacArgs.add("-classpath");
- javacArgs.add(batch.classPath);
- }
-
- /*
- * For now, rmic still always produces class files that have a
- * class file format version compatible with JDK 1.1.
- */
- javacArgs.add("-source");
- javacArgs.add("1.3");
- javacArgs.add("-target");
- javacArgs.add("1.1");
-
- // add source files to compile
- for (File file : files) {
- javacArgs.add(file.getPath());
- }
-
- // run javac with our output stream
- int status = com.sun.tools.javac.Main.compile(
- javacArgs.toArray(new String[javacArgs.size()]),
- new PrintWriter(out, true));
- return status == 0;
- }
-
- /**
- * The data for an rmic compliation batch: the processed command
- * line arguments.
- **/
- private class Batch {
- boolean keepGenerated = false; // -keep or -keepgenerated
- boolean debug = false; // -g
- boolean noWarn = false; // -nowarn
- boolean noWrite = false; // -nowrite
- boolean verbose = false; // -verbose
- boolean noCompile = false; // -Xnocompile
- String bootClassPath = null; // -bootclasspath
- String extDirs = null; // -extdirs
- String classPath = null; // -classpath
- File destDir = null; // -d
- List<Generator> generators = new ArrayList<Generator>();
- Class<? extends BatchEnvironment> envClass = BatchEnvironment.class;
- List<String> classes = new ArrayList<String>();
-
- Batch() { }
-
- /**
- * Returns the Main instance for this batch.
- **/
- Main enclosingMain() {
- return Main.this;
- }
- }
-}