src/share/classes/sun/rmi/rmic/Main.java

Print this page




  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<String> classes;
  77     boolean nowrite;
  78     boolean nocompile;
  79     boolean keepGenerated;
  80     boolean status;
  81     String[] generatorArgs;
  82     Vector<Generator> generators;
  83     Class<? extends BatchEnvironment> environmentClass =
  84         BatchEnvironment.class;
  85     boolean iiopGeneration = false;
  86 
  87     /**
  88      * Name of the program.
  89      */
  90     String program;
  91 
  92     /**
  93      * The stream where error message are printed.
  94      */
  95     OutputStream out;
  96 
  97     /**
  98      * Constructor.
  99      */
 100     public Main(OutputStream out, String program) {
 101         this.out = out;
 102         this.program = program;
 103     }
 104 


 167 
 168     /**
 169      * Get the destination directory.
 170      */
 171     public File getDestinationDir() {
 172         return destDir;
 173     }
 174 
 175     /**
 176      * Parse the arguments for compile.
 177      */
 178     public boolean parseArgs(String argv[]) {
 179         sourcePathArg = null;
 180         sysClassPathArg = null;
 181         extDirsArg = null;
 182 
 183         classPathString = null;
 184         destDir = null;
 185         flags = F_WARNINGS;
 186         tm = System.currentTimeMillis();
 187         classes = new Vector<>();
 188         nowrite = false;
 189         nocompile = false;
 190         keepGenerated = false;
 191         generatorArgs = getArray("generator.args",true);
 192         if (generatorArgs == null) {
 193             return false;
 194         }
 195         generators = new Vector<>();
 196 
 197         // Pre-process command line for @file arguments
 198         try {
 199             argv = CommandLine.parse(argv);
 200         } catch (FileNotFoundException e) {
 201             error("rmic.cant.read", e.getMessage());
 202             return false;
 203         } catch (IOException e) {
 204             e.printStackTrace(out instanceof PrintStream ?
 205                               (PrintStream) out :
 206                               new PrintStream(out, true));
 207             return false;
 208         }
 209 
 210         // Parse arguments
 211         for (int i = 0 ; i < argv.length ; i++) {
 212             if (argv[i] != null) {
 213                 if (argv[i].equals("-g")) {
 214                     flags &= ~F_OPT;
 215                     flags |= F_DEBUG_LINES | F_DEBUG_VARS;


 395         // Create an instance of the generator and add it to
 396         // the array...
 397 
 398         String className = getString("generator.class." + arg);
 399         if (className == null) {
 400             error("rmic.missing.property",arg);
 401             return null;
 402         }
 403 
 404         try {
 405             gen = (Generator) Class.forName(className).newInstance();
 406         } catch (Exception e) {
 407             error("rmic.cannot.instantiate",className);
 408             return null;
 409         }
 410 
 411         generators.addElement(gen);
 412 
 413         // Get the environment required by this generator...
 414 
 415         Class<?> envClass = BatchEnvironment.class;
 416         String env = getString("generator.env." + arg);
 417         if (env != null) {
 418             try {
 419                 envClass = Class.forName(env);
 420 
 421                 // Is the new class a subclass of the current one?
 422 
 423                 if (environmentClass.isAssignableFrom(envClass)) {
 424 
 425                     // Yes, so switch to the new one...
 426 
 427                     environmentClass = BatchEnvironment.class.asSubclass(environmentClass);
 428 
 429                 } else {
 430 
 431                     // No. Is the current class a subclass of the
 432                     // new one?
 433 
 434                     if (!envClass.isAssignableFrom(environmentClass)) {
 435 
 436                         // No, so it's a conflict...
 437 
 438                         error("rmic.cannot.use.both",environmentClass.getName(),envClass.getName());
 439                         return null;
 440                     }
 441                 }
 442             } catch (ClassNotFoundException e) {
 443                 error("rmic.class.not.found",env);
 444                 return null;
 445             }
 446         }
 447 


 479         for (int i = 0; i < count; i++) {
 480             result[i] = parser.nextToken();
 481         }
 482 
 483         return result;
 484     }
 485 
 486     /**
 487      * Get the correct type of BatchEnvironment
 488      */
 489     public BatchEnvironment getEnv() {
 490 
 491         ClassPath classPath =
 492             BatchEnvironment.createClassPath(classPathString,
 493                                              sysClassPathArg,
 494                                              extDirsArg);
 495         BatchEnvironment result = null;
 496         try {
 497             Class[] ctorArgTypes = {OutputStream.class,ClassPath.class,Main.class};
 498             Object[] ctorArgs = {out,classPath,this};
 499             Constructor<? extends BatchEnvironment> constructor =
 500                 environmentClass.getConstructor(ctorArgTypes);
 501             result =  constructor.newInstance(ctorArgs);
 502             result.reset();
 503         }
 504         catch (Exception e) {
 505             error("rmic.cannot.instantiate",environmentClass.getName());
 506         }
 507         return result;
 508     }
 509 
 510 
 511     /**
 512      * Do the compile with the switches and files already supplied
 513      */
 514     public boolean doCompile() {
 515         // Create batch environment
 516         BatchEnvironment env = getEnv();
 517         env.flags |= flags;
 518 
 519         // Set the classfile version numbers
 520         // Compat and 1.1 stubs must retain the old version number.
 521         env.majorVersion = 45;
 522         env.minorVersion = 3;
 523 
 524         // Preload the "out of memory" error string just in case we run
 525         // out of memory during the compile.
 526         String noMemoryErrorString = getText("rmic.no.memory");
 527         String stackOverflowErrorString = getText("rmic.stack.overflow");
 528 
 529         try {
 530             /** Load the classes on the command line
 531              * Replace the entries in classes with the ClassDefinition for the class
 532              */
 533             for (int i = classes.size()-1; i >= 0; i-- ) {
 534                 Identifier implClassName =
 535                     Identifier.lookup(classes.elementAt(i));
 536 
 537                 /*
 538                  * Fix bugid 4049354: support using '.' as an inner class
 539                  * qualifier on the command line (previously, only mangled
 540                  * inner class names were understood, like "pkg.Outer$Inner").
 541                  *
 542                  * The following method, also used by "javap", resolves the
 543                  * given unmangled inner class name to the appropriate
 544                  * internal identifier.  For example, it translates
 545                  * "pkg.Outer.Inner" to "pkg.Outer. Inner".
 546                  */
 547                 implClassName = env.resolvePackageQualifiedName(implClassName);
 548                 /*
 549                  * But if we use such an internal inner class name identifier
 550                  * to load the class definition, the Java compiler will notice
 551                  * if the impl class is a "private" inner class and then deny
 552                  * skeletons (needed unless "-v1.2" is used) the ability to
 553                  * cast to it.  To work around this problem, we mangle inner
 554                  * class name identifiers to their binary "outer" class name:
 555                  * "pkg.Outer. Inner" becomes "pkg.Outer$Inner".
 556                  */
 557                 implClassName = Names.mangleClass(implClassName);
 558 
 559                 ClassDeclaration decl = env.getClassDeclaration(implClassName);
 560                 try {
 561                     ClassDefinition def = decl.getClassDefinition(env);
 562                     for (int j = 0; j < generators.size(); j++) {
 563                         Generator gen = generators.elementAt(j);
 564                         gen.generate(env, def, destDir);
 565                     }
 566                 } catch (ClassNotFound ex) {
 567                     env.error(0, "rmic.class.not.found", implClassName);
 568                 }
 569 
 570             }
 571 
 572             // compile all classes that need compilation
 573             if (!nocompile) {
 574                 compileAllClasses(env);
 575             }
 576         } catch (OutOfMemoryError ee) {
 577             // The compiler has run out of memory.  Use the error string
 578             // which we preloaded.
 579             env.output(noMemoryErrorString);
 580             return false;
 581         } catch (StackOverflowError ee) {
 582             env.output(stackOverflowErrorString);
 583             return false;


 658         generators = null;
 659         environmentClass = null;
 660         program = null;
 661         out = null;
 662 
 663         return status;
 664     }
 665 
 666     /*
 667      * Compile all classes that need to be compiled.
 668      */
 669     public void compileAllClasses (BatchEnvironment env)
 670         throws ClassNotFound,
 671                IOException,
 672                InterruptedException {
 673         ByteArrayOutputStream buf = new ByteArrayOutputStream(4096);
 674         boolean done;
 675 
 676         do {
 677             done = true;
 678             for (Enumeration<?> e = env.getClasses() ; e.hasMoreElements() ; ) {
 679                 ClassDeclaration c = (ClassDeclaration)e.nextElement();
 680                 done = compileClass(c,buf,env);
 681             }
 682         } while (!done);
 683     }
 684 
 685     /*
 686      * Compile a single class.
 687      * Fallthrough is intentional
 688      */
 689     @SuppressWarnings("fallthrough")
 690     public boolean compileClass (ClassDeclaration c,
 691                                  ByteArrayOutputStream buf,
 692                                  BatchEnvironment env)
 693         throws ClassNotFound,
 694                IOException,
 695                InterruptedException {
 696         boolean done = true;
 697         env.flushErrors();
 698         SourceClass src;
 699 
 700         switch (c.getStatus()) {
 701         case CS_UNDEFINED:
 702             {
 703                 if (!env.dependencies()) {
 704                     break;
 705                 }
 706                 // fall through
 707             }
 708 
 709         case CS_SOURCE:


 866     }
 867 
 868     public static String getText(String key, String arg0, String arg1) {
 869         return getText(key, arg0, arg1, null);
 870     }
 871 
 872     public static String getText(String key,
 873                                  String arg0, String arg1, String arg2)
 874     {
 875         String format = getString(key);
 876         if (format == null) {
 877             format = "no text found: key = \"" + key + "\", " +
 878                 "arguments = \"{0}\", \"{1}\", \"{2}\"";
 879         }
 880 
 881         String[] args = new String[3];
 882         args[0] = (arg0 != null ? arg0.toString() : "null");
 883         args[1] = (arg1 != null ? arg1.toString() : "null");
 884         args[2] = (arg2 != null ? arg2.toString() : "null");
 885 
 886         return java.text.MessageFormat.format(format, (Object[]) args);
 887     }
 888 }


  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 


 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;


 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 


 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;


 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:


 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 }