History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/rmi/rmic/Main.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/rmi/rmic/Main.java+884−0
@@ -0,0 +1,884 @@
1+/*
2+ * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+/*
27+ * Licensed Materials - Property of IBM
28+ * RMI-IIOP v1.0
29+ * Copyright IBM Corp. 1998 1999 All Rights Reserved
30+ *
31+ */
32+
33+package sun.rmi.rmic;
34+
35+import java.util.Vector;
36+import java.util.Enumeration;
37+import java.util.ResourceBundle;
38+import java.util.StringTokenizer;
39+import java.util.MissingResourceException;
40+
41+import java.io.OutputStream;
42+import java.io.PrintStream;
43+import java.io.IOException;
44+import java.io.File;
45+import java.io.FileNotFoundException;
46+import java.io.FileOutputStream;
47+import java.io.ByteArrayOutputStream;
48+
49+import sun.tools.java.ClassFile;
50+import sun.tools.java.ClassDefinition;
51+import sun.tools.java.ClassDeclaration;
52+import sun.tools.java.ClassNotFound;
53+import sun.tools.java.Identifier;
54+import sun.tools.java.ClassPath;
55+
56+import sun.tools.javac.SourceClass;
57+import sun.tools.util.CommandLine;
58+import java.lang.reflect.Constructor;
59+import java.util.Properties;
60+
61+/**
62+ * Main "rmic" program.
63+ *
64+ * WARNING: The contents of this source file are not part of any
65+ * supported API. Code that depends on them does so at its own risk:
66+ * they are subject to change or removal without notice.
67+ */
68+public class Main implements sun.rmi.rmic.Constants {
69+ String sourcePathArg;
70+ String sysClassPathArg;
71+ String extDirsArg;
72+ String classPathString;
73+ File destDir;
74+ int flags;
75+ long tm;
76+ Vector classes;
77+ boolean nowrite;
78+ boolean nocompile;
79+ boolean keepGenerated;
80+ boolean status;
81+ String[] generatorArgs;
82+ Vector generators;
83+ Class environmentClass = BatchEnvironment.class;
84+ boolean iiopGeneration = false;
85+
86+ /**
87+ * Name of the program.
88+ */
89+ String program;
90+
91+ /**
92+ * The stream where error message are printed.
93+ */
94+ OutputStream out;
95+
96+ /**
97+ * Constructor.
98+ */
99+ public Main(OutputStream out, String program) {
100+ this.out = out;
101+ this.program = program;
102+ }
103+
104+ /**
105+ * Output a message.
106+ */
107+ public void output(String msg) {
108+ PrintStream out =
109+ this.out instanceof PrintStream ? (PrintStream)this.out
110+ : new PrintStream(this.out, true);
111+ out.println(msg);
112+ }
113+
114+ /**
115+ * Top level error message. This method is called when the
116+ * environment could not be set up yet.
117+ */
118+ public void error(String msg) {
119+ output(getText(msg));
120+ }
121+
122+ public void error(String msg, String arg1) {
123+ output(getText(msg, arg1));
124+ }
125+
126+ public void error(String msg, String arg1, String arg2) {
127+ output(getText(msg, arg1, arg2));
128+ }
129+
130+ /**
131+ * Usage
132+ */
133+ public void usage() {
134+ error("rmic.usage", program);
135+ }
136+
137+ /**
138+ * Run the compiler
139+ */
140+ public synchronized boolean compile(String argv[]) {
141+
142+ /*
143+ * Handle internal option to use the new (and incomplete) rmic
144+ * implementation. This option is handled here, rather than
145+ * in parseArgs, so that none of the arguments will be nulled
146+ * before delegating to the new implementation.
147+ */
148+ for (int i = 0; i < argv.length; i++) {
149+ if (argv[i].equals("-Xnew")) {
150+ return (new sun.rmi.rmic.newrmic.Main(out,
151+ program)).compile(argv);
152+ }
153+ }
154+
155+ if (!parseArgs(argv)) {
156+ return false;
157+ }
158+
159+ if (classes.size() == 0) {
160+ usage();
161+ return false;
162+ }
163+
164+ return doCompile();
165+ }
166+
167+ /**
168+ * Get the destination directory.
169+ */
170+ public File getDestinationDir() {
171+ return destDir;
172+ }
173+
174+ /**
175+ * Parse the arguments for compile.
176+ */
177+ public boolean parseArgs(String argv[]) {
178+ sourcePathArg = null;
179+ sysClassPathArg = null;
180+ extDirsArg = null;
181+
182+ classPathString = null;
183+ destDir = null;
184+ flags = F_WARNINGS;
185+ tm = System.currentTimeMillis();
186+ classes = new Vector();
187+ nowrite = false;
188+ nocompile = false;
189+ keepGenerated = false;
190+ generatorArgs = getArray("generator.args",true);
191+ if (generatorArgs == null) {
192+ return false;
193+ }
194+ generators = new Vector();
195+
196+ // Pre-process command line for @file arguments
197+ try {
198+ argv = CommandLine.parse(argv);
199+ } catch (FileNotFoundException e) {
200+ error("rmic.cant.read", e.getMessage());
201+ return false;
202+ } catch (IOException e) {
203+ e.printStackTrace(out instanceof PrintStream ?
204+ (PrintStream) out :
205+ new PrintStream(out, true));
206+ return false;
207+ }
208+
209+ // Parse arguments
210+ for (int i = 0 ; i < argv.length ; i++) {
211+ if (argv[i] != null) {
212+ if (argv[i].equals("-g")) {
213+ flags &= ~F_OPT;
214+ flags |= F_DEBUG_LINES | F_DEBUG_VARS;
215+ argv[i] = null;
216+ } else if (argv[i].equals("-O")) {
217+ flags &= ~F_DEBUG_LINES;
218+ flags &= ~F_DEBUG_VARS;
219+ flags |= F_OPT | F_DEPENDENCIES;
220+ argv[i] = null;
221+ } else if (argv[i].equals("-nowarn")) {
222+ flags &= ~F_WARNINGS;
223+ argv[i] = null;
224+ } else if (argv[i].equals("-debug")) {
225+ flags |= F_DUMP;
226+ argv[i] = null;
227+ } else if (argv[i].equals("-depend")) {
228+ flags |= F_DEPENDENCIES;
229+ argv[i] = null;
230+ } else if (argv[i].equals("-verbose")) {
231+ flags |= F_VERBOSE;
232+ argv[i] = null;
233+ } else if (argv[i].equals("-nowrite")) {
234+ nowrite = true;
235+ argv[i] = null;
236+ } else if (argv[i].equals("-Xnocompile")) {
237+ nocompile = true;
238+ keepGenerated = true;
239+ argv[i] = null;
240+ } else if (argv[i].equals("-keep") ||
241+ argv[i].equals("-keepgenerated")) {
242+ keepGenerated = true;
243+ argv[i] = null;
244+ } else if (argv[i].equals("-show")) {
245+ error("rmic.option.unsupported", "-show");
246+ usage();
247+ return false;
248+ } else if (argv[i].equals("-classpath")) {
249+ if ((i + 1) < argv.length) {
250+ if (classPathString != null) {
251+ error("rmic.option.already.seen", "-classpath");
252+ usage();
253+ return false;
254+ }
255+ argv[i] = null;
256+ classPathString = argv[++i];
257+ argv[i] = null;
258+ } else {
259+ error("rmic.option.requires.argument", "-classpath");
260+ usage();
261+ return false;
262+ }
263+ } else if (argv[i].equals("-sourcepath")) {
264+ if ((i + 1) < argv.length) {
265+ if (sourcePathArg != null) {
266+ error("rmic.option.already.seen", "-sourcepath");
267+ usage();
268+ return false;
269+ }
270+ argv[i] = null;
271+ sourcePathArg = argv[++i];
272+ argv[i] = null;
273+ } else {
274+ error("rmic.option.requires.argument", "-sourcepath");
275+ usage();
276+ return false;
277+ }
278+ } else if (argv[i].equals("-bootclasspath")) {
279+ if ((i + 1) < argv.length) {
280+ if (sysClassPathArg != null) {
281+ error("rmic.option.already.seen", "-bootclasspath");
282+ usage();
283+ return false;
284+ }
285+ argv[i] = null;
286+ sysClassPathArg = argv[++i];
287+ argv[i] = null;
288+ } else {
289+ error("rmic.option.requires.argument", "-bootclasspath");
290+ usage();
291+ return false;
292+ }
293+ } else if (argv[i].equals("-extdirs")) {
294+ if ((i + 1) < argv.length) {
295+ if (extDirsArg != null) {
296+ error("rmic.option.already.seen", "-extdirs");
297+ usage();
298+ return false;
299+ }
300+ argv[i] = null;
301+ extDirsArg = argv[++i];
302+ argv[i] = null;
303+ } else {
304+ error("rmic.option.requires.argument", "-extdirs");
305+ usage();
306+ return false;
307+ }
308+ } else if (argv[i].equals("-d")) {
309+ if ((i + 1) < argv.length) {
310+ if (destDir != null) {
311+ error("rmic.option.already.seen", "-d");
312+ usage();
313+ return false;
314+ }
315+ argv[i] = null;
316+ destDir = new File(argv[++i]);
317+ argv[i] = null;
318+ if (!destDir.exists()) {
319+ error("rmic.no.such.directory", destDir.getPath());
320+ usage();
321+ return false;
322+ }
323+ } else {
324+ error("rmic.option.requires.argument", "-d");
325+ usage();
326+ return false;
327+ }
328+ } else {
329+ if (!checkGeneratorArg(argv,i)) {
330+ usage();
331+ return false;
332+ }
333+ }
334+ }
335+ }
336+
337+
338+ // Now that all generators have had a chance at the args,
339+ // scan what's left for classes and illegal args...
340+
341+ for (int i = 0; i < argv.length; i++) {
342+ if (argv[i] != null) {
343+ if (argv[i].startsWith("-")) {
344+ error("rmic.no.such.option", argv[i]);
345+ usage();
346+ return false;
347+ } else {
348+ classes.addElement(argv[i]);
349+ }
350+ }
351+ }
352+
353+
354+ // If the generators vector is empty, add the default generator...
355+
356+ if (generators.size() == 0) {
357+ addGenerator("default");
358+ }
359+
360+ return true;
361+ }
362+
363+ /**
364+ * If this argument is for a generator, instantiate it, call
365+ * parseArgs(...) and add generator to generators vector.
366+ * Returns false on error.
367+ */
368+ protected boolean checkGeneratorArg(String[] argv, int currentIndex) {
369+ boolean result = true;
370+ if (argv[currentIndex].startsWith("-")) {
371+ String arg = argv[currentIndex].substring(1).toLowerCase(); // Remove '-'
372+ for (int i = 0; i < generatorArgs.length; i++) {
373+ if (arg.equalsIgnoreCase(generatorArgs[i])) {
374+ // Got a match, add Generator and call parseArgs...
375+ Generator gen = addGenerator(arg);
376+ if (gen == null) {
377+ return false;
378+ }
379+ result = gen.parseArgs(argv,this);
380+ break;
381+ }
382+ }
383+ }
384+ return result;
385+ }
386+
387+ /**
388+ * Instantiate and add a generator to the generators array.
389+ */
390+ protected Generator addGenerator(String arg) {
391+
392+ Generator gen;
393+
394+ // Create an instance of the generator and add it to
395+ // the array...
396+
397+ String className = getString("generator.class." + arg);
398+ if (className == null) {
399+ error("rmic.missing.property",arg);
400+ return null;
401+ }
402+
403+ try {
404+ gen = (Generator) Class.forName(className).newInstance();
405+ } catch (Exception e) {
406+ error("rmic.cannot.instantiate",className);
407+ return null;
408+ }
409+
410+ generators.addElement(gen);
411+
412+ // Get the environment required by this generator...
413+
414+ Class envClass = BatchEnvironment.class;
415+ String env = getString("generator.env." + arg);
416+ if (env != null) {
417+ try {
418+ envClass = Class.forName(env);
419+
420+ // Is the new class a subclass of the current one?
421+
422+ if (environmentClass.isAssignableFrom(envClass)) {
423+
424+ // Yes, so switch to the new one...
425+
426+ environmentClass = envClass;
427+
428+ } else {
429+
430+ // No. Is the current class a subclass of the
431+ // new one?
432+
433+ if (!envClass.isAssignableFrom(environmentClass)) {
434+
435+ // No, so it's a conflict...
436+
437+ error("rmic.cannot.use.both",environmentClass.getName(),envClass.getName());
438+ return null;
439+ }
440+ }
441+ } catch (ClassNotFoundException e) {
442+ error("rmic.class.not.found",env);
443+ return null;
444+ }
445+ }
446+
447+ // If this is the iiop stub generator, cache
448+ // that fact for the jrmp generator...
449+
450+ if (arg.equals("iiop")) {
451+ iiopGeneration = true;
452+ }
453+ return gen;
454+ }
455+
456+ /**
457+ * Grab a resource string and parse it into an array of strings. Assumes
458+ * comma separated list.
459+ * @param name The resource name.
460+ * @param mustExist If true, throws error if resource does not exist. If
461+ * false and resource does not exist, returns zero element array.
462+ */
463+ protected String[] getArray(String name, boolean mustExist) {
464+ String[] result = null;
465+ String value = getString(name);
466+ if (value == null) {
467+ if (mustExist) {
468+ error("rmic.resource.not.found",name);
469+ return null;
470+ } else {
471+ return new String[0];
472+ }
473+ }
474+
475+ StringTokenizer parser = new StringTokenizer(value,", \t\n\r", false);
476+ int count = parser.countTokens();
477+ result = new String[count];
478+ for (int i = 0; i < count; i++) {
479+ result[i] = parser.nextToken();
480+ }
481+
482+ return result;
483+ }
484+
485+ /**
486+ * Get the correct type of BatchEnvironment
487+ */
488+ public BatchEnvironment getEnv() {
489+
490+ ClassPath classPath =
491+ BatchEnvironment.createClassPath(classPathString,
492+ sysClassPathArg,
493+ extDirsArg);
494+ BatchEnvironment result = null;
495+ try {
496+ Class[] ctorArgTypes = {OutputStream.class,ClassPath.class,Main.class};
497+ Object[] ctorArgs = {out,classPath,this};
498+ Constructor constructor = environmentClass.getConstructor(ctorArgTypes);
499+ result = (BatchEnvironment) constructor.newInstance(ctorArgs);
500+ result.reset();
501+ }
502+ catch (Exception e) {
503+ error("rmic.cannot.instantiate",environmentClass.getName());
504+ }
505+ return result;
506+ }
507+
508+
509+ /**
510+ * Do the compile with the switches and files already supplied
511+ */
512+ public boolean doCompile() {
513+ // Create batch environment
514+ BatchEnvironment env = getEnv();
515+ env.flags |= flags;
516+
517+ // Set the classfile version numbers
518+ // Compat and 1.1 stubs must retain the old version number.
519+ env.majorVersion = 45;
520+ env.minorVersion = 3;
521+
522+ // Preload the "out of memory" error string just in case we run
523+ // out of memory during the compile.
524+ String noMemoryErrorString = getText("rmic.no.memory");
525+ String stackOverflowErrorString = getText("rmic.stack.overflow");
526+
527+ try {
528+ /** Load the classes on the command line
529+ * Replace the entries in classes with the ClassDefinition for the class
530+ */
531+ for (int i = classes.size()-1; i >= 0; i-- ) {
532+ Identifier implClassName =
533+ Identifier.lookup((String)classes.elementAt(i));
534+
535+ /*
536+ * Fix bugid 4049354: support using '.' as an inner class
537+ * qualifier on the command line (previously, only mangled
538+ * inner class names were understood, like "pkg.Outer$Inner").
539+ *
540+ * The following method, also used by "javap", resolves the
541+ * given unmangled inner class name to the appropriate
542+ * internal identifier. For example, it translates
543+ * "pkg.Outer.Inner" to "pkg.Outer. Inner".
544+ */
545+ implClassName = env.resolvePackageQualifiedName(implClassName);
546+ /*
547+ * But if we use such an internal inner class name identifier
548+ * to load the class definition, the Java compiler will notice
549+ * if the impl class is a "private" inner class and then deny
550+ * skeletons (needed unless "-v1.2" is used) the ability to
551+ * cast to it. To work around this problem, we mangle inner
552+ * class name identifiers to their binary "outer" class name:
553+ * "pkg.Outer. Inner" becomes "pkg.Outer$Inner".
554+ */
555+ implClassName = Names.mangleClass(implClassName);
556+
557+ ClassDeclaration decl = env.getClassDeclaration(implClassName);
558+ try {
559+ ClassDefinition def = decl.getClassDefinition(env);
560+ for (int j = 0; j < generators.size(); j++) {
561+ Generator gen = (Generator)generators.elementAt(j);
562+ gen.generate(env, def, destDir);
563+ }
564+ } catch (ClassNotFound ex) {
565+ env.error(0, "rmic.class.not.found", implClassName);
566+ }
567+
568+ }
569+
570+ // compile all classes that need compilation
571+ if (!nocompile) {
572+ compileAllClasses(env);
573+ }
574+ } catch (OutOfMemoryError ee) {
575+ // The compiler has run out of memory. Use the error string
576+ // which we preloaded.
577+ env.output(noMemoryErrorString);
578+ return false;
579+ } catch (StackOverflowError ee) {
580+ env.output(stackOverflowErrorString);
581+ return false;
582+ } catch (Error ee) {
583+ // We allow the compiler to take an exception silently if a program
584+ // error has previously been detected. Presumably, this makes the
585+ // compiler more robust in the face of bad error recovery.
586+ if (env.nerrors == 0 || env.dump()) {
587+ env.error(0, "fatal.error");
588+ ee.printStackTrace(out instanceof PrintStream ?
589+ (PrintStream) out :
590+ new PrintStream(out, true));
591+ }
592+ } catch (Exception ee) {
593+ if (env.nerrors == 0 || env.dump()) {
594+ env.error(0, "fatal.exception");
595+ ee.printStackTrace(out instanceof PrintStream ?
596+ (PrintStream) out :
597+ new PrintStream(out, true));
598+ }
599+ }
600+
601+ env.flushErrors();
602+
603+ boolean status = true;
604+ if (env.nerrors > 0) {
605+ String msg = "";
606+ if (env.nerrors > 1) {
607+ msg = getText("rmic.errors", env.nerrors);
608+ } else {
609+ msg = getText("rmic.1error");
610+ }
611+ if (env.nwarnings > 0) {
612+ if (env.nwarnings > 1) {
613+ msg += ", " + getText("rmic.warnings", env.nwarnings);
614+ } else {
615+ msg += ", " + getText("rmic.1warning");
616+ }
617+ }
618+ output(msg);
619+ status = false;
620+ } else {
621+ if (env.nwarnings > 0) {
622+ if (env.nwarnings > 1) {
623+ output(getText("rmic.warnings", env.nwarnings));
624+ } else {
625+ output(getText("rmic.1warning"));
626+ }
627+ }
628+ }
629+
630+ // last step is to delete generated source files
631+ if (!keepGenerated) {
632+ env.deleteGeneratedFiles();
633+ }
634+
635+ // We're done
636+ if (env.verbose()) {
637+ tm = System.currentTimeMillis() - tm;
638+ output(getText("rmic.done_in", Long.toString(tm)));
639+ }
640+
641+ // Shutdown the environment object and release our resources.
642+ // Note that while this is unneccessary when rmic is invoked
643+ // the command line, there are environments in which rmic
644+ // from is invoked within a server process, so resource
645+ // reclamation is important...
646+
647+ env.shutdown();
648+
649+ sourcePathArg = null;
650+ sysClassPathArg = null;
651+ extDirsArg = null;
652+ classPathString = null;
653+ destDir = null;
654+ classes = null;
655+ generatorArgs = null;
656+ generators = null;
657+ environmentClass = null;
658+ program = null;
659+ out = null;
660+
661+ return status;
662+ }
663+
664+ /*
665+ * Compile all classes that need to be compiled.
666+ */
667+ public void compileAllClasses (BatchEnvironment env)
668+ throws ClassNotFound,
669+ IOException,
670+ InterruptedException {
671+ ByteArrayOutputStream buf = new ByteArrayOutputStream(4096);
672+ boolean done;
673+
674+ do {
675+ done = true;
676+ for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {
677+ ClassDeclaration c = (ClassDeclaration)e.nextElement();
678+ done = compileClass(c,buf,env);
679+ }
680+ } while (!done);
681+ }
682+
683+ /*
684+ * Compile a single class.
685+ */
686+ public boolean compileClass (ClassDeclaration c,
687+ ByteArrayOutputStream buf,
688+ BatchEnvironment env)
689+ throws ClassNotFound,
690+ IOException,
691+ InterruptedException {
692+ boolean done = true;
693+ env.flushErrors();
694+ SourceClass src;
695+
696+ switch (c.getStatus()) {
697+ case CS_UNDEFINED:
698+ {
699+ if (!env.dependencies()) {
700+ break;
701+ }
702+ // fall through
703+ }
704+
705+ case CS_SOURCE:
706+ {
707+ done = false;
708+ env.loadDefinition(c);
709+ if (c.getStatus() != CS_PARSED) {
710+ break;
711+ }
712+ // fall through
713+ }
714+
715+ case CS_PARSED:
716+ {
717+ if (c.getClassDefinition().isInsideLocal()) {
718+ break;
719+ }
720+ // If we get to here, then compilation is going
721+ // to occur. If the -Xnocompile switch is set
722+ // then fail. Note that this check is required
723+ // here because this method is called from
724+ // generators, not just from within this class...
725+
726+ if (nocompile) {
727+ throw new IOException("Compilation required, but -Xnocompile option in effect");
728+ }
729+
730+ done = false;
731+
732+ src = (SourceClass)c.getClassDefinition(env);
733+ src.check(env);
734+ c.setDefinition(src, CS_CHECKED);
735+ // fall through
736+ }
737+
738+ case CS_CHECKED:
739+ {
740+ src = (SourceClass)c.getClassDefinition(env);
741+ // bail out if there were any errors
742+ if (src.getError()) {
743+ c.setDefinition(src, CS_COMPILED);
744+ break;
745+ }
746+ done = false;
747+ buf.reset();
748+ src.compile(buf);
749+ c.setDefinition(src, CS_COMPILED);
750+ src.cleanup(env);
751+
752+ if (src.getError() || nowrite) {
753+ break;
754+ }
755+
756+ String pkgName = c.getName().getQualifier().toString().replace('.', File.separatorChar);
757+ String className = c.getName().getFlatName().toString().replace('.', SIGC_INNERCLASS) + ".class";
758+
759+ File file;
760+ if (destDir != null) {
761+ if (pkgName.length() > 0) {
762+ file = new File(destDir, pkgName);
763+ if (!file.exists()) {
764+ file.mkdirs();
765+ }
766+ file = new File(file, className);
767+ } else {
768+ file = new File(destDir, className);
769+ }
770+ } else {
771+ ClassFile classfile = (ClassFile)src.getSource();
772+ if (classfile.isZipped()) {
773+ env.error(0, "cant.write", classfile.getPath());
774+ break;
775+ }
776+ file = new File(classfile.getPath());
777+ file = new File(file.getParent(), className);
778+ }
779+
780+ // Create the file
781+ try {
782+ FileOutputStream out = new FileOutputStream(file.getPath());
783+ buf.writeTo(out);
784+ out.close();
785+ if (env.verbose()) {
786+ output(getText("rmic.wrote", file.getPath()));
787+ }
788+ } catch (IOException ee) {
789+ env.error(0, "cant.write", file.getPath());
790+ }
791+ }
792+ }
793+ return done;
794+ }
795+
796+ /**
797+ * Main program
798+ */
799+ public static void main(String argv[]) {
800+ Main compiler = new Main(System.out, "rmic");
801+ System.exit(compiler.compile(argv) ? 0 : 1);
802+ }
803+
804+ /**
805+ * Return the string value of a named resource in the rmic.properties
806+ * resource bundle. If the resource is not found, null is returned.
807+ */
808+ public static String getString(String key) {
809+ if (!resourcesInitialized) {
810+ initResources();
811+ }
812+
813+ // To enable extensions, search the 'resourcesExt'
814+ // bundle first, followed by the 'resources' bundle...
815+
816+ if (resourcesExt != null) {
817+ try {
818+ return resourcesExt.getString(key);
819+ } catch (MissingResourceException e) {}
820+ }
821+
822+ try {
823+ return resources.getString(key);
824+ } catch (MissingResourceException ignore) {
825+ }
826+ return null;
827+ }
828+
829+ private static boolean resourcesInitialized = false;
830+ private static ResourceBundle resources;
831+ private static ResourceBundle resourcesExt = null;
832+
833+ private static void initResources() {
834+ try {
835+ resources =
836+ ResourceBundle.getBundle("sun.rmi.rmic.resources.rmic");
837+ resourcesInitialized = true;
838+ try {
839+ resourcesExt =
840+ ResourceBundle.getBundle("sun.rmi.rmic.resources.rmicext");
841+ } catch (MissingResourceException e) {}
842+ } catch (MissingResourceException e) {
843+ throw new Error("fatal: missing resource bundle: " +
844+ e.getClassName());
845+ }
846+ }
847+
848+ public static String getText(String key) {
849+ String message = getString(key);
850+ if (message == null) {
851+ message = "no text found: \"" + key + "\"";
852+ }
853+ return message;
854+ }
855+
856+ public static String getText(String key, int num) {
857+ return getText(key, Integer.toString(num), null, null);
858+ }
859+
860+ public static String getText(String key, String arg0) {
861+ return getText(key, arg0, null, null);
862+ }
863+
864+ public static String getText(String key, String arg0, String arg1) {
865+ return getText(key, arg0, arg1, null);
866+ }
867+
868+ public static String getText(String key,
869+ String arg0, String arg1, String arg2)
870+ {
871+ String format = getString(key);
872+ if (format == null) {
873+ format = "no text found: key = \"" + key + "\", " +
874+ "arguments = \"{0}\", \"{1}\", \"{2}\"";
875+ }
876+
877+ String[] args = new String[3];
878+ args[0] = (arg0 != null ? arg0.toString() : "null");
879+ args[1] = (arg1 != null ? arg1.toString() : "null");
880+ args[2] = (arg2 != null ? arg2.toString() : "null");
881+
882+ return java.text.MessageFormat.format(format, args);
883+ }
884+}