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 
  29 import sun.jvm.hotspot.oops.ArrayKlass;
  30 import sun.jvm.hotspot.oops.InstanceKlass;
  31 import sun.jvm.hotspot.oops.ObjArrayKlass;
  32 import sun.jvm.hotspot.oops.TypeArrayKlass;
  33 import sun.jvm.hotspot.oops.Klass;
  34 import sun.jvm.hotspot.oops.Instance;
  35 import sun.jvm.hotspot.oops.Symbol;
  36 import java.util.List;
  37 import java.util.ArrayList;
  38 import java.util.Iterator;
  39 import java.util.Map;
  40 
  41 public class ArrayTypeImpl extends ReferenceTypeImpl implements ArrayType {
  42   protected ArrayTypeImpl(VirtualMachine aVm, ArrayKlass aRef) {
  43         super(aVm, aRef);
  44     }
  45 
  46     public ArrayReference newInstance(int length) {
  47         vm.throwNotReadOnlyException("ArrayType.newInstance(int)");
  48         return null;
  49     }
  50 
  51     public String componentSignature() {
  52         return signature().substring(1); // Just skip the leading '['
  53     }
  54 
  55     public String componentTypeName() {
  56         JNITypeParser parser = new JNITypeParser(componentSignature());
  57         return parser.typeName();
  58     }
  59 
  60     public ClassLoaderReference classLoader() {
  61         if (ref() instanceof TypeArrayKlass) {
  62             // primitive array klasses are loaded by bootstrap loader
  63             return null;
  64         } else {
  65             Klass bottomKlass = ((ObjArrayKlass)ref()).getBottomKlass();
  66             if (bottomKlass instanceof TypeArrayKlass) {
  67                 // multidimensional primitive array klasses are loaded by bootstrap loader
  68                 return null;
  69             } else {
  70                 // class loader of any other obj array klass is same as the loader
  71                 // that loaded the bottom InstanceKlass
  72                 Instance xx = (Instance)(((InstanceKlass) bottomKlass).getClassLoader());
  73                 return vm.classLoaderMirror(xx);
  74             }
  75         }
  76     }
  77 
  78     void addVisibleMethods(Map methodMap) {
  79         // arrays don't have methods
  80     }
  81 
  82     List getAllMethods() {
  83         // arrays don't have methods
  84         // JLS says arrays have methods of java.lang.Object. But
  85         // JVMDI-JDI returns zero size list. We do the same here
  86         // for consistency.
  87         return new ArrayList(0);
  88     }
  89 
  90     /*
  91      * Find the type object, if any, of a component type of this array.
  92      * The component type does not have to be immediate; e.g. this method
  93      * can be used to find the component Foo of Foo[][].
  94      */
  95     public Type componentType() throws ClassNotLoadedException {
  96         ArrayKlass k = (ArrayKlass) ref();
  97         if (k instanceof ObjArrayKlass) {
  98             Klass elementKlass = ((ObjArrayKlass)k).getElementKlass();
  99             if (elementKlass == null) {
 100                 throw new ClassNotLoadedException(componentSignature());
 101             } else {
 102                 return vm.referenceType(elementKlass);
 103             }
 104         } else {
 105             // It's a primitive type
 106             return vm.primitiveTypeMirror(signature().charAt(1));
 107         }
 108     }
 109 
 110     static boolean isComponentAssignable(Type destination, Type source) {
 111         if (source instanceof PrimitiveType) {
 112             // Assignment of primitive arrays requires identical
 113             // component types.
 114             return source.equals(destination);
 115         } else {
 116            if (destination instanceof PrimitiveType) {
 117                 return false;
 118             }
 119 
 120             ReferenceTypeImpl refSource = (ReferenceTypeImpl)source;
 121             ReferenceTypeImpl refDestination = (ReferenceTypeImpl)destination;
 122             // Assignment of object arrays requires availability
 123             // of widening conversion of component types
 124             return refSource.isAssignableTo(refDestination);
 125         }
 126     }
 127 
 128 
 129     /*
 130     * Return true if an instance of the  given reference type
 131     * can be assigned to a variable of this type
 132     */
 133     boolean isAssignableTo(ReferenceType destType) {
 134         if (destType instanceof ArrayType) {
 135             try {
 136                 Type destComponentType = ((ArrayType)destType).componentType();
 137                 return isComponentAssignable(destComponentType, componentType());
 138             } catch (ClassNotLoadedException e) {
 139                 // One or both component types has not yet been
 140                 // loaded => can't assign
 141                 return false;
 142             }
 143         } else {
 144             Symbol typeName = ((ReferenceTypeImpl)destType).typeNameAsSymbol();
 145             if (destType instanceof InterfaceType) {
 146                 // Every array type implements java.io.Serializable and
 147                 // java.lang.Cloneable. fixme in JVMDI-JDI, includes only
 148                 // Cloneable but not Serializable.
 149                 return typeName.equals(vm.javaLangCloneable()) ||
 150                        typeName.equals(vm.javaIoSerializable());
 151             } else {
 152                 // Only valid ClassType assignee is Object
 153                 return typeName.equals(vm.javaLangObject());
 154             }
 155         }
 156     }
 157 
 158     List inheritedTypes() {
 159         // arrays are derived from java.lang.Object and
 160         // B[] is derived from A[] if B is derived from A.
 161         // But JVMDI-JDI returns zero sized list and we do the
 162         // same for consistency.
 163         return new ArrayList(0);
 164     }
 165 
 166     int getModifiers() {
 167         /*
 168          * For object arrays, the return values for Interface
 169          * Accessible.isPrivate(), Accessible.isProtected(),
 170          * etc... are the same as would be returned for the
 171          * component type.  Fetch the modifier bits from the
 172          * component type and use those.
 173          *
 174          * For primitive arrays, the modifiers are always
 175          *   VMModifiers.FINAL | VMModifiers.PUBLIC
 176          *
 177          * Reference com.sun.jdi.Accessible.java.
 178          */
 179         try {
 180             Type t = componentType();
 181             if (t instanceof PrimitiveType) {
 182                 return VMModifiers.FINAL | VMModifiers.PUBLIC;
 183             } else {
 184                 ReferenceType rt = (ReferenceType)t;
 185                 return rt.modifiers();
 186             }
 187         } catch (ClassNotLoadedException cnle) {
 188             cnle.printStackTrace();
 189         }
 190         return -1;
 191     }
 192 
 193     public String toString() {
 194        return "array class " + name() + " (" + loaderString() + ")";
 195     }
 196 
 197     /*
 198      * Save a pointless trip over the wire for these methods
 199      * which have undefined results for arrays.
 200      */
 201     public boolean isPrepared() { return true; }
 202     public boolean isVerified() { return true; }
 203     public boolean isInitialized() { return true; }
 204     public boolean failedToInitialize() { return false; }
 205     public boolean isAbstract() { return false; }
 206 
 207     /*
 208      * Defined always to be true for arrays
 209      */
 210     public boolean isFinal() { return true; }
 211 }