|
1 /* |
|
2 * Copyright (c) 1998, 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 /* |
|
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.Arrays; |
|
36 import java.util.Vector; |
|
37 import sun.tools.java.Identifier; |
|
38 import sun.tools.java.ClassNotFound; |
|
39 import sun.tools.java.ClassDefinition; |
|
40 import sun.tools.java.ClassDeclaration; |
|
41 import sun.tools.java.MemberDefinition; |
|
42 import sun.tools.java.CompilerError; |
|
43 import sun.tools.tree.Node; |
|
44 import sun.tools.tree.LocalMember; |
|
45 import sun.tools.tree.CharExpression; |
|
46 import sun.tools.tree.IntegerExpression; |
|
47 import sun.rmi.rmic.IndentingWriter; |
|
48 import java.io.IOException; |
|
49 import java.util.HashSet; |
|
50 import java.util.Enumeration; |
|
51 import java.io.File; |
|
52 |
|
53 /** |
|
54 * A CompoundType is an abstract base class for all IIOP class and |
|
55 * interface types. |
|
56 * |
|
57 * @author Bryan Atsatt |
|
58 */ |
|
59 public abstract class CompoundType extends Type { |
|
60 |
|
61 protected Method[] methods; |
|
62 protected InterfaceType[] interfaces; |
|
63 protected Member[] members; |
|
64 protected ClassDefinition classDef; |
|
65 protected ClassDeclaration classDecl; |
|
66 |
|
67 protected boolean isCORBAObject = false; |
|
68 protected boolean isIDLEntity = false; |
|
69 protected boolean isAbstractBase = false; |
|
70 protected boolean isValueBase = false; |
|
71 protected boolean isCORBAUserException = false; |
|
72 protected boolean isException = false; |
|
73 protected boolean isCheckedException = false; |
|
74 protected boolean isRemoteExceptionOrSubclass = false; |
|
75 protected String idlExceptionName; |
|
76 protected String qualifiedIDLExceptionName; |
|
77 |
|
78 //_____________________________________________________________________ |
|
79 // Public Interfaces |
|
80 //_____________________________________________________________________ |
|
81 |
|
82 /** |
|
83 * Return true if this type implements |
|
84 * org.omg.CORBA.Object. |
|
85 */ |
|
86 public boolean isCORBAObject () { |
|
87 return isCORBAObject; |
|
88 } |
|
89 |
|
90 /** |
|
91 * Return true if this type implements |
|
92 * org.omg.CORBA.portable.IDLEntity. |
|
93 */ |
|
94 public boolean isIDLEntity () { |
|
95 return isIDLEntity; |
|
96 } |
|
97 |
|
98 /** |
|
99 * Return true if this type implements |
|
100 * org.omg.CORBA.portable.ValueBase. |
|
101 */ |
|
102 public boolean isValueBase () { |
|
103 return isValueBase; |
|
104 } |
|
105 |
|
106 /** |
|
107 * Return true if this type is a CORBA |
|
108 * abstract interface. |
|
109 */ |
|
110 public boolean isAbstractBase () { |
|
111 return isAbstractBase; |
|
112 } |
|
113 |
|
114 /** |
|
115 * Return true if this type is an exception. |
|
116 */ |
|
117 public boolean isException () { |
|
118 return isException; |
|
119 } |
|
120 |
|
121 /** |
|
122 * Return true if this type is a "checked" exception. |
|
123 * Result if valid iff isException() returns true. |
|
124 */ |
|
125 public boolean isCheckedException () { |
|
126 return isCheckedException; |
|
127 } |
|
128 |
|
129 /** |
|
130 * Return true if this type is a java.rmi.RemoteException |
|
131 * or one of its subclasses. Result if valid iff isException() |
|
132 * returns true. |
|
133 */ |
|
134 public boolean isRemoteExceptionOrSubclass () { |
|
135 return isRemoteExceptionOrSubclass; |
|
136 } |
|
137 |
|
138 /** |
|
139 * Return true if this type is exactly |
|
140 * org.omg.CORBA.UserException. |
|
141 */ |
|
142 public boolean isCORBAUserException () { |
|
143 return isCORBAUserException; |
|
144 } |
|
145 |
|
146 /** |
|
147 * Return true if this type implements |
|
148 * isIDLEntity() && isException(). |
|
149 */ |
|
150 public boolean isIDLEntityException () { |
|
151 return isIDLEntity() && isException(); |
|
152 } |
|
153 /** |
|
154 * Return true if isIDLEntity() && !isValueBase() |
|
155 * && !isAbstractBase() && !isCORBAObject() |
|
156 * && !isIDLEntityException(). |
|
157 */ |
|
158 public boolean isBoxed () { |
|
159 return (isIDLEntity() && !isValueBase() && |
|
160 !isAbstractBase() && !isCORBAObject() && |
|
161 !isIDLEntityException()); |
|
162 } |
|
163 |
|
164 /** |
|
165 * If this type represents an exception, return the |
|
166 * IDL name including the "Ex" mangling, otherwise |
|
167 * return null. |
|
168 */ |
|
169 public String getIDLExceptionName () { |
|
170 return idlExceptionName; |
|
171 } |
|
172 |
|
173 /** |
|
174 * If this type represents an exception, return the |
|
175 * qualified IDL name including the "Ex" mangling, |
|
176 * otherwise return null. |
|
177 * @param global If true, prepends "::". |
|
178 */ |
|
179 public String getQualifiedIDLExceptionName (boolean global) { |
|
180 if (qualifiedIDLExceptionName != null && |
|
181 global && |
|
182 getIDLModuleNames().length > 0) { |
|
183 return IDL_NAME_SEPARATOR + qualifiedIDLExceptionName; |
|
184 } else { |
|
185 return qualifiedIDLExceptionName; |
|
186 } |
|
187 } |
|
188 |
|
189 /** |
|
190 * Return signature for this type (e.g. com.acme.Dynamite |
|
191 * would return "com.acme.Dynamite", byte = "B") |
|
192 */ |
|
193 public String getSignature() { |
|
194 String sig = classDecl.getType().getTypeSignature(); |
|
195 if (sig.endsWith(";")) { |
|
196 sig = sig.substring(0,sig.length()-1); |
|
197 } |
|
198 return sig; |
|
199 } |
|
200 |
|
201 /** |
|
202 * Return the ClassDeclaration for this type. |
|
203 */ |
|
204 public ClassDeclaration getClassDeclaration() { |
|
205 return classDecl; |
|
206 } |
|
207 |
|
208 /** |
|
209 * Return the ClassDefinition for this type. |
|
210 */ |
|
211 public ClassDefinition getClassDefinition() { |
|
212 return classDef; |
|
213 } |
|
214 |
|
215 /** |
|
216 * Return the parent class of this type. Returns null if this |
|
217 * type is an interface or if there is no parent. |
|
218 */ |
|
219 public ClassType getSuperclass() { |
|
220 return null; |
|
221 } |
|
222 |
|
223 /** |
|
224 * Return an array of interfaces directly implemented by this type. |
|
225 * <p> |
|
226 * The order of the array returned is arbitrary. |
|
227 */ |
|
228 public InterfaceType[] getInterfaces() { |
|
229 if( interfaces != null ) { |
|
230 return (InterfaceType[]) interfaces.clone(); |
|
231 } |
|
232 return null; |
|
233 } |
|
234 |
|
235 /** |
|
236 * Return an array of Type.Method objects representing all |
|
237 * of the methods implemented directly by this type. |
|
238 */ |
|
239 public Method[] getMethods() { |
|
240 if( methods != null ) { |
|
241 return (Method[]) methods.clone(); |
|
242 } |
|
243 return null; |
|
244 } |
|
245 |
|
246 /** |
|
247 * Return an array of Type.Member objects representing all of |
|
248 * the data members directly implemented by this interface. |
|
249 */ |
|
250 public Member[] getMembers() { |
|
251 if( members != null ) { |
|
252 return (Member[]) members.clone(); |
|
253 } |
|
254 return null; |
|
255 } |
|
256 |
|
257 /** |
|
258 * Create a CompoundType object for the given class. |
|
259 * |
|
260 * If the class is not a properly formed or if some other error occurs, the |
|
261 * return value will be null, and errors will have been reported to the |
|
262 * supplied BatchEnvironment. |
|
263 */ |
|
264 public static CompoundType forCompound (ClassDefinition classDef, |
|
265 ContextStack stack) { |
|
266 CompoundType result = null; |
|
267 |
|
268 try { |
|
269 result = (CompoundType) makeType(classDef.getType(),classDef,stack); |
|
270 } catch (ClassCastException e) {} |
|
271 |
|
272 return result; |
|
273 } |
|
274 |
|
275 |
|
276 //_____________________________________________________________________ |
|
277 // Subclass/Internal Interfaces |
|
278 //_____________________________________________________________________ |
|
279 |
|
280 /** |
|
281 * Release all resources. |
|
282 */ |
|
283 protected void destroy () { |
|
284 if (!destroyed) { |
|
285 super.destroy(); |
|
286 |
|
287 if (methods != null) { |
|
288 for (int i = 0; i < methods.length; i++) { |
|
289 if (methods[i] != null) methods[i].destroy(); |
|
290 } |
|
291 methods = null; |
|
292 } |
|
293 |
|
294 if (interfaces != null) { |
|
295 for (int i = 0; i < interfaces.length; i++) { |
|
296 if (interfaces[i] != null) interfaces[i].destroy(); |
|
297 } |
|
298 interfaces = null; |
|
299 } |
|
300 |
|
301 if (members != null) { |
|
302 for (int i = 0; i < members.length; i++) { |
|
303 if (members[i] != null) members[i].destroy(); |
|
304 } |
|
305 members = null; |
|
306 } |
|
307 |
|
308 classDef = null; |
|
309 classDecl = null; |
|
310 } |
|
311 } |
|
312 |
|
313 /* |
|
314 * Load a Class instance. Return null if fail. |
|
315 */ |
|
316 protected Class loadClass() { |
|
317 |
|
318 Class ourClass = null; |
|
319 |
|
320 // To avoid getting out-of-date Class instances, and |
|
321 // to ensure that there is an instance, we must compile |
|
322 // any classes that we've seen and which are not yet |
|
323 // compiled. We can't just compile this class, 'cuz it |
|
324 // may have dependencies on classes which have not been |
|
325 // compiled... |
|
326 |
|
327 try { |
|
328 env.getMain().compileAllClasses(env); |
|
329 } catch (Exception e1) { |
|
330 for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) { |
|
331 ClassDeclaration c = (ClassDeclaration)e.nextElement(); |
|
332 } |
|
333 failedConstraint(26,false,stack,"required classes"); |
|
334 env.flushErrors(); |
|
335 } |
|
336 |
|
337 // Now try to get the Class... |
|
338 // The outer try block is there for people who might want to use |
|
339 // the compiler at run-time of their AS. |
|
340 // They could set and use their own context class loader for loading |
|
341 // classes directly. |
|
342 try { |
|
343 ClassLoader cl = Thread.currentThread().getContextClassLoader(); |
|
344 ourClass = cl.loadClass(getQualifiedName()); |
|
345 } catch(ClassNotFoundException cfe) { |
|
346 |
|
347 try { |
|
348 ourClass = env.classPathLoader.loadClass(getQualifiedName()); |
|
349 } catch (NullPointerException e) { |
|
350 // This should never happen |
|
351 } catch (ClassNotFoundException e) { |
|
352 // Fall through to the next case (which is to look in the |
|
353 // output directory for generated files) |
|
354 } |
|
355 } |
|
356 |
|
357 /* This piece of code used to cause the compiler to ignore jar files |
|
358 on its classpath |
|
359 try { |
|
360 ourClass = Util.loadClass(getQualifiedName(),null,null); |
|
361 } catch (ClassNotFoundException e) { |
|
362 } catch (LinkageError e) { |
|
363 } |
|
364 */ |
|
365 |
|
366 if (ourClass == null) { |
|
367 |
|
368 // Try one last thing. If the class was compiled into |
|
369 // a directory that's not in the classpath, the load |
|
370 // will fail. Let's get the bits off the disk and load |
|
371 // it directly... |
|
372 |
|
373 if (env.loader == null) { |
|
374 File destDir = env.getMain().getDestinationDir(); |
|
375 if (destDir == null) { |
|
376 destDir = new File("."); |
|
377 } |
|
378 env.loader = new DirectoryLoader(destDir); |
|
379 } |
|
380 |
|
381 try { |
|
382 ourClass = env.loader.loadClass(getQualifiedName()); |
|
383 } catch (Exception e) {} |
|
384 } |
|
385 |
|
386 return ourClass; |
|
387 } |
|
388 |
|
389 // Print "extends XX" |
|
390 |
|
391 protected boolean printExtends (IndentingWriter writer, |
|
392 boolean useQualifiedNames, |
|
393 boolean useIDLNames, |
|
394 boolean globalIDLNames) throws IOException { |
|
395 |
|
396 ClassType parent = getSuperclass(); |
|
397 |
|
398 if (parent != null && (!useIDLNames || |
|
399 (!parent.isType(TYPE_ANY) && !parent.isType(TYPE_CORBA_OBJECT)))) { |
|
400 writer.p(" extends "); |
|
401 parent.printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); |
|
402 return true; |
|
403 } |
|
404 return false; |
|
405 } |
|
406 |
|
407 // Print "implements XX, YY" |
|
408 |
|
409 protected void printImplements (IndentingWriter writer, |
|
410 String prefix, |
|
411 boolean useQualifiedNames, |
|
412 boolean useIDLNames, |
|
413 boolean globalIDLNames) throws IOException { |
|
414 |
|
415 InterfaceType[] interfaces = getInterfaces(); |
|
416 |
|
417 String adjective = " implements"; |
|
418 |
|
419 if (isInterface()) { |
|
420 adjective = " extends"; |
|
421 } |
|
422 |
|
423 if (useIDLNames) { |
|
424 adjective = ":"; |
|
425 } |
|
426 |
|
427 for (int i = 0; i < interfaces.length; i++) { |
|
428 if (!useIDLNames || (!interfaces[i].isType(TYPE_ANY) && !interfaces[i].isType(TYPE_CORBA_OBJECT))) { |
|
429 if (i == 0) { |
|
430 writer.p(prefix + adjective + " "); |
|
431 } else { |
|
432 writer.p(", "); |
|
433 } |
|
434 interfaces[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); |
|
435 } |
|
436 } |
|
437 } |
|
438 |
|
439 // Print members |
|
440 |
|
441 protected void printMembers ( IndentingWriter writer, |
|
442 boolean useQualifiedNames, |
|
443 boolean useIDLNames, |
|
444 boolean globalIDLNames) throws IOException { |
|
445 |
|
446 CompoundType.Member[] members = getMembers(); |
|
447 |
|
448 for (int i = 0; i < members.length; i++) { |
|
449 if (!members[i].isInnerClassDeclaration()) { |
|
450 Type it = members[i].getType(); |
|
451 String visibility = members[i].getVisibility(); |
|
452 String name; |
|
453 |
|
454 if (useIDLNames) { |
|
455 name = members[i].getIDLName(); |
|
456 } else { |
|
457 name = members[i].getName(); |
|
458 } |
|
459 |
|
460 String value = members[i].getValue(); |
|
461 |
|
462 writer.p(visibility); |
|
463 if (visibility.length() > 0) { |
|
464 writer.p(" "); |
|
465 } |
|
466 it.printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); |
|
467 writer.p(" " + name); |
|
468 |
|
469 if (value != null) { |
|
470 writer.pln(" = " + value + ";"); |
|
471 } else { |
|
472 writer.pln(";"); |
|
473 } |
|
474 } |
|
475 } |
|
476 } |
|
477 |
|
478 // Print methods |
|
479 |
|
480 protected void printMethods ( IndentingWriter writer, |
|
481 boolean useQualifiedNames, |
|
482 boolean useIDLNames, |
|
483 boolean globalIDLNames) throws IOException { |
|
484 |
|
485 CompoundType.Method[] methods = getMethods(); |
|
486 |
|
487 for (int m = 0; m < methods.length; m++) { |
|
488 CompoundType.Method theMethod = methods[m]; |
|
489 printMethod(theMethod,writer,useQualifiedNames,useIDLNames,globalIDLNames); |
|
490 } |
|
491 } |
|
492 |
|
493 // Print a method... |
|
494 |
|
495 protected void printMethod (CompoundType.Method it, |
|
496 IndentingWriter writer, |
|
497 boolean useQualifiedNames, |
|
498 boolean useIDLNames, |
|
499 boolean globalIDLNames) throws IOException { |
|
500 |
|
501 |
|
502 // Write visibility... |
|
503 |
|
504 String visibility = it.getVisibility(); |
|
505 |
|
506 writer.p(visibility); |
|
507 if (visibility.length() > 0) { |
|
508 writer.p(" "); |
|
509 } |
|
510 |
|
511 // Write return type... |
|
512 |
|
513 it.getReturnType().printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); |
|
514 |
|
515 // Write method name... |
|
516 |
|
517 if (useIDLNames) { |
|
518 writer.p(" " + it.getIDLName()); |
|
519 } else { |
|
520 writer.p(" " + it.getName()); |
|
521 } |
|
522 |
|
523 // Write arguments... |
|
524 |
|
525 writer.p(" ("); |
|
526 Type[] args = it.getArguments(); |
|
527 String[] argNames = it.getArgumentNames(); |
|
528 |
|
529 for (int i = 0; i < args.length; i++) { |
|
530 if (i > 0) { |
|
531 writer.p(", "); |
|
532 } |
|
533 |
|
534 if (useIDLNames) { |
|
535 writer.p("in "); |
|
536 } |
|
537 |
|
538 args[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); |
|
539 writer.p(" " + argNames[i]); |
|
540 } |
|
541 writer.p(")"); |
|
542 |
|
543 // Write exceptions... |
|
544 |
|
545 ClassType[] exceptions; |
|
546 |
|
547 if (isType(TYPE_IMPLEMENTATION)) { |
|
548 exceptions = it.getImplExceptions(); |
|
549 } else { |
|
550 exceptions = it.getExceptions(); |
|
551 } |
|
552 |
|
553 for (int i = 0; i < exceptions.length; i++) { |
|
554 if (i == 0) { |
|
555 if (useIDLNames) { |
|
556 writer.p(" raises ("); |
|
557 } else { |
|
558 writer.p(" throws "); |
|
559 } |
|
560 } else { |
|
561 writer.p(", "); |
|
562 } |
|
563 |
|
564 if (useIDLNames) { |
|
565 if (useQualifiedNames) { |
|
566 writer.p(exceptions[i].getQualifiedIDLExceptionName(globalIDLNames)); |
|
567 } else { |
|
568 writer.p(exceptions[i].getIDLExceptionName()); |
|
569 } |
|
570 writer.p(" [a.k.a. "); |
|
571 exceptions[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); |
|
572 writer.p("]"); |
|
573 } else { |
|
574 exceptions[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); |
|
575 } |
|
576 } |
|
577 |
|
578 if (useIDLNames && exceptions.length > 0) { |
|
579 writer.p(")"); |
|
580 } |
|
581 |
|
582 if (it.isInherited()) { |
|
583 writer.p(" // Inherited from "); |
|
584 writer.p(it.getDeclaredBy()); |
|
585 } |
|
586 |
|
587 writer.pln(";"); |
|
588 } |
|
589 |
|
590 /** |
|
591 * Create a CompoundType instance for the given class. NOTE: This constructor |
|
592 * is ONLY for SpecialClassType and SpecialInterfaceType. |
|
593 */ |
|
594 protected CompoundType(ContextStack stack, int typeCode, ClassDefinition classDef) { |
|
595 super(stack,typeCode); |
|
596 this.classDef = classDef; |
|
597 classDecl = classDef.getClassDeclaration(); |
|
598 interfaces = new InterfaceType[0]; |
|
599 methods = new Method[0]; |
|
600 members = new Member[0]; |
|
601 |
|
602 // If we are an inner class/interface, reset the type codes... |
|
603 |
|
604 if (classDef.isInnerClass()) { |
|
605 setTypeCode(typeCode | TM_INNER); |
|
606 } |
|
607 |
|
608 // Set special flags... |
|
609 |
|
610 setFlags(); |
|
611 } |
|
612 |
|
613 private void setFlags() { |
|
614 |
|
615 try { |
|
616 |
|
617 // Set our special interface flags... |
|
618 |
|
619 isCORBAObject = env.defCorbaObject.implementedBy(env,classDecl); |
|
620 isIDLEntity = env.defIDLEntity.implementedBy(env,classDecl); |
|
621 isValueBase = env.defValueBase.implementedBy(env,classDecl); |
|
622 isAbstractBase = isInterface() && // Interface, not a class. |
|
623 isIDLEntity && // Implements IDLEntity. |
|
624 !isValueBase && // Does not implement ValueBase. |
|
625 !isCORBAObject; // Does not implement org.omg.CORBA.Object; |
|
626 isCORBAUserException = (classDecl.getName() == idCorbaUserException); |
|
627 |
|
628 // Is this an exception? |
|
629 |
|
630 if (env.defThrowable.implementedBy(env, classDecl)) { |
|
631 |
|
632 // Yes... |
|
633 |
|
634 isException = true; |
|
635 |
|
636 // Is it a checked exception? |
|
637 |
|
638 if (env.defRuntimeException.implementedBy(env,classDecl) || |
|
639 env.defError.implementedBy(env,classDecl)) { |
|
640 isCheckedException = false; |
|
641 } else { |
|
642 isCheckedException = true; |
|
643 } |
|
644 |
|
645 // Is it java.rmi.RemoteException or a subclass? |
|
646 |
|
647 if (env.defRemoteException.implementedBy(env,classDecl)) { |
|
648 isRemoteExceptionOrSubclass = true; |
|
649 } else { |
|
650 isRemoteExceptionOrSubclass = false; |
|
651 } |
|
652 } else { |
|
653 isException = false; |
|
654 } |
|
655 } catch (ClassNotFound e) { |
|
656 classNotFound(stack,e); |
|
657 } |
|
658 } |
|
659 |
|
660 /** |
|
661 * Create a CompoundType instance for the given class. The resulting |
|
662 * object is not yet completely initialized. |
|
663 */ |
|
664 protected CompoundType(ContextStack stack, ClassDefinition classDef, |
|
665 int typeCode) { |
|
666 super(stack,typeCode); |
|
667 this.classDef = classDef; |
|
668 classDecl = classDef.getClassDeclaration(); |
|
669 |
|
670 // If we are an inner class/interface, reset the type codes... |
|
671 |
|
672 if (classDef.isInnerClass()) { |
|
673 setTypeCode(typeCode | TM_INNER); |
|
674 } |
|
675 |
|
676 // Set special flags... |
|
677 |
|
678 setFlags(); |
|
679 |
|
680 // Set names... |
|
681 |
|
682 Identifier id = classDef.getName(); |
|
683 String idlName; |
|
684 String[] idlModuleNames; |
|
685 |
|
686 try { |
|
687 |
|
688 // These can fail if we get case-sensitive name matches... |
|
689 |
|
690 idlName = IDLNames.getClassOrInterfaceName(id,env); |
|
691 idlModuleNames = IDLNames.getModuleNames(id,isBoxed(),env); |
|
692 |
|
693 setNames(id,idlModuleNames,idlName); |
|
694 |
|
695 // Is this an exception? |
|
696 |
|
697 if (isException()) { |
|
698 |
|
699 // Yes, so set our mangled exception names... |
|
700 |
|
701 isException = true; |
|
702 idlExceptionName = IDLNames.getExceptionName(getIDLName()); |
|
703 qualifiedIDLExceptionName = |
|
704 IDLNames.getQualifiedName(getIDLModuleNames(),idlExceptionName); |
|
705 } |
|
706 |
|
707 // Set interfaces, methods and members... |
|
708 |
|
709 interfaces = null; // set in initialize() |
|
710 methods = null; // set in initialize() |
|
711 members = null; // set in initialize() |
|
712 |
|
713 } catch (Exception e) { |
|
714 failedConstraint(7,false,stack,id.toString(),e.getMessage()); |
|
715 throw new CompilerError(""); |
|
716 } |
|
717 } |
|
718 |
|
719 /** |
|
720 * Initialize this instance. |
|
721 */ |
|
722 protected boolean initialize ( Vector directInterfaces, |
|
723 Vector directMethods, |
|
724 Vector directMembers, |
|
725 ContextStack stack, |
|
726 boolean quiet) { |
|
727 |
|
728 boolean result = true; |
|
729 |
|
730 // Initialize our arrays... |
|
731 |
|
732 if (directInterfaces != null && directInterfaces.size() > 0) { |
|
733 interfaces = new InterfaceType[directInterfaces.size()]; |
|
734 directInterfaces.copyInto(interfaces); |
|
735 } else { |
|
736 interfaces = new InterfaceType[0]; |
|
737 } |
|
738 |
|
739 if (directMethods != null && directMethods.size() > 0) { |
|
740 methods = new Method[directMethods.size()]; |
|
741 directMethods.copyInto(methods); |
|
742 |
|
743 // Now set the idl names for each... |
|
744 |
|
745 try { |
|
746 IDLNames.setMethodNames(this, methods,env); |
|
747 } catch (Exception e) { |
|
748 failedConstraint(13,quiet,stack,getQualifiedName(),e.getMessage()); |
|
749 result = false; |
|
750 } |
|
751 |
|
752 } else { |
|
753 methods = new Method[0]; |
|
754 } |
|
755 |
|
756 if (directMembers != null && directMembers.size() > 0) { |
|
757 members = new Member[directMembers.size()]; |
|
758 directMembers.copyInto(members); |
|
759 |
|
760 // If we have any un-initialized inner classes, now is the time |
|
761 // to init them... |
|
762 |
|
763 for (int i = 0; i < members.length; i++) { |
|
764 if (members[i].isInnerClassDeclaration()) { |
|
765 try { |
|
766 members[i].init(stack,this); |
|
767 } catch (CompilerError e) { |
|
768 return false; |
|
769 } |
|
770 } |
|
771 } |
|
772 |
|
773 // Now set the idl names for each... |
|
774 |
|
775 try { |
|
776 IDLNames.setMemberNames(this, members,methods,env); |
|
777 } catch (Exception e) { |
|
778 int constraint = classDef.isInterface() ? 19 : 20; |
|
779 failedConstraint(constraint,quiet,stack,getQualifiedName(),e.getMessage()); |
|
780 result = false; |
|
781 } |
|
782 |
|
783 } else { |
|
784 members = new Member[0]; |
|
785 } |
|
786 |
|
787 // Set our repositoryID... |
|
788 |
|
789 if (result) { |
|
790 result = setRepositoryID(); |
|
791 } |
|
792 |
|
793 return result; |
|
794 } |
|
795 |
|
796 /* |
|
797 * Return Type or null if error. classDef may be null. |
|
798 */ |
|
799 protected static Type makeType (sun.tools.java.Type theType, |
|
800 ClassDefinition classDef, |
|
801 ContextStack stack) { |
|
802 |
|
803 if (stack.anyErrors()) return null; |
|
804 |
|
805 // See if we can find this type in the cache. If so, return it... |
|
806 |
|
807 String key = theType.toString(); |
|
808 |
|
809 Type result = getType(key,stack); |
|
810 |
|
811 if (result != null) { |
|
812 return result; |
|
813 } |
|
814 |
|
815 // Gotta try with context... |
|
816 |
|
817 result = getType(key + stack.getContextCodeString(),stack); |
|
818 |
|
819 if (result != null) { |
|
820 return result; |
|
821 } |
|
822 |
|
823 // Gotta map it... |
|
824 |
|
825 BatchEnvironment env = stack.getEnv(); |
|
826 int typeCode = theType.getTypeCode(); |
|
827 switch (typeCode) { |
|
828 case TC_BOOLEAN: |
|
829 case TC_BYTE: |
|
830 case TC_CHAR: |
|
831 case TC_SHORT: |
|
832 case TC_INT: |
|
833 case TC_LONG: |
|
834 case TC_FLOAT: |
|
835 case TC_DOUBLE: |
|
836 { |
|
837 // Primitive... |
|
838 |
|
839 result = PrimitiveType.forPrimitive(theType,stack); |
|
840 break; |
|
841 } |
|
842 |
|
843 case TC_ARRAY: |
|
844 { |
|
845 // Array. |
|
846 |
|
847 result = ArrayType.forArray(theType,stack); |
|
848 break; |
|
849 } |
|
850 |
|
851 case TC_CLASS: |
|
852 { |
|
853 try { |
|
854 // First, make sure we have the class definition... |
|
855 |
|
856 ClassDefinition theClass = classDef; |
|
857 |
|
858 if (theClass == null) { |
|
859 theClass = env.getClassDeclaration(theType).getClassDefinition(env); |
|
860 } |
|
861 |
|
862 // Is it an interface or a class? |
|
863 |
|
864 if (theClass.isInterface()) { |
|
865 |
|
866 // An interface. Is it a special case? |
|
867 |
|
868 result = SpecialInterfaceType.forSpecial(theClass,stack); |
|
869 |
|
870 if (result == null) { |
|
871 |
|
872 // No, does it implement java.rmi.Remote? |
|
873 |
|
874 if (env.defRemote.implementedBy(env,theClass.getClassDeclaration())) { |
|
875 |
|
876 // Yep, so just see if we can create an instance of RemoteType |
|
877 // from it... |
|
878 |
|
879 boolean parentIsValue = stack.isParentAValue(); |
|
880 result = RemoteType.forRemote(theClass,stack,parentIsValue); |
|
881 |
|
882 // If we did not succeed AND we are in a value context, then |
|
883 // go ahead and make an NC type out of it... |
|
884 |
|
885 if (result == null && parentIsValue) { |
|
886 result = NCInterfaceType.forNCInterface(theClass,stack); |
|
887 } |
|
888 } else { |
|
889 |
|
890 // Nope, is it an AbstractType? |
|
891 |
|
892 result = AbstractType.forAbstract(theClass,stack,true); |
|
893 |
|
894 if (result == null) { |
|
895 |
|
896 // No, so treat it as a non-conforming interface type... |
|
897 |
|
898 result = NCInterfaceType.forNCInterface(theClass,stack); |
|
899 } |
|
900 } |
|
901 } |
|
902 } else { |
|
903 |
|
904 // A class. Is it a special case? |
|
905 |
|
906 result = SpecialClassType.forSpecial(theClass,stack); |
|
907 |
|
908 if (result == null) { |
|
909 |
|
910 ClassDeclaration classDecl = theClass.getClassDeclaration(); |
|
911 |
|
912 // Nope, does it implement java.rmi.Remote? |
|
913 |
|
914 if (env.defRemote.implementedBy(env,classDecl)) { |
|
915 |
|
916 // Yep, so just see if we can create an instance of |
|
917 // ImplementationType from it... |
|
918 |
|
919 boolean parentIsValue = stack.isParentAValue(); |
|
920 result = ImplementationType.forImplementation(theClass,stack,parentIsValue); |
|
921 |
|
922 // If we did not succeed AND inValue is true, then |
|
923 // go ahead and make an NC type out of it... |
|
924 |
|
925 if (result == null && parentIsValue) { |
|
926 result = NCClassType.forNCClass(theClass,stack); |
|
927 } |
|
928 } else { |
|
929 |
|
930 // No, does it implement Serializable? |
|
931 |
|
932 if (env.defSerializable.implementedBy(env,classDecl)) { |
|
933 |
|
934 // Yep, so just see if we can create an instance of ValueType |
|
935 // from it... |
|
936 |
|
937 result = ValueType.forValue(theClass,stack,true); |
|
938 } |
|
939 |
|
940 if (result == null) { |
|
941 |
|
942 // Treat it as a non-conforming class type... |
|
943 |
|
944 result = NCClassType.forNCClass(theClass,stack); |
|
945 } |
|
946 } |
|
947 } |
|
948 } |
|
949 } catch (ClassNotFound e) { |
|
950 classNotFound(stack,e); |
|
951 } |
|
952 break; |
|
953 } |
|
954 |
|
955 default: throw new CompilerError("Unknown typecode (" + typeCode + ") for " + theType.getTypeSignature()); |
|
956 } |
|
957 |
|
958 return result; |
|
959 } |
|
960 |
|
961 /* |
|
962 * Check if exception is RemoteException or one of its parents. |
|
963 */ |
|
964 public static boolean isRemoteException (ClassType ex, |
|
965 BatchEnvironment env) { |
|
966 sun.tools.java.Type exceptionType = ex.getClassDeclaration().getType(); |
|
967 |
|
968 if (exceptionType.equals(env.typeRemoteException) || |
|
969 exceptionType.equals(env.typeIOException) || |
|
970 exceptionType.equals(env.typeException) || |
|
971 exceptionType.equals(env.typeThrowable)) { |
|
972 |
|
973 return true; |
|
974 } |
|
975 return false; |
|
976 } |
|
977 |
|
978 /* |
|
979 * Check if method is conforming. |
|
980 */ |
|
981 protected boolean isConformingRemoteMethod (Method method, boolean quiet) |
|
982 throws ClassNotFound { |
|
983 |
|
984 // Do we have one exception that is RemoteException or |
|
985 // a superclass of RemoteException? |
|
986 |
|
987 boolean haveRemote = false; |
|
988 ClassType[] exceptions = method.getExceptions(); |
|
989 |
|
990 for (int i = 0; i < exceptions.length; i++) { |
|
991 |
|
992 // Is it a conforming exception? |
|
993 |
|
994 if (isRemoteException(exceptions[i],env)) { |
|
995 |
|
996 // Got it. |
|
997 |
|
998 haveRemote = true; |
|
999 break; |
|
1000 } |
|
1001 } |
|
1002 |
|
1003 // Do we have our exception? |
|
1004 |
|
1005 if (!haveRemote) { |
|
1006 |
|
1007 // No, so report failure... |
|
1008 |
|
1009 failedConstraint(5,quiet,stack,method.getEnclosing(), method.toString()); |
|
1010 } |
|
1011 |
|
1012 // Are any of the arguments exceptions which implement IDLEntity? |
|
1013 // If so, report failure... |
|
1014 |
|
1015 boolean noIDLEntity = !isIDLEntityException(method.getReturnType(),method,quiet); |
|
1016 if (noIDLEntity) { |
|
1017 Type[] args = method.getArguments(); |
|
1018 for (int i = 0; i < args.length; i++) { |
|
1019 if (isIDLEntityException(args[i],method,quiet)) { |
|
1020 noIDLEntity = false; |
|
1021 break; |
|
1022 } |
|
1023 } |
|
1024 } |
|
1025 |
|
1026 return (haveRemote && noIDLEntity); |
|
1027 } |
|
1028 |
|
1029 protected boolean isIDLEntityException(Type type, CompoundType.Method method,boolean quiet) |
|
1030 throws ClassNotFound { |
|
1031 if (type.isArray()) { |
|
1032 type = type.getElementType(); |
|
1033 } |
|
1034 if (type.isCompound()){ |
|
1035 if (((CompoundType)type).isIDLEntityException()) { |
|
1036 failedConstraint(18,quiet,stack,method.getEnclosing(), method.toString()); |
|
1037 return true; |
|
1038 } |
|
1039 } |
|
1040 return false; |
|
1041 } |
|
1042 |
|
1043 /** |
|
1044 * Convert all invalid types to valid ones. |
|
1045 */ |
|
1046 protected void swapInvalidTypes () { |
|
1047 |
|
1048 // Walk all interfaces and check them... |
|
1049 |
|
1050 for (int i = 0; i < interfaces.length; i++) { |
|
1051 if (interfaces[i].getStatus() != STATUS_VALID) { |
|
1052 interfaces[i] = (InterfaceType)getValidType(interfaces[i]); |
|
1053 } |
|
1054 } |
|
1055 |
|
1056 // Update methods... |
|
1057 |
|
1058 for (int i = 0; i < methods.length; i++) { |
|
1059 methods[i].swapInvalidTypes(); |
|
1060 } |
|
1061 |
|
1062 // Update members... |
|
1063 |
|
1064 for (int i = 0; i < members.length; i++) { |
|
1065 members[i].swapInvalidTypes(); |
|
1066 } |
|
1067 } |
|
1068 |
|
1069 /* |
|
1070 * Add matching types to list. Return true if this type has not |
|
1071 * been previously checked, false otherwise. |
|
1072 */ |
|
1073 protected boolean addTypes (int typeCodeFilter, |
|
1074 HashSet checked, |
|
1075 Vector matching) { |
|
1076 |
|
1077 // Check self. |
|
1078 |
|
1079 boolean result = super.addTypes(typeCodeFilter,checked,matching); |
|
1080 |
|
1081 // Have we been checked before? |
|
1082 |
|
1083 if (result) { |
|
1084 |
|
1085 // Nope, so walk parent(s) and check them... |
|
1086 |
|
1087 ClassType parent = getSuperclass(); |
|
1088 |
|
1089 if (parent != null) { |
|
1090 parent.addTypes(typeCodeFilter,checked,matching); |
|
1091 } |
|
1092 |
|
1093 // Walk all interfaces and check them... |
|
1094 |
|
1095 //if (interfaces == null) System.out.println("NULL for " +getQualifiedName() + " interfaces"); |
|
1096 for (int i = 0; i < interfaces.length; i++) { |
|
1097 |
|
1098 // Now recurse and add it and any referenced types... |
|
1099 |
|
1100 //if (interfaces[i] == null) System.out.println("NULL for " +getQualifiedName() + " interfaces[" + i + "]"); |
|
1101 interfaces[i].addTypes(typeCodeFilter,checked,matching); |
|
1102 } |
|
1103 |
|
1104 // Walk all methods and check arguments... |
|
1105 |
|
1106 //if (methods == null) System.out.println("NULL for " +getQualifiedName() + " methods"); |
|
1107 for (int i = 0; i < methods.length; i++) { |
|
1108 |
|
1109 // Add return type... |
|
1110 //if (methods[i] == null) System.out.println("NULL for " +getQualifiedName() + " methods[" + i + "]"); |
|
1111 //if (methods[i].getReturnType() == null) System.out.println("NULL for " +getQualifiedName() + methods[i]); |
|
1112 methods[i].getReturnType().addTypes(typeCodeFilter,checked,matching); |
|
1113 |
|
1114 // Add args... |
|
1115 |
|
1116 Type[] args = methods[i].getArguments(); |
|
1117 //if (args == null) System.out.println("NULL for " + getQualifiedName() + " args"); |
|
1118 |
|
1119 for (int j = 0; j < args.length; j++) { |
|
1120 |
|
1121 Type arg = args[j]; |
|
1122 //if (arg == null) System.out.println("NULL for " + getQualifiedName() + " arg[" +j+"]"); |
|
1123 |
|
1124 // Add argument... |
|
1125 |
|
1126 arg.addTypes(typeCodeFilter,checked,matching); |
|
1127 } |
|
1128 |
|
1129 // Add exceptions... |
|
1130 |
|
1131 ClassType[] exceptions = methods[i].getExceptions(); |
|
1132 //if (exceptions == null) System.out.println("NULL for " + getQualifiedName() + " exceptions"); |
|
1133 |
|
1134 for (int j = 0; j < exceptions.length; j++) { |
|
1135 |
|
1136 ClassType ex = exceptions[j]; |
|
1137 |
|
1138 // Add argument... |
|
1139 |
|
1140 ex.addTypes(typeCodeFilter,checked,matching); |
|
1141 } |
|
1142 } |
|
1143 |
|
1144 // Walk all members and add em... |
|
1145 |
|
1146 //if (members == null) System.out.println("NULL for " +getQualifiedName() + " members"); |
|
1147 for (int i = 0; i < members.length; i++) { |
|
1148 //if (members[i] == null) System.out.println("NULL for " +getQualifiedName() + " members[" + i + "]"); |
|
1149 Type cType = members[i].getType(); |
|
1150 //if (cType == null) System.out.println("NULL for " + getQualifiedName() + " cType"); |
|
1151 |
|
1152 // Add it... |
|
1153 |
|
1154 cType.addTypes(typeCodeFilter,checked,matching); |
|
1155 } |
|
1156 } |
|
1157 |
|
1158 return result; |
|
1159 } |
|
1160 |
|
1161 /* |
|
1162 * Return true if theType is a conforming constant type. |
|
1163 */ |
|
1164 private boolean isConformingConstantType (MemberDefinition member) { |
|
1165 return isConformingConstantType(member.getType(),member); |
|
1166 } |
|
1167 |
|
1168 /* |
|
1169 * Return true if theType is a conforming constant type. |
|
1170 */ |
|
1171 private boolean isConformingConstantType (sun.tools.java.Type theType,MemberDefinition member) { |
|
1172 |
|
1173 // Constraint 3: Constants must be either primitives or String. |
|
1174 |
|
1175 boolean result = true; |
|
1176 int typeCode = theType.getTypeCode(); |
|
1177 switch (typeCode) { |
|
1178 case TC_BOOLEAN: |
|
1179 case TC_BYTE: |
|
1180 case TC_CHAR: |
|
1181 case TC_SHORT: |
|
1182 case TC_INT: |
|
1183 case TC_LONG: |
|
1184 case TC_FLOAT: |
|
1185 case TC_DOUBLE: // Primitive, so OK... |
|
1186 { |
|
1187 break; |
|
1188 } |
|
1189 |
|
1190 case TC_CLASS: // Must be java.lang.String |
|
1191 { |
|
1192 if (theType.getClassName() != idJavaLangString) { |
|
1193 failedConstraint(3,false,stack,member.getClassDefinition(),member.getName()); |
|
1194 result = false; |
|
1195 } |
|
1196 break; |
|
1197 } |
|
1198 |
|
1199 case TC_ARRAY: // Array constants are not allowed. |
|
1200 { |
|
1201 failedConstraint(3,false,stack,member.getClassDefinition(),member.getName()); |
|
1202 result = false; |
|
1203 break; |
|
1204 } |
|
1205 |
|
1206 default: |
|
1207 throw new Error("unexpected type code: " + typeCode); |
|
1208 } |
|
1209 |
|
1210 return result; |
|
1211 } |
|
1212 |
|
1213 |
|
1214 /* |
|
1215 * Update any method from 'currentMethods' which is defined in a |
|
1216 * parent class so that it's 'declaredBy' field specifies the |
|
1217 * parent. |
|
1218 * @param current The class or interface to gather methods from. |
|
1219 * @param currentMethods The list into which to put the methods. |
|
1220 * for contraint 6. |
|
1221 * @param quiet true if silent errors. |
|
1222 * @param stack the context stack. |
|
1223 * @return currentMethods or null if failed a constraint check. |
|
1224 */ |
|
1225 protected Vector updateParentClassMethods(ClassDefinition current, |
|
1226 Vector currentMethods, |
|
1227 boolean quiet, |
|
1228 ContextStack stack) |
|
1229 throws ClassNotFound { |
|
1230 |
|
1231 ClassDeclaration parentDecl = current.getSuperClass(env); |
|
1232 |
|
1233 while (parentDecl != null) { |
|
1234 |
|
1235 ClassDefinition parentDef = parentDecl.getClassDefinition(env); |
|
1236 Identifier currentID = parentDecl.getName(); |
|
1237 |
|
1238 if ( currentID == idJavaLangObject ) break; |
|
1239 |
|
1240 // Walk all members of this class and update any that |
|
1241 // already exist in currentMethods... |
|
1242 |
|
1243 for (MemberDefinition member = parentDef.getFirstMember(); |
|
1244 member != null; |
|
1245 member = member.getNextMember()) { |
|
1246 |
|
1247 if (member.isMethod() && |
|
1248 !member.isInitializer() && |
|
1249 !member.isConstructor() && |
|
1250 !member.isPrivate()) { |
|
1251 |
|
1252 // It's a method. Is it valid? |
|
1253 |
|
1254 Method method; |
|
1255 try { |
|
1256 method = new Method((CompoundType)this,member,quiet,stack); |
|
1257 } catch (Exception e) { |
|
1258 // Don't report anything here, it's already been reported... |
|
1259 return null; |
|
1260 } |
|
1261 |
|
1262 // Have we already seen it? |
|
1263 |
|
1264 int index = currentMethods.indexOf(method); |
|
1265 if (index >= 0) { |
|
1266 |
|
1267 // Yes, so update it... |
|
1268 |
|
1269 Method currentMethod = (Method)currentMethods.elementAt(index); |
|
1270 currentMethod.setDeclaredBy(currentID); |
|
1271 } |
|
1272 else currentMethods.addElement(method); |
|
1273 } |
|
1274 } |
|
1275 |
|
1276 // Update parent and keep walking up the chain... |
|
1277 |
|
1278 parentDecl = parentDef.getSuperClass(env); |
|
1279 } |
|
1280 |
|
1281 return currentMethods; |
|
1282 } |
|
1283 |
|
1284 /* |
|
1285 * Add all of the public and protected methods defined in |
|
1286 * current (other than initializers) to allMethods. If a sub-interface |
|
1287 * re-declares an inherited method, it will not be added. |
|
1288 * @param current The class or interface to gather methods from. |
|
1289 * @param directMethods The list into which to put the methods. |
|
1290 * @param noMultiInheritedMethods A flag to enable/disable checking |
|
1291 * for contraint 6. |
|
1292 * @param quiet true if silent errors. |
|
1293 * @param stack the context stack. |
|
1294 * @return directMethods or null if failed a constraint check. |
|
1295 */ |
|
1296 protected Vector addAllMethods (ClassDefinition current, Vector directMethods, |
|
1297 boolean noMultiInheritedMethods, |
|
1298 boolean quiet, |
|
1299 ContextStack stack) |
|
1300 throws ClassNotFound { |
|
1301 |
|
1302 // Constraint 6: Multiple inherited interfaces may not |
|
1303 // declare the same method. |
|
1304 |
|
1305 ClassDeclaration[] interfaces = current.getInterfaces(); |
|
1306 |
|
1307 // We want to add members starting at the _least_ derived |
|
1308 // interfaces. To do so, recurse until we have no more |
|
1309 // interfaces... |
|
1310 |
|
1311 for (int i = 0; i < interfaces.length; i++) { |
|
1312 |
|
1313 Vector result = addAllMethods(interfaces[i].getClassDefinition(env), |
|
1314 directMethods, |
|
1315 noMultiInheritedMethods,quiet,stack); |
|
1316 if (result == null) { |
|
1317 return null; |
|
1318 } |
|
1319 } |
|
1320 |
|
1321 // Walk all members of this interface, adding any unique methods |
|
1322 // other than initializers and private methods... |
|
1323 |
|
1324 for (MemberDefinition member = current.getFirstMember(); |
|
1325 member != null; |
|
1326 member = member.getNextMember()) |
|
1327 { |
|
1328 if (member.isMethod() && |
|
1329 !member.isInitializer() && |
|
1330 !member.isPrivate()) { |
|
1331 |
|
1332 // It's a method. Is it valid? |
|
1333 |
|
1334 Method method; |
|
1335 try { |
|
1336 method = new Method((CompoundType)this,member,quiet,stack); |
|
1337 } catch (Exception e) { |
|
1338 // Don't report anything here, it's already been reported... |
|
1339 return null; |
|
1340 } |
|
1341 |
|
1342 // Have we already seen it? |
|
1343 |
|
1344 if (!directMethods.contains(method)) { |
|
1345 |
|
1346 // Nope, so add it... |
|
1347 |
|
1348 directMethods.addElement(method); |
|
1349 |
|
1350 } else { |
|
1351 |
|
1352 // Yes. This is an error unless we are looking at the |
|
1353 // target interface (or this is a ValueType). Are we? |
|
1354 |
|
1355 if (noMultiInheritedMethods && current != classDef && |
|
1356 !stack.isParentAValue() && !stack.getContext().isValue()) { |
|
1357 |
|
1358 // Nope. Say so and signal error by returning null.. |
|
1359 |
|
1360 Method existingMethod = (Method) directMethods.elementAt(directMethods.indexOf(method)); |
|
1361 ClassDefinition existingMemberClassDef = existingMethod.getMemberDefinition().getClassDefinition(); |
|
1362 |
|
1363 // There are more legal cases to consider here. |
|
1364 // If the two methods belong to interfaces that inherit from each other |
|
1365 // then it is just a redefinition which is legal. |
|
1366 if ( current != existingMemberClassDef && |
|
1367 ! inheritsFrom(current, existingMemberClassDef) && |
|
1368 ! inheritsFrom(existingMemberClassDef, current)) |
|
1369 { |
|
1370 //Identifier int1 = existingMethod.getEnclosing().getIdentifier(); |
|
1371 //Identifier int2 = current.getName(); |
|
1372 //String message = int1.toString() + " and " + int2.toString(); |
|
1373 String message = existingMemberClassDef.getName() + " and " + current.getName(); |
|
1374 failedConstraint(6,quiet,stack,classDef,message,method); |
|
1375 return null; |
|
1376 } |
|
1377 } |
|
1378 |
|
1379 // Bug fix 5014329 |
|
1380 |
|
1381 // find a matching method. |
|
1382 int index = directMethods.indexOf(method); |
|
1383 Method other = (Method) directMethods.get(index); |
|
1384 |
|
1385 // merge the two methods, such that the new method |
|
1386 // will contain only those exception that can be thrown |
|
1387 // by both these methods, not just one of them. |
|
1388 Method newMethod = method.mergeWith(other); |
|
1389 |
|
1390 // replace the old method with the new. |
|
1391 directMethods.set(index, newMethod); |
|
1392 } |
|
1393 } |
|
1394 } |
|
1395 |
|
1396 return directMethods; |
|
1397 } |
|
1398 |
|
1399 // This should really be a method on ClassDefinition, but it takes too long to change the shared source. |
|
1400 // Works for both, classes and interfaces. |
|
1401 protected boolean inheritsFrom(ClassDefinition def, ClassDefinition otherDef) { |
|
1402 if (def == otherDef) |
|
1403 return true; |
|
1404 |
|
1405 ClassDefinition superDef; |
|
1406 if (def.getSuperClass() != null) { |
|
1407 superDef = def.getSuperClass().getClassDefinition(); |
|
1408 if (inheritsFrom(superDef, otherDef)) |
|
1409 return true; |
|
1410 } |
|
1411 |
|
1412 ClassDeclaration[] interfaces = def.getInterfaces(); |
|
1413 for (int i=0; i<interfaces.length; i++) { |
|
1414 superDef = interfaces[i].getClassDefinition(); |
|
1415 if (inheritsFrom(superDef, otherDef)) |
|
1416 return true; |
|
1417 } |
|
1418 return false; |
|
1419 } |
|
1420 |
|
1421 /* |
|
1422 * Add all of the interfaces implemented directly by current |
|
1423 * to the list. Returns null if any are non-conforming. |
|
1424 */ |
|
1425 protected Vector addRemoteInterfaces (Vector list, |
|
1426 boolean allowNonConforming, |
|
1427 ContextStack stack) throws ClassNotFound { |
|
1428 |
|
1429 // Add all the interfaces of current... |
|
1430 |
|
1431 ClassDefinition theInterface = getClassDefinition(); |
|
1432 ClassDeclaration[] interfaces = theInterface.getInterfaces(); |
|
1433 |
|
1434 stack.setNewContextCode(ContextStack.IMPLEMENTS); |
|
1435 |
|
1436 for (int i = 0; i < interfaces.length; i++) { |
|
1437 |
|
1438 ClassDefinition def = interfaces[i].getClassDefinition(env); |
|
1439 |
|
1440 // Is it a SpecialInterfaceType... |
|
1441 |
|
1442 InterfaceType it = SpecialInterfaceType.forSpecial(def,stack);; |
|
1443 |
|
1444 if (it == null) { |
|
1445 |
|
1446 // No, is it Remote? |
|
1447 |
|
1448 if (env.defRemote.implementedBy(env, interfaces[i])) { |
|
1449 |
|
1450 // Yes, so it must be a RemoteType. |
|
1451 |
|
1452 it = RemoteType.forRemote(def,stack,false); |
|
1453 |
|
1454 } else { |
|
1455 |
|
1456 // Then try Abstract... |
|
1457 |
|
1458 it = AbstractType.forAbstract(def,stack,true); |
|
1459 |
|
1460 if (it == null && allowNonConforming) { |
|
1461 |
|
1462 // Must be non-conforming... |
|
1463 |
|
1464 it = NCInterfaceType.forNCInterface(def,stack); |
|
1465 } |
|
1466 } |
|
1467 } |
|
1468 |
|
1469 if (it != null) { |
|
1470 list.addElement(it); |
|
1471 } else { |
|
1472 return null; |
|
1473 } |
|
1474 } |
|
1475 |
|
1476 return list; |
|
1477 } |
|
1478 |
|
1479 /* |
|
1480 * Add all of the interfaces implemented directly by current |
|
1481 * to the list. |
|
1482 */ |
|
1483 protected Vector addNonRemoteInterfaces (Vector list, |
|
1484 ContextStack stack) throws ClassNotFound { |
|
1485 |
|
1486 // Add all the interfaces of current... |
|
1487 |
|
1488 ClassDefinition theInterface = getClassDefinition(); |
|
1489 ClassDeclaration[] interfaces = theInterface.getInterfaces(); |
|
1490 |
|
1491 stack.setNewContextCode(ContextStack.IMPLEMENTS); |
|
1492 |
|
1493 for (int i = 0; i < interfaces.length; i++) { |
|
1494 |
|
1495 ClassDefinition def = interfaces[i].getClassDefinition(env); |
|
1496 |
|
1497 // First try SpecialInterfaceType... |
|
1498 |
|
1499 InterfaceType it = SpecialInterfaceType.forSpecial(def,stack); |
|
1500 |
|
1501 if (it == null) { |
|
1502 |
|
1503 // Then try AbstractType... |
|
1504 |
|
1505 it = AbstractType.forAbstract(def,stack,true); |
|
1506 |
|
1507 if (it == null) { |
|
1508 |
|
1509 // Then try NCInterfaceType... |
|
1510 |
|
1511 it = NCInterfaceType.forNCInterface(def,stack); |
|
1512 } |
|
1513 } |
|
1514 |
|
1515 if (it != null) { |
|
1516 list.addElement(it); |
|
1517 } else { |
|
1518 return null; |
|
1519 } |
|
1520 } |
|
1521 |
|
1522 return list; |
|
1523 } |
|
1524 |
|
1525 |
|
1526 /* |
|
1527 * Walk self, adding constants and data members. |
|
1528 * @return true if all conform, false otherwise. |
|
1529 */ |
|
1530 protected boolean addAllMembers (Vector allMembers, |
|
1531 boolean onlyConformingConstants, // AND inner classes. |
|
1532 boolean quiet, |
|
1533 ContextStack stack) { |
|
1534 |
|
1535 boolean result = true; |
|
1536 |
|
1537 // Walk all members of this interface... |
|
1538 |
|
1539 for (MemberDefinition member = getClassDefinition().getFirstMember(); |
|
1540 member != null && result; |
|
1541 member = member.getNextMember()) |
|
1542 { |
|
1543 if (!member.isMethod()) { |
|
1544 |
|
1545 try { |
|
1546 String value = null; |
|
1547 |
|
1548 // Prod it to setValue if it is a constant... |
|
1549 |
|
1550 member.getValue(env); |
|
1551 |
|
1552 // Get the value, if any... |
|
1553 |
|
1554 Node node = member.getValue(); |
|
1555 |
|
1556 if (node != null) { |
|
1557 // We don't want to change the code in CharExpression, |
|
1558 // which is shared among tools, to return the right string |
|
1559 // in case the type is char, so we treat it special here. |
|
1560 if (member.getType().getTypeCode() == TC_CHAR) { |
|
1561 Integer intValue = (Integer)((IntegerExpression)node).getValue(); |
|
1562 value = "L'" + String.valueOf((char)intValue.intValue()) + "'"; |
|
1563 } else { |
|
1564 value = node.toString(); |
|
1565 } |
|
1566 } |
|
1567 |
|
1568 // Are we supposed to allow only conforming constants? |
|
1569 |
|
1570 if (onlyConformingConstants && member.getInnerClass() == null) { |
|
1571 |
|
1572 // Yep, so check it... |
|
1573 |
|
1574 if (value == null || !isConformingConstantType(member)) { |
|
1575 failedConstraint(3,quiet,stack,member.getClassDefinition(),member.getName()); |
|
1576 result = false; |
|
1577 break; |
|
1578 } |
|
1579 } |
|
1580 |
|
1581 // Make member and add to list... |
|
1582 |
|
1583 try { |
|
1584 Member newMember = new Member(member,value,stack,this); |
|
1585 allMembers.addElement(newMember); |
|
1586 } catch (CompilerError e) { |
|
1587 result = false; |
|
1588 } |
|
1589 |
|
1590 } catch (ClassNotFound e) { |
|
1591 classNotFound(stack,e); |
|
1592 result = false; |
|
1593 } |
|
1594 } |
|
1595 } |
|
1596 |
|
1597 return result; |
|
1598 } |
|
1599 /* |
|
1600 * Walk self, adding constants. |
|
1601 * @return true if all conform, false otherwise. |
|
1602 */ |
|
1603 protected boolean addConformingConstants (Vector allMembers, |
|
1604 boolean quiet, |
|
1605 ContextStack stack) { |
|
1606 |
|
1607 boolean result = true; |
|
1608 |
|
1609 // Walk all members of this interface... |
|
1610 |
|
1611 for (MemberDefinition member = getClassDefinition().getFirstMember(); |
|
1612 member != null && result; |
|
1613 member = member.getNextMember()) |
|
1614 { |
|
1615 if (!member.isMethod()) { |
|
1616 |
|
1617 try { |
|
1618 String value = null; |
|
1619 |
|
1620 // Prod it to setValue if it is a constant... |
|
1621 |
|
1622 member.getValue(env); |
|
1623 |
|
1624 // Get the value, if any... |
|
1625 |
|
1626 Node node = member.getValue(); |
|
1627 |
|
1628 if (node != null) { |
|
1629 value = node.toString(); |
|
1630 } |
|
1631 |
|
1632 |
|
1633 // Is it a constant? |
|
1634 |
|
1635 if (value != null) { |
|
1636 |
|
1637 // Yes, is it conforming? |
|
1638 |
|
1639 if (!isConformingConstantType(member)) { |
|
1640 failedConstraint(3,quiet,stack,member.getClassDefinition(),member.getName()); |
|
1641 result = false; |
|
1642 break; |
|
1643 } |
|
1644 |
|
1645 // Yes, so make a member and add to list... |
|
1646 |
|
1647 try { |
|
1648 Member newMember = new Member(member,value,stack,this); |
|
1649 allMembers.addElement(newMember); |
|
1650 } catch (CompilerError e) { |
|
1651 result = false; |
|
1652 } |
|
1653 } |
|
1654 } catch (ClassNotFound e) { |
|
1655 classNotFound(stack,e); |
|
1656 result = false; |
|
1657 } |
|
1658 } |
|
1659 } |
|
1660 |
|
1661 return result; |
|
1662 } |
|
1663 |
|
1664 protected ValueType[] getMethodExceptions (MemberDefinition member, |
|
1665 boolean quiet, |
|
1666 ContextStack stack) throws Exception { |
|
1667 |
|
1668 boolean result = true; |
|
1669 stack.setNewContextCode(ContextStack.METHOD_EXCEPTION); |
|
1670 ClassDeclaration[] except = member.getExceptions(env); |
|
1671 ValueType[] exceptions = new ValueType[except.length]; |
|
1672 |
|
1673 try { |
|
1674 for (int i = 0; i < except.length; i++) { |
|
1675 ClassDefinition theClass = except[i].getClassDefinition(env); |
|
1676 try { |
|
1677 ValueType type = ValueType.forValue(theClass,stack,false); |
|
1678 if (type != null) { |
|
1679 exceptions[i] = type; |
|
1680 } else { |
|
1681 result = false; |
|
1682 } |
|
1683 } catch (ClassCastException e1) { |
|
1684 failedConstraint(22,quiet,stack,getQualifiedName()); |
|
1685 throw new CompilerError("Method: exception " + theClass.getName() + " not a class type!"); |
|
1686 } catch (NullPointerException e2) { |
|
1687 failedConstraint(23,quiet,stack,getQualifiedName()); |
|
1688 throw new CompilerError("Method: caught null pointer exception"); |
|
1689 } |
|
1690 } |
|
1691 } catch (ClassNotFound e) { |
|
1692 classNotFound(quiet,stack,e); |
|
1693 result = false; |
|
1694 } |
|
1695 |
|
1696 if (!result) { |
|
1697 throw new Exception(); |
|
1698 } |
|
1699 |
|
1700 // Remove any duplicates (javac seems to allow them, but rmic will |
|
1701 // generate bad ties)... |
|
1702 |
|
1703 int dupCount = 0; |
|
1704 for (int i = 0; i < exceptions.length; i++) { |
|
1705 for (int j = 0; j < exceptions.length; j++) { |
|
1706 if (i != j && exceptions[i] != null && exceptions[i] == exceptions[j]) { |
|
1707 exceptions[j] = null; |
|
1708 dupCount++; |
|
1709 } |
|
1710 } |
|
1711 } |
|
1712 if (dupCount > 0) { |
|
1713 int offset = 0; |
|
1714 ValueType[] temp = new ValueType[exceptions.length - dupCount]; |
|
1715 for (int i = 0; i < exceptions.length; i++) { |
|
1716 if (exceptions[i] != null) { |
|
1717 temp[offset++] = exceptions[i]; |
|
1718 } |
|
1719 } |
|
1720 exceptions = temp; |
|
1721 } |
|
1722 |
|
1723 return exceptions; |
|
1724 } |
|
1725 |
|
1726 |
|
1727 protected static String getVisibilityString (MemberDefinition member) { |
|
1728 String vis = ""; |
|
1729 String prefix = ""; |
|
1730 |
|
1731 if (member.isPublic()) { |
|
1732 vis += "public"; |
|
1733 prefix = " "; |
|
1734 } else if (member.isProtected()) { |
|
1735 vis += "protected"; |
|
1736 prefix = " "; |
|
1737 } else if (member.isPrivate()) { |
|
1738 vis += "private"; |
|
1739 prefix = " "; |
|
1740 } |
|
1741 |
|
1742 if (member.isStatic()) { |
|
1743 vis += prefix; |
|
1744 vis += "static"; |
|
1745 prefix = " "; |
|
1746 } |
|
1747 |
|
1748 if (member.isFinal()) { |
|
1749 vis += prefix; |
|
1750 vis += "final"; |
|
1751 prefix = " "; |
|
1752 } |
|
1753 |
|
1754 return vis; |
|
1755 } |
|
1756 |
|
1757 protected boolean assertNotImpl(Type type, |
|
1758 boolean quiet, |
|
1759 ContextStack stack, |
|
1760 CompoundType enclosing, |
|
1761 boolean dataMember) { |
|
1762 |
|
1763 if (type.isType(TYPE_IMPLEMENTATION)) { |
|
1764 int constraint = dataMember ? 28 : 21; |
|
1765 failedConstraint(constraint,quiet,stack,type,enclosing.getName()); |
|
1766 return false; |
|
1767 } |
|
1768 return true; |
|
1769 } |
|
1770 |
|
1771 //_____________________________________________________________________ |
|
1772 // Inner Class "Method" |
|
1773 //_____________________________________________________________________ |
|
1774 |
|
1775 /** |
|
1776 * A CompoundType.Method object encapsulates IIOP-specific information |
|
1777 * about a particular method in the interface represented by the outer |
|
1778 * instance. |
|
1779 */ |
|
1780 public class Method implements ContextElement, Cloneable { |
|
1781 |
|
1782 /** |
|
1783 * Is this method inherited? |
|
1784 */ |
|
1785 public boolean isInherited () { |
|
1786 return declaredBy != enclosing.getIdentifier(); |
|
1787 } |
|
1788 |
|
1789 /** |
|
1790 * Is this method an attribute? |
|
1791 * Return true if getAttributeKind != ATTRIBUTE_NONE. |
|
1792 */ |
|
1793 public boolean isAttribute () { |
|
1794 return attributeKind != ATTRIBUTE_NONE; |
|
1795 } |
|
1796 |
|
1797 /** |
|
1798 * Is this method a read-write attribute? |
|
1799 */ |
|
1800 public boolean isReadWriteAttribute () { |
|
1801 return attributeKind == ATTRIBUTE_IS_RW || |
|
1802 attributeKind == ATTRIBUTE_GET_RW; |
|
1803 } |
|
1804 |
|
1805 /** |
|
1806 * Return the attribute kind. |
|
1807 */ |
|
1808 public int getAttributeKind() { |
|
1809 return attributeKind; |
|
1810 } |
|
1811 |
|
1812 /** |
|
1813 * Return the attribute name. Will be null if |
|
1814 * attribute kind == ATTRIBUTE_NONE. |
|
1815 */ |
|
1816 public String getAttributeName() { |
|
1817 return attributeName; |
|
1818 } |
|
1819 |
|
1820 /** |
|
1821 * For kinds ATTRIBUTE_GET_RW or ATTRIBUTE_IS_RW, return |
|
1822 * the index of the matching ATTRIBUTE_SET method, and |
|
1823 * vice-versa. For all other cases, return -1. |
|
1824 */ |
|
1825 public int getAttributePairIndex() { |
|
1826 return attributePairIndex; |
|
1827 } |
|
1828 |
|
1829 /** |
|
1830 * Return context element name. |
|
1831 */ |
|
1832 public String getElementName() { |
|
1833 return memberDef.toString(); |
|
1834 } |
|
1835 |
|
1836 /** |
|
1837 * Equality check based on method signature. |
|
1838 */ |
|
1839 public boolean equals(Object obj) { |
|
1840 Method other = (Method) obj; |
|
1841 |
|
1842 if (getName().equals(other.getName()) && |
|
1843 arguments.length == other.arguments.length) { |
|
1844 |
|
1845 for (int i = 0; i < arguments.length; i++) { |
|
1846 if (! arguments[i].equals(other.arguments[i])) { |
|
1847 return false; |
|
1848 } |
|
1849 } |
|
1850 return true; |
|
1851 } |
|
1852 return false; |
|
1853 } |
|
1854 |
|
1855 public int hashCode() { |
|
1856 return getName().hashCode() ^ Arrays.hashCode(arguments); |
|
1857 } |
|
1858 |
|
1859 /** |
|
1860 * Return a new Method object that is a legal combination of |
|
1861 * this method object and another one. |
|
1862 * |
|
1863 * This requires determining the exceptions declared by the |
|
1864 * combined method, which must be only those exceptions |
|
1865 * that may thrown by both of the old methods. |
|
1866 */ |
|
1867 public Method mergeWith(Method other) { |
|
1868 if (!equals(other)) { |
|
1869 env.error(0, "attempt to merge method failed:", getName(), |
|
1870 enclosing.getClassDefinition().getName()); |
|
1871 } |
|
1872 |
|
1873 Vector legalExceptions = new Vector(); |
|
1874 try { |
|
1875 collectCompatibleExceptions( |
|
1876 other.exceptions, exceptions, legalExceptions); |
|
1877 collectCompatibleExceptions( |
|
1878 exceptions, other.exceptions, legalExceptions); |
|
1879 } catch (ClassNotFound e) { |
|
1880 env.error(0, "class.not.found", e.name, |
|
1881 enclosing.getClassDefinition().getName()); |
|
1882 return null; |
|
1883 } |
|
1884 |
|
1885 Method merged = (Method) clone(); |
|
1886 merged.exceptions = new ValueType[legalExceptions.size()]; |
|
1887 legalExceptions.copyInto(merged.exceptions); |
|
1888 merged.implExceptions = merged.exceptions; |
|
1889 |
|
1890 return merged; |
|
1891 } |
|
1892 |
|
1893 /** |
|
1894 * Add to the supplied list all exceptions in the "from" array |
|
1895 * that are subclasses of an exception in the "with" array. |
|
1896 */ |
|
1897 private void collectCompatibleExceptions( |
|
1898 ValueType[] from, ValueType[] with, Vector list) |
|
1899 throws ClassNotFound { |
|
1900 |
|
1901 for (int i = 0; i < from.length; i++) { |
|
1902 ClassDefinition exceptionDef = from[i].getClassDefinition(); |
|
1903 if (!list.contains(from[i])) { |
|
1904 for (int j = 0; j < with.length; j++) { |
|
1905 if (exceptionDef.subClassOf( |
|
1906 enclosing.getEnv(), |
|
1907 with[j].getClassDeclaration())) { |
|
1908 list.addElement(from[i]); |
|
1909 break; |
|
1910 } |
|
1911 } |
|
1912 } |
|
1913 } |
|
1914 } |
|
1915 |
|
1916 /** |
|
1917 * Return the compound type which contains this method. |
|
1918 */ |
|
1919 public CompoundType getEnclosing() { |
|
1920 return enclosing; |
|
1921 } |
|
1922 |
|
1923 /** |
|
1924 * Return the identifier for the class or interface which |
|
1925 * declares this method. |
|
1926 */ |
|
1927 public Identifier getDeclaredBy() { |
|
1928 return declaredBy; |
|
1929 } |
|
1930 |
|
1931 /** |
|
1932 * Return the visibility (e.g. "public final") of this member. |
|
1933 */ |
|
1934 public String getVisibility() { |
|
1935 return vis; |
|
1936 } |
|
1937 |
|
1938 /** |
|
1939 * Methods to check various attributes. |
|
1940 */ |
|
1941 public boolean isPublic() { |
|
1942 return memberDef.isPublic(); |
|
1943 } |
|
1944 |
|
1945 public boolean isProtected() { |
|
1946 return memberDef.isPrivate(); |
|
1947 } |
|
1948 |
|
1949 public boolean isPrivate() { |
|
1950 return memberDef.isPrivate(); |
|
1951 } |
|
1952 |
|
1953 public boolean isStatic() { |
|
1954 return memberDef.isStatic(); |
|
1955 } |
|
1956 |
|
1957 /** |
|
1958 * Return the name of this method. |
|
1959 */ |
|
1960 public String getName() { |
|
1961 return name; |
|
1962 } |
|
1963 |
|
1964 /** |
|
1965 * IDL_Naming |
|
1966 * Return the IDL name of this method. |
|
1967 */ |
|
1968 public String getIDLName() { |
|
1969 return idlName; |
|
1970 } |
|
1971 |
|
1972 /** |
|
1973 * Return the type of this method. |
|
1974 */ |
|
1975 public sun.tools.java.Type getType() { |
|
1976 return memberDef.getType(); |
|
1977 } |
|
1978 |
|
1979 /** |
|
1980 * Return true if this is a constructor. |
|
1981 */ |
|
1982 public boolean isConstructor () { |
|
1983 return memberDef.isConstructor(); |
|
1984 } |
|
1985 |
|
1986 /** |
|
1987 * Return true if this is NOT a constructor && is not |
|
1988 * an attribute. |
|
1989 */ |
|
1990 public boolean isNormalMethod () { |
|
1991 return (!memberDef.isConstructor()) && attributeKind == ATTRIBUTE_NONE; |
|
1992 } |
|
1993 |
|
1994 /** |
|
1995 * Get the return type of this method. May be null. |
|
1996 */ |
|
1997 public Type getReturnType() { |
|
1998 return returnType; |
|
1999 } |
|
2000 |
|
2001 /** |
|
2002 * Return the argument types of this method. |
|
2003 */ |
|
2004 public Type[] getArguments() { |
|
2005 return (Type[]) arguments.clone(); |
|
2006 } |
|
2007 |
|
2008 /** |
|
2009 * Return the names of the argument types of this method. |
|
2010 */ |
|
2011 public String[] getArgumentNames() { |
|
2012 return argumentNames; |
|
2013 } |
|
2014 |
|
2015 /** |
|
2016 * Return the MemberDefinition from which this method was created. |
|
2017 */ |
|
2018 public MemberDefinition getMemberDefinition() { |
|
2019 return memberDef; |
|
2020 } |
|
2021 |
|
2022 /** |
|
2023 * Return an array of the exception classes declared to be |
|
2024 * thrown by this remote method. |
|
2025 * |
|
2026 * For methods with the same name and type signature inherited |
|
2027 * from multiple remote interfaces, the array will contain |
|
2028 * the set of exceptions declared in all of the interfaces' |
|
2029 * methods that can be legally thrown in each of them. |
|
2030 */ |
|
2031 public ValueType[] getExceptions() { |
|
2032 return (ValueType[]) exceptions.clone(); |
|
2033 } |
|
2034 |
|
2035 /** |
|
2036 * Same as getExceptions(), except when method is in an |
|
2037 * ImplementationType and the exceptions list is narrower. |
|
2038 */ |
|
2039 public ValueType[] getImplExceptions() { |
|
2040 return (ValueType[]) implExceptions.clone(); |
|
2041 } |
|
2042 |
|
2043 /** |
|
2044 * Return an array containing only those exceptions which |
|
2045 * need to be caught. Removes java.rmi.RemoteException, |
|
2046 * java.lang.RuntimeException, java.lang.Error, and their |
|
2047 * subclasses, then removes any exceptions which are more |
|
2048 * derived than another in the list. Returns null if no |
|
2049 * exceptions need to be caught. |
|
2050 */ |
|
2051 public ValueType[] getUniqueCatchList(ValueType[] list) { |
|
2052 ValueType[] result = list; |
|
2053 int newSize = list.length; |
|
2054 |
|
2055 try { |
|
2056 |
|
2057 // First, remove RemoteException, RuntimeException, Error, and their subclasses... |
|
2058 for (int i = 0; i < list.length; i++) { |
|
2059 ClassDeclaration decl = list[i].getClassDeclaration(); |
|
2060 if (env.defRemoteException.superClassOf(env, decl) || |
|
2061 env.defRuntimeException.superClassOf(env, decl) || |
|
2062 env.defError.superClassOf(env, decl)) { |
|
2063 list[i] = null; |
|
2064 newSize--; |
|
2065 } |
|
2066 } |
|
2067 |
|
2068 // Now remove derived types... |
|
2069 for (int i = 0; i < list.length; i++) { |
|
2070 if (list[i] != null) { |
|
2071 ClassDefinition current = list[i].getClassDefinition(); |
|
2072 for (int j = 0; j < list.length; j++) { |
|
2073 if (j != i && list[i] != null && list[j] != null && |
|
2074 current.superClassOf(env, list[j].getClassDeclaration())) { |
|
2075 list[j] = null; |
|
2076 newSize--; |
|
2077 } |
|
2078 } |
|
2079 } |
|
2080 } |
|
2081 |
|
2082 } catch (ClassNotFound e) { |
|
2083 classNotFound(stack,e); // Report error but do not stop. |
|
2084 } |
|
2085 |
|
2086 // Create new list if we removed anything... |
|
2087 |
|
2088 if (newSize < list.length) { |
|
2089 ValueType[] temp = new ValueType[newSize]; |
|
2090 int offset = 0; |
|
2091 for (int i = 0; i < list.length; i++) { |
|
2092 if (list[i] != null) { |
|
2093 temp[offset++] = list[i]; |
|
2094 } |
|
2095 } |
|
2096 list = temp; |
|
2097 } |
|
2098 |
|
2099 if (list.length == 0) { |
|
2100 return null; |
|
2101 } else { |
|
2102 return list; |
|
2103 } |
|
2104 } |
|
2105 |
|
2106 /** |
|
2107 * Return an array containing only those exceptions which need to be |
|
2108 * handled explicitly by the stub. Removes java.lang.RuntimeException, |
|
2109 * java.lang.Error, and their subclasses, since these are all passed |
|
2110 * back as CORBA system exceptions. Also removes subclasses of |
|
2111 * java.rmi.RemoteException but not java.rmi.RemoteException itself, |
|
2112 * since this may need to be thrown by the stub. |
|
2113 */ |
|
2114 public ValueType[] getFilteredStubExceptions(ValueType[] list) { |
|
2115 ValueType[] result = list; |
|
2116 int newSize = list.length; |
|
2117 |
|
2118 try { |
|
2119 |
|
2120 for (int i = 0; i < list.length; i++) { |
|
2121 ClassDeclaration decl = list[i].getClassDeclaration(); |
|
2122 if ((env.defRemoteException.superClassOf(env, decl) && |
|
2123 !env.defRemoteException.getClassDeclaration().equals(decl)) || |
|
2124 env.defRuntimeException.superClassOf(env, decl) || |
|
2125 env.defError.superClassOf(env, decl)) { |
|
2126 list[i] = null; |
|
2127 newSize--; |
|
2128 } |
|
2129 } |
|
2130 |
|
2131 } catch (ClassNotFound e) { |
|
2132 classNotFound(stack,e); // Report error but do not stop. |
|
2133 } |
|
2134 |
|
2135 // Create new list if we removed anything... |
|
2136 |
|
2137 if (newSize < list.length) { |
|
2138 ValueType[] temp = new ValueType[newSize]; |
|
2139 int offset = 0; |
|
2140 for (int i = 0; i < list.length; i++) { |
|
2141 if (list[i] != null) { |
|
2142 temp[offset++] = list[i]; |
|
2143 } |
|
2144 } |
|
2145 list = temp; |
|
2146 } |
|
2147 |
|
2148 return list; |
|
2149 } |
|
2150 |
|
2151 /** |
|
2152 * Return the string representation of this method. |
|
2153 */ |
|
2154 public String toString() { |
|
2155 |
|
2156 if (stringRep == null) { |
|
2157 |
|
2158 StringBuffer result = new StringBuffer(returnType.toString()); |
|
2159 |
|
2160 // Add name... |
|
2161 |
|
2162 result.append(" "); |
|
2163 result.append(getName()); |
|
2164 result.append(" ("); |
|
2165 |
|
2166 // Add arguments... |
|
2167 |
|
2168 for (int i = 0; i < arguments.length; i++) { |
|
2169 if (i > 0) { |
|
2170 result.append(", "); |
|
2171 } |
|
2172 result.append(arguments[i]); |
|
2173 result.append(" "); |
|
2174 result.append(argumentNames[i]); |
|
2175 } |
|
2176 |
|
2177 result.append(")"); |
|
2178 |
|
2179 // Add exceptions... |
|
2180 |
|
2181 for (int i = 0; i < exceptions.length; i++) { |
|
2182 if (i == 0) { |
|
2183 result.append(" throws "); |
|
2184 } else { |
|
2185 result.append(", "); |
|
2186 } |
|
2187 result.append(exceptions[i]); |
|
2188 } |
|
2189 |
|
2190 result.append(";"); |
|
2191 |
|
2192 stringRep = result.toString(); |
|
2193 } |
|
2194 |
|
2195 return stringRep; |
|
2196 } |
|
2197 |
|
2198 |
|
2199 /** |
|
2200 * Set attribute kind. May only be called during initialization. |
|
2201 */ |
|
2202 public void setAttributeKind(int kind) { |
|
2203 attributeKind = kind; |
|
2204 } |
|
2205 |
|
2206 /** |
|
2207 * Set pair index. May only be called during initialization. |
|
2208 */ |
|
2209 public void setAttributePairIndex(int index) { |
|
2210 attributePairIndex = index; |
|
2211 } |
|
2212 |
|
2213 /** |
|
2214 * Set attribute name. May only be called during initialization. |
|
2215 */ |
|
2216 public void setAttributeName(String name) { |
|
2217 attributeName = name; |
|
2218 } |
|
2219 |
|
2220 /** |
|
2221 * Set the idl name. May only be called during initialization. |
|
2222 */ |
|
2223 public void setIDLName (String idlName) { |
|
2224 this.idlName=idlName; |
|
2225 } |
|
2226 |
|
2227 /** |
|
2228 * Set the implExceptions array. May only be called during initialization. |
|
2229 */ |
|
2230 public void setImplExceptions (ValueType[] exceptions) { |
|
2231 implExceptions = exceptions; |
|
2232 } |
|
2233 |
|
2234 /** |
|
2235 * Set the declaredBy Identifier. May only be called during initialization. |
|
2236 */ |
|
2237 public void setDeclaredBy (Identifier by) { |
|
2238 declaredBy = by; |
|
2239 } |
|
2240 |
|
2241 /** |
|
2242 * Convert all invalid types to valid ones. |
|
2243 */ |
|
2244 protected void swapInvalidTypes () { |
|
2245 |
|
2246 // Check return type... |
|
2247 |
|
2248 if (returnType.getStatus() != STATUS_VALID) { |
|
2249 returnType = getValidType(returnType); |
|
2250 } |
|
2251 |
|
2252 // Check args... |
|
2253 |
|
2254 for (int i = 0; i < arguments.length; i++) { |
|
2255 if (arguments[i].getStatus() != STATUS_VALID) { |
|
2256 arguments[i] = getValidType(arguments[i]); |
|
2257 } |
|
2258 } |
|
2259 |
|
2260 // Check exceptions... |
|
2261 |
|
2262 for (int i = 0; i < exceptions.length; i++) { |
|
2263 if (exceptions[i].getStatus() != STATUS_VALID) { |
|
2264 exceptions[i] = (ValueType)getValidType(exceptions[i]); |
|
2265 } |
|
2266 } |
|
2267 |
|
2268 // Check implExceptions... |
|
2269 |
|
2270 for (int i = 0; i < implExceptions.length; i++) { |
|
2271 if (implExceptions[i].getStatus() != STATUS_VALID) { |
|
2272 implExceptions[i] = (ValueType)getValidType(implExceptions[i]); |
|
2273 } |
|
2274 } |
|
2275 } |
|
2276 |
|
2277 /** |
|
2278 * Release all resources. |
|
2279 */ |
|
2280 public void destroy () { |
|
2281 if (memberDef != null) { |
|
2282 memberDef = null; |
|
2283 enclosing = null; |
|
2284 if (exceptions != null) { |
|
2285 for (int i = 0; i < exceptions.length; i++) { |
|
2286 if (exceptions[i] != null) exceptions[i].destroy(); |
|
2287 exceptions[i] = null; |
|
2288 } |
|
2289 exceptions = null; |
|
2290 } |
|
2291 |
|
2292 if (implExceptions != null) { |
|
2293 for (int i = 0; i < implExceptions.length; i++) { |
|
2294 if (implExceptions[i] != null) implExceptions[i].destroy(); |
|
2295 implExceptions[i] = null; |
|
2296 } |
|
2297 implExceptions = null; |
|
2298 } |
|
2299 |
|
2300 if (returnType != null) returnType.destroy(); |
|
2301 returnType = null; |
|
2302 |
|
2303 if (arguments != null) { |
|
2304 for (int i = 0; i < arguments.length; i++) { |
|
2305 if (arguments[i] != null) arguments[i].destroy(); |
|
2306 arguments[i] = null; |
|
2307 } |
|
2308 arguments = null; |
|
2309 } |
|
2310 |
|
2311 if (argumentNames != null) { |
|
2312 for (int i = 0; i < argumentNames.length; i++) { |
|
2313 argumentNames[i] = null; |
|
2314 } |
|
2315 argumentNames = null; |
|
2316 } |
|
2317 |
|
2318 vis = null; |
|
2319 name = null; |
|
2320 idlName = null; |
|
2321 stringRep = null; |
|
2322 attributeName = null; |
|
2323 declaredBy = null; |
|
2324 } |
|
2325 } |
|
2326 |
|
2327 private MemberDefinition memberDef; |
|
2328 private CompoundType enclosing; |
|
2329 private ValueType[] exceptions; |
|
2330 private ValueType[] implExceptions; |
|
2331 private Type returnType; |
|
2332 private Type[] arguments; |
|
2333 private String[] argumentNames; |
|
2334 private String vis; |
|
2335 private String name; |
|
2336 private String idlName; |
|
2337 private String stringRep = null; |
|
2338 private int attributeKind = ATTRIBUTE_NONE; |
|
2339 private String attributeName = null; |
|
2340 private int attributePairIndex = -1; |
|
2341 private Identifier declaredBy = null; |
|
2342 |
|
2343 /** |
|
2344 * Make up an argument name for the given type. |
|
2345 */ |
|
2346 private String makeArgName (int argNum, Type type) { |
|
2347 return "arg" + argNum; |
|
2348 } |
|
2349 |
|
2350 /** |
|
2351 * Create a new Method object corresponding to the given |
|
2352 * method definition. |
|
2353 */ |
|
2354 public Method (CompoundType enclosing, |
|
2355 MemberDefinition memberDef, |
|
2356 boolean quiet, |
|
2357 ContextStack stack) throws Exception { |
|
2358 |
|
2359 this.enclosing = enclosing; |
|
2360 this.memberDef = memberDef; |
|
2361 vis = getVisibilityString(memberDef); |
|
2362 idlName = null; // See setIDLName() |
|
2363 boolean valid = true; |
|
2364 declaredBy = memberDef.getClassDeclaration().getName(); |
|
2365 |
|
2366 // Set name... |
|
2367 |
|
2368 name = memberDef.getName().toString(); |
|
2369 |
|
2370 // Update the context... |
|
2371 |
|
2372 stack.setNewContextCode(ContextStack.METHOD); |
|
2373 stack.push(this); |
|
2374 |
|
2375 // Set return type... |
|
2376 |
|
2377 stack.setNewContextCode(ContextStack.METHOD_RETURN); |
|
2378 sun.tools.java.Type methodType = memberDef.getType(); |
|
2379 sun.tools.java.Type rtnType = methodType.getReturnType(); |
|
2380 |
|
2381 if (rtnType == sun.tools.java.Type.tVoid) { |
|
2382 returnType = PrimitiveType.forPrimitive(rtnType,stack); |
|
2383 } else { |
|
2384 returnType = makeType(rtnType,null,stack); |
|
2385 if (returnType == null || |
|
2386 !assertNotImpl(returnType,quiet,stack,enclosing,false)) { |
|
2387 valid = false; |
|
2388 failedConstraint(24,quiet,stack,enclosing.getName()); |
|
2389 } |
|
2390 } |
|
2391 |
|
2392 // Set arguments and argument names... |
|
2393 |
|
2394 stack.setNewContextCode(ContextStack.METHOD_ARGUMENT); |
|
2395 sun.tools.java.Type[] args = memberDef.getType().getArgumentTypes(); |
|
2396 arguments = new Type[args.length]; |
|
2397 argumentNames = new String[args.length]; |
|
2398 Vector origArgNames = memberDef.getArguments(); |
|
2399 |
|
2400 for (int i = 0; i < args.length; i++) { |
|
2401 Type type = null; |
|
2402 try { |
|
2403 type = makeType(args[i],null,stack); |
|
2404 } catch (Exception e) { |
|
2405 } |
|
2406 |
|
2407 if (type != null) { |
|
2408 if (!assertNotImpl(type,quiet,stack,enclosing,false)) { |
|
2409 valid = false; |
|
2410 } else { |
|
2411 arguments[i] = type; |
|
2412 if (origArgNames != null) { |
|
2413 LocalMember local = (LocalMember)origArgNames.elementAt(i+1); |
|
2414 argumentNames[i] = local.getName().toString(); |
|
2415 } else { |
|
2416 argumentNames[i] = makeArgName(i,type); |
|
2417 } |
|
2418 } |
|
2419 } else { |
|
2420 valid = false; |
|
2421 failedConstraint(25,false,stack,enclosing.getQualifiedName(),name); |
|
2422 } |
|
2423 } |
|
2424 |
|
2425 if (!valid) { |
|
2426 stack.pop(false); |
|
2427 throw new Exception(); |
|
2428 } |
|
2429 |
|
2430 // Set exceptions... |
|
2431 |
|
2432 try { |
|
2433 exceptions = enclosing.getMethodExceptions(memberDef,quiet,stack); |
|
2434 implExceptions = exceptions; |
|
2435 stack.pop(true); |
|
2436 } catch (Exception e) { |
|
2437 stack.pop(false); |
|
2438 throw new Exception(); |
|
2439 } |
|
2440 } |
|
2441 |
|
2442 /** |
|
2443 * Cloning is supported by returning a shallow copy of this object. |
|
2444 */ |
|
2445 protected Object clone() { |
|
2446 try { |
|
2447 return super.clone(); |
|
2448 } catch (CloneNotSupportedException e) { |
|
2449 throw new Error("clone failed"); |
|
2450 } |
|
2451 } |
|
2452 } |
|
2453 |
|
2454 //_____________________________________________________________________ |
|
2455 // Inner Class "Member" |
|
2456 //_____________________________________________________________________ |
|
2457 |
|
2458 /** |
|
2459 * An CompoundType.Member object wraps a Type and a value representing |
|
2460 * a data member, including constants. |
|
2461 */ |
|
2462 public class Member implements ContextElement, Cloneable { |
|
2463 |
|
2464 /** |
|
2465 * Return context element name. |
|
2466 */ |
|
2467 public String getElementName() { |
|
2468 return "\"" + getName() + "\""; |
|
2469 } |
|
2470 |
|
2471 /** |
|
2472 * Return the type of this member. |
|
2473 */ |
|
2474 public Type getType() { |
|
2475 return type; |
|
2476 } |
|
2477 |
|
2478 /** |
|
2479 * Return the name of this member. |
|
2480 */ |
|
2481 public String getName() { |
|
2482 return name; |
|
2483 } |
|
2484 |
|
2485 /** |
|
2486 * IDL_Naming |
|
2487 * Return the IDL name of this member. |
|
2488 */ |
|
2489 public String getIDLName() { |
|
2490 return idlName; |
|
2491 } |
|
2492 |
|
2493 /** |
|
2494 * Return the visibility (e.g. "public final") of this member. |
|
2495 */ |
|
2496 public String getVisibility() { |
|
2497 return vis; |
|
2498 } |
|
2499 |
|
2500 /** |
|
2501 * Methods to check various attributes. |
|
2502 */ |
|
2503 public boolean isPublic() { |
|
2504 return member.isPublic(); |
|
2505 } |
|
2506 |
|
2507 public boolean isPrivate() { |
|
2508 return member.isPrivate(); |
|
2509 } |
|
2510 |
|
2511 public boolean isStatic() { |
|
2512 return member.isStatic(); |
|
2513 } |
|
2514 |
|
2515 public boolean isFinal() { |
|
2516 return member.isFinal(); |
|
2517 } |
|
2518 |
|
2519 public boolean isTransient() { |
|
2520 if (forceTransient) return true; |
|
2521 return member.isTransient(); |
|
2522 } |
|
2523 |
|
2524 /** |
|
2525 * Return the value of this member. May be null. |
|
2526 */ |
|
2527 public String getValue() { |
|
2528 return value; |
|
2529 } |
|
2530 |
|
2531 /** |
|
2532 * Return true if this member represents an inner class declaration, |
|
2533 * false otherwise. |
|
2534 */ |
|
2535 public boolean isInnerClassDeclaration() { |
|
2536 return innerClassDecl; |
|
2537 } |
|
2538 |
|
2539 /** |
|
2540 * Return true if this member represents a constant. |
|
2541 */ |
|
2542 public boolean isConstant () { |
|
2543 return constant; |
|
2544 } |
|
2545 |
|
2546 /** |
|
2547 * Return the string representation of this constant. |
|
2548 */ |
|
2549 public String toString() { |
|
2550 |
|
2551 String result = type.toString(); |
|
2552 |
|
2553 if (value != null) { |
|
2554 result += (" = " + value); |
|
2555 } |
|
2556 |
|
2557 return result; |
|
2558 } |
|
2559 |
|
2560 /** |
|
2561 * Convert all invalid types to valid ones. |
|
2562 */ |
|
2563 protected void swapInvalidTypes () { |
|
2564 if (type.getStatus() != STATUS_VALID) { |
|
2565 type = getValidType(type); |
|
2566 } |
|
2567 } |
|
2568 |
|
2569 protected void setTransient() { |
|
2570 if (! isTransient()) { |
|
2571 forceTransient = true; |
|
2572 if (vis.length() > 0) { |
|
2573 vis = vis + " transient"; |
|
2574 } else { |
|
2575 vis = "transient"; |
|
2576 } |
|
2577 } |
|
2578 } |
|
2579 |
|
2580 protected MemberDefinition getMemberDefinition() { |
|
2581 return member; |
|
2582 } |
|
2583 |
|
2584 /** |
|
2585 * Release all resources. |
|
2586 */ |
|
2587 public void destroy () { |
|
2588 if (type != null) { |
|
2589 type.destroy(); |
|
2590 type = null; |
|
2591 vis = null; |
|
2592 value = null; |
|
2593 name = null; |
|
2594 idlName = null; |
|
2595 member = null; |
|
2596 } |
|
2597 } |
|
2598 |
|
2599 private Type type; |
|
2600 private String vis; |
|
2601 private String value; |
|
2602 private String name; |
|
2603 private String idlName; |
|
2604 private boolean innerClassDecl; |
|
2605 private boolean constant; |
|
2606 private MemberDefinition member; |
|
2607 private boolean forceTransient; |
|
2608 |
|
2609 /** |
|
2610 * Create a new Member object. |
|
2611 */ |
|
2612 public Member(MemberDefinition member, |
|
2613 String value, |
|
2614 ContextStack stack, |
|
2615 CompoundType enclosing) { |
|
2616 this.member = member; |
|
2617 this.value = value; |
|
2618 forceTransient = false; |
|
2619 innerClassDecl = member.getInnerClass() != null; |
|
2620 |
|
2621 // If we are not an inner class, finish initializing now. |
|
2622 // Otherwise, wait until outer class is finished, then |
|
2623 // call init to avoid potential recursion problems... |
|
2624 |
|
2625 if (!innerClassDecl) { |
|
2626 init (stack,enclosing); |
|
2627 } |
|
2628 } |
|
2629 |
|
2630 public void init (ContextStack stack, CompoundType enclosing) { |
|
2631 |
|
2632 constant = false; |
|
2633 name = member.getName().toString(); |
|
2634 vis = getVisibilityString(member); |
|
2635 idlName = null; |
|
2636 |
|
2637 // Add self to stack... |
|
2638 |
|
2639 int contextCode = ContextStack.MEMBER; |
|
2640 stack.setNewContextCode(contextCode); |
|
2641 |
|
2642 // Check for special contextCodes... |
|
2643 |
|
2644 if (member.isVariable()) { |
|
2645 if (value != null && member.isConstant()) { |
|
2646 contextCode = ContextStack.MEMBER_CONSTANT; |
|
2647 this.constant = true; |
|
2648 } else if (member.isStatic()) { |
|
2649 contextCode = ContextStack.MEMBER_STATIC; |
|
2650 } else if (member.isTransient()) { |
|
2651 contextCode = ContextStack.MEMBER_TRANSIENT; |
|
2652 } |
|
2653 } |
|
2654 |
|
2655 stack.setNewContextCode(contextCode); |
|
2656 stack.push(this); |
|
2657 |
|
2658 type = makeType(member.getType(),null,stack); |
|
2659 |
|
2660 if (type == null || |
|
2661 (!innerClassDecl && |
|
2662 !member.isStatic() && |
|
2663 !member.isTransient() && |
|
2664 !assertNotImpl(type,false,stack,enclosing,true))) { |
|
2665 stack.pop(false); |
|
2666 throw new CompilerError(""); |
|
2667 } |
|
2668 |
|
2669 // Clean up primitive constant values... |
|
2670 |
|
2671 if (constant && type.isPrimitive()) { |
|
2672 if (type.isType(TYPE_LONG) || type.isType(TYPE_FLOAT) || type.isType(TYPE_DOUBLE)) { |
|
2673 int length = value.length(); |
|
2674 char lastChar = value.charAt(length-1); |
|
2675 if (!Character.isDigit(lastChar)) { |
|
2676 this.value = value.substring(0,length-1); |
|
2677 } |
|
2678 } else if (type.isType(TYPE_BOOLEAN)) { |
|
2679 value = value.toUpperCase(); |
|
2680 } |
|
2681 } |
|
2682 if (constant && type.isType(TYPE_STRING)) { |
|
2683 value = "L" + value; |
|
2684 } |
|
2685 stack.pop(true); |
|
2686 } |
|
2687 |
|
2688 public void setIDLName (String name) { |
|
2689 this.idlName = name; |
|
2690 } |
|
2691 |
|
2692 /** |
|
2693 * Cloning is supported by returning a shallow copy of this object. |
|
2694 */ |
|
2695 protected Object clone() { |
|
2696 try { |
|
2697 return super.clone(); |
|
2698 } catch (CloneNotSupportedException e) { |
|
2699 throw new Error("clone failed"); |
|
2700 } |
|
2701 } |
|
2702 } |
|
2703 } |