1 /* 2 * Copyright (c) 2002, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.jdi; 26 27 import java.lang.ref.SoftReference; 28 import java.util.ArrayList; 29 import java.util.Collections; 30 import java.util.HashSet; 31 import java.util.Iterator; 32 import java.util.List; 33 import java.util.Map; 34 import java.util.Set; 35 36 import sun.jvm.hotspot.oops.InstanceKlass; 37 38 import com.sun.jdi.ClassNotLoadedException; 39 import com.sun.jdi.ClassType; 40 import com.sun.jdi.Field; 41 import com.sun.jdi.IncompatibleThreadStateException; 42 import com.sun.jdi.InterfaceType; 43 import com.sun.jdi.InvalidTypeException; 44 import com.sun.jdi.InvocationException; 45 import com.sun.jdi.Method; 46 import com.sun.jdi.ObjectReference; 47 import com.sun.jdi.ReferenceType; 48 import com.sun.jdi.ThreadReference; 49 import com.sun.jdi.Value; 50 import com.sun.jdi.VirtualMachine; 51 52 public class ClassTypeImpl extends ReferenceTypeImpl 53 implements ClassType 54 { 55 private SoftReference interfacesCache = null; 56 private SoftReference allInterfacesCache = null; 57 private SoftReference subclassesCache = null; 58 59 protected ClassTypeImpl(VirtualMachine aVm, InstanceKlass aRef) { 60 super(aVm, aRef); 61 } 62 63 public ClassType superclass() { 64 InstanceKlass kk = (InstanceKlass)ref().getSuper(); 65 if (kk == null) { 66 return null; 67 } 68 return (ClassType) vm.referenceType(kk); 69 } 70 71 public List interfaces() { 72 List interfaces = (interfacesCache != null)? (List) interfacesCache.get() : null; 73 if (interfaces == null) { 74 checkPrepared(); 75 interfaces = Collections.unmodifiableList(getInterfaces()); 76 interfacesCache = new SoftReference(interfaces); 77 } 78 return interfaces; 79 } 80 81 void addInterfaces(List list) { 82 List immediate = interfaces(); 83 84 HashSet hashList = new HashSet(list); 85 hashList.addAll(immediate); 86 list.clear(); 87 list.addAll(hashList); 88 89 Iterator iter = immediate.iterator(); 90 while (iter.hasNext()) { 91 InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); 92 interfaze.addSuperinterfaces(list); 93 } 94 95 ClassTypeImpl superclass = (ClassTypeImpl)superclass(); 96 if (superclass != null) { 97 superclass.addInterfaces(list); 98 } 99 } 100 101 public List allInterfaces() { 102 List allinterfaces = (allInterfacesCache != null)? (List) allInterfacesCache.get() : null; 103 if (allinterfaces == null) { 104 checkPrepared(); 105 allinterfaces = new ArrayList(); 106 addInterfaces(allinterfaces); 107 allinterfaces = Collections.unmodifiableList(allinterfaces); 108 allInterfacesCache = new SoftReference(allinterfaces); 109 } 110 return allinterfaces; 111 } 112 113 public List subclasses() { 114 List subclasses = (subclassesCache != null)? (List) subclassesCache.get() : null; 115 if (subclasses == null) { 116 List all = vm.allClasses(); 117 subclasses = new ArrayList(0); 118 Iterator iter = all.iterator(); 119 while (iter.hasNext()) { 120 ReferenceType refType = (ReferenceType)iter.next(); 121 if (refType instanceof ClassType) { 122 ClassType clazz = (ClassType)refType; 123 ClassType superclass = clazz.superclass(); 124 if ((superclass != null) && superclass.equals(this)) { 125 subclasses.add(refType); 126 } 127 } 128 } 129 subclasses = Collections.unmodifiableList(subclasses); 130 subclassesCache = new SoftReference(subclasses); 131 } 132 return subclasses; 133 } 134 135 public Method concreteMethodByName(String name, String signature) { 136 checkPrepared(); 137 List methods = visibleMethods(); 138 Method method = null; 139 Iterator iter = methods.iterator(); 140 while (iter.hasNext()) { 141 Method candidate = (Method)iter.next(); 142 if (candidate.name().equals(name) && 143 candidate.signature().equals(signature) && 144 !candidate.isAbstract()) { 145 146 method = candidate; 147 break; 148 } 149 } 150 return method; 151 } 152 153 List getAllMethods() { 154 ArrayList list = new ArrayList(methods()); 155 ClassType clazz = superclass(); 156 while (clazz != null) { 157 list.addAll(clazz.methods()); 158 clazz = clazz.superclass(); 159 } 160 /* 161 * Avoid duplicate checking on each method by iterating through 162 * duplicate-free allInterfaces() rather than recursing 163 */ 164 Iterator iter = allInterfaces().iterator(); 165 while (iter.hasNext()) { 166 InterfaceType interfaze = (InterfaceType)iter.next(); 167 list.addAll(interfaze.methods()); 168 } 169 return list; 170 } 171 172 List inheritedTypes() { 173 List inherited = new ArrayList(interfaces()); 174 if (superclass() != null) { 175 inherited.add(0, superclass()); /* insert at front */ 176 } 177 return inherited; 178 } 179 180 public boolean isEnum() { 181 ClassTypeImpl superclass = (ClassTypeImpl) superclass(); 182 if (superclass != null) { 183 return superclass.typeNameAsSymbol().equals(vm.javaLangEnum()); 184 } else { 185 return false; 186 } 187 } 188 189 public void setValue(Field field, Value value) 190 throws InvalidTypeException, ClassNotLoadedException { 191 vm.throwNotReadOnlyException("ClassType.setValue(...)"); 192 } 193 194 195 public Value invokeMethod(ThreadReference threadIntf, Method methodIntf, 196 List arguments, int options) 197 throws InvalidTypeException, 198 ClassNotLoadedException, 199 IncompatibleThreadStateException, 200 InvocationException { 201 vm.throwNotReadOnlyException("ClassType.invokeMethod(...)"); 202 return null; 203 } 204 205 public ObjectReference newInstance(ThreadReference threadIntf, 206 Method methodIntf, 207 List arguments, int options) 208 throws InvalidTypeException, 209 ClassNotLoadedException, 210 IncompatibleThreadStateException, 211 InvocationException { 212 vm.throwNotReadOnlyException("ClassType.newInstance(...)"); 213 return null; 214 } 215 216 @Override 217 void addVisibleMethods(Map<String, Method> methodMap, Set<InterfaceType> seenInterfaces) { 218 /* 219 * Add methods from 220 * parent types first, so that the methods in this class will 221 * overwrite them in the hash table 222 */ 223 224 Iterator<InterfaceType> iter = interfaces().iterator(); 225 while (iter.hasNext()) { 226 InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); 227 if (!seenInterfaces.contains(interfaze)) { 228 interfaze.addVisibleMethods(methodMap, seenInterfaces); 229 seenInterfaces.add(interfaze); 230 } 231 } 232 233 ClassTypeImpl clazz = (ClassTypeImpl)superclass(); 234 if (clazz != null) { 235 clazz.addVisibleMethods(methodMap, seenInterfaces); 236 } 237 238 addToMethodMap(methodMap, methods()); 239 } 240 241 boolean isAssignableTo(ReferenceType type) { 242 ClassTypeImpl superclazz = (ClassTypeImpl)superclass(); 243 if (this.equals(type)) { 244 return true; 245 } else if ((superclazz != null) && superclazz.isAssignableTo(type)) { 246 return true; 247 } else { 248 List interfaces = interfaces(); 249 Iterator iter = interfaces.iterator(); 250 while (iter.hasNext()) { 251 InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); 252 if (interfaze.isAssignableTo(type)) { 253 return true; 254 } 255 } 256 return false; 257 } 258 } 259 260 public String toString() { 261 return "class " + name() + "(" + loaderString() + ")"; 262 } 263 }