ImplementationType.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 1998, 2007, 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 33package sun.rmi.rmic.iiop; 34 35import java.util.Vector; 36import sun.tools.java.CompilerError; 37import sun.tools.java.ClassNotFound; 38import sun.tools.java.ClassDefinition; 39import sun.tools.java.MemberDefinition; 40 41/** 42 * ImplementationType represents any non-special class which implements 43 * one or more interfaces which inherit from java.rmi.Remote. 44 * <p> 45 * The static forImplementation(...) method must be used to obtain an instance, 46 * and will return null if the ClassDefinition is non-conforming. 47 * 48 * @author Bryan Atsatt 49 */ 50public class ImplementationType extends ClassType { 51 52 //_____________________________________________________________________ 53 // Public Interfaces 54 //_____________________________________________________________________ 55 56 /** 57 * Create an ImplementationType for the given class. 58 * 59 * If the class is not a properly formed or if some other error occurs, the 60 * return value will be null, and errors will have been reported to the 61 * supplied BatchEnvironment. 62 */ 63 public static ImplementationType forImplementation(ClassDefinition classDef, 64 ContextStack stack, 65 boolean quiet) { 66 if (stack.anyErrors()) return null; 67 68 boolean doPop = false; 69 ImplementationType result = null; 70 71 try { 72 // Do we already have it? 73 74 sun.tools.java.Type theType = classDef.getType(); 75 Type existing = getType(theType,stack); 76 77 if (existing != null) { 78 79 if (!(existing instanceof ImplementationType)) return null; // False hit. 80 81 // Yep, so return it... 82 83 return (ImplementationType) existing; 84 85 } 86 87 // Could this be an implementation? 88 89 if (couldBeImplementation(quiet,stack,classDef)) { 90 91 // Yes, so check it... 92 93 ImplementationType it = new ImplementationType(stack, classDef); 94 putType(theType,it,stack); 95 stack.push(it); 96 doPop = true; 97 98 if (it.initialize(stack,quiet)) { 99 stack.pop(true); 100 result = it; 101 } else { 102 removeType(theType,stack); 103 stack.pop(false); 104 } 105 } 106 } catch (CompilerError e) { 107 if (doPop) stack.pop(false); 108 } 109 110 return result; 111 } 112 113 /** 114 * Return a string describing this type. 115 */ 116 public String getTypeDescription () { 117 return "Implementation"; 118 } 119 120 121 //_____________________________________________________________________ 122 // Internal Interfaces 123 //_____________________________________________________________________ 124 125 /** 126 * Create a ImplementationType instance for the given class. The resulting 127 * object is not yet completely initialized. 128 */ 129 private ImplementationType(ContextStack stack, ClassDefinition classDef) { 130 super(TYPE_IMPLEMENTATION | TM_CLASS | TM_COMPOUND,classDef,stack); // Use special constructor. 131 } 132 133 134 private static boolean couldBeImplementation(boolean quiet, ContextStack stack, 135 ClassDefinition classDef) { 136 boolean result = false; 137 BatchEnvironment env = stack.getEnv(); 138 139 try { 140 if (!classDef.isClass()) { 141 failedConstraint(17,quiet,stack,classDef.getName()); 142 } else { 143 result = env.defRemote.implementedBy(env, classDef.getClassDeclaration()); 144 if (!result) failedConstraint(8,quiet,stack,classDef.getName()); 145 } 146 } catch (ClassNotFound e) { 147 classNotFound(stack,e); 148 } 149 150 return result; 151 } 152 153 154 /** 155 * Initialize this instance. 156 */ 157 private boolean initialize (ContextStack stack, boolean quiet) { 158 159 boolean result = false; 160 ClassDefinition theClass = getClassDefinition(); 161 162 if (initParents(stack)) { 163 164 // Make up our collections... 165 166 Vector directInterfaces = new Vector(); 167 Vector directMethods = new Vector(); 168 169 // Check interfaces... 170 171 try { 172 if (addRemoteInterfaces(directInterfaces,true,stack) != null) { 173 174 boolean haveRemote = false; 175 176 // Get methods from all interfaces... 177 178 for (int i = 0; i < directInterfaces.size(); i++) { 179 InterfaceType theInt = (InterfaceType) directInterfaces.elementAt(i); 180 if (theInt.isType(TYPE_REMOTE) || 181 theInt.isType(TYPE_JAVA_RMI_REMOTE)) { 182 haveRemote = true; 183 } 184 185 copyRemoteMethods(theInt,directMethods); 186 } 187 188 // Make sure we have at least one remote interface... 189 190 if (!haveRemote) { 191 failedConstraint(8,quiet,stack,getQualifiedName()); 192 return false; 193 } 194 195 // Now check the methods to ensure we have the 196 // correct throws clauses... 197 198 if (checkMethods(theClass,directMethods,stack,quiet)) { 199 200 // We're ok, so pass 'em up... 201 202 result = initialize(directInterfaces,directMethods,null,stack,quiet); 203 } 204 } 205 } catch (ClassNotFound e) { 206 classNotFound(stack,e); 207 } 208 } 209 210 return result; 211 } 212 213 private static void copyRemoteMethods(InterfaceType type, Vector list) { 214 215 if (type.isType(TYPE_REMOTE)) { 216 217 // Copy all the unique methods from type... 218 219 Method[] allMethods = type.getMethods(); 220 221 for (int i = 0; i < allMethods.length; i++) { 222 Method theMethod = allMethods[i]; 223 224 if (!list.contains(theMethod)) { 225 list.addElement(theMethod); 226 } 227 } 228 229 // Now recurse thru all inherited interfaces... 230 231 InterfaceType[] allInterfaces = type.getInterfaces(); 232 233 for (int i = 0; i < allInterfaces.length; i++) { 234 copyRemoteMethods(allInterfaces[i],list); 235 } 236 } 237 } 238 239 // Walk all methods of the class, and for each that is already in 240 // the list, call setImplExceptions()... 241 242 private boolean checkMethods(ClassDefinition theClass, Vector list, 243 ContextStack stack, boolean quiet) { 244 245 // Convert vector to array... 246 247 Method[] methods = new Method[list.size()]; 248 list.copyInto(methods); 249 250 for (MemberDefinition member = theClass.getFirstMember(); 251 member != null; 252 member = member.getNextMember()) { 253 254 if (member.isMethod() && !member.isConstructor() 255 && !member.isInitializer()) { 256 257 // It's a method... 258 259 if (!updateExceptions(member,methods,stack,quiet)) { 260 return false; 261 } 262 } 263 } 264 return true; 265 } 266 267 private boolean updateExceptions (MemberDefinition implMethod, Method[] list, 268 ContextStack stack, boolean quiet) { 269 int length = list.length; 270 String implMethodSig = implMethod.toString(); 271 272 for (int i = 0; i < length; i++) { 273 Method existingMethod = list[i]; 274 MemberDefinition existing = existingMethod.getMemberDefinition(); 275 276 // Do we have a matching method? 277 278 if (implMethodSig.equals(existing.toString())) { 279 280 // Yes, so create exception list... 281 282 try { 283 ValueType[] implExcept = getMethodExceptions(implMethod,quiet,stack); 284 existingMethod.setImplExceptions(implExcept); 285 } catch (Exception e) { 286 return false; 287 } 288 } 289 } 290 return true; 291 } 292} 293