KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > corba > se > impl > presentation > rmi > IDLNameTranslatorImpl


1 /*
2  * @(#)IDLNameTranslatorImpl.java 1.13 07/04/17
3  *
4  * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.corba.se.impl.presentation.rmi ;
9
10 import java.security.AccessController JavaDoc;
11 import java.security.PrivilegedAction JavaDoc;
12
13 import java.lang.reflect.Method JavaDoc;
14
15 import java.math.BigInteger JavaDoc;
16
17 import java.util.Map JavaDoc;
18 import java.util.Set JavaDoc;
19 import java.util.HashSet JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.StringTokenizer JavaDoc;
23
24 import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ;
25
26 import com.sun.corba.se.impl.presentation.rmi.IDLType ;
27 import com.sun.corba.se.impl.presentation.rmi.IDLTypeException ;
28 import com.sun.corba.se.impl.presentation.rmi.IDLTypesUtil ;
29 import com.sun.corba.se.impl.orbutil.ObjectUtility ;
30
31 /**
32  * Bidirectional translator between RMI-IIOP interface methods and
33  * and IDL Names.
34  */

35 public class IDLNameTranslatorImpl implements IDLNameTranslator {
36
37     // From CORBA Spec, Table 6 Keywords.
38
// Note that since all IDL identifiers are case
39
// insensitive, java identifier comparisons to these
40
// will be case insensitive also.
41
private static String JavaDoc[] IDL_KEYWORDS = {
42
43         "abstract", "any", "attribute", "boolean", "case", "char",
44         "const", "context", "custom", "default", "double", "enum",
45         "exception", "factory", "FALSE", "fixed", "float", "in", "inout",
46         "interface", "long", "module", "native", "Object", "octet",
47         "oneway", "out", "private", "public", "raises", "readonly", "sequence",
48         "short", "string", "struct", "supports", "switch", "TRUE", "truncatable",
49         "typedef", "unsigned", "union", "ValueBase", "valuetype", "void",
50     "wchar", "wstring"
51
52     };
53
54     private static char[] HEX_DIGITS = {
55         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
56         'A', 'B', 'C', 'D', 'E', 'F'
57     };
58     
59     private static final String JavaDoc UNDERSCORE = "_";
60
61     // used to mangle java inner class names
62
private static final String JavaDoc INNER_CLASS_SEPARATOR =
63         UNDERSCORE + UNDERSCORE;
64
65     // used to form IDL array type names
66
private static final String JavaDoc[] BASE_IDL_ARRAY_MODULE_TYPE=
67     new String JavaDoc[] { "org", "omg", "boxedRMI" } ;
68
69     private static final String JavaDoc BASE_IDL_ARRAY_ELEMENT_TYPE = "seq";
70
71     // used to mangling java identifiers that have a leading underscore
72
private static final String JavaDoc LEADING_UNDERSCORE_CHAR = "J";
73     private static final String JavaDoc ID_CONTAINER_CLASH_CHAR = UNDERSCORE;
74
75     // separator used between types in a mangled overloaded method name
76
private static final String JavaDoc OVERLOADED_TYPE_SEPARATOR =
77         UNDERSCORE + UNDERSCORE;
78
79     // string appended to attribute if it clashes with a method name
80
private static final String JavaDoc ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS =
81         UNDERSCORE + UNDERSCORE;
82
83     // strings prepended to the attribute names in order to form their
84
// IDL names.
85
private static final String JavaDoc GET_ATTRIBUTE_PREFIX = "_get_";
86     private static final String JavaDoc SET_ATTRIBUTE_PREFIX = "_set_";
87     private static final String JavaDoc IS_ATTRIBUTE_PREFIX = "_get_";
88
89     private static Set JavaDoc idlKeywords_;
90
91     static {
92         
93         idlKeywords_ = new HashSet JavaDoc();
94         for(int i = 0; i < IDL_KEYWORDS.length; i++) {
95             String JavaDoc next = (String JavaDoc) IDL_KEYWORDS[i];
96             // Convert keyword to all caps to ease equality
97
// check.
98
String JavaDoc keywordAllCaps = next.toUpperCase();
99             idlKeywords_.add(keywordAllCaps);
100         }
101
102     }
103
104     //
105
// Instance state
106
//
107

108     // Remote interface for name translation.
109
private Class JavaDoc[] interf_;
110
111     // Maps used to hold name translations. These do not need to be
112
// synchronized since the translation is never modified after
113
// initialization.
114
private Map JavaDoc methodToIDLNameMap_;
115     private Map JavaDoc IDLNameToMethodMap_;
116     private Method JavaDoc[] methods_;
117     
118     /**
119      * Return an IDLNameTranslator for the given interface.
120      *
121      * @throws IllegalStateException if given class is not a valid
122      * RMI/IIOP Remote Interface
123      */

124     public static IDLNameTranslator get( Class JavaDoc interf )
125     {
126         
127         return new IDLNameTranslatorImpl(new Class JavaDoc[] { interf } );
128
129     }
130
131     /**
132      * Return an IDLNameTranslator for the given interfacex.
133      *
134      * @throws IllegalStateException if given classes are not valid
135      * RMI/IIOP Remote Interfaces
136      */

137     public static IDLNameTranslator get( Class JavaDoc[] interfaces )
138     {
139         
140         return new IDLNameTranslatorImpl(interfaces );
141
142     }
143
144     public static String JavaDoc getExceptionId( Class JavaDoc cls )
145     {
146     // Requirements for this method:
147
// 1. cls must be an exception but not a RemoteException.
148
// 2. If cls has an IDL keyword name, an underscore is prepended (1.3.2.2).
149
// 3. If cls jas a leading underscore, J is prepended (1.3.2.3).
150
// 4. If cls has an illegal IDL ident char, it is mapped to UXXXX where
151
// XXXX is the unicode value in hex of the char (1.3.2.4).
152
// 5. double underscore for inner class (1.3.2.5).
153
// 6. The ID is "IDL:" + name with / separators + ":1.0".
154
IDLType itype = classToIDLType( cls ) ;
155     return itype.getExceptionName() ;
156     }
157
158     public Class JavaDoc[] getInterfaces()
159     {
160         return interf_;
161     }
162
163     public Method JavaDoc[] getMethods()
164     {
165     return methods_ ;
166     }
167
168     public Method JavaDoc getMethod( String JavaDoc idlName )
169     {
170         return (Method JavaDoc) IDLNameToMethodMap_.get(idlName);
171     }
172
173     public String JavaDoc getIDLName( Method JavaDoc method )
174     {
175         return (String JavaDoc) methodToIDLNameMap_.get(method);
176     }
177
178     /**
179      * Initialize an IDLNameTranslator for the given interface.
180      *
181      * @throws IllegalStateException if given class is not a valid
182      * RMI/IIOP Remote Interface
183      */

184     private IDLNameTranslatorImpl(Class JavaDoc[] interfaces)
185     {
186         SecurityManager JavaDoc s = System.getSecurityManager();
187         if (s != null) {
188             s.checkPermission(new DynamicAccessPermission("access"));
189         }
190         try {
191             IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
192         for (int ctr=0; ctr<interfaces.length; ctr++)
193         idlTypesUtil.validateRemoteInterface(interfaces[ctr]);
194             interf_ = interfaces;
195             buildNameTranslation();
196         } catch( IDLTypeException ite) {
197             String JavaDoc msg = ite.getMessage();
198             IllegalStateException JavaDoc ise = new IllegalStateException JavaDoc(msg);
199             ise.initCause(ite);
200             throw ise;
201         }
202     }
203
204     private void buildNameTranslation()
205     {
206     // holds method info, keyed by method
207
Map JavaDoc allMethodInfo = new HashMap JavaDoc() ;
208
209     for (int ctr=0; ctr<interf_.length; ctr++) {
210         Class JavaDoc interf = interf_[ctr] ;
211
212         IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
213         final Method JavaDoc[] methods = interf.getMethods();
214         // Handle the case of a non-public interface!
215
AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
216                 public Object JavaDoc run() {
217             Method.setAccessible( methods, true ) ;
218             return null ;
219         }
220         } ) ;
221
222         // Take an initial pass through all the methods and create some
223
// information that will be used to track the IDL name
224
// transformation.
225
for(int i = 0; i < methods.length; i++) {
226         
227         Method JavaDoc nextMethod = methods[i];
228
229         IDLMethodInfo methodInfo = new IDLMethodInfo();
230
231         methodInfo.method = nextMethod;
232
233         if (idlTypesUtil.isPropertyAccessorMethod(nextMethod, interf)) {
234             methodInfo.isProperty = true;
235             String JavaDoc attributeName = idlTypesUtil.
236             getAttributeNameForProperty(nextMethod.getName());
237             methodInfo.originalName = attributeName;
238             methodInfo.mangledName = attributeName;
239         } else {
240             methodInfo.isProperty = false;
241             methodInfo.originalName = nextMethod.getName();
242             methodInfo.mangledName = nextMethod.getName();
243         }
244         
245         allMethodInfo.put(nextMethod, methodInfo);
246         }
247     }
248
249         //
250
// Perform case sensitivity test first. This applies to all
251
// method names AND attributes. Compare each method name and
252
// attribute to all other method names and attributes. If names
253
// differ only in case, apply mangling as defined in section 1.3.2.7
254
// of Java2IDL spec. Note that we compare using the original names.
255
//
256
for(Iterator JavaDoc outerIter=allMethodInfo.values().iterator();
257             outerIter.hasNext();) {
258             IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
259             for(Iterator JavaDoc innerIter = allMethodInfo.values().iterator();
260                 innerIter.hasNext();) {
261                 IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
262
263                 if( (outer != inner) &&
264                     (!outer.originalName.equals(inner.originalName)) &&
265                     outer.originalName.equalsIgnoreCase(inner.originalName) ) {
266                     outer.mangledName =
267                         mangleCaseSensitiveCollision(outer.originalName);
268                     break;
269                 }
270
271             }
272         }
273                    
274         for(Iterator JavaDoc iter = allMethodInfo.values().iterator();
275             iter.hasNext();) {
276             IDLMethodInfo next = (IDLMethodInfo) iter.next();
277             next.mangledName =
278                 mangleIdentifier(next.mangledName, next.isProperty);
279         }
280
281         //
282
// Now check for overloaded method names and apply 1.3.2.6.
283
//
284
for(Iterator JavaDoc outerIter=allMethodInfo.values().iterator();
285             outerIter.hasNext();) {
286             IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
287             if( outer.isProperty ) {
288                 continue;
289             }
290             for(Iterator JavaDoc innerIter = allMethodInfo.values().iterator();
291                 innerIter.hasNext();) {
292                 IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
293
294                 if( (outer != inner) &&
295                     !inner.isProperty &&
296                     outer.originalName.equals(inner.originalName) ) {
297                     outer.mangledName = mangleOverloadedMethod
298                         (outer.mangledName, outer.method);
299                     break;
300                 }
301             }
302         }
303        
304         //
305
// Now mangle any properties that clash with method names.
306
//
307
for(Iterator JavaDoc outerIter=allMethodInfo.values().iterator();
308             outerIter.hasNext();) {
309             IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
310             if( !outer.isProperty ) {
311                 continue;
312             }
313             for(Iterator JavaDoc innerIter = allMethodInfo.values().iterator();
314                 innerIter.hasNext();) {
315                 IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
316                 if( (outer != inner) &&
317                     !inner.isProperty &&
318                     outer.mangledName.equals(inner.mangledName) ) {
319                     outer.mangledName = outer.mangledName +
320                         ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS;
321                     break;
322                 }
323             }
324         }
325
326         //
327
// Ensure that no mapped method names clash with mapped name
328
// of container(1.3.2.9). This is a case insensitive comparison.
329
//
330
for (int ctr=0; ctr<interf_.length; ctr++ ) {
331         Class JavaDoc interf = interf_[ctr] ;
332         String JavaDoc mappedContainerName = getMappedContainerName(interf);
333         for(Iterator JavaDoc iter = allMethodInfo.values().iterator();
334         iter.hasNext();) {
335         IDLMethodInfo next = (IDLMethodInfo) iter.next();
336         if( !next.isProperty &&
337             identifierClashesWithContainer(mappedContainerName,
338                            next.mangledName)) {
339             next.mangledName = mangleContainerClash(next.mangledName);
340         }
341         }
342     }
343
344         //
345
// Populate name translation maps.
346
//
347
methodToIDLNameMap_ = new HashMap JavaDoc();
348         IDLNameToMethodMap_ = new HashMap JavaDoc();
349     methods_ = (Method JavaDoc[])allMethodInfo.keySet().toArray(
350         new Method JavaDoc[0] ) ;
351
352         for(Iterator JavaDoc iter = allMethodInfo.values().iterator();
353             iter.hasNext();) {
354             IDLMethodInfo next = (IDLMethodInfo) iter.next();
355             String JavaDoc idlName = next.mangledName;
356             if( next.isProperty ) {
357                 String JavaDoc origMethodName = next.method.getName();
358                 String JavaDoc prefix = "";
359
360                 if( origMethodName.startsWith("get") ) {
361                     prefix = GET_ATTRIBUTE_PREFIX;
362                 } else if( origMethodName.startsWith("set") ) {
363                     prefix = SET_ATTRIBUTE_PREFIX;
364                 } else {
365                     prefix = IS_ATTRIBUTE_PREFIX;
366                 }
367
368                 idlName = prefix + next.mangledName;
369             }
370             
371             methodToIDLNameMap_.put(next.method, idlName);
372
373             // Final check to see if there are any clashes after all the
374
// manglings have been applied. If so, this is treated as an
375
// invalid interface. Currently, we do a CASE-SENSITIVE
376
// comparison since that matches the rmic behavior.
377
// @@@ Shouldn't this be a case-insensitive check?
378
if( IDLNameToMethodMap_.containsKey(idlName) ) {
379                 // @@@ I18N
380
Method JavaDoc clash = (Method JavaDoc) IDLNameToMethodMap_.get(idlName);
381                 throw new IllegalStateException JavaDoc("Error : methods " +
382                     clash + " and " + next.method +
383                     " both result in IDL name '" + idlName + "'");
384             } else {
385                 IDLNameToMethodMap_.put(idlName, next.method);
386             }
387         }
388
389         return;
390
391     }
392
393     
394     /**
395      * Perform all necessary stand-alone identifier mangling operations
396      * on a java identifier that is being transformed into an IDL name.
397      * That is, mangling operations that don't require looking at anything
398      * else but the identifier itself. This covers sections 1.3.2.2, 1.3.2.3,
399      * and 1.3.2.4 of the Java2IDL spec. Method overloading and
400      * case-sensitivity checks are handled elsewhere.
401      */

402
403     private static String JavaDoc mangleIdentifier(String JavaDoc identifier) {
404         return mangleIdentifier(identifier, false);
405     }
406
407     private static String JavaDoc mangleIdentifier(String JavaDoc identifier, boolean attribute) {
408
409         String JavaDoc mangledName = identifier;
410
411         //
412
// Apply leading underscore test (1.3.2.3)
413
// This should be done before IDL Keyword clash test, since clashing
414
// IDL keywords are mangled by adding a leading underscore.
415
//
416
if( hasLeadingUnderscore(mangledName) ) {
417             mangledName = mangleLeadingUnderscore(mangledName);
418         }
419         
420         //
421
// Apply IDL keyword clash test (1.3.2.2).
422
// This is not needed for attributes since when the full property
423
// name is composed it cannot clash with an IDL keyword.
424
// (Also, rmic doesn't do it.)
425
//
426

427         if( !attribute && isIDLKeyword(mangledName) ) {
428             mangledName = mangleIDLKeywordClash(mangledName);
429         }
430
431         //
432
// Replace illegal IDL identifier characters (1.3.2.4)
433
// for all method names and attributes.
434
//
435
if( !isIDLIdentifier(mangledName) ) {
436             mangledName = mangleUnicodeChars(mangledName);
437         }
438         
439         return mangledName;
440     }
441
442     // isIDLKeyword and mangleIDLKeywordClash are exposed here so that
443
// IDLType can use them.
444
//
445
// XXX refactoring needed:
446
// 1. Split off isIDLKeywork and mangleIDLKeywordClash (and possibly
447
// other methods) into a utility class.
448
// 2. Move all of classToIDLType to a constructor inside IDLType.
449
//
450
// The problem appears to be that we need all of the code that
451
// performs various checks for name problems and the corresponding
452
// fixes into a utility class. Then we need to see what other
453
// refactorings present themselves.
454

455     /**
456      * Checks whether a java identifier clashes with an
457      * IDL keyword. Note that this is a case-insensitive
458      * comparison.
459      *
460      * Used to implement section 1.3.2.2 of Java2IDL spec.
461      */

462     static boolean isIDLKeyword(String JavaDoc identifier) {
463         
464         String JavaDoc identifierAllCaps = identifier.toUpperCase();
465
466         return idlKeywords_.contains(identifierAllCaps);
467     }
468
469     static String JavaDoc mangleIDLKeywordClash(String JavaDoc identifier) {
470         return UNDERSCORE + identifier;
471     }
472
473     private static String JavaDoc mangleLeadingUnderscore(String JavaDoc identifier) {
474         return LEADING_UNDERSCORE_CHAR + identifier;
475     }
476
477     /**
478      * Checks whether a java identifier starts with an underscore.
479      * Used to implement section 1.3.2.3 of Java2IDL spec.
480      */

481     private static boolean hasLeadingUnderscore(String JavaDoc identifier) {
482         return identifier.startsWith(UNDERSCORE);
483     }
484
485     /**
486      * Implements Section 1.3.2.4 of Java2IDL Mapping.
487      * All non-IDL identifier characters must be replaced
488      * with their Unicode representation.
489      */

490     static String JavaDoc mangleUnicodeChars(String JavaDoc identifier) {
491         StringBuffer JavaDoc mangledIdentifier = new StringBuffer JavaDoc();
492
493         for(int i = 0; i < identifier.length(); i++) {
494             char nextChar = identifier.charAt(i);
495             if( isIDLIdentifierChar(nextChar) ) {
496                 mangledIdentifier.append(nextChar);
497             } else {
498                 String JavaDoc unicode = charToUnicodeRepresentation(nextChar);
499                 mangledIdentifier.append(unicode);
500             }
501         }
502         
503         return mangledIdentifier.toString();
504     }
505
506     /**
507      * Implements mangling portion of Section 1.3.2.7 of Java2IDL spec.
508      * This method only deals with the actual mangling. Decision about
509      * whether case-sensitive collision mangling is required is made
510      * elsewhere.
511      *
512      *
513      * "...a mangled name is generated consisting of the original name
514      * followed by an underscore separated list of decimal indices
515      * into the string, where the indices identify all the upper case
516      * characters in the original string. Indices are zero based."
517      *
518      */

519     String JavaDoc mangleCaseSensitiveCollision(String JavaDoc identifier) {
520
521         StringBuffer JavaDoc mangledIdentifier = new StringBuffer JavaDoc(identifier);
522
523         // There is always at least one trailing underscore, whether or
524
// not the identifier has uppercase letters.
525
mangledIdentifier.append(UNDERSCORE);
526
527         boolean needUnderscore = false;
528         for(int i = 0; i < identifier.length(); i++) {
529             char next = identifier.charAt(i);
530             if( Character.isUpperCase(next) ) {
531                 // This bit of logic is needed to ensure that we have
532
// an underscore separated list of indices but no
533
// trailing underscores. Basically, after we have at least
534
// one uppercase letter, we always put an undercore before
535
// printing the next one.
536
if( needUnderscore ) {
537                     mangledIdentifier.append(UNDERSCORE);
538                 }
539                 mangledIdentifier.append(i);
540                 needUnderscore = true;
541             }
542         }
543
544         return mangledIdentifier.toString();
545     }
546
547     private static String JavaDoc mangleContainerClash(String JavaDoc identifier) {
548         return identifier + ID_CONTAINER_CLASH_CHAR;
549     }
550
551     /**
552      * Implements Section 1.3.2.9 of Java2IDL Mapping. Container in this
553      * context means the name of the java Class(excluding package) in which
554      * the identifier is defined. Comparison is case-insensitive.
555      */

556     private static boolean identifierClashesWithContainer
557         (String JavaDoc mappedContainerName, String JavaDoc identifier) {
558
559         return identifier.equalsIgnoreCase(mappedContainerName);
560     }
561
562     /**
563      * Returns Unicode mangling as defined in Section 1.3.2.4 of
564      * Java2IDL spec.
565      *
566      * "For Java identifiers that contain illegal OMG IDL identifier
567      * characters such as '$' or Unicode characters outside of ISO Latin 1,
568      * any such illegal characters are replaced by "U" followed by the
569      * 4 hexadecimal characters(in upper case) representing the Unicode
570      * value. So, the Java name a$b is mapped to aU0024b and
571      * x?y is mapped to xU03BCy."
572      */

573     public static String JavaDoc charToUnicodeRepresentation(char c) {
574         
575         int orig = (int) c;
576         StringBuffer JavaDoc hexString = new StringBuffer JavaDoc();
577         
578         int value = orig;
579
580         while( value > 0 ) {
581             int div = value / 16;
582             int mod = value % 16;
583             hexString.insert(0, HEX_DIGITS[mod]);
584             value = div;
585         }
586
587         int numZerosToAdd = 4 - hexString.length();
588         for(int i = 0; i < numZerosToAdd; i++) {
589             hexString.insert(0, "0");
590         }
591
592         hexString.insert(0, "U");
593         return hexString.toString();
594     }
595
596     private static boolean isIDLIdentifier(String JavaDoc identifier) {
597
598         boolean isIdentifier = true;
599
600         for(int i = 0; i < identifier.length(); i++) {
601             char nextChar = identifier.charAt(i);
602             // 1st char must be alphbetic.
603
isIdentifier = (i == 0) ?
604                 isIDLAlphabeticChar(nextChar) :
605                 isIDLIdentifierChar(nextChar);
606             if( !isIdentifier ) {
607                 break;
608             }
609         }
610
611         return isIdentifier;
612         
613     }
614
615     private static boolean isIDLIdentifierChar(char c) {
616         return (isIDLAlphabeticChar(c) ||
617                 isIDLDecimalDigit(c) ||
618                 isUnderscore(c));
619     }
620
621     /**
622      * True if character is one of 114 Alphabetic characters as
623      * specified in Table 2 of Chapter 3 in CORBA spec.
624      */

625     private static boolean isIDLAlphabeticChar(char c) {
626
627         // NOTE that we can't use the java.lang.Character
628
// isUpperCase, isLowerCase, etc. methods since they
629
// include many characters other than the Alphabetic list in
630
// the CORBA spec. Instead, we test for inclusion in the
631
// Unicode value ranges for the corresponding legal characters.
632

633         boolean alphaChar =
634             (
635              // A - Z
636
((c >= 0x0041) && (c <= 0x005A))
637
638              ||
639              
640              // a - z
641
((c >= 0x0061) && (c <= 0x007A))
642              
643              ||
644              
645              // other letter uppercase, other letter lowercase, which is
646
// the entire upper half of C1 Controls except X and /
647
((c >= 0x00C0) && (c <= 0x00FF)
648               && (c != 0x00D7) && (c != 0x00F7)));
649         
650         return alphaChar;
651     }
652
653     /**
654      * True if character is one of 10 Decimal Digits
655      * specified in Table 3 of Chapter 3 in CORBA spec.
656      */

657     private static boolean isIDLDecimalDigit(char c) {
658         return ( (c >= 0x0030) && (c <= 0x0039) );
659     }
660
661     private static boolean isUnderscore(char c) {
662         return ( c == 0x005F );
663     }
664     
665     /**
666      * Mangle an overloaded method name as defined in Section 1.3.2.6 of
667      * Java2IDL spec. Current value of method name is passed in as argument.
668      * We can't start from original method name since the name might have
669      * been partially mangled as a result of the other rules.
670      */

671     private static String JavaDoc mangleOverloadedMethod(String JavaDoc mangledName, Method JavaDoc m) {
672
673         IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
674
675         // Start by appending the separator string
676
String JavaDoc newMangledName = mangledName + OVERLOADED_TYPE_SEPARATOR;
677         
678         Class JavaDoc[] parameterTypes = m.getParameterTypes();
679         
680         for(int i = 0; i < parameterTypes.length; i++) {
681             Class JavaDoc nextParamType = parameterTypes[i];
682             
683             if( i > 0 ) {
684                 newMangledName = newMangledName + OVERLOADED_TYPE_SEPARATOR;
685             }
686             IDLType idlType = classToIDLType(nextParamType);
687
688             String JavaDoc moduleName = idlType.getModuleName();
689             String JavaDoc memberName = idlType.getMemberName();
690
691             String JavaDoc typeName = (moduleName.length() > 0) ?
692                 moduleName + UNDERSCORE + memberName : memberName;
693                                    
694             if( !idlTypesUtil.isPrimitive(nextParamType) &&
695                 (idlTypesUtil.getSpecialCaseIDLTypeMapping(nextParamType)
696                  == null) &&
697                 isIDLKeyword(typeName) ) {
698                 typeName = mangleIDLKeywordClash(typeName);
699             }
700
701             typeName = mangleUnicodeChars(typeName);
702
703             newMangledName = newMangledName + typeName;
704         }
705
706         return newMangledName;
707     }
708
709
710     private static IDLType classToIDLType(Class JavaDoc c) {
711                
712         IDLType idlType = null;
713         IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
714
715         if( idlTypesUtil.isPrimitive(c) ) {
716
717             idlType = idlTypesUtil.getPrimitiveIDLTypeMapping(c);
718
719         } else if( c.isArray() ) {
720             
721             // Calculate array depth, as well as base element type.
722
Class JavaDoc componentType = c.getComponentType();
723             int numArrayDimensions = 1;
724             while(componentType.isArray()) {
725                 componentType = componentType.getComponentType();
726                 numArrayDimensions++;
727             }
728             IDLType componentIdlType = classToIDLType(componentType);
729             
730             String JavaDoc[] modules = BASE_IDL_ARRAY_MODULE_TYPE;
731             if( componentIdlType.hasModule() ) {
732                 modules = (String JavaDoc[])ObjectUtility.concatenateArrays( modules,
733                     componentIdlType.getModules() ) ;
734             }
735
736             String JavaDoc memberName = BASE_IDL_ARRAY_ELEMENT_TYPE +
737                 numArrayDimensions + UNDERSCORE +
738                 componentIdlType.getMemberName();
739             
740             idlType = new IDLType(c, modules, memberName);
741                
742         } else {
743             idlType = idlTypesUtil.getSpecialCaseIDLTypeMapping(c);
744
745             if (idlType == null) {
746                 // Section 1.3.2.5 of Java2IDL spec defines mangling rules for
747
// inner classes.
748
String JavaDoc memberName = getUnmappedContainerName(c);
749
750                 // replace inner class separator with double underscore
751
memberName = memberName.replaceAll("\\$",
752                                                    INNER_CLASS_SEPARATOR);
753                                 
754                 if( hasLeadingUnderscore(memberName) ) {
755                     memberName = mangleLeadingUnderscore(memberName);
756                 }
757
758                 // Get raw package name. If there is a package, it
759
// will still have the "." separators and none of the
760
// mangling rules will have been applied.
761
String JavaDoc packageName = getPackageName(c);
762                 
763                 if (packageName == null) {
764             idlType = new IDLType( c, memberName ) ;
765         } else {
766             // If this is a generated IDL Entity Type we need to
767
// prepend org_omg_boxedIDL per sections 1.3.5 and 1.3.9
768
if (idlTypesUtil.isEntity(c)) {
769             packageName = "org.omg.boxedIDL." + packageName ;
770             }
771             
772             // Section 1.3.2.1 and 1.3.2.6 of Java2IDL spec defines
773
// rules for mapping java packages to IDL modules and for
774
// mangling module name portion of type name. NOTE that
775
// of the individual identifier mangling rules,
776
// only the leading underscore test is done here.
777
// The other two(IDL Keyword, Illegal Unicode chars) are
778
// done in mangleOverloadedMethodName.
779
StringTokenizer JavaDoc tokenizer =
780                         new StringTokenizer JavaDoc(packageName, ".");
781             
782             String JavaDoc[] modules = new String JavaDoc[ tokenizer.countTokens() ] ;
783             int index = 0 ;
784                     while (tokenizer.hasMoreElements()) {
785                         String JavaDoc next = tokenizer.nextToken();
786                         String JavaDoc moreMangled = hasLeadingUnderscore( next ) ?
787                             mangleLeadingUnderscore( next ) : next;
788
789             modules[index++] = moreMangled ;
790                     }
791
792             idlType = new IDLType(c, modules, memberName);
793                 }
794             }
795         }
796
797         return idlType;
798     }
799
800     /**
801      * Return Class' package name or null if there is no package.
802      */

803     private static String JavaDoc getPackageName(Class JavaDoc c) {
804         Package JavaDoc thePackage = c.getPackage();
805         String JavaDoc packageName = null;
806
807         // Try to get package name by introspection. Some classloaders might
808
// not provide this information, so check for null.
809
if( thePackage != null ) {
810             packageName = thePackage.getName();
811         } else {
812             // brute force method
813
String JavaDoc fullyQualifiedClassName = c.getName();
814             int lastDot = fullyQualifiedClassName.indexOf('.');
815             packageName = (lastDot == -1) ? null :
816                 fullyQualifiedClassName.substring(0, lastDot);
817         }
818         return packageName;
819     }
820     
821     private static String JavaDoc getMappedContainerName(Class JavaDoc c) {
822         String JavaDoc unmappedName = getUnmappedContainerName(c);
823
824         return mangleIdentifier(unmappedName);
825     }
826
827     /**
828      * Return portion of class name excluding package name.
829      */

830     private static String JavaDoc getUnmappedContainerName(Class JavaDoc c) {
831
832         String JavaDoc memberName = null;
833         String JavaDoc packageName = getPackageName(c);
834
835         String JavaDoc fullyQualifiedClassName = c.getName();
836                
837         if( packageName != null ) {
838             int packageLength = packageName.length();
839             memberName = fullyQualifiedClassName.substring(packageLength + 1);
840         } else {
841             memberName = fullyQualifiedClassName;
842
843         }
844
845         return memberName;
846     }
847
848     /**
849      * Internal helper class for tracking information related to each
850      * interface method while we're building the name translation table.
851      */

852     private static class IDLMethodInfo
853     {
854         public Method JavaDoc method;
855         public boolean isProperty;
856         
857         // If this is a property, originalName holds the original
858
// attribute name. Otherwise, it holds the original method name.
859
public String JavaDoc originalName;
860
861         // If this is a property, mangledName holds the mangled attribute
862
// name. Otherwise, it holds the mangled method name.
863
public String JavaDoc mangledName;
864
865     }
866
867     public String JavaDoc toString() {
868
869         StringBuffer JavaDoc contents = new StringBuffer JavaDoc();
870         contents.append("IDLNameTranslator[" );
871     for( int ctr=0; ctr<interf_.length; ctr++) {
872         if (ctr != 0)
873         contents.append( " " ) ;
874         contents.append( interf_[ctr].getName() ) ;
875     }
876         contents.append("]\n");
877         for(Iterator JavaDoc iter = methodToIDLNameMap_.keySet().iterator();
878             iter.hasNext();) {
879
880             Method JavaDoc method = (Method JavaDoc) iter.next();
881             String JavaDoc idlName = (String JavaDoc) methodToIDLNameMap_.get(method);
882
883             contents.append(idlName + ":" + method + "\n");
884
885         }
886
887         return contents.toString();
888     }
889
890     public static void main(String JavaDoc[] args) {
891         
892         Class JavaDoc remoteInterface = java.rmi.Remote JavaDoc.class;
893         
894         if( args.length > 0 ) {
895             String JavaDoc className = args[0];
896             try {
897                 remoteInterface = Class.forName(className);
898             } catch(Exception JavaDoc e) {
899                 e.printStackTrace();
900                 System.exit(-1);
901             }
902         }
903         
904         System.out.println("Building name translation for " + remoteInterface);
905         try {
906             IDLNameTranslator nameTranslator =
907                 IDLNameTranslatorImpl.get(remoteInterface);
908             System.out.println(nameTranslator);
909         } catch(IllegalStateException JavaDoc ise) {
910             ise.printStackTrace();
911         }
912     }
913 }
914
Popular Tags