|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
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.). |
|
*/ |
|
|
|
|
|
private static final Object batchCountLock = new Object(); |
|
|
|
|
|
private static long batchCount = 0; |
|
|
|
|
|
private static final Map<Long,Batch> batchTable = |
|
Collections.synchronizedMap(new HashMap<Long,Batch>()); |
|
|
|
|
|
private final PrintStream out; |
|
|
|
|
|
private final String program; |
|
|
|
|
|
|
|
**/ |
|
public static void main(String[] args) { |
|
Main rmic = new Main(System.err, "rmic"); |
|
System.exit(rmic.compile(args) ? 0 : 1); |
|
} |
|
|
|
|
|
|
|
|
|
**/ |
|
public Main(OutputStream out, String program) { |
|
this.out = out instanceof PrintStream ? |
|
(PrintStream) out : new PrintStream(out); |
|
this.program = program; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
public boolean compile(String[] args) { |
|
long startTime = System.currentTimeMillis(); |
|
|
|
long batchID; |
|
synchronized (batchCountLock) { |
|
batchID = batchCount++; |
|
} |
|
|
|
|
|
Batch batch = parseArgs(args); |
|
if (batch == null) { |
|
return false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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; |
|
} |
|
|
|
|
|
|
|
|
|
**/ |
|
public void output(String msg) { |
|
out.println(msg); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
public void error(String msg, String... args) { |
|
output(Resources.getText(msg, args)); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
public void usage() { |
|
error("rmic.usage", program); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
private Batch parseArgs(String[] args) { |
|
Batch batch = new Batch(); |
|
|
|
|
|
|
|
*/ |
|
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) { |
|
|
|
continue; |
|
|
|
} else if (args[i].equals("-Xnew")) { |
|
|
|
args[i] = null; |
|
|
|
} else if (args[i].equals("-show")) { |
|
|
|
error("rmic.option.unsupported", args[i]); |
|
usage(); |
|
return null; |
|
|
|
} else if (args[i].equals("-O")) { |
|
|
|
error("rmic.option.unsupported", args[i]); |
|
args[i] = null; |
|
|
|
} else if (args[i].equals("-debug")) { |
|
|
|
error("rmic.option.unsupported", args[i]); |
|
args[i] = null; |
|
|
|
} else if (args[i].equals("-depend")) { |
|
// obselete: warn but tolerate |
|
|
|
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); |
|
|
|
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 |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
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 (batch.generators.isEmpty()) { |
|
batch.generators.add(new JrmpGenerator()); |
|
} |
|
return batch; |
|
} |
|
|
|
|
|
|
|
**/ |
|
public static boolean start(RootDoc rootDoc) { |
|
|
|
|
|
|
|
|
|
*/ |
|
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; |
|
|
|
|
|
|
|
|
|
*/ |
|
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); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
File destDir = batch.destDir; |
|
if (destDir == null) { |
|
destDir = new File(System.getProperty("user.dir")); |
|
} |
|
|
|
|
|
|
|
*/ |
|
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. |
|
*/ |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
boolean status = true; |
|
List<File> generatedFiles = env.generatedFiles(); |
|
if (!batch.noCompile && !batch.noWrite && !generatedFiles.isEmpty()) { |
|
status = batch.enclosingMain().invokeJavac(batch, generatedFiles); |
|
} |
|
|
|
|
|
|
|
*/ |
|
if (!batch.keepGenerated) { |
|
for (File file : generatedFiles) { |
|
file.delete(); |
|
} |
|
} |
|
|
|
return status; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
public static int optionLength(String option) { |
|
if (option.equals("-batchID")) { |
|
return 2; |
|
} else { |
|
return 0; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
private boolean invokeJavadoc(Batch batch, long batchID) { |
|
List<String> javadocArgs = new ArrayList<String>(); |
|
|
|
|
|
javadocArgs.add("-private"); |
|
|
|
|
|
javadocArgs.add("-Xclasses"); |
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
javadocArgs.add("-batchID"); |
|
javadocArgs.add(Long.toString(batchID)); |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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); |
|
} |
|
|
|
|
|
int status = com.sun.tools.javadoc.Main.execute( |
|
program, |
|
new PrintWriter(out, true), |
|
new PrintWriter(out, true), |
|
new PrintWriter(out, true), |
|
this.getClass().getName(), |
|
javadocArgs.toArray(new String[javadocArgs.size()])); |
|
return status == 0; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
private boolean invokeJavac(Batch batch, List<File> files) { |
|
List<String> javacArgs = new ArrayList<String>(); |
|
|
|
|
|
javacArgs.add("-nowarn"); |
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
javacArgs.add("-source"); |
|
javacArgs.add("1.3"); |
|
javacArgs.add("-target"); |
|
javacArgs.add("1.1"); |
|
|
|
|
|
for (File file : files) { |
|
javacArgs.add(file.getPath()); |
|
} |
|
|
|
|
|
int status = com.sun.tools.javac.Main.compile( |
|
javacArgs.toArray(new String[javacArgs.size()]), |
|
new PrintWriter(out, true)); |
|
return status == 0; |
|
} |
|
|
|
|
|
|
|
|
|
**/ |
|
private class Batch { |
|
boolean keepGenerated = false; |
|
boolean debug = false; |
|
boolean noWarn = false; |
|
boolean noWrite = false; |
|
boolean verbose = false; |
|
boolean noCompile = false; |
|
String bootClassPath = null; |
|
String extDirs = null; |
|
String classPath = null; |
|
File destDir = null; |
|
List<Generator> generators = new ArrayList<Generator>(); |
|
Class<? extends BatchEnvironment> envClass = BatchEnvironment.class; |
|
List<String> classes = new ArrayList<String>(); |
|
|
|
Batch() { } |
|
|
|
|
|
|
|
**/ |
|
Main enclosingMain() { |
|
return Main.this; |
|
} |
|
} |
|
} |