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 }