duke@1: /* msheppar@512: * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@158: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@158: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@158: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@158: * or visit www.oracle.com if you need additional information or have any ohair@158: * questions. duke@1: */ duke@1: duke@1: /* duke@1: * Licensed Materials - Property of IBM duke@1: * RMI-IIOP v1.0 duke@1: * Copyright IBM Corp. 1998 1999 All Rights Reserved duke@1: * duke@1: */ duke@1: duke@1: package sun.rmi.rmic.iiop; duke@1: duke@1: import java.io.File; duke@1: import java.io.IOException; msheppar@512: import java.io.SerializablePermission; msheppar@512: import java.security.AccessController; msheppar@512: import java.security.PrivilegedAction; duke@1: import java.util.Vector; duke@1: import java.util.Hashtable; duke@1: import java.util.Enumeration; duke@1: import sun.tools.java.Identifier; duke@1: import sun.tools.java.ClassNotFound; duke@1: import sun.tools.java.ClassDefinition; duke@1: import sun.tools.java.ClassDeclaration; duke@1: import sun.tools.java.CompilerError; duke@1: import sun.rmi.rmic.IndentingWriter; duke@1: import java.util.HashSet; duke@1: import java.util.Arrays; duke@1: import com.sun.corba.se.impl.util.Utility; duke@1: import com.sun.corba.se.impl.util.PackagePrefixChecker; duke@1: import sun.rmi.rmic.Main; duke@1: msheppar@512: duke@1: /** duke@1: * An IIOP stub/tie generator for rmic. duke@1: * duke@1: * @author Bryan Atsatt duke@1: * @author Anil Vijendran duke@1: * @author M. Mortazavi duke@1: */ duke@1: duke@1: public class StubGenerator extends sun.rmi.rmic.iiop.Generator { duke@1: duke@1: private static final String DEFAULT_STUB_CLASS = "javax.rmi.CORBA.Stub"; duke@1: private static final String DEFAULT_TIE_CLASS = "org.omg.CORBA_2_3.portable.ObjectImpl"; duke@1: private static final String DEFAULT_POA_TIE_CLASS = "org.omg.PortableServer.Servant"; duke@1: duke@1: protected boolean reverseIDs = false; duke@1: protected boolean localStubs = true; duke@1: protected boolean standardPackage = false; duke@1: protected boolean useHash = true; duke@1: protected String stubBaseClass = DEFAULT_STUB_CLASS; duke@1: protected String tieBaseClass = DEFAULT_TIE_CLASS; duke@1: protected HashSet namesInUse = new HashSet(); duke@1: protected Hashtable classesInUse = new Hashtable(); duke@1: protected Hashtable imports = new Hashtable(); duke@1: protected int importCount = 0; duke@1: protected String currentPackage = null; duke@1: protected String currentClass = null; duke@1: protected boolean castArray = false; duke@1: protected Hashtable transactionalObjects = new Hashtable() ; duke@1: protected boolean POATie = false ; msheppar@512: protected boolean emitPermissionCheck = false; duke@1: duke@1: /** duke@1: * Default constructor for Main to use. duke@1: */ duke@1: public StubGenerator() { duke@1: } duke@1: duke@1: /** duke@1: * Overridden in order to set the standardPackage flag. duke@1: */ duke@1: public void generate( duke@1: sun.rmi.rmic.BatchEnvironment env, duke@1: ClassDefinition cdef, File destDir) { duke@1: ((sun.rmi.rmic.iiop.BatchEnvironment)env). duke@1: setStandardPackage(standardPackage); duke@1: super.generate(env, cdef, destDir); duke@1: } duke@1: duke@1: /** duke@1: * Return true if a new instance should be created for each duke@1: * class on the command line. Subclasses which return true duke@1: * should override newInstance() to return an appropriately duke@1: * constructed instance. duke@1: */ duke@1: protected boolean requireNewInstance() { duke@1: return false; duke@1: } duke@1: duke@1: /** duke@1: * Return true if non-conforming types should be parsed. duke@1: * @param stack The context stack. duke@1: */ duke@1: protected boolean parseNonConforming(ContextStack stack) { duke@1: duke@1: // We let the environment setting decide so that duke@1: // another generator (e.g. IDLGenerator) can change duke@1: // it and we will just go with the flow... duke@1: duke@1: return stack.getEnv().getParseNonConforming(); duke@1: } duke@1: duke@1: /** duke@1: * Create and return a top-level type. duke@1: * @param cdef The top-level class definition. duke@1: * @param stack The context stack. duke@1: * @return The compound type or null if is non-conforming. duke@1: */ duke@1: protected CompoundType getTopType(ClassDefinition cdef, ContextStack stack) { duke@1: duke@1: CompoundType result = null; duke@1: duke@1: // Do we have an interface? duke@1: duke@1: if (cdef.isInterface()) { duke@1: duke@1: // Yes, so first try Abstract... duke@1: duke@1: result = AbstractType.forAbstract(cdef,stack,true); duke@1: duke@1: if (result == null) { duke@1: duke@1: // Then try Remote... duke@1: duke@1: result = RemoteType.forRemote(cdef,stack,false); duke@1: } duke@1: } else { duke@1: duke@1: // Not an interface, so try Implementation... duke@1: duke@1: result = ImplementationType.forImplementation(cdef,stack,false); duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Examine and consume command line arguments. duke@1: * @param argv The command line arguments. Ignore null duke@1: * and unknown arguments. Set each consumed argument to null. duke@1: * @param error Report any errors using the main.error() methods. duke@1: * @return true if no errors, false otherwise. duke@1: */ duke@1: public boolean parseArgs(String argv[], Main main) { duke@1: Object marker = new Object() ; duke@1: duke@1: // Reset any cached options... duke@1: duke@1: reverseIDs = false; duke@1: localStubs = true; duke@1: useHash = true; duke@1: stubBaseClass = DEFAULT_STUB_CLASS; duke@1: // tieBaseClass = DEFAULT_TIE_CLASS; duke@1: transactionalObjects = new Hashtable() ; duke@1: duke@1: // Parse options... duke@1: duke@1: boolean result = super.parseArgs(argv,main); duke@1: if (result) { duke@1: for (int i = 0; i < argv.length; i++) { duke@1: if (argv[i] != null) { duke@1: String arg = argv[i].toLowerCase(); duke@1: if (arg.equals("-iiop")) { duke@1: argv[i] = null; duke@1: } else if (arg.equals("-xreverseids")) { duke@1: reverseIDs = true; duke@1: argv[i] = null; duke@1: } else if (arg.equals("-nolocalstubs")) { duke@1: localStubs = false; duke@1: argv[i] = null; duke@1: } else if (arg.equals("-xnohash")) { duke@1: useHash = false; duke@1: argv[i] = null; duke@1: } else if (argv[i].equals("-standardPackage")) { duke@1: standardPackage = true; duke@1: argv[i] = null; msheppar@512: } else if (argv[i].equals("-emitPermissionCheck")) { msheppar@512: emitPermissionCheck = true; msheppar@512: argv[i] = null; duke@1: } else if (arg.equals("-xstubbase")) { duke@1: argv[i] = null; duke@1: if (++i < argv.length && argv[i] != null && !argv[i].startsWith("-")) { duke@1: stubBaseClass = argv[i]; duke@1: argv[i] = null; duke@1: } else { duke@1: main.error("rmic.option.requires.argument", "-Xstubbase"); duke@1: result = false; duke@1: } duke@1: } else if (arg.equals("-xtiebase")) { duke@1: argv[i] = null; duke@1: if (++i < argv.length && argv[i] != null && !argv[i].startsWith("-")) { duke@1: tieBaseClass = argv[i]; duke@1: argv[i] = null; duke@1: } else { duke@1: main.error("rmic.option.requires.argument", "-Xtiebase"); duke@1: result = false; duke@1: } duke@1: } else if (arg.equals("-transactional" )) { duke@1: // Scan for the next non-flag argument. duke@1: // Assume that it is a class name and add it duke@1: // to the list of transactional classes. duke@1: for ( int ctr=i+1; ctr 0) { duke@1: for(int i = 0; i < remoteInterfaces.length; i++) { duke@1: if (i > 0) { duke@1: p.pln(","); duke@1: } duke@1: String objName = testUtil(getName(remoteInterfaces[i]), theType); duke@1: p.p(objName); duke@1: } duke@1: } duke@1: duke@1: // Add java.rmi.Remote if this type does not implement it. duke@1: // This allows stubs for Abstract interfaces to be treated duke@1: // uniformly... duke@1: duke@1: if (!implementsRemote(theType)) { duke@1: p.pln(","); duke@1: p.p(getName("java.rmi.Remote")); duke@1: } duke@1: duke@1: p.plnI(" {"); duke@1: p.pln(); duke@1: duke@1: // Write the ids... duke@1: duke@1: writeIds( p, theType, false ); duke@1: p.pln(); duke@1: msheppar@512: if (emitPermissionCheck) { msheppar@512: msheppar@512: // produce the following generated code for example msheppar@512: // private static Void checkPermission() { msheppar@512: // SecurityManager sm = System.getSecurityManager(); msheppar@512: // if (sm != null) { msheppar@512: // sm.checkPermission(new SerializablePermission( msheppar@512: // "enableSubclassImplementation")); // testing msheppar@512: // } msheppar@512: // return null; msheppar@512: // } msheppar@512: // msheppar@512: // private _XXXXX_Stub(Void ignore) { msheppar@512: // } msheppar@512: // msheppar@512: // public _XXXXX_Stub() { msheppar@512: // this(checkPermission()); msheppar@512: // } msheppar@512: // msheppar@512: // where XXXXX is the name of the remote interface msheppar@512: msheppar@512: p.pln(); msheppar@512: p.plnI("private static Void checkPermission() {"); msheppar@512: p.plnI("SecurityManager sm = System.getSecurityManager();"); msheppar@512: p.pln("if (sm != null) {"); msheppar@512: p.pI(); msheppar@512: p.plnI("sm.checkPermission(new SerializablePermission("); msheppar@512: p.plnI("\"enableSubclassImplementation\"));"); msheppar@512: p.pO(); msheppar@512: p.pO(); msheppar@512: p.pOln("}"); msheppar@512: p.pln("return null;"); msheppar@512: p.pO(); msheppar@512: p.pOln("}"); msheppar@512: p.pln(); msheppar@512: p.pO(); msheppar@512: msheppar@512: p.pI(); msheppar@512: p.pln("private " + currentClass + "(Void ignore) { }"); msheppar@512: p.pln(); msheppar@512: msheppar@512: p.plnI("public " + currentClass + "() { "); msheppar@512: p.pln("this(checkPermission());"); msheppar@512: p.pOln("}"); msheppar@512: p.pln(); msheppar@512: } msheppar@512: msheppar@512: if (!emitPermissionCheck) { msheppar@512: p.pI(); msheppar@512: } msheppar@512: duke@1: // Write the _ids() method... duke@1: duke@1: p.plnI("public String[] _ids() { "); coffeys@370: p.pln("return (String[]) _type_ids.clone();"); duke@1: p.pOln("}"); duke@1: duke@1: // Get all the methods and write each stub method... duke@1: duke@1: CompoundType.Method[] remoteMethods = theType.getMethods(); duke@1: int methodCount = remoteMethods.length; duke@1: if (methodCount > 0) { duke@1: boolean writeHeader = true; duke@1: for(int i = 0; i < methodCount; i++) { duke@1: if (!remoteMethods[i].isConstructor()) { duke@1: if (writeHeader) { duke@1: writeHeader = false; duke@1: } duke@1: p.pln(); duke@1: writeStubMethod(p, remoteMethods[i], theType); duke@1: } duke@1: } duke@1: } duke@1: duke@1: // Write the cast array hack... duke@1: duke@1: writeCastArray(p); duke@1: duke@1: p.pOln("}"); // end stub class duke@1: } duke@1: duke@1: void addClassInUse(String qualifiedName) { duke@1: String unqualifiedName = qualifiedName; duke@1: String packageName = null; duke@1: int index = qualifiedName.lastIndexOf('.'); duke@1: if (index > 0) { duke@1: unqualifiedName = qualifiedName.substring(index+1); duke@1: packageName = qualifiedName.substring(0,index); duke@1: } duke@1: addClassInUse(unqualifiedName,qualifiedName,packageName); duke@1: } duke@1: duke@1: void addClassInUse(Type type) { duke@1: if (!type.isPrimitive()) { duke@1: Identifier id = type.getIdentifier(); duke@1: String name = IDLNames.replace(id.getName().toString(),". ","."); duke@1: String packageName = type.getPackageName(); duke@1: String qualifiedName; duke@1: if (packageName != null) { duke@1: qualifiedName = packageName+"."+name; duke@1: } else { duke@1: qualifiedName = name; duke@1: } duke@1: addClassInUse(name,qualifiedName,packageName); duke@1: } duke@1: } duke@1: duke@1: void addClassInUse(Type[] types) { duke@1: for (int i = 0; i < types.length; i++) { duke@1: addClassInUse(types[i]); duke@1: } duke@1: } duke@1: duke@1: void addStubInUse(Type type) { duke@1: if (type.getIdentifier() != idCorbaObject && duke@1: type.isType(TYPE_CORBA_OBJECT)) { duke@1: String stubName = getStubNameFor(type,false); duke@1: String packageName = type.getPackageName(); duke@1: String fullName; duke@1: if (packageName == null) { duke@1: fullName = stubName; duke@1: } else { duke@1: fullName = packageName + "." + stubName; duke@1: } duke@1: addClassInUse(stubName,fullName,packageName); duke@1: } duke@1: if (type.isType(TYPE_REMOTE) || duke@1: type.isType(TYPE_JAVA_RMI_REMOTE)) { duke@1: addClassInUse("javax.rmi.PortableRemoteObject"); duke@1: } duke@1: } duke@1: duke@1: String getStubNameFor(Type type, boolean qualified) { duke@1: String stubName; duke@1: String className; duke@1: if (qualified) { duke@1: className = type.getQualifiedName(); duke@1: } else { duke@1: className = type.getName(); duke@1: } duke@1: if (((CompoundType)type).isCORBAObject()) { duke@1: stubName = Utility.idlStubName(className); duke@1: } else { duke@1: stubName = Utility.stubNameForCompiler(className); duke@1: } duke@1: return stubName; duke@1: } duke@1: duke@1: void addStubInUse(Type[] types) { duke@1: for (int i = 0; i < types.length; i++) { duke@1: addStubInUse(types[i]); duke@1: } duke@1: } duke@1: duke@1: private static final String NO_IMPORT = new String(); duke@1: duke@1: void addClassInUse(String unqualifiedName, String qualifiedName, String packageName) { duke@1: duke@1: // Have we already got an entry for this qualifiedName? duke@1: duke@1: String currentName = (String)classesInUse.get(qualifiedName); duke@1: duke@1: if (currentName == null) { duke@1: duke@1: // No, never seen it before. Grab any existing import duke@1: // name and then decide what to do... duke@1: duke@1: String importName = (String) imports.get(unqualifiedName); duke@1: String nameToUse = null; duke@1: duke@1: if (packageName == null) { duke@1: duke@1: // Default package, so doesn't matter which name to use... duke@1: duke@1: nameToUse = unqualifiedName; duke@1: duke@1: } else if (packageName.equals("java.lang")) { duke@1: duke@1: // java.lang.*, so use unqualified name... duke@1: duke@1: nameToUse = unqualifiedName; duke@1: duke@1: // unless you want to be able to import things from the right place :--) duke@1: duke@1: if(nameToUse.endsWith("_Stub")) nameToUse = Util.packagePrefix()+qualifiedName; duke@1: duke@1: } else if (currentPackage != null && packageName.equals(currentPackage)) { duke@1: duke@1: // Class in currentPackage, so use unqualified name... duke@1: duke@1: nameToUse = unqualifiedName; duke@1: duke@1: // Do we already have a previous import under this duke@1: // unqualified name? duke@1: duke@1: if (importName != null) { duke@1: duke@1: // Yes, so we use qualifiedName... duke@1: duke@1: nameToUse = qualifiedName; duke@1: duke@1: } duke@1: duke@1: } else if (importName != null) { duke@1: duke@1: // It is in some package for which we normally duke@1: // would import, but we have a previous import duke@1: // under this unqualified name. We must use duke@1: // the qualified name... duke@1: duke@1: nameToUse = qualifiedName; duke@1: duke@1: /* duke@1: // Is the currentPackage the default package? duke@1: duke@1: if (currentPackage == null) { duke@1: duke@1: // Yes, so undo the import so that all duke@1: // uses for this name will be qualified... duke@1: duke@1: String old = (String)imports.remove(unqualifiedName); duke@1: classesInUse.put(old,old); duke@1: importCount--; duke@1: duke@1: // Note that this name is in use but should duke@1: // not be imported... duke@1: duke@1: imports.put(nameToUse,NO_IMPORT); duke@1: } duke@1: */ duke@1: } else if (qualifiedName.equals("org.omg.CORBA.Object")) { duke@1: duke@1: // Always qualify this quy to avoid confusion... duke@1: duke@1: nameToUse = qualifiedName; duke@1: duke@1: } else { duke@1: duke@1: // Default to using unqualified name, and add duke@1: // this guy to the imports... duke@1: duke@1: // Check for nested class in which case we use duke@1: // the fully qualified name instead of imports duke@1: if (unqualifiedName.indexOf('.') != -1) { duke@1: nameToUse = qualifiedName; duke@1: } else { duke@1: nameToUse = unqualifiedName; duke@1: imports.put(unqualifiedName,qualifiedName); duke@1: importCount++; duke@1: } duke@1: } duke@1: duke@1: // Now add the name... duke@1: duke@1: classesInUse.put(qualifiedName,nameToUse); duke@1: } duke@1: } duke@1: duke@1: String getName(Type type) { duke@1: if (type.isPrimitive()) { duke@1: return type.getName() + type.getArrayBrackets(); duke@1: } duke@1: Identifier id = type.getIdentifier(); duke@1: String name = IDLNames.replace(id.toString(),". ","."); duke@1: return getName(name) + type.getArrayBrackets(); duke@1: } duke@1: duke@1: // Added for Bug 4818753 duke@1: String getExceptionName(Type type) { duke@1: Identifier id = type.getIdentifier(); duke@1: return IDLNames.replace(id.toString(),". ","."); duke@1: } duke@1: duke@1: String getName(String qualifiedName) { duke@1: return (String)classesInUse.get(qualifiedName); duke@1: } duke@1: duke@1: String getName(Identifier id) { duke@1: return getName(id.toString()); duke@1: } duke@1: duke@1: String getStubName(Type type) { duke@1: String stubName = getStubNameFor(type,true); duke@1: return getName(stubName); duke@1: } duke@1: duke@1: void setStandardClassesInUse(CompoundType type, duke@1: boolean stub) throws IOException { duke@1: duke@1: // Reset our state... duke@1: duke@1: currentPackage = type.getPackageName(); duke@1: imports.clear(); duke@1: classesInUse.clear(); duke@1: namesInUse.clear(); duke@1: importCount = 0; duke@1: castArray = false; duke@1: duke@1: // Add the top-level type... duke@1: duke@1: addClassInUse(type); duke@1: duke@1: // Set current class name... duke@1: duke@1: if (stub) { duke@1: currentClass = Utility.stubNameForCompiler(type.getName()); duke@1: } else { duke@1: currentClass = Utility.tieNameForCompiler(type.getName()); duke@1: } duke@1: duke@1: // Add current class... duke@1: duke@1: if (currentPackage == null) { duke@1: addClassInUse(currentClass,currentClass,currentPackage); duke@1: } else { duke@1: addClassInUse(currentClass,(currentPackage+"."+currentClass),currentPackage); duke@1: } duke@1: duke@1: // Add standard classes... duke@1: duke@1: addClassInUse("javax.rmi.CORBA.Util"); duke@1: addClassInUse(idRemote.toString()); duke@1: addClassInUse(idRemoteException.toString()); duke@1: addClassInUse(idOutputStream.toString()); duke@1: addClassInUse(idInputStream.toString()); duke@1: addClassInUse(idSystemException.toString()); duke@1: addClassInUse(idJavaIoSerializable.toString()); duke@1: addClassInUse(idCorbaORB.toString()); duke@1: addClassInUse(idReplyHandler.toString()); duke@1: duke@1: // Add stub/tie specific imports... duke@1: duke@1: if (stub) { duke@1: addClassInUse(stubBaseClass); duke@1: addClassInUse("java.rmi.UnexpectedException"); duke@1: addClassInUse(idRemarshalException.toString()); duke@1: addClassInUse(idApplicationException.toString()); duke@1: if (localStubs) { duke@1: addClassInUse("org.omg.CORBA.portable.ServantObject"); duke@1: } duke@1: } else { duke@1: addClassInUse(type); duke@1: addClassInUse(tieBaseClass); duke@1: addClassInUse(idTieInterface.toString()); duke@1: addClassInUse(idBadMethodException.toString()); duke@1: addClassInUse(idPortableUnknownException.toString()); duke@1: addClassInUse(idJavaLangThrowable.toString()); duke@1: } duke@1: } duke@1: duke@1: void addClassesInUse(CompoundType type, RemoteType[] interfaces) { duke@1: duke@1: // Walk all methods and add types in use... duke@1: duke@1: CompoundType.Method[] methods = type.getMethods(); duke@1: for (int i = 0; i < methods.length; i++) { duke@1: addClassInUse(methods[i].getReturnType()); duke@1: addStubInUse(methods[i].getReturnType()); duke@1: addClassInUse(methods[i].getArguments()); duke@1: addStubInUse(methods[i].getArguments()); duke@1: addClassInUse(methods[i].getExceptions()); duke@1: // bug 4473859: Also include narrower subtypes for use duke@1: addClassInUse(methods[i].getImplExceptions()); duke@1: } duke@1: duke@1: // If this is a stub, add all interfaces... duke@1: duke@1: if (interfaces != null) { duke@1: addClassInUse(interfaces); duke@1: } duke@1: } duke@1: duke@1: void writePackageAndImports(IndentingWriter p) throws IOException { duke@1: duke@1: // Write package declaration... duke@1: duke@1: if (currentPackage != null) { duke@1: p.pln("package " + duke@1: Util.correctPackageName( duke@1: currentPackage, false, standardPackage) duke@1: + ";"); duke@1: p.pln(); duke@1: } duke@1: duke@1: // Get imports into an array and sort them... duke@1: duke@1: String[] names = new String[importCount]; duke@1: int index = 0; duke@1: for (Enumeration e = imports.elements() ; e.hasMoreElements() ;) { duke@1: String it = (String) e.nextElement(); duke@1: if (it != NO_IMPORT) { duke@1: names[index++] = it; duke@1: } duke@1: } duke@1: duke@1: Arrays.sort(names,new StringComparator()); duke@1: duke@1: // Now dump them out... duke@1: duke@1: for (int i = 0; i < importCount; i++) { duke@1: if( duke@1: Util.isOffendingPackage(names[i]) duke@1: && names[i].endsWith("_Stub") duke@1: && String.valueOf(names[i].charAt(names[i].lastIndexOf(".")+1)).equals("_") duke@1: ){ duke@1: p.pln("import " + PackagePrefixChecker.packagePrefix()+names[i]+";"); duke@1: } else{ duke@1: p.pln("import " + names[i] + ";"); duke@1: } duke@1: } duke@1: p.pln(); duke@1: duke@1: // Include offending packages . . . duke@1: if ( currentPackage!=null && Util.isOffendingPackage(currentPackage) ){ duke@1: p.pln("import " + currentPackage +".* ;"); duke@1: } duke@1: p.pln(); duke@1: duke@1: } duke@1: duke@1: boolean implementsRemote(CompoundType theType) { duke@1: boolean result = theType.isType(TYPE_REMOTE) && !theType.isType(TYPE_ABSTRACT); duke@1: duke@1: // If theType is not remote, look at all the interfaces duke@1: // until we find one that is... duke@1: duke@1: if (!result) { duke@1: InterfaceType[] interfaces = theType.getInterfaces(); duke@1: for (int i = 0; i < interfaces.length; i++) { duke@1: result = implementsRemote(interfaces[i]); duke@1: if (result) { duke@1: break; duke@1: } duke@1: } duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: void writeStubMethod ( IndentingWriter p, duke@1: CompoundType.Method method, duke@1: CompoundType theType) throws IOException { duke@1: duke@1: // Wtite the method declaration and opening brace... duke@1: String methodName = method.getName(); duke@1: String methodIDLName = method.getIDLName(); duke@1: duke@1: Type paramTypes[] = method.getArguments(); duke@1: String paramNames[] = method.getArgumentNames(); duke@1: Type returnType = method.getReturnType(); duke@1: ValueType[] exceptions = getStubExceptions(method,false); duke@1: duke@1: addNamesInUse(method); duke@1: addNameInUse("_type_ids"); duke@1: duke@1: String objName = testUtil(getName(returnType), returnType); duke@1: p.p("public " + objName + " " + methodName + "("); duke@1: for(int i = 0; i < paramTypes.length; i++) { duke@1: if (i > 0) duke@1: p.p(", "); duke@1: p.p(getName(paramTypes[i]) + " " + paramNames[i]); duke@1: } duke@1: duke@1: p.p(")"); duke@1: if (exceptions.length > 0) { duke@1: p.p(" throws "); duke@1: for(int i = 0; i < exceptions.length; i++) { duke@1: if (i > 0) { duke@1: p.p(", "); duke@1: } duke@1: // Added for Bug 4818753 duke@1: p.p(getExceptionName(exceptions[i])); duke@1: } duke@1: } duke@1: duke@1: p.plnI(" {"); duke@1: duke@1: // Now create the method body... duke@1: duke@1: if (localStubs) { duke@1: writeLocalStubMethodBody(p,method,theType); duke@1: } else { duke@1: writeNonLocalStubMethodBody(p,method,theType); duke@1: } duke@1: duke@1: // Close out the method... duke@1: duke@1: p.pOln("}"); duke@1: } duke@1: duke@1: duke@1: void writeLocalStubMethodBody (IndentingWriter p, duke@1: CompoundType.Method method, duke@1: CompoundType theType) throws IOException { duke@1: duke@1: String objName; duke@1: String paramNames[] = method.getArgumentNames(); duke@1: Type returnType = method.getReturnType(); duke@1: ValueType[] exceptions = getStubExceptions(method,false); duke@1: String methodName = method.getName(); duke@1: String methodIDLName = method.getIDLName(); duke@1: duke@1: p.plnI("if (!Util.isLocal(this)) {"); duke@1: writeNonLocalStubMethodBody(p,method,theType); duke@1: p.pOlnI("} else {"); duke@1: String so = getVariableName("so"); duke@1: duke@1: p.pln("ServantObject "+so+" = _servant_preinvoke(\""+methodIDLName+"\","+getName(theType)+".class);"); duke@1: p.plnI("if ("+so+" == null) {"); duke@1: if (!returnType.isType(TYPE_VOID)) { duke@1: p.p("return "); duke@1: } duke@1: p.p(methodName+"("); duke@1: for (int i = 0; i < paramNames.length; i++) { duke@1: if (i > 0) duke@1: p.p(", "); duke@1: p.p(paramNames[i]); duke@1: } duke@1: p.pln(");"); duke@1: if (returnType.isType(TYPE_VOID)) { duke@1: p.pln( "return ;" ) ; duke@1: } duke@1: duke@1: p.pOln("}"); duke@1: p.plnI("try {"); duke@1: duke@1: // Generate code to copy required arguments, and duke@1: // get back the names by which all arguments are known... duke@1: duke@1: String[] argNames = writeCopyArguments(method,p); duke@1: duke@1: // Now write the method... duke@1: duke@1: boolean copyReturn = mustCopy(returnType); duke@1: String resultName = null; duke@1: if (!returnType.isType(TYPE_VOID)) { duke@1: if (copyReturn) { duke@1: resultName = getVariableName("result"); duke@1: objName = testUtil(getName(returnType), returnType); duke@1: p.p(objName+" "+resultName + " = "); duke@1: } else { duke@1: p.p("return "); duke@1: } duke@1: } duke@1: objName = testUtil(getName(theType), theType); duke@1: p.p("(("+objName+")"+so+".servant)."+methodName+"("); duke@1: duke@1: for (int i = 0; i < argNames.length; i++) { duke@1: if (i > 0) duke@1: p.p(", "); duke@1: p.p(argNames[i]); duke@1: } duke@1: duke@1: if (copyReturn) { duke@1: p.pln(");"); duke@1: objName = testUtil(getName(returnType), returnType); duke@1: p.pln("return ("+objName+")Util.copyObject("+resultName+",_orb());"); duke@1: } else { duke@1: p.pln(");"); duke@1: } duke@1: duke@1: String e1 = getVariableName("ex"); duke@1: String e2 = getVariableName("exCopy"); duke@1: p.pOlnI("} catch (Throwable "+e1+") {"); duke@1: duke@1: p.pln("Throwable "+e2+" = (Throwable)Util.copyObject("+e1+",_orb());"); duke@1: for(int i = 0; i < exceptions.length; i++) { duke@1: if (exceptions[i].getIdentifier() != idRemoteException && duke@1: exceptions[i].isType(TYPE_VALUE)) { duke@1: // Added for Bug 4818753 duke@1: p.plnI("if ("+e2+" instanceof "+getExceptionName(exceptions[i])+") {"); duke@1: p.pln("throw ("+getExceptionName(exceptions[i])+")"+e2+";"); duke@1: p.pOln("}"); duke@1: } duke@1: } duke@1: duke@1: p.pln("throw Util.wrapException("+e2+");"); duke@1: p.pOlnI("} finally {"); duke@1: p.pln("_servant_postinvoke("+so+");"); duke@1: p.pOln("}"); duke@1: p.pOln("}"); duke@1: } duke@1: duke@1: duke@1: void writeNonLocalStubMethodBody ( IndentingWriter p, duke@1: CompoundType.Method method, duke@1: CompoundType theType) throws IOException { duke@1: duke@1: String methodName = method.getName(); duke@1: String methodIDLName = method.getIDLName(); duke@1: duke@1: Type paramTypes[] = method.getArguments(); duke@1: String paramNames[] = method.getArgumentNames(); duke@1: Type returnType = method.getReturnType(); duke@1: ValueType[] exceptions = getStubExceptions(method,true); duke@1: duke@1: String in = getVariableName("in"); duke@1: String out = getVariableName("out"); duke@1: String ex = getVariableName("ex"); duke@1: duke@1: // Decide if we need to use the new streams for duke@1: // any of the read calls... duke@1: duke@1: boolean needNewReadStreamClass = false; duke@1: for (int i = 0; i < exceptions.length; i++) { duke@1: if (exceptions[i].getIdentifier() != idRemoteException && duke@1: exceptions[i].isType(TYPE_VALUE) && duke@1: needNewReadStreamClass(exceptions[i])) { duke@1: needNewReadStreamClass = true; duke@1: break; duke@1: } duke@1: } duke@1: if (!needNewReadStreamClass) { duke@1: for (int i = 0; i < paramTypes.length; i++) { duke@1: if (needNewReadStreamClass(paramTypes[i])) { duke@1: needNewReadStreamClass = true; duke@1: break; duke@1: } duke@1: } duke@1: } duke@1: if (!needNewReadStreamClass) { duke@1: needNewReadStreamClass = needNewReadStreamClass(returnType); duke@1: } duke@1: duke@1: // Decide if we need to use the new streams for duke@1: // any of the write calls... duke@1: duke@1: boolean needNewWriteStreamClass = false; duke@1: for (int i = 0; i < paramTypes.length; i++) { duke@1: if (needNewWriteStreamClass(paramTypes[i])) { duke@1: needNewWriteStreamClass = true; duke@1: break; duke@1: } duke@1: } duke@1: duke@1: // Now write the method, inserting casts where needed... duke@1: duke@1: p.plnI("try {"); duke@1: if (needNewReadStreamClass) { duke@1: p.pln(idExtInputStream + " "+in+" = null;"); duke@1: } else { duke@1: p.pln(idInputStream + " "+in+" = null;"); duke@1: } duke@1: p.plnI("try {"); duke@1: duke@1: String argStream = "null"; duke@1: duke@1: if (needNewWriteStreamClass) { duke@1: p.plnI(idExtOutputStream + " "+out+" = "); duke@1: p.pln("(" + idExtOutputStream + ")"); duke@1: p.pln("_request(\"" + methodIDLName + "\", true);"); duke@1: p.pO(); duke@1: } else { duke@1: p.pln("OutputStream "+out+" = _request(\"" + methodIDLName + "\", true);"); duke@1: } duke@1: duke@1: if (paramTypes.length > 0) { duke@1: writeMarshalArguments(p, out, paramTypes, paramNames); duke@1: p.pln(); duke@1: } duke@1: argStream = out; duke@1: duke@1: if (returnType.isType(TYPE_VOID)) { duke@1: p.pln("_invoke(" + argStream + ");" ); duke@1: } else { duke@1: if (needNewReadStreamClass) { duke@1: p.plnI(in+" = (" + idExtInputStream + ")_invoke(" + argStream + ");"); duke@1: p.pO(); duke@1: } else { duke@1: p.pln(in+" = _invoke(" + argStream + ");"); duke@1: } duke@1: p.p("return "); duke@1: writeUnmarshalArgument(p, in, returnType, null); duke@1: p.pln(); duke@1: } duke@1: duke@1: // Handle ApplicationException... duke@1: duke@1: p.pOlnI("} catch ("+getName(idApplicationException)+" "+ex+") {"); duke@1: if (needNewReadStreamClass) { duke@1: p.pln(in + " = (" + idExtInputStream + ") "+ex+".getInputStream();"); duke@1: } else { duke@1: p.pln(in + " = "+ex+".getInputStream();"); duke@1: } duke@1: duke@1: boolean idRead = false; duke@1: boolean idAllocated = false; duke@1: for(int i = 0; i < exceptions.length; i++) { duke@1: if (exceptions[i].getIdentifier() != idRemoteException) { duke@1: duke@1: // Is this our special-case IDLEntity exception? duke@1: duke@1: if (exceptions[i].isIDLEntityException() && !exceptions[i].isCORBAUserException()) { duke@1: duke@1: // Yes. duke@1: duke@1: if (!idAllocated && !idRead) { duke@1: p.pln("String $_id = "+ex+".getId();"); duke@1: idAllocated = true; duke@1: } duke@1: duke@1: String helperName = IDLNames.replace(exceptions[i].getQualifiedIDLName(false),"::","."); duke@1: helperName += "Helper"; duke@1: p.plnI("if ($_id.equals("+helperName+".id())) {"); duke@1: p.pln("throw "+helperName+".read("+in+");"); duke@1: duke@1: } else { duke@1: duke@1: // No. duke@1: duke@1: if (!idAllocated && !idRead) { duke@1: p.pln("String $_id = "+in+".read_string();"); duke@1: idAllocated = true; duke@1: idRead = true; duke@1: } else if (idAllocated && !idRead) { duke@1: p.pln("$_id = "+in+".read_string();"); duke@1: idRead = true; duke@1: } duke@1: p.plnI("if ($_id.equals(\""+getExceptionRepositoryID(exceptions[i])+"\")) {"); duke@1: // Added for Bug 4818753 duke@1: p.pln("throw ("+getExceptionName(exceptions[i])+") "+in+".read_value(" + getExceptionName(exceptions[i]) + ".class);"); duke@1: } duke@1: p.pOln("}"); duke@1: } duke@1: } duke@1: if (!idAllocated && !idRead) { duke@1: p.pln("String $_id = "+in+".read_string();"); duke@1: idAllocated = true; duke@1: idRead = true; duke@1: } else if (idAllocated && !idRead) { duke@1: p.pln("$_id = "+in+".read_string();"); duke@1: idRead = true; duke@1: } duke@1: p.pln("throw new UnexpectedException($_id);"); duke@1: duke@1: // Handle RemarshalException... duke@1: duke@1: p.pOlnI("} catch ("+getName(idRemarshalException)+" "+ex+") {"); duke@1: if (!returnType.isType(TYPE_VOID)) { duke@1: p.p("return "); duke@1: } duke@1: p.p(methodName + "("); duke@1: for(int i = 0; i < paramTypes.length; i++) { duke@1: if (i > 0) { duke@1: p.p(","); duke@1: } duke@1: p.p(paramNames[i]); duke@1: } duke@1: p.pln(");"); duke@1: duke@1: // Ensure that we release the reply... duke@1: duke@1: p.pOlnI("} finally {"); duke@1: p.pln("_releaseReply("+in+");"); duke@1: duke@1: p.pOln("}"); duke@1: duke@1: // Handle SystemException... duke@1: duke@1: p.pOlnI("} catch (SystemException "+ex+") {"); duke@1: p.pln("throw Util.mapSystemException("+ex+");"); duke@1: p.pOln("}"); duke@1: duke@1: // returnResult(p,returnType); duke@1: } duke@1: duke@1: void allocateResult (IndentingWriter p, duke@1: Type returnType) throws IOException { duke@1: if (!returnType.isType(TYPE_VOID)) { duke@1: String objName = testUtil(getName(returnType), returnType); duke@1: p.p(objName + " result = "); duke@1: } duke@1: } duke@1: duke@1: int getTypeCode(Type type) { duke@1: duke@1: int typeCode = type.getTypeCode(); duke@1: duke@1: // Handle late-breaking special case for duke@1: // abstract IDL entities... duke@1: duke@1: if ((type instanceof CompoundType) && duke@1: ((CompoundType)type).isAbstractBase()) { duke@1: typeCode = TYPE_ABSTRACT; duke@1: } duke@1: duke@1: return typeCode; duke@1: } duke@1: duke@1: duke@1: /** duke@1: * Write a snippet of Java code to marshal a value named "name" of duke@1: * type "type" to the java.io.ObjectOutput stream named "stream". duke@1: */ duke@1: void writeMarshalArgument(IndentingWriter p, duke@1: String streamName, duke@1: Type type, String name) throws IOException { duke@1: duke@1: int typeCode = getTypeCode(type); duke@1: duke@1: switch (typeCode) { duke@1: case TYPE_BOOLEAN: duke@1: p.p(streamName + ".write_boolean(" + name + ");"); duke@1: break; duke@1: case TYPE_BYTE: duke@1: p.p(streamName + ".write_octet(" + name + ");"); duke@1: break; duke@1: case TYPE_CHAR: duke@1: p.p(streamName + ".write_wchar(" + name + ");"); duke@1: break; duke@1: case TYPE_SHORT: duke@1: p.p(streamName + ".write_short(" + name + ");"); duke@1: break; duke@1: case TYPE_INT: duke@1: p.p(streamName + ".write_long(" + name + ");"); duke@1: break; duke@1: case TYPE_LONG: duke@1: p.p(streamName + ".write_longlong(" + name + ");"); duke@1: break; duke@1: case TYPE_FLOAT: duke@1: p.p(streamName + ".write_float(" + name + ");"); duke@1: break; duke@1: case TYPE_DOUBLE: duke@1: p.p(streamName + ".write_double(" + name + ");"); duke@1: break; duke@1: case TYPE_STRING: duke@1: p.p(streamName + ".write_value(" + name + "," + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_ANY: duke@1: p.p("Util.writeAny("+ streamName + "," + name + ");"); duke@1: break; duke@1: case TYPE_CORBA_OBJECT: duke@1: p.p(streamName + ".write_Object(" + name + ");"); duke@1: break; duke@1: case TYPE_REMOTE: duke@1: p.p("Util.writeRemoteObject("+ streamName + "," + name + ");"); duke@1: break; duke@1: case TYPE_ABSTRACT: duke@1: p.p("Util.writeAbstractObject("+ streamName + "," + name + ");"); duke@1: break; duke@1: case TYPE_NC_INTERFACE: duke@1: p.p(streamName + ".write_value((Serializable)" + name + "," + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_VALUE: duke@1: p.p(streamName + ".write_value(" + name + "," + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_IMPLEMENTATION: duke@1: p.p(streamName + ".write_value((Serializable)" + name + "," + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_NC_CLASS: duke@1: p.p(streamName + ".write_value((Serializable)" + name + "," + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_ARRAY: duke@1: castArray = true; duke@1: p.p(streamName + ".write_value(cast_array(" + name + ")," + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_JAVA_RMI_REMOTE: duke@1: p.p("Util.writeRemoteObject("+ streamName + "," + name + ");"); duke@1: break; duke@1: default: duke@1: throw new Error("unexpected type code: " + typeCode); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Write a snippet of Java code to unmarshal a value of type "type" duke@1: * from the java.io.ObjectInput stream named "stream" into a variable duke@1: * named "name" (if "name" is null, the value in unmarshalled and duke@1: * discarded). duke@1: */ duke@1: void writeUnmarshalArgument(IndentingWriter p, duke@1: String streamName, duke@1: Type type, duke@1: String name) throws IOException { duke@1: duke@1: int typeCode = getTypeCode(type); duke@1: duke@1: if (name != null) { duke@1: p.p(name + " = "); duke@1: } duke@1: duke@1: switch (typeCode) { duke@1: case TYPE_BOOLEAN: duke@1: p.p(streamName + ".read_boolean();"); duke@1: break; duke@1: case TYPE_BYTE: duke@1: p.p(streamName + ".read_octet();"); duke@1: break; duke@1: case TYPE_CHAR: duke@1: p.p(streamName + ".read_wchar();"); duke@1: break; duke@1: case TYPE_SHORT: duke@1: p.p(streamName + ".read_short();"); duke@1: break; duke@1: case TYPE_INT: duke@1: p.p(streamName + ".read_long();"); duke@1: break; duke@1: case TYPE_LONG: duke@1: p.p(streamName + ".read_longlong();"); duke@1: break; duke@1: case TYPE_FLOAT: duke@1: p.p(streamName + ".read_float();"); duke@1: break; duke@1: case TYPE_DOUBLE: duke@1: p.p(streamName + ".read_double();"); duke@1: break; duke@1: case TYPE_STRING: duke@1: p.p("(String) " + streamName + ".read_value(" + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_ANY: duke@1: if (type.getIdentifier() != idJavaLangObject) { duke@1: p.p("(" + getName(type) + ") "); duke@1: } duke@1: p.p("Util.readAny(" + streamName + ");"); duke@1: break; duke@1: case TYPE_CORBA_OBJECT: duke@1: if (type.getIdentifier() == idCorbaObject) { duke@1: p.p("(" + getName(type) + ") " + streamName + ".read_Object();"); duke@1: } else { duke@1: p.p("(" + getName(type) + ") " + streamName + ".read_Object(" + getStubName(type) + ".class);"); duke@1: } duke@1: break; duke@1: case TYPE_REMOTE: duke@1: String objName = testUtil(getName(type), type); duke@1: p.p("(" + objName + ") " + duke@1: "PortableRemoteObject.narrow(" + streamName + ".read_Object(), " + objName + ".class);"); duke@1: break; duke@1: case TYPE_ABSTRACT: duke@1: p.p("(" + getName(type) + ") " + streamName + ".read_abstract_interface();"); duke@1: break; duke@1: case TYPE_NC_INTERFACE: duke@1: p.p("(" + getName(type) + ") " + streamName + ".read_value(" + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_VALUE: duke@1: p.p("(" + getName(type) + ") " + streamName + ".read_value(" + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_IMPLEMENTATION: duke@1: p.p("(" + getName(type) + ") " + streamName + ".read_value(" + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_NC_CLASS: duke@1: p.p("(" + getName(type) + ") " + streamName + ".read_value(" + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_ARRAY: duke@1: p.p("(" + getName(type) + ") " + streamName + ".read_value(" + getName(type) + ".class);"); duke@1: break; duke@1: case TYPE_JAVA_RMI_REMOTE: duke@1: p.p("(" + getName(type) + ") " + duke@1: "PortableRemoteObject.narrow(" + streamName + ".read_Object(), " + getName(type) + ".class);"); duke@1: // p.p("(" + getName(type) + ") " + streamName + ".read_Object(" + getStubName(type) + ".class);"); duke@1: break; duke@1: default: duke@1: throw new Error("unexpected type code: " + typeCode); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Get a list of all the RepositoryIDs for interfaces duke@1: * implemented directly or indirectly by theType. In the duke@1: * case of an ImplementationType which implements 2 or duke@1: * more remote interfaces, this list will begin with the duke@1: * Identifier for the implementation (see section 5.9 in duke@1: * the Java -> IDL mapping). Ensures that the most derived duke@1: * type is first in the list because the IOR is generated duke@1: * using that entry in the _ids array. duke@1: */ duke@1: String[] getAllRemoteRepIDs (CompoundType theType) { duke@1: duke@1: String[] result; duke@1: duke@1: // Collect up all the (inherited) remote interfaces duke@1: // (ignores all the 'special' interfaces: Remote, duke@1: // Serializable, Externalizable)... duke@1: duke@1: Type[] types = collectAllRemoteInterfaces(theType); duke@1: duke@1: int length = types.length; duke@1: boolean haveImpl = theType instanceof ImplementationType; duke@1: InterfaceType[] interfaces = theType.getInterfaces(); duke@1: int remoteCount = countRemote(interfaces,false); duke@1: int offset = 0; duke@1: duke@1: // Do we have an implementation type that implements duke@1: // more than one remote interface? duke@1: duke@1: if (haveImpl && remoteCount > 1) { duke@1: duke@1: // Yes, so we need to insert it at the beginning... duke@1: duke@1: result = new String[length + 1]; duke@1: result[0] = getRepositoryID(theType); duke@1: offset = 1; duke@1: duke@1: } else { duke@1: duke@1: // No. duke@1: duke@1: result = new String[length]; duke@1: duke@1: // Here we need to ensure that the most derived duke@1: // interface ends up being first in the list. If duke@1: // there is only one, we're done. duke@1: duke@1: if (length > 1) { duke@1: duke@1: // First, decide what the most derived type is... duke@1: duke@1: String mostDerived = null; duke@1: duke@1: if (haveImpl) { duke@1: duke@1: // If we get here, we know that there is only one duke@1: // direct remote interface, so just find it... duke@1: duke@1: for (int i = 0; i < interfaces.length; i++) { duke@1: if (interfaces[i].isType(TYPE_REMOTE)) { duke@1: mostDerived = interfaces[i].getRepositoryID(); duke@1: break; duke@1: } duke@1: } duke@1: } else { duke@1: duke@1: // If we get here we know that theType is a RemoteType duke@1: // so just use its id... duke@1: duke@1: mostDerived = theType.getRepositoryID(); duke@1: } duke@1: duke@1: // Now search types list and make sure mostDerived is duke@1: // at index zero... duke@1: duke@1: for (int i = 0; i < length; i++) { duke@1: if (types[i].getRepositoryID() == mostDerived) { duke@1: duke@1: // Found it. Swap it if we need to... duke@1: duke@1: if (i > 0) { duke@1: Type temp = types[0]; duke@1: types[0] = types[i]; duke@1: types[i] = temp; duke@1: } duke@1: duke@1: break; duke@1: } duke@1: } duke@1: } duke@1: } duke@1: duke@1: // Now copy contents of the types array... duke@1: duke@1: for (int i = 0; i < types.length; i++) { duke@1: result[offset++] = getRepositoryID(types[i]); duke@1: } duke@1: duke@1: // If we're supposed to, reverse the array. This duke@1: // is only done when the -testReverseIDs flag is duke@1: // passed, and that should ONLY be done for test duke@1: // cases. This is an undocumented feature. duke@1: duke@1: if (reverseIDs) { duke@1: int start = 0; duke@1: int end = result.length -1; duke@1: while (start < end) { duke@1: String temp = result[start]; duke@1: result[start++] = result[end]; duke@1: result[end--] = temp; duke@1: } duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Collect all the inherited remote interfaces. duke@1: */ duke@1: Type[] collectAllRemoteInterfaces (CompoundType theType) { duke@1: Vector list = new Vector(); duke@1: duke@1: // Collect up all the Remote interfaces, and get an instance duke@1: // for java.rmi.Remote... duke@1: duke@1: addRemoteInterfaces(list,theType); duke@1: duke@1: // Create and return our results... duke@1: duke@1: Type[] result = new Type[list.size()]; duke@1: list.copyInto(result); duke@1: duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Add all the inherited remote interfaces to list. duke@1: */ duke@1: void addRemoteInterfaces(Vector list, CompoundType theType) { duke@1: duke@1: if (theType != null) { duke@1: if (theType.isInterface() && !list.contains(theType)) { duke@1: list.addElement(theType); duke@1: } duke@1: duke@1: InterfaceType[] interfaces = theType.getInterfaces(); duke@1: for (int i = 0; i < interfaces.length; i++) { duke@1: duke@1: if (interfaces[i].isType(TYPE_REMOTE)) { duke@1: addRemoteInterfaces(list,interfaces[i]); duke@1: } duke@1: } duke@1: duke@1: addRemoteInterfaces(list,theType.getSuperclass()); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Get a list of all the remote interfaces which this stub duke@1: * should declare. duke@1: */ duke@1: RemoteType[] getDirectRemoteInterfaces (CompoundType theType) { duke@1: duke@1: RemoteType[] result; duke@1: InterfaceType[] interfaces = theType.getInterfaces(); duke@1: duke@1: // First, get a list of all the interfaces... duke@1: duke@1: InterfaceType[] list; duke@1: duke@1: // Because we can be passed either an ImplementationType duke@1: // (which has interfaces) or a RemoteType (which is an duke@1: // interface and may have interfaces) we must handle each duke@1: // separately... duke@1: duke@1: // Do we have an implementation type? duke@1: duke@1: if (theType instanceof ImplementationType) { duke@1: duke@1: // Yes, so list is exactly what this type duke@1: // implements and is correct already. duke@1: duke@1: list = interfaces; duke@1: duke@1: } else { duke@1: duke@1: // No, so list is just theType... duke@1: duke@1: list = new InterfaceType[1]; duke@1: list[0] = (InterfaceType) theType; duke@1: } duke@1: duke@1: // Ok, now count up the remote interfaces, allocate duke@1: // our result and fill it in... duke@1: duke@1: int remoteCount = countRemote(list,false); duke@1: duke@1: if (remoteCount == 0) { duke@1: throw new CompilerError("iiop.StubGenerator: No remote interfaces!"); duke@1: } duke@1: duke@1: result = new RemoteType[remoteCount]; duke@1: int offset = 0; duke@1: for (int i = 0; i < list.length; i++) { duke@1: if (list[i].isType(TYPE_REMOTE)) { duke@1: result[offset++] = (RemoteType)list[i]; duke@1: } duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: int countRemote (Type[] list, boolean includeAbstract) { duke@1: int remoteCount = 0; duke@1: for (int i = 0; i < list.length; i++) { duke@1: if (list[i].isType(TYPE_REMOTE) && duke@1: (includeAbstract || !list[i].isType(TYPE_ABSTRACT))) { duke@1: remoteCount++; duke@1: } duke@1: } duke@1: duke@1: return remoteCount; duke@1: } duke@1: duke@1: void writeCastArray(IndentingWriter p) throws IOException { duke@1: if (castArray) { duke@1: p.pln(); duke@1: p.pln("// This method is required as a work-around for"); duke@1: p.pln("// a bug in the JDK 1.1.6 verifier."); duke@1: p.pln(); duke@1: p.plnI("private "+getName(idJavaIoSerializable)+" cast_array(Object obj) {"); duke@1: p.pln("return ("+getName(idJavaIoSerializable)+")obj;"); duke@1: p.pOln("}"); duke@1: } duke@1: } duke@1: void writeIds(IndentingWriter p, CompoundType theType, boolean isTie duke@1: ) throws IOException { duke@1: p.plnI("private static final String[] _type_ids = {"); duke@1: duke@1: String[] ids = getAllRemoteRepIDs(theType); duke@1: duke@1: if (ids.length >0 ) { duke@1: for(int i = 0; i < ids.length; i++) { duke@1: if (i > 0) duke@1: p.pln(", "); duke@1: p.p("\"" + ids[i] + "\""); duke@1: } duke@1: } else { duke@1: // Must be an implementation which only implements Remote... duke@1: p.pln("\"\""); duke@1: } duke@1: String qname = theType.getQualifiedName() ; duke@1: boolean isTransactional = isTie && transactionalObjects.containsKey( qname ) ; duke@1: // Add TransactionalObject if needed. duke@1: if (isTransactional) { duke@1: // Have already written an id. duke@1: p.pln( ", " ) ; duke@1: p.pln( "\"IDL:omg.org/CosTransactions/TransactionalObject:1.0\"" ) ; duke@1: } else if (ids.length > 0) { duke@1: p.pln(); duke@1: } duke@1: p.pOln("};"); duke@1: } duke@1: duke@1: duke@1: /** duke@1: * Write the Tie for the remote class to a stream. duke@1: */ duke@1: protected void writeTie(OutputType outputType, duke@1: IndentingWriter p) throws IOException duke@1: { duke@1: CompoundType theType = (CompoundType) outputType.getType(); duke@1: RemoteType[] remoteInterfaces = null; duke@1: duke@1: // Write comment... duke@1: p.pln("// Tie class generated by rmic, do not edit."); duke@1: p.pln("// Contents subject to change without notice."); duke@1: p.pln(); duke@1: duke@1: // Set our standard classes... duke@1: setStandardClassesInUse(theType,false); duke@1: duke@1: // Add classes for this type... duke@1: addClassesInUse(theType,remoteInterfaces); duke@1: duke@1: // Write package and import statements... duke@1: writePackageAndImports(p); duke@1: duke@1: // Declare the tie class. duke@1: p.p("public class " + currentClass + " extends " + duke@1: getName(tieBaseClass) + " implements Tie"); duke@1: duke@1: // Add java.rmi.Remote if this type does not implement it. duke@1: // This allows stubs for Abstract interfaces to be treated duke@1: // uniformly... duke@1: if (!implementsRemote(theType)) { duke@1: p.pln(","); duke@1: p.p(getName("java.rmi.Remote")); duke@1: } duke@1: duke@1: p.plnI(" {"); duke@1: duke@1: // Write data members... duke@1: p.pln(); alanb@402: p.pln("volatile private " + getName(theType) + " target = null;"); duke@1: p.pln(); duke@1: duke@1: // Write the ids... duke@1: writeIds( p, theType, true ) ; duke@1: duke@1: // Write setTarget method... duke@1: p.pln(); duke@1: p.plnI("public void setTarget(Remote target) {"); duke@1: p.pln("this.target = (" + getName(theType) + ") target;"); duke@1: p.pOln("}"); duke@1: duke@1: // Write getTarget method... duke@1: p.pln(); duke@1: p.plnI("public Remote getTarget() {"); duke@1: p.pln("return target;"); duke@1: p.pOln("}"); duke@1: duke@1: // Write thisObject method... duke@1: p.pln(); duke@1: write_tie_thisObject_method(p,idCorbaObject); duke@1: duke@1: // Write deactivate method... duke@1: p.pln(); duke@1: write_tie_deactivate_method(p); duke@1: duke@1: // Write get orb method... duke@1: p.pln(); duke@1: p.plnI("public ORB orb() {"); duke@1: p.pln("return _orb();"); duke@1: p.pOln("}"); duke@1: duke@1: // Write set orb method... duke@1: p.pln(); duke@1: write_tie_orb_method(p); duke@1: duke@1: // Write the _ids() method... duke@1: p.pln(); duke@1: write_tie__ids_method(p); duke@1: duke@1: // Get all the methods... duke@1: CompoundType.Method[] remoteMethods = theType.getMethods(); duke@1: duke@1: // Register all the argument names used, plus our duke@1: // data member names... duke@1: duke@1: addNamesInUse(remoteMethods); duke@1: addNameInUse("target"); duke@1: addNameInUse("_type_ids"); duke@1: duke@1: // Write the _invoke method... duke@1: p.pln(); duke@1: duke@1: String in = getVariableName("in"); duke@1: String _in = getVariableName("_in"); duke@1: String ex = getVariableName("ex"); duke@1: String method = getVariableName("method"); duke@1: String reply = getVariableName("reply"); duke@1: duke@1: p.plnI("public OutputStream _invoke(String "+method+", InputStream "+_in+", " + duke@1: "ResponseHandler "+reply+") throws SystemException {"); duke@1: duke@1: if (remoteMethods.length > 0) { duke@1: p.plnI("try {"); alanb@402: p.pln(getName(theType) + " target = this.target;"); alanb@402: p.plnI("if (target == null) {"); alanb@402: p.pln("throw new java.io.IOException();"); alanb@402: p.pOln("}"); duke@1: p.plnI(idExtInputStream + " "+in+" = "); duke@1: p.pln("(" + idExtInputStream + ") "+_in+";"); duke@1: p.pO(); duke@1: duke@1: // See if we should use a hash table style duke@1: // comparison... duke@1: duke@1: StaticStringsHash hash = getStringsHash(remoteMethods); duke@1: duke@1: if (hash != null) { duke@1: p.plnI("switch ("+method+"."+hash.method+") {"); duke@1: for (int i = 0; i < hash.buckets.length; i++) { duke@1: p.plnI("case "+hash.keys[i]+": "); duke@1: for (int j = 0; j < hash.buckets[i].length; j++) { duke@1: CompoundType.Method current = remoteMethods[hash.buckets[i][j]]; duke@1: if (j > 0) { duke@1: p.pO("} else "); duke@1: } duke@1: p.plnI("if ("+method+".equals(\""+ current.getIDLName() +"\")) {"); duke@1: writeTieMethod(p, theType,current); duke@1: } duke@1: p.pOln("}"); duke@1: p.pO(); duke@1: } duke@1: } else { duke@1: for(int i = 0; i < remoteMethods.length; i++) { duke@1: CompoundType.Method current = remoteMethods[i]; duke@1: if (i > 0) { duke@1: p.pO("} else "); duke@1: } duke@1: duke@1: p.plnI("if ("+method+".equals(\""+ current.getIDLName() +"\")) {"); duke@1: writeTieMethod(p, theType, current); duke@1: } duke@1: } duke@1: duke@1: if (hash != null) { duke@1: p.pI(); duke@1: // p.plnI("default:"); duke@1: } else { duke@1: // p.pOlnI("} else {"); duke@1: } duke@1: // p.pln("throw new "+getName(idBadMethodException)+"();"); duke@1: duke@1: if (hash != null) { duke@1: p.pO(); duke@1: } duke@1: p.pOln("}"); duke@1: p.pln("throw new "+getName(idBadMethodException)+"();"); duke@1: duke@1: p.pOlnI("} catch ("+getName(idSystemException)+" "+ex+") {"); duke@1: p.pln("throw "+ex+";"); duke@1: duke@1: p.pOlnI("} catch ("+getName(idJavaLangThrowable)+" "+ex+") {"); duke@1: p.pln("throw new " + getName(idPortableUnknownException) + "("+ex+");"); duke@1: p.pOln("}"); duke@1: } else { duke@1: // No methods... duke@1: duke@1: p.pln("throw new " + getName(idBadMethodException) + "();"); duke@1: } duke@1: duke@1: p.pOln("}"); // end invoke duke@1: duke@1: // Write the cast array hack... duke@1: duke@1: writeCastArray(p); duke@1: duke@1: // End tie class... duke@1: p.pOln("}"); duke@1: } duke@1: public void catchWrongPolicy(IndentingWriter p) throws IOException { duke@1: p.pln(""); duke@1: } duke@1: public void catchServantNotActive(IndentingWriter p) throws IOException { duke@1: p.pln(""); duke@1: } duke@1: public void catchObjectNotActive(IndentingWriter p) throws IOException { duke@1: p.pln(""); duke@1: } duke@1: duke@1: public void write_tie_thisObject_method(IndentingWriter p, duke@1: Identifier idCorbaObject) duke@1: throws IOException duke@1: { duke@1: if(POATie){ duke@1: p.plnI("public " + idCorbaObject + " thisObject() {"); duke@1: /* duke@1: p.pln("org.omg.CORBA.Object objref = null;"); duke@1: p.pln("try{"); duke@1: p.pln("objref = _poa().servant_to_reference(this);"); duke@1: p.pln("}catch (org.omg.PortableServer.POAPackage.WrongPolicy exception){"); duke@1: catchWrongPolicy(p); duke@1: p.pln("}catch (org.omg.PortableServer.POAPackage.ServantNotActive exception){"); duke@1: catchServantNotActive(p); duke@1: p.pln("}"); duke@1: p.pln("return objref;"); duke@1: */ duke@1: p.pln("return _this_object();"); duke@1: p.pOln("}"); duke@1: } else { duke@1: p.plnI("public " + idCorbaObject + " thisObject() {"); duke@1: p.pln("return this;"); duke@1: p.pOln("}"); duke@1: } duke@1: } duke@1: duke@1: public void write_tie_deactivate_method(IndentingWriter p) duke@1: throws IOException duke@1: { duke@1: if(POATie){ duke@1: p.plnI("public void deactivate() {"); duke@1: p.pln("try{"); duke@1: p.pln("_poa().deactivate_object(_poa().servant_to_id(this));"); duke@1: p.pln("}catch (org.omg.PortableServer.POAPackage.WrongPolicy exception){"); duke@1: catchWrongPolicy(p); duke@1: p.pln("}catch (org.omg.PortableServer.POAPackage.ObjectNotActive exception){"); duke@1: catchObjectNotActive(p); duke@1: p.pln("}catch (org.omg.PortableServer.POAPackage.ServantNotActive exception){"); duke@1: catchServantNotActive(p); duke@1: p.pln("}"); duke@1: p.pOln("}"); duke@1: } else { duke@1: p.plnI("public void deactivate() {"); duke@1: p.pln("_orb().disconnect(this);"); duke@1: p.pln("_set_delegate(null);"); duke@1: p.pln("target = null;"); duke@1: p.pOln("}"); duke@1: } duke@1: } duke@1: duke@1: public void write_tie_orb_method(IndentingWriter p) duke@1: throws IOException duke@1: { duke@1: if(POATie){ duke@1: p.plnI("public void orb(ORB orb) {"); duke@1: /* duke@1: p.pln("try{"); duke@1: p.pln("orb.connect(_poa().servant_to_reference(this));"); duke@1: p.pln("}catch (org.omg.PortableServer.POAPackage.WrongPolicy exception){"); duke@1: catchWrongPolicy(p); duke@1: p.pln("}catch (org.omg.PortableServer.POAPackage.ServantNotActive exception){"); duke@1: catchServantNotActive(p); duke@1: p.pln("}"); duke@1: */ duke@1: p.pln("try {"); duke@1: p.pln(" ((org.omg.CORBA_2_3.ORB)orb).set_delegate(this);"); duke@1: p.pln("}"); duke@1: p.pln("catch(ClassCastException e) {"); duke@1: p.pln(" throw new org.omg.CORBA.BAD_PARAM"); duke@1: p.pln(" (\"POA Servant requires an instance of org.omg.CORBA_2_3.ORB\");"); duke@1: p.pln("}"); duke@1: p.pOln("}"); duke@1: } else { duke@1: p.plnI("public void orb(ORB orb) {"); duke@1: p.pln("orb.connect(this);"); duke@1: p.pOln("}"); duke@1: } duke@1: } duke@1: duke@1: public void write_tie__ids_method(IndentingWriter p) duke@1: throws IOException duke@1: { duke@1: if(POATie){ duke@1: p.plnI("public String[] _all_interfaces(org.omg.PortableServer.POA poa, byte[] objectId){"); coffeys@370: p.pln("return (String[]) _type_ids.clone();"); duke@1: p.pOln("}"); duke@1: } else { duke@1: p.plnI("public String[] _ids() { "); coffeys@370: p.pln("return (String[]) _type_ids.clone();"); duke@1: p.pOln("}"); duke@1: } duke@1: } duke@1: duke@1: duke@1: StaticStringsHash getStringsHash (CompoundType.Method[] methods) { duke@1: if (useHash && methods.length > 1) { duke@1: String[] methodNames = new String[methods.length]; duke@1: for (int i = 0; i < methodNames.length; i++) { duke@1: methodNames[i] = methods[i].getIDLName(); duke@1: } duke@1: return new StaticStringsHash(methodNames); duke@1: } duke@1: return null; duke@1: } duke@1: duke@1: static boolean needNewReadStreamClass(Type type) { duke@1: if (type.isType(TYPE_ABSTRACT)) { duke@1: return true; duke@1: } duke@1: // Handle late-breaking special case for duke@1: // abstract IDL entities... duke@1: if ((type instanceof CompoundType) && duke@1: ((CompoundType)type).isAbstractBase()) { duke@1: return true; duke@1: } duke@1: return needNewWriteStreamClass(type); duke@1: } duke@1: duke@1: static boolean needNewWriteStreamClass(Type type) { duke@1: switch (type.getTypeCode()) { duke@1: case TYPE_VOID: duke@1: case TYPE_BOOLEAN: duke@1: case TYPE_BYTE: duke@1: case TYPE_CHAR: duke@1: case TYPE_SHORT: duke@1: case TYPE_INT: duke@1: case TYPE_LONG: duke@1: case TYPE_FLOAT: duke@1: case TYPE_DOUBLE: return false; duke@1: duke@1: case TYPE_STRING: return true; duke@1: case TYPE_ANY: return false; duke@1: case TYPE_CORBA_OBJECT: return false; duke@1: case TYPE_REMOTE: return false; duke@1: case TYPE_ABSTRACT: return false; duke@1: case TYPE_NC_INTERFACE: return true; duke@1: case TYPE_VALUE: return true; duke@1: case TYPE_IMPLEMENTATION: return true; duke@1: case TYPE_NC_CLASS: return true; duke@1: case TYPE_ARRAY: return true; duke@1: case TYPE_JAVA_RMI_REMOTE: return false; duke@1: duke@1: default: throw new Error("unexpected type code: " + type.getTypeCode()); duke@1: } duke@1: } duke@1: duke@1: /* duke@1: * Decide which arguments need to be copied and write duke@1: * the copy code. Returns an array of argument names to duke@1: * use to refer to either the copy or the original. duke@1: */ duke@1: String[] writeCopyArguments(CompoundType.Method method, duke@1: IndentingWriter p) throws IOException { duke@1: duke@1: Type[] args = method.getArguments(); duke@1: String[] origNames = method.getArgumentNames(); duke@1: duke@1: // Copy the current parameter names to a result array... duke@1: duke@1: String[] result = new String[origNames.length]; duke@1: for (int i = 0; i < result.length; i++) { duke@1: result[i] = origNames[i]; duke@1: } duke@1: duke@1: // Decide which arguments must be copied, if any. If duke@1: // any of the arguments are types for which a 'real' copy duke@1: // will be done, rather than just an autoConnect, set duke@1: // realCopy = true. Note that abstract types may only duke@1: // need autoConnect, but we cannot know that at compile duke@1: // time... duke@1: duke@1: boolean realCopy = false; duke@1: boolean[] copyArg = new boolean[args.length]; duke@1: int copyCount = 0; duke@1: int firstCopiedArg = 0; // Only used in single copy case. It is only the first arg that duke@1: // needs copying IF copyCount == 1. duke@1: duke@1: for (int i = 0; i < args.length; i++) { duke@1: if (mustCopy(args[i])) { duke@1: copyArg[i] = true; duke@1: copyCount++; duke@1: firstCopiedArg = i; duke@1: if (args[i].getTypeCode() != TYPE_REMOTE && duke@1: args[i].getTypeCode() != TYPE_IMPLEMENTATION) { duke@1: realCopy = true; duke@1: } duke@1: } else { duke@1: copyArg[i] = false; duke@1: } duke@1: } duke@1: duke@1: // Do we have any types which must be copied? duke@1: if (copyCount > 0) { duke@1: // Yes. Are we only doing the copy to ensure duke@1: // that autoConnect occurs? duke@1: if (realCopy) { duke@1: // Nope. We need to go back thru the list and duke@1: // mark any strings so that they will be copied duke@1: // to preserve any shared references... duke@1: for (int i = 0; i < args.length; i++) { duke@1: if (args[i].getTypeCode() == TYPE_STRING) { duke@1: copyArg[i] = true; duke@1: copyCount++; duke@1: } duke@1: } duke@1: } duke@1: duke@1: // We're ready to generate code. Do we have more than duke@1: // one to copy? duke@1: if (copyCount > 1) { duke@1: // Generate a call to copyObjects... duke@1: String arrayName = getVariableName("copies"); duke@1: p.p("Object[] " + arrayName + " = Util.copyObjects(new Object[]{"); duke@1: boolean first = true; duke@1: for (int i = 0; i < args.length; i++) { duke@1: if (copyArg[i]) { duke@1: if (!first) { duke@1: p.p(","); duke@1: } duke@1: first = false; duke@1: p.p(origNames[i]); duke@1: } duke@1: } duke@1: p.pln("},_orb());"); duke@1: duke@1: // For each of the types which was copied, create duke@1: // a local temporary for it, updating the result duke@1: // array with the new local parameter name... duke@1: int copyIndex = 0 ; duke@1: for (int i = 0; i < args.length; i++) { duke@1: if (copyArg[i]) { duke@1: result[i] = getVariableName(result[i]+"Copy"); duke@1: p.pln( getName(args[i]) + " " + result[i] + " = (" + getName(args[i]) + ") " + duke@1: arrayName + "[" + copyIndex++ +"];"); duke@1: } duke@1: } duke@1: } else { duke@1: // Generate a call to copyObject, updating the result duke@1: // with the new local parameter name... duke@1: result[firstCopiedArg] = getVariableName(result[firstCopiedArg]+"Copy"); duke@1: p.pln( getName(args[firstCopiedArg]) + " " + result[firstCopiedArg] + " = (" + duke@1: getName(args[firstCopiedArg]) + ") Util.copyObject(" + duke@1: origNames[firstCopiedArg] + ",_orb());"); duke@1: } duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: static final String SINGLE_SLASH = "\\"; duke@1: static final String DOUBLE_SLASH = SINGLE_SLASH + SINGLE_SLASH; duke@1: duke@1: String getRepositoryID(Type type) { duke@1: return IDLNames.replace(type.getRepositoryID(), SINGLE_SLASH, DOUBLE_SLASH); duke@1: } duke@1: duke@1: String getExceptionRepositoryID(Type type) { duke@1: ClassType theType = (ClassType) type; duke@1: return IDLNames.getIDLRepositoryID(theType.getQualifiedIDLExceptionName(false)); duke@1: } duke@1: duke@1: String getVariableName(String proposed) { duke@1: while (namesInUse.contains(proposed)) { duke@1: proposed = "$" + proposed; duke@1: } duke@1: duke@1: return proposed; duke@1: } duke@1: duke@1: void addNamesInUse(CompoundType.Method[] methods) { duke@1: for (int i = 0; i < methods.length; i++) { duke@1: addNamesInUse(methods[i]); duke@1: } duke@1: } duke@1: duke@1: void addNamesInUse(CompoundType.Method method) { duke@1: String paramNames[] = method.getArgumentNames(); duke@1: for (int i = 0; i < paramNames.length; i++) { duke@1: addNameInUse(paramNames[i]); duke@1: } duke@1: } duke@1: duke@1: void addNameInUse(String name) { duke@1: namesInUse.add(name); duke@1: } duke@1: duke@1: static boolean mustCopy(Type type) { duke@1: switch (type.getTypeCode()) { duke@1: case TYPE_VOID: duke@1: case TYPE_BOOLEAN: duke@1: case TYPE_BYTE: duke@1: case TYPE_CHAR: duke@1: case TYPE_SHORT: duke@1: case TYPE_INT: duke@1: case TYPE_LONG: duke@1: case TYPE_FLOAT: duke@1: case TYPE_DOUBLE: duke@1: case TYPE_STRING: return false; duke@1: duke@1: case TYPE_ANY: return true; duke@1: duke@1: case TYPE_CORBA_OBJECT: return false; duke@1: duke@1: case TYPE_REMOTE: duke@1: case TYPE_ABSTRACT: duke@1: case TYPE_NC_INTERFACE: duke@1: case TYPE_VALUE: duke@1: case TYPE_IMPLEMENTATION: duke@1: case TYPE_NC_CLASS: duke@1: case TYPE_ARRAY: duke@1: case TYPE_JAVA_RMI_REMOTE: return true; duke@1: duke@1: default: throw new Error("unexpected type code: " + type.getTypeCode()); duke@1: } duke@1: } duke@1: duke@1: ValueType[] getStubExceptions (CompoundType.Method method, boolean sort) { duke@1: duke@1: ValueType[] list = method.getFilteredStubExceptions(method.getExceptions()); duke@1: duke@1: // Sort the list so that all org.omg.CORBA.UserException duke@1: // subtypes are at the beginning of the list. This ensures duke@1: // that the stub will not call read_string() before calling duke@1: // XXHelper.read(). duke@1: duke@1: if (sort) { duke@1: Arrays.sort(list,new UserExceptionComparator()); duke@1: } duke@1: duke@1: return list; duke@1: } duke@1: duke@1: ValueType[] getTieExceptions (CompoundType.Method method) { duke@1: return method.getUniqueCatchList(method.getImplExceptions()); duke@1: } duke@1: duke@1: void writeTieMethod(IndentingWriter p, CompoundType type, duke@1: CompoundType.Method method) throws IOException { duke@1: String methodName = method.getName(); duke@1: Type paramTypes[] = method.getArguments(); duke@1: String paramNames[] = method.getArgumentNames(); duke@1: Type returnType = method.getReturnType(); duke@1: ValueType[] exceptions = getTieExceptions(method); duke@1: String in = getVariableName("in"); duke@1: String ex = getVariableName("ex"); duke@1: String out = getVariableName("out"); duke@1: String reply = getVariableName("reply"); duke@1: duke@1: for (int i = 0; i < paramTypes.length; i++) { duke@1: p.p(getName(paramTypes[i])+" "+paramNames[i]+" = "); duke@1: writeUnmarshalArgument(p, in, paramTypes[i], null); duke@1: p.pln(); duke@1: } duke@1: duke@1: boolean handleExceptions = exceptions != null; duke@1: boolean doReturn = !returnType.isType(TYPE_VOID); duke@1: duke@1: if (handleExceptions && doReturn) { duke@1: String objName = testUtil(getName(returnType), returnType); duke@1: p.pln(objName+" result;"); duke@1: } duke@1: duke@1: if (handleExceptions) duke@1: p.plnI("try {"); duke@1: duke@1: if (doReturn) { duke@1: if (handleExceptions) { duke@1: p.p("result = "); duke@1: } else { duke@1: p.p(getName(returnType)+" result = "); duke@1: } duke@1: } duke@1: duke@1: p.p("target."+methodName+"("); duke@1: for(int i = 0; i < paramNames.length; i++) { duke@1: if (i > 0) duke@1: p.p(", "); duke@1: p.p(paramNames[i]); duke@1: } duke@1: p.pln(");"); duke@1: duke@1: if (handleExceptions) { duke@1: for(int i = 0; i < exceptions.length; i++) { duke@1: p.pOlnI("} catch ("+getName(exceptions[i])+" "+ex+") {"); duke@1: duke@1: // Is this our IDLEntity Exception special case? duke@1: duke@1: if (exceptions[i].isIDLEntityException() && !exceptions[i].isCORBAUserException()) { duke@1: duke@1: // Yes... duke@1: duke@1: String helperName = IDLNames.replace(exceptions[i].getQualifiedIDLName(false),"::","."); duke@1: helperName += "Helper"; duke@1: p.pln(idOutputStream+" "+out +" = "+reply+".createExceptionReply();"); duke@1: p.pln(helperName+".write("+out+","+ex+");"); duke@1: duke@1: } else { duke@1: duke@1: // No... duke@1: duke@1: p.pln("String id = \"" + getExceptionRepositoryID(exceptions[i]) + "\";"); duke@1: p.plnI(idExtOutputStream + " "+out+" = "); duke@1: p.pln("(" + idExtOutputStream + ") "+reply+".createExceptionReply();"); duke@1: p.pOln(out+".write_string(id);"); duke@1: p.pln(out+".write_value("+ex+"," + getName(exceptions[i]) + ".class);"); duke@1: } duke@1: duke@1: p.pln("return "+out+";"); duke@1: } duke@1: p.pOln("}"); duke@1: } duke@1: duke@1: if (needNewWriteStreamClass(returnType)) { duke@1: p.plnI(idExtOutputStream + " "+out+" = "); duke@1: p.pln("(" + idExtOutputStream + ") "+reply+".createReply();"); duke@1: p.pO(); duke@1: } else { duke@1: p.pln("OutputStream "+out+" = "+reply+".createReply();"); duke@1: } duke@1: duke@1: if (doReturn) { duke@1: writeMarshalArgument(p, out, returnType, "result"); duke@1: p.pln(); duke@1: } duke@1: duke@1: p.pln("return "+out+";"); duke@1: } duke@1: duke@1: duke@1: /** duke@1: * Write Java statements to marshal a series of values in order as duke@1: * named in the "names" array, with types as specified in the "types" duke@1: * array", to the java.io.ObjectOutput stream named "stream". duke@1: */ duke@1: void writeMarshalArguments(IndentingWriter p, duke@1: String streamName, duke@1: Type[] types, String[] names) duke@1: throws IOException duke@1: { duke@1: if (types.length != names.length) { duke@1: throw new Error("paramter type and name arrays different sizes"); duke@1: } duke@1: duke@1: for (int i = 0; i < types.length; i++) { duke@1: writeMarshalArgument(p, streamName, types[i], names[i]); duke@1: if (i != types.length -1) { duke@1: p.pln(); duke@1: } duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Added for IASRI 4987274. Remote classes named "Util" were duke@1: * getting confused with javax.rmi.CORBA.Util and the duke@1: * unqualifiedName "Util". duke@1: */ duke@1: String testUtil(String objectName, Type ttype) { duke@1: if (objectName.equals("Util")) { duke@1: String correctedName = (String)ttype.getPackageName() + "." + objectName; duke@1: return correctedName; duke@1: } else { duke@1: return objectName; duke@1: } duke@1: } duke@1: } duke@1: duke@1: class StringComparator implements java.util.Comparator { duke@1: public int compare(Object o1, Object o2) { duke@1: String s1 = (String)o1; duke@1: String s2 = (String)o2; duke@1: return s1.compareTo(s2); duke@1: } duke@1: } duke@1: duke@1: duke@1: class UserExceptionComparator implements java.util.Comparator { duke@1: public int compare(Object o1, Object o2) { duke@1: ValueType v1 = (ValueType)o1; duke@1: ValueType v2 = (ValueType)o2; duke@1: int result = 0; duke@1: if (isUserException(v1)) { duke@1: if (!isUserException(v2)) { duke@1: result = -1; duke@1: } duke@1: } else if (isUserException(v2)) { duke@1: if (!isUserException(v1)) { duke@1: result = 1; duke@1: } duke@1: } duke@1: return result; duke@1: } duke@1: duke@1: final boolean isUserException(ValueType it) { duke@1: return it.isIDLEntityException() && !it.isCORBAUserException(); duke@1: } duke@1: }