src/share/classes/sun/rmi/rmic/iiop/CompoundType.java

Fri, 14 Jun 2013 16:31:55 +0100

author
msheppar
date
Fri, 14 Jun 2013 16:31:55 +0100
changeset 512
81d694b1ab2f
parent 473
5845df371e25
child 553
5ca1b4c282b8
permissions
-rw-r--r--

8011157: Improve CORBA portablility
Summary: fix also reviewed by Alexander Fomin
Reviewed-by: alanb, coffeys, skoivu

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

mercurial