0N/A/*
2362N/A * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * Licensed Materials - Property of IBM
0N/A * RMI-IIOP v1.0
0N/A * Copyright IBM Corp. 1998 1999 All Rights Reserved
0N/A *
0N/A */
0N/A
0N/Apackage sun.rmi.rmic;
0N/A
0N/Aimport java.util.Vector;
0N/Aimport java.util.Enumeration;
0N/Aimport java.util.ResourceBundle;
0N/Aimport java.util.StringTokenizer;
0N/Aimport java.util.MissingResourceException;
0N/A
0N/Aimport java.io.OutputStream;
0N/Aimport java.io.PrintStream;
0N/Aimport java.io.IOException;
0N/Aimport java.io.File;
0N/Aimport java.io.FileNotFoundException;
0N/Aimport java.io.FileOutputStream;
0N/Aimport java.io.ByteArrayOutputStream;
0N/A
0N/Aimport sun.tools.java.ClassFile;
0N/Aimport sun.tools.java.ClassDefinition;
0N/Aimport sun.tools.java.ClassDeclaration;
0N/Aimport sun.tools.java.ClassNotFound;
0N/Aimport sun.tools.java.Identifier;
0N/Aimport sun.tools.java.ClassPath;
0N/A
0N/Aimport sun.tools.javac.SourceClass;
0N/Aimport sun.tools.util.CommandLine;
0N/Aimport java.lang.reflect.Constructor;
0N/Aimport java.util.Properties;
0N/A
0N/A/**
0N/A * Main "rmic" program.
0N/A *
0N/A * WARNING: The contents of this source file are not part of any
0N/A * supported API. Code that depends on them does so at its own risk:
0N/A * they are subject to change or removal without notice.
0N/A */
0N/Apublic class Main implements sun.rmi.rmic.Constants {
0N/A String sourcePathArg;
0N/A String sysClassPathArg;
0N/A String extDirsArg;
0N/A String classPathString;
0N/A File destDir;
0N/A int flags;
0N/A long tm;
5561N/A Vector<String> classes;
0N/A boolean nowrite;
0N/A boolean nocompile;
0N/A boolean keepGenerated;
0N/A boolean status;
0N/A String[] generatorArgs;
5561N/A Vector<Generator> generators;
5561N/A Class<? extends BatchEnvironment> environmentClass =
5561N/A BatchEnvironment.class;
0N/A boolean iiopGeneration = false;
0N/A
0N/A /**
0N/A * Name of the program.
0N/A */
0N/A String program;
0N/A
0N/A /**
0N/A * The stream where error message are printed.
0N/A */
0N/A OutputStream out;
0N/A
0N/A /**
0N/A * Constructor.
0N/A */
0N/A public Main(OutputStream out, String program) {
0N/A this.out = out;
0N/A this.program = program;
0N/A }
0N/A
0N/A /**
0N/A * Output a message.
0N/A */
0N/A public void output(String msg) {
0N/A PrintStream out =
0N/A this.out instanceof PrintStream ? (PrintStream)this.out
0N/A : new PrintStream(this.out, true);
0N/A out.println(msg);
0N/A }
0N/A
0N/A /**
0N/A * Top level error message. This method is called when the
0N/A * environment could not be set up yet.
0N/A */
0N/A public void error(String msg) {
0N/A output(getText(msg));
0N/A }
0N/A
0N/A public void error(String msg, String arg1) {
0N/A output(getText(msg, arg1));
0N/A }
0N/A
0N/A public void error(String msg, String arg1, String arg2) {
0N/A output(getText(msg, arg1, arg2));
0N/A }
0N/A
0N/A /**
0N/A * Usage
0N/A */
0N/A public void usage() {
0N/A error("rmic.usage", program);
0N/A }
0N/A
0N/A /**
0N/A * Run the compiler
0N/A */
0N/A public synchronized boolean compile(String argv[]) {
0N/A
0N/A /*
0N/A * Handle internal option to use the new (and incomplete) rmic
0N/A * implementation. This option is handled here, rather than
0N/A * in parseArgs, so that none of the arguments will be nulled
0N/A * before delegating to the new implementation.
0N/A */
0N/A for (int i = 0; i < argv.length; i++) {
0N/A if (argv[i].equals("-Xnew")) {
0N/A return (new sun.rmi.rmic.newrmic.Main(out,
0N/A program)).compile(argv);
0N/A }
0N/A }
0N/A
0N/A if (!parseArgs(argv)) {
0N/A return false;
0N/A }
0N/A
0N/A if (classes.size() == 0) {
0N/A usage();
0N/A return false;
0N/A }
0N/A
0N/A return doCompile();
0N/A }
0N/A
0N/A /**
0N/A * Get the destination directory.
0N/A */
0N/A public File getDestinationDir() {
0N/A return destDir;
0N/A }
0N/A
0N/A /**
0N/A * Parse the arguments for compile.
0N/A */
0N/A public boolean parseArgs(String argv[]) {
0N/A sourcePathArg = null;
0N/A sysClassPathArg = null;
0N/A extDirsArg = null;
0N/A
0N/A classPathString = null;
0N/A destDir = null;
0N/A flags = F_WARNINGS;
0N/A tm = System.currentTimeMillis();
5561N/A classes = new Vector<>();
0N/A nowrite = false;
0N/A nocompile = false;
0N/A keepGenerated = false;
0N/A generatorArgs = getArray("generator.args",true);
0N/A if (generatorArgs == null) {
0N/A return false;
0N/A }
5561N/A generators = new Vector<>();
0N/A
0N/A // Pre-process command line for @file arguments
0N/A try {
0N/A argv = CommandLine.parse(argv);
0N/A } catch (FileNotFoundException e) {
0N/A error("rmic.cant.read", e.getMessage());
0N/A return false;
0N/A } catch (IOException e) {
0N/A e.printStackTrace(out instanceof PrintStream ?
0N/A (PrintStream) out :
0N/A new PrintStream(out, true));
0N/A return false;
0N/A }
0N/A
0N/A // Parse arguments
0N/A for (int i = 0 ; i < argv.length ; i++) {
0N/A if (argv[i] != null) {
0N/A if (argv[i].equals("-g")) {
0N/A flags &= ~F_OPT;
0N/A flags |= F_DEBUG_LINES | F_DEBUG_VARS;
0N/A argv[i] = null;
0N/A } else if (argv[i].equals("-O")) {
0N/A flags &= ~F_DEBUG_LINES;
0N/A flags &= ~F_DEBUG_VARS;
0N/A flags |= F_OPT | F_DEPENDENCIES;
0N/A argv[i] = null;
0N/A } else if (argv[i].equals("-nowarn")) {
0N/A flags &= ~F_WARNINGS;
0N/A argv[i] = null;
0N/A } else if (argv[i].equals("-debug")) {
0N/A flags |= F_DUMP;
0N/A argv[i] = null;
0N/A } else if (argv[i].equals("-depend")) {
0N/A flags |= F_DEPENDENCIES;
0N/A argv[i] = null;
0N/A } else if (argv[i].equals("-verbose")) {
0N/A flags |= F_VERBOSE;
0N/A argv[i] = null;
0N/A } else if (argv[i].equals("-nowrite")) {
0N/A nowrite = true;
0N/A argv[i] = null;
0N/A } else if (argv[i].equals("-Xnocompile")) {
0N/A nocompile = true;
0N/A keepGenerated = true;
0N/A argv[i] = null;
0N/A } else if (argv[i].equals("-keep") ||
0N/A argv[i].equals("-keepgenerated")) {
0N/A keepGenerated = true;
0N/A argv[i] = null;
0N/A } else if (argv[i].equals("-show")) {
0N/A error("rmic.option.unsupported", "-show");
0N/A usage();
0N/A return false;
0N/A } else if (argv[i].equals("-classpath")) {
0N/A if ((i + 1) < argv.length) {
0N/A if (classPathString != null) {
0N/A error("rmic.option.already.seen", "-classpath");
0N/A usage();
0N/A return false;
0N/A }
0N/A argv[i] = null;
0N/A classPathString = argv[++i];
0N/A argv[i] = null;
0N/A } else {
0N/A error("rmic.option.requires.argument", "-classpath");
0N/A usage();
0N/A return false;
0N/A }
0N/A } else if (argv[i].equals("-sourcepath")) {
0N/A if ((i + 1) < argv.length) {
0N/A if (sourcePathArg != null) {
0N/A error("rmic.option.already.seen", "-sourcepath");
0N/A usage();
0N/A return false;
0N/A }
0N/A argv[i] = null;
0N/A sourcePathArg = argv[++i];
0N/A argv[i] = null;
0N/A } else {
0N/A error("rmic.option.requires.argument", "-sourcepath");
0N/A usage();
0N/A return false;
0N/A }
0N/A } else if (argv[i].equals("-bootclasspath")) {
0N/A if ((i + 1) < argv.length) {
0N/A if (sysClassPathArg != null) {
0N/A error("rmic.option.already.seen", "-bootclasspath");
0N/A usage();
0N/A return false;
0N/A }
0N/A argv[i] = null;
0N/A sysClassPathArg = argv[++i];
0N/A argv[i] = null;
0N/A } else {
0N/A error("rmic.option.requires.argument", "-bootclasspath");
0N/A usage();
0N/A return false;
0N/A }
0N/A } else if (argv[i].equals("-extdirs")) {
0N/A if ((i + 1) < argv.length) {
0N/A if (extDirsArg != null) {
0N/A error("rmic.option.already.seen", "-extdirs");
0N/A usage();
0N/A return false;
0N/A }
0N/A argv[i] = null;
0N/A extDirsArg = argv[++i];
0N/A argv[i] = null;
0N/A } else {
0N/A error("rmic.option.requires.argument", "-extdirs");
0N/A usage();
0N/A return false;
0N/A }
0N/A } else if (argv[i].equals("-d")) {
0N/A if ((i + 1) < argv.length) {
0N/A if (destDir != null) {
0N/A error("rmic.option.already.seen", "-d");
0N/A usage();
0N/A return false;
0N/A }
0N/A argv[i] = null;
0N/A destDir = new File(argv[++i]);
0N/A argv[i] = null;
0N/A if (!destDir.exists()) {
0N/A error("rmic.no.such.directory", destDir.getPath());
0N/A usage();
0N/A return false;
0N/A }
0N/A } else {
0N/A error("rmic.option.requires.argument", "-d");
0N/A usage();
0N/A return false;
0N/A }
0N/A } else {
0N/A if (!checkGeneratorArg(argv,i)) {
0N/A usage();
0N/A return false;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A
0N/A // Now that all generators have had a chance at the args,
0N/A // scan what's left for classes and illegal args...
0N/A
0N/A for (int i = 0; i < argv.length; i++) {
0N/A if (argv[i] != null) {
0N/A if (argv[i].startsWith("-")) {
0N/A error("rmic.no.such.option", argv[i]);
0N/A usage();
0N/A return false;
0N/A } else {
0N/A classes.addElement(argv[i]);
0N/A }
0N/A }
0N/A }
0N/A
0N/A
0N/A // If the generators vector is empty, add the default generator...
0N/A
0N/A if (generators.size() == 0) {
0N/A addGenerator("default");
0N/A }
0N/A
0N/A return true;
0N/A }
0N/A
0N/A /**
0N/A * If this argument is for a generator, instantiate it, call
0N/A * parseArgs(...) and add generator to generators vector.
0N/A * Returns false on error.
0N/A */
0N/A protected boolean checkGeneratorArg(String[] argv, int currentIndex) {
0N/A boolean result = true;
0N/A if (argv[currentIndex].startsWith("-")) {
0N/A String arg = argv[currentIndex].substring(1).toLowerCase(); // Remove '-'
0N/A for (int i = 0; i < generatorArgs.length; i++) {
0N/A if (arg.equalsIgnoreCase(generatorArgs[i])) {
0N/A // Got a match, add Generator and call parseArgs...
0N/A Generator gen = addGenerator(arg);
0N/A if (gen == null) {
0N/A return false;
0N/A }
0N/A result = gen.parseArgs(argv,this);
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A return result;
0N/A }
0N/A
0N/A /**
0N/A * Instantiate and add a generator to the generators array.
0N/A */
0N/A protected Generator addGenerator(String arg) {
0N/A
0N/A Generator gen;
0N/A
0N/A // Create an instance of the generator and add it to
0N/A // the array...
0N/A
0N/A String className = getString("generator.class." + arg);
0N/A if (className == null) {
0N/A error("rmic.missing.property",arg);
0N/A return null;
0N/A }
0N/A
0N/A try {
0N/A gen = (Generator) Class.forName(className).newInstance();
0N/A } catch (Exception e) {
0N/A error("rmic.cannot.instantiate",className);
0N/A return null;
0N/A }
0N/A
0N/A generators.addElement(gen);
0N/A
0N/A // Get the environment required by this generator...
0N/A
5561N/A Class<?> envClass = BatchEnvironment.class;
0N/A String env = getString("generator.env." + arg);
0N/A if (env != null) {
0N/A try {
0N/A envClass = Class.forName(env);
0N/A
0N/A // Is the new class a subclass of the current one?
0N/A
0N/A if (environmentClass.isAssignableFrom(envClass)) {
0N/A
0N/A // Yes, so switch to the new one...
0N/A
5561N/A environmentClass = envClass.asSubclass(BatchEnvironment.class);
0N/A
0N/A } else {
0N/A
0N/A // No. Is the current class a subclass of the
0N/A // new one?
0N/A
0N/A if (!envClass.isAssignableFrom(environmentClass)) {
0N/A
0N/A // No, so it's a conflict...
0N/A
0N/A error("rmic.cannot.use.both",environmentClass.getName(),envClass.getName());
0N/A return null;
0N/A }
0N/A }
0N/A } catch (ClassNotFoundException e) {
0N/A error("rmic.class.not.found",env);
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A // If this is the iiop stub generator, cache
0N/A // that fact for the jrmp generator...
0N/A
0N/A if (arg.equals("iiop")) {
0N/A iiopGeneration = true;
0N/A }
0N/A return gen;
0N/A }
0N/A
0N/A /**
0N/A * Grab a resource string and parse it into an array of strings. Assumes
0N/A * comma separated list.
0N/A * @param name The resource name.
0N/A * @param mustExist If true, throws error if resource does not exist. If
0N/A * false and resource does not exist, returns zero element array.
0N/A */
0N/A protected String[] getArray(String name, boolean mustExist) {
0N/A String[] result = null;
0N/A String value = getString(name);
0N/A if (value == null) {
0N/A if (mustExist) {
0N/A error("rmic.resource.not.found",name);
0N/A return null;
0N/A } else {
0N/A return new String[0];
0N/A }
0N/A }
0N/A
0N/A StringTokenizer parser = new StringTokenizer(value,", \t\n\r", false);
0N/A int count = parser.countTokens();
0N/A result = new String[count];
0N/A for (int i = 0; i < count; i++) {
0N/A result[i] = parser.nextToken();
0N/A }
0N/A
0N/A return result;
0N/A }
0N/A
0N/A /**
0N/A * Get the correct type of BatchEnvironment
0N/A */
0N/A public BatchEnvironment getEnv() {
0N/A
0N/A ClassPath classPath =
0N/A BatchEnvironment.createClassPath(classPathString,
0N/A sysClassPathArg,
0N/A extDirsArg);
0N/A BatchEnvironment result = null;
0N/A try {
0N/A Class[] ctorArgTypes = {OutputStream.class,ClassPath.class,Main.class};
0N/A Object[] ctorArgs = {out,classPath,this};
5561N/A Constructor<? extends BatchEnvironment> constructor =
5561N/A environmentClass.getConstructor(ctorArgTypes);
5561N/A result = constructor.newInstance(ctorArgs);
0N/A result.reset();
0N/A }
0N/A catch (Exception e) {
0N/A error("rmic.cannot.instantiate",environmentClass.getName());
0N/A }
0N/A return result;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Do the compile with the switches and files already supplied
0N/A */
0N/A public boolean doCompile() {
0N/A // Create batch environment
0N/A BatchEnvironment env = getEnv();
0N/A env.flags |= flags;
0N/A
0N/A // Set the classfile version numbers
0N/A // Compat and 1.1 stubs must retain the old version number.
0N/A env.majorVersion = 45;
0N/A env.minorVersion = 3;
0N/A
0N/A // Preload the "out of memory" error string just in case we run
0N/A // out of memory during the compile.
0N/A String noMemoryErrorString = getText("rmic.no.memory");
0N/A String stackOverflowErrorString = getText("rmic.stack.overflow");
0N/A
0N/A try {
0N/A /** Load the classes on the command line
0N/A * Replace the entries in classes with the ClassDefinition for the class
0N/A */
0N/A for (int i = classes.size()-1; i >= 0; i-- ) {
0N/A Identifier implClassName =
5561N/A Identifier.lookup(classes.elementAt(i));
0N/A
0N/A /*
0N/A * Fix bugid 4049354: support using '.' as an inner class
0N/A * qualifier on the command line (previously, only mangled
0N/A * inner class names were understood, like "pkg.Outer$Inner").
0N/A *
0N/A * The following method, also used by "javap", resolves the
0N/A * given unmangled inner class name to the appropriate
0N/A * internal identifier. For example, it translates
0N/A * "pkg.Outer.Inner" to "pkg.Outer. Inner".
0N/A */
0N/A implClassName = env.resolvePackageQualifiedName(implClassName);
0N/A /*
0N/A * But if we use such an internal inner class name identifier
0N/A * to load the class definition, the Java compiler will notice
0N/A * if the impl class is a "private" inner class and then deny
0N/A * skeletons (needed unless "-v1.2" is used) the ability to
0N/A * cast to it. To work around this problem, we mangle inner
0N/A * class name identifiers to their binary "outer" class name:
0N/A * "pkg.Outer. Inner" becomes "pkg.Outer$Inner".
0N/A */
0N/A implClassName = Names.mangleClass(implClassName);
0N/A
0N/A ClassDeclaration decl = env.getClassDeclaration(implClassName);
0N/A try {
0N/A ClassDefinition def = decl.getClassDefinition(env);
0N/A for (int j = 0; j < generators.size(); j++) {
5561N/A Generator gen = generators.elementAt(j);
0N/A gen.generate(env, def, destDir);
0N/A }
0N/A } catch (ClassNotFound ex) {
0N/A env.error(0, "rmic.class.not.found", implClassName);
0N/A }
0N/A
0N/A }
0N/A
0N/A // compile all classes that need compilation
0N/A if (!nocompile) {
0N/A compileAllClasses(env);
0N/A }
0N/A } catch (OutOfMemoryError ee) {
0N/A // The compiler has run out of memory. Use the error string
0N/A // which we preloaded.
0N/A env.output(noMemoryErrorString);
0N/A return false;
0N/A } catch (StackOverflowError ee) {
0N/A env.output(stackOverflowErrorString);
0N/A return false;
0N/A } catch (Error ee) {
0N/A // We allow the compiler to take an exception silently if a program
0N/A // error has previously been detected. Presumably, this makes the
0N/A // compiler more robust in the face of bad error recovery.
0N/A if (env.nerrors == 0 || env.dump()) {
0N/A env.error(0, "fatal.error");
0N/A ee.printStackTrace(out instanceof PrintStream ?
0N/A (PrintStream) out :
0N/A new PrintStream(out, true));
0N/A }
0N/A } catch (Exception ee) {
0N/A if (env.nerrors == 0 || env.dump()) {
0N/A env.error(0, "fatal.exception");
0N/A ee.printStackTrace(out instanceof PrintStream ?
0N/A (PrintStream) out :
0N/A new PrintStream(out, true));
0N/A }
0N/A }
0N/A
0N/A env.flushErrors();
0N/A
0N/A boolean status = true;
0N/A if (env.nerrors > 0) {
0N/A String msg = "";
0N/A if (env.nerrors > 1) {
0N/A msg = getText("rmic.errors", env.nerrors);
0N/A } else {
0N/A msg = getText("rmic.1error");
0N/A }
0N/A if (env.nwarnings > 0) {
0N/A if (env.nwarnings > 1) {
0N/A msg += ", " + getText("rmic.warnings", env.nwarnings);
0N/A } else {
0N/A msg += ", " + getText("rmic.1warning");
0N/A }
0N/A }
0N/A output(msg);
0N/A status = false;
0N/A } else {
0N/A if (env.nwarnings > 0) {
0N/A if (env.nwarnings > 1) {
0N/A output(getText("rmic.warnings", env.nwarnings));
0N/A } else {
0N/A output(getText("rmic.1warning"));
0N/A }
0N/A }
0N/A }
0N/A
0N/A // last step is to delete generated source files
0N/A if (!keepGenerated) {
0N/A env.deleteGeneratedFiles();
0N/A }
0N/A
0N/A // We're done
0N/A if (env.verbose()) {
0N/A tm = System.currentTimeMillis() - tm;
0N/A output(getText("rmic.done_in", Long.toString(tm)));
0N/A }
0N/A
0N/A // Shutdown the environment object and release our resources.
0N/A // Note that while this is unneccessary when rmic is invoked
0N/A // the command line, there are environments in which rmic
0N/A // from is invoked within a server process, so resource
0N/A // reclamation is important...
0N/A
0N/A env.shutdown();
0N/A
0N/A sourcePathArg = null;
0N/A sysClassPathArg = null;
0N/A extDirsArg = null;
0N/A classPathString = null;
0N/A destDir = null;
0N/A classes = null;
0N/A generatorArgs = null;
0N/A generators = null;
0N/A environmentClass = null;
0N/A program = null;
0N/A out = null;
0N/A
0N/A return status;
0N/A }
0N/A
0N/A /*
0N/A * Compile all classes that need to be compiled.
0N/A */
0N/A public void compileAllClasses (BatchEnvironment env)
0N/A throws ClassNotFound,
0N/A IOException,
0N/A InterruptedException {
0N/A ByteArrayOutputStream buf = new ByteArrayOutputStream(4096);
0N/A boolean done;
0N/A
0N/A do {
0N/A done = true;
5561N/A for (Enumeration<?> e = env.getClasses() ; e.hasMoreElements() ; ) {
0N/A ClassDeclaration c = (ClassDeclaration)e.nextElement();
0N/A done = compileClass(c,buf,env);
0N/A }
0N/A } while (!done);
0N/A }
0N/A
0N/A /*
0N/A * Compile a single class.
5561N/A * Fallthrough is intentional
0N/A */
5561N/A @SuppressWarnings("fallthrough")
0N/A public boolean compileClass (ClassDeclaration c,
0N/A ByteArrayOutputStream buf,
0N/A BatchEnvironment env)
0N/A throws ClassNotFound,
0N/A IOException,
0N/A InterruptedException {
0N/A boolean done = true;
0N/A env.flushErrors();
0N/A SourceClass src;
0N/A
0N/A switch (c.getStatus()) {
0N/A case CS_UNDEFINED:
0N/A {
0N/A if (!env.dependencies()) {
0N/A break;
0N/A }
0N/A // fall through
0N/A }
0N/A
0N/A case CS_SOURCE:
0N/A {
0N/A done = false;
0N/A env.loadDefinition(c);
0N/A if (c.getStatus() != CS_PARSED) {
0N/A break;
0N/A }
0N/A // fall through
0N/A }
0N/A
0N/A case CS_PARSED:
0N/A {
0N/A if (c.getClassDefinition().isInsideLocal()) {
0N/A break;
0N/A }
0N/A // If we get to here, then compilation is going
0N/A // to occur. If the -Xnocompile switch is set
0N/A // then fail. Note that this check is required
0N/A // here because this method is called from
0N/A // generators, not just from within this class...
0N/A
0N/A if (nocompile) {
0N/A throw new IOException("Compilation required, but -Xnocompile option in effect");
0N/A }
0N/A
0N/A done = false;
0N/A
0N/A src = (SourceClass)c.getClassDefinition(env);
0N/A src.check(env);
0N/A c.setDefinition(src, CS_CHECKED);
0N/A // fall through
0N/A }
0N/A
0N/A case CS_CHECKED:
0N/A {
0N/A src = (SourceClass)c.getClassDefinition(env);
0N/A // bail out if there were any errors
0N/A if (src.getError()) {
0N/A c.setDefinition(src, CS_COMPILED);
0N/A break;
0N/A }
0N/A done = false;
0N/A buf.reset();
0N/A src.compile(buf);
0N/A c.setDefinition(src, CS_COMPILED);
0N/A src.cleanup(env);
0N/A
0N/A if (src.getError() || nowrite) {
0N/A break;
0N/A }
0N/A
0N/A String pkgName = c.getName().getQualifier().toString().replace('.', File.separatorChar);
0N/A String className = c.getName().getFlatName().toString().replace('.', SIGC_INNERCLASS) + ".class";
0N/A
0N/A File file;
0N/A if (destDir != null) {
0N/A if (pkgName.length() > 0) {
0N/A file = new File(destDir, pkgName);
0N/A if (!file.exists()) {
0N/A file.mkdirs();
0N/A }
0N/A file = new File(file, className);
0N/A } else {
0N/A file = new File(destDir, className);
0N/A }
0N/A } else {
0N/A ClassFile classfile = (ClassFile)src.getSource();
0N/A if (classfile.isZipped()) {
0N/A env.error(0, "cant.write", classfile.getPath());
0N/A break;
0N/A }
0N/A file = new File(classfile.getPath());
0N/A file = new File(file.getParent(), className);
0N/A }
0N/A
0N/A // Create the file
0N/A try {
0N/A FileOutputStream out = new FileOutputStream(file.getPath());
0N/A buf.writeTo(out);
0N/A out.close();
0N/A if (env.verbose()) {
0N/A output(getText("rmic.wrote", file.getPath()));
0N/A }
0N/A } catch (IOException ee) {
0N/A env.error(0, "cant.write", file.getPath());
0N/A }
0N/A }
0N/A }
0N/A return done;
0N/A }
0N/A
0N/A /**
0N/A * Main program
0N/A */
0N/A public static void main(String argv[]) {
0N/A Main compiler = new Main(System.out, "rmic");
0N/A System.exit(compiler.compile(argv) ? 0 : 1);
0N/A }
0N/A
0N/A /**
0N/A * Return the string value of a named resource in the rmic.properties
0N/A * resource bundle. If the resource is not found, null is returned.
0N/A */
0N/A public static String getString(String key) {
0N/A if (!resourcesInitialized) {
0N/A initResources();
0N/A }
0N/A
0N/A // To enable extensions, search the 'resourcesExt'
0N/A // bundle first, followed by the 'resources' bundle...
0N/A
0N/A if (resourcesExt != null) {
0N/A try {
0N/A return resourcesExt.getString(key);
0N/A } catch (MissingResourceException e) {}
0N/A }
0N/A
0N/A try {
0N/A return resources.getString(key);
0N/A } catch (MissingResourceException ignore) {
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A private static boolean resourcesInitialized = false;
0N/A private static ResourceBundle resources;
0N/A private static ResourceBundle resourcesExt = null;
0N/A
0N/A private static void initResources() {
0N/A try {
0N/A resources =
0N/A ResourceBundle.getBundle("sun.rmi.rmic.resources.rmic");
0N/A resourcesInitialized = true;
0N/A try {
0N/A resourcesExt =
0N/A ResourceBundle.getBundle("sun.rmi.rmic.resources.rmicext");
0N/A } catch (MissingResourceException e) {}
0N/A } catch (MissingResourceException e) {
0N/A throw new Error("fatal: missing resource bundle: " +
0N/A e.getClassName());
0N/A }
0N/A }
0N/A
0N/A public static String getText(String key) {
0N/A String message = getString(key);
0N/A if (message == null) {
0N/A message = "no text found: \"" + key + "\"";
0N/A }
0N/A return message;
0N/A }
0N/A
0N/A public static String getText(String key, int num) {
0N/A return getText(key, Integer.toString(num), null, null);
0N/A }
0N/A
0N/A public static String getText(String key, String arg0) {
0N/A return getText(key, arg0, null, null);
0N/A }
0N/A
0N/A public static String getText(String key, String arg0, String arg1) {
0N/A return getText(key, arg0, arg1, null);
0N/A }
0N/A
0N/A public static String getText(String key,
0N/A String arg0, String arg1, String arg2)
0N/A {
0N/A String format = getString(key);
0N/A if (format == null) {
0N/A format = "no text found: key = \"" + key + "\", " +
0N/A "arguments = \"{0}\", \"{1}\", \"{2}\"";
0N/A }
0N/A
0N/A String[] args = new String[3];
0N/A args[0] = (arg0 != null ? arg0.toString() : "null");
0N/A args[1] = (arg1 != null ? arg1.toString() : "null");
0N/A args[2] = (arg2 != null ? arg2.toString() : "null");
0N/A
5561N/A return java.text.MessageFormat.format(format, (Object[]) args);
0N/A }
0N/A}