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