2381 lines
79 KiB
Java
2381 lines
79 KiB
Java
/*
|
|
* 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();
|
|
}
|
|
}
|