|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package com.sun.tools.jdi; |
|
|
|
import com.sun.jdi.*; |
|
|
|
import java.util.*; |
|
|
|
final public class ClassTypeImpl extends InvokableTypeImpl |
|
implements ClassType |
|
{ |
|
private static class IResult implements InvocationResult { |
|
final private JDWP.ClassType.InvokeMethod rslt; |
|
|
|
public IResult(JDWP.ClassType.InvokeMethod rslt) { |
|
this.rslt = rslt; |
|
} |
|
|
|
@Override |
|
public ObjectReferenceImpl getException() { |
|
return rslt.exception; |
|
} |
|
|
|
@Override |
|
public ValueImpl getResult() { |
|
return rslt.returnValue; |
|
} |
|
} |
|
|
|
private boolean cachedSuperclass = false; |
|
private ClassType superclass = null; |
|
private int lastLine = -1; |
|
private List<InterfaceType> interfaces = null; |
|
|
|
protected ClassTypeImpl(VirtualMachine aVm,long aRef) { |
|
super(aVm, aRef); |
|
} |
|
|
|
public ClassType superclass() { |
|
if(!cachedSuperclass) { |
|
ClassTypeImpl sup = null; |
|
try { |
|
sup = JDWP.ClassType.Superclass. |
|
process(vm, this).superclass; |
|
} catch (JDWPException exc) { |
|
throw exc.toJDIException(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
if (sup != null) { |
|
superclass = sup; |
|
} |
|
cachedSuperclass = true; |
|
} |
|
|
|
return superclass; |
|
} |
|
|
|
@Override |
|
public List<InterfaceType> interfaces() { |
|
if (interfaces == null) { |
|
interfaces = getInterfaces(); |
|
} |
|
return interfaces; |
|
} |
|
|
|
@Override |
|
public List<InterfaceType> allInterfaces() { |
|
return getAllInterfaces(); |
|
} |
|
|
|
public List<ClassType> subclasses() { |
|
List<ClassType> subs = new ArrayList<ClassType>(); |
|
for (ReferenceType refType : vm.allClasses()) { |
|
if (refType instanceof ClassType) { |
|
ClassType clazz = (ClassType)refType; |
|
ClassType superclass = clazz.superclass(); |
|
if ((superclass != null) && superclass.equals(this)) { |
|
subs.add((ClassType)refType); |
|
} |
|
} |
|
} |
|
|
|
return subs; |
|
} |
|
|
|
public boolean isEnum() { |
|
ClassType superclass = superclass(); |
|
if (superclass != null && |
|
superclass.name().equals("java.lang.Enum")) { |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
public void setValue(Field field, Value value) |
|
throws InvalidTypeException, ClassNotLoadedException { |
|
|
|
validateMirror(field); |
|
validateMirrorOrNull(value); |
|
validateFieldSet(field); |
|
|
|
|
|
if(!field.isStatic()) { |
|
throw new IllegalArgumentException( |
|
"Must set non-static field through an instance"); |
|
} |
|
|
|
try { |
|
JDWP.ClassType.SetValues.FieldValue[] values = |
|
new JDWP.ClassType.SetValues.FieldValue[1]; |
|
values[0] = new JDWP.ClassType.SetValues.FieldValue( |
|
((FieldImpl)field).ref(), |
|
|
|
ValueImpl.prepareForAssignment(value, (FieldImpl)field)); |
|
|
|
try { |
|
JDWP.ClassType.SetValues.process(vm, this, values); |
|
} catch (JDWPException exc) { |
|
throw exc.toJDIException(); |
|
} |
|
} catch (ClassNotLoadedException e) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
if (value != null) { |
|
throw e; |
|
} |
|
} |
|
} |
|
|
|
PacketStream sendNewInstanceCommand(final ThreadReferenceImpl thread, |
|
final MethodImpl method, |
|
final ValueImpl[] args, |
|
final int options) { |
|
CommandSender sender = |
|
new CommandSender() { |
|
public PacketStream send() { |
|
return JDWP.ClassType.NewInstance.enqueueCommand( |
|
vm, ClassTypeImpl.this, thread, |
|
method.ref(), args, options); |
|
} |
|
}; |
|
|
|
PacketStream stream; |
|
if ((options & INVOKE_SINGLE_THREADED) != 0) { |
|
stream = thread.sendResumingCommand(sender); |
|
} else { |
|
stream = vm.sendResumingCommand(sender); |
|
} |
|
return stream; |
|
} |
|
|
|
public ObjectReference newInstance(ThreadReference threadIntf, |
|
Method methodIntf, |
|
List<? extends Value> origArguments, |
|
int options) |
|
throws InvalidTypeException, |
|
ClassNotLoadedException, |
|
IncompatibleThreadStateException, |
|
InvocationException { |
|
validateMirror(threadIntf); |
|
validateMirror(methodIntf); |
|
validateMirrorsOrNulls(origArguments); |
|
|
|
MethodImpl method = (MethodImpl)methodIntf; |
|
ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf; |
|
|
|
validateConstructorInvocation(method); |
|
|
|
List<Value> arguments = method.validateAndPrepareArgumentsForInvoke( |
|
origArguments); |
|
ValueImpl[] args = arguments.toArray(new ValueImpl[0]); |
|
JDWP.ClassType.NewInstance ret = null; |
|
try { |
|
PacketStream stream = |
|
sendNewInstanceCommand(thread, method, args, options); |
|
ret = JDWP.ClassType.NewInstance.waitForReply(vm, stream); |
|
} catch (JDWPException exc) { |
|
if (exc.errorCode() == JDWP.Error.INVALID_THREAD) { |
|
throw new IncompatibleThreadStateException(); |
|
} else { |
|
throw exc.toJDIException(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
if ((options & INVOKE_SINGLE_THREADED) == 0) { |
|
vm.notifySuspend(); |
|
} |
|
|
|
if (ret.exception != null) { |
|
throw new InvocationException(ret.exception); |
|
} else { |
|
return ret.newObject; |
|
} |
|
} |
|
|
|
public Method concreteMethodByName(String name, String signature) { |
|
Method method = null; |
|
for (Method candidate : visibleMethods()) { |
|
if (candidate.name().equals(name) && |
|
candidate.signature().equals(signature) && |
|
!candidate.isAbstract()) { |
|
|
|
method = candidate; |
|
break; |
|
} |
|
} |
|
return method; |
|
} |
|
|
|
void validateConstructorInvocation(Method method) |
|
throws InvalidTypeException, |
|
InvocationException { |
|
|
|
|
|
*/ |
|
ReferenceTypeImpl declType = (ReferenceTypeImpl)method.declaringType(); |
|
if (!declType.equals(this)) { |
|
throw new IllegalArgumentException("Invalid constructor"); |
|
} |
|
|
|
|
|
|
|
*/ |
|
if (!method.isConstructor()) { |
|
throw new IllegalArgumentException("Cannot create instance with non-constructor"); |
|
} |
|
} |
|
|
|
|
|
public String toString() { |
|
return "class " + name() + " (" + loaderString() + ")"; |
|
} |
|
|
|
@Override |
|
CommandSender getInvokeMethodSender(ThreadReferenceImpl thread, |
|
MethodImpl method, |
|
ValueImpl[] args, |
|
int options) { |
|
return () -> |
|
JDWP.ClassType.InvokeMethod.enqueueCommand(vm, |
|
ClassTypeImpl.this, |
|
thread, |
|
method.ref(), |
|
args, |
|
options); |
|
} |
|
|
|
@Override |
|
InvocationResult waitForReply(PacketStream stream) throws JDWPException { |
|
return new IResult(JDWP.ClassType.InvokeMethod.waitForReply(vm, stream)); |
|
} |
|
|
|
@Override |
|
boolean canInvoke(Method method) { |
|
|
|
return ((ReferenceTypeImpl)method.declaringType()).isAssignableFrom(this); |
|
} |
|
} |