1 /* 2 * Copyright (c) 1998, 2011, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.jdi; 27 28 import com.sun.jdi.*; 29 30 import java.util.List; 31 import java.util.ArrayList; 32 import java.util.Iterator; 33 import java.util.Map; 34 import java.util.Set; 35 36 public class ArrayTypeImpl extends ReferenceTypeImpl 37 implements ArrayType 38 { 39 protected ArrayTypeImpl(VirtualMachine aVm, long aRef) { 40 super(aVm, aRef); 41 } 42 43 public ArrayReference newInstance(int length) { 44 try { 45 return (ArrayReference)JDWP.ArrayType.NewInstance. 46 process(vm, this, length).newArray; 47 } catch (JDWPException exc) { 48 throw exc.toJDIException(); 49 } 50 } 51 52 public String componentSignature() { 53 return signature().substring(1); // Just skip the leading '[' 54 } 55 56 public String componentTypeName() { 57 JNITypeParser parser = new JNITypeParser(componentSignature()); 58 return parser.typeName(); 59 } 60 61 Type type() throws ClassNotLoadedException { 62 return findType(componentSignature()); 63 } 64 65 @Override 66 void addVisibleMethods(Map<String, Method> map, Set<InterfaceType> seenInterfaces) { 67 // arrays don't have methods 68 } 69 70 public List<Method> allMethods() { 71 return new ArrayList<Method>(0); // arrays don't have methods 72 } 73 74 /* 75 * Find the type object, if any, of a component type of this array. 76 * The component type does not have to be immediate; e.g. this method 77 * can be used to find the component Foo of Foo[][]. This method takes 78 * advantage of the property that an array and its component must have 79 * the same class loader. Since array set operations don't have an 80 * implicit enclosing type like field and variable set operations, 81 * this method is sometimes needed for proper type checking. 82 */ 83 Type findComponentType(String signature) throws ClassNotLoadedException { 84 byte tag = (byte)signature.charAt(0); 85 if (PacketStream.isObjectTag(tag)) { 86 // It's a reference type 87 JNITypeParser parser = new JNITypeParser(componentSignature()); 88 List<ReferenceType> list = vm.classesByName(parser.typeName()); 89 Iterator<ReferenceType> iter = list.iterator(); 90 while (iter.hasNext()) { 91 ReferenceType type = iter.next(); 92 ClassLoaderReference cl = type.classLoader(); 93 if ((cl == null)? 94 (classLoader() == null) : 95 (cl.equals(classLoader()))) { 96 return type; 97 } 98 } 99 // Component class has not yet been loaded 100 throw new ClassNotLoadedException(componentTypeName()); 101 } else { 102 // It's a primitive type 103 return vm.primitiveTypeMirror(tag); 104 } 105 } 106 107 public Type componentType() throws ClassNotLoadedException { 108 return findComponentType(componentSignature()); 109 } 110 111 static boolean isComponentAssignable(Type destination, Type source) { 112 if (source instanceof PrimitiveType) { 113 // Assignment of primitive arrays requires identical 114 // component types. 115 return source.equals(destination); 116 } else { 117 if (destination instanceof PrimitiveType) { 118 return false; 119 } 120 121 ReferenceTypeImpl refSource = (ReferenceTypeImpl)source; 122 ReferenceTypeImpl refDestination = (ReferenceTypeImpl)destination; 123 // Assignment of object arrays requires availability 124 // of widening conversion of component types 125 return refSource.isAssignableTo(refDestination); 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 if (destType instanceof InterfaceType) { 144 // Only valid InterfaceType assignee is Cloneable 145 return destType.name().equals("java.lang.Cloneable"); 146 } else { 147 // Only valid ClassType assignee is Object 148 return destType.name().equals("java.lang.Object"); 149 } 150 } 151 152 List<ReferenceType> inheritedTypes() { 153 return new ArrayList<ReferenceType>(0); 154 } 155 156 void getModifiers() { 157 if (modifiers != -1) { 158 return; 159 } 160 /* 161 * For object arrays, the return values for Interface 162 * Accessible.isPrivate(), Accessible.isProtected(), 163 * etc... are the same as would be returned for the 164 * component type. Fetch the modifier bits from the 165 * component type and use those. 166 * 167 * For primitive arrays, the modifiers are always 168 * VMModifiers.FINAL | VMModifiers.PUBLIC 169 * 170 * Reference com.sun.jdi.Accessible.java. 171 */ 172 try { 173 Type t = componentType(); 174 if (t instanceof PrimitiveType) { 175 modifiers = VMModifiers.FINAL | VMModifiers.PUBLIC; 176 } else { 177 ReferenceType rt = (ReferenceType)t; 178 modifiers = rt.modifiers(); 179 } 180 } catch (ClassNotLoadedException cnle) { 181 cnle.printStackTrace(); 182 } 183 } 184 185 public String toString() { 186 return "array class " + name() + " (" + loaderString() + ")"; 187 } 188 189 /* 190 * Save a pointless trip over the wire for these methods 191 * which have undefined results for arrays. 192 */ 193 public boolean isPrepared() { return true; } 194 public boolean isVerified() { return true; } 195 public boolean isInitialized() { return true; } 196 public boolean failedToInitialize() { return false; } 197 public boolean isAbstract() { return false; } 198 199 /* 200 * Defined always to be true for arrays 201 */ 202 public boolean isFinal() { return true; } 203 204 /* 205 * Defined always to be false for arrays 206 */ 207 public boolean isStatic() { return false; } 208 } 209