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