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