package jetbrains.mps.debugger.java.runtime.evaluation;
/*Generated by MPS */
import jetbrains.mps.debugger.java.api.evaluation.EvaluationUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import com.intellij.openapi.application.ApplicationManager;
import com.sun.jdi.Value;
import com.sun.jdi.ArrayReference;
import org.jetbrains.annotations.NotNull;
import com.sun.jdi.ThreadReference;
import jetbrains.mps.debugger.java.api.evaluation.EvaluationException;
import com.sun.jdi.ClassType;
import com.sun.jdi.Method;
import java.util.List;
import jetbrains.mps.debugger.java.api.evaluation.proxies.MirrorUtil;
import com.sun.jdi.InvocationException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.VirtualMachine;
import jetbrains.mps.debugger.java.api.evaluation.InvalidEvaluatedExpressionException;
import com.sun.jdi.Field;
import com.sun.jdi.ReferenceType;
import org.jetbrains.annotations.Nullable;
import com.sun.jdi.Type;
import com.sun.jdi.ArrayType;
import com.sun.jdi.InterfaceType;
import jetbrains.mps.debugger.java.api.evaluation.proxies.IValueProxy;
import com.sun.jdi.StackFrame;
import com.sun.jdi.LocalVariable;
import com.sun.jdi.AbsentInformationException;
import jetbrains.mps.debugger.java.api.evaluation.proxies.IObjectValueProxy;
import jetbrains.mps.debugger.java.api.evaluation.proxies.IterableProxy;
import jetbrains.mps.debugger.java.api.evaluation.proxies.IArrayValueProxy;
import jetbrains.mps.debugger.java.api.evaluation.proxies.IterableArrayProxy;
import com.sun.jdi.ClassObjectReference;
import jetbrains.mps.debugger.java.api.evaluation.proxies.PrimitiveValueProxy;
import com.sun.jdi.PrimitiveValue;
import com.sun.jdi.BooleanValue;
import com.sun.jdi.ShortValue;
import com.sun.jdi.ByteValue;
import com.sun.jdi.CharValue;
import com.sun.jdi.DoubleValue;
import com.sun.jdi.FloatValue;
import com.sun.jdi.IntegerValue;
import com.sun.jdi.LongValue;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import com.sun.jdi.ObjectReference;
public class EvaluationUtilsImpl extends EvaluationUtils {
private static final Logger LOG = LogManager.getLogger(EvaluationUtilsImpl.class);
public EvaluationUtilsImpl() {
}
@Override
public void dispose() {
synchronized (LOCK) {
INSTANCE = null;
}
}
@Override
public void init() {
synchronized (LOCK) {
INSTANCE = this;
}
}
public void assertEvaluating() {
// todo real check
LOG.assertLog(!(ApplicationManager.getApplication().isDispatchThread()), "Evaluation should be invoked in evaluation command rather than in edt.");
}
@Override
public Value getArrayElementAt(ArrayReference array, int index) {
assertEvaluating();
return array.getValue(index);
}
private Value invokeStaticInternal(String className, String methodName, String jniSignature, @NotNull final ThreadReference threadReference, Object... args) throws EvaluationException {
assertEvaluating();
final ClassType referenceType = (ClassType) findClassType(className, threadReference.virtualMachine());
final Method method = findMethod(referenceType, methodName, jniSignature);
final List<Value> argValues = MirrorUtil.getInstance().getValues(threadReference.virtualMachine(), args);
return EvaluationUtils.handleInvocationExceptions(new EvaluationUtils.ThreadInvocatable<Value>(threadReference) {
@Override
public Value invoke() throws InvocationException, InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException {
return referenceType.invokeMethod(threadReference, method, argValues, 0);
}
});
}
private Value getStaticFieldValueInternal(String className, String fieldName, @NotNull final VirtualMachine machine) throws InvalidEvaluatedExpressionException {
assertEvaluating();
ClassType referenceType = (ClassType) findClassType(className, machine);
Field field = findField(referenceType, fieldName);
assert field.isStatic();
return referenceType.getValue(field);
}
private Value invokeConstructorInternal(String className, String jniSignature, @NotNull final ThreadReference threadReference, Object... args) throws EvaluationException {
// TODO duplication in code
assertEvaluating();
final ClassType referenceType = (ClassType) findClassType(className, threadReference.virtualMachine());
final Method constructor = findConstructor(referenceType, jniSignature);
final List<Value> argValues = MirrorUtil.getInstance().getValues(threadReference.virtualMachine(), args);
return EvaluationUtils.handleInvocationExceptions(new EvaluationUtils.ThreadInvocatable<Value>(threadReference) {
@Override
public Value invoke() throws InvocationException, InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException {
return referenceType.newInstance(threadReference, constructor, argValues, 0);
}
});
}
@NotNull
@Override
public Field findField(ClassType referenceType, String fieldName) throws InvalidEvaluatedExpressionException {
assertEvaluating();
Field field = referenceType.fieldByName(fieldName);
if (field == null) {
throw new InvalidEvaluatedExpressionException("Could not find field " + fieldName + " in " + referenceType.name() + ".");
}
return field;
}
@Override
public List<Field> findFields(ClassType referenceType) {
return referenceType.fields();
}
@NotNull
@Override
public Method findConstructor(ClassType referenceType, String jniSignature) throws InvalidEvaluatedExpressionException {
assertEvaluating();
List<Method> methods = referenceType.methodsByName("<init>", jniSignature);
if (methods.size() == 0) {
throw new InvalidEvaluatedExpressionException("Could not find constructor with signature " + jniSignature + " in " + referenceType.name() + ".");
}
Method constructor = null;
for (Method m : methods) {
if (m.isConstructor()) {
constructor = m;
break;
}
}
if (constructor == null) {
throw new InvalidEvaluatedExpressionException("Could not find constructor with signature " + jniSignature + " in " + referenceType.name() + ".");
}
return constructor;
}
@NotNull
@Override
public Method findMethod(ClassType referenceType, String methodsName, String jniSignature) throws InvalidEvaluatedExpressionException {
assertEvaluating();
List<Method> methods = referenceType.methodsByName(methodsName, jniSignature);
if (methods.size() == 0) {
throw new InvalidEvaluatedExpressionException("Could not find method " + methodsName + " with signature " + jniSignature + " in " + referenceType.name() + ".");
}
return methods.get(0);
}
@NotNull
@Override
public ReferenceType findClassType(String className, VirtualMachine virtualMachine) throws InvalidEvaluatedExpressionException {
assertEvaluating();
ReferenceType classType = findClassTypeSilently(className, virtualMachine);
if (classType == null) {
throw new InvalidEvaluatedExpressionException("Could not find class " + className + ".");
}
return classType;
}
@Nullable
@Override
public ReferenceType findClassTypeSilently(String className, VirtualMachine virtualMachine) throws InvalidEvaluatedExpressionException {
assertEvaluating();
// apparently, classesByName works for both dot and slash (ie for java.lang.String and for java/lang/String)
// even for java.lang/String
List<ReferenceType> classes = virtualMachine.classesByName(className);
if (classes.size() == 0) {
return null;
}
return classes.get(0);
}
@Nullable
@Override
public Type findTypeSilently(String typeSignature, VirtualMachine virtualMachine) throws InvalidEvaluatedExpressionException {
if ("Z".equals(typeSignature)) {
return virtualMachine.mirrorOf(true).type();
} else if ("B".equals(typeSignature)) {
return virtualMachine.mirrorOf((byte) 1).type();
} else if ("C".equals(typeSignature)) {
return virtualMachine.mirrorOf('C').type();
} else if ("S".equals(typeSignature)) {
return virtualMachine.mirrorOf((short) 1).type();
} else if ("I".equals(typeSignature)) {
return virtualMachine.mirrorOf(1).type();
} else if ("J".equals(typeSignature)) {
return virtualMachine.mirrorOf((long) 1).type();
} else if ("F".equals(typeSignature)) {
return virtualMachine.mirrorOf((float) 1.0).type();
} else if ("D".equals(typeSignature)) {
return virtualMachine.mirrorOf((double) 1.0).type();
} else if (typeSignature.startsWith("[")) {
try {
return createArrayProxy(EvaluationUtils.JAVA_LANG_OBJECT, virtualMachine, 0).getJDIValue().type();
} catch (EvaluationException e) {
LOG.error(e);
return findClassTypeSilently(JAVA_LANG_OBJECT, virtualMachine);
}
}
return findClassTypeSilently(typeSignature.substring(1, typeSignature.length() - 1), virtualMachine);
}
@Override
public boolean instanceOf(final Type what, final String jniSignature, final VirtualMachine machine) throws EvaluationException {
assertEvaluating();
if (jniSignature.equals(EvaluationUtils.JAVA_LANG_OBJECT)) {
// o_O
// this is kinda not true when what is of primitive type
return true;
}
if (what.signature().equals(jniSignature)) {
return true;
}
return EvaluationUtils.handleInvocationExceptions(new EvaluationUtils.Invocatable<Boolean>() {
@Override
public Boolean invoke() throws InvocationException, InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, EvaluationException {
if (jniSignature.startsWith("[")) {
if (!((what instanceof ArrayType))) {
return false;
}
return EvaluationUtilsImpl.this.instanceOf(((ArrayType) what).componentType(), jniSignature.substring(1), machine);
} else
if (jniSignature.startsWith("L")) {
if (!((what instanceof ClassType))) {
return false;
}
ReferenceType type = findClassTypeSilently(jniSignature.substring(1, jniSignature.length() - 1), machine);
if (type == null) {
return false;
}
ClassType whatClassType = (ClassType) what;
if (type instanceof InterfaceType) {
return whatClassType.allInterfaces().contains((InterfaceType) type);
}
do {
if (type.equals(whatClassType)) {
return true;
}
whatClassType = whatClassType.superclass();
} while (whatClassType != null);
return false;
}
return false;
}
});
}
@NotNull
@Override
public IValueProxy getVariableValue(String varName, StackFrame stackFrame) throws EvaluationException {
assert stackFrame != null;
assertEvaluating();
LocalVariable localVariable;
try {
localVariable = stackFrame.visibleVariableByName(varName);
} catch (AbsentInformationException ex) {
throw new EvaluationException(ex);
}
if (localVariable == null) {
throw new EvaluationException("variable not found: " + varName);
}
Value v = stackFrame.getValue(localVariable);
return MirrorUtil.getInstance().getValueProxy(v);
}
@NotNull
@Override
public <T extends IValueProxy> Iterable<T> toIterableProxy(IObjectValueProxy valueProxy, ThreadReference threadReference) {
assertEvaluating();
return new IterableProxy<T>(valueProxy, threadReference);
}
@NotNull
@Override
public <T extends IValueProxy> Iterable<T> toIterableProxyFromArray(IArrayValueProxy valueProxy) {
assertEvaluating();
return new IterableArrayProxy<T>(valueProxy);
}
@NotNull
@Override
public IValueProxy invokeStaticMethod(String className, String name, String jniSignature, ThreadReference threadReference, Object... args) throws EvaluationException {
assertEvaluating();
return MirrorUtil.getInstance().getValueProxy(invokeStaticInternal(className, name, jniSignature, threadReference, args));
}
@NotNull
@Override
public IValueProxy getStaticField(String className, String fieldName, VirtualMachine machine) throws InvalidEvaluatedExpressionException {
assertEvaluating();
return MirrorUtil.getInstance().getValueProxy(getStaticFieldValueInternal(className, fieldName, machine));
}
@NotNull
@Override
public IObjectValueProxy invokeConstructorProxy(String className, String jniSignature, ThreadReference threadReference, Object... args) throws EvaluationException {
assertEvaluating();
return (IObjectValueProxy) MirrorUtil.getInstance().getValueProxy(invokeConstructorInternal(className, jniSignature, threadReference, args));
}
@Override
public IArrayValueProxy createArrayProxy(String className, VirtualMachine machine, int size) throws EvaluationException {
assertEvaluating();
List<ReferenceType> referenceTypes = machine.classesByName(className + "[");
if (referenceTypes.isEmpty()) {
throw new EvaluationException("Could not find type " + className + "[]");
}
ArrayType arrayType = null;
for (ReferenceType referenceType : referenceTypes) {
if (referenceType instanceof ArrayType) {
arrayType = (ArrayType) referenceType;
break;
}
}
if (arrayType == null) {
throw new EvaluationException("Could not find type " + className + "[]");
}
ArrayReference arrayReference = arrayType.newInstance(size);
return (IArrayValueProxy) MirrorUtil.getInstance().getValueProxy(arrayReference);
}
@Override
public final IArrayValueProxy createArrayProxyFromValues(String className, VirtualMachine machine, Object... args) throws EvaluationException {
assertEvaluating();
if (args == null) {
// array of one element -- null
return createArrayProxy(className, machine, 1);
} else {
IArrayValueProxy array = createArrayProxy(className, machine, args.length);
List<Value> values = MirrorUtil.getInstance().getValues(machine, args);
for (int i = 0; i < values.size(); i++) {
array.setElement(values.get(i), i);
}
return array;
}
}
@NotNull
@Override
public IValueProxy getClass(String className, VirtualMachine machine) throws InvalidEvaluatedExpressionException {
assertEvaluating();
ClassType referenceType = (ClassType) findClassType(className, machine);
ClassObjectReference classObject = referenceType.classObject();
return MirrorUtil.getInstance().getValueProxy(classObject);
}
@NotNull
@Override
public IObjectValueProxy boxValue(PrimitiveValueProxy primitiveValueProxy, ThreadReference threadReference) throws EvaluationException {
assertEvaluating();
PrimitiveValue primitiveValue = primitiveValueProxy.getPrimitiveValue();
if (primitiveValue instanceof BooleanValue) {
return (IObjectValueProxy) invokeStaticMethod(Boolean.class.getName(), "valueOf", "(Z)Ljava/lang/Boolean;", threadReference, primitiveValue.booleanValue());
}
if (primitiveValue instanceof ShortValue) {
return (IObjectValueProxy) invokeStaticMethod(Short.class.getName(), "valueOf", "(S)Ljava/lang/Short;", threadReference, primitiveValue.shortValue());
}
if (primitiveValue instanceof ByteValue) {
return (IObjectValueProxy) invokeStaticMethod(Byte.class.getName(), "valueOf", "(B)Ljava/lang/Byte;", threadReference, primitiveValue.byteValue());
}
if (primitiveValue instanceof CharValue) {
return (IObjectValueProxy) invokeStaticMethod(Character.class.getName(), "valueOf", "(C)Ljava/lang/Character;", threadReference, primitiveValue.charValue());
}
if (primitiveValue instanceof DoubleValue) {
return (IObjectValueProxy) invokeStaticMethod(Double.class.getName(), "valueOf", "(D)Ljava/lang/Double;", threadReference, primitiveValue.doubleValue());
}
if (primitiveValue instanceof FloatValue) {
return (IObjectValueProxy) invokeStaticMethod(Float.class.getName(), "valueOf", "(F)Ljava/lang/Float;", threadReference, primitiveValue.floatValue());
}
if (primitiveValue instanceof IntegerValue) {
return (IObjectValueProxy) invokeStaticMethod(Integer.class.getName(), "valueOf", "(I)Ljava/lang/Integer;", threadReference, primitiveValue.intValue());
}
if (primitiveValue instanceof LongValue) {
return (IObjectValueProxy) invokeStaticMethod(Long.class.getName(), "valueOf", "(J)Ljava/lang/Long;", threadReference, primitiveValue.longValue());
}
throw new UnsupportedOperationException("Cant box " + primitiveValue);
}
@Override
public PrimitiveValueProxy unboxValue(IObjectValueProxy valueProxy, ThreadReference threadReference) throws EvaluationException {
assertEvaluating();
Type type = valueProxy.getJDIValue().type();
if (type.name().equals(Boolean.class.getName())) {
return (PrimitiveValueProxy) valueProxy.invokeMethod("booleanValue", "()Z", threadReference);
}
if (type.name().equals(Short.class.getName())) {
return (PrimitiveValueProxy) valueProxy.invokeMethod("shortValue", "()S", threadReference);
}
if (type.name().equals(Byte.class.getName())) {
return (PrimitiveValueProxy) valueProxy.invokeMethod("byteValue", "()B", threadReference);
}
if (type.name().equals(Character.class.getName())) {
return (PrimitiveValueProxy) valueProxy.invokeMethod("charValue", "()C", threadReference);
}
if (type.name().equals(Double.class.getName())) {
return (PrimitiveValueProxy) valueProxy.invokeMethod("doubleValue", "()D", threadReference);
}
if (type.name().equals(Float.class.getName())) {
return (PrimitiveValueProxy) valueProxy.invokeMethod("floatValue", "()F", threadReference);
}
if (type.name().equals(Integer.class.getName())) {
return (PrimitiveValueProxy) valueProxy.invokeMethod("intValue", "()I", threadReference);
}
if (type.name().equals(Long.class.getName())) {
return (PrimitiveValueProxy) valueProxy.invokeMethod("longValue", "()J", threadReference);
}
throw new UnsupportedOperationException("Cant unbox value of type" + type);
}
@Override
public String getStringPresentation(@NotNull final Value value, @NotNull final ThreadReference threadReference) {
assertEvaluating();
try {
return MirrorUtil.getInstance().getJavaValue(value).toString();
} catch (UnsupportedOperationException e) {
if (value instanceof ArrayReference) {
ArrayReference array = (ArrayReference) value;
StringBuffer buffer = new StringBuffer();
buffer.append("[");
int length = array.length();
int i = 0;
for (Value item : ListSequence.fromList(array.getValues())) {
buffer.append(getStringPresentation(item, threadReference));
if (i < length - 1) {
buffer.append(", ");
}
i++;
}
buffer.append("]");
return buffer.toString();
} else {
return EvaluationUtils.consumeEvaluationException(new EvaluationUtils.EvaluationInvocatable<String>() {
@Override
public String invoke() throws EvaluationException {
ObjectReference object = (ObjectReference) value;
IObjectValueProxy valueProxy = (IObjectValueProxy) MirrorUtil.getInstance().getValueProxy(object);
IValueProxy result = valueProxy.invokeMethod("toString", "()Ljava/lang/String;", threadReference);
return getStringPresentation(result.getJDIValue(), threadReference);
}
}, null);
}
}
}
}