/* * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * Licensed Materials - Property of IBM * RMI-IIOP v1.0 * Copyright IBM Corp. 1998 1999 All Rights Reserved * */ package sun.rmi.rmic.iiop; import java.util.Hashtable; import java.util.Locale; import sun.tools.java.Identifier; import sun.tools.java.CompilerError; import sun.tools.java.ClassDefinition; import sun.tools.java.ClassNotFound; import com.sun.corba.se.impl.util.RepositoryId; /** * IDLNames provides static utility methods to perform the IDL * name mappings specified in Chapter 5 of the Java Language * to IDL specification. * * @author Bryan Atsatt */ public class IDLNames implements sun.rmi.rmic.iiop.Constants { /** * Used to convert ascii to hex. */ public static final byte ASCII_HEX[] = { (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', }; // Legal IDL Identifier characters (1 = legal). Note // that '.' (2E) is marked as legal even though it is // not legal in IDL. This allows us to treat a fully // qualified Java name with '.' package separators // uniformly, and is safe because that is the only // legal use of '.' in a Java name. private static final byte[] IDL_IDENTIFIER_CHARS = { // 0 1 2 3 4 5 6 7 8 9 a b c d e f 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 00-0f 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 10-1f 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,0, // 20-2f 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, // 30-3f 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 40-4f 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,1, // 50-5f 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 60-6f 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, // 70-7f 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 80-8f 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 90-9f 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // a0-af 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // b0-bf 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // c0-cf 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // d0-df 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // e0-ef 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // f0-ff }; //_____________________________________________________________________ // Public Interfaces //_____________________________________________________________________ /** * Convert a name. The nameContext argument MUST be pre-filled with * all names from the appropriate context (e.g. all the method names * in a given class). The names must not have had any IDL conversions * applied. *
* Section 28.3.2.2 * Section 28.3.2.3 * Section 28.3.2.4 * Section 28.3.2.7 (member and method names only) */ public static String getMemberOrMethodName (NameContext nameContext, String name, BatchEnvironment env) { // Check namesCache... String result = (String) env.namesCache.get(name); if (result == null) { // 28.3.2.7 Case sensitive member names. // Note: This must be done before any of // the other conversions! result = nameContext.get(name); // 28.3.2.3 Leading underscores... result = convertLeadingUnderscores(result); // 28.3.2.2 IDL keywords (NOTE: must be done // after leading underscore conversion because // the mangling for IDL keywords creates a // leading underscore!)... result = convertIDLKeywords(result); // 28.3.2.4 Illegal IDL identifier characters... result = convertToISOLatin1(result); // Add to namesCache... env.namesCache.put(name,result); } return result; } /** * Convert names with illegal IDL identifier characters. *
* Section 28.3.2.4 */ public static String convertToISOLatin1 (String name) { // First, replace any escape sequences... String result = replace(name,"x\\u","U"); result = replace(result,"x\\U","U"); // Now see if we have any remaining illegal characters (see // IDL_IDENTIFIER_CHARS array)... int length = result.length(); StringBuffer buffer = null; for (int i = 0; i < length; i++) { char c = result.charAt(i); if (c > 255 || IDL_IDENTIFIER_CHARS[c] == 0) { // We gotta convert. Have we already started? if (buffer == null) { // No, so get set up... buffer = new StringBuffer(result.substring(0,i)); } // Convert the character into the IDL escape syntax... buffer.append("U"); buffer.append((char)ASCII_HEX[(c & 0xF000) >>> 12]); buffer.append((char)ASCII_HEX[(c & 0x0F00) >>> 8]); buffer.append((char)ASCII_HEX[(c & 0x00F0) >>> 4]); buffer.append((char)ASCII_HEX[(c & 0x000F)]); } else { if (buffer != null) { buffer.append(c); } } } if (buffer != null) { result = buffer.toString(); } return result; } /** * Convert names which collide with IDL keywords. *
* Section 28.3.2.5 */ public static String convertIDLKeywords (String name) { for (int i = 0; i < IDL_KEYWORDS.length; i++) { if (name.equalsIgnoreCase(IDL_KEYWORDS[i])) { return "_" + name; } } return name; } /** * Convert names which have leading underscores *
* Section 28.3.2.3 */ public static String convertLeadingUnderscores (String name) { if (name.startsWith("_")) { return "J" + name; } return name; } /** * Convert a type name. *
* Section 28.3.2.5 * Section 28.3.2.7 (class or interface names only) * Throws exception if fails 28.3.2.7. */ public static String getClassOrInterfaceName (Identifier id, BatchEnvironment env) throws Exception { // Get the type and package name... String typeName = id.getName().toString(); String packageName = null; if (id.isQualified()) { packageName = id.getQualifier().toString(); } // Check namesCache... String result = (String) env.namesCache.get(typeName); if (result == null) { // 28.3.2.5 Inner classes... result = replace(typeName,". ","__"); // 28.3.2.4 Illegal identifier characters... result = convertToISOLatin1(result); // 28.3.2.7 Case sensitive class or interface names... NameContext context = NameContext.forName(packageName,false,env); context.assertPut(result); // Run it through the name checks... result = getTypeOrModuleName(result); // Add it to the namesCache... env.namesCache.put(typeName,result); } return result; } /** * Convert an Exception name. *
* Section 28.3.7.2 (see ValueType) */ public static String getExceptionName (String idlName) { String result = idlName; // d.11315 Incorrectly mangled exception names if (idlName.endsWith(EXCEPTION_SUFFIX)) { // Remove "Exception" and append "Ex". Strip leading underscore // in case the idlName is exactly "_Exception"... result = stripLeadingUnderscore(idlName.substring(0,idlName.lastIndexOf(EXCEPTION_SUFFIX)) + EX_SUFFIX); } else { result = idlName + EX_SUFFIX; } return result; } /** * Convert a qualified Identifier into an array of IDL names. *
* Section 28.3.2.1 (see CompoundType) * Throws exception if fails 28.3.2.7. */ public static String[] getModuleNames (Identifier theID, boolean boxIt, BatchEnvironment env) throws Exception { String[] result = null; if (theID.isQualified()) { // Extract the qualifier... Identifier id = theID.getQualifier(); // 28.3.2.7 Case sensitive module names. env.modulesContext.assertPut(id.toString()); // Count them... int count = 1; Identifier current = id; while (current.isQualified()) { current = current.getQualifier(); count++; } result = new String[count]; int index = count-1; current = id; // Now walk them and fill our array (backwards)... for (int i = 0; i < count; i++) { String item = current.getName().toString(); // Check namesCache... String cachedItem = (String) env.namesCache.get(item); if (cachedItem == null) { // 28.3.2.4 Illegal identifier characters... cachedItem = convertToISOLatin1(item); // Run it through the name checks... cachedItem = getTypeOrModuleName(cachedItem); // Add it to the namesCache... env.namesCache.put(item,cachedItem); } result[index--] = cachedItem; current = current.getQualifier(); } } // If it is supposed to be "boxed", prepend // IDL_BOXEDIDL_MODULE... if (boxIt) { if (result == null) { result = IDL_BOXEDIDL_MODULE; } else { String[] boxed = new String[result.length+IDL_BOXEDIDL_MODULE.length]; System.arraycopy(IDL_BOXEDIDL_MODULE,0,boxed,0,IDL_BOXEDIDL_MODULE.length); System.arraycopy(result,0,boxed,IDL_BOXEDIDL_MODULE.length,result.length); result = boxed; } } return result; } /** * Get an array name with the specified dimensions. *
* Section 28.3.6 (see ArrayType)
*/
public static String getArrayName (Type theType, int arrayDimension) {
StringBuffer idlName = new StringBuffer(64);
// Prefix with seq
* Section 28.3.2.7 (see CompoundType)
* Section 28.3.2.7
* Section 28.3.4.3 (RemoteType/AbstractType only).
*/
public static void setMethodNames (CompoundType container,
CompoundType.Method[] allMethods,
BatchEnvironment env)
throws Exception {
// This method implements the following name mangling sequence:
//
// 1. If methods belong to a Remote interface, identify
// those which qualify as an attribute under 28.3.4.3.
// Those that do are referred to as 'attributes' below;
// those that do not are referred to as 'methods'.
//
// 2. Apply the 28.3.4.3 manglings, except "__", to all
// attribute names.
//
// 3. Apply all 28.3 manglings, except 28.3.2.7, to all names.
//
// 4. Apply 28.3.2.7 manglings to all method names.
//
// 5. Compare each attribute name to each method name. For
// any which compare equal, append "__" to the attribute
// name.
//
// 6. Compare each name (attribute and method) to all others.
// If any compare equal, throw an Exception with the
// conflicting name as the message.
int count = allMethods.length;
if (count == 0) return;
// Make an array of all the method names...
String[] names = new String[count];
for (int i = 0; i < count; i++) {
names[i] = allMethods[i].getName();
}
// Are we dealing with a RemoteType, AbstractType, or ValueType?
CompoundType enclosing = allMethods[0].getEnclosing();
if (enclosing.isType(TYPE_REMOTE) ||
enclosing.isType(TYPE_ABSTRACT) ||
enclosing.isType(TYPE_VALUE)) {
// Yes, so we must do the 28.3.4.3 attribute mapping. First, get
// the initial attribute kind of each method...
int[] kinds = new int[count];
for (int i = 0; i < count; i++) {
kinds[i] = getInitialAttributeKind(allMethods[i],env);
}
// Now set the attribute kind for each method and do the
// 28.3.4.3 name mangling...
setAttributeKinds(allMethods,kinds,names);
}
// Make and populate a new context from our names array...
NameContext context = new NameContext(true);
for (int i = 0; i < count; i++) {
context.put(names[i]);
}
// Apply the appropriate 28.3 manglings to all the names...
boolean haveConstructor = false;
for (int i = 0; i < count; i++) {
if (!allMethods[i].isConstructor()) {
names[i] = getMemberOrMethodName(context,names[i],env);
} else {
names[i] = IDL_CONSTRUCTOR;
haveConstructor = true;
}
}
// Now do the 28.3.2.7 mangling for method name collisions...
// Do this in two passes so that we don't change one during
// the detection of collisions and then miss a real one...
boolean overloaded[] = new boolean[count];
for (int i = 0; i < count; i++) {
overloaded[i] = (!allMethods[i].isAttribute() &&
!allMethods[i].isConstructor() &&
doesMethodCollide(names[i],allMethods[i],allMethods,names,true));
}
convertOverloadedMethods(allMethods,names,overloaded);
// Now do the same mangling for constructor name collisions...
for (int i = 0; i < count; i++) {
overloaded[i] = (!allMethods[i].isAttribute() &&
allMethods[i].isConstructor() &&
doesConstructorCollide(names[i],allMethods[i],allMethods,names,true));
}
convertOverloadedMethods(allMethods,names,overloaded);
// Now do the 28.3.4.3 mangling for attribute name collisions...
for (int i = 0; i < count; i++) {
CompoundType.Method method = allMethods[i];
// If this is an attribute name, does it collide with a method?
if (method.isAttribute() &&
doesMethodCollide(names[i],method,allMethods,names,true)) {
// Yes, so add double underscore...
names[i] += "__";
}
}
// Do the same mangling for any constructors which collide with
// methods...
if (haveConstructor) {
for (int i = 0; i < count; i++) {
CompoundType.Method method = allMethods[i];
// Is this a constructor which collides with a method?
if (method.isConstructor() &&
doesConstructorCollide(names[i],method,allMethods,names,false)) {
// Yes, so add double underscore...
names[i] += "__";
}
}
}
// Now see if we have a collision with the container name (28.3.2.9).
String containerName = container.getIDLName();
for (int i = 0; i < count; i++) {
if (names[i].equalsIgnoreCase(containerName)) {
// Do not add underscore to attributes.
// Otherwise getFoo will turn into _get_foo_.
if (! allMethods[i].isAttribute()) {
names[i] += "_";
}
}
}
// Now see if we have any collisions (28.3.2.9). If we do,
// it's an error. Note: a get/set pair does not collide.
for (int i = 0; i < count; i++) {
// Does it collide with any other name?
if (doesMethodCollide(names[i],allMethods[i],allMethods,names,false)) {
// Yes, so bail...
throw new Exception(allMethods[i].toString());
}
}
// Ok. We have unique names. Create the appropriate 'wire' name
// for each and set as the 'idl' name. If it is an attribute, also
// set the attribute name...
for (int i = 0; i < count; i++) {
CompoundType.Method method = allMethods[i];
String wireName = names[i];
if (method.isAttribute()) {
wireName = ATTRIBUTE_WIRE_PREFIX[method.getAttributeKind()] +
stripLeadingUnderscore(wireName);
String attributeName = names[i];
method.setAttributeName(attributeName);
}
method.setIDLName(wireName);
}
}
private static String stripLeadingUnderscore (String name) {
if (name != null && name.length() > 1
&& name.charAt(0) == '_')
{
return name.substring(1);
}
return name;
}
private static String stripTrailingUnderscore (String name) {
if (name != null && name.length() > 1 &&
name.charAt(name.length() - 1) == '_')
{
return name.substring(0, name.length() - 1);
}
return name;
}
private static void convertOverloadedMethods(CompoundType.Method[] allMethods,
String[] names,
boolean[] overloaded) {
for (int i = 0; i < names.length; i++) {
// Do we need to mangle it?
if (overloaded[i]) {
// Yes, so add arguments...
CompoundType.Method method = allMethods[i];
Type[] args = method.getArguments();
for (int k = 0; k < args.length; k++) {
// Add the separator...
names[i] += "__";
// Get the fully qualified IDL name, without the "::"
// prefix...
String argIDLName = args[k].getQualifiedIDLName(false);
// Replace any occurances of "::_" with "_" to
// undo any IDL keyword mangling and do next step
// at the same time...
argIDLName = replace(argIDLName,"::_","_");
// Replace any occurances of "::" with "_"...
argIDLName = replace(argIDLName,"::","_");
// Replace any occurances of " " with "_"...
argIDLName = replace(argIDLName," ","_");
// Add the argument type name...
names[i] += argIDLName;
}
if (args.length == 0) {
names[i] += "__";
}
// Remove any IDL keyword mangling...
names[i] = stripLeadingUnderscore(names[i]);
}
}
}
private static boolean doesMethodCollide (String name,
CompoundType.Method method,
CompoundType.Method[] allMethods,
String[] allNames,
boolean ignoreAttributes) {
// Scan all methods looking for a match...
for (int i = 0; i < allMethods.length; i++) {
CompoundType.Method target = allMethods[i];
if (method != target && // Not same instance
!target.isConstructor() && // Not a constructor
(!ignoreAttributes || !target.isAttribute()) && // Correct kind
name.equals(allNames[i])) { // Same names
// Are we looking at a get/set pair?
int kind1 = method.getAttributeKind();
int kind2 = target.getAttributeKind();
if ((kind1 != ATTRIBUTE_NONE && kind2 != ATTRIBUTE_NONE) &&
((kind1 == ATTRIBUTE_SET && kind2 != ATTRIBUTE_SET) ||
(kind1 != ATTRIBUTE_SET && kind2 == ATTRIBUTE_SET) ||
// one is a is-getter/setter pair and the other is just a getter
(kind1 == ATTRIBUTE_IS_RW && kind2 == ATTRIBUTE_GET) ||
(kind1 == ATTRIBUTE_GET && kind2 == ATTRIBUTE_IS_RW))) {
// Yes, so ignore it...
} else {
// No, so we have a collision...
return true;
}
}
}
return false;
}
private static boolean doesConstructorCollide (String name,
CompoundType.Method method,
CompoundType.Method[] allMethods,
String[] allNames,
boolean compareConstructors) {
// Scan all methods looking for a match...
for (int i = 0; i < allMethods.length; i++) {
CompoundType.Method target = allMethods[i];
if (method != target && // Not same instance
(target.isConstructor() == compareConstructors) && // Correct kind
name.equals(allNames[i])) { // Same names
// We have a collision...
return true;
}
}
return false;
}
/**
* Set all the member names in a given class.
*
* Section 28.3.2.7 (see CompoundType)
* Section 28.3.2.7
*/
public static void setMemberNames (CompoundType container,
CompoundType.Member[] allMembers,
CompoundType.Method[] allMethods,
BatchEnvironment env)
throws Exception {
// Make and populate a new context...
NameContext context = new NameContext(true);
for (int i = 0; i < allMembers.length; i++) {
context.put(allMembers[i].getName());
}
// Now set all the idl names...
for (int i = 0; i < allMembers.length; i++) {
CompoundType.Member member = allMembers[i];
String idlName = getMemberOrMethodName(context,member.getName(),env);
member.setIDLName(idlName);
}
// First see if we have a collision with the container name (28.3.2.9).
String containerName = container.getIDLName();
for (int i = 0; i < allMembers.length; i++) {
String name = allMembers[i].getIDLName();
if (name.equalsIgnoreCase(containerName)) {
// REVISIT - How is this different than line 788
allMembers[i].setIDLName(name+"_");
}
}
// Check for collisions between member names...
for (int i = 0; i < allMembers.length; i++) {
String name = allMembers[i].getIDLName();
for (int j = 0; j < allMembers.length; j++) {
if (i != j && allMembers[j].getIDLName().equals(name)) {
// Collision...
throw new Exception(name);
}
}
}
// Now check for collisions between member names and
// method names...
boolean changed;
do {
changed = false;
for (int i = 0; i < allMembers.length; i++) {
String name = allMembers[i].getIDLName();
for (int j = 0; j < allMethods.length; j++) {
if (allMethods[j].getIDLName().equals(name)) {
// Collision, so append "_" to member name...
allMembers[i].setIDLName(name+"_");
changed = true;
break;
}
}
}
} while (changed);
}
/**
* Get the name for the specified type code.
*
* Section 28.3..3 (see PrimitiveType)
* Section 28.3.5.10 (see SpecialClassType)
* Section 28.3.4.1 (see SpecialInterfaceType)
* Section 28.3.10.1 (see SpecialInterfaceType)
* Section 28.3.10.2 (see SpecialClassType)
*/
public static String getTypeName(int typeCode, boolean isConstant) {
String idlName = null;
switch (typeCode) {
case TYPE_VOID: idlName = IDL_VOID; break;
case TYPE_BOOLEAN: idlName = IDL_BOOLEAN; break;
case TYPE_BYTE: idlName = IDL_BYTE; break;
case TYPE_CHAR: idlName = IDL_CHAR; break;
case TYPE_SHORT: idlName = IDL_SHORT; break;
case TYPE_INT: idlName = IDL_INT; break;
case TYPE_LONG: idlName = IDL_LONG; break;
case TYPE_FLOAT: idlName = IDL_FLOAT; break;
case TYPE_DOUBLE: idlName = IDL_DOUBLE; break;
case TYPE_ANY: idlName = IDL_ANY; break;
case TYPE_CORBA_OBJECT: idlName = IDL_CORBA_OBJECT; break;
case TYPE_STRING:
{
if (isConstant) {
idlName = IDL_CONSTANT_STRING;
} else {
idlName = IDL_STRING;
}
break;
}
}
return idlName;
}
/**
* Create a qualified name.
*/
public static String getQualifiedName (String[] idlModuleNames, String idlName) {
String result = null;
if (idlModuleNames != null && idlModuleNames.length > 0) {
for (int i = 0; i < idlModuleNames.length;i++) {
if (i == 0) {
result = idlModuleNames[0];
} else {
result += IDL_NAME_SEPARATOR;
result += idlModuleNames[i];
}
}
result += IDL_NAME_SEPARATOR;
result += idlName;
} else {
result = idlName;
}
return result;
}
/**
* Replace substrings
* @param source The source string.
* @param match The string to search for within the source string.
* @param replace The replacement for any matching components.
* @return
*/
public static String replace (String source, String match, String replace) {
int index = source.indexOf(match,0);
if (index >=0) {
// We have at least one match, so gotta do the
// work...
StringBuffer result = new StringBuffer(source.length() + 16);
int matchLength = match.length();
int startIndex = 0;
while (index >= 0) {
result.append(source.substring(startIndex,index));
result.append(replace);
startIndex = index + matchLength;
index = source.indexOf(match,startIndex);
}
// Grab the last piece, if any...
if (startIndex < source.length()) {
result.append(source.substring(startIndex));
}
return result.toString();
} else {
// No matches, just return the source...
return source;
}
}
/**
* Get an IDL style repository id for
*/
public static String getIDLRepositoryID (String idlName) {
return IDL_REPOSITORY_ID_PREFIX +
replace(idlName,"::", "/") +
IDL_REPOSITORY_ID_VERSION;
}
//_____________________________________________________________________
// Internal Interfaces
//_____________________________________________________________________
/**
* Convert a type or module name.
*
* Section 28.3.2.2
* Section 28.3.2.3
*/
private static String getTypeOrModuleName (String name) {
// 28.3.2.3 Leading underscores...
String result = convertLeadingUnderscores(name);
// 28.3.2.2 IDL keywords (NOTE: must be done
// after leading underscore conversion because
// the mangling for IDL keywords creates a
// leading underscore!)...
return convertIDLKeywords(result);
}
}