/* * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.jdi; import com.sun.jdi.*; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import java.util.Map; public class ArrayTypeImpl extends ReferenceTypeImpl implements ArrayType { protected ArrayTypeImpl(VirtualMachine aVm, long aRef) { super(aVm, aRef); } public ArrayReference newInstance(int length) { try { return (ArrayReference)JDWP.ArrayType.NewInstance. process(vm, this, length).newArray; } catch (JDWPException exc) { throw exc.toJDIException(); } } public String componentSignature() { return signature().substring(1); // Just skip the leading '[' } public String componentTypeName() { JNITypeParser parser = new JNITypeParser(componentSignature()); return parser.typeName(); } Type type() throws ClassNotLoadedException { return findType(componentSignature()); } void addVisibleMethods(Map<String, Method> map) { // arrays don't have methods } public List<Method> allMethods() { return new ArrayList<Method>(0); // arrays don't have methods } /* * Find the type object, if any, of a component type of this array. * The component type does not have to be immediate; e.g. this method * can be used to find the component Foo of Foo[][]. This method takes * advantage of the property that an array and its component must have * the same class loader. Since array set operations don't have an * implicit enclosing type like field and variable set operations, * this method is sometimes needed for proper type checking. */ Type findComponentType(String signature) throws ClassNotLoadedException { byte tag = (byte)signature.charAt(0); if (PacketStream.isObjectTag(tag)) { // It's a reference type JNITypeParser parser = new JNITypeParser(componentSignature()); List<ReferenceType> list = vm.classesByName(parser.typeName()); Iterator<ReferenceType> iter = list.iterator(); while (iter.hasNext()) { ReferenceType type = iter.next(); ClassLoaderReference cl = type.classLoader(); if ((cl == null)? (classLoader() == null) : (cl.equals(classLoader()))) { return type; } } // Component class has not yet been loaded throw new ClassNotLoadedException(componentTypeName()); } else { // It's a primitive type return vm.primitiveTypeMirror(tag); } } public Type componentType() throws ClassNotLoadedException { return findComponentType(componentSignature()); } static boolean isComponentAssignable(Type destination, Type source) { if (source instanceof PrimitiveType) { // Assignment of primitive arrays requires identical // component types. return source.equals(destination); } else { if (destination instanceof PrimitiveType) { return false; } ReferenceTypeImpl refSource = (ReferenceTypeImpl)source; ReferenceTypeImpl refDestination = (ReferenceTypeImpl)destination; // Assignment of object arrays requires availability // of widening conversion of component types return refSource.isAssignableTo(refDestination); } } /* * Return true if an instance of the given reference type * can be assigned to a variable of this type */ boolean isAssignableTo(ReferenceType destType) { if (destType instanceof ArrayType) { try { Type destComponentType = ((ArrayType)destType).componentType(); return isComponentAssignable(destComponentType, componentType()); } catch (ClassNotLoadedException e) { // One or both component types has not yet been // loaded => can't assign return false; } } else if (destType instanceof InterfaceType) { // Only valid InterfaceType assignee is Cloneable return destType.name().equals("java.lang.Cloneable"); } else { // Only valid ClassType assignee is Object return destType.name().equals("java.lang.Object"); } } List<ReferenceType> inheritedTypes() { return new ArrayList<ReferenceType>(0); } void getModifiers() { if (modifiers != -1) { return; } /* * For object arrays, the return values for Interface * Accessible.isPrivate(), Accessible.isProtected(), * etc... are the same as would be returned for the * component type. Fetch the modifier bits from the * component type and use those. * * For primitive arrays, the modifiers are always * VMModifiers.FINAL | VMModifiers.PUBLIC * * Reference com.sun.jdi.Accessible.java. */ try { Type t = componentType(); if (t instanceof PrimitiveType) { modifiers = VMModifiers.FINAL | VMModifiers.PUBLIC; } else { ReferenceType rt = (ReferenceType)t; modifiers = rt.modifiers(); } } catch (ClassNotLoadedException cnle) { cnle.printStackTrace(); } } public String toString() { return "array class " + name() + " (" + loaderString() + ")"; } /* * Save a pointless trip over the wire for these methods * which have undefined results for arrays. */ public boolean isPrepared() { return true; } public boolean isVerified() { return true; } public boolean isInitialized() { return true; } public boolean failedToInitialize() { return false; } public boolean isAbstract() { return false; } /* * Defined always to be true for arrays */ public boolean isFinal() { return true; } }