Mon, 19 Aug 2013 15:22:59 +0100
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 }