| /* |
| * Copyright (c) 2003, 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. |
| */ |
| |
| 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(); |
| } |
| } |