1 /* 2 * Copyright (c) 2002, 2004, 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.Iterator; 31 import java.util.List; 32 import java.util.Map; 33 import java.util.Set; 34 35 import sun.jvm.hotspot.oops.InstanceKlass; 36 37 import com.sun.jdi.ClassNotPreparedException; 38 import com.sun.jdi.ClassType; 39 import com.sun.jdi.InterfaceType; 40 import com.sun.jdi.Method; 41 import com.sun.jdi.ReferenceType; 42 import com.sun.jdi.VirtualMachine; 43 44 public class InterfaceTypeImpl extends ReferenceTypeImpl 45 implements InterfaceType { 46 private SoftReference superInterfacesCache = null; 47 private SoftReference subInterfacesCache = null; 48 private SoftReference implementorsCache = null; 49 50 protected InterfaceTypeImpl(VirtualMachine aVm, InstanceKlass aRef) { 51 super(aVm, aRef); 52 } 53 54 public List superinterfaces() throws ClassNotPreparedException { 55 List superinterfaces = (superInterfacesCache != null)? (List) superInterfacesCache.get() : null; 56 if (superinterfaces == null) { 57 checkPrepared(); 58 superinterfaces = Collections.unmodifiableList(getInterfaces()); 59 superInterfacesCache = new SoftReference(superinterfaces); 60 } 61 return superinterfaces; 62 } 63 64 public List subinterfaces() { 65 List subinterfaces = (subInterfacesCache != null)? (List) subInterfacesCache.get() : null; 66 if (subinterfaces == null) { 67 List all = vm.allClasses(); 68 subinterfaces = new ArrayList(); 69 Iterator iter = all.iterator(); 70 while (iter.hasNext()) { 71 ReferenceType refType = (ReferenceType)iter.next(); 72 if (refType instanceof InterfaceType) { 73 InterfaceType interfaze = (InterfaceType)refType; 74 if (interfaze.isPrepared() && interfaze.superinterfaces().contains(this)) { 75 subinterfaces.add(interfaze); 76 } 77 } 78 } 79 subinterfaces = Collections.unmodifiableList(subinterfaces); 80 subInterfacesCache = new SoftReference(subinterfaces); 81 } 82 return subinterfaces; 83 } 84 85 public List implementors() { 86 List implementors = (implementorsCache != null)? (List) implementorsCache.get() : null; 87 if (implementors == null) { 88 List all = vm.allClasses(); 89 implementors = new ArrayList(); 90 Iterator iter = all.iterator(); 91 while (iter.hasNext()) { 92 ReferenceType refType = (ReferenceType)iter.next(); 93 if (refType instanceof ClassType) { 94 ClassType clazz = (ClassType)refType; 95 if (clazz.isPrepared() && clazz.interfaces().contains(this)) { 96 implementors.add(clazz); 97 } 98 } 99 } 100 implementors = Collections.unmodifiableList(implementors); 101 implementorsCache = new SoftReference(implementors); 102 } 103 return implementors; 104 } 105 106 @Override 107 void addVisibleMethods(Map<String, Method> methodMap, Set<InterfaceType> seenInterfaces) { 108 /* 109 * Add methods from 110 * parent types first, so that the methods in this class will 111 * overwrite them in the hash table 112 */ 113 Iterator<InterfaceType> iter = superinterfaces().iterator(); 114 while (iter.hasNext()) { 115 InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); 116 if (!seenInterfaces.contains(interfaze)) { 117 interfaze.addVisibleMethods(methodMap, seenInterfaces); 118 seenInterfaces.add(interfaze); 119 } 120 } 121 122 addToMethodMap(methodMap, methods()); 123 } 124 125 List getAllMethods() { 126 ArrayList list = new ArrayList(methods()); 127 /* 128 * It's more efficient if don't do this 129 * recursively. 130 */ 131 List interfaces = allSuperinterfaces(); 132 Iterator iter = interfaces.iterator(); 133 while (iter.hasNext()) { 134 InterfaceType interfaze = (InterfaceType)iter.next(); 135 list.addAll(interfaze.methods()); 136 } 137 138 return list; 139 } 140 141 List allSuperinterfaces() { 142 ArrayList list = new ArrayList(); 143 addSuperinterfaces(list); 144 return list; 145 } 146 147 void addSuperinterfaces(List list) { 148 /* 149 * This code is a little strange because it 150 * builds the list with a more suitable order than the 151 * depth-first approach a normal recursive solution would 152 * take. Instead, all direct superinterfaces precede all 153 * indirect ones. 154 */ 155 156 /* 157 * Get a list of direct superinterfaces that's not already in the 158 * list being built. 159 */ 160 List immediate = new ArrayList(superinterfaces()); 161 Iterator iter = immediate.iterator(); 162 while (iter.hasNext()) { 163 InterfaceType interfaze = (InterfaceType)iter.next(); 164 if (list.contains(interfaze)) { 165 iter.remove(); 166 } 167 } 168 169 /* 170 * Add all new direct superinterfaces 171 */ 172 list.addAll(immediate); 173 174 /* 175 * Recurse for all new direct superinterfaces. 176 */ 177 iter = immediate.iterator(); 178 while (iter.hasNext()) { 179 InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); 180 interfaze.addSuperinterfaces(list); 181 } 182 } 183 184 boolean isAssignableTo(ReferenceType type) { 185 186 // Exact match? 187 if (this.equals(type)) { 188 return true; 189 } else { 190 // Try superinterfaces. 191 List supers = superinterfaces(); 192 Iterator iter = supers.iterator(); 193 while (iter.hasNext()) { 194 InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); 195 if (interfaze.isAssignableTo(type)) { 196 return true; 197 } 198 } 199 200 return false; 201 } 202 } 203 204 List inheritedTypes() { 205 return superinterfaces(); 206 } 207 208 public boolean isInitialized() { 209 return isPrepared(); 210 } 211 212 public String toString() { 213 return "interface " + name() + " (" + loaderString() + ")"; 214 } 215 }