1 /* 2 * Copyright (c) 2003, 2013, 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 */ 25 26 package com.sun.corba.se.impl.presentation.rmi ; 27 28 import java.security.AccessController; 29 import java.security.PrivilegedAction; 30 31 import java.lang.reflect.Method; 32 33 import java.math.BigInteger; 34 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; 41 42 import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ; 43 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 ; 48 49 /** 50 * Bidirectional translator between RMI-IIOP interface methods and 51 * and IDL Names. 52 */ 53 public class IDLNameTranslatorImpl implements IDLNameTranslator { 54 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 = { 60 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" 69 70 }; 71 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 }; 76 77 private static final String UNDERSCORE = "_"; 78 79 // used to mangle java inner class names 80 private static final String INNER_CLASS_SEPARATOR = 81 UNDERSCORE + UNDERSCORE; 82 83 // used to form IDL array type names 84 private static final String[] BASE_IDL_ARRAY_MODULE_TYPE= 85 new String[] { "org", "omg", "boxedRMI" } ; 86 87 private static final String BASE_IDL_ARRAY_ELEMENT_TYPE = "seq"; 88 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; 92 93 // separator used between types in a mangled overloaded method name 94 private static final String OVERLOADED_TYPE_SEPARATOR = 95 UNDERSCORE + UNDERSCORE; 96 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; 100 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_"; 106 107 private static Set idlKeywords_; 108 109 static { 110 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 } 119 120 } 121 122 // 123 // Instance state 124 // 125 126 // Remote interface for name translation. 127 private Class[] interf_; 128 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_; 135 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 { 144 145 return new IDLNameTranslatorImpl(new Class[] { interf } ); 146 147 } 148 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 { 157 158 return new IDLNameTranslatorImpl(interfaces ); 159 160 } 161 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 } 175 176 public Class[] getInterfaces() 177 { 178 return interf_; 179 } 180 181 public Method[] getMethods() 182 { 183 return methods_ ; 184 } 185 186 public Method getMethod( String idlName ) 187 { 188 return (Method) IDLNameToMethodMap_.get(idlName); 189 } 190 191 public String getIDLName( Method method ) 192 { 193 return (String) methodToIDLNameMap_.get(method); 194 } 195 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 { 204 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 } 222 223 private void buildNameTranslation() 224 { 225 // holds method info, keyed by method 226 Map allMethodInfo = new HashMap() ; 227 228 for (int ctr=0; ctr<interf_.length; ctr++) { 229 Class interf = interf_[ctr] ; 230 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 } ) ; 240 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++) { 245 246 Method nextMethod = methods[i]; 247 248 IDLMethodInfo methodInfo = new IDLMethodInfo(); 249 250 methodInfo.method = nextMethod; 251 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 } 263 264 allMethodInfo.put(nextMethod, methodInfo); 265 } 266 } 267 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(); 281 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 } 289 290 } 291 } 292 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 } 299 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(); 312 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 } 322 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 } 344 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 } 362 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] ) ; 370 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 = ""; 378 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 } 386 387 idlName = prefix + next.mangledName; 388 } 389 390 methodToIDLNameMap_.put(next.method, idlName); 391 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 } 407 408 return; 409 410 } 411 412 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 */ 421 422 private static String mangleIdentifier(String identifier) { 423 return mangleIdentifier(identifier, false); 424 } 425 426 private static String mangleIdentifier(String identifier, boolean attribute) { 427 428 String mangledName = identifier; 429 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 } 438 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 // 445 446 if( !attribute && isIDLKeyword(mangledName) ) { 447 mangledName = mangleIDLKeywordClash(mangledName); 448 } 449 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 } 457 458 return mangledName; 459 } 460 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. 473 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) { 482 483 String identifierAllCaps = identifier.toUpperCase(); 484 485 return idlKeywords_.contains(identifierAllCaps); 486 } 487 488 static String mangleIDLKeywordClash(String identifier) { 489 return UNDERSCORE + identifier; 490 } 491 492 private static String mangleLeadingUnderscore(String identifier) { 493 return LEADING_UNDERSCORE_CHAR + identifier; 494 } 495 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 } 503 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(); 511 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 } 521 522 return mangledIdentifier.toString(); 523 } 524 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) { 539 540 StringBuffer mangledIdentifier = new StringBuffer(identifier); 541 542 // There is always at least one trailing underscore, whether or 543 // not the identifier has uppercase letters. 544 mangledIdentifier.append(UNDERSCORE); 545 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 } 562 563 return mangledIdentifier.toString(); 564 } 565 566 private static String mangleContainerClash(String identifier) { 567 return identifier + ID_CONTAINER_CLASH_CHAR; 568 } 569 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) { 577 578 return identifier.equalsIgnoreCase(mappedContainerName); 579 } 580 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) { 593 594 int orig = (int) c; 595 StringBuffer hexString = new StringBuffer(); 596 597 int value = orig; 598 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 } 605 606 int numZerosToAdd = 4 - hexString.length(); 607 for(int i = 0; i < numZerosToAdd; i++) { 608 hexString.insert(0, "0"); 609 } 610 611 hexString.insert(0, "U"); 612 return hexString.toString(); 613 } 614 615 private static boolean isIDLIdentifier(String identifier) { 616 617 boolean isIdentifier = true; 618 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 } 629 630 return isIdentifier; 631 632 } 633 634 private static boolean isIDLIdentifierChar(char c) { 635 return (isIDLAlphabeticChar(c) || 636 isIDLDecimalDigit(c) || 637 isUnderscore(c)); 638 } 639 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) { 645 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. 651 652 boolean alphaChar = 653 ( 654 // A - Z 655 ((c >= 0x0041) && (c <= 0x005A)) 656 657 || 658 659 // a - z 660 ((c >= 0x0061) && (c <= 0x007A)) 661 662 || 663 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))); 668 669 return alphaChar; 670 } 671 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 } 679 680 private static boolean isUnderscore(char c) { 681 return ( c == 0x005F ); 682 } 683 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) { 691 692 IDLTypesUtil idlTypesUtil = new IDLTypesUtil(); 693 694 // Start by appending the separator string 695 String newMangledName = mangledName + OVERLOADED_TYPE_SEPARATOR; 696 697 Class[] parameterTypes = m.getParameterTypes(); 698 699 for(int i = 0; i < parameterTypes.length; i++) { 700 Class nextParamType = parameterTypes[i]; 701 702 if( i > 0 ) { 703 newMangledName = newMangledName + OVERLOADED_TYPE_SEPARATOR; 704 } 705 IDLType idlType = classToIDLType(nextParamType); 706 707 String moduleName = idlType.getModuleName(); 708 String memberName = idlType.getMemberName(); 709 710 String typeName = (moduleName.length() > 0) ? 711 moduleName + UNDERSCORE + memberName : memberName; 712 713 if( !idlTypesUtil.isPrimitive(nextParamType) && 714 (idlTypesUtil.getSpecialCaseIDLTypeMapping(nextParamType) 715 == null) && 716 isIDLKeyword(typeName) ) { 717 typeName = mangleIDLKeywordClash(typeName); 718 } 719 720 typeName = mangleUnicodeChars(typeName); 721 722 newMangledName = newMangledName + typeName; 723 } 724 725 return newMangledName; 726 } 727 728 729 private static IDLType classToIDLType(Class c) { 730 731 IDLType idlType = null; 732 IDLTypesUtil idlTypesUtil = new IDLTypesUtil(); 733 734 if( idlTypesUtil.isPrimitive(c) ) { 735 736 idlType = idlTypesUtil.getPrimitiveIDLTypeMapping(c); 737 738 } else if( c.isArray() ) { 739 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); 748 749 String[] modules = BASE_IDL_ARRAY_MODULE_TYPE; 750 if( componentIdlType.hasModule() ) { 751 modules = (String[])ObjectUtility.concatenateArrays( modules, 752 componentIdlType.getModules() ) ; 753 } 754 755 String memberName = BASE_IDL_ARRAY_ELEMENT_TYPE + 756 numArrayDimensions + UNDERSCORE + 757 componentIdlType.getMemberName(); 758 759 idlType = new IDLType(c, modules, memberName); 760 761 } else { 762 idlType = idlTypesUtil.getSpecialCaseIDLTypeMapping(c); 763 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); 768 769 // replace inner class separator with double underscore 770 memberName = memberName.replaceAll("\\$", 771 INNER_CLASS_SEPARATOR); 772 773 if( hasLeadingUnderscore(memberName) ) { 774 memberName = mangleLeadingUnderscore(memberName); 775 } 776 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); 781 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 } 790 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, "."); 800 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; 807 808 modules[index++] = moreMangled ; 809 } 810 811 idlType = new IDLType(c, modules, memberName); 812 } 813 } 814 } 815 816 return idlType; 817 } 818 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; 825 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 } 839 840 private static String getMappedContainerName(Class c) { 841 String unmappedName = getUnmappedContainerName(c); 842 843 return mangleIdentifier(unmappedName); 844 } 845 846 /** 847 * Return portion of class name excluding package name. 848 */ 849 private static String getUnmappedContainerName(Class c) { 850 851 String memberName = null; 852 String packageName = getPackageName(c); 853 854 String fullyQualifiedClassName = c.getName(); 855 856 if( packageName != null ) { 857 int packageLength = packageName.length(); 858 memberName = fullyQualifiedClassName.substring(packageLength + 1); 859 } else { 860 memberName = fullyQualifiedClassName; 861 862 } 863 864 return memberName; 865 } 866 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; 875 876 // If this is a property, originalName holds the original 877 // attribute name. Otherwise, it holds the original method name. 878 public String originalName; 879 880 // If this is a property, mangledName holds the mangled attribute 881 // name. Otherwise, it holds the mangled method name. 882 public String mangledName; 883 884 } 885 886 public String toString() { 887 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();) { 898 899 Method method = (Method) iter.next(); 900 String idlName = (String) methodToIDLNameMap_.get(method); 901 902 contents.append(idlName + ":" + method + "\n"); 903 904 } 905 906 return contents.toString(); 907 } 908 }