Sat, 01 Dec 2007 00:00:00 +0000
Initial load
1 /*
2 * Copyright 2003-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 try {
206 IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
207 for (int ctr=0; ctr<interfaces.length; ctr++)
208 idlTypesUtil.validateRemoteInterface(interfaces[ctr]);
209 interf_ = interfaces;
210 buildNameTranslation();
211 } catch( IDLTypeException ite) {
212 String msg = ite.getMessage();
213 IllegalStateException ise = new IllegalStateException(msg);
214 ise.initCause(ite);
215 throw ise;
216 }
217 }
219 private void buildNameTranslation()
220 {
221 // holds method info, keyed by method
222 Map allMethodInfo = new HashMap() ;
224 for (int ctr=0; ctr<interf_.length; ctr++) {
225 Class interf = interf_[ctr] ;
227 IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
228 final Method[] methods = interf.getMethods();
229 // Handle the case of a non-public interface!
230 AccessController.doPrivileged(new PrivilegedAction() {
231 public Object run() {
232 Method.setAccessible( methods, true ) ;
233 return null ;
234 }
235 } ) ;
237 // Take an initial pass through all the methods and create some
238 // information that will be used to track the IDL name
239 // transformation.
240 for(int i = 0; i < methods.length; i++) {
242 Method nextMethod = methods[i];
244 IDLMethodInfo methodInfo = new IDLMethodInfo();
246 methodInfo.method = nextMethod;
248 if (idlTypesUtil.isPropertyAccessorMethod(nextMethod, interf)) {
249 methodInfo.isProperty = true;
250 String attributeName = idlTypesUtil.
251 getAttributeNameForProperty(nextMethod.getName());
252 methodInfo.originalName = attributeName;
253 methodInfo.mangledName = attributeName;
254 } else {
255 methodInfo.isProperty = false;
256 methodInfo.originalName = nextMethod.getName();
257 methodInfo.mangledName = nextMethod.getName();
258 }
260 allMethodInfo.put(nextMethod, methodInfo);
261 }
262 }
264 //
265 // Perform case sensitivity test first. This applies to all
266 // method names AND attributes. Compare each method name and
267 // attribute to all other method names and attributes. If names
268 // differ only in case, apply mangling as defined in section 1.3.2.7
269 // of Java2IDL spec. Note that we compare using the original names.
270 //
271 for(Iterator outerIter=allMethodInfo.values().iterator();
272 outerIter.hasNext();) {
273 IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
274 for(Iterator innerIter = allMethodInfo.values().iterator();
275 innerIter.hasNext();) {
276 IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
278 if( (outer != inner) &&
279 (!outer.originalName.equals(inner.originalName)) &&
280 outer.originalName.equalsIgnoreCase(inner.originalName) ) {
281 outer.mangledName =
282 mangleCaseSensitiveCollision(outer.originalName);
283 break;
284 }
286 }
287 }
289 for(Iterator iter = allMethodInfo.values().iterator();
290 iter.hasNext();) {
291 IDLMethodInfo next = (IDLMethodInfo) iter.next();
292 next.mangledName =
293 mangleIdentifier(next.mangledName, next.isProperty);
294 }
296 //
297 // Now check for overloaded method names and apply 1.3.2.6.
298 //
299 for(Iterator outerIter=allMethodInfo.values().iterator();
300 outerIter.hasNext();) {
301 IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
302 if( outer.isProperty ) {
303 continue;
304 }
305 for(Iterator innerIter = allMethodInfo.values().iterator();
306 innerIter.hasNext();) {
307 IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
309 if( (outer != inner) &&
310 !inner.isProperty &&
311 outer.originalName.equals(inner.originalName) ) {
312 outer.mangledName = mangleOverloadedMethod
313 (outer.mangledName, outer.method);
314 break;
315 }
316 }
317 }
319 //
320 // Now mangle any properties that clash with method names.
321 //
322 for(Iterator outerIter=allMethodInfo.values().iterator();
323 outerIter.hasNext();) {
324 IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
325 if( !outer.isProperty ) {
326 continue;
327 }
328 for(Iterator innerIter = allMethodInfo.values().iterator();
329 innerIter.hasNext();) {
330 IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
331 if( (outer != inner) &&
332 !inner.isProperty &&
333 outer.mangledName.equals(inner.mangledName) ) {
334 outer.mangledName = outer.mangledName +
335 ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS;
336 break;
337 }
338 }
339 }
341 //
342 // Ensure that no mapped method names clash with mapped name
343 // of container(1.3.2.9). This is a case insensitive comparison.
344 //
345 for (int ctr=0; ctr<interf_.length; ctr++ ) {
346 Class interf = interf_[ctr] ;
347 String mappedContainerName = getMappedContainerName(interf);
348 for(Iterator iter = allMethodInfo.values().iterator();
349 iter.hasNext();) {
350 IDLMethodInfo next = (IDLMethodInfo) iter.next();
351 if( !next.isProperty &&
352 identifierClashesWithContainer(mappedContainerName,
353 next.mangledName)) {
354 next.mangledName = mangleContainerClash(next.mangledName);
355 }
356 }
357 }
359 //
360 // Populate name translation maps.
361 //
362 methodToIDLNameMap_ = new HashMap();
363 IDLNameToMethodMap_ = new HashMap();
364 methods_ = (Method[])allMethodInfo.keySet().toArray(
365 new Method[0] ) ;
367 for(Iterator iter = allMethodInfo.values().iterator();
368 iter.hasNext();) {
369 IDLMethodInfo next = (IDLMethodInfo) iter.next();
370 String idlName = next.mangledName;
371 if( next.isProperty ) {
372 String origMethodName = next.method.getName();
373 String prefix = "";
375 if( origMethodName.startsWith("get") ) {
376 prefix = GET_ATTRIBUTE_PREFIX;
377 } else if( origMethodName.startsWith("set") ) {
378 prefix = SET_ATTRIBUTE_PREFIX;
379 } else {
380 prefix = IS_ATTRIBUTE_PREFIX;
381 }
383 idlName = prefix + next.mangledName;
384 }
386 methodToIDLNameMap_.put(next.method, idlName);
388 // Final check to see if there are any clashes after all the
389 // manglings have been applied. If so, this is treated as an
390 // invalid interface. Currently, we do a CASE-SENSITIVE
391 // comparison since that matches the rmic behavior.
392 // @@@ Shouldn't this be a case-insensitive check?
393 if( IDLNameToMethodMap_.containsKey(idlName) ) {
394 // @@@ I18N
395 Method clash = (Method) IDLNameToMethodMap_.get(idlName);
396 throw new IllegalStateException("Error : methods " +
397 clash + " and " + next.method +
398 " both result in IDL name '" + idlName + "'");
399 } else {
400 IDLNameToMethodMap_.put(idlName, next.method);
401 }
402 }
404 return;
406 }
409 /**
410 * Perform all necessary stand-alone identifier mangling operations
411 * on a java identifier that is being transformed into an IDL name.
412 * That is, mangling operations that don't require looking at anything
413 * else but the identifier itself. This covers sections 1.3.2.2, 1.3.2.3,
414 * and 1.3.2.4 of the Java2IDL spec. Method overloading and
415 * case-sensitivity checks are handled elsewhere.
416 */
418 private static String mangleIdentifier(String identifier) {
419 return mangleIdentifier(identifier, false);
420 }
422 private static String mangleIdentifier(String identifier, boolean attribute) {
424 String mangledName = identifier;
426 //
427 // Apply leading underscore test (1.3.2.3)
428 // This should be done before IDL Keyword clash test, since clashing
429 // IDL keywords are mangled by adding a leading underscore.
430 //
431 if( hasLeadingUnderscore(mangledName) ) {
432 mangledName = mangleLeadingUnderscore(mangledName);
433 }
435 //
436 // Apply IDL keyword clash test (1.3.2.2).
437 // This is not needed for attributes since when the full property
438 // name is composed it cannot clash with an IDL keyword.
439 // (Also, rmic doesn't do it.)
440 //
442 if( !attribute && isIDLKeyword(mangledName) ) {
443 mangledName = mangleIDLKeywordClash(mangledName);
444 }
446 //
447 // Replace illegal IDL identifier characters (1.3.2.4)
448 // for all method names and attributes.
449 //
450 if( !isIDLIdentifier(mangledName) ) {
451 mangledName = mangleUnicodeChars(mangledName);
452 }
454 return mangledName;
455 }
457 // isIDLKeyword and mangleIDLKeywordClash are exposed here so that
458 // IDLType can use them.
459 //
460 // XXX refactoring needed:
461 // 1. Split off isIDLKeywork and mangleIDLKeywordClash (and possibly
462 // other methods) into a utility class.
463 // 2. Move all of classToIDLType to a constructor inside IDLType.
464 //
465 // The problem appears to be that we need all of the code that
466 // performs various checks for name problems and the corresponding
467 // fixes into a utility class. Then we need to see what other
468 // refactorings present themselves.
470 /**
471 * Checks whether a java identifier clashes with an
472 * IDL keyword. Note that this is a case-insensitive
473 * comparison.
474 *
475 * Used to implement section 1.3.2.2 of Java2IDL spec.
476 */
477 static boolean isIDLKeyword(String identifier) {
479 String identifierAllCaps = identifier.toUpperCase();
481 return idlKeywords_.contains(identifierAllCaps);
482 }
484 static String mangleIDLKeywordClash(String identifier) {
485 return UNDERSCORE + identifier;
486 }
488 private static String mangleLeadingUnderscore(String identifier) {
489 return LEADING_UNDERSCORE_CHAR + identifier;
490 }
492 /**
493 * Checks whether a java identifier starts with an underscore.
494 * Used to implement section 1.3.2.3 of Java2IDL spec.
495 */
496 private static boolean hasLeadingUnderscore(String identifier) {
497 return identifier.startsWith(UNDERSCORE);
498 }
500 /**
501 * Implements Section 1.3.2.4 of Java2IDL Mapping.
502 * All non-IDL identifier characters must be replaced
503 * with their Unicode representation.
504 */
505 static String mangleUnicodeChars(String identifier) {
506 StringBuffer mangledIdentifier = new StringBuffer();
508 for(int i = 0; i < identifier.length(); i++) {
509 char nextChar = identifier.charAt(i);
510 if( isIDLIdentifierChar(nextChar) ) {
511 mangledIdentifier.append(nextChar);
512 } else {
513 String unicode = charToUnicodeRepresentation(nextChar);
514 mangledIdentifier.append(unicode);
515 }
516 }
518 return mangledIdentifier.toString();
519 }
521 /**
522 * Implements mangling portion of Section 1.3.2.7 of Java2IDL spec.
523 * This method only deals with the actual mangling. Decision about
524 * whether case-sensitive collision mangling is required is made
525 * elsewhere.
526 *
527 *
528 * "...a mangled name is generated consisting of the original name
529 * followed by an underscore separated list of decimal indices
530 * into the string, where the indices identify all the upper case
531 * characters in the original string. Indices are zero based."
532 *
533 */
534 String mangleCaseSensitiveCollision(String identifier) {
536 StringBuffer mangledIdentifier = new StringBuffer(identifier);
538 // There is always at least one trailing underscore, whether or
539 // not the identifier has uppercase letters.
540 mangledIdentifier.append(UNDERSCORE);
542 boolean needUnderscore = false;
543 for(int i = 0; i < identifier.length(); i++) {
544 char next = identifier.charAt(i);
545 if( Character.isUpperCase(next) ) {
546 // This bit of logic is needed to ensure that we have
547 // an underscore separated list of indices but no
548 // trailing underscores. Basically, after we have at least
549 // one uppercase letter, we always put an undercore before
550 // printing the next one.
551 if( needUnderscore ) {
552 mangledIdentifier.append(UNDERSCORE);
553 }
554 mangledIdentifier.append(i);
555 needUnderscore = true;
556 }
557 }
559 return mangledIdentifier.toString();
560 }
562 private static String mangleContainerClash(String identifier) {
563 return identifier + ID_CONTAINER_CLASH_CHAR;
564 }
566 /**
567 * Implements Section 1.3.2.9 of Java2IDL Mapping. Container in this
568 * context means the name of the java Class(excluding package) in which
569 * the identifier is defined. Comparison is case-insensitive.
570 */
571 private static boolean identifierClashesWithContainer
572 (String mappedContainerName, String identifier) {
574 return identifier.equalsIgnoreCase(mappedContainerName);
575 }
577 /**
578 * Returns Unicode mangling as defined in Section 1.3.2.4 of
579 * Java2IDL spec.
580 *
581 * "For Java identifiers that contain illegal OMG IDL identifier
582 * characters such as '$' or Unicode characters outside of ISO Latin 1,
583 * any such illegal characters are replaced by "U" followed by the
584 * 4 hexadecimal characters(in upper case) representing the Unicode
585 * value. So, the Java name a$b is mapped to aU0024b and
586 * x\u03bCy is mapped to xU03BCy."
587 */
588 public static String charToUnicodeRepresentation(char c) {
590 int orig = (int) c;
591 StringBuffer hexString = new StringBuffer();
593 int value = orig;
595 while( value > 0 ) {
596 int div = value / 16;
597 int mod = value % 16;
598 hexString.insert(0, HEX_DIGITS[mod]);
599 value = div;
600 }
602 int numZerosToAdd = 4 - hexString.length();
603 for(int i = 0; i < numZerosToAdd; i++) {
604 hexString.insert(0, "0");
605 }
607 hexString.insert(0, "U");
608 return hexString.toString();
609 }
611 private static boolean isIDLIdentifier(String identifier) {
613 boolean isIdentifier = true;
615 for(int i = 0; i < identifier.length(); i++) {
616 char nextChar = identifier.charAt(i);
617 // 1st char must be alphbetic.
618 isIdentifier = (i == 0) ?
619 isIDLAlphabeticChar(nextChar) :
620 isIDLIdentifierChar(nextChar);
621 if( !isIdentifier ) {
622 break;
623 }
624 }
626 return isIdentifier;
628 }
630 private static boolean isIDLIdentifierChar(char c) {
631 return (isIDLAlphabeticChar(c) ||
632 isIDLDecimalDigit(c) ||
633 isUnderscore(c));
634 }
636 /**
637 * True if character is one of 114 Alphabetic characters as
638 * specified in Table 2 of Chapter 3 in CORBA spec.
639 */
640 private static boolean isIDLAlphabeticChar(char c) {
642 // NOTE that we can't use the java.lang.Character
643 // isUpperCase, isLowerCase, etc. methods since they
644 // include many characters other than the Alphabetic list in
645 // the CORBA spec. Instead, we test for inclusion in the
646 // Unicode value ranges for the corresponding legal characters.
648 boolean alphaChar =
649 (
650 // A - Z
651 ((c >= 0x0041) && (c <= 0x005A))
653 ||
655 // a - z
656 ((c >= 0x0061) && (c <= 0x007A))
658 ||
660 // other letter uppercase, other letter lowercase, which is
661 // the entire upper half of C1 Controls except X and /
662 ((c >= 0x00C0) && (c <= 0x00FF)
663 && (c != 0x00D7) && (c != 0x00F7)));
665 return alphaChar;
666 }
668 /**
669 * True if character is one of 10 Decimal Digits
670 * specified in Table 3 of Chapter 3 in CORBA spec.
671 */
672 private static boolean isIDLDecimalDigit(char c) {
673 return ( (c >= 0x0030) && (c <= 0x0039) );
674 }
676 private static boolean isUnderscore(char c) {
677 return ( c == 0x005F );
678 }
680 /**
681 * Mangle an overloaded method name as defined in Section 1.3.2.6 of
682 * Java2IDL spec. Current value of method name is passed in as argument.
683 * We can't start from original method name since the name might have
684 * been partially mangled as a result of the other rules.
685 */
686 private static String mangleOverloadedMethod(String mangledName, Method m) {
688 IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
690 // Start by appending the separator string
691 String newMangledName = mangledName + OVERLOADED_TYPE_SEPARATOR;
693 Class[] parameterTypes = m.getParameterTypes();
695 for(int i = 0; i < parameterTypes.length; i++) {
696 Class nextParamType = parameterTypes[i];
698 if( i > 0 ) {
699 newMangledName = newMangledName + OVERLOADED_TYPE_SEPARATOR;
700 }
701 IDLType idlType = classToIDLType(nextParamType);
703 String moduleName = idlType.getModuleName();
704 String memberName = idlType.getMemberName();
706 String typeName = (moduleName.length() > 0) ?
707 moduleName + UNDERSCORE + memberName : memberName;
709 if( !idlTypesUtil.isPrimitive(nextParamType) &&
710 (idlTypesUtil.getSpecialCaseIDLTypeMapping(nextParamType)
711 == null) &&
712 isIDLKeyword(typeName) ) {
713 typeName = mangleIDLKeywordClash(typeName);
714 }
716 typeName = mangleUnicodeChars(typeName);
718 newMangledName = newMangledName + typeName;
719 }
721 return newMangledName;
722 }
725 private static IDLType classToIDLType(Class c) {
727 IDLType idlType = null;
728 IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
730 if( idlTypesUtil.isPrimitive(c) ) {
732 idlType = idlTypesUtil.getPrimitiveIDLTypeMapping(c);
734 } else if( c.isArray() ) {
736 // Calculate array depth, as well as base element type.
737 Class componentType = c.getComponentType();
738 int numArrayDimensions = 1;
739 while(componentType.isArray()) {
740 componentType = componentType.getComponentType();
741 numArrayDimensions++;
742 }
743 IDLType componentIdlType = classToIDLType(componentType);
745 String[] modules = BASE_IDL_ARRAY_MODULE_TYPE;
746 if( componentIdlType.hasModule() ) {
747 modules = (String[])ObjectUtility.concatenateArrays( modules,
748 componentIdlType.getModules() ) ;
749 }
751 String memberName = BASE_IDL_ARRAY_ELEMENT_TYPE +
752 numArrayDimensions + UNDERSCORE +
753 componentIdlType.getMemberName();
755 idlType = new IDLType(c, modules, memberName);
757 } else {
758 idlType = idlTypesUtil.getSpecialCaseIDLTypeMapping(c);
760 if (idlType == null) {
761 // Section 1.3.2.5 of Java2IDL spec defines mangling rules for
762 // inner classes.
763 String memberName = getUnmappedContainerName(c);
765 // replace inner class separator with double underscore
766 memberName = memberName.replaceAll("\\$",
767 INNER_CLASS_SEPARATOR);
769 if( hasLeadingUnderscore(memberName) ) {
770 memberName = mangleLeadingUnderscore(memberName);
771 }
773 // Get raw package name. If there is a package, it
774 // will still have the "." separators and none of the
775 // mangling rules will have been applied.
776 String packageName = getPackageName(c);
778 if (packageName == null) {
779 idlType = new IDLType( c, memberName ) ;
780 } else {
781 // If this is a generated IDL Entity Type we need to
782 // prepend org_omg_boxedIDL per sections 1.3.5 and 1.3.9
783 if (idlTypesUtil.isEntity(c)) {
784 packageName = "org.omg.boxedIDL." + packageName ;
785 }
787 // Section 1.3.2.1 and 1.3.2.6 of Java2IDL spec defines
788 // rules for mapping java packages to IDL modules and for
789 // mangling module name portion of type name. NOTE that
790 // of the individual identifier mangling rules,
791 // only the leading underscore test is done here.
792 // The other two(IDL Keyword, Illegal Unicode chars) are
793 // done in mangleOverloadedMethodName.
794 StringTokenizer tokenizer =
795 new StringTokenizer(packageName, ".");
797 String[] modules = new String[ tokenizer.countTokens() ] ;
798 int index = 0 ;
799 while (tokenizer.hasMoreElements()) {
800 String next = tokenizer.nextToken();
801 String moreMangled = hasLeadingUnderscore( next ) ?
802 mangleLeadingUnderscore( next ) : next;
804 modules[index++] = moreMangled ;
805 }
807 idlType = new IDLType(c, modules, memberName);
808 }
809 }
810 }
812 return idlType;
813 }
815 /**
816 * Return Class' package name or null if there is no package.
817 */
818 private static String getPackageName(Class c) {
819 Package thePackage = c.getPackage();
820 String packageName = null;
822 // Try to get package name by introspection. Some classloaders might
823 // not provide this information, so check for null.
824 if( thePackage != null ) {
825 packageName = thePackage.getName();
826 } else {
827 // brute force method
828 String fullyQualifiedClassName = c.getName();
829 int lastDot = fullyQualifiedClassName.indexOf('.');
830 packageName = (lastDot == -1) ? null :
831 fullyQualifiedClassName.substring(0, lastDot);
832 }
833 return packageName;
834 }
836 private static String getMappedContainerName(Class c) {
837 String unmappedName = getUnmappedContainerName(c);
839 return mangleIdentifier(unmappedName);
840 }
842 /**
843 * Return portion of class name excluding package name.
844 */
845 private static String getUnmappedContainerName(Class c) {
847 String memberName = null;
848 String packageName = getPackageName(c);
850 String fullyQualifiedClassName = c.getName();
852 if( packageName != null ) {
853 int packageLength = packageName.length();
854 memberName = fullyQualifiedClassName.substring(packageLength + 1);
855 } else {
856 memberName = fullyQualifiedClassName;
858 }
860 return memberName;
861 }
863 /**
864 * Internal helper class for tracking information related to each
865 * interface method while we're building the name translation table.
866 */
867 private static class IDLMethodInfo
868 {
869 public Method method;
870 public boolean isProperty;
872 // If this is a property, originalName holds the original
873 // attribute name. Otherwise, it holds the original method name.
874 public String originalName;
876 // If this is a property, mangledName holds the mangled attribute
877 // name. Otherwise, it holds the mangled method name.
878 public String mangledName;
880 }
882 public String toString() {
884 StringBuffer contents = new StringBuffer();
885 contents.append("IDLNameTranslator[" );
886 for( int ctr=0; ctr<interf_.length; ctr++) {
887 if (ctr != 0)
888 contents.append( " " ) ;
889 contents.append( interf_[ctr].getName() ) ;
890 }
891 contents.append("]\n");
892 for(Iterator iter = methodToIDLNameMap_.keySet().iterator();
893 iter.hasNext();) {
895 Method method = (Method) iter.next();
896 String idlName = (String) methodToIDLNameMap_.get(method);
898 contents.append(idlName + ":" + method + "\n");
900 }
902 return contents.toString();
903 }
905 public static void main(String[] args) {
907 Class remoteInterface = java.rmi.Remote.class;
909 if( args.length > 0 ) {
910 String className = args[0];
911 try {
912 remoteInterface = Class.forName(className);
913 } catch(Exception e) {
914 e.printStackTrace();
915 System.exit(-1);
916 }
917 }
919 System.out.println("Building name translation for " + remoteInterface);
920 try {
921 IDLNameTranslator nameTranslator =
922 IDLNameTranslatorImpl.get(remoteInterface);
923 System.out.println(nameTranslator);
924 } catch(IllegalStateException ise) {
925 ise.printStackTrace();
926 }
927 }
928 }