/******************************************************************************* * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Jesper Steen Møller <jesper@selskabet.org> - Bug 430839 *******************************************************************************/ package org.eclipse.jdi.internal; import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.jdi.internal.jdwp.JdwpClassObjectID; import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket; import org.eclipse.jdi.internal.jdwp.JdwpID; import org.eclipse.jdi.internal.jdwp.JdwpInterfaceID; import com.sun.jdi.ClassNotLoadedException; import com.sun.jdi.ClassNotPreparedException; import com.sun.jdi.ClassType; import com.sun.jdi.IncompatibleThreadStateException; import com.sun.jdi.InterfaceType; import com.sun.jdi.InvalidTypeException; import com.sun.jdi.InvocationException; import com.sun.jdi.Method; import com.sun.jdi.ReferenceType; import com.sun.jdi.ThreadReference; import com.sun.jdi.Value; /** * this class implements the corresponding interfaces declared by the JDI * specification. See the com.sun.jdi package for more information. * */ public class InterfaceTypeImpl extends ReferenceTypeImpl implements InterfaceType { /** JDWP Tag. */ public static final byte typeTag = JdwpID.TYPE_TAG_INTERFACE; /** * Creates new InterfaceTypeImpl. */ public InterfaceTypeImpl(VirtualMachineImpl vmImpl, JdwpInterfaceID interfaceID) { super("InterfaceType", vmImpl, interfaceID); //$NON-NLS-1$ } /** * Creates new InterfaceTypeImpl. */ public InterfaceTypeImpl(VirtualMachineImpl vmImpl, JdwpInterfaceID interfaceID, String signature, String genericSignature) { super("InterfaceType", vmImpl, interfaceID, signature, genericSignature); //$NON-NLS-1$ } /** * @return Create a null value instance of the type. */ @Override public Value createNullValue() { return new ClassObjectReferenceImpl(virtualMachineImpl(), new JdwpClassObjectID(virtualMachineImpl())); } /** * @return Returns type tag. */ @Override public byte typeTag() { return typeTag; } /** * Flushes all stored Jdwp results. */ @Override public void flushStoredJdwpResults() { super.flushStoredJdwpResults(); // For all reference types that have this interface cached, this cache must be // undone. Iterator<Object> itr = virtualMachineImpl().allCachedRefTypes(); while (itr.hasNext()) { ReferenceTypeImpl refType = (ReferenceTypeImpl) itr.next(); if (refType.fInterfaces != null && refType.fInterfaces.contains(this)) { refType.flushStoredJdwpResults(); } } } /* (non-Javadoc) * @see com.sun.jdi.InterfaceType#implementors() */ @Override public List<ClassType> implementors() { // Note that this information should not be cached. List<ClassType> implementors = new ArrayList<>(); Iterator<ReferenceType> itr = virtualMachineImpl().allRefTypes(); while (itr.hasNext()) { ReferenceType refType = itr.next(); if (refType instanceof ClassTypeImpl) { try { ClassTypeImpl classType = (ClassTypeImpl) refType; List<InterfaceType> interfaces = classType.interfaces(); if (interfaces.contains(this)) { implementors.add(classType); } } catch (ClassNotPreparedException e) { continue; } } } return implementors; } /* (non-Javadoc) * @see com.sun.jdi.InterfaceType#subinterfaces() */ @Override public List<InterfaceType> subinterfaces() { // Note that this information should not be cached. List<InterfaceType> implementors = new ArrayList<>(); Iterator<ReferenceType> itr = virtualMachineImpl().allRefTypes(); while (itr.hasNext()) { try { ReferenceType refType = itr.next(); if (refType instanceof InterfaceTypeImpl) { InterfaceTypeImpl interFaceType = (InterfaceTypeImpl) refType; List<InterfaceType> interfaces = interFaceType.superinterfaces(); if (interfaces.contains(this)) { implementors.add(interFaceType); } } } catch (ClassNotPreparedException e) { continue; } } return implementors; } /* (non-Javadoc) * @see com.sun.jdi.InterfaceType#superinterfaces() */ @Override public List<InterfaceType> superinterfaces() { return interfaces(); } /* (non-Javadoc) * @see com.sun.jdi.InterfaceType#invokeMethod(com.sun.jdi.ThreadReference, com.sun.jdi.Method, java.util.List, int) */ @Override public Value invokeMethod(ThreadReference thread, Method method, List<? extends Value> arguments, int options) throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException { return invokeMethod(thread, method, arguments, options, JdwpCommandPacket.IT_INVOKE_METHOD); } /** * @return Returns a the single non-abstract Method visible from this class * that has the given name and signature. */ public Method concreteMethodByName(String name, String signature) { /* * Recursion is used to find the method: The methods of its own (own * methods() command); The methods of it's superclass. */ Iterator<Method> methods = methods().iterator(); Method method; while (methods.hasNext()) { method = methods.next(); if (method.name().equals(name) && method.signature().equals(signature)) { if (method.isAbstract()) { return null; } return method; } } if (superinterfaces() != null) { for (InterfaceType superi: superinterfaces()) { Method foundMethod = ((InterfaceTypeImpl)superi).concreteMethodByName(name, signature); if (foundMethod != null) { return foundMethod; } } } return null; } /** * @return Returns true if this type has been initialized. */ @Override public boolean isInitialized() { return isPrepared(); } /** * @return Reads ID and returns known ReferenceTypeImpl with that ID, or if * ID is unknown a newly created ReferenceTypeImpl. */ public static InterfaceTypeImpl read(MirrorImpl target, DataInputStream in) throws IOException { VirtualMachineImpl vmImpl = target.virtualMachineImpl(); JdwpInterfaceID ID = new JdwpInterfaceID(vmImpl); ID.read(in); if (target.fVerboseWriter != null) { target.fVerboseWriter.println("interfaceType", ID.value()); //$NON-NLS-1$ } if (ID.isNull()) { return null; } InterfaceTypeImpl mirror = (InterfaceTypeImpl) vmImpl .getCachedMirror(ID); if (mirror == null) { mirror = new InterfaceTypeImpl(vmImpl, ID); vmImpl.addCachedMirror(mirror); } return mirror; } /** * @return Reads ID and returns known ReferenceTypeImpl with that ID, or if * ID is unknown a newly created ReferenceTypeImpl. */ public static InterfaceTypeImpl readWithSignature(MirrorImpl target, boolean withGenericSignature, DataInputStream in) throws IOException { VirtualMachineImpl vmImpl = target.virtualMachineImpl(); JdwpInterfaceID ID = new JdwpInterfaceID(vmImpl); ID.read(in); if (target.fVerboseWriter != null) { target.fVerboseWriter.println("interfaceType", ID.value()); //$NON-NLS-1$ } String signature = target.readString("signature", in); //$NON-NLS-1$ String genericSignature = null; if (withGenericSignature) { genericSignature = target.readString("generic signature", in); //$NON-NLS-1$ } if (ID.isNull()) { return null; } InterfaceTypeImpl mirror = (InterfaceTypeImpl) vmImpl .getCachedMirror(ID); if (mirror == null) { mirror = new InterfaceTypeImpl(vmImpl, ID); vmImpl.addCachedMirror(mirror); } mirror.setSignature(signature); mirror.setGenericSignature(genericSignature); return mirror; } }