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