--- old/src/jdk.rmic/share/classes/sun/rmi/rmic/newrmic/Main.java 2017-10-31 15:19:09.000000000 -0400 +++ /dev/null 2017-10-31 15:19:09.000000000 -0400 @@ -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 batchTable = - Collections.synchronizedMap(new HashMap()); - - /** 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 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 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 javadocArgs = new ArrayList(); - - // 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 classNames = new HashSet(); - 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 files) { - List javacArgs = new ArrayList(); - - // 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 generators = new ArrayList(); - Class envClass = BatchEnvironment.class; - List classes = new ArrayList(); - - Batch() { } - - /** - * Returns the Main instance for this batch. - **/ - Main enclosingMain() { - return Main.this; - } - } -}