src/share/classes/com/sun/corba/se/impl/presentation/rmi/IDLNameTranslatorImpl.java

Mon, 19 Aug 2013 15:22:59 +0100

author
msheppar
date
Mon, 19 Aug 2013 15:22:59 +0100
changeset 520
9c75c61d97f8
parent 158
91006f157c46
child 553
5ca1b4c282b8
permissions
-rw-r--r--

8022940: Enhance CORBA translations
Reviewed-by: coffeys, alanb, skoivu

     1 /*
     2  * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.corba.se.impl.presentation.rmi ;
    28 import java.security.AccessController;
    29 import java.security.PrivilegedAction;
    31 import java.lang.reflect.Method;
    33 import java.math.BigInteger;
    35 import java.util.Map;
    36 import java.util.Set;
    37 import java.util.HashSet;
    38 import java.util.Iterator;
    39 import java.util.HashMap;
    40 import java.util.StringTokenizer;
    42 import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ;
    44 import com.sun.corba.se.impl.presentation.rmi.IDLType ;
    45 import com.sun.corba.se.impl.presentation.rmi.IDLTypeException ;
    46 import com.sun.corba.se.impl.presentation.rmi.IDLTypesUtil ;
    47 import com.sun.corba.se.impl.orbutil.ObjectUtility ;
    49 /**
    50  * Bidirectional translator between RMI-IIOP interface methods and
    51  * and IDL Names.
    52  */
    53 public class IDLNameTranslatorImpl implements IDLNameTranslator {
    55     // From CORBA Spec, Table 6 Keywords.
    56     // Note that since all IDL identifiers are case
    57     // insensitive, java identifier comparisons to these
    58     // will be case insensitive also.
    59     private static String[] IDL_KEYWORDS = {
    61         "abstract", "any", "attribute", "boolean", "case", "char",
    62         "const", "context", "custom", "default", "double", "enum",
    63         "exception", "factory", "FALSE", "fixed", "float", "in", "inout",
    64         "interface", "long", "module", "native", "Object", "octet",
    65         "oneway", "out", "private", "public", "raises", "readonly", "sequence",
    66         "short", "string", "struct", "supports", "switch", "TRUE", "truncatable",
    67         "typedef", "unsigned", "union", "ValueBase", "valuetype", "void",
    68         "wchar", "wstring"
    70     };
    72     private static char[] HEX_DIGITS = {
    73         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    74         'A', 'B', 'C', 'D', 'E', 'F'
    75     };
    77     private static final String UNDERSCORE = "_";
    79     // used to mangle java inner class names
    80     private static final String INNER_CLASS_SEPARATOR =
    81         UNDERSCORE + UNDERSCORE;
    83     // used to form IDL array type names
    84     private static final String[] BASE_IDL_ARRAY_MODULE_TYPE=
    85         new String[] { "org", "omg", "boxedRMI" } ;
    87     private static final String BASE_IDL_ARRAY_ELEMENT_TYPE = "seq";
    89     // used to mangling java identifiers that have a leading underscore
    90     private static final String LEADING_UNDERSCORE_CHAR = "J";
    91     private static final String ID_CONTAINER_CLASH_CHAR = UNDERSCORE;
    93     // separator used between types in a mangled overloaded method name
    94     private static final String OVERLOADED_TYPE_SEPARATOR =
    95         UNDERSCORE + UNDERSCORE;
    97     // string appended to attribute if it clashes with a method name
    98     private static final String ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS =
    99         UNDERSCORE + UNDERSCORE;
   101     // strings prepended to the attribute names in order to form their
   102     // IDL names.
   103     private static final String GET_ATTRIBUTE_PREFIX = "_get_";
   104     private static final String SET_ATTRIBUTE_PREFIX = "_set_";
   105     private static final String IS_ATTRIBUTE_PREFIX  = "_get_";
   107     private static Set idlKeywords_;
   109     static {
   111         idlKeywords_ = new HashSet();
   112         for(int i = 0; i < IDL_KEYWORDS.length; i++) {
   113             String next = (String) IDL_KEYWORDS[i];
   114             // Convert keyword to all caps to ease equality
   115             // check.
   116             String keywordAllCaps = next.toUpperCase();
   117             idlKeywords_.add(keywordAllCaps);
   118         }
   120     }
   122     //
   123     // Instance state
   124     //
   126     // Remote interface for name translation.
   127     private Class[] interf_;
   129     // Maps used to hold name translations.  These do not need to be
   130     // synchronized since the translation is never modified after
   131     // initialization.
   132     private Map methodToIDLNameMap_;
   133     private Map IDLNameToMethodMap_;
   134     private Method[] methods_;
   136     /**
   137      * Return an IDLNameTranslator for the given interface.
   138      *
   139      * @throws IllegalStateException if given class is not a valid
   140      *         RMI/IIOP Remote Interface
   141      */
   142     public static IDLNameTranslator get( Class interf )
   143     {
   145         return new IDLNameTranslatorImpl(new Class[] { interf } );
   147     }
   149     /**
   150      * Return an IDLNameTranslator for the given interfacex.
   151      *
   152      * @throws IllegalStateException if given classes are not  valid
   153      *         RMI/IIOP Remote Interfaces
   154      */
   155     public static IDLNameTranslator get( Class[] interfaces )
   156     {
   158         return new IDLNameTranslatorImpl(interfaces );
   160     }
   162     public static String getExceptionId( Class cls )
   163     {
   164         // Requirements for this method:
   165         // 1. cls must be an exception but not a RemoteException.
   166         // 2. If cls has an IDL keyword name, an underscore is prepended (1.3.2.2).
   167         // 3. If cls jas a leading underscore, J is prepended (1.3.2.3).
   168         // 4. If cls has an illegal IDL ident char, it is mapped to UXXXX where
   169         //    XXXX is the unicode value in hex of the char (1.3.2.4).
   170         // 5. double underscore for inner class (1.3.2.5).
   171         // 6. The ID is "IDL:" + name with / separators + ":1.0".
   172         IDLType itype = classToIDLType( cls ) ;
   173         return itype.getExceptionName() ;
   174     }
   176     public Class[] getInterfaces()
   177     {
   178         return interf_;
   179     }
   181     public Method[] getMethods()
   182     {
   183         return methods_ ;
   184     }
   186     public Method getMethod( String idlName )
   187     {
   188         return (Method) IDLNameToMethodMap_.get(idlName);
   189     }
   191     public String getIDLName( Method method )
   192     {
   193         return (String) methodToIDLNameMap_.get(method);
   194     }
   196     /**
   197      * Initialize an IDLNameTranslator for the given interface.
   198      *
   199      * @throws IllegalStateException if given class is not a valid
   200      *         RMI/IIOP Remote Interface
   201      */
   202     private IDLNameTranslatorImpl(Class[] interfaces)
   203     {
   205         SecurityManager s = System.getSecurityManager();
   206         if (s != null) {
   207             s.checkPermission(new DynamicAccessPermission("access"));
   208         }
   209         try {
   210             IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
   211             for (int ctr=0; ctr<interfaces.length; ctr++)
   212                 idlTypesUtil.validateRemoteInterface(interfaces[ctr]);
   213             interf_ = interfaces;
   214             buildNameTranslation();
   215         } catch( IDLTypeException ite) {
   216             String msg = ite.getMessage();
   217             IllegalStateException ise = new IllegalStateException(msg);
   218             ise.initCause(ite);
   219             throw ise;
   220         }
   221     }
   223     private void buildNameTranslation()
   224     {
   225         // holds method info, keyed by method
   226         Map allMethodInfo = new HashMap() ;
   228         for (int ctr=0; ctr<interf_.length; ctr++) {
   229             Class interf = interf_[ctr] ;
   231             IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
   232             final Method[] methods = interf.getMethods();
   233             // Handle the case of a non-public interface!
   234             AccessController.doPrivileged(new PrivilegedAction() {
   235                 public Object run() {
   236                     Method.setAccessible( methods, true ) ;
   237                     return null ;
   238                 }
   239             } ) ;
   241             // Take an initial pass through all the methods and create some
   242             // information that will be used to track the IDL name
   243             // transformation.
   244             for(int i = 0; i < methods.length; i++) {
   246                 Method nextMethod = methods[i];
   248                 IDLMethodInfo methodInfo = new IDLMethodInfo();
   250                 methodInfo.method = nextMethod;
   252                 if (idlTypesUtil.isPropertyAccessorMethod(nextMethod, interf)) {
   253                     methodInfo.isProperty = true;
   254                     String attributeName = idlTypesUtil.
   255                         getAttributeNameForProperty(nextMethod.getName());
   256                     methodInfo.originalName = attributeName;
   257                     methodInfo.mangledName  = attributeName;
   258                 } else {
   259                     methodInfo.isProperty = false;
   260                     methodInfo.originalName = nextMethod.getName();
   261                     methodInfo.mangledName  = nextMethod.getName();
   262                 }
   264                 allMethodInfo.put(nextMethod, methodInfo);
   265             }
   266         }
   268         //
   269         // Perform case sensitivity test first.  This applies to all
   270         // method names AND attributes.  Compare each method name and
   271         // attribute to all other method names and attributes.  If names
   272         // differ only in case, apply mangling as defined in section 1.3.2.7
   273         // of Java2IDL spec.  Note that we compare using the original names.
   274         //
   275         for(Iterator outerIter=allMethodInfo.values().iterator();
   276             outerIter.hasNext();) {
   277             IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
   278             for(Iterator innerIter = allMethodInfo.values().iterator();
   279                 innerIter.hasNext();) {
   280                 IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
   282                 if( (outer != inner) &&
   283                     (!outer.originalName.equals(inner.originalName)) &&
   284                     outer.originalName.equalsIgnoreCase(inner.originalName) ) {
   285                     outer.mangledName =
   286                         mangleCaseSensitiveCollision(outer.originalName);
   287                     break;
   288                 }
   290             }
   291         }
   293         for(Iterator iter = allMethodInfo.values().iterator();
   294             iter.hasNext();) {
   295             IDLMethodInfo next = (IDLMethodInfo) iter.next();
   296             next.mangledName =
   297                 mangleIdentifier(next.mangledName, next.isProperty);
   298         }
   300         //
   301         // Now check for overloaded method names and apply 1.3.2.6.
   302         //
   303         for(Iterator outerIter=allMethodInfo.values().iterator();
   304             outerIter.hasNext();) {
   305             IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
   306             if( outer.isProperty ) {
   307                 continue;
   308             }
   309             for(Iterator innerIter = allMethodInfo.values().iterator();
   310                 innerIter.hasNext();) {
   311                 IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
   313                 if( (outer != inner) &&
   314                     !inner.isProperty &&
   315                     outer.originalName.equals(inner.originalName) ) {
   316                     outer.mangledName = mangleOverloadedMethod
   317                         (outer.mangledName, outer.method);
   318                     break;
   319                 }
   320             }
   321         }
   323         //
   324         // Now mangle any properties that clash with method names.
   325         //
   326         for(Iterator outerIter=allMethodInfo.values().iterator();
   327             outerIter.hasNext();) {
   328             IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
   329             if( !outer.isProperty ) {
   330                 continue;
   331             }
   332             for(Iterator innerIter = allMethodInfo.values().iterator();
   333                 innerIter.hasNext();) {
   334                 IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
   335                 if( (outer != inner) &&
   336                     !inner.isProperty &&
   337                     outer.mangledName.equals(inner.mangledName) ) {
   338                     outer.mangledName = outer.mangledName +
   339                         ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS;
   340                     break;
   341                 }
   342             }
   343         }
   345         //
   346         // Ensure that no mapped method names clash with mapped name
   347         // of container(1.3.2.9).  This is a case insensitive comparison.
   348         //
   349         for (int ctr=0; ctr<interf_.length; ctr++ ) {
   350             Class interf = interf_[ctr] ;
   351             String mappedContainerName = getMappedContainerName(interf);
   352             for(Iterator iter = allMethodInfo.values().iterator();
   353                 iter.hasNext();) {
   354                 IDLMethodInfo next = (IDLMethodInfo) iter.next();
   355                 if( !next.isProperty &&
   356                     identifierClashesWithContainer(mappedContainerName,
   357                                                    next.mangledName)) {
   358                     next.mangledName = mangleContainerClash(next.mangledName);
   359                 }
   360             }
   361         }
   363         //
   364         // Populate name translation maps.
   365         //
   366         methodToIDLNameMap_ = new HashMap();
   367         IDLNameToMethodMap_ = new HashMap();
   368         methods_ = (Method[])allMethodInfo.keySet().toArray(
   369             new Method[0] ) ;
   371         for(Iterator iter = allMethodInfo.values().iterator();
   372             iter.hasNext();) {
   373             IDLMethodInfo next = (IDLMethodInfo) iter.next();
   374             String idlName = next.mangledName;
   375             if( next.isProperty ) {
   376                 String origMethodName = next.method.getName();
   377                 String prefix = "";
   379                 if( origMethodName.startsWith("get") ) {
   380                     prefix = GET_ATTRIBUTE_PREFIX;
   381                 } else if( origMethodName.startsWith("set") ) {
   382                     prefix = SET_ATTRIBUTE_PREFIX;
   383                 } else {
   384                     prefix = IS_ATTRIBUTE_PREFIX;
   385                 }
   387                 idlName = prefix + next.mangledName;
   388             }
   390             methodToIDLNameMap_.put(next.method, idlName);
   392             // Final check to see if there are any clashes after all the
   393             // manglings have been applied.  If so, this is treated as an
   394             // invalid interface.  Currently, we do a CASE-SENSITIVE
   395             // comparison since that matches the rmic behavior.
   396             // @@@ Shouldn't this be a case-insensitive check?
   397             if( IDLNameToMethodMap_.containsKey(idlName) ) {
   398                 // @@@ I18N
   399                 Method clash = (Method) IDLNameToMethodMap_.get(idlName);
   400                 throw new IllegalStateException("Error : methods " +
   401                     clash + " and " + next.method +
   402                     " both result in IDL name '" + idlName + "'");
   403             } else {
   404                 IDLNameToMethodMap_.put(idlName, next.method);
   405             }
   406         }
   408         return;
   410     }
   413     /**
   414      * Perform all necessary stand-alone identifier mangling operations
   415      * on a java identifier that is being transformed into an IDL name.
   416      * That is, mangling operations that don't require looking at anything
   417      * else but the identifier itself.  This covers sections 1.3.2.2, 1.3.2.3,
   418      * and 1.3.2.4 of the Java2IDL spec.  Method overloading and
   419      * case-sensitivity checks are handled elsewhere.
   420      */
   422     private static String mangleIdentifier(String identifier) {
   423         return mangleIdentifier(identifier, false);
   424     }
   426     private static String mangleIdentifier(String identifier, boolean attribute) {
   428         String mangledName = identifier;
   430         //
   431         // Apply leading underscore test (1.3.2.3)
   432         // This should be done before IDL Keyword clash test, since clashing
   433         // IDL keywords are mangled by adding a leading underscore.
   434         //
   435         if( hasLeadingUnderscore(mangledName) ) {
   436             mangledName = mangleLeadingUnderscore(mangledName);
   437         }
   439         //
   440         // Apply IDL keyword clash test (1.3.2.2).
   441         // This is not needed for attributes since when the full property
   442         // name is composed it cannot clash with an IDL keyword.
   443         // (Also, rmic doesn't do it.)
   444         //
   446         if( !attribute && isIDLKeyword(mangledName) ) {
   447             mangledName = mangleIDLKeywordClash(mangledName);
   448         }
   450         //
   451         // Replace illegal IDL identifier characters (1.3.2.4)
   452         // for all method names and attributes.
   453         //
   454         if( !isIDLIdentifier(mangledName) ) {
   455             mangledName = mangleUnicodeChars(mangledName);
   456         }
   458         return mangledName;
   459     }
   461     // isIDLKeyword and mangleIDLKeywordClash are exposed here so that
   462     // IDLType can use them.
   463     //
   464     // XXX refactoring needed:
   465     // 1. Split off isIDLKeywork and mangleIDLKeywordClash (and possibly
   466     //    other methods) into a utility class.
   467     // 2. Move all of classToIDLType to a constructor inside IDLType.
   468     //
   469     // The problem appears to be that we need all of the code that
   470     // performs various checks for name problems and the corresponding
   471     // fixes into a utility class.  Then we need to see what other
   472     // refactorings present themselves.
   474     /**
   475      * Checks whether a java identifier clashes with an
   476      * IDL keyword.  Note that this is a case-insensitive
   477      * comparison.
   478      *
   479      * Used to implement section 1.3.2.2 of Java2IDL spec.
   480      */
   481     static boolean isIDLKeyword(String identifier) {
   483         String identifierAllCaps = identifier.toUpperCase();
   485         return idlKeywords_.contains(identifierAllCaps);
   486     }
   488     static String mangleIDLKeywordClash(String identifier) {
   489         return UNDERSCORE + identifier;
   490     }
   492     private static String mangleLeadingUnderscore(String identifier) {
   493         return LEADING_UNDERSCORE_CHAR + identifier;
   494     }
   496     /**
   497      * Checks whether a java identifier starts with an underscore.
   498      * Used to implement section 1.3.2.3 of Java2IDL spec.
   499      */
   500     private static boolean hasLeadingUnderscore(String identifier) {
   501         return identifier.startsWith(UNDERSCORE);
   502     }
   504     /**
   505      * Implements Section 1.3.2.4 of Java2IDL Mapping.
   506      * All non-IDL identifier characters must be replaced
   507      * with their Unicode representation.
   508      */
   509     static String mangleUnicodeChars(String identifier) {
   510         StringBuffer mangledIdentifier = new StringBuffer();
   512         for(int i = 0; i < identifier.length(); i++) {
   513             char nextChar = identifier.charAt(i);
   514             if( isIDLIdentifierChar(nextChar) ) {
   515                 mangledIdentifier.append(nextChar);
   516             } else {
   517                 String unicode = charToUnicodeRepresentation(nextChar);
   518                 mangledIdentifier.append(unicode);
   519             }
   520         }
   522         return mangledIdentifier.toString();
   523     }
   525     /**
   526      * Implements mangling portion of Section 1.3.2.7 of Java2IDL spec.
   527      * This method only deals with the actual mangling.  Decision about
   528      * whether case-sensitive collision mangling is required is made
   529      * elsewhere.
   530      *
   531      *
   532      * "...a mangled name is generated consisting of the original name
   533      * followed by an underscore separated list of decimal indices
   534      * into the string, where the indices identify all the upper case
   535      * characters in the original string. Indices are zero based."
   536      *
   537      */
   538     String mangleCaseSensitiveCollision(String identifier) {
   540         StringBuffer mangledIdentifier = new StringBuffer(identifier);
   542         // There is always at least one trailing underscore, whether or
   543         // not the identifier has uppercase letters.
   544         mangledIdentifier.append(UNDERSCORE);
   546         boolean needUnderscore = false;
   547         for(int i = 0; i < identifier.length(); i++) {
   548             char next = identifier.charAt(i);
   549             if( Character.isUpperCase(next) ) {
   550                 // This bit of logic is needed to ensure that we have
   551                 // an underscore separated list of indices but no
   552                 // trailing underscores.  Basically, after we have at least
   553                 // one uppercase letter, we always put an undercore before
   554                 // printing the next one.
   555                 if( needUnderscore ) {
   556                     mangledIdentifier.append(UNDERSCORE);
   557                 }
   558                 mangledIdentifier.append(i);
   559                 needUnderscore = true;
   560             }
   561         }
   563         return mangledIdentifier.toString();
   564     }
   566     private static String mangleContainerClash(String identifier) {
   567         return identifier + ID_CONTAINER_CLASH_CHAR;
   568     }
   570     /**
   571      * Implements Section 1.3.2.9 of Java2IDL Mapping. Container in this
   572      * context means the name of the java Class(excluding package) in which
   573      * the identifier is defined.  Comparison is case-insensitive.
   574      */
   575     private static boolean identifierClashesWithContainer
   576         (String mappedContainerName, String identifier) {
   578         return identifier.equalsIgnoreCase(mappedContainerName);
   579     }
   581     /**
   582      * Returns Unicode mangling as defined in Section 1.3.2.4 of
   583      * Java2IDL spec.
   584      *
   585      * "For Java identifiers that contain illegal OMG IDL identifier
   586      * characters such as '$' or Unicode characters outside of ISO Latin 1,
   587      * any such illegal characters are replaced by "U" followed by the
   588      * 4 hexadecimal characters(in upper case) representing the Unicode
   589      * value.  So, the Java name a$b is mapped to aU0024b and
   590      * x\u03bCy is mapped to xU03BCy."
   591      */
   592     public static String charToUnicodeRepresentation(char c) {
   594         int orig = (int) c;
   595         StringBuffer hexString = new StringBuffer();
   597         int value = orig;
   599         while( value > 0 ) {
   600             int div = value / 16;
   601             int mod = value % 16;
   602             hexString.insert(0, HEX_DIGITS[mod]);
   603             value = div;
   604         }
   606         int numZerosToAdd = 4 - hexString.length();
   607         for(int i = 0; i < numZerosToAdd; i++) {
   608             hexString.insert(0, "0");
   609         }
   611         hexString.insert(0, "U");
   612         return hexString.toString();
   613     }
   615     private static boolean isIDLIdentifier(String identifier) {
   617         boolean isIdentifier = true;
   619         for(int i = 0; i < identifier.length(); i++) {
   620             char nextChar = identifier.charAt(i);
   621             // 1st char must be alphbetic.
   622             isIdentifier  = (i == 0) ?
   623                 isIDLAlphabeticChar(nextChar) :
   624                 isIDLIdentifierChar(nextChar);
   625             if( !isIdentifier ) {
   626                 break;
   627             }
   628         }
   630         return isIdentifier;
   632     }
   634     private static boolean isIDLIdentifierChar(char c) {
   635         return (isIDLAlphabeticChar(c) ||
   636                 isIDLDecimalDigit(c)   ||
   637                 isUnderscore(c));
   638     }
   640     /**
   641      * True if character is one of 114 Alphabetic characters as
   642      * specified in Table 2 of Chapter 3 in CORBA spec.
   643      */
   644     private static boolean isIDLAlphabeticChar(char c) {
   646         // NOTE that we can't use the java.lang.Character
   647         // isUpperCase, isLowerCase, etc. methods since they
   648         // include many characters other than the Alphabetic list in
   649         // the CORBA spec.  Instead, we test for inclusion in the
   650         // Unicode value ranges for the corresponding legal characters.
   652         boolean alphaChar =
   653             (
   654              // A - Z
   655              ((c >= 0x0041) && (c <= 0x005A))
   657              ||
   659              // a - z
   660              ((c >= 0x0061) && (c <= 0x007A))
   662              ||
   664              // other letter uppercase, other letter lowercase, which is
   665              // the entire upper half of C1 Controls except X and /
   666              ((c >= 0x00C0) && (c <= 0x00FF)
   667               && (c != 0x00D7) && (c != 0x00F7)));
   669         return alphaChar;
   670     }
   672     /**
   673      * True if character is one of 10 Decimal Digits
   674      * specified in Table 3 of Chapter 3 in CORBA spec.
   675      */
   676     private static boolean isIDLDecimalDigit(char c) {
   677         return ( (c >= 0x0030) && (c <= 0x0039) );
   678     }
   680     private static boolean isUnderscore(char c) {
   681         return ( c == 0x005F );
   682     }
   684     /**
   685      * Mangle an overloaded method name as defined in Section 1.3.2.6 of
   686      * Java2IDL spec.  Current value of method name is passed in as argument.
   687      * We can't start from original method name since the name might have
   688      * been partially mangled as a result of the other rules.
   689      */
   690     private static String mangleOverloadedMethod(String mangledName, Method m) {
   692         IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
   694         // Start by appending the separator string
   695         String newMangledName = mangledName + OVERLOADED_TYPE_SEPARATOR;
   697         Class[] parameterTypes = m.getParameterTypes();
   699         for(int i = 0; i < parameterTypes.length; i++) {
   700             Class nextParamType = parameterTypes[i];
   702             if( i > 0 ) {
   703                 newMangledName = newMangledName + OVERLOADED_TYPE_SEPARATOR;
   704             }
   705             IDLType idlType = classToIDLType(nextParamType);
   707             String moduleName = idlType.getModuleName();
   708             String memberName = idlType.getMemberName();
   710             String typeName = (moduleName.length() > 0) ?
   711                 moduleName + UNDERSCORE + memberName : memberName;
   713             if( !idlTypesUtil.isPrimitive(nextParamType) &&
   714                 (idlTypesUtil.getSpecialCaseIDLTypeMapping(nextParamType)
   715                  == null) &&
   716                 isIDLKeyword(typeName) ) {
   717                 typeName = mangleIDLKeywordClash(typeName);
   718             }
   720             typeName = mangleUnicodeChars(typeName);
   722             newMangledName = newMangledName + typeName;
   723         }
   725         return newMangledName;
   726     }
   729     private static IDLType classToIDLType(Class c) {
   731         IDLType idlType = null;
   732         IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
   734         if( idlTypesUtil.isPrimitive(c) ) {
   736             idlType = idlTypesUtil.getPrimitiveIDLTypeMapping(c);
   738         } else if( c.isArray() ) {
   740             // Calculate array depth, as well as base element type.
   741             Class componentType = c.getComponentType();
   742             int numArrayDimensions = 1;
   743             while(componentType.isArray()) {
   744                 componentType = componentType.getComponentType();
   745                 numArrayDimensions++;
   746             }
   747             IDLType componentIdlType = classToIDLType(componentType);
   749             String[] modules = BASE_IDL_ARRAY_MODULE_TYPE;
   750             if( componentIdlType.hasModule() ) {
   751                 modules = (String[])ObjectUtility.concatenateArrays( modules,
   752                     componentIdlType.getModules() ) ;
   753             }
   755             String memberName = BASE_IDL_ARRAY_ELEMENT_TYPE +
   756                 numArrayDimensions + UNDERSCORE +
   757                 componentIdlType.getMemberName();
   759             idlType = new IDLType(c, modules, memberName);
   761         } else {
   762             idlType = idlTypesUtil.getSpecialCaseIDLTypeMapping(c);
   764             if (idlType == null) {
   765                 // Section 1.3.2.5 of Java2IDL spec defines mangling rules for
   766                 // inner classes.
   767                 String memberName = getUnmappedContainerName(c);
   769                 // replace inner class separator with double underscore
   770                 memberName = memberName.replaceAll("\\$",
   771                                                    INNER_CLASS_SEPARATOR);
   773                 if( hasLeadingUnderscore(memberName) ) {
   774                     memberName = mangleLeadingUnderscore(memberName);
   775                 }
   777                 // Get raw package name.  If there is a package, it
   778                 // will still have the "." separators and none of the
   779                 // mangling rules will have been applied.
   780                 String packageName = getPackageName(c);
   782                 if (packageName == null) {
   783                     idlType = new IDLType( c, memberName ) ;
   784                 } else {
   785                     // If this is a generated IDL Entity Type we need to
   786                     // prepend org_omg_boxedIDL per sections 1.3.5 and 1.3.9
   787                     if (idlTypesUtil.isEntity(c)) {
   788                         packageName = "org.omg.boxedIDL." + packageName ;
   789                     }
   791                     // Section 1.3.2.1 and 1.3.2.6 of Java2IDL spec defines
   792                     // rules for mapping java packages to IDL modules and for
   793                     // mangling module name portion of type name.  NOTE that
   794                     // of the individual identifier mangling rules,
   795                     // only the leading underscore test is done here.
   796                     // The other two(IDL Keyword, Illegal Unicode chars) are
   797                     // done in mangleOverloadedMethodName.
   798                     StringTokenizer tokenizer =
   799                         new StringTokenizer(packageName, ".");
   801                     String[] modules = new String[ tokenizer.countTokens() ] ;
   802                     int index = 0 ;
   803                     while (tokenizer.hasMoreElements()) {
   804                         String next = tokenizer.nextToken();
   805                         String moreMangled = hasLeadingUnderscore( next ) ?
   806                             mangleLeadingUnderscore( next ) : next;
   808                         modules[index++] = moreMangled ;
   809                     }
   811                     idlType = new IDLType(c, modules, memberName);
   812                 }
   813             }
   814         }
   816         return idlType;
   817     }
   819     /**
   820      * Return Class' package name or null if there is no package.
   821      */
   822     private static String getPackageName(Class c) {
   823         Package thePackage = c.getPackage();
   824         String packageName = null;
   826         // Try to get package name by introspection.  Some classloaders might
   827         // not provide this information, so check for null.
   828         if( thePackage != null ) {
   829             packageName = thePackage.getName();
   830         } else {
   831             // brute force method
   832             String fullyQualifiedClassName = c.getName();
   833             int lastDot = fullyQualifiedClassName.indexOf('.');
   834             packageName = (lastDot == -1) ? null :
   835                 fullyQualifiedClassName.substring(0, lastDot);
   836         }
   837         return packageName;
   838     }
   840     private static String getMappedContainerName(Class c) {
   841         String unmappedName = getUnmappedContainerName(c);
   843         return mangleIdentifier(unmappedName);
   844     }
   846     /**
   847      * Return portion of class name excluding package name.
   848      */
   849     private static String getUnmappedContainerName(Class c) {
   851         String memberName  = null;
   852         String packageName = getPackageName(c);
   854         String fullyQualifiedClassName = c.getName();
   856         if( packageName != null ) {
   857             int packageLength = packageName.length();
   858             memberName = fullyQualifiedClassName.substring(packageLength + 1);
   859         } else {
   860             memberName = fullyQualifiedClassName;
   862         }
   864         return memberName;
   865     }
   867     /**
   868      * Internal helper class for tracking information related to each
   869      * interface method while we're building the name translation table.
   870      */
   871     private static class IDLMethodInfo
   872     {
   873         public Method method;
   874         public boolean isProperty;
   876         // If this is a property, originalName holds the original
   877         // attribute name. Otherwise, it holds the original method name.
   878         public String originalName;
   880         // If this is a property, mangledName holds the mangled attribute
   881         // name. Otherwise, it holds the mangled method name.
   882         public String mangledName;
   884     }
   886     public String toString() {
   888         StringBuffer contents = new StringBuffer();
   889         contents.append("IDLNameTranslator[" );
   890         for( int ctr=0; ctr<interf_.length; ctr++) {
   891             if (ctr != 0)
   892                 contents.append( " " ) ;
   893             contents.append( interf_[ctr].getName() ) ;
   894         }
   895         contents.append("]\n");
   896         for(Iterator iter = methodToIDLNameMap_.keySet().iterator();
   897             iter.hasNext();) {
   899             Method method  = (Method) iter.next();
   900             String idlName = (String) methodToIDLNameMap_.get(method);
   902             contents.append(idlName + ":" + method + "\n");
   904         }
   906         return contents.toString();
   907     }
   908 }

mercurial