duke@1: /* mbankal@371: * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@158: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@158: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@158: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@158: * or visit www.oracle.com if you need additional information or have any ohair@158: * questions. duke@1: */ duke@1: duke@1: /* duke@1: * Licensed Materials - Property of IBM duke@1: * RMI-IIOP v1.0 duke@1: * Copyright IBM Corp. 1998 1999 All Rights Reserved duke@1: * duke@1: */ duke@1: duke@1: package sun.rmi.rmic.iiop; duke@1: duke@1: import java.util.Hashtable; duke@1: import java.util.Locale; duke@1: import sun.tools.java.Identifier; duke@1: import sun.tools.java.CompilerError; duke@1: import sun.tools.java.ClassDefinition; duke@1: import sun.tools.java.ClassNotFound; duke@1: import com.sun.corba.se.impl.util.RepositoryId; duke@1: duke@1: /** duke@1: * IDLNames provides static utility methods to perform the IDL duke@1: * name mappings specified in Chapter 5 of the Java Language duke@1: * to IDL specification. duke@1: * duke@1: * @author Bryan Atsatt duke@1: */ duke@1: public class IDLNames implements sun.rmi.rmic.iiop.Constants { duke@1: duke@1: /** duke@1: * Used to convert ascii to hex. duke@1: */ duke@1: public static final byte ASCII_HEX[] = { duke@1: (byte)'0', duke@1: (byte)'1', duke@1: (byte)'2', duke@1: (byte)'3', duke@1: (byte)'4', duke@1: (byte)'5', duke@1: (byte)'6', duke@1: (byte)'7', duke@1: (byte)'8', duke@1: (byte)'9', duke@1: (byte)'A', duke@1: (byte)'B', duke@1: (byte)'C', duke@1: (byte)'D', duke@1: (byte)'E', duke@1: (byte)'F', duke@1: }; duke@1: mbankal@371: // Legal IDL Identifier characters (1 = legal). Note mbankal@371: // that '.' (2E) is marked as legal even though it is mbankal@371: // not legal in IDL. This allows us to treat a fully mbankal@371: // qualified Java name with '.' package separators mbankal@371: // uniformly, and is safe because that is the only mbankal@371: // legal use of '.' in a Java name. mbankal@371: mbankal@371: private static final byte[] IDL_IDENTIFIER_CHARS = { mbankal@371: mbankal@371: // 0 1 2 3 4 5 6 7 8 9 a b c d e f mbankal@371: 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 00-0f mbankal@371: 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 10-1f mbankal@371: 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,0, // 20-2f mbankal@371: 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, // 30-3f mbankal@371: 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 40-4f mbankal@371: 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,1, // 50-5f mbankal@371: 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 60-6f mbankal@371: 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, // 70-7f mbankal@371: 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 80-8f mbankal@371: 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 90-9f mbankal@371: 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // a0-af mbankal@371: 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // b0-bf mbankal@371: 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // c0-cf mbankal@371: 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // d0-df mbankal@371: 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // e0-ef mbankal@371: 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // f0-ff mbankal@371: }; mbankal@371: duke@1: //_____________________________________________________________________ duke@1: // Public Interfaces duke@1: //_____________________________________________________________________ duke@1: duke@1: /** duke@1: * Convert a name. The nameContext argument MUST be pre-filled with duke@1: * all names from the appropriate context (e.g. all the method names duke@1: * in a given class). The names must not have had any IDL conversions duke@1: * applied. duke@1: *

duke@1: * Section 28.3.2.2 duke@1: * Section 28.3.2.3 duke@1: * Section 28.3.2.4 duke@1: * Section 28.3.2.7 (member and method names only) duke@1: */ duke@1: public static String getMemberOrMethodName (NameContext nameContext, duke@1: String name, duke@1: BatchEnvironment env) { duke@1: duke@1: // Check namesCache... duke@1: duke@1: String result = (String) env.namesCache.get(name); duke@1: duke@1: if (result == null) { duke@1: duke@1: // 28.3.2.7 Case sensitive member names. duke@1: duke@1: // Note: This must be done before any of duke@1: // the other conversions! duke@1: duke@1: result = nameContext.get(name); duke@1: duke@1: // 28.3.2.3 Leading underscores... duke@1: duke@1: result = convertLeadingUnderscores(result); duke@1: duke@1: // 28.3.2.2 IDL keywords (NOTE: must be done duke@1: // after leading underscore conversion because duke@1: // the mangling for IDL keywords creates a duke@1: // leading underscore!)... duke@1: duke@1: result = convertIDLKeywords(result); duke@1: duke@1: // 28.3.2.4 Illegal IDL identifier characters... duke@1: duke@1: result = convertToISOLatin1(result); duke@1: duke@1: // Add to namesCache... duke@1: duke@1: env.namesCache.put(name,result); duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Convert names with illegal IDL identifier characters. duke@1: *

duke@1: * Section 28.3.2.4 duke@1: */ duke@1: public static String convertToISOLatin1 (String name) { duke@1: duke@1: // First, replace any escape sequences... duke@1: duke@1: String result = replace(name,"x\\u","U"); duke@1: result = replace(result,"x\\U","U"); duke@1: duke@1: // Now see if we have any remaining illegal characters (see mbankal@371: // IDL_IDENTIFIER_CHARS array)... duke@1: duke@1: int length = result.length(); duke@1: StringBuffer buffer = null; duke@1: duke@1: for (int i = 0; i < length; i++) { duke@1: duke@1: char c = result.charAt(i); duke@1: mbankal@371: if (c > 255 || IDL_IDENTIFIER_CHARS[c] == 0) { duke@1: duke@1: // We gotta convert. Have we already started? duke@1: duke@1: if (buffer == null) { duke@1: duke@1: // No, so get set up... duke@1: duke@1: buffer = new StringBuffer(result.substring(0,i)); duke@1: } duke@1: duke@1: // Convert the character into the IDL escape syntax... duke@1: duke@1: buffer.append("U"); duke@1: buffer.append((char)ASCII_HEX[(c & 0xF000) >>> 12]); duke@1: buffer.append((char)ASCII_HEX[(c & 0x0F00) >>> 8]); duke@1: buffer.append((char)ASCII_HEX[(c & 0x00F0) >>> 4]); duke@1: buffer.append((char)ASCII_HEX[(c & 0x000F)]); duke@1: duke@1: } else { duke@1: if (buffer != null) { duke@1: buffer.append(c); duke@1: } duke@1: } duke@1: } duke@1: duke@1: if (buffer != null) { duke@1: result = buffer.toString(); duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Convert names which collide with IDL keywords. duke@1: *

duke@1: * Section 28.3.2.5 duke@1: */ duke@1: public static String convertIDLKeywords (String name) { duke@1: duke@1: for (int i = 0; i < IDL_KEYWORDS.length; i++) { duke@1: if (name.equalsIgnoreCase(IDL_KEYWORDS[i])) { duke@1: return "_" + name; duke@1: } duke@1: } duke@1: duke@1: return name; duke@1: } duke@1: duke@1: /** duke@1: * Convert names which have leading underscores duke@1: *

duke@1: * Section 28.3.2.3 duke@1: */ duke@1: public static String convertLeadingUnderscores (String name) { duke@1: duke@1: if (name.startsWith("_")) { duke@1: return "J" + name; duke@1: } duke@1: duke@1: return name; duke@1: } duke@1: duke@1: /** duke@1: * Convert a type name. duke@1: *

duke@1: * Section 28.3.2.5 duke@1: * Section 28.3.2.7 (class or interface names only) duke@1: * Throws exception if fails 28.3.2.7. duke@1: */ duke@1: public static String getClassOrInterfaceName (Identifier id, duke@1: BatchEnvironment env) throws Exception { duke@1: duke@1: // Get the type and package name... duke@1: duke@1: String typeName = id.getName().toString(); duke@1: String packageName = null; duke@1: duke@1: if (id.isQualified()) { duke@1: packageName = id.getQualifier().toString(); duke@1: } duke@1: duke@1: // Check namesCache... duke@1: duke@1: String result = (String) env.namesCache.get(typeName); duke@1: duke@1: if (result == null) { duke@1: duke@1: // 28.3.2.5 Inner classes... duke@1: duke@1: result = replace(typeName,". ","__"); duke@1: duke@1: // 28.3.2.4 Illegal identifier characters... duke@1: duke@1: result = convertToISOLatin1(result); duke@1: duke@1: // 28.3.2.7 Case sensitive class or interface names... duke@1: duke@1: NameContext context = NameContext.forName(packageName,false,env); duke@1: context.assertPut(result); duke@1: duke@1: // Run it through the name checks... duke@1: duke@1: result = getTypeOrModuleName(result); duke@1: duke@1: // Add it to the namesCache... duke@1: duke@1: env.namesCache.put(typeName,result); duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Convert an Exception name. duke@1: *

duke@1: * Section 28.3.7.2 (see ValueType) duke@1: */ duke@1: public static String getExceptionName (String idlName) { duke@1: duke@1: String result = idlName; duke@1: // d.11315 Incorrectly mangled exception names duke@1: if (idlName.endsWith(EXCEPTION_SUFFIX)) { duke@1: duke@1: // Remove "Exception" and append "Ex". Strip leading underscore duke@1: // in case the idlName is exactly "_Exception"... duke@1: duke@1: result = stripLeadingUnderscore(idlName.substring(0,idlName.lastIndexOf(EXCEPTION_SUFFIX)) + EX_SUFFIX); duke@1: } else { duke@1: result = idlName + EX_SUFFIX; duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Convert a qualified Identifier into an array of IDL names. duke@1: *

duke@1: * Section 28.3.2.1 (see CompoundType) duke@1: * Throws exception if fails 28.3.2.7. duke@1: */ duke@1: public static String[] getModuleNames (Identifier theID, duke@1: boolean boxIt, duke@1: BatchEnvironment env) throws Exception { duke@1: duke@1: String[] result = null; duke@1: duke@1: if (theID.isQualified()) { duke@1: duke@1: // Extract the qualifier... duke@1: duke@1: Identifier id = theID.getQualifier(); duke@1: duke@1: // 28.3.2.7 Case sensitive module names. duke@1: duke@1: env.modulesContext.assertPut(id.toString()); duke@1: duke@1: // Count them... duke@1: duke@1: int count = 1; duke@1: Identifier current = id; duke@1: while (current.isQualified()) { duke@1: current = current.getQualifier(); duke@1: count++; duke@1: } duke@1: duke@1: result = new String[count]; duke@1: int index = count-1; duke@1: current = id; duke@1: duke@1: // Now walk them and fill our array (backwards)... duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: duke@1: String item = current.getName().toString(); duke@1: duke@1: // Check namesCache... duke@1: duke@1: String cachedItem = (String) env.namesCache.get(item); duke@1: duke@1: if (cachedItem == null) { duke@1: duke@1: // 28.3.2.4 Illegal identifier characters... duke@1: duke@1: cachedItem = convertToISOLatin1(item); duke@1: duke@1: // Run it through the name checks... duke@1: duke@1: cachedItem = getTypeOrModuleName(cachedItem); duke@1: duke@1: // Add it to the namesCache... duke@1: duke@1: env.namesCache.put(item,cachedItem); duke@1: } duke@1: duke@1: result[index--] = cachedItem; duke@1: current = current.getQualifier(); duke@1: } duke@1: } duke@1: duke@1: duke@1: // If it is supposed to be "boxed", prepend duke@1: // IDL_BOXEDIDL_MODULE... duke@1: duke@1: if (boxIt) { duke@1: if (result == null) { duke@1: result = IDL_BOXEDIDL_MODULE; duke@1: } else { duke@1: String[] boxed = new String[result.length+IDL_BOXEDIDL_MODULE.length]; duke@1: System.arraycopy(IDL_BOXEDIDL_MODULE,0,boxed,0,IDL_BOXEDIDL_MODULE.length); duke@1: System.arraycopy(result,0,boxed,IDL_BOXEDIDL_MODULE.length,result.length); duke@1: result = boxed; duke@1: } duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Get an array name with the specified dimensions. duke@1: *

duke@1: * Section 28.3.6 (see ArrayType) duke@1: */ duke@1: public static String getArrayName (Type theType, int arrayDimension) { duke@1: duke@1: StringBuffer idlName = new StringBuffer(64); duke@1: duke@1: // Prefix with seq_... duke@1: duke@1: idlName.append(IDL_SEQUENCE); duke@1: idlName.append(Integer.toString(arrayDimension)); duke@1: idlName.append("_"); duke@1: duke@1: // Add the type name. We need to map any spaces in the duke@1: // name to "_"... duke@1: duke@1: idlName.append(replace(stripLeadingUnderscore(theType.getIDLName())," ","_")); duke@1: duke@1: // And we're done... duke@1: duke@1: return idlName.toString(); duke@1: } duke@1: duke@1: /** duke@1: * Get an array module names. duke@1: */ duke@1: public static String[] getArrayModuleNames (Type theType) { duke@1: duke@1: String[] moduleName; duke@1: String[] typeModule = theType.getIDLModuleNames(); duke@1: int typeModuleLength = typeModule.length; duke@1: duke@1: // Does the type have a module? duke@1: duke@1: if (typeModuleLength == 0) { duke@1: duke@1: // Nope, so just use the sequence module... duke@1: duke@1: moduleName = IDL_SEQUENCE_MODULE; duke@1: } else { duke@1: duke@1: // Yes, so gotta concatenate... duke@1: duke@1: moduleName = new String[typeModuleLength + IDL_SEQUENCE_MODULE.length]; duke@1: System.arraycopy(IDL_SEQUENCE_MODULE,0,moduleName,0,IDL_SEQUENCE_MODULE.length); duke@1: System.arraycopy(typeModule,0,moduleName,IDL_SEQUENCE_MODULE.length,typeModuleLength); duke@1: } duke@1: duke@1: return moduleName; duke@1: } duke@1: duke@1: private static int getInitialAttributeKind (CompoundType.Method method, duke@1: BatchEnvironment env) throws ClassNotFound { duke@1: duke@1: int result = ATTRIBUTE_NONE; duke@1: duke@1: // First make sure it is not a constructor... duke@1: duke@1: if (!method.isConstructor()) { duke@1: duke@1: // Now check exceptions. It may not throw any checked duke@1: // exception other than RemoteException or one of its duke@1: // subclasses... duke@1: duke@1: boolean validExceptions = true; duke@1: ClassType[] exceptions = method.getExceptions(); duke@1: duke@1: if (exceptions.length > 0) { duke@1: for (int i = 0; i < exceptions.length; i++) { duke@1: if (exceptions[i].isCheckedException() && duke@1: !exceptions[i].isRemoteExceptionOrSubclass()) { duke@1: validExceptions = false; duke@1: break; duke@1: } duke@1: } duke@1: } else { duke@1: duke@1: // If this is a ValueType, it is ok to not have any exceptions, duke@1: // otherwise this method does not qualify... duke@1: duke@1: validExceptions = method.getEnclosing().isType(TYPE_VALUE); duke@1: } duke@1: duke@1: if (validExceptions) { duke@1: String name = method.getName(); duke@1: int nameLength = name.length(); duke@1: int argCount = method.getArguments().length; duke@1: Type returnType = method.getReturnType(); duke@1: boolean voidReturn = returnType.isType(TYPE_VOID); duke@1: boolean booleanReturn = returnType.isType(TYPE_BOOLEAN); duke@1: duke@1: // It's a getter if name starts with "get" and it has no arguments duke@1: // and a return type that is not void... duke@1: duke@1: if (name.startsWith("get") && nameLength > 3 && argCount == 0 && !voidReturn) { duke@1: result = ATTRIBUTE_GET; duke@1: } else { duke@1: duke@1: // It's a getter if name starts with "is" and it has no arguments duke@1: // and a boolean return type... duke@1: duke@1: if (name.startsWith("is") && nameLength > 2 && argCount == 0 && booleanReturn) { duke@1: result = ATTRIBUTE_IS; duke@1: } else { duke@1: duke@1: // It's a setter if name starts with "set" and it has 1 argument duke@1: // and a void return type... duke@1: duke@1: if (name.startsWith("set") && nameLength > 3 && argCount == 1 && voidReturn) { duke@1: result = ATTRIBUTE_SET; duke@1: } duke@1: } duke@1: } duke@1: } duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: private static void setAttributeKinds (CompoundType.Method[] methods, duke@1: int[] kinds, duke@1: String[] names) { duke@1: duke@1: int count = methods.length; duke@1: duke@1: // Strip the prefixes off of the attribute names... duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: switch (kinds[i]) { duke@1: case ATTRIBUTE_GET: names[i] = names[i].substring(3); break; duke@1: case ATTRIBUTE_IS: names[i] = names[i].substring(2); break; duke@1: case ATTRIBUTE_SET: names[i] = names[i].substring(3); break; duke@1: } duke@1: } duke@1: duke@1: // Now, we need to look at all the IS attributes to see duke@1: // if there is a corresponding getter or setter which has duke@1: // a different return type. If so, mark it as not an duke@1: // attribute. Do this before checking for invalid setters... duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: if (kinds[i] == ATTRIBUTE_IS) { duke@1: for (int j = 0; j < count; j++) { duke@1: if (j != i && duke@1: (kinds[j] == ATTRIBUTE_GET || kinds[j] == ATTRIBUTE_SET) && duke@1: names[i].equals(names[j])) { duke@1: duke@1: // We have matching getter or setter. Do the types match? duke@1: duke@1: Type isType = methods[i].getReturnType(); duke@1: Type targetType; duke@1: duke@1: if (kinds[j] == ATTRIBUTE_GET) { duke@1: targetType = methods[j].getReturnType(); duke@1: } else { duke@1: targetType = methods[j].getArguments()[0]; duke@1: } duke@1: duke@1: if (!isType.equals(targetType)) { duke@1: duke@1: // No, so forget this guy as an attribute... duke@1: duke@1: kinds[i] = ATTRIBUTE_NONE; duke@1: names[i] = methods[i].getName(); duke@1: break; duke@1: } duke@1: } duke@1: } duke@1: } duke@1: } duke@1: duke@1: // Now, we need to look at all the setters to see if there duke@1: // is a corresponding getter. If not, it is not a setter. duke@1: // If there is, change the getter type to _RW and set the duke@1: // pair index... duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: if (kinds[i] == ATTRIBUTE_SET) { duke@1: int getterIndex = -1; duke@1: int isGetterIndex = -1; duke@1: // First look for is-getters, then for getters. duke@1: // This is preferred for boolean attributes. duke@1: for (int j = 0; j < count; j++) { duke@1: if (j != i && names[i].equals(names[j])) { duke@1: // Yep, is the return type of the getter the same duke@1: // as the argument type of the setter? duke@1: duke@1: Type getterReturn = methods[j].getReturnType(); duke@1: Type setterArg = methods[i].getArguments()[0]; duke@1: duke@1: if (getterReturn.equals(setterArg)) { duke@1: if (kinds[j] == ATTRIBUTE_IS) { duke@1: isGetterIndex = j; duke@1: // continue looking for another getter duke@1: } else if (kinds[j] == ATTRIBUTE_GET) { duke@1: getterIndex = j; duke@1: // continue looking for an is-getter duke@1: } duke@1: } duke@1: } duke@1: } duke@1: duke@1: if (getterIndex > -1) { duke@1: if (isGetterIndex > -1) { duke@1: // We have both, a boolean is-getter and a boolean getter. duke@1: // Use the is-getter and drop the getter. duke@1: duke@1: // We have a matching getter. Change it to a read-write type... duke@1: kinds[isGetterIndex] = ATTRIBUTE_IS_RW; duke@1: duke@1: // Now set the pair index for both the getter and the setter... duke@1: methods[isGetterIndex].setAttributePairIndex(i); duke@1: methods[i].setAttributePairIndex(isGetterIndex); duke@1: duke@1: // We found a better matching is-getter. duke@1: // Forget this other getter as an attribute. duke@1: kinds[getterIndex] = ATTRIBUTE_NONE; duke@1: names[getterIndex] = methods[getterIndex].getName(); duke@1: } else { duke@1: // We only have one getter. duke@1: duke@1: // We have a matching getter. Change it to a read-write type... duke@1: kinds[getterIndex] = ATTRIBUTE_GET_RW; duke@1: duke@1: // Now set the pair index for both the getter and the setter... duke@1: methods[getterIndex].setAttributePairIndex(i); duke@1: methods[i].setAttributePairIndex(getterIndex); duke@1: } duke@1: } else { duke@1: if (isGetterIndex > -1) { duke@1: // We only have one is-getter. duke@1: duke@1: // We have a matching getter. Change it to a read-write type... duke@1: kinds[isGetterIndex] = ATTRIBUTE_IS_RW; duke@1: duke@1: // Now set the pair index for both the getter and the setter... duke@1: methods[isGetterIndex].setAttributePairIndex(i); duke@1: methods[i].setAttributePairIndex(isGetterIndex); duke@1: } else { duke@1: // We did not find a matching getter. duke@1: // Forget this setter as an attribute. duke@1: kinds[i] = ATTRIBUTE_NONE; duke@1: names[i] = methods[i].getName(); duke@1: } duke@1: } duke@1: } duke@1: } duke@1: duke@1: // Finally, do the case conversion and set the duke@1: // attribute kinds for each method... duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: duke@1: if (kinds[i] != ATTRIBUTE_NONE) { duke@1: duke@1: String name = names[i]; duke@1: duke@1: // Is the first character upper case? duke@1: duke@1: if (Character.isUpperCase(name.charAt(0))) { duke@1: duke@1: // Yes, is the second? duke@1: duke@1: if (name.length() == 1 || Character.isLowerCase(name.charAt(1))) { duke@1: duke@1: // No, so convert the first character to lower case... duke@1: duke@1: StringBuffer buffer = new StringBuffer(name); duke@1: buffer.setCharAt(0,Character.toLowerCase(name.charAt(0))); duke@1: names[i] = buffer.toString(); duke@1: } duke@1: } duke@1: } duke@1: duke@1: methods[i].setAttributeKind(kinds[i]); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Set all the method names in a given class. duke@1: *

duke@1: * Section 28.3.2.7 (see CompoundType) duke@1: * Section 28.3.2.7 duke@1: * Section 28.3.4.3 (RemoteType/AbstractType only). duke@1: */ duke@1: public static void setMethodNames (CompoundType container, duke@1: CompoundType.Method[] allMethods, duke@1: BatchEnvironment env) duke@1: throws Exception { duke@1: duke@1: // This method implements the following name mangling sequence: duke@1: // duke@1: // 1. If methods belong to a Remote interface, identify duke@1: // those which qualify as an attribute under 28.3.4.3. duke@1: // Those that do are referred to as 'attributes' below; duke@1: // those that do not are referred to as 'methods'. duke@1: // duke@1: // 2. Apply the 28.3.4.3 manglings, except "__", to all duke@1: // attribute names. duke@1: // duke@1: // 3. Apply all 28.3 manglings, except 28.3.2.7, to all names. duke@1: // duke@1: // 4. Apply 28.3.2.7 manglings to all method names. duke@1: // duke@1: // 5. Compare each attribute name to each method name. For duke@1: // any which compare equal, append "__" to the attribute duke@1: // name. duke@1: // duke@1: // 6. Compare each name (attribute and method) to all others. duke@1: // If any compare equal, throw an Exception with the duke@1: // conflicting name as the message. duke@1: duke@1: int count = allMethods.length; duke@1: duke@1: if (count == 0) return; duke@1: duke@1: // Make an array of all the method names... duke@1: duke@1: String[] names = new String[count]; duke@1: for (int i = 0; i < count; i++) { duke@1: names[i] = allMethods[i].getName(); duke@1: } duke@1: duke@1: // Are we dealing with a RemoteType, AbstractType, or ValueType? duke@1: duke@1: CompoundType enclosing = allMethods[0].getEnclosing(); duke@1: if (enclosing.isType(TYPE_REMOTE) || duke@1: enclosing.isType(TYPE_ABSTRACT) || duke@1: enclosing.isType(TYPE_VALUE)) { duke@1: duke@1: // Yes, so we must do the 28.3.4.3 attribute mapping. First, get duke@1: // the initial attribute kind of each method... duke@1: duke@1: int[] kinds = new int[count]; duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: kinds[i] = getInitialAttributeKind(allMethods[i],env); duke@1: } duke@1: duke@1: // Now set the attribute kind for each method and do the duke@1: // 28.3.4.3 name mangling... duke@1: duke@1: setAttributeKinds(allMethods,kinds,names); duke@1: } duke@1: duke@1: // Make and populate a new context from our names array... duke@1: duke@1: NameContext context = new NameContext(true); duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: context.put(names[i]); duke@1: } duke@1: duke@1: // Apply the appropriate 28.3 manglings to all the names... duke@1: duke@1: boolean haveConstructor = false; duke@1: for (int i = 0; i < count; i++) { duke@1: if (!allMethods[i].isConstructor()) { duke@1: names[i] = getMemberOrMethodName(context,names[i],env); duke@1: } else { duke@1: names[i] = IDL_CONSTRUCTOR; duke@1: haveConstructor = true; duke@1: } duke@1: } duke@1: duke@1: // Now do the 28.3.2.7 mangling for method name collisions... duke@1: // Do this in two passes so that we don't change one during duke@1: // the detection of collisions and then miss a real one... duke@1: duke@1: boolean overloaded[] = new boolean[count]; duke@1: for (int i = 0; i < count; i++) { duke@1: overloaded[i] = (!allMethods[i].isAttribute() && duke@1: !allMethods[i].isConstructor() && duke@1: doesMethodCollide(names[i],allMethods[i],allMethods,names,true)); duke@1: } duke@1: convertOverloadedMethods(allMethods,names,overloaded); duke@1: duke@1: // Now do the same mangling for constructor name collisions... duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: overloaded[i] = (!allMethods[i].isAttribute() && duke@1: allMethods[i].isConstructor() && duke@1: doesConstructorCollide(names[i],allMethods[i],allMethods,names,true)); duke@1: } duke@1: convertOverloadedMethods(allMethods,names,overloaded); duke@1: duke@1: // Now do the 28.3.4.3 mangling for attribute name collisions... duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: duke@1: CompoundType.Method method = allMethods[i]; duke@1: duke@1: // If this is an attribute name, does it collide with a method? duke@1: duke@1: if (method.isAttribute() && duke@1: doesMethodCollide(names[i],method,allMethods,names,true)) { duke@1: duke@1: // Yes, so add double underscore... duke@1: duke@1: names[i] += "__"; duke@1: } duke@1: } duke@1: duke@1: // Do the same mangling for any constructors which collide with duke@1: // methods... duke@1: duke@1: if (haveConstructor) { duke@1: for (int i = 0; i < count; i++) { duke@1: CompoundType.Method method = allMethods[i]; duke@1: duke@1: // Is this a constructor which collides with a method? duke@1: duke@1: if (method.isConstructor() && duke@1: doesConstructorCollide(names[i],method,allMethods,names,false)) { duke@1: duke@1: // Yes, so add double underscore... duke@1: duke@1: names[i] += "__"; duke@1: } duke@1: } duke@1: } duke@1: duke@1: // Now see if we have a collision with the container name (28.3.2.9). duke@1: duke@1: String containerName = container.getIDLName(); duke@1: for (int i = 0; i < count; i++) { duke@1: if (names[i].equalsIgnoreCase(containerName)) { duke@1: // Do not add underscore to attributes. duke@1: // Otherwise getFoo will turn into _get_foo_. duke@1: if (! allMethods[i].isAttribute()) { duke@1: names[i] += "_"; duke@1: } duke@1: } duke@1: } duke@1: duke@1: // Now see if we have any collisions (28.3.2.9). If we do, duke@1: // it's an error. Note: a get/set pair does not collide. duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: duke@1: // Does it collide with any other name? duke@1: duke@1: if (doesMethodCollide(names[i],allMethods[i],allMethods,names,false)) { duke@1: duke@1: // Yes, so bail... duke@1: duke@1: throw new Exception(allMethods[i].toString()); duke@1: } duke@1: } duke@1: duke@1: // Ok. We have unique names. Create the appropriate 'wire' name duke@1: // for each and set as the 'idl' name. If it is an attribute, also duke@1: // set the attribute name... duke@1: duke@1: for (int i = 0; i < count; i++) { duke@1: duke@1: CompoundType.Method method = allMethods[i]; duke@1: String wireName = names[i]; duke@1: duke@1: if (method.isAttribute()) { duke@1: wireName = ATTRIBUTE_WIRE_PREFIX[method.getAttributeKind()] + duke@1: stripLeadingUnderscore(wireName); duke@1: String attributeName = names[i]; duke@1: method.setAttributeName(attributeName); duke@1: } duke@1: method.setIDLName(wireName); duke@1: } duke@1: } duke@1: duke@1: private static String stripLeadingUnderscore (String name) { duke@1: if (name != null && name.length() > 1 duke@1: && name.charAt(0) == '_') duke@1: { duke@1: return name.substring(1); duke@1: } duke@1: return name; duke@1: } duke@1: duke@1: duke@1: private static String stripTrailingUnderscore (String name) { duke@1: if (name != null && name.length() > 1 && duke@1: name.charAt(name.length() - 1) == '_') duke@1: { duke@1: return name.substring(0, name.length() - 1); duke@1: } duke@1: return name; duke@1: } duke@1: duke@1: duke@1: private static void convertOverloadedMethods(CompoundType.Method[] allMethods, duke@1: String[] names, duke@1: boolean[] overloaded) { duke@1: duke@1: for (int i = 0; i < names.length; i++) { duke@1: duke@1: // Do we need to mangle it? duke@1: duke@1: if (overloaded[i]) { duke@1: duke@1: // Yes, so add arguments... duke@1: duke@1: CompoundType.Method method = allMethods[i]; duke@1: Type[] args = method.getArguments(); duke@1: duke@1: for (int k = 0; k < args.length; k++) { duke@1: duke@1: // Add the separator... duke@1: duke@1: names[i] += "__"; duke@1: duke@1: // Get the fully qualified IDL name, without the "::" duke@1: // prefix... duke@1: duke@1: String argIDLName = args[k].getQualifiedIDLName(false); duke@1: duke@1: // Replace any occurances of "::_" with "_" to duke@1: // undo any IDL keyword mangling and do next step duke@1: // at the same time... duke@1: duke@1: argIDLName = replace(argIDLName,"::_","_"); duke@1: duke@1: // Replace any occurances of "::" with "_"... duke@1: duke@1: argIDLName = replace(argIDLName,"::","_"); duke@1: duke@1: // Replace any occurances of " " with "_"... duke@1: duke@1: argIDLName = replace(argIDLName," ","_"); duke@1: duke@1: // Add the argument type name... duke@1: duke@1: names[i] += argIDLName; duke@1: } duke@1: duke@1: if (args.length == 0) { duke@1: names[i] += "__"; duke@1: } duke@1: duke@1: // Remove any IDL keyword mangling... duke@1: duke@1: names[i] = stripLeadingUnderscore(names[i]); duke@1: } duke@1: } duke@1: } duke@1: duke@1: private static boolean doesMethodCollide (String name, duke@1: CompoundType.Method method, duke@1: CompoundType.Method[] allMethods, duke@1: String[] allNames, duke@1: boolean ignoreAttributes) { duke@1: duke@1: // Scan all methods looking for a match... duke@1: duke@1: for (int i = 0; i < allMethods.length; i++) { duke@1: duke@1: CompoundType.Method target = allMethods[i]; duke@1: duke@1: if (method != target && // Not same instance duke@1: !target.isConstructor() && // Not a constructor duke@1: (!ignoreAttributes || !target.isAttribute()) && // Correct kind duke@1: name.equals(allNames[i])) { // Same names duke@1: duke@1: // Are we looking at a get/set pair? duke@1: duke@1: int kind1 = method.getAttributeKind(); duke@1: int kind2 = target.getAttributeKind(); duke@1: duke@1: if ((kind1 != ATTRIBUTE_NONE && kind2 != ATTRIBUTE_NONE) && duke@1: ((kind1 == ATTRIBUTE_SET && kind2 != ATTRIBUTE_SET) || duke@1: (kind1 != ATTRIBUTE_SET && kind2 == ATTRIBUTE_SET) || duke@1: // one is a is-getter/setter pair and the other is just a getter duke@1: (kind1 == ATTRIBUTE_IS_RW && kind2 == ATTRIBUTE_GET) || duke@1: (kind1 == ATTRIBUTE_GET && kind2 == ATTRIBUTE_IS_RW))) { duke@1: duke@1: // Yes, so ignore it... duke@1: duke@1: } else { duke@1: duke@1: // No, so we have a collision... duke@1: duke@1: return true; duke@1: } duke@1: } duke@1: } duke@1: duke@1: return false; duke@1: } duke@1: duke@1: private static boolean doesConstructorCollide (String name, duke@1: CompoundType.Method method, duke@1: CompoundType.Method[] allMethods, duke@1: String[] allNames, duke@1: boolean compareConstructors) { duke@1: duke@1: // Scan all methods looking for a match... duke@1: duke@1: for (int i = 0; i < allMethods.length; i++) { duke@1: duke@1: CompoundType.Method target = allMethods[i]; duke@1: duke@1: if (method != target && // Not same instance duke@1: (target.isConstructor() == compareConstructors) && // Correct kind duke@1: name.equals(allNames[i])) { // Same names duke@1: duke@1: // We have a collision... duke@1: duke@1: return true; duke@1: } duke@1: } duke@1: duke@1: return false; duke@1: } duke@1: duke@1: duke@1: /** duke@1: * Set all the member names in a given class. duke@1: *

duke@1: * Section 28.3.2.7 (see CompoundType) duke@1: * Section 28.3.2.7 duke@1: */ duke@1: public static void setMemberNames (CompoundType container, duke@1: CompoundType.Member[] allMembers, duke@1: CompoundType.Method[] allMethods, duke@1: BatchEnvironment env) duke@1: throws Exception { duke@1: duke@1: // Make and populate a new context... duke@1: duke@1: NameContext context = new NameContext(true); duke@1: duke@1: for (int i = 0; i < allMembers.length; i++) { duke@1: context.put(allMembers[i].getName()); duke@1: } duke@1: duke@1: // Now set all the idl names... duke@1: duke@1: for (int i = 0; i < allMembers.length; i++) { duke@1: duke@1: CompoundType.Member member = allMembers[i]; duke@1: String idlName = getMemberOrMethodName(context,member.getName(),env); duke@1: member.setIDLName(idlName); duke@1: } duke@1: duke@1: // First see if we have a collision with the container name (28.3.2.9). duke@1: duke@1: String containerName = container.getIDLName(); duke@1: for (int i = 0; i < allMembers.length; i++) { duke@1: String name = allMembers[i].getIDLName(); duke@1: if (name.equalsIgnoreCase(containerName)) { duke@1: // REVISIT - How is this different than line 788 duke@1: allMembers[i].setIDLName(name+"_"); duke@1: } duke@1: } duke@1: duke@1: // Check for collisions between member names... duke@1: duke@1: for (int i = 0; i < allMembers.length; i++) { duke@1: String name = allMembers[i].getIDLName(); duke@1: for (int j = 0; j < allMembers.length; j++) { duke@1: if (i != j && allMembers[j].getIDLName().equals(name)) { duke@1: duke@1: // Collision... duke@1: duke@1: throw new Exception(name); duke@1: } duke@1: } duke@1: } duke@1: duke@1: // Now check for collisions between member names and duke@1: // method names... duke@1: duke@1: boolean changed; duke@1: do { duke@1: changed = false; duke@1: for (int i = 0; i < allMembers.length; i++) { duke@1: String name = allMembers[i].getIDLName(); duke@1: for (int j = 0; j < allMethods.length; j++) { duke@1: if (allMethods[j].getIDLName().equals(name)) { duke@1: duke@1: // Collision, so append "_" to member name... duke@1: duke@1: allMembers[i].setIDLName(name+"_"); duke@1: changed = true; duke@1: break; duke@1: } duke@1: } duke@1: } duke@1: } while (changed); duke@1: } duke@1: duke@1: /** duke@1: * Get the name for the specified type code. duke@1: *

duke@1: * Section 28.3..3 (see PrimitiveType) duke@1: * Section 28.3.5.10 (see SpecialClassType) duke@1: * Section 28.3.4.1 (see SpecialInterfaceType) duke@1: * Section 28.3.10.1 (see SpecialInterfaceType) duke@1: * Section 28.3.10.2 (see SpecialClassType) duke@1: */ duke@1: public static String getTypeName(int typeCode, boolean isConstant) { duke@1: duke@1: String idlName = null; duke@1: duke@1: switch (typeCode) { duke@1: case TYPE_VOID: idlName = IDL_VOID; break; duke@1: case TYPE_BOOLEAN: idlName = IDL_BOOLEAN; break; duke@1: case TYPE_BYTE: idlName = IDL_BYTE; break; duke@1: case TYPE_CHAR: idlName = IDL_CHAR; break; duke@1: case TYPE_SHORT: idlName = IDL_SHORT; break; duke@1: case TYPE_INT: idlName = IDL_INT; break; duke@1: case TYPE_LONG: idlName = IDL_LONG; break; duke@1: case TYPE_FLOAT: idlName = IDL_FLOAT; break; duke@1: case TYPE_DOUBLE: idlName = IDL_DOUBLE; break; duke@1: case TYPE_ANY: idlName = IDL_ANY; break; duke@1: case TYPE_CORBA_OBJECT: idlName = IDL_CORBA_OBJECT; break; duke@1: case TYPE_STRING: duke@1: { duke@1: if (isConstant) { duke@1: idlName = IDL_CONSTANT_STRING; duke@1: } else { duke@1: idlName = IDL_STRING; duke@1: } duke@1: duke@1: break; duke@1: } duke@1: } duke@1: duke@1: return idlName; duke@1: } duke@1: duke@1: /** duke@1: * Create a qualified name. duke@1: */ duke@1: public static String getQualifiedName (String[] idlModuleNames, String idlName) { duke@1: String result = null; duke@1: if (idlModuleNames != null && idlModuleNames.length > 0) { duke@1: for (int i = 0; i < idlModuleNames.length;i++) { duke@1: if (i == 0) { duke@1: result = idlModuleNames[0]; duke@1: } else { duke@1: result += IDL_NAME_SEPARATOR; duke@1: result += idlModuleNames[i]; duke@1: } duke@1: } duke@1: result += IDL_NAME_SEPARATOR; duke@1: result += idlName; duke@1: } else { duke@1: result = idlName; duke@1: } duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Replace substrings duke@1: * @param source The source string. duke@1: * @param match The string to search for within the source string. duke@1: * @param replace The replacement for any matching components. duke@1: * @return duke@1: */ duke@1: public static String replace (String source, String match, String replace) { duke@1: duke@1: int index = source.indexOf(match,0); duke@1: duke@1: if (index >=0) { duke@1: duke@1: // We have at least one match, so gotta do the duke@1: // work... duke@1: duke@1: StringBuffer result = new StringBuffer(source.length() + 16); duke@1: int matchLength = match.length(); duke@1: int startIndex = 0; duke@1: duke@1: while (index >= 0) { duke@1: result.append(source.substring(startIndex,index)); duke@1: result.append(replace); duke@1: startIndex = index + matchLength; duke@1: index = source.indexOf(match,startIndex); duke@1: } duke@1: duke@1: // Grab the last piece, if any... duke@1: duke@1: if (startIndex < source.length()) { duke@1: result.append(source.substring(startIndex)); duke@1: } duke@1: duke@1: return result.toString(); duke@1: duke@1: } else { duke@1: duke@1: // No matches, just return the source... duke@1: duke@1: return source; duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Get an IDL style repository id for duke@1: */ duke@1: public static String getIDLRepositoryID (String idlName) { duke@1: return IDL_REPOSITORY_ID_PREFIX + duke@1: replace(idlName,"::", "/") + duke@1: IDL_REPOSITORY_ID_VERSION; duke@1: } duke@1: duke@1: //_____________________________________________________________________ duke@1: // Internal Interfaces duke@1: //_____________________________________________________________________ duke@1: duke@1: duke@1: /** duke@1: * Convert a type or module name. duke@1: *

duke@1: * Section 28.3.2.2 duke@1: * Section 28.3.2.3 duke@1: */ duke@1: private static String getTypeOrModuleName (String name) { duke@1: duke@1: // 28.3.2.3 Leading underscores... duke@1: duke@1: String result = convertLeadingUnderscores(name); duke@1: duke@1: // 28.3.2.2 IDL keywords (NOTE: must be done duke@1: // after leading underscore conversion because duke@1: // the mangling for IDL keywords creates a duke@1: // leading underscore!)... duke@1: duke@1: return convertIDLKeywords(result); duke@1: } duke@1: }