package jetbrains.mps.debugger.java.api.evaluation; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import com.sun.jdi.Value; import com.sun.jdi.ArrayReference; import org.jetbrains.annotations.NotNull; import com.sun.jdi.Field; import com.sun.jdi.ClassType; import java.util.List; import com.sun.jdi.Method; import com.sun.jdi.ReferenceType; import com.sun.jdi.VirtualMachine; import org.jetbrains.annotations.Nullable; import com.sun.jdi.Type; import jetbrains.mps.debugger.java.api.evaluation.proxies.IValueProxy; import com.sun.jdi.StackFrame; import jetbrains.mps.debugger.java.api.evaluation.proxies.IObjectValueProxy; import com.sun.jdi.ThreadReference; import jetbrains.mps.debugger.java.api.evaluation.proxies.IArrayValueProxy; import jetbrains.mps.debugger.java.api.evaluation.proxies.PrimitiveValueProxy; import com.sun.jdi.InvocationException; import com.sun.jdi.InvalidTypeException; import com.sun.jdi.IncompatibleThreadStateException; import org.apache.log4j.Level; import com.sun.jdi.ClassNotLoadedException; public abstract class EvaluationUtils { private static final Logger LOG = LogManager.getLogger(EvaluationUtils.class); protected static EvaluationUtils INSTANCE; protected static final Object LOCK = new Object(); public static final String JAVA_LANG_OBJECT = "Ljava/lang/Object;"; public EvaluationUtils() { } public abstract void init(); public abstract void dispose(); public abstract Value getArrayElementAt(ArrayReference array, int index); @NotNull public abstract Field findField(ClassType referenceType, String fieldName) throws InvalidEvaluatedExpressionException; public abstract List<Field> findFields(ClassType referenceType); @NotNull public abstract Method findConstructor(ClassType referenceType, String jniSignature) throws InvalidEvaluatedExpressionException; @NotNull public abstract Method findMethod(ClassType referenceType, String methodsName, String jniSignature) throws InvalidEvaluatedExpressionException; @NotNull public abstract ReferenceType findClassType(String className, VirtualMachine virtualMachine) throws InvalidEvaluatedExpressionException; @Nullable public abstract ReferenceType findClassTypeSilently(String className, VirtualMachine virtualMachine) throws InvalidEvaluatedExpressionException; @Nullable public abstract Type findTypeSilently(String className, VirtualMachine virtualMachine) throws InvalidEvaluatedExpressionException; public abstract boolean instanceOf(final Type what, final String jniSignature, final VirtualMachine machine) throws EvaluationException; @NotNull public abstract IValueProxy getVariableValue(String varName, StackFrame stackFrame) throws EvaluationException; @NotNull public abstract <T extends IValueProxy> Iterable<T> toIterableProxy(IObjectValueProxy valueProxy, ThreadReference threadReference); @NotNull public abstract <T extends IValueProxy> Iterable<T> toIterableProxyFromArray(IArrayValueProxy valueProxy); @NotNull public abstract IValueProxy invokeStaticMethod(String className, String name, String jniSignature, ThreadReference threadReference, Object... args) throws EvaluationException; @NotNull public abstract IValueProxy getStaticField(String className, String fieldName, VirtualMachine machine) throws InvalidEvaluatedExpressionException; @NotNull public abstract IObjectValueProxy invokeConstructorProxy(String className, String jniSignature, ThreadReference threadReference, Object... args) throws EvaluationException; public abstract IArrayValueProxy createArrayProxy(String className, VirtualMachine machine, int size) throws EvaluationException; public abstract IArrayValueProxy createArrayProxyFromValues(String className, VirtualMachine machine, Object... args) throws EvaluationException; @NotNull public abstract IValueProxy getClass(String className, VirtualMachine machine) throws InvalidEvaluatedExpressionException; @NotNull public abstract IObjectValueProxy boxValue(PrimitiveValueProxy primitiveValueProxy, ThreadReference threadReference) throws EvaluationException; public abstract PrimitiveValueProxy unboxValue(IObjectValueProxy valueProxy, ThreadReference threadReference) throws EvaluationException; public abstract String getStringPresentation(@NotNull Value value, ThreadReference reference); public static EvaluationUtils getInstance() { synchronized (LOCK) { return INSTANCE; } } /** * Do something and convert jdi exceptions to evaluation exception * * @param invocatable what to invoke * @param <T> result * @throws EvaluationException wrapper of the original exception * @return result */ public static <T> T handleInvocationExceptions(EvaluationUtils.Invocatable<T> invocatable) throws EvaluationException { try { return invocatable.invoke(); } catch (InvocationException e) { if (invocatable instanceof EvaluationUtils.ThreadInvocatable) { throw new TargetVMEvaluationException(e, ((EvaluationUtils.ThreadInvocatable) invocatable).getCurrentThreadReference()); } else { throw new TargetVMEvaluationException(e); } } catch (IllegalArgumentException e) { throw new InvalidEvaluatedExpressionException(e); } catch (InvalidTypeException e) { throw new InvalidEvaluatedExpressionException(e); } catch (RuntimeException e) { if (e.getClass().getName().startsWith("com.sun.jdi")) { throw new JdiRuntimeExceptionEvaluationException(e); } throw new EvaluationRuntimeException(e); } catch (IncompatibleThreadStateException e) { if (invocatable instanceof EvaluationUtils.ThreadInvocatable) { throw new EvaluationException("Incompatible thread " + ((EvaluationUtils.ThreadInvocatable) invocatable).getCurrentThreadReference().name(), e); } else { throw new EvaluationException(e); } } catch (Throwable t) { throw new EvaluationException(t); } } /** * When we need to call something from ui which throws evaluation exception. * For example when we update the tree. * * @param invocatable the action to invoke * @param failure value to return in case of failure * @param <T> result * @return result */ public static <T> T consumeEvaluationException(EvaluationUtils.EvaluationInvocatable<T> invocatable, T failure) { try { return invocatable.invoke(); } catch (InvalidEvaluatedExpressionException e) { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("", e); } } catch (InvocationTargetEvaluationException e) { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("", e); } } catch (TargetVMEvaluationException e) { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("", e); } } catch (JdiRuntimeExceptionEvaluationException e) { if (LOG.isInfoEnabled()) { LOG.info("", e); } } catch (EvaluationException e) { if (LOG.isDebugEnabled()) { LOG.debug("", e); } } return failure; } /** * Something that can throw one of jdi exceptions or EvaluationException * * @param <T> result */ public interface Invocatable<T> { T invoke() throws InvocationException, InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, EvaluationException; } /** * Something that can throw EvaluationException * * @param <T> result */ public interface EvaluationInvocatable<T> { T invoke() throws EvaluationException; } /** * Some action which also has information about thread reference where it happenes. * * @param <T> result */ public static abstract class ThreadInvocatable<T> implements EvaluationUtils.Invocatable<T> { private final ThreadReference myThreadReference; public ThreadInvocatable(ThreadReference threadReference) { myThreadReference = threadReference; } public ThreadReference getCurrentThreadReference() { return myThreadReference; } } }