+ An abstract Evaluator
class is introduced, with two
+ evaluate
methods, which implementation should be registered
+ fro the desired language that compiles into bytecode.
+
evaluate
+ * methods and register using the annotation for the desired language.
+ *
+ * @author Martin Entlicher
+ *
+ * @since 2.21
+ */
+public abstract class Evaluator {
+
+ /**
+ * Evaluates given expression and provide the result.
+ * Override this method if the evaluation process can be performed
+ * using JPDA APIs.
+ *
+ * @param expression the expression to be evaluated
+ * @param csf call stack frame in which is the evaluation performed
+ * @param var an optional context variable or null
. When non-null,
+ * all methods and fields should be treated relative to the variable
+ * instance.
+ *
+ * @return current value of evaluated expression
+ */
+ public Variable evaluate (String expression, CallStackFrame csf, ObjectVariable var)
+ throws InvalidExpressionException {
+
+ class uoev extends UnsupportedOperationException implements Variable {
+ public String getType() {
+ throw new UnsupportedOperationException();
+ }
+ public String getValue() {
+ throw new UnsupportedOperationException();
+ }
+ }
+ return new uoev();
+ }
+
+ /**
+ * Evaluates given expression and provide the result.
+ * Override this method if the evaluation process needs direct access to JDI.
+ * Since JPDADebugger keeps track of running/suspended status of threads,
+ * it's required that the implementation calls methodInvokePreprocessor.run()
+ * before any call to JDI that cause the current thread (sf.thread()
) to resume -
+ * e.g. {@link ObjectReference#invokeMethod(com.sun.jdi.ThreadReference, com.sun.jdi.Method, java.util.List, int)},
+ * {@link ClassType#invokeMethod(com.sun.jdi.ThreadReference, com.sun.jdi.Method, java.util.List, int)},
+ * {@link ClassType#newInstance(com.sun.jdi.ThreadReference, com.sun.jdi.Method, java.util.List, int)}.
+ *
+ * @param expression the expression to be evaluated
+ * @param sf call stack frame in which is the evaluation performed
+ * @param stackDepth the depth of the stack frame. Note, that method
+ * invocation destroys the stack frame, therefore implementation
+ * class might want to re-create the stack frame via
+ * ThreadReference.frame(stackDepth)
, where
+ * ThreadReference
was retrieved from sf.thread()
+ * before sf
was destroyed.
+ * @param var an optional context object or null
. When non-null,
+ * all methods and fields should be treated relative to the object
+ * instance.
+ * @param canInvokeMethods hint, whether we can invoke methods. As soon as
+ * method invocation throws {@link UnsupportedOperationException},
+ * canInvokeMethods
becomes false next time. The evaluator
+ * should not try to invoke methods when canInvokeMethods
+ * is false
.
+ * @param methodInvokePreprocessor a Runnable that is required to be called
+ * before a call to JDI that cause the current thread
+ * (sf.thread()
) to resume - e.g.
+ * {@link ObjectReference#invokeMethod(com.sun.jdi.ThreadReference, com.sun.jdi.Method, java.util.List, int)},
+ * {@link ClassType#invokeMethod(com.sun.jdi.ThreadReference, com.sun.jdi.Method, java.util.List, int)},
+ * {@link ClassType#newInstance(com.sun.jdi.ThreadReference, com.sun.jdi.Method, java.util.List, int)}.
+ *
+ * @return current value of evaluated expression
+ */
+ public Value evaluate (String expression, StackFrame sf, int stackDepth,
+ ObjectReference var, boolean canInvokeMethods,
+ Runnable methodInvokePreprocessor) throws InvalidExpressionException {
+
+ class uoev extends UnsupportedOperationException implements Value {
+ public Type type() {
+ throw new UnsupportedOperationException();
+ }
+ public VirtualMachine virtualMachine() {
+ throw new UnsupportedOperationException();
+ }
+ }
+ return new uoev();
+ }
+
+ /**
+ * Declarative registration of Evaluator implementation.
+ * By marking the implementation class with this annotation,
+ * you automatically register that implementation for use by debugger.
+ * The class must be public and have a public constructor which takes
+ * no arguments or takes {@link ContextProvider} as an argument.
+ *
+ * @author Martin Entlicher
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE})
+ public @interface Registration {
+ /**
+ * The language to register this evaluator for.
+ */
+ String language();
+
+ }
+
+ static class ContextAware extends Evaluator implements ContextAwareServiceContextAwareService
based on layer.xml
+ * attribute values
+ *
+ * @param attrs attributes loaded from layer.xml
+ * @return new ContextAwareService
instance
+ */
+ static ContextAwareService createService(Map attrs) throws ClassNotFoundException {
+ String serviceName = (String) attrs.get(DebuggerProcessor.SERVICE_NAME);
+ return new ContextAware(serviceName);
+ }
+
+ }
+}