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