1 /* 2 * Copyright (c) 1998, 2012, 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 /* 27 * Licensed Materials - Property of IBM 28 * RMI-IIOP v1.0 29 * Copyright IBM Corp. 1998 1999 All Rights Reserved 30 * 31 */ 32 33 package sun.rmi.rmic.iiop; 34 35 import java.util.Hashtable; 36 import java.util.Locale; 37 import sun.tools.java.Identifier; 38 import sun.tools.java.CompilerError; 39 import sun.tools.java.ClassDefinition; 40 import sun.tools.java.ClassNotFound; 41 import com.sun.corba.se.impl.util.RepositoryId; 42 43 /** 44 * IDLNames provides static utility methods to perform the IDL 45 * name mappings specified in Chapter 5 of the Java Language 46 * to IDL specification. 47 * 48 * @author Bryan Atsatt 49 */ 50 public class IDLNames implements sun.rmi.rmic.iiop.Constants { 51 52 /** 53 * Used to convert ascii to hex. 54 */ 55 public static final byte ASCII_HEX[] = { 56 (byte)'0', 57 (byte)'1', 58 (byte)'2', 59 (byte)'3', 60 (byte)'4', 61 (byte)'5', 62 (byte)'6', 63 (byte)'7', 64 (byte)'8', 65 (byte)'9', 66 (byte)'A', 67 (byte)'B', 68 (byte)'C', 69 (byte)'D', 70 (byte)'E', 71 (byte)'F', 72 }; 73 74 // Legal IDL Identifier characters (1 = legal). Note 75 // that '.' (2E) is marked as legal even though it is 76 // not legal in IDL. This allows us to treat a fully 77 // qualified Java name with '.' package separators 78 // uniformly, and is safe because that is the only 79 // legal use of '.' in a Java name. 80 81 private static final byte[] IDL_IDENTIFIER_CHARS = { 82 83 // 0 1 2 3 4 5 6 7 8 9 a b c d e f 84 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 00-0f 85 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 10-1f 86 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,0, // 20-2f 87 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, // 30-3f 88 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 40-4f 89 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,1, // 50-5f 90 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 60-6f 91 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, // 70-7f 92 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 80-8f 93 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 90-9f 94 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // a0-af 95 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // b0-bf 96 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // c0-cf 97 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // d0-df 98 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // e0-ef 99 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // f0-ff 100 }; 101 102 //_____________________________________________________________________ 103 // Public Interfaces 104 //_____________________________________________________________________ 105 106 /** 107 * Convert a name. The nameContext argument MUST be pre-filled with 108 * all names from the appropriate context (e.g. all the method names 109 * in a given class). The names must not have had any IDL conversions 110 * applied. 111 * <p> 112 * Section 28.3.2.2 113 * Section 28.3.2.3 114 * Section 28.3.2.4 115 * Section 28.3.2.7 (member and method names only) 116 */ getMemberOrMethodName(NameContext nameContext, String name, BatchEnvironment env)117 public static String getMemberOrMethodName (NameContext nameContext, 118 String name, 119 BatchEnvironment env) { 120 121 // Check namesCache... 122 123 String result = (String) env.namesCache.get(name); 124 125 if (result == null) { 126 127 // 28.3.2.7 Case sensitive member names. 128 129 // Note: This must be done before any of 130 // the other conversions! 131 132 result = nameContext.get(name); 133 134 // 28.3.2.3 Leading underscores... 135 136 result = convertLeadingUnderscores(result); 137 138 // 28.3.2.2 IDL keywords (NOTE: must be done 139 // after leading underscore conversion because 140 // the mangling for IDL keywords creates a 141 // leading underscore!)... 142 143 result = convertIDLKeywords(result); 144 145 // 28.3.2.4 Illegal IDL identifier characters... 146 147 result = convertToISOLatin1(result); 148 149 // Add to namesCache... 150 151 env.namesCache.put(name,result); 152 } 153 154 return result; 155 } 156 157 /** 158 * Convert names with illegal IDL identifier characters. 159 * <p> 160 * Section 28.3.2.4 161 */ convertToISOLatin1(String name)162 public static String convertToISOLatin1 (String name) { 163 164 // First, replace any escape sequences... 165 166 String result = replace(name,"x\\u","U"); 167 result = replace(result,"x\\U","U"); 168 169 // Now see if we have any remaining illegal characters (see 170 // IDL_IDENTIFIER_CHARS array)... 171 172 int length = result.length(); 173 StringBuffer buffer = null; 174 175 for (int i = 0; i < length; i++) { 176 177 char c = result.charAt(i); 178 179 if (c > 255 || IDL_IDENTIFIER_CHARS[c] == 0) { 180 181 // We gotta convert. Have we already started? 182 183 if (buffer == null) { 184 185 // No, so get set up... 186 187 buffer = new StringBuffer(result.substring(0,i)); 188 } 189 190 // Convert the character into the IDL escape syntax... 191 192 buffer.append("U"); 193 buffer.append((char)ASCII_HEX[(c & 0xF000) >>> 12]); 194 buffer.append((char)ASCII_HEX[(c & 0x0F00) >>> 8]); 195 buffer.append((char)ASCII_HEX[(c & 0x00F0) >>> 4]); 196 buffer.append((char)ASCII_HEX[(c & 0x000F)]); 197 198 } else { 199 if (buffer != null) { 200 buffer.append(c); 201 } 202 } 203 } 204 205 if (buffer != null) { 206 result = buffer.toString(); 207 } 208 209 return result; 210 } 211 212 /** 213 * Convert names which collide with IDL keywords. 214 * <p> 215 * Section 28.3.2.5 216 */ convertIDLKeywords(String name)217 public static String convertIDLKeywords (String name) { 218 219 for (int i = 0; i < IDL_KEYWORDS.length; i++) { 220 if (name.equalsIgnoreCase(IDL_KEYWORDS[i])) { 221 return "_" + name; 222 } 223 } 224 225 return name; 226 } 227 228 /** 229 * Convert names which have leading underscores 230 * <p> 231 * Section 28.3.2.3 232 */ convertLeadingUnderscores(String name)233 public static String convertLeadingUnderscores (String name) { 234 235 if (name.startsWith("_")) { 236 return "J" + name; 237 } 238 239 return name; 240 } 241 242 /** 243 * Convert a type name. 244 * <p> 245 * Section 28.3.2.5 246 * Section 28.3.2.7 (class or interface names only) 247 * Throws exception if fails 28.3.2.7. 248 */ getClassOrInterfaceName(Identifier id, BatchEnvironment env)249 public static String getClassOrInterfaceName (Identifier id, 250 BatchEnvironment env) throws Exception { 251 252 // Get the type and package name... 253 254 String typeName = id.getName().toString(); 255 String packageName = null; 256 257 if (id.isQualified()) { 258 packageName = id.getQualifier().toString(); 259 } 260 261 // Check namesCache... 262 263 String result = (String) env.namesCache.get(typeName); 264 265 if (result == null) { 266 267 // 28.3.2.5 Inner classes... 268 269 result = replace(typeName,". ","__"); 270 271 // 28.3.2.4 Illegal identifier characters... 272 273 result = convertToISOLatin1(result); 274 275 // 28.3.2.7 Case sensitive class or interface names... 276 277 NameContext context = NameContext.forName(packageName,false,env); 278 context.assertPut(result); 279 280 // Run it through the name checks... 281 282 result = getTypeOrModuleName(result); 283 284 // Add it to the namesCache... 285 286 env.namesCache.put(typeName,result); 287 } 288 289 return result; 290 } 291 292 /** 293 * Convert an Exception name. 294 * <p> 295 * Section 28.3.7.2 (see ValueType) 296 */ getExceptionName(String idlName)297 public static String getExceptionName (String idlName) { 298 299 String result = idlName; 300 // d.11315 Incorrectly mangled exception names 301 if (idlName.endsWith(EXCEPTION_SUFFIX)) { 302 303 // Remove "Exception" and append "Ex". Strip leading underscore 304 // in case the idlName is exactly "_Exception"... 305 306 result = stripLeadingUnderscore(idlName.substring(0,idlName.lastIndexOf(EXCEPTION_SUFFIX)) + EX_SUFFIX); 307 } else { 308 result = idlName + EX_SUFFIX; 309 } 310 311 return result; 312 } 313 314 /** 315 * Convert a qualified Identifier into an array of IDL names. 316 * <p> 317 * Section 28.3.2.1 (see CompoundType) 318 * Throws exception if fails 28.3.2.7. 319 */ getModuleNames(Identifier theID, boolean boxIt, BatchEnvironment env)320 public static String[] getModuleNames (Identifier theID, 321 boolean boxIt, 322 BatchEnvironment env) throws Exception { 323 324 String[] result = null; 325 326 if (theID.isQualified()) { 327 328 // Extract the qualifier... 329 330 Identifier id = theID.getQualifier(); 331 332 // 28.3.2.7 Case sensitive module names. 333 334 env.modulesContext.assertPut(id.toString()); 335 336 // Count them... 337 338 int count = 1; 339 Identifier current = id; 340 while (current.isQualified()) { 341 current = current.getQualifier(); 342 count++; 343 } 344 345 result = new String[count]; 346 int index = count-1; 347 current = id; 348 349 // Now walk them and fill our array (backwards)... 350 351 for (int i = 0; i < count; i++) { 352 353 String item = current.getName().toString(); 354 355 // Check namesCache... 356 357 String cachedItem = (String) env.namesCache.get(item); 358 359 if (cachedItem == null) { 360 361 // 28.3.2.4 Illegal identifier characters... 362 363 cachedItem = convertToISOLatin1(item); 364 365 // Run it through the name checks... 366 367 cachedItem = getTypeOrModuleName(cachedItem); 368 369 // Add it to the namesCache... 370 371 env.namesCache.put(item,cachedItem); 372 } 373 374 result[index--] = cachedItem; 375 current = current.getQualifier(); 376 } 377 } 378 379 380 // If it is supposed to be "boxed", prepend 381 // IDL_BOXEDIDL_MODULE... 382 383 if (boxIt) { 384 if (result == null) { 385 result = IDL_BOXEDIDL_MODULE; 386 } else { 387 String[] boxed = new String[result.length+IDL_BOXEDIDL_MODULE.length]; 388 System.arraycopy(IDL_BOXEDIDL_MODULE,0,boxed,0,IDL_BOXEDIDL_MODULE.length); 389 System.arraycopy(result,0,boxed,IDL_BOXEDIDL_MODULE.length,result.length); 390 result = boxed; 391 } 392 } 393 394 return result; 395 } 396 397 /** 398 * Get an array name with the specified dimensions. 399 * <p> 400 * Section 28.3.6 (see ArrayType) 401 */ getArrayName(Type theType, int arrayDimension)402 public static String getArrayName (Type theType, int arrayDimension) { 403 404 StringBuffer idlName = new StringBuffer(64); 405 406 // Prefix with seq<n>_... 407 408 idlName.append(IDL_SEQUENCE); 409 idlName.append(Integer.toString(arrayDimension)); 410 idlName.append("_"); 411 412 // Add the type name. We need to map any spaces in the 413 // name to "_"... 414 415 idlName.append(replace(stripLeadingUnderscore(theType.getIDLName())," ","_")); 416 417 // And we're done... 418 419 return idlName.toString(); 420 } 421 422 /** 423 * Get an array module names. 424 */ getArrayModuleNames(Type theType)425 public static String[] getArrayModuleNames (Type theType) { 426 427 String[] moduleName; 428 String[] typeModule = theType.getIDLModuleNames(); 429 int typeModuleLength = typeModule.length; 430 431 // Does the type have a module? 432 433 if (typeModuleLength == 0) { 434 435 // Nope, so just use the sequence module... 436 437 moduleName = IDL_SEQUENCE_MODULE; 438 } else { 439 440 // Yes, so gotta concatenate... 441 442 moduleName = new String[typeModuleLength + IDL_SEQUENCE_MODULE.length]; 443 System.arraycopy(IDL_SEQUENCE_MODULE,0,moduleName,0,IDL_SEQUENCE_MODULE.length); 444 System.arraycopy(typeModule,0,moduleName,IDL_SEQUENCE_MODULE.length,typeModuleLength); 445 } 446 447 return moduleName; 448 } 449 getInitialAttributeKind(CompoundType.Method method, BatchEnvironment env)450 private static int getInitialAttributeKind (CompoundType.Method method, 451 BatchEnvironment env) throws ClassNotFound { 452 453 int result = ATTRIBUTE_NONE; 454 455 // First make sure it is not a constructor... 456 457 if (!method.isConstructor()) { 458 459 // Now check exceptions. It may not throw any checked 460 // exception other than RemoteException or one of its 461 // subclasses... 462 463 boolean validExceptions = true; 464 ClassType[] exceptions = method.getExceptions(); 465 466 if (exceptions.length > 0) { 467 for (int i = 0; i < exceptions.length; i++) { 468 if (exceptions[i].isCheckedException() && 469 !exceptions[i].isRemoteExceptionOrSubclass()) { 470 validExceptions = false; 471 break; 472 } 473 } 474 } else { 475 476 // If this is a ValueType, it is ok to not have any exceptions, 477 // otherwise this method does not qualify... 478 479 validExceptions = method.getEnclosing().isType(TYPE_VALUE); 480 } 481 482 if (validExceptions) { 483 String name = method.getName(); 484 int nameLength = name.length(); 485 int argCount = method.getArguments().length; 486 Type returnType = method.getReturnType(); 487 boolean voidReturn = returnType.isType(TYPE_VOID); 488 boolean booleanReturn = returnType.isType(TYPE_BOOLEAN); 489 490 // It's a getter if name starts with "get" and it has no arguments 491 // and a return type that is not void... 492 493 if (name.startsWith("get") && nameLength > 3 && argCount == 0 && !voidReturn) { 494 result = ATTRIBUTE_GET; 495 } else { 496 497 // It's a getter if name starts with "is" and it has no arguments 498 // and a boolean return type... 499 500 if (name.startsWith("is") && nameLength > 2 && argCount == 0 && booleanReturn) { 501 result = ATTRIBUTE_IS; 502 } else { 503 504 // It's a setter if name starts with "set" and it has 1 argument 505 // and a void return type... 506 507 if (name.startsWith("set") && nameLength > 3 && argCount == 1 && voidReturn) { 508 result = ATTRIBUTE_SET; 509 } 510 } 511 } 512 } 513 } 514 515 return result; 516 } 517 setAttributeKinds(CompoundType.Method[] methods, int[] kinds, String[] names)518 private static void setAttributeKinds (CompoundType.Method[] methods, 519 int[] kinds, 520 String[] names) { 521 522 int count = methods.length; 523 524 // Strip the prefixes off of the attribute names... 525 526 for (int i = 0; i < count; i++) { 527 switch (kinds[i]) { 528 case ATTRIBUTE_GET: names[i] = names[i].substring(3); break; 529 case ATTRIBUTE_IS: names[i] = names[i].substring(2); break; 530 case ATTRIBUTE_SET: names[i] = names[i].substring(3); break; 531 } 532 } 533 534 // Now, we need to look at all the IS attributes to see 535 // if there is a corresponding getter or setter which has 536 // a different return type. If so, mark it as not an 537 // attribute. Do this before checking for invalid setters... 538 539 for (int i = 0; i < count; i++) { 540 if (kinds[i] == ATTRIBUTE_IS) { 541 for (int j = 0; j < count; j++) { 542 if (j != i && 543 (kinds[j] == ATTRIBUTE_GET || kinds[j] == ATTRIBUTE_SET) && 544 names[i].equals(names[j])) { 545 546 // We have matching getter or setter. Do the types match? 547 548 Type isType = methods[i].getReturnType(); 549 Type targetType; 550 551 if (kinds[j] == ATTRIBUTE_GET) { 552 targetType = methods[j].getReturnType(); 553 } else { 554 targetType = methods[j].getArguments()[0]; 555 } 556 557 if (!isType.equals(targetType)) { 558 559 // No, so forget this guy as an attribute... 560 561 kinds[i] = ATTRIBUTE_NONE; 562 names[i] = methods[i].getName(); 563 break; 564 } 565 } 566 } 567 } 568 } 569 570 // Now, we need to look at all the setters to see if there 571 // is a corresponding getter. If not, it is not a setter. 572 // If there is, change the getter type to _RW and set the 573 // pair index... 574 575 for (int i = 0; i < count; i++) { 576 if (kinds[i] == ATTRIBUTE_SET) { 577 int getterIndex = -1; 578 int isGetterIndex = -1; 579 // First look for is-getters, then for getters. 580 // This is preferred for boolean attributes. 581 for (int j = 0; j < count; j++) { 582 if (j != i && names[i].equals(names[j])) { 583 // Yep, is the return type of the getter the same 584 // as the argument type of the setter? 585 586 Type getterReturn = methods[j].getReturnType(); 587 Type setterArg = methods[i].getArguments()[0]; 588 589 if (getterReturn.equals(setterArg)) { 590 if (kinds[j] == ATTRIBUTE_IS) { 591 isGetterIndex = j; 592 // continue looking for another getter 593 } else if (kinds[j] == ATTRIBUTE_GET) { 594 getterIndex = j; 595 // continue looking for an is-getter 596 } 597 } 598 } 599 } 600 601 if (getterIndex > -1) { 602 if (isGetterIndex > -1) { 603 // We have both, a boolean is-getter and a boolean getter. 604 // Use the is-getter and drop the getter. 605 606 // We have a matching getter. Change it to a read-write type... 607 kinds[isGetterIndex] = ATTRIBUTE_IS_RW; 608 609 // Now set the pair index for both the getter and the setter... 610 methods[isGetterIndex].setAttributePairIndex(i); 611 methods[i].setAttributePairIndex(isGetterIndex); 612 613 // We found a better matching is-getter. 614 // Forget this other getter as an attribute. 615 kinds[getterIndex] = ATTRIBUTE_NONE; 616 names[getterIndex] = methods[getterIndex].getName(); 617 } else { 618 // We only have one getter. 619 620 // We have a matching getter. Change it to a read-write type... 621 kinds[getterIndex] = ATTRIBUTE_GET_RW; 622 623 // Now set the pair index for both the getter and the setter... 624 methods[getterIndex].setAttributePairIndex(i); 625 methods[i].setAttributePairIndex(getterIndex); 626 } 627 } else { 628 if (isGetterIndex > -1) { 629 // We only have one is-getter. 630 631 // We have a matching getter. Change it to a read-write type... 632 kinds[isGetterIndex] = ATTRIBUTE_IS_RW; 633 634 // Now set the pair index for both the getter and the setter... 635 methods[isGetterIndex].setAttributePairIndex(i); 636 methods[i].setAttributePairIndex(isGetterIndex); 637 } else { 638 // We did not find a matching getter. 639 // Forget this setter as an attribute. 640 kinds[i] = ATTRIBUTE_NONE; 641 names[i] = methods[i].getName(); 642 } 643 } 644 } 645 } 646 647 // Finally, do the case conversion and set the 648 // attribute kinds for each method... 649 650 for (int i = 0; i < count; i++) { 651 652 if (kinds[i] != ATTRIBUTE_NONE) { 653 654 String name = names[i]; 655 656 // Is the first character upper case? 657 658 if (Character.isUpperCase(name.charAt(0))) { 659 660 // Yes, is the second? 661 662 if (name.length() == 1 || Character.isLowerCase(name.charAt(1))) { 663 664 // No, so convert the first character to lower case... 665 666 StringBuffer buffer = new StringBuffer(name); 667 buffer.setCharAt(0,Character.toLowerCase(name.charAt(0))); 668 names[i] = buffer.toString(); 669 } 670 } 671 } 672 673 methods[i].setAttributeKind(kinds[i]); 674 } 675 } 676 677 /** 678 * Set all the method names in a given class. 679 * <p> 680 * Section 28.3.2.7 (see CompoundType) 681 * Section 28.3.2.7 682 * Section 28.3.4.3 (RemoteType/AbstractType only). 683 */ setMethodNames(CompoundType container, CompoundType.Method[] allMethods, BatchEnvironment env)684 public static void setMethodNames (CompoundType container, 685 CompoundType.Method[] allMethods, 686 BatchEnvironment env) 687 throws Exception { 688 689 // This method implements the following name mangling sequence: 690 // 691 // 1. If methods belong to a Remote interface, identify 692 // those which qualify as an attribute under 28.3.4.3. 693 // Those that do are referred to as 'attributes' below; 694 // those that do not are referred to as 'methods'. 695 // 696 // 2. Apply the 28.3.4.3 manglings, except "__", to all 697 // attribute names. 698 // 699 // 3. Apply all 28.3 manglings, except 28.3.2.7, to all names. 700 // 701 // 4. Apply 28.3.2.7 manglings to all method names. 702 // 703 // 5. Compare each attribute name to each method name. For 704 // any which compare equal, append "__" to the attribute 705 // name. 706 // 707 // 6. Compare each name (attribute and method) to all others. 708 // If any compare equal, throw an Exception with the 709 // conflicting name as the message. 710 711 int count = allMethods.length; 712 713 if (count == 0) return; 714 715 // Make an array of all the method names... 716 717 String[] names = new String[count]; 718 for (int i = 0; i < count; i++) { 719 names[i] = allMethods[i].getName(); 720 } 721 722 // Are we dealing with a RemoteType, AbstractType, or ValueType? 723 724 CompoundType enclosing = allMethods[0].getEnclosing(); 725 if (enclosing.isType(TYPE_REMOTE) || 726 enclosing.isType(TYPE_ABSTRACT) || 727 enclosing.isType(TYPE_VALUE)) { 728 729 // Yes, so we must do the 28.3.4.3 attribute mapping. First, get 730 // the initial attribute kind of each method... 731 732 int[] kinds = new int[count]; 733 734 for (int i = 0; i < count; i++) { 735 kinds[i] = getInitialAttributeKind(allMethods[i],env); 736 } 737 738 // Now set the attribute kind for each method and do the 739 // 28.3.4.3 name mangling... 740 741 setAttributeKinds(allMethods,kinds,names); 742 } 743 744 // Make and populate a new context from our names array... 745 746 NameContext context = new NameContext(true); 747 748 for (int i = 0; i < count; i++) { 749 context.put(names[i]); 750 } 751 752 // Apply the appropriate 28.3 manglings to all the names... 753 754 boolean haveConstructor = false; 755 for (int i = 0; i < count; i++) { 756 if (!allMethods[i].isConstructor()) { 757 names[i] = getMemberOrMethodName(context,names[i],env); 758 } else { 759 names[i] = IDL_CONSTRUCTOR; 760 haveConstructor = true; 761 } 762 } 763 764 // Now do the 28.3.2.7 mangling for method name collisions... 765 // Do this in two passes so that we don't change one during 766 // the detection of collisions and then miss a real one... 767 768 boolean overloaded[] = new boolean[count]; 769 for (int i = 0; i < count; i++) { 770 overloaded[i] = (!allMethods[i].isAttribute() && 771 !allMethods[i].isConstructor() && 772 doesMethodCollide(names[i],allMethods[i],allMethods,names,true)); 773 } 774 convertOverloadedMethods(allMethods,names,overloaded); 775 776 // Now do the same mangling for constructor name collisions... 777 778 for (int i = 0; i < count; i++) { 779 overloaded[i] = (!allMethods[i].isAttribute() && 780 allMethods[i].isConstructor() && 781 doesConstructorCollide(names[i],allMethods[i],allMethods,names,true)); 782 } 783 convertOverloadedMethods(allMethods,names,overloaded); 784 785 // Now do the 28.3.4.3 mangling for attribute name collisions... 786 787 for (int i = 0; i < count; i++) { 788 789 CompoundType.Method method = allMethods[i]; 790 791 // If this is an attribute name, does it collide with a method? 792 793 if (method.isAttribute() && 794 doesMethodCollide(names[i],method,allMethods,names,true)) { 795 796 // Yes, so add double underscore... 797 798 names[i] += "__"; 799 } 800 } 801 802 // Do the same mangling for any constructors which collide with 803 // methods... 804 805 if (haveConstructor) { 806 for (int i = 0; i < count; i++) { 807 CompoundType.Method method = allMethods[i]; 808 809 // Is this a constructor which collides with a method? 810 811 if (method.isConstructor() && 812 doesConstructorCollide(names[i],method,allMethods,names,false)) { 813 814 // Yes, so add double underscore... 815 816 names[i] += "__"; 817 } 818 } 819 } 820 821 // Now see if we have a collision with the container name (28.3.2.9). 822 823 String containerName = container.getIDLName(); 824 for (int i = 0; i < count; i++) { 825 if (names[i].equalsIgnoreCase(containerName)) { 826 // Do not add underscore to attributes. 827 // Otherwise getFoo will turn into _get_foo_. 828 if (! allMethods[i].isAttribute()) { 829 names[i] += "_"; 830 } 831 } 832 } 833 834 // Now see if we have any collisions (28.3.2.9). If we do, 835 // it's an error. Note: a get/set pair does not collide. 836 837 for (int i = 0; i < count; i++) { 838 839 // Does it collide with any other name? 840 841 if (doesMethodCollide(names[i],allMethods[i],allMethods,names,false)) { 842 843 // Yes, so bail... 844 845 throw new Exception(allMethods[i].toString()); 846 } 847 } 848 849 // Ok. We have unique names. Create the appropriate 'wire' name 850 // for each and set as the 'idl' name. If it is an attribute, also 851 // set the attribute name... 852 853 for (int i = 0; i < count; i++) { 854 855 CompoundType.Method method = allMethods[i]; 856 String wireName = names[i]; 857 858 if (method.isAttribute()) { 859 wireName = ATTRIBUTE_WIRE_PREFIX[method.getAttributeKind()] + 860 stripLeadingUnderscore(wireName); 861 String attributeName = names[i]; 862 method.setAttributeName(attributeName); 863 } 864 method.setIDLName(wireName); 865 } 866 } 867 stripLeadingUnderscore(String name)868 private static String stripLeadingUnderscore (String name) { 869 if (name != null && name.length() > 1 870 && name.charAt(0) == '_') 871 { 872 return name.substring(1); 873 } 874 return name; 875 } 876 877 stripTrailingUnderscore(String name)878 private static String stripTrailingUnderscore (String name) { 879 if (name != null && name.length() > 1 && 880 name.charAt(name.length() - 1) == '_') 881 { 882 return name.substring(0, name.length() - 1); 883 } 884 return name; 885 } 886 887 convertOverloadedMethods(CompoundType.Method[] allMethods, String[] names, boolean[] overloaded)888 private static void convertOverloadedMethods(CompoundType.Method[] allMethods, 889 String[] names, 890 boolean[] overloaded) { 891 892 for (int i = 0; i < names.length; i++) { 893 894 // Do we need to mangle it? 895 896 if (overloaded[i]) { 897 898 // Yes, so add arguments... 899 900 CompoundType.Method method = allMethods[i]; 901 Type[] args = method.getArguments(); 902 903 for (int k = 0; k < args.length; k++) { 904 905 // Add the separator... 906 907 names[i] += "__"; 908 909 // Get the fully qualified IDL name, without the "::" 910 // prefix... 911 912 String argIDLName = args[k].getQualifiedIDLName(false); 913 914 // Replace any occurances of "::_" with "_" to 915 // undo any IDL keyword mangling and do next step 916 // at the same time... 917 918 argIDLName = replace(argIDLName,"::_","_"); 919 920 // Replace any occurances of "::" with "_"... 921 922 argIDLName = replace(argIDLName,"::","_"); 923 924 // Replace any occurances of " " with "_"... 925 926 argIDLName = replace(argIDLName," ","_"); 927 928 // Add the argument type name... 929 930 names[i] += argIDLName; 931 } 932 933 if (args.length == 0) { 934 names[i] += "__"; 935 } 936 937 // Remove any IDL keyword mangling... 938 939 names[i] = stripLeadingUnderscore(names[i]); 940 } 941 } 942 } 943 doesMethodCollide(String name, CompoundType.Method method, CompoundType.Method[] allMethods, String[] allNames, boolean ignoreAttributes)944 private static boolean doesMethodCollide (String name, 945 CompoundType.Method method, 946 CompoundType.Method[] allMethods, 947 String[] allNames, 948 boolean ignoreAttributes) { 949 950 // Scan all methods looking for a match... 951 952 for (int i = 0; i < allMethods.length; i++) { 953 954 CompoundType.Method target = allMethods[i]; 955 956 if (method != target && // Not same instance 957 !target.isConstructor() && // Not a constructor 958 (!ignoreAttributes || !target.isAttribute()) && // Correct kind 959 name.equals(allNames[i])) { // Same names 960 961 // Are we looking at a get/set pair? 962 963 int kind1 = method.getAttributeKind(); 964 int kind2 = target.getAttributeKind(); 965 966 if ((kind1 != ATTRIBUTE_NONE && kind2 != ATTRIBUTE_NONE) && 967 ((kind1 == ATTRIBUTE_SET && kind2 != ATTRIBUTE_SET) || 968 (kind1 != ATTRIBUTE_SET && kind2 == ATTRIBUTE_SET) || 969 // one is a is-getter/setter pair and the other is just a getter 970 (kind1 == ATTRIBUTE_IS_RW && kind2 == ATTRIBUTE_GET) || 971 (kind1 == ATTRIBUTE_GET && kind2 == ATTRIBUTE_IS_RW))) { 972 973 // Yes, so ignore it... 974 975 } else { 976 977 // No, so we have a collision... 978 979 return true; 980 } 981 } 982 } 983 984 return false; 985 } 986 doesConstructorCollide(String name, CompoundType.Method method, CompoundType.Method[] allMethods, String[] allNames, boolean compareConstructors)987 private static boolean doesConstructorCollide (String name, 988 CompoundType.Method method, 989 CompoundType.Method[] allMethods, 990 String[] allNames, 991 boolean compareConstructors) { 992 993 // Scan all methods looking for a match... 994 995 for (int i = 0; i < allMethods.length; i++) { 996 997 CompoundType.Method target = allMethods[i]; 998 999 if (method != target && // Not same instance 1000 (target.isConstructor() == compareConstructors) && // Correct kind 1001 name.equals(allNames[i])) { // Same names 1002 1003 // We have a collision... 1004 1005 return true; 1006 } 1007 } 1008 1009 return false; 1010 } 1011 1012 1013 /** 1014 * Set all the member names in a given class. 1015 * <p> 1016 * Section 28.3.2.7 (see CompoundType) 1017 * Section 28.3.2.7 1018 */ setMemberNames(CompoundType container, CompoundType.Member[] allMembers, CompoundType.Method[] allMethods, BatchEnvironment env)1019 public static void setMemberNames (CompoundType container, 1020 CompoundType.Member[] allMembers, 1021 CompoundType.Method[] allMethods, 1022 BatchEnvironment env) 1023 throws Exception { 1024 1025 // Make and populate a new context... 1026 1027 NameContext context = new NameContext(true); 1028 1029 for (int i = 0; i < allMembers.length; i++) { 1030 context.put(allMembers[i].getName()); 1031 } 1032 1033 // Now set all the idl names... 1034 1035 for (int i = 0; i < allMembers.length; i++) { 1036 1037 CompoundType.Member member = allMembers[i]; 1038 String idlName = getMemberOrMethodName(context,member.getName(),env); 1039 member.setIDLName(idlName); 1040 } 1041 1042 // First see if we have a collision with the container name (28.3.2.9). 1043 1044 String containerName = container.getIDLName(); 1045 for (int i = 0; i < allMembers.length; i++) { 1046 String name = allMembers[i].getIDLName(); 1047 if (name.equalsIgnoreCase(containerName)) { 1048 // REVISIT - How is this different than line 788 1049 allMembers[i].setIDLName(name+"_"); 1050 } 1051 } 1052 1053 // Check for collisions between member names... 1054 1055 for (int i = 0; i < allMembers.length; i++) { 1056 String name = allMembers[i].getIDLName(); 1057 for (int j = 0; j < allMembers.length; j++) { 1058 if (i != j && allMembers[j].getIDLName().equals(name)) { 1059 1060 // Collision... 1061 1062 throw new Exception(name); 1063 } 1064 } 1065 } 1066 1067 // Now check for collisions between member names and 1068 // method names... 1069 1070 boolean changed; 1071 do { 1072 changed = false; 1073 for (int i = 0; i < allMembers.length; i++) { 1074 String name = allMembers[i].getIDLName(); 1075 for (int j = 0; j < allMethods.length; j++) { 1076 if (allMethods[j].getIDLName().equals(name)) { 1077 1078 // Collision, so append "_" to member name... 1079 1080 allMembers[i].setIDLName(name+"_"); 1081 changed = true; 1082 break; 1083 } 1084 } 1085 } 1086 } while (changed); 1087 } 1088 1089 /** 1090 * Get the name for the specified type code. 1091 * <p> 1092 * Section 28.3..3 (see PrimitiveType) 1093 * Section 28.3.5.10 (see SpecialClassType) 1094 * Section 28.3.4.1 (see SpecialInterfaceType) 1095 * Section 28.3.10.1 (see SpecialInterfaceType) 1096 * Section 28.3.10.2 (see SpecialClassType) 1097 */ getTypeName(int typeCode, boolean isConstant)1098 public static String getTypeName(int typeCode, boolean isConstant) { 1099 1100 String idlName = null; 1101 1102 switch (typeCode) { 1103 case TYPE_VOID: idlName = IDL_VOID; break; 1104 case TYPE_BOOLEAN: idlName = IDL_BOOLEAN; break; 1105 case TYPE_BYTE: idlName = IDL_BYTE; break; 1106 case TYPE_CHAR: idlName = IDL_CHAR; break; 1107 case TYPE_SHORT: idlName = IDL_SHORT; break; 1108 case TYPE_INT: idlName = IDL_INT; break; 1109 case TYPE_LONG: idlName = IDL_LONG; break; 1110 case TYPE_FLOAT: idlName = IDL_FLOAT; break; 1111 case TYPE_DOUBLE: idlName = IDL_DOUBLE; break; 1112 case TYPE_ANY: idlName = IDL_ANY; break; 1113 case TYPE_CORBA_OBJECT: idlName = IDL_CORBA_OBJECT; break; 1114 case TYPE_STRING: 1115 { 1116 if (isConstant) { 1117 idlName = IDL_CONSTANT_STRING; 1118 } else { 1119 idlName = IDL_STRING; 1120 } 1121 1122 break; 1123 } 1124 } 1125 1126 return idlName; 1127 } 1128 1129 /** 1130 * Create a qualified name. 1131 */ getQualifiedName(String[] idlModuleNames, String idlName)1132 public static String getQualifiedName (String[] idlModuleNames, String idlName) { 1133 String result = null; 1134 if (idlModuleNames != null && idlModuleNames.length > 0) { 1135 for (int i = 0; i < idlModuleNames.length;i++) { 1136 if (i == 0) { 1137 result = idlModuleNames[0]; 1138 } else { 1139 result += IDL_NAME_SEPARATOR; 1140 result += idlModuleNames[i]; 1141 } 1142 } 1143 result += IDL_NAME_SEPARATOR; 1144 result += idlName; 1145 } else { 1146 result = idlName; 1147 } 1148 return result; 1149 } 1150 1151 /** 1152 * Replace substrings 1153 * @param source The source string. 1154 * @param match The string to search for within the source string. 1155 * @param replace The replacement for any matching components. 1156 * @return 1157 */ replace(String source, String match, String replace)1158 public static String replace (String source, String match, String replace) { 1159 1160 int index = source.indexOf(match,0); 1161 1162 if (index >=0) { 1163 1164 // We have at least one match, so gotta do the 1165 // work... 1166 1167 StringBuffer result = new StringBuffer(source.length() + 16); 1168 int matchLength = match.length(); 1169 int startIndex = 0; 1170 1171 while (index >= 0) { 1172 result.append(source.substring(startIndex,index)); 1173 result.append(replace); 1174 startIndex = index + matchLength; 1175 index = source.indexOf(match,startIndex); 1176 } 1177 1178 // Grab the last piece, if any... 1179 1180 if (startIndex < source.length()) { 1181 result.append(source.substring(startIndex)); 1182 } 1183 1184 return result.toString(); 1185 1186 } else { 1187 1188 // No matches, just return the source... 1189 1190 return source; 1191 } 1192 } 1193 1194 /** 1195 * Get an IDL style repository id for 1196 */ getIDLRepositoryID(String idlName)1197 public static String getIDLRepositoryID (String idlName) { 1198 return IDL_REPOSITORY_ID_PREFIX + 1199 replace(idlName,"::", "/") + 1200 IDL_REPOSITORY_ID_VERSION; 1201 } 1202 1203 //_____________________________________________________________________ 1204 // Internal Interfaces 1205 //_____________________________________________________________________ 1206 1207 1208 /** 1209 * Convert a type or module name. 1210 * <p> 1211 * Section 28.3.2.2 1212 * Section 28.3.2.3 1213 */ getTypeOrModuleName(String name)1214 private static String getTypeOrModuleName (String name) { 1215 1216 // 28.3.2.3 Leading underscores... 1217 1218 String result = convertLeadingUnderscores(name); 1219 1220 // 28.3.2.2 IDL keywords (NOTE: must be done 1221 // after leading underscore conversion because 1222 // the mangling for IDL keywords creates a 1223 // leading underscore!)... 1224 1225 return convertIDLKeywords(result); 1226 } 1227 } 1228