/* * Copyright (c) 1997, 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. */ /*****************************************************************************//* Copyright (c) IBM Corporation 1998 *//* *//* (C) Copyright IBM Corp. 1998 *//* *//*****************************************************************************/ package sun.rmi.rmic; import java.io.File;import java.io.FileOutputStream;import java.io.OutputStreamWriter;import java.io.IOException;import java.util.Enumeration;import java.util.Hashtable;import java.util.Vector;import sun.tools.java.Type;import sun.tools.java.Identifier;import sun.tools.java.ClassDefinition;import sun.tools.java.ClassDeclaration;import sun.tools.java.ClassNotFound;import sun.tools.java.ClassFile;import sun.tools.java.MemberDefinition;import com.sun.corba.se.impl.util.Utility; /** * A Generator object will generate the Java source code of the stub * and skeleton classes for an RMI remote implementation class, using * a particular stub protocol version. * * 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. * * @author Peter Jones, Bryan Atsatt */public class RMIGenerator implements RMIConstants, Generator { private static final Hashtable versionOptions = new Hashtable(); static { versionOptions.put("-v1.1", new Integer(STUB_VERSION_1_1)); versionOptions.put("-vcompat", new Integer(STUB_VERSION_FAT)); versionOptions.put("-v1.2", new Integer(STUB_VERSION_1_2)); } /** * Default constructor for Main to use. */ public RMIGenerator() { version = STUB_VERSION_1_2; // default is -v1.2 (see 4638155) } /** * Examine and consume command line arguments. * @param argv The command line arguments. Ignore null * and unknown arguments. Set each consumed argument to null. * @param error Report any errors using the main.error() methods. * @return true if no errors, false otherwise. */ public boolean parseArgs(String argv[], Main main) { String explicitVersion = null; for (int i = 0; i < argv.length; i++) { if (argv[i] != null) { String arg = argv[i].toLowerCase(); if (versionOptions.containsKey(arg)) { if (explicitVersion != null && !explicitVersion.equals(arg)) { main.error("rmic.cannot.use.both", explicitVersion, arg); return false; } explicitVersion = arg; version = ((Integer) versionOptions.get(arg)).intValue(); argv[i] = null; } } } return true; } /** * Generate the source files for the stub and/or skeleton classes * needed by RMI for the given remote implementation class. * * @param env compiler environment * @param cdef definition of remote implementation class * to generate stubs and/or skeletons for * @param destDir directory for the root of the package hierarchy * for generated files */ public void generate(BatchEnvironment env, ClassDefinition cdef, File destDir) { RemoteClass remoteClass = RemoteClass.forClass(env, cdef); if (remoteClass == null) // exit if an error occurred return; RMIGenerator gen; try { gen = new RMIGenerator(env, cdef, destDir, remoteClass, version); } catch (ClassNotFound e) { env.error(0, "rmic.class.not.found", e.name); return; } gen.generate(); } private void generate() { env.addGeneratedFile(stubFile); try { IndentingWriter out = new IndentingWriter( new OutputStreamWriter(new FileOutputStream(stubFile))); writeStub(out); out.close(); if (env.verbose()) { env.output(Main.getText("rmic.wrote", stubFile.getPath())); } env.parseFile(new ClassFile(stubFile)); } catch (IOException e) { env.error(0, "cant.write", stubFile.toString()); return; } if (version == STUB_VERSION_1_1 || version == STUB_VERSION_FAT) { env.addGeneratedFile(skeletonFile); try { IndentingWriter out = new IndentingWriter( new OutputStreamWriter( new FileOutputStream(skeletonFile))); writeSkeleton(out); out.close(); if (env.verbose()) { env.output(Main.getText("rmic.wrote", skeletonFile.getPath())); } env.parseFile(new ClassFile(skeletonFile)); } catch (IOException e) { env.error(0, "cant.write", stubFile.toString()); return; } } else { /* * For bugid 4135136: if skeleton files are not being generated * for this compilation run, delete old skeleton source or class * files for this remote implementation class that were * (presumably) left over from previous runs, to avoid user * confusion from extraneous or inconsistent generated files. */ File outputDir = Util.getOutputDirectoryFor(remoteClassName,destDir,env); File skeletonClassFile = new File(outputDir,skeletonClassName.getName().toString() + ".class"); skeletonFile.delete(); // ignore failures (no big deal) skeletonClassFile.delete(); } } /** * Return the File object that should be used as the source file * for the given Java class, using the supplied destination * directory for the top of the package hierarchy. */ protected static File sourceFileForClass(Identifier className, Identifier outputClassName, File destDir, BatchEnvironment env) { File packageDir = Util.getOutputDirectoryFor(className,destDir,env); String outputName = Names.mangleClass(outputClassName).getName().toString(); // Is there any existing _Tie equivalent leftover from a // previous invocation of rmic -iiop? Only do this once per // class by looking for skeleton generation... if (outputName.endsWith("_Skel")) { String classNameStr = className.getName().toString(); File temp = new File(packageDir, Utility.tieName(classNameStr) + ".class"); if (temp.exists()) { // Found a tie. Is IIOP generation also being done? if (!env.getMain().iiopGeneration) { // No, so write a warning... env.error(0,"warn.rmic.tie.found", classNameStr, temp.getAbsolutePath()); } } } String outputFileName = outputName + ".java"; return new File(packageDir, outputFileName); } /** rmic environment for this object */ private BatchEnvironment env; /** the remote class that this instance is generating code for */ private RemoteClass remoteClass; /** version of the stub protocol to use in code generation */ private int version; /** remote methods for remote class, indexed by operation number */ private RemoteClass.Method[] remoteMethods; /** * Names for the remote class and the stub and skeleton classes * to be generated for it. */ private Identifier remoteClassName; private Identifier stubClassName; private Identifier skeletonClassName; private ClassDefinition cdef; private File destDir; private File stubFile; private File skeletonFile; /** * Names to use for the java.lang.reflect.Method static fields * corresponding to each remote method. */ private String[] methodFieldNames; /** cached definition for certain exception classes in this environment */ private ClassDefinition defException; private ClassDefinition defRemoteException; private ClassDefinition defRuntimeException; /** * Create a new stub/skeleton Generator object for the given * remote implementation class to generate code according to * the given stub protocol version. */ private RMIGenerator(BatchEnvironment env, ClassDefinition cdef, File destDir, RemoteClass remoteClass, int version) throws ClassNotFound { this.destDir = destDir; this.cdef = cdef; this.env = env; this.remoteClass = remoteClass; this.version = version; remoteMethods = remoteClass.getRemoteMethods(); remoteClassName = remoteClass.getName(); stubClassName = Names.stubFor(remoteClassName); skeletonClassName = Names.skeletonFor(remoteClassName); methodFieldNames = nameMethodFields(remoteMethods); stubFile = sourceFileForClass(remoteClassName,stubClassName, destDir , env); skeletonFile = sourceFileForClass(remoteClassName,skeletonClassName, destDir, env); /* * Initialize cached definitions for exception classes used * in the generation process. */ defException = env.getClassDeclaration(idJavaLangException). getClassDefinition(env); defRemoteException = env.getClassDeclaration(idRemoteException). getClassDefinition(env); defRuntimeException = env.getClassDeclaration(idJavaLangRuntimeException). getClassDefinition(env); } /** * Write the stub for the remote class to a stream. */ private void writeStub(IndentingWriter p) throws IOException { /* * Write boiler plate comment. */ p.pln("// Stub class generated by rmic, do not edit."); p.pln("// Contents subject to change without notice."); p.pln(); /* * If remote implementation class was in a particular package, * declare the stub class to be in the same package. */ if (remoteClassName.isQualified()) { p.pln("package " + remoteClassName.getQualifier() + ";"); p.pln(); } /* * Declare the stub class; implement all remote interfaces. */ p.plnI("public final class " + Names.mangleClass(stubClassName.getName())); p.pln("extends " + idRemoteStub); ClassDefinition[] remoteInterfaces = remoteClass.getRemoteInterfaces(); if (remoteInterfaces.length > 0) { p.p("implements "); for (int i = 0; i < remoteInterfaces.length; i++) { if (i > 0) p.p(", "); p.p(remoteInterfaces[i].getName().toString()); } p.pln(); } p.pOlnI("{"); if (version == STUB_VERSION_1_1 || version == STUB_VERSION_FAT) { writeOperationsArray(p); p.pln(); writeInterfaceHash(p); p.pln(); } if (version == STUB_VERSION_FAT || version == STUB_VERSION_1_2) { p.pln("private static final long serialVersionUID = " + STUB_SERIAL_VERSION_UID + ";"); p.pln(); /* * We only need to declare and initialize the static fields of * Method objects for each remote method if there are any remote * methods; otherwise, skip this code entirely, to avoid generating * a try/catch block for a checked exception that cannot occur * (see bugid 4125181). */ if (methodFieldNames.length > 0) { if (version == STUB_VERSION_FAT) { p.pln("private static boolean useNewInvoke;"); } writeMethodFieldDeclarations(p); p.pln(); /* * Initialize java.lang.reflect.Method fields for each remote * method in a static initializer. */ p.plnI("static {"); p.plnI("try {"); if (version == STUB_VERSION_FAT) { /* * Fat stubs must determine whether the API required for * the JDK 1.2 stub protocol is supported in the current * runtime, so that it can use it if supported. This is * determined by using the Reflection API to test if the * new invoke method on RemoteRef exists, and setting the * static boolean "useNewInvoke" to true if it does, or * to false if a NoSuchMethodException is thrown. */ p.plnI(idRemoteRef + ".class.getMethod(\"invoke\","); p.plnI("new java.lang.Class[] {"); p.pln(idRemote + ".class,"); p.pln("java.lang.reflect.Method.class,"); p.pln("java.lang.Object[].class,"); p.pln("long.class"); p.pOln("});"); p.pO(); p.pln("useNewInvoke = true;"); } writeMethodFieldInitializers(p); p.pOlnI("} catch (java.lang.NoSuchMethodException e) {"); if (version == STUB_VERSION_FAT) { p.pln("useNewInvoke = false;"); } else { /* * REMIND: By throwing an Error here, the application will * get the NoSuchMethodError directly when the stub class * is initialized. If we throw a RuntimeException * instead, the application would get an * ExceptionInInitializerError. Would that be more * appropriate, and if so, which RuntimeException should * be thrown? */ p.plnI("throw new java.lang.NoSuchMethodError("); p.pln("\"stub class initialization failed\");"); p.pO(); } p.pOln("}"); // end try/catch block p.pOln("}"); // end static initializer p.pln(); } } writeStubConstructors(p); p.pln(); /* * Write each stub method. */ if (remoteMethods.length > 0) { p.pln("// methods from remote interfaces"); for (int i = 0; i < remoteMethods.length; ++i) { p.pln(); writeStubMethod(p, i); } } p.pOln("}"); // end stub class } /** * Write the constructors for the stub class. */ private void writeStubConstructors(IndentingWriter p) throws IOException { p.pln("// constructors"); /* * Only stubs compatible with the JDK 1.1 stub protocol need * a no-arg constructor; later versions use reflection to find * the constructor that directly takes a RemoteRef argument. */ if (version == STUB_VERSION_1_1 || version == STUB_VERSION_FAT) { p.plnI("public " + Names.mangleClass(stubClassName.getName()) + "() {"); p.pln("super();"); p.pOln("}"); } p.plnI("public " + Names.mangleClass(stubClassName.getName()) + "(" + idRemoteRef + " ref) {"); p.pln("super(ref);"); p.pOln("}"); } /** * Write the stub method for the remote method with the given "opnum". */ private void writeStubMethod(IndentingWriter p, int opnum) throws IOException { RemoteClass.Method method = remoteMethods[opnum]; Identifier methodName = method.getName(); Type methodType = method.getType(); Type paramTypes[] = methodType.getArgumentTypes(); String paramNames[] = nameParameters(paramTypes); Type returnType = methodType.getReturnType(); ClassDeclaration[] exceptions = method.getExceptions(); /* * Declare stub method; throw exceptions declared in remote * interface(s). */ p.pln("// implementation of " + methodType.typeString(methodName.toString(), true, false)); p.p("public " + returnType + " " + methodName + "("); for (int i = 0; i < paramTypes.length; i++) { if (i > 0) p.p(", "); p.p(paramTypes[i] + " " + paramNames[i]); } p.plnI(")"); if (exceptions.length > 0) { p.p("throws "); for (int i = 0; i < exceptions.length; i++) { if (i > 0) p.p(", "); p.p(exceptions[i].getName().toString()); }Lines 1–500 of 1303. Load more
/* * Copyright (c) 1997, 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. */ /*****************************************************************************/ /* Copyright (c) IBM Corporation 1998 */ /* */ /* (C) Copyright IBM Corp. 1998 */ /* */ /*****************************************************************************/ package sun.rmi.rmic; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.IOException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import sun.tools.java.Type; import sun.tools.java.Identifier; import sun.tools.java.ClassDefinition; import sun.tools.java.ClassDeclaration; import sun.tools.java.ClassNotFound; import sun.tools.java.ClassFile; import sun.tools.java.MemberDefinition; import com.sun.corba.se.impl.util.Utility; /** * A Generator object will generate the Java source code of the stub * and skeleton classes for an RMI remote implementation class, using * a particular stub protocol version. * * 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. * * @author Peter Jones, Bryan Atsatt */ public class RMIGenerator implements RMIConstants, Generator { private static final Hashtable versionOptions = new Hashtable(); static { versionOptions.put("-v1.1", new Integer(STUB_VERSION_1_1)); versionOptions.put("-vcompat", new Integer(STUB_VERSION_FAT)); versionOptions.put("-v1.2", new Integer(STUB_VERSION_1_2)); } /** * Default constructor for Main to use. */ public RMIGenerator() { version = STUB_VERSION_1_2; // default is -v1.2 (see 4638155) } /** * Examine and consume command line arguments. * @param argv The command line arguments. Ignore null * and unknown arguments. Set each consumed argument to null. * @param error Report any errors using the main.error() methods. * @return true if no errors, false otherwise. */ public boolean parseArgs(String argv[], Main main) { String explicitVersion = null; for (int i = 0; i < argv.length; i++) { if (argv[i] != null) { String arg = argv[i].toLowerCase(); if (versionOptions.containsKey(arg)) { if (explicitVersion != null && !explicitVersion.equals(arg)) { main.error("rmic.cannot.use.both", explicitVersion, arg); return false; } explicitVersion = arg; version = ((Integer) versionOptions.get(arg)).intValue(); argv[i] = null; } } } return true; } /** * Generate the source files for the stub and/or skeleton classes * needed by RMI for the given remote implementation class. * * @param env compiler environment * @param cdef definition of remote implementation class * to generate stubs and/or skeletons for * @param destDir directory for the root of the package hierarchy * for generated files */ public void generate(BatchEnvironment env, ClassDefinition cdef, File destDir) { RemoteClass remoteClass = RemoteClass.forClass(env, cdef); if (remoteClass == null) // exit if an error occurred return; RMIGenerator gen; try { gen = new RMIGenerator(env, cdef, destDir, remoteClass, version); } catch (ClassNotFound e) { env.error(0, "rmic.class.not.found", e.name); return; } gen.generate(); } private void generate() { env.addGeneratedFile(stubFile); try { IndentingWriter out = new IndentingWriter( new OutputStreamWriter(new FileOutputStream(stubFile))); writeStub(out); out.close(); if (env.verbose()) { env.output(Main.getText("rmic.wrote", stubFile.getPath())); } env.parseFile(new ClassFile(stubFile)); } catch (IOException e) { env.error(0, "cant.write", stubFile.toString()); return; } if (version == STUB_VERSION_1_1 || version == STUB_VERSION_FAT) { env.addGeneratedFile(skeletonFile); try { IndentingWriter out = new IndentingWriter( new OutputStreamWriter( new FileOutputStream(skeletonFile))); writeSkeleton(out); out.close(); if (env.verbose()) { env.output(Main.getText("rmic.wrote", skeletonFile.getPath())); } env.parseFile(new ClassFile(skeletonFile)); } catch (IOException e) { env.error(0, "cant.write", stubFile.toString()); return; } } else { /* * For bugid 4135136: if skeleton files are not being generated * for this compilation run, delete old skeleton source or class * files for this remote implementation class that were * (presumably) left over from previous runs, to avoid user * confusion from extraneous or inconsistent generated files. */ File outputDir = Util.getOutputDirectoryFor(remoteClassName,destDir,env); File skeletonClassFile = new File(outputDir,skeletonClassName.getName().toString() + ".class"); skeletonFile.delete(); // ignore failures (no big deal) skeletonClassFile.delete(); } } /** * Return the File object that should be used as the source file * for the given Java class, using the supplied destination * directory for the top of the package hierarchy. */ protected static File sourceFileForClass(Identifier className, Identifier outputClassName, File destDir, BatchEnvironment env) { File packageDir = Util.getOutputDirectoryFor(className,destDir,env); String outputName = Names.mangleClass(outputClassName).getName().toString(); // Is there any existing _Tie equivalent leftover from a // previous invocation of rmic -iiop? Only do this once per // class by looking for skeleton generation... if (outputName.endsWith("_Skel")) { String classNameStr = className.getName().toString(); File temp = new File(packageDir, Utility.tieName(classNameStr) + ".class"); if (temp.exists()) { // Found a tie. Is IIOP generation also being done? if (!env.getMain().iiopGeneration) { // No, so write a warning... env.error(0,"warn.rmic.tie.found", classNameStr, temp.getAbsolutePath()); } } } String outputFileName = outputName + ".java"; return new File(packageDir, outputFileName); } /** rmic environment for this object */ private BatchEnvironment env; /** the remote class that this instance is generating code for */ private RemoteClass remoteClass; /** version of the stub protocol to use in code generation */ private int version; /** remote methods for remote class, indexed by operation number */ private RemoteClass.Method[] remoteMethods; /** * Names for the remote class and the stub and skeleton classes * to be generated for it. */ private Identifier remoteClassName; private Identifier stubClassName; private Identifier skeletonClassName; private ClassDefinition cdef; private File destDir; private File stubFile; private File skeletonFile; /** * Names to use for the java.lang.reflect.Method static fields * corresponding to each remote method. */ private String[] methodFieldNames; /** cached definition for certain exception classes in this environment */ private ClassDefinition defException; private ClassDefinition defRemoteException; private ClassDefinition defRuntimeException; /** * Create a new stub/skeleton Generator object for the given * remote implementation class to generate code according to * the given stub protocol version. */ private RMIGenerator(BatchEnvironment env, ClassDefinition cdef, File destDir, RemoteClass remoteClass, int version) throws ClassNotFound { this.destDir = destDir; this.cdef = cdef; this.env = env; this.remoteClass = remoteClass; this.version = version; remoteMethods = remoteClass.getRemoteMethods(); remoteClassName = remoteClass.getName(); stubClassName = Names.stubFor(remoteClassName); skeletonClassName = Names.skeletonFor(remoteClassName); methodFieldNames = nameMethodFields(remoteMethods); stubFile = sourceFileForClass(remoteClassName,stubClassName, destDir , env); skeletonFile = sourceFileForClass(remoteClassName,skeletonClassName, destDir, env); /* * Initialize cached definitions for exception classes used * in the generation process. */ defException = env.getClassDeclaration(idJavaLangException). getClassDefinition(env); defRemoteException = env.getClassDeclaration(idRemoteException). getClassDefinition(env); defRuntimeException = env.getClassDeclaration(idJavaLangRuntimeException). getClassDefinition(env); } /** * Write the stub for the remote class to a stream. */ private void writeStub(IndentingWriter p) throws IOException { /* * Write boiler plate comment. */ p.pln("// Stub class generated by rmic, do not edit."); p.pln("// Contents subject to change without notice."); p.pln(); /* * If remote implementation class was in a particular package, * declare the stub class to be in the same package. */ if (remoteClassName.isQualified()) { p.pln("package " + remoteClassName.getQualifier() + ";"); p.pln(); } /* * Declare the stub class; implement all remote interfaces. */ p.plnI("public final class " + Names.mangleClass(stubClassName.getName())); p.pln("extends " + idRemoteStub); ClassDefinition[] remoteInterfaces = remoteClass.getRemoteInterfaces(); if (remoteInterfaces.length > 0) { p.p("implements "); for (int i = 0; i < remoteInterfaces.length; i++) { if (i > 0) p.p(", "); p.p(remoteInterfaces[i].getName().toString()); } p.pln(); } p.pOlnI("{"); if (version == STUB_VERSION_1_1 || version == STUB_VERSION_FAT) { writeOperationsArray(p); p.pln(); writeInterfaceHash(p); p.pln(); } if (version == STUB_VERSION_FAT || version == STUB_VERSION_1_2) { p.pln("private static final long serialVersionUID = " + STUB_SERIAL_VERSION_UID + ";"); p.pln(); /* * We only need to declare and initialize the static fields of * Method objects for each remote method if there are any remote * methods; otherwise, skip this code entirely, to avoid generating * a try/catch block for a checked exception that cannot occur * (see bugid 4125181). */ if (methodFieldNames.length > 0) { if (version == STUB_VERSION_FAT) { p.pln("private static boolean useNewInvoke;"); } writeMethodFieldDeclarations(p); p.pln(); /* * Initialize java.lang.reflect.Method fields for each remote * method in a static initializer. */ p.plnI("static {"); p.plnI("try {"); if (version == STUB_VERSION_FAT) { /* * Fat stubs must determine whether the API required for * the JDK 1.2 stub protocol is supported in the current * runtime, so that it can use it if supported. This is * determined by using the Reflection API to test if the * new invoke method on RemoteRef exists, and setting the * static boolean "useNewInvoke" to true if it does, or * to false if a NoSuchMethodException is thrown. */ p.plnI(idRemoteRef + ".class.getMethod(\"invoke\","); p.plnI("new java.lang.Class[] {"); p.pln(idRemote + ".class,"); p.pln("java.lang.reflect.Method.class,"); p.pln("java.lang.Object[].class,"); p.pln("long.class"); p.pOln("});"); p.pO(); p.pln("useNewInvoke = true;"); } writeMethodFieldInitializers(p); p.pOlnI("} catch (java.lang.NoSuchMethodException e) {"); if (version == STUB_VERSION_FAT) { p.pln("useNewInvoke = false;"); } else { /* * REMIND: By throwing an Error here, the application will * get the NoSuchMethodError directly when the stub class * is initialized. If we throw a RuntimeException * instead, the application would get an * ExceptionInInitializerError. Would that be more * appropriate, and if so, which RuntimeException should * be thrown? */ p.plnI("throw new java.lang.NoSuchMethodError("); p.pln("\"stub class initialization failed\");"); p.pO(); } p.pOln("}"); // end try/catch block p.pOln("}"); // end static initializer p.pln(); } } writeStubConstructors(p); p.pln(); /* * Write each stub method. */ if (remoteMethods.length > 0) { p.pln("// methods from remote interfaces"); for (int i = 0; i < remoteMethods.length; ++i) { p.pln(); writeStubMethod(p, i); } } p.pOln("}"); // end stub class } /** * Write the constructors for the stub class. */ private void writeStubConstructors(IndentingWriter p) throws IOException { p.pln("// constructors"); /* * Only stubs compatible with the JDK 1.1 stub protocol need * a no-arg constructor; later versions use reflection to find * the constructor that directly takes a RemoteRef argument. */ if (version == STUB_VERSION_1_1 || version == STUB_VERSION_FAT) { p.plnI("public " + Names.mangleClass(stubClassName.getName()) + "() {"); p.pln("super();"); p.pOln("}"); } p.plnI("public " + Names.mangleClass(stubClassName.getName()) + "(" + idRemoteRef + " ref) {"); p.pln("super(ref);"); p.pOln("}"); } /** * Write the stub method for the remote method with the given "opnum". */ private void writeStubMethod(IndentingWriter p, int opnum) throws IOException { RemoteClass.Method method = remoteMethods[opnum]; Identifier methodName = method.getName(); Type methodType = method.getType(); Type paramTypes[] = methodType.getArgumentTypes(); String paramNames[] = nameParameters(paramTypes); Type returnType = methodType.getReturnType(); ClassDeclaration[] exceptions = method.getExceptions(); /* * Declare stub method; throw exceptions declared in remote * interface(s). */ p.pln("// implementation of " + methodType.typeString(methodName.toString(), true, false)); p.p("public " + returnType + " " + methodName + "("); for (int i = 0; i < paramTypes.length; i++) { if (i > 0) p.p(", "); p.p(paramTypes[i] + " " + paramNames[i]); } p.plnI(")"); if (exceptions.length > 0) { p.p("throws "); for (int i = 0; i < exceptions.length; i++) { if (i > 0) p.p(", "); p.p(exceptions[i].getName().toString()); }