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

Print this page




  44 import sun.tools.java.ClassDefinition;
  45 import sun.tools.java.ClassDeclaration;
  46 import sun.tools.java.ClassNotFound;
  47 import sun.tools.java.ClassFile;
  48 import sun.tools.java.MemberDefinition;
  49 import com.sun.corba.se.impl.util.Utility;
  50 
  51 /**
  52  * A Generator object will generate the Java source code of the stub
  53  * and skeleton classes for an RMI remote implementation class, using
  54  * a particular stub protocol version.
  55  *
  56  * WARNING: The contents of this source file are not part of any
  57  * supported API.  Code that depends on them does so at its own risk:
  58  * they are subject to change or removal without notice.
  59  *
  60  * @author      Peter Jones,  Bryan Atsatt
  61  */
  62 public class RMIGenerator implements RMIConstants, Generator {
  63 
  64     private static final Hashtable<String, Integer> versionOptions = new Hashtable<>();
  65     static {
  66         versionOptions.put("-v1.1", new Integer(STUB_VERSION_1_1));
  67         versionOptions.put("-vcompat", new Integer(STUB_VERSION_FAT));
  68         versionOptions.put("-v1.2", new Integer(STUB_VERSION_1_2));
  69     }
  70 
  71     /**
  72      * Default constructor for Main to use.
  73      */
  74     public RMIGenerator() {
  75         version = STUB_VERSION_1_2;     // default is -v1.2 (see 4638155)
  76     }
  77 
  78     /**
  79      * Examine and consume command line arguments.
  80      * @param argv The command line arguments. Ignore null
  81      * and unknown arguments. Set each consumed argument to null.
  82      * @param error Report any errors using the main.error() methods.
  83      * @return true if no errors, false otherwise.
  84      */
  85     public boolean parseArgs(String argv[], Main main) {
  86         String explicitVersion = null;
  87         for (int i = 0; i < argv.length; i++) {
  88             if (argv[i] != null) {
  89                 String arg = argv[i].toLowerCase();
  90                 if (versionOptions.containsKey(arg)) {
  91                     if (explicitVersion != null &&
  92                         !explicitVersion.equals(arg))
  93                     {
  94                         main.error("rmic.cannot.use.both",
  95                                    explicitVersion, arg);
  96                         return false;
  97                     }
  98                     explicitVersion = arg;
  99                     version = versionOptions.get(arg);
 100                     argv[i] = null;
 101                 }
 102             }
 103         }
 104         return true;
 105     }
 106 
 107     /**
 108      * Generate the source files for the stub and/or skeleton classes
 109      * needed by RMI for the given remote implementation class.
 110      *
 111      * @param env       compiler environment
 112      * @param cdef      definition of remote implementation class
 113      *                  to generate stubs and/or skeletons for
 114      * @param destDir   directory for the root of the package hierarchy
 115      *                  for generated files
 116      */
 117     public void generate(BatchEnvironment env, ClassDefinition cdef, File destDir) {
 118         RemoteClass remoteClass = RemoteClass.forClass(env, cdef);
 119         if (remoteClass == null)        // exit if an error occurred


 502         }
 503         p.pOlnI("{");
 504 
 505         /*
 506          * The RemoteRef.invoke methods throw Exception, but unless this
 507          * stub method throws Exception as well, we must catch Exceptions
 508          * thrown from the invocation.  So we must catch Exception and
 509          * rethrow something we can throw: UnexpectedException, which is a
 510          * subclass of RemoteException.  But for any subclasses of Exception
 511          * that we can throw, like RemoteException, RuntimeException, and
 512          * any of the exceptions declared by this stub method, we want them
 513          * to pass through unharmed, so first we must catch any such
 514          * exceptions and rethrow it directly.
 515          *
 516          * We have to be careful generating the rethrowing catch blocks
 517          * here, because javac will flag an error if there are any
 518          * unreachable catch blocks, i.e. if the catch of an exception class
 519          * follows a previous catch of it or of one of its superclasses.
 520          * The following method invocation takes care of these details.
 521          */
 522         Vector<ClassDefinition> catchList = computeUniqueCatchList(exceptions);
 523 
 524         /*
 525          * If we need to catch any particular exceptions (i.e. this method
 526          * does not declare java.lang.Exception), put the entire stub
 527          * method in a try block.
 528          */
 529         if (catchList.size() > 0) {
 530             p.plnI("try {");
 531         }
 532 
 533         if (version == STUB_VERSION_FAT) {
 534             p.plnI("if (useNewInvoke) {");
 535         }
 536         if (version == STUB_VERSION_FAT ||
 537             version == STUB_VERSION_1_2)
 538         {
 539             if (!returnType.isType(TC_VOID)) {
 540                 p.p("Object $result = ");               // REMIND: why $?
 541             }
 542             p.p("ref.invoke(this, " + methodFieldNames[opnum] + ", ");


 598                     p.pOlnI("} catch (java.lang.ClassNotFoundException e) {");
 599                     p.pln("throw new " + idUnmarshalException +
 600                         "(\"error unmarshalling return\", e);");
 601                 }
 602                 p.pOlnI("} finally {");
 603                 p.pln("ref.done(call);");
 604                 p.pOln("}");
 605                 p.pln("return $result;");
 606             }
 607         }
 608         if (version == STUB_VERSION_FAT) {
 609             p.pOln("}");                // end if/else (useNewInvoke) block
 610         }
 611 
 612         /*
 613          * If we need to catch any particular exceptions, finally write
 614          * the catch blocks for them, rethrow any other Exceptions with an
 615          * UnexpectedException, and end the try block.
 616          */
 617         if (catchList.size() > 0) {
 618             for (Enumeration<ClassDefinition> enumeration = catchList.elements();
 619                  enumeration.hasMoreElements();)
 620             {
 621                 ClassDefinition def = enumeration.nextElement();
 622                 p.pOlnI("} catch (" + def.getName() + " e) {");
 623                 p.pln("throw e;");
 624             }
 625             p.pOlnI("} catch (java.lang.Exception e) {");
 626             p.pln("throw new " + idUnexpectedException +
 627                 "(\"undeclared checked exception\", e);");
 628             p.pOln("}");                // end try/catch block
 629         }
 630 
 631         p.pOln("}");                    // end stub method
 632     }
 633 
 634     /**
 635      * Compute the exceptions which need to be caught and rethrown in a
 636      * stub method before wrapping Exceptions in UnexpectedExceptions,
 637      * given the exceptions declared in the throws clause of the method.
 638      * Returns a Vector containing ClassDefinition objects for each
 639      * exception to catch.  Each exception is guaranteed to be unique,
 640      * i.e. not a subclass of any of the other exceptions in the Vector,
 641      * so the catch blocks for these exceptions may be generated in any
 642      * order relative to each other.
 643      *
 644      * RemoteException and RuntimeException are each automatically placed
 645      * in the returned Vector (if none of their superclasses are already
 646      * present), since those exceptions should always be directly rethrown
 647      * by a stub method.
 648      *
 649      * The returned Vector will be empty if java.lang.Exception or one
 650      * of its superclasses is in the throws clause of the method, indicating
 651      * that no exceptions need to be caught.
 652      */
 653     private Vector<ClassDefinition> computeUniqueCatchList(ClassDeclaration[] exceptions) {
 654         Vector<ClassDefinition> uniqueList = new Vector<>();       // unique exceptions to catch
 655 
 656         uniqueList.addElement(defRuntimeException);
 657         uniqueList.addElement(defRemoteException);
 658 
 659         /* For each exception declared by the stub method's throws clause: */
 660     nextException:
 661         for (int i = 0; i < exceptions.length; i++) {
 662             ClassDeclaration decl = exceptions[i];
 663             try {
 664                 if (defException.subClassOf(env, decl)) {
 665                     /*
 666                      * (If java.lang.Exception (or a superclass) was declared
 667                      * in the throws clause of this stub method, then we don't
 668                      * have to bother catching anything; clear the list and
 669                      * return.)
 670                      */
 671                     uniqueList.clear();
 672                     break;
 673                 } else if (!defException.superClassOf(env, decl)) {
 674                     /*
 675                      * Ignore other Throwables that do not extend Exception,
 676                      * since they do not need to be caught anyway.
 677                      */
 678                     continue;
 679                 }
 680                 /*
 681                  * Compare this exception against the current list of
 682                  * exceptions that need to be caught:
 683                  */
 684                 for (int j = 0; j < uniqueList.size();) {
 685                     ClassDefinition def = uniqueList.elementAt(j);

 686                     if (def.superClassOf(env, decl)) {
 687                         /*
 688                          * If a superclass of this exception is already on
 689                          * the list to catch, then ignore and continue;
 690                          */
 691                         continue nextException;
 692                     } else if (def.subClassOf(env, decl)) {
 693                         /*
 694                          * If a subclass of this exception is on the list
 695                          * to catch, then remove it.
 696                          */
 697                         uniqueList.removeElementAt(j);
 698                     } else {
 699                         j++;    // else continue comparing
 700                     }
 701                 }
 702                 /* This exception is unique: add it to the list to catch. */
 703                 uniqueList.addElement(decl.getClassDefinition(env));
 704             } catch (ClassNotFound e) {
 705                 env.error(0, "class.not.found", e.name, decl.getName());




  44 import sun.tools.java.ClassDefinition;
  45 import sun.tools.java.ClassDeclaration;
  46 import sun.tools.java.ClassNotFound;
  47 import sun.tools.java.ClassFile;
  48 import sun.tools.java.MemberDefinition;
  49 import com.sun.corba.se.impl.util.Utility;
  50 
  51 /**
  52  * A Generator object will generate the Java source code of the stub
  53  * and skeleton classes for an RMI remote implementation class, using
  54  * a particular stub protocol version.
  55  *
  56  * WARNING: The contents of this source file are not part of any
  57  * supported API.  Code that depends on them does so at its own risk:
  58  * they are subject to change or removal without notice.
  59  *
  60  * @author      Peter Jones,  Bryan Atsatt
  61  */
  62 public class RMIGenerator implements RMIConstants, Generator {
  63 
  64     private static final Hashtable versionOptions = new Hashtable();
  65     static {
  66         versionOptions.put("-v1.1", new Integer(STUB_VERSION_1_1));
  67         versionOptions.put("-vcompat", new Integer(STUB_VERSION_FAT));
  68         versionOptions.put("-v1.2", new Integer(STUB_VERSION_1_2));
  69     }
  70 
  71     /**
  72      * Default constructor for Main to use.
  73      */
  74     public RMIGenerator() {
  75         version = STUB_VERSION_1_2;     // default is -v1.2 (see 4638155)
  76     }
  77 
  78     /**
  79      * Examine and consume command line arguments.
  80      * @param argv The command line arguments. Ignore null
  81      * and unknown arguments. Set each consumed argument to null.
  82      * @param error Report any errors using the main.error() methods.
  83      * @return true if no errors, false otherwise.
  84      */
  85     public boolean parseArgs(String argv[], Main main) {
  86         String explicitVersion = null;
  87         for (int i = 0; i < argv.length; i++) {
  88             if (argv[i] != null) {
  89                 String arg = argv[i].toLowerCase();
  90                 if (versionOptions.containsKey(arg)) {
  91                     if (explicitVersion != null &&
  92                         !explicitVersion.equals(arg))
  93                     {
  94                         main.error("rmic.cannot.use.both",
  95                                    explicitVersion, arg);
  96                         return false;
  97                     }
  98                     explicitVersion = arg;
  99                     version = ((Integer) versionOptions.get(arg)).intValue();
 100                     argv[i] = null;
 101                 }
 102             }
 103         }
 104         return true;
 105     }
 106 
 107     /**
 108      * Generate the source files for the stub and/or skeleton classes
 109      * needed by RMI for the given remote implementation class.
 110      *
 111      * @param env       compiler environment
 112      * @param cdef      definition of remote implementation class
 113      *                  to generate stubs and/or skeletons for
 114      * @param destDir   directory for the root of the package hierarchy
 115      *                  for generated files
 116      */
 117     public void generate(BatchEnvironment env, ClassDefinition cdef, File destDir) {
 118         RemoteClass remoteClass = RemoteClass.forClass(env, cdef);
 119         if (remoteClass == null)        // exit if an error occurred


 502         }
 503         p.pOlnI("{");
 504 
 505         /*
 506          * The RemoteRef.invoke methods throw Exception, but unless this
 507          * stub method throws Exception as well, we must catch Exceptions
 508          * thrown from the invocation.  So we must catch Exception and
 509          * rethrow something we can throw: UnexpectedException, which is a
 510          * subclass of RemoteException.  But for any subclasses of Exception
 511          * that we can throw, like RemoteException, RuntimeException, and
 512          * any of the exceptions declared by this stub method, we want them
 513          * to pass through unharmed, so first we must catch any such
 514          * exceptions and rethrow it directly.
 515          *
 516          * We have to be careful generating the rethrowing catch blocks
 517          * here, because javac will flag an error if there are any
 518          * unreachable catch blocks, i.e. if the catch of an exception class
 519          * follows a previous catch of it or of one of its superclasses.
 520          * The following method invocation takes care of these details.
 521          */
 522         Vector catchList = computeUniqueCatchList(exceptions);
 523 
 524         /*
 525          * If we need to catch any particular exceptions (i.e. this method
 526          * does not declare java.lang.Exception), put the entire stub
 527          * method in a try block.
 528          */
 529         if (catchList.size() > 0) {
 530             p.plnI("try {");
 531         }
 532 
 533         if (version == STUB_VERSION_FAT) {
 534             p.plnI("if (useNewInvoke) {");
 535         }
 536         if (version == STUB_VERSION_FAT ||
 537             version == STUB_VERSION_1_2)
 538         {
 539             if (!returnType.isType(TC_VOID)) {
 540                 p.p("Object $result = ");               // REMIND: why $?
 541             }
 542             p.p("ref.invoke(this, " + methodFieldNames[opnum] + ", ");


 598                     p.pOlnI("} catch (java.lang.ClassNotFoundException e) {");
 599                     p.pln("throw new " + idUnmarshalException +
 600                         "(\"error unmarshalling return\", e);");
 601                 }
 602                 p.pOlnI("} finally {");
 603                 p.pln("ref.done(call);");
 604                 p.pOln("}");
 605                 p.pln("return $result;");
 606             }
 607         }
 608         if (version == STUB_VERSION_FAT) {
 609             p.pOln("}");                // end if/else (useNewInvoke) block
 610         }
 611 
 612         /*
 613          * If we need to catch any particular exceptions, finally write
 614          * the catch blocks for them, rethrow any other Exceptions with an
 615          * UnexpectedException, and end the try block.
 616          */
 617         if (catchList.size() > 0) {
 618             for (Enumeration enumeration = catchList.elements();
 619                  enumeration.hasMoreElements();)
 620             {
 621                 ClassDefinition def = (ClassDefinition) enumeration.nextElement();
 622                 p.pOlnI("} catch (" + def.getName() + " e) {");
 623                 p.pln("throw e;");
 624             }
 625             p.pOlnI("} catch (java.lang.Exception e) {");
 626             p.pln("throw new " + idUnexpectedException +
 627                 "(\"undeclared checked exception\", e);");
 628             p.pOln("}");                // end try/catch block
 629         }
 630 
 631         p.pOln("}");                    // end stub method
 632     }
 633 
 634     /**
 635      * Compute the exceptions which need to be caught and rethrown in a
 636      * stub method before wrapping Exceptions in UnexpectedExceptions,
 637      * given the exceptions declared in the throws clause of the method.
 638      * Returns a Vector containing ClassDefinition objects for each
 639      * exception to catch.  Each exception is guaranteed to be unique,
 640      * i.e. not a subclass of any of the other exceptions in the Vector,
 641      * so the catch blocks for these exceptions may be generated in any
 642      * order relative to each other.
 643      *
 644      * RemoteException and RuntimeException are each automatically placed
 645      * in the returned Vector (if none of their superclasses are already
 646      * present), since those exceptions should always be directly rethrown
 647      * by a stub method.
 648      *
 649      * The returned Vector will be empty if java.lang.Exception or one
 650      * of its superclasses is in the throws clause of the method, indicating
 651      * that no exceptions need to be caught.
 652      */
 653     private Vector computeUniqueCatchList(ClassDeclaration[] exceptions) {
 654         Vector uniqueList = new Vector();       // unique exceptions to catch
 655 
 656         uniqueList.addElement(defRuntimeException);
 657         uniqueList.addElement(defRemoteException);
 658 
 659         /* For each exception declared by the stub method's throws clause: */
 660     nextException:
 661         for (int i = 0; i < exceptions.length; i++) {
 662             ClassDeclaration decl = exceptions[i];
 663             try {
 664                 if (defException.subClassOf(env, decl)) {
 665                     /*
 666                      * (If java.lang.Exception (or a superclass) was declared
 667                      * in the throws clause of this stub method, then we don't
 668                      * have to bother catching anything; clear the list and
 669                      * return.)
 670                      */
 671                     uniqueList.clear();
 672                     break;
 673                 } else if (!defException.superClassOf(env, decl)) {
 674                     /*
 675                      * Ignore other Throwables that do not extend Exception,
 676                      * since they do not need to be caught anyway.
 677                      */
 678                     continue;
 679                 }
 680                 /*
 681                  * Compare this exception against the current list of
 682                  * exceptions that need to be caught:
 683                  */
 684                 for (int j = 0; j < uniqueList.size();) {
 685                     ClassDefinition def =
 686                         (ClassDefinition) uniqueList.elementAt(j);
 687                     if (def.superClassOf(env, decl)) {
 688                         /*
 689                          * If a superclass of this exception is already on
 690                          * the list to catch, then ignore and continue;
 691                          */
 692                         continue nextException;
 693                     } else if (def.subClassOf(env, decl)) {
 694                         /*
 695                          * If a subclass of this exception is on the list
 696                          * to catch, then remove it.
 697                          */
 698                         uniqueList.removeElementAt(j);
 699                     } else {
 700                         j++;    // else continue comparing
 701                     }
 702                 }
 703                 /* This exception is unique: add it to the list to catch. */
 704                 uniqueList.addElement(decl.getClassDefinition(env));
 705             } catch (ClassNotFound e) {
 706                 env.error(0, "class.not.found", e.name, decl.getName());