blob: 65137b9a79cf86901829801d191f91e67b232f6c [file] [log] [blame]
/*******************************************************************************
* 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;
}
}