/* * Copyright (c) 2003, 2004, 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. */ package com.sun.corba.se.impl.presentation.rmi ; import java.security.AccessController; import java.security.PrivilegedAction; import java.lang.reflect.Method; import java.math.BigInteger; import java.util.Map; import java.util.Set; import java.util.HashSet; import java.util.Iterator; import java.util.HashMap; import java.util.StringTokenizer; import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ; import com.sun.corba.se.impl.presentation.rmi.IDLType ; import com.sun.corba.se.impl.presentation.rmi.IDLTypeException ; import com.sun.corba.se.impl.presentation.rmi.IDLTypesUtil ; import com.sun.corba.se.impl.orbutil.ObjectUtility ; /** * Bidirectional translator between RMI-IIOP interface methods and * and IDL Names. */ public class IDLNameTranslatorImpl implements IDLNameTranslator { // From CORBA Spec, Table 6 Keywords. // Note that since all IDL identifiers are case // insensitive, java identifier comparisons to these // will be case insensitive also. private static String[] IDL_KEYWORDS = { "abstract", "any", "attribute", "boolean", "case", "char", "const", "context", "custom", "default", "double", "enum", "exception", "factory", "FALSE", "fixed", "float", "in", "inout", "interface", "long", "module", "native", "Object", "octet", "oneway", "out", "private", "public", "raises", "readonly", "sequence", "short", "string", "struct", "supports", "switch", "TRUE", "truncatable", "typedef", "unsigned", "union", "ValueBase", "valuetype", "void", "wchar", "wstring" }; private static char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; private static final String UNDERSCORE = "_"; // used to mangle java inner class names private static final String INNER_CLASS_SEPARATOR = UNDERSCORE + UNDERSCORE; // used to form IDL array type names private static final String[] BASE_IDL_ARRAY_MODULE_TYPE= new String[] { "org", "omg", "boxedRMI" } ; private static final String BASE_IDL_ARRAY_ELEMENT_TYPE = "seq"; // used to mangling java identifiers that have a leading underscore private static final String LEADING_UNDERSCORE_CHAR = "J"; private static final String ID_CONTAINER_CLASH_CHAR = UNDERSCORE; // separator used between types in a mangled overloaded method name private static final String OVERLOADED_TYPE_SEPARATOR = UNDERSCORE + UNDERSCORE; // string appended to attribute if it clashes with a method name private static final String ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS = UNDERSCORE + UNDERSCORE; // strings prepended to the attribute names in order to form their // IDL names. private static final String GET_ATTRIBUTE_PREFIX = "_get_"; private static final String SET_ATTRIBUTE_PREFIX = "_set_"; private static final String IS_ATTRIBUTE_PREFIX = "_get_"; private static Set idlKeywords_; static { idlKeywords_ = new HashSet(); for(int i = 0; i < IDL_KEYWORDS.length; i++) { String next = (String) IDL_KEYWORDS[i]; // Convert keyword to all caps to ease equality // check. String keywordAllCaps = next.toUpperCase(); idlKeywords_.add(keywordAllCaps); } } // // Instance state // // Remote interface for name translation. private Class[] interf_; // Maps used to hold name translations. These do not need to be // synchronized since the translation is never modified after // initialization. private Map methodToIDLNameMap_; private Map IDLNameToMethodMap_; private Method[] methods_; /** * Return an IDLNameTranslator for the given interface. * * @throws IllegalStateException if given class is not a valid * RMI/IIOP Remote Interface */ public static IDLNameTranslator get( Class interf ) { return new IDLNameTranslatorImpl(new Class[] { interf } ); } /** * Return an IDLNameTranslator for the given interfacex. * * @throws IllegalStateException if given classes are not valid * RMI/IIOP Remote Interfaces */ public static IDLNameTranslator get( Class[] interfaces ) { return new IDLNameTranslatorImpl(interfaces ); } public static String getExceptionId( Class cls ) { // Requirements for this method: // 1. cls must be an exception but not a RemoteException. // 2. If cls has an IDL keyword name, an underscore is prepended (1.3.2.2). // 3. If cls jas a leading underscore, J is prepended (1.3.2.3). // 4. If cls has an illegal IDL ident char, it is mapped to UXXXX where // XXXX is the unicode value in hex of the char (1.3.2.4). // 5. double underscore for inner class (1.3.2.5). // 6. The ID is "IDL:" + name with / separators + ":1.0". IDLType itype = classToIDLType( cls ) ; return itype.getExceptionName() ; } public Class[] getInterfaces() { return interf_; } public Method[] getMethods() { return methods_ ; } public Method getMethod( String idlName ) { return (Method) IDLNameToMethodMap_.get(idlName); } public String getIDLName( Method method ) { return (String) methodToIDLNameMap_.get(method); } /** * Initialize an IDLNameTranslator for the given interface. * * @throws IllegalStateException if given class is not a valid * RMI/IIOP Remote Interface */ private IDLNameTranslatorImpl(Class[] interfaces) { SecurityManager s = System.getSecurityManager(); if (s != null) { s.checkPermission(new DynamicAccessPermission("access")); } try { IDLTypesUtil idlTypesUtil = new IDLTypesUtil(); for (int ctr=0; ctr<interfaces.length; ctr++) idlTypesUtil.validateRemoteInterface(interfaces[ctr]); interf_ = interfaces; buildNameTranslation(); } catch( IDLTypeException ite) { String msg = ite.getMessage(); IllegalStateException ise = new IllegalStateException(msg); ise.initCause(ite); throw ise; } } private void buildNameTranslation() { // holds method info, keyed by method Map allMethodInfo = new HashMap() ; for (int ctr=0; ctr<interf_.length; ctr++) { Class interf = interf_[ctr] ; IDLTypesUtil idlTypesUtil = new IDLTypesUtil(); final Method[] methods = interf.getMethods(); // Handle the case of a non-public interface! AccessController.doPrivileged(new PrivilegedAction() { public Object run() { Method.setAccessible( methods, true ) ; return null ; } } ) ; // Take an initial pass through all the methods and create some // information that will be used to track the IDL name // transformation. for(int i = 0; i < methods.length; i++) { Method nextMethod = methods[i]; IDLMethodInfo methodInfo = new IDLMethodInfo(); methodInfo.method = nextMethod; if (idlTypesUtil.isPropertyAccessorMethod(nextMethod, interf)) { methodInfo.isProperty = true; String attributeName = idlTypesUtil. getAttributeNameForProperty(nextMethod.getName()); methodInfo.originalName = attributeName; methodInfo.mangledName = attributeName; } else { methodInfo.isProperty = false; methodInfo.originalName = nextMethod.getName(); methodInfo.mangledName = nextMethod.getName(); } allMethodInfo.put(nextMethod, methodInfo); } } // // Perform case sensitivity test first. This applies to all // method names AND attributes. Compare each method name and // attribute to all other method names and attributes. If names // differ only in case, apply mangling as defined in section 1.3.2.7 // of Java2IDL spec. Note that we compare using the original names. // for(Iterator outerIter=allMethodInfo.values().iterator(); outerIter.hasNext();) { IDLMethodInfo outer = (IDLMethodInfo) outerIter.next(); for(Iterator innerIter = allMethodInfo.values().iterator(); innerIter.hasNext();) { IDLMethodInfo inner = (IDLMethodInfo) innerIter.next(); if( (outer != inner) && (!outer.originalName.equals(inner.originalName)) && outer.originalName.equalsIgnoreCase(inner.originalName) ) { outer.mangledName = mangleCaseSensitiveCollision(outer.originalName); break; } } } for(Iterator iter = allMethodInfo.values().iterator(); iter.hasNext();) { IDLMethodInfo next = (IDLMethodInfo) iter.next(); next.mangledName = mangleIdentifier(next.mangledName, next.isProperty); } // // Now check for overloaded method names and apply 1.3.2.6. // for(Iterator outerIter=allMethodInfo.values().iterator(); outerIter.hasNext();) { IDLMethodInfo outer = (IDLMethodInfo) outerIter.next(); if( outer.isProperty ) { continue; } for(Iterator innerIter = allMethodInfo.values().iterator(); innerIter.hasNext();) { IDLMethodInfo inner = (IDLMethodInfo) innerIter.next(); if( (outer != inner) && !inner.isProperty && outer.originalName.equals(inner.originalName) ) { outer.mangledName = mangleOverloadedMethod (outer.mangledName, outer.method); break; } } } // // Now mangle any properties that clash with method names. // for(Iterator outerIter=allMethodInfo.values().iterator(); outerIter.hasNext();) { IDLMethodInfo outer = (IDLMethodInfo) outerIter.next(); if( !outer.isProperty ) { continue; } for(Iterator innerIter = allMethodInfo.values().iterator(); innerIter.hasNext();) { IDLMethodInfo inner = (IDLMethodInfo) innerIter.next(); if( (outer != inner) && !inner.isProperty && outer.mangledName.equals(inner.mangledName) ) { outer.mangledName = outer.mangledName + ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS; break; } } } // // Ensure that no mapped method names clash with mapped name // of container(1.3.2.9). This is a case insensitive comparison. // for (int ctr=0; ctr<interf_.length; ctr++ ) { Class interf = interf_[ctr] ; String mappedContainerName = getMappedContainerName(interf); for(Iterator iter = allMethodInfo.values().iterator(); iter.hasNext();) { IDLMethodInfo next = (IDLMethodInfo) iter.next(); if( !next.isProperty && identifierClashesWithContainer(mappedContainerName, next.mangledName)) { next.mangledName = mangleContainerClash(next.mangledName); } } } // // Populate name translation maps. // methodToIDLNameMap_ = new HashMap(); IDLNameToMethodMap_ = new HashMap(); methods_ = (Method[])allMethodInfo.keySet().toArray( new Method[0] ) ; for(Iterator iter = allMethodInfo.values().iterator(); iter.hasNext();) { IDLMethodInfo next = (IDLMethodInfo) iter.next(); String idlName = next.mangledName; if( next.isProperty ) { String origMethodName = next.method.getName(); String prefix = ""; if( origMethodName.startsWith("get") ) { prefix = GET_ATTRIBUTE_PREFIX; } else if( origMethodName.startsWith("set") ) { prefix = SET_ATTRIBUTE_PREFIX; } else { prefix = IS_ATTRIBUTE_PREFIX; } idlName = prefix + next.mangledName; } methodToIDLNameMap_.put(next.method, idlName); // Final check to see if there are any clashes after all the // manglings have been applied. If so, this is treated as an // invalid interface. Currently, we do a CASE-SENSITIVE // comparison since that matches the rmic behavior. // @@@ Shouldn't this be a case-insensitive check? if( IDLNameToMethodMap_.containsKey(idlName) ) { // @@@ I18N Method clash = (Method) IDLNameToMethodMap_.get(idlName); throw new IllegalStateException("Error : methods " + clash + " and " + next.method + " both result in IDL name '" + idlName + "'"); } else { IDLNameToMethodMap_.put(idlName, next.method); } } return; } /** * Perform all necessary stand-alone identifier mangling operations * on a java identifier that is being transformed into an IDL name. * That is, mangling operations that don't require looking at anything * else but the identifier itself. This covers sections 1.3.2.2, 1.3.2.3, * and 1.3.2.4 of the Java2IDL spec. Method overloading and * case-sensitivity checks are handled elsewhere. */ private static String mangleIdentifier(String identifier) { return mangleIdentifier(identifier, false); } private static String mangleIdentifier(String identifier, boolean attribute) { String mangledName = identifier; // // Apply leading underscore test (1.3.2.3) // This should be done before IDL Keyword clash test, since clashing // IDL keywords are mangled by adding a leading underscore. // if( hasLeadingUnderscore(mangledName) ) { mangledName = mangleLeadingUnderscore(mangledName); } // // Apply IDL keyword clash test (1.3.2.2). // This is not needed for attributes since when the full property // name is composed it cannot clash with an IDL keyword. // (Also, rmic doesn't do it.) // if( !attribute && isIDLKeyword(mangledName) ) { mangledName = mangleIDLKeywordClash(mangledName); } // // Replace illegal IDL identifier characters (1.3.2.4) // for all method names and attributes. // if( !isIDLIdentifier(mangledName) ) { mangledName = mangleUnicodeChars(mangledName); } return mangledName; } // isIDLKeyword and mangleIDLKeywordClash are exposed here so that // IDLType can use them. // // XXX refactoring needed: // 1. Split off isIDLKeywork and mangleIDLKeywordClash (and possibly // other methods) into a utility class. // 2. Move all of classToIDLType to a constructor inside IDLType. // // The problem appears to be that we need all of the code that // performs various checks for name problems and the corresponding // fixes into a utility class. Then we need to see what other // refactorings present themselves. /** * Checks whether a java identifier clashes with an * IDL keyword. Note that this is a case-insensitive * comparison. * * Used to implement section 1.3.2.2 of Java2IDL spec. */ static boolean isIDLKeyword(String identifier) { String identifierAllCaps = identifier.toUpperCase(); return idlKeywords_.contains(identifierAllCaps); } static String mangleIDLKeywordClash(String identifier) { return UNDERSCORE + identifier; } private static String mangleLeadingUnderscore(String identifier) { return LEADING_UNDERSCORE_CHAR + identifier; } /** * Checks whether a java identifier starts with an underscore. * Used to implement section 1.3.2.3 of Java2IDL spec. */ private static boolean hasLeadingUnderscore(String identifier) { return identifier.startsWith(UNDERSCORE); } /** * Implements Section 1.3.2.4 of Java2IDL Mapping. * All non-IDL identifier characters must be replaced * with their Unicode representation. */ static String mangleUnicodeChars(String identifier) { StringBuffer mangledIdentifier = new StringBuffer(); for(int i = 0; i < identifier.length(); i++) { char nextChar = identifier.charAt(i); if( isIDLIdentifierChar(nextChar) ) { mangledIdentifier.append(nextChar); } else { String unicode = charToUnicodeRepresentation(nextChar); mangledIdentifier.append(unicode); } } return mangledIdentifier.toString(); } /** * Implements mangling portion of Section 1.3.2.7 of Java2IDL spec. * This method only deals with the actual mangling. Decision about * whether case-sensitive collision mangling is required is made * elsewhere. * * * "...a mangled name is generated consisting of the original name * followed by an underscore separated list of decimal indices * into the string, where the indices identify all the upper case * characters in the original string. Indices are zero based." * */ String mangleCaseSensitiveCollision(String identifier) { StringBuffer mangledIdentifier = new StringBuffer(identifier); // There is always at least one trailing underscore, whether or // not the identifier has uppercase letters. mangledIdentifier.append(UNDERSCORE); boolean needUnderscore = false; for(int i = 0; i < identifier.length(); i++) { char next = identifier.charAt(i); if( Character.isUpperCase(next) ) { // This bit of logic is needed to ensure that we have // an underscore separated list of indices but no // trailing underscores. Basically, after we have at least // one uppercase letter, we always put an undercore before // printing the next one. if( needUnderscore ) { mangledIdentifier.append(UNDERSCORE); } mangledIdentifier.append(i); needUnderscore = true; } } return mangledIdentifier.toString(); } private static String mangleContainerClash(String identifier) { return identifier + ID_CONTAINER_CLASH_CHAR; } /** * Implements Section 1.3.2.9 of Java2IDL Mapping. Container in this * context means the name of the java Class(excluding package) in which * the identifier is defined. Comparison is case-insensitive. */ private static boolean identifierClashesWithContainer (String mappedContainerName, String identifier) { return identifier.equalsIgnoreCase(mappedContainerName); } /** * Returns Unicode mangling as defined in Section 1.3.2.4 of * Java2IDL spec. * * "For Java identifiers that contain illegal OMG IDL identifier * characters such as '$' or Unicode characters outside of ISO Latin 1, * any such illegal characters are replaced by "U" followed by the * 4 hexadecimal characters(in upper case) representing the Unicode * value. So, the Java name a$b is mapped to aU0024b and * x\u03bCy is mapped to xU03BCy." */ public static String charToUnicodeRepresentation(char c) { int orig = (int) c; StringBuffer hexString = new StringBuffer(); int value = orig; while( value > 0 ) { int div = value / 16; int mod = value % 16; hexString.insert(0, HEX_DIGITS[mod]); value = div; } int numZerosToAdd = 4 - hexString.length(); for(int i = 0; i < numZerosToAdd; i++) { hexString.insert(0, "0"); } hexString.insert(0, "U"); return hexString.toString(); } private static boolean isIDLIdentifier(String identifier) { boolean isIdentifier = true; for(int i = 0; i < identifier.length(); i++) { char nextChar = identifier.charAt(i); // 1st char must be alphbetic. isIdentifier = (i == 0) ? isIDLAlphabeticChar(nextChar) : isIDLIdentifierChar(nextChar); if( !isIdentifier ) { break; } } return isIdentifier; } private static boolean isIDLIdentifierChar(char c) { return (isIDLAlphabeticChar(c) || isIDLDecimalDigit(c) || isUnderscore(c)); } /** * True if character is one of 114 Alphabetic characters as * specified in Table 2 of Chapter 3 in CORBA spec. */ private static boolean isIDLAlphabeticChar(char c) { // NOTE that we can't use the java.lang.Character // isUpperCase, isLowerCase, etc. methods since they // include many characters other than the Alphabetic list in // the CORBA spec. Instead, we test for inclusion in the // Unicode value ranges for the corresponding legal characters. boolean alphaChar = ( // A - Z ((c >= 0x0041) && (c <= 0x005A)) || // a - z ((c >= 0x0061) && (c <= 0x007A)) || // other letter uppercase, other letter lowercase, which is // the entire upper half of C1 Controls except X and / ((c >= 0x00C0) && (c <= 0x00FF) && (c != 0x00D7) && (c != 0x00F7))); return alphaChar; } /** * True if character is one of 10 Decimal Digits * specified in Table 3 of Chapter 3 in CORBA spec. */ private static boolean isIDLDecimalDigit(char c) { return ( (c >= 0x0030) && (c <= 0x0039) ); } private static boolean isUnderscore(char c) { return ( c == 0x005F ); } /** * Mangle an overloaded method name as defined in Section 1.3.2.6 of * Java2IDL spec. Current value of method name is passed in as argument. * We can't start from original method name since the name might have * been partially mangled as a result of the other rules. */ private static String mangleOverloadedMethod(String mangledName, Method m) { IDLTypesUtil idlTypesUtil = new IDLTypesUtil(); // Start by appending the separator string String newMangledName = mangledName + OVERLOADED_TYPE_SEPARATOR; Class[] parameterTypes = m.getParameterTypes(); for(int i = 0; i < parameterTypes.length; i++) { Class nextParamType = parameterTypes[i]; if( i > 0 ) { newMangledName = newMangledName + OVERLOADED_TYPE_SEPARATOR; } IDLType idlType = classToIDLType(nextParamType); String moduleName = idlType.getModuleName(); String memberName = idlType.getMemberName(); String typeName = (moduleName.length() > 0) ? moduleName + UNDERSCORE + memberName : memberName; if( !idlTypesUtil.isPrimitive(nextParamType) && (idlTypesUtil.getSpecialCaseIDLTypeMapping(nextParamType) == null) && isIDLKeyword(typeName) ) { typeName = mangleIDLKeywordClash(typeName); } typeName = mangleUnicodeChars(typeName); newMangledName = newMangledName + typeName; } return newMangledName; } private static IDLType classToIDLType(Class c) { IDLType idlType = null; IDLTypesUtil idlTypesUtil = new IDLTypesUtil(); if( idlTypesUtil.isPrimitive(c) ) { idlType = idlTypesUtil.getPrimitiveIDLTypeMapping(c); } else if( c.isArray() ) { // Calculate array depth, as well as base element type. Class componentType = c.getComponentType(); int numArrayDimensions = 1; while(componentType.isArray()) { componentType = componentType.getComponentType(); numArrayDimensions++; } IDLType componentIdlType = classToIDLType(componentType); String[] modules = BASE_IDL_ARRAY_MODULE_TYPE; if( componentIdlType.hasModule() ) { modules = (String[])ObjectUtility.concatenateArrays( modules, componentIdlType.getModules() ) ; } String memberName = BASE_IDL_ARRAY_ELEMENT_TYPE + numArrayDimensions + UNDERSCORE + componentIdlType.getMemberName(); idlType = new IDLType(c, modules, memberName); } else { idlType = idlTypesUtil.getSpecialCaseIDLTypeMapping(c); if (idlType == null) { // Section 1.3.2.5 of Java2IDL spec defines mangling rules for // inner classes. String memberName = getUnmappedContainerName(c); // replace inner class separator with double underscore memberName = memberName.replaceAll("\\$", INNER_CLASS_SEPARATOR); if( hasLeadingUnderscore(memberName) ) { memberName = mangleLeadingUnderscore(memberName); } // Get raw package name. If there is a package, it // will still have the "." separators and none of the // mangling rules will have been applied. String packageName = getPackageName(c); if (packageName == null) { idlType = new IDLType( c, memberName ) ; } else { // If this is a generated IDL Entity Type we need to // prepend org_omg_boxedIDL per sections 1.3.5 and 1.3.9 if (idlTypesUtil.isEntity(c)) { packageName = "org.omg.boxedIDL." + packageName ; } // Section 1.3.2.1 and 1.3.2.6 of Java2IDL spec defines // rules for mapping java packages to IDL modules and for // mangling module name portion of type name. NOTE that // of the individual identifier mangling rules, // only the leading underscore test is done here. // The other two(IDL Keyword, Illegal Unicode chars) are // done in mangleOverloadedMethodName. StringTokenizer tokenizer = new StringTokenizer(packageName, "."); String[] modules = new String[ tokenizer.countTokens() ] ; int index = 0 ; while (tokenizer.hasMoreElements()) { String next = tokenizer.nextToken(); String moreMangled = hasLeadingUnderscore( next ) ? mangleLeadingUnderscore( next ) : next; modules[index++] = moreMangled ; } idlType = new IDLType(c, modules, memberName); } } } return idlType; } /** * Return Class' package name or null if there is no package. */ private static String getPackageName(Class c) { Package thePackage = c.getPackage(); String packageName = null; // Try to get package name by introspection. Some classloaders might // not provide this information, so check for null. if( thePackage != null ) { packageName = thePackage.getName(); } else { // brute force method String fullyQualifiedClassName = c.getName(); int lastDot = fullyQualifiedClassName.indexOf('.'); packageName = (lastDot == -1) ? null : fullyQualifiedClassName.substring(0, lastDot); } return packageName; } private static String getMappedContainerName(Class c) { String unmappedName = getUnmappedContainerName(c); return mangleIdentifier(unmappedName); } /** * Return portion of class name excluding package name. */ private static String getUnmappedContainerName(Class c) { String memberName = null; String packageName = getPackageName(c); String fullyQualifiedClassName = c.getName(); if( packageName != null ) { int packageLength = packageName.length(); memberName = fullyQualifiedClassName.substring(packageLength + 1); } else { memberName = fullyQualifiedClassName; } return memberName; } /** * Internal helper class for tracking information related to each * interface method while we're building the name translation table. */ private static class IDLMethodInfo { public Method method; public boolean isProperty; // If this is a property, originalName holds the original // attribute name. Otherwise, it holds the original method name. public String originalName; // If this is a property, mangledName holds the mangled attribute // name. Otherwise, it holds the mangled method name. public String mangledName; } public String toString() { StringBuffer contents = new StringBuffer(); contents.append("IDLNameTranslator[" ); for( int ctr=0; ctr<interf_.length; ctr++) { if (ctr != 0) contents.append( " " ) ; contents.append( interf_[ctr].getName() ) ; } contents.append("]\n"); for(Iterator iter = methodToIDLNameMap_.keySet().iterator(); iter.hasNext();) { Method method = (Method) iter.next(); String idlName = (String) methodToIDLNameMap_.get(method); contents.append(idlName + ":" + method + "\n"); } return contents.toString(); } public static void main(String[] args) { Class remoteInterface = java.rmi.Remote.class; if( args.length > 0 ) { String className = args[0]; try { remoteInterface = Class.forName(className); } catch(Exception e) { e.printStackTrace(); System.exit(-1); } } System.out.println("Building name translation for " + remoteInterface); try { IDLNameTranslator nameTranslator = IDLNameTranslatorImpl.get(remoteInterface); System.out.println(nameTranslator); } catch(IllegalStateException ise) { ise.printStackTrace(); } } }