### Eclipse Workspace Patch 1.0
#P org.eclipse.jdt.debug
Index: eval/org/eclipse/jdt/internal/debug/eval/ast/engine/RuntimeContext.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/RuntimeContext.java,v
retrieving revision 1.8
diff -u -r1.8 RuntimeContext.java
--- eval/org/eclipse/jdt/internal/debug/eval/ast/engine/RuntimeContext.java 4 Aug 2005 18:58:14 -0000 1.8
+++ eval/org/eclipse/jdt/internal/debug/eval/ast/engine/RuntimeContext.java 18 Sep 2009 18:48:07 -0000
@@ -37,7 +37,7 @@
* @return a new runtime context
*/
public RuntimeContext(IJavaProject project, IJavaStackFrame frame) {
- super(project);
+ super(project, (IJavaThread) frame.getThread());
setFrame(frame);
}
@@ -89,13 +89,6 @@
*/
private void setFrame(IJavaStackFrame frame) {
fFrame = frame;
- }
-
- /**
- * @see IRuntimeContext#getThread()
- */
- public IJavaThread getThread() {
- return (IJavaThread)getFrame().getThread();
}
/**
@@ -104,6 +97,13 @@
public boolean isConstructor() throws CoreException {
return getFrame().isConstructor();
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#isStatic()
+ */
+ public boolean isStatic() throws CoreException {
+ return getFrame().isStatic();
+ }
}
Index: eval/org/eclipse/jdt/internal/debug/eval/ast/engine/AbstractRuntimeContext.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/AbstractRuntimeContext.java,v
retrieving revision 1.6
diff -u -r1.6 AbstractRuntimeContext.java
--- eval/org/eclipse/jdt/internal/debug/eval/ast/engine/AbstractRuntimeContext.java 8 May 2006 20:23:01 -0000 1.6
+++ eval/org/eclipse/jdt/internal/debug/eval/ast/engine/AbstractRuntimeContext.java 18 Sep 2009 18:48:07 -0000
@@ -10,8 +10,6 @@
*******************************************************************************/
package org.eclipse.jdt.internal.debug.eval.ast.engine;
-import com.ibm.icu.text.MessageFormat;
-
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
@@ -19,11 +17,14 @@
import org.eclipse.jdt.debug.core.IJavaClassObject;
import org.eclipse.jdt.debug.core.IJavaClassType;
import org.eclipse.jdt.debug.core.IJavaObject;
+import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
+import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.InstructionsEvaluationMessages;
+import com.ibm.icu.text.MessageFormat;
import com.sun.jdi.InvocationException;
/**
@@ -44,6 +45,11 @@
* Cache of java.lang.Class type
*/
private IJavaClassType fJavaLangClass;
+
+ /**
+ * Thread to perform message sends in
+ */
+ private IJavaThread fThread;
/**
* Java project context
@@ -55,8 +61,9 @@
public static final String FOR_NAME_SIGNATURE= "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"; //$NON-NLS-1$
- public AbstractRuntimeContext(IJavaProject project) {
+ public AbstractRuntimeContext(IJavaProject project, IJavaThread thread) {
fProject = project;
+ fThread = thread;
}
/**
@@ -70,6 +77,16 @@
protected IJavaObject getClassLoaderObject() throws CoreException {
if (fClassLoader == null) {
fClassLoader = getReceivingType().getClassLoaderObject();
+ //loader is null for those classes loaded by the bootstrap loader
+ if (fClassLoader == null) {
+ IJavaObject child = ((JDIDebugTarget)getVM()).getSomeClassLoader();
+ IJavaObject parent = child;
+ while (parent != null && !parent.isNull()) {
+ child = parent;
+ parent = (IJavaObject)child.sendMessage("getParent", "()Ljava/lang/ClassLoader;", null, getThread(), false); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ fClassLoader = child;
+ }
}
return fClassLoader;
}
@@ -132,4 +149,12 @@
public IJavaProject getProject() {
return fProject;
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#getThread()
+ */
+ public IJavaThread getThread() {
+ return fThread;
+ }
+
}
Index: eval/org/eclipse/jdt/internal/debug/eval/ast/engine/JavaObjectRuntimeContext.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/JavaObjectRuntimeContext.java,v
retrieving revision 1.8
diff -u -r1.8 JavaObjectRuntimeContext.java
--- eval/org/eclipse/jdt/internal/debug/eval/ast/engine/JavaObjectRuntimeContext.java 4 Aug 2005 18:58:14 -0000 1.8
+++ eval/org/eclipse/jdt/internal/debug/eval/ast/engine/JavaObjectRuntimeContext.java 18 Sep 2009 18:48:07 -0000
@@ -25,12 +25,7 @@
* this
object or this context.
*/
private IJavaObject fThisObject;
-
- /**
- * The thread for this context.
- */
- private IJavaThread fThread;
-
+
/**
* ObjectValueRuntimeContext constructor.
*
@@ -39,9 +34,8 @@
* @param thread the thread for this context.
*/
public JavaObjectRuntimeContext(IJavaObject thisObject, IJavaProject javaProject, IJavaThread thread) {
- super(javaProject);
+ super(javaProject, thread);
fThisObject= thisObject;
- fThread= thread;
}
/**
@@ -73,17 +67,17 @@
}
/**
- * @see IRuntimeContext#getThread()
- */
- public IJavaThread getThread() {
- return fThread;
- }
-
- /**
* @see IRuntimeContext#isConstructor()
*/
public boolean isConstructor() {
return false;
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#isStatic()
+ */
+ public boolean isStatic() {
+ return false;
+ }
}
Index: eval/org/eclipse/jdt/internal/debug/eval/ast/engine/IRuntimeContext.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/IRuntimeContext.java,v
retrieving revision 1.7
diff -u -r1.7 IRuntimeContext.java
--- eval/org/eclipse/jdt/internal/debug/eval/ast/engine/IRuntimeContext.java 13 Jul 2005 19:09:44 -0000 1.7
+++ eval/org/eclipse/jdt/internal/debug/eval/ast/engine/IRuntimeContext.java 18 Sep 2009 18:48:07 -0000
@@ -54,6 +54,14 @@
IJavaObject getThis() throws CoreException;
/**
+ * Returns whether this evaluation context is static.
+ *
+ * @return whether the evaluation context is static
+ * @exception CoreException on failure
+ */
+ boolean isStatic() throws CoreException;
+
+ /**
* Returns the receiving type context in which to perform
* the evaluation. The type of 'this', or in the case of a
* static context, the class or interface in which the evaluation is being
Index: eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ArrayRuntimeContext.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ArrayRuntimeContext.java,v
retrieving revision 1.6
diff -u -r1.6 ArrayRuntimeContext.java
--- eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ArrayRuntimeContext.java 29 May 2008 15:47:44 -0000 1.6
+++ eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ArrayRuntimeContext.java 18 Sep 2009 18:48:07 -0000
@@ -37,13 +37,11 @@
private IJavaArray fArray = null;
private IJavaReferenceType fReceivingType = null;
- private IJavaThread fThread = null;
private IJavaVariable fLocalArray = null;
public ArrayRuntimeContext(IJavaArray arrayObject, IJavaThread thread, IJavaProject project) {
- super(project);
+ super(project, thread);
fArray = arrayObject;
- fThread = thread;
fLocalArray = new JDIPlaceholderVariable(ARRAY_THIS_VARIABLE, arrayObject);
}
@@ -85,16 +83,16 @@
}
/* (non-Javadoc)
- * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#getThread()
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#isConstructor()
*/
- public IJavaThread getThread() {
- return fThread;
+ public boolean isConstructor() throws CoreException {
+ return false;
}
-
+
/* (non-Javadoc)
- * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#isConstructor()
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#isStatic()
*/
- public boolean isConstructor() throws CoreException {
+ public boolean isStatic() {
return false;
}
Index: eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java,v
retrieving revision 1.70
diff -u -r1.70 ASTEvaluationEngine.java
--- eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java 21 May 2009 20:22:26 -0000 1.70
+++ eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java 18 Sep 2009 18:48:07 -0000
@@ -214,7 +214,7 @@
// Compile in context of declaring type to get proper visibility of locals and members.
// Compiling in context of receiving type potentially provides access to more members,
// but does not allow access to privates members in declaring type
- IJavaReferenceType receivingType = frame.getReferenceType();
+ IJavaReferenceType receivingType = context.getReceivingType();
// currently disabled - see bugs 99416 and 106492
// if (frame.isStatic()) {
Index: model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java,v
retrieving revision 1.141
diff -u -r1.141 JDIDebugTarget.java
--- model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java 10 Sep 2009 18:45:15 -0000 1.141
+++ model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java 18 Sep 2009 18:48:08 -0000
@@ -46,6 +46,8 @@
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.debug.core.IJavaBreakpoint;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaObject;
+import org.eclipse.jdt.debug.core.IJavaReferenceType;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaThreadGroup;
import org.eclipse.jdt.debug.core.IJavaType;
@@ -69,6 +71,7 @@
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.event.ClassPrepareEvent;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.ThreadDeathEvent;
@@ -452,11 +455,12 @@
/**
* Registers event handlers for thread creation,
- * thread termination.
+ * thread termination, and class prepare requests.
*/
protected void initializeRequests() {
setThreadStartHandler(new ThreadStartHandler());
- new ThreadDeathHandler();
+ new ThreadDeathHandler();
+ new ClassLoaderHandler();
}
/**
@@ -1951,6 +1955,83 @@
}
+ /**
+ * Listens to all class prepare events to discover the bootstrap class loader.
+ */
+ class ClassLoaderHandler implements IJDIEventListener {
+
+ public ClassLoaderHandler() {
+ createRequest();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.core.IJDIEventListener#eventSetComplete(com.sun.jdi.event.Event, org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget, boolean, com.sun.jdi.event.EventSet)
+ */
+ public void eventSetComplete(Event event, JDIDebugTarget target, boolean suspend, EventSet eventSet) {
+ // do nothing
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.core.IJDIEventListener#handleEvent(com.sun.jdi.event.Event, org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget, boolean, com.sun.jdi.event.EventSet)
+ */
+ public boolean handleEvent(Event event, JDIDebugTarget target, boolean suspendVote, EventSet eventSet) {
+ if (event instanceof ClassPrepareEvent) {
+ ClassPrepareEvent cpe = (ClassPrepareEvent) event;
+ IJavaObject loader = null;
+ try {
+ ReferenceType type = cpe.referenceType();
+ IJavaReferenceType refType = (IJavaReferenceType) JDIType.createType(target, type);
+ loader = refType.getClassLoaderObject();
+ } catch (DebugException e) {
+ // do nothing
+ }
+ if (loader != null) {
+ fSomeClassLoader = loader;
+ // remove listener & disable request
+ removeJDIEventListener(this, cpe.request());
+ cpe.request().disable();
+ }
+ }
+ // always resume
+ return true;
+ }
+
+ /**
+ * Creates and registers a request to handle all class prepare
+ * events
+ */
+ protected void createRequest() {
+ EventRequestManager manager = getEventRequestManager();
+ if (manager != null) {
+ try {
+ ClassPrepareRequest req= manager.createClassPrepareRequest();
+ req.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
+ req.enable();
+ addJDIEventListener(this, req);
+ } catch (RuntimeException e) {
+ logError(e);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * The first class loader that the VM can find. Cached for debugger evaluations
+ * so we can locate the boot strap class loader when needed.
+ */
+ private IJavaObject fSomeClassLoader = null;
+
+ /**
+ * Returns the first class loader object found by this target, or null
+ * if none yet.
+ *
+ * @return some class loader object or null
+ */
+ public IJavaObject getSomeClassLoader() {
+ return fSomeClassLoader;
+ }
+
class CleanUpJob extends Job {
/**
Index: META-INF/MANIFEST.MF
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.debug/META-INF/MANIFEST.MF,v
retrieving revision 1.19
diff -u -r1.19 MANIFEST.MF
--- META-INF/MANIFEST.MF 22 Jun 2009 15:30:35 -0000 1.19
+++ META-INF/MANIFEST.MF 18 Sep 2009 18:48:07 -0000
@@ -31,7 +31,8 @@
org.eclipse.jdt.internal.debug.core.model;x-friends:="org.eclipse.jdt.debug.ui",
org.eclipse.jdt.internal.debug.eval;x-friends:="org.eclipse.jdt.debug.ui",
org.eclipse.jdt.internal.debug.eval.ast.engine;x-friends:="org.eclipse.jdt.debug.ui",
- org.eclipse.jdt.internal.debug.eval.ast.instructions;x-friends:="org.eclipse.jdt.debug.ui"
+ org.eclipse.jdt.internal.debug.eval.ast.instructions;x-friends:="org.eclipse.jdt.debug.ui",
+ org.eclipse.jdt.internal.debug.eval.engine;x-internal:=true
Require-Bundle: org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
org.eclipse.debug.core;bundle-version="[3.5.0,4.0.0)",
org.eclipse.jdt.core;bundle-version="[3.5.0,4.0.0)",
Index: model/org/eclipse/jdt/internal/debug/core/IJDIEventListener.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/IJDIEventListener.java,v
retrieving revision 1.13
diff -u -r1.13 IJDIEventListener.java
--- model/org/eclipse/jdt/internal/debug/core/IJDIEventListener.java 7 Apr 2009 18:21:18 -0000 1.13
+++ model/org/eclipse/jdt/internal/debug/core/IJDIEventListener.java 18 Sep 2009 18:48:07 -0000
@@ -17,12 +17,12 @@
import com.sun.jdi.event.EventSet;
/**
- * A jdi event listener is notified of events associated with
- * a specific jdi event request. A listener registers/deregisters
- * event requests with a debug target.
+ * A JDI event listener is notified of events associated with
+ * a specific JDI event request. A listener registers/unregisters
+ * event requests with a JDI debug element.
*
- * @see JDIDebugTarget#addJDIEventListener(IJDIEventListener, EventRequest)
- * @see JDIDebugTarget#removeJDIEventListener(IJDIEventListener, EventRequest)
+ * @see org.eclipse.jdt.internal.debug.core.model.JDIDebugElement#addJDIEventListener(IJDIEventListener, com.sun.jdi.request.EventRequest)
+ * @see org.eclipse.jdt.internal.debug.core.model.JDIDebugElement#removeJDIEventListener(IJDIEventListener, com.sun.jdi.request.EventRequest)
*/
public interface IJDIEventListener {
Index: eval/org/eclipse/jdt/debug/eval/EvaluationManager.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.debug/eval/org/eclipse/jdt/debug/eval/EvaluationManager.java,v
retrieving revision 1.19
diff -u -r1.19 EvaluationManager.java
--- eval/org/eclipse/jdt/debug/eval/EvaluationManager.java 29 May 2008 15:47:44 -0000 1.19
+++ eval/org/eclipse/jdt/debug/eval/EvaluationManager.java 18 Sep 2009 18:48:07 -0000
@@ -16,7 +16,7 @@
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.internal.debug.eval.LocalEvaluationEngine;
-import org.eclipse.jdt.internal.debug.eval.ast.engine.ASTEvaluationEngine;
+import org.eclipse.jdt.internal.debug.eval.engine.RemoteEvaluationEngine;
/**
* The evaluation manager provides factory methods for
@@ -67,7 +67,7 @@
* @return an evaluation engine
*/
public static IAstEvaluationEngine newAstEvaluationEngine(IJavaProject project, IJavaDebugTarget target) {
- return new ASTEvaluationEngine(project, target);
+ return new RemoteEvaluationEngine(target, project);
}
}
Index: eval/org/eclipse/jdt/internal/debug/eval/engine/RemoteEvaluationEngine.java
===================================================================
RCS file: eval/org/eclipse/jdt/internal/debug/eval/engine/RemoteEvaluationEngine.java
diff -N eval/org/eclipse/jdt/internal/debug/eval/engine/RemoteEvaluationEngine.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ eval/org/eclipse/jdt/internal/debug/eval/engine/RemoteEvaluationEngine.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,460 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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
+ *******************************************************************************/
+package org.eclipse.jdt.internal.debug.eval.engine;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventFilter;
+import org.eclipse.debug.core.model.ITerminate;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.eval.IEvaluationContext;
+import org.eclipse.jdt.debug.core.IEvaluationRunnable;
+import org.eclipse.jdt.debug.core.IJavaClassType;
+import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaInterfaceType;
+import org.eclipse.jdt.debug.core.IJavaObject;
+import org.eclipse.jdt.debug.core.IJavaReferenceType;
+import org.eclipse.jdt.debug.core.IJavaStackFrame;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.core.IJavaValue;
+import org.eclipse.jdt.debug.core.IJavaVariable;
+import org.eclipse.jdt.debug.core.JDIDebugModel;
+import org.eclipse.jdt.debug.eval.IAstEvaluationEngine;
+import org.eclipse.jdt.debug.eval.ICompiledExpression;
+import org.eclipse.jdt.debug.eval.IEvaluationListener;
+import org.eclipse.jdt.debug.eval.IEvaluationResult;
+import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
+import org.eclipse.jdt.internal.debug.core.JavaDebugUtils;
+import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
+import org.eclipse.jdt.internal.debug.core.model.JDIThread;
+import org.eclipse.jdt.internal.debug.core.model.JDIValue;
+import org.eclipse.jdt.internal.debug.eval.EvaluationResult;
+import org.eclipse.jdt.internal.debug.eval.ast.engine.EvaluationEngineMessages;
+import org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext;
+import org.eclipse.jdt.internal.debug.eval.ast.engine.JavaObjectRuntimeContext;
+import org.eclipse.jdt.internal.debug.eval.ast.engine.RuntimeContext;
+import org.eclipse.jdt.internal.debug.eval.ast.engine.TypeRuntimeContext;
+
+import com.sun.jdi.InvocationException;
+import com.sun.jdi.ObjectReference;
+
+/**
+ *
+ */
+public class RemoteEvaluationEngine implements IAstEvaluationEngine {
+
+ /**
+ * Associated Java project
+ */
+ private IJavaProject fProject;
+
+ /**
+ * Associated debug target
+ */
+ private IJavaDebugTarget fTarget;
+
+ /**
+ * Runnable serialized on a thread to perform submit an evaluation
+ */
+ class EvalRunnable implements Runnable {
+
+ private CompiledExpression fExpression;
+
+ private int fEvaluationDetail;
+
+ private boolean fHitBreakpoints;
+
+ private IRuntimeContext fContext;
+
+ private IEvaluationListener fListener;
+
+ public EvalRunnable(CompiledExpression expression, IRuntimeContext context, IEvaluationListener listener, int evaluationDetail, boolean hitBreakpoints) {
+ fExpression= expression;
+ fContext= context;
+ fListener= listener;
+ fEvaluationDetail= evaluationDetail;
+ fHitBreakpoints= hitBreakpoints;
+ }
+
+ public void run() {
+ EvaluationResult result = new EvaluationResult(RemoteEvaluationEngine.this, fExpression.getSnippet(), fContext.getThread());
+ if (fExpression.hasErrors()) {
+ String[] errors = fExpression.getErrorMessages();
+ for (int i = 0, numErrors = errors.length; i < numErrors; i++) {
+ result.addError(errors[i]);
+ }
+ evaluationFinished(result);
+ return;
+ }
+
+ class EvaluationRunnable implements IEvaluationRunnable, ITerminate {
+
+ CoreException fException;
+ boolean fTerminated = false;
+
+ public void run(IJavaThread jt, IProgressMonitor pm) {
+ EventFilter filter = new EventFilter();
+ try {
+ DebugPlugin.getDefault().addDebugEventFilter(filter);
+ fExpression.execute(fContext);
+ } catch (CoreException exception) {
+ fException = exception;
+ if (fEvaluationDetail == DebugEvent.EVALUATION && exception.getStatus().getException() instanceof InvocationException) {
+ // print the stack trace for the exception if an *explicit* evaluation
+ InvocationException invocationException = (InvocationException)exception.getStatus().getException();
+ ObjectReference exObject = invocationException.exception();
+ IJavaObject modelObject = (IJavaObject)JDIValue.createValue((JDIDebugTarget)getDebugTarget(), exObject);
+ try {
+ modelObject.sendMessage("printStackTrace", "()V", null, jt, false); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (DebugException e) {
+ // unable to print stack trace
+ }
+ }
+ } finally {
+ DebugPlugin.getDefault().removeDebugEventFilter(filter);
+ fTerminated = true;
+ }
+ }
+ public void terminate() {
+ fTerminated = true;
+ // TODO: how to support terminate?
+ }
+ public boolean canTerminate() {
+ return !fTerminated;
+ }
+ public boolean isTerminated() {
+ return fTerminated;
+ }
+
+ public CoreException getException() {
+ return fException;
+ }
+ }
+
+ EvaluationRunnable er = new EvaluationRunnable();
+ CoreException exception = null;
+ try {
+ fContext.getThread().runEvaluation(er, null, fEvaluationDetail, fHitBreakpoints);
+ } catch (DebugException e) {
+ exception = e;
+ }
+
+ IJavaValue value = fExpression.getResult();
+
+ if (exception == null) {
+ exception = er.getException();
+ }
+
+ result.setTerminated(er.fTerminated);
+ if (exception != null) {
+ if (exception instanceof DebugException) {
+ result.setException((DebugException)exception);
+ } else {
+ result.setException(new DebugException(exception.getStatus()));
+ }
+ } else {
+ if (value != null) {
+ result.setValue(value);
+ } else {
+ result.addError(EvaluationEngineMessages.ASTEvaluationEngine_An_unknown_error_occurred_during_evaluation);
+ }
+ }
+
+
+ evaluationFinished(result);
+ }
+ private void evaluationFinished(IEvaluationResult result) {
+ // only notify if plug-in not yet shutdown - bug# 8693
+ if(JDIDebugPlugin.getDefault() != null) {
+ fListener.evaluationComplete(result);
+ }
+ }
+
+ }
+
+ /**
+ * Filters variable change events during an evaluation to avoid refreshing the variables
+ * view until done.
+ */
+ class EventFilter implements IDebugEventFilter {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IDebugEventFilter#filterDebugEvents(org.eclipse.debug.core.DebugEvent[])
+ */
+ public DebugEvent[] filterDebugEvents(DebugEvent[] events) {
+ if (events.length == 1) {
+ DebugEvent event = events[0];
+ if (event.getSource() instanceof IJavaVariable && event.getKind() == DebugEvent.CHANGE) {
+ if (((IJavaVariable)event.getSource()).getDebugTarget().equals(getDebugTarget())) {
+ return null;
+ }
+ }
+ }
+ return events;
+ }
+
+ }
+
+ /**
+ * Constructs a new engine on the given target and project.
+ *
+ * @param target debug target
+ * @param project associated project for compilation purposes
+ */
+ public RemoteEvaluationEngine(IJavaDebugTarget target, IJavaProject project) {
+ fProject = project;
+ fTarget = target;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#evaluateExpression(org.eclipse.jdt.debug.eval.ICompiledExpression, org.eclipse.jdt.debug.core.IJavaStackFrame, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
+ */
+ public void evaluateExpression(ICompiledExpression expression, IJavaStackFrame frame, final IEvaluationListener listener, int evaluationDetail, boolean hitBreakpoints) throws DebugException {
+ IRuntimeContext debugContext = new RuntimeContext(getJavaProject(), frame);
+ evaluateExpression(expression, debugContext, listener, evaluationDetail, hitBreakpoints);
+ }
+
+ /**
+ * Evaluates the given expression in the specified thread and the context.
+ *
+ * @param expression expression to evaluate
+ * @param context context to evaluate in
+ * @param listener listener to report results to
+ * @param evaluationDetail detail event to fire with evaluation resume/suspend
+ * @param hitBreakpoints whether to honor breakpoints during the evaluation
+ */
+ private void evaluateExpression(ICompiledExpression expression, IRuntimeContext context, IEvaluationListener listener, int evaluationDetail, boolean hitBreakpoints) throws DebugException {
+ if (expression instanceof CompiledExpression) {
+ IJavaThread thread = context.getThread();
+ // don't queue explicit evaluation if the thread is all ready performing an evaluation.
+ if (thread.isSuspended() && ((JDIThread)thread).isInvokingMethod() || thread.isPerformingEvaluation() && evaluationDetail == DebugEvent.EVALUATION) {
+ EvaluationResult result= new EvaluationResult(this, expression.getSnippet(), thread);
+ result.addError(EvaluationEngineMessages.ASTEvaluationEngine_Cannot_perform_nested_evaluations);
+ listener.evaluationComplete(result);
+ return;
+ }
+ thread.queueRunnable(new EvalRunnable((CompiledExpression)expression, context, listener, evaluationDetail, hitBreakpoints));
+ } else {
+ throw new DebugException(new Status(IStatus.ERROR, JDIDebugPlugin.getUniqueIdentifier(), IStatus.OK, EvaluationEngineMessages.ASTEvaluationEngine_AST_evaluation_engine_cannot_evaluate_expression, null));
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#evaluateExpression(org.eclipse.jdt.debug.eval.ICompiledExpression, org.eclipse.jdt.debug.core.IJavaObject, org.eclipse.jdt.debug.core.IJavaThread, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
+ */
+ public void evaluateExpression(ICompiledExpression expression,
+ IJavaObject object, IJavaThread thread,
+ IEvaluationListener listener, int evaluationDetail,
+ boolean hitBreakpoints) throws DebugException {
+ IRuntimeContext debugContext = new JavaObjectRuntimeContext(object, getJavaProject(), thread);
+ evaluateExpression(expression, debugContext, listener, evaluationDetail, hitBreakpoints);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#getCompiledExpression(java.lang.String, org.eclipse.jdt.debug.core.IJavaStackFrame)
+ */
+ public ICompiledExpression getCompiledExpression(String expression, IJavaStackFrame frame) throws DebugException {
+ return getCompiledExpression(expression, new RuntimeContext(getJavaProject(), frame));
+ }
+
+ /**
+ * Returns a compiled expression for the given snippet in the given debugger context.
+ *
+ * @param snippet expression to compile
+ * @param debugContext current execution context to compile in
+ * @return compiled expression
+ * @throws DebugException on failure
+ */
+ private ICompiledExpression getCompiledExpression(final String snippet, final IRuntimeContext debugContext) throws DebugException {
+ IJavaProject javaProject = getJavaProject();
+ final IEvaluationContext evalContext = javaProject.newEvaluationContext();
+
+ try {
+ IJavaVariable[] localsVar = debugContext.getLocals();
+ int numLocalsVar= localsVar.length;
+ Set names = new HashSet();
+ // ******
+ // to hide problems with local variable declare as instance of Local Types
+ // and to remove locals with duplicate names
+ IJavaVariable[] locals= new IJavaVariable[numLocalsVar];
+ int numLocals= 0;
+ for (int i = 0; i < numLocalsVar; i++) {
+ if (!isLocalType(localsVar[i].getSignature()) && !names.contains(localsVar[i].getName())) {
+ locals[numLocals++]= localsVar[i];
+ names.add(localsVar[i].getName());
+ }
+ }
+ // to solve and remove
+ // ******
+ final String[] localTypesNames= new String[numLocals];
+ final String[] localVariables= new String[numLocals];
+ final int[] localModifiers = new int[numLocals];
+ for (int i = 0; i < numLocals; i++) {
+ localVariables[i] = locals[i].getName();
+ localTypesNames[i] = Signature.toString(locals[i].getGenericSignature()).replace('/', '.');
+ localModifiers[i] = Flags.AccDefault;
+ if (locals[i].isFinal()) {
+ localModifiers[i] = Flags.AccFinal;
+ }
+ }
+ // Compile in context of declaring type to get proper visibility of locals and members.
+ // Compiling in context of receiving type potentially provides access to more members,
+ // but does not allow access to privates members in declaring type
+ IJavaReferenceType receivingType = debugContext.getReceivingType();
+ IType iType = JavaDebugUtils.resolveType(receivingType);
+ while (iType.isAnonymous() && receivingType instanceof IJavaClassType) {
+ // cannot compile in context of anonymous classes, so compile in context of their superclass
+ receivingType = ((IJavaClassType)receivingType).getSuperclass();
+ iType = JavaDebugUtils.resolveType(receivingType);
+ }
+
+ final IType declaringType = iType;
+ final CompiledExpression compiledExpression = new CompiledExpression(snippet, localVariables);
+ Job job = new Job("Debugger Evaluation") {
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ evalContext.evaluateCodeSnippet(
+ snippet,
+ localTypesNames,
+ localVariables,
+ localModifiers,
+ declaringType,
+ debugContext.isStatic(),
+ debugContext.isConstructor(),
+ compiledExpression,
+ new NullProgressMonitor());
+ } catch (JavaModelException e) {
+ return e.getStatus();
+ } catch (CoreException e) {
+ return e.getStatus();
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.setSystem(true);
+ job.schedule();
+ try {
+ job.join();
+ } catch (InterruptedException e) {
+ throw new DebugException(new Status(IStatus.ERROR, JDIDebugModel.getPluginIdentifier(), "Evaluation interrupted", e));
+ }
+
+ return compiledExpression;
+ } catch (CoreException e) {
+ throw new DebugException(e.getStatus());
+ }
+ }
+
+ //TODO: local types might be OK with this new engine
+
+ // ******
+ // to hide problems with local variable declare as instance of Local Types
+ private boolean isLocalType(String typeName) {
+ StringTokenizer strTok= new StringTokenizer(typeName,"$"); //$NON-NLS-1$
+ strTok.nextToken();
+ while (strTok.hasMoreTokens()) {
+ char char0= strTok.nextToken().charAt(0);
+ if ('0' <= char0 && char0 <= '9') {
+ return true;
+ }
+ }
+ return false;
+ }
+ // ******
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#getCompiledExpression(java.lang.String, org.eclipse.jdt.debug.core.IJavaObject)
+ */
+ public ICompiledExpression getCompiledExpression(String expression, IJavaObject object) throws DebugException {
+ return getCompiledExpression(expression, new JavaObjectRuntimeContext(object, getJavaProject(), null));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#getCompiledExpression(java.lang.String, org.eclipse.jdt.debug.core.IJavaReferenceType)
+ */
+ public ICompiledExpression getCompiledExpression(String expression, IJavaReferenceType type) throws DebugException {
+ return getCompiledExpression(expression, new TypeRuntimeContext(getJavaProject(), null, type));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.IEvaluationEngine#dispose()
+ */
+ public void dispose() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * Checks if the stack frame is declared in an interface an aborts
+ * if so.
+ *
+ * @param frame stack frame
+ * @throws DebugException if declaring type is an interface
+ */
+ private void checkInterface(IJavaStackFrame frame) throws DebugException {
+ if (frame.getReferenceType() instanceof IJavaInterfaceType) {
+ IStatus status = new Status(IStatus.ERROR, JDIDebugModel.getPluginIdentifier(), DebugException.REQUEST_FAILED,
+ EvaluationEngineMessages.ASTEvaluationEngine_0, null);
+ throw new DebugException(status);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.IEvaluationEngine#evaluate(java.lang.String, org.eclipse.jdt.debug.core.IJavaStackFrame, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
+ */
+ public void evaluate(String snippet, IJavaStackFrame frame, IEvaluationListener listener, int evaluationDetail, boolean hitBreakpoints) throws DebugException {
+ checkInterface(frame);
+ IRuntimeContext context = new RuntimeContext(getJavaProject(), frame);
+ ICompiledExpression expression= getCompiledExpression(snippet, context);
+ evaluateExpression(expression, context, listener, evaluationDetail, hitBreakpoints);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.IEvaluationEngine#evaluate(java.lang.String, org.eclipse.jdt.debug.core.IJavaObject, org.eclipse.jdt.debug.core.IJavaThread, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
+ */
+ public void evaluate(String snippet, IJavaObject thisContext,
+ IJavaThread thread, IEvaluationListener listener,
+ int evaluationDetail, boolean hitBreakpoints) throws DebugException {
+ IRuntimeContext context = new JavaObjectRuntimeContext(thisContext, getJavaProject(), thread);
+ ICompiledExpression expression= getCompiledExpression(snippet, context);
+ evaluateExpression(expression, context, listener, evaluationDetail, hitBreakpoints);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.IEvaluationEngine#getDebugTarget()
+ */
+ public IJavaDebugTarget getDebugTarget() {
+ return fTarget;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.IEvaluationEngine#getJavaProject()
+ */
+ public IJavaProject getJavaProject() {
+ return fProject;
+ }
+
+}
Index: eval/org/eclipse/jdt/internal/debug/eval/ast/engine/TypeRuntimeContext.java
===================================================================
RCS file: eval/org/eclipse/jdt/internal/debug/eval/ast/engine/TypeRuntimeContext.java
diff -N eval/org/eclipse/jdt/internal/debug/eval/ast/engine/TypeRuntimeContext.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ eval/org/eclipse/jdt/internal/debug/eval/ast/engine/TypeRuntimeContext.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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
+ *******************************************************************************/
+package org.eclipse.jdt.internal.debug.eval.ast.engine;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaObject;
+import org.eclipse.jdt.debug.core.IJavaReferenceType;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.core.IJavaVariable;
+
+/**
+ * Expression evaluation in the context of a type. Not a static context - used
+ * for logical structures which are evaluated in a nont-static context.
+ *
+ * @since 3.6
+ */
+public class TypeRuntimeContext extends AbstractRuntimeContext {
+
+ /**
+ * Type context for evaluation
+ */
+ private IJavaReferenceType fType;
+
+ /**
+ * Constructs a new evaluation context for the given type.
+ *
+ * @param project associated project
+ * @param thread thread for message sends
+ * @param type reference type
+ */
+ public TypeRuntimeContext(IJavaProject project, IJavaThread thread, IJavaReferenceType type) {
+ super(project, thread);
+ fType = type;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#getLocals()
+ */
+ public IJavaVariable[] getLocals() throws CoreException {
+ return new IJavaVariable[0];
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#getReceivingType()
+ */
+ public IJavaReferenceType getReceivingType() throws CoreException {
+ return fType;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#getThis()
+ */
+ public IJavaObject getThis() throws CoreException {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#getVM()
+ */
+ public IJavaDebugTarget getVM() {
+ return (IJavaDebugTarget) fType.getDebugTarget();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#isConstructor()
+ */
+ public boolean isConstructor() throws CoreException {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext#isStatic()
+ */
+ public boolean isStatic() throws CoreException {
+ return false;
+ }
+
+}
Index: eval/org/eclipse/jdt/internal/debug/eval/engine/CompiledExpression.java
===================================================================
RCS file: eval/org/eclipse/jdt/internal/debug/eval/engine/CompiledExpression.java
diff -N eval/org/eclipse/jdt/internal/debug/eval/engine/CompiledExpression.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ eval/org/eclipse/jdt/internal/debug/eval/engine/CompiledExpression.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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
+ *******************************************************************************/
+package org.eclipse.jdt.internal.debug.eval.engine;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.jdt.core.dom.Message;
+import org.eclipse.jdt.core.eval.ICodeSnippetRequestor;
+import org.eclipse.jdt.debug.core.IJavaArray;
+import org.eclipse.jdt.debug.core.IJavaArrayType;
+import org.eclipse.jdt.debug.core.IJavaClassObject;
+import org.eclipse.jdt.debug.core.IJavaClassType;
+import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaObject;
+import org.eclipse.jdt.debug.core.IJavaReferenceType;
+import org.eclipse.jdt.debug.core.IJavaValue;
+import org.eclipse.jdt.debug.core.IJavaVariable;
+import org.eclipse.jdt.debug.core.JDIDebugModel;
+import org.eclipse.jdt.debug.eval.ICompiledExpression;
+import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
+import org.eclipse.jdt.internal.debug.eval.EvaluationMessages;
+import org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext;
+
+/**
+ *
+ */
+public class CompiledExpression implements ICompiledExpression, ICodeSnippetRequestor {
+
+ /**
+ * List of String
s describing compilation problems.
+ */
+ private List fErrors = new ArrayList();
+
+ /**
+ * Expression to evaluate
+ */
+ private String fSnippet;
+
+ List fClassFileBytes = new ArrayList();
+
+ List fClassFileNames = new ArrayList();
+
+ private String fCodeSnippetClass;
+
+ private String[] fLocalNames;
+
+ /**
+ * Result of the evaluation or null
if none
+ */
+ private IJavaValue fResult;
+
+ /**
+ * Constructs a new compiled expression
+ *
+ * @param expression the expression being evaluated
+ */
+ public CompiledExpression(String expression, String[] localVarNames) {
+ fSnippet = expression;
+ fLocalNames = localVarNames;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.ICompiledExpression#getErrorMessages()
+ */
+ public String[] getErrorMessages() {
+ return (String[])fErrors.toArray(new String[fErrors.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.ICompiledExpression#getErrors()
+ */
+ public Message[] getErrors() {
+ Message[] messages= new Message[fErrors.size()];
+ int i= 0;
+ for (Iterator iter= fErrors.iterator(); iter.hasNext();) {
+ messages[i++]= new Message((String) iter.next(), -1);
+ }
+ return messages;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.ICompiledExpression#getSnippet()
+ */
+ public String getSnippet() {
+ return fSnippet;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.eval.ICompiledExpression#hasErrors()
+ */
+ public boolean hasErrors() {
+ return fErrors.size() > 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.eval.ICodeSnippetRequestor#acceptClassFiles(byte[][], java.lang.String[][], java.lang.String)
+ */
+ public boolean acceptClassFiles(byte[][] classFileBytes, String[][] classFileCompoundNames, String codeSnippetClassName) {
+ for (int i = 0; i < classFileBytes.length; i++) {
+ byte[] bs = classFileBytes[i];
+ String[] ids = classFileCompoundNames[i];
+ StringBuffer buffer = new StringBuffer();
+ for (int j = 0; j < ids.length; j++) {
+ if (j > 0) {
+ buffer.append('.');
+ }
+ buffer.append(ids[j]);
+ }
+ fClassFileBytes.add(bs);
+ fClassFileNames.add(buffer.toString());
+ }
+ fCodeSnippetClass = codeSnippetClassName;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.eval.ICodeSnippetRequestor#acceptProblem(org.eclipse.core.resources.IMarker, java.lang.String, int)
+ */
+ public void acceptProblem(IMarker problemMarker, String fragmentSource, int fragmentKind) {
+ if (problemMarker.getAttribute(IMarker.SEVERITY, -1) != IMarker.SEVERITY_ERROR) {
+ return;
+ }
+ fErrors.add(problemMarker.getAttribute(IMarker.MESSAGE, "")); //$NON-NLS-1$
+ }
+
+ byte[][] getClassFiles() {
+ return (byte[][]) fClassFileBytes.toArray(new byte[fClassFileBytes.size()][]);
+ }
+
+ String[] getClassFileNames() {
+ return (String[]) fClassFileNames.toArray(new String[fClassFileNames.size()]);
+ }
+
+ String getSnippetClass() {
+ return fCodeSnippetClass;
+ }
+
+ String[] getLocalVarNames() {
+ return fLocalNames;
+ }
+
+ IJavaValue execute(IRuntimeContext debugContext) throws CoreException {
+ IJavaReferenceType receivingType = debugContext.getReceivingType();
+ IJavaDebugTarget target = debugContext.getVM();
+ IJavaObject loader = receivingType.getClassLoaderObject();
+ //loader is null for those classes loaded by the bootstrap loader
+ if (loader == null) {
+ IJavaObject child = ((JDIDebugTarget)target).getSomeClassLoader();
+ IJavaObject parent = child;
+ while (parent != null && !parent.isNull()) {
+ child = parent;
+ parent = (IJavaObject)child.sendMessage("getParent", "()Ljava/lang/ClassLoader;", null, debugContext.getThread(), false); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ loader = child;
+ }
+ if (loader == null) {
+ throw new CoreException(new Status(IStatus.ERROR, JDIDebugModel.getPluginIdentifier(), "Unable to locate bootstrap class loader"));
+ }
+ String[] names = getClassFileNames();
+ byte[][] bytes = getClassFiles();
+ for (int i = 0; i < bytes.length; i++) {
+ byte[] bs = bytes[i];
+ String name = names[i];
+ IJavaClassObject loaded = debugContext.classForName(name);
+ if (loaded == null) {
+ IJavaValue[] args = new IJavaValue[4];
+
+ args[0] = target.newValue(name);
+ IJavaClassObject clazz = debugContext.classForName("[B"); //$NON-NLS-1$
+ IJavaArrayType byteArrayType = (IJavaArrayType) clazz.getInstanceType();
+ IJavaArray array = byteArrayType.newInstance(bs.length);
+ IJavaValue[] values = new IJavaValue[bs.length];
+ for (int j = 0; j < bs.length; j++) {
+ values[j] = target.newValue(bs[j]);
+ }
+ array.setValues(0, bs.length, values, 0);
+ args[1] = array;
+
+ args[2] = target.newValue(0);
+ args[3] = target.newValue(bs.length);
+ IJavaValue result = loader.sendMessage("defineClass", "(Ljava/lang/String;[BII)Ljava/lang/Class;", args, debugContext.getThread(), false); //$NON-NLS-1$ //$NON-NLS-2$
+ System.out.println(result);
+ args = new IJavaValue[1];
+ args[0] = result;
+ IJavaValue voidRes = loader.sendMessage("resolveClass", "(Ljava/lang/Class;)V", args, debugContext.getThread(), false); //$NON-NLS-1$ //$NON-NLS-2$
+ System.out.println(voidRes);
+ }
+ }
+
+ // invoke the snippet method
+ IJavaClassObject snippetClazz = debugContext.classForName(getSnippetClass());
+ IJavaClassType refType = (IJavaClassType) snippetClazz.getInstanceType();
+ IJavaObject receiver = refType.newInstance("()V", null, debugContext.getThread()); //$NON-NLS-1$
+ // initialize locals
+ initializeLocals(debugContext, receiver);
+ // execute code
+ receiver.sendMessage(ICodeSnippetRequestor.RUN_METHOD, "()V", null, debugContext.getThread(), false); //$NON-NLS-1$
+
+ // retrieve the result
+ // now retrieve the description of the result
+ IVariable[] fields = receiver.getVariables();
+ IJavaVariable resultValue = null;
+ IJavaVariable resultType = null;
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i].getName().equals(ICodeSnippetRequestor.RESULT_TYPE_FIELD)) {
+ resultType = (IJavaVariable)fields[i];
+ }
+ if (fields[i].getName().equals(ICodeSnippetRequestor.RESULT_VALUE_FIELD)) {
+ resultValue = (IJavaVariable)fields[i];
+ }
+ }
+ // TODO: copy locals back
+ fResult = convertResult((IJavaClassObject)resultType.getValue(), (IJavaValue)resultValue.getValue());
+ return fResult;
+ }
+
+ /**
+ * Returns the result of the evaluation or null
if
+ * none (evaluation failed).
+ *
+ * @return evaluation result or null
+ */
+ public IJavaValue getResult() {
+ return fResult;
+ }
+
+ /**
+ * Initializes the value of instance variables in the
+ * 'code snippet object' that are used as place holders
+ * for locals and 'this' in the current stack frame.
+ *
+ * @param context debug context
+ * @exception DebugException if an exception is thrown
+ * accessing the given object
+ */
+ protected void initializeLocals(IRuntimeContext context, IJavaObject snippetObject) throws CoreException {
+ IJavaVariable[] locals = context.getLocals();
+ IJavaObject thisObject = context.getThis();
+ if (locals != null) {
+ for (int i = 0; i < locals.length; i++) {
+ IJavaVariable local = locals[i];
+ IJavaVariable field = snippetObject.getField(ICodeSnippetRequestor.LOCAL_VAR_PREFIX + local.getName(), false);
+ // internal error if field is not found
+ if (field == null) {
+ throw new DebugException(
+ new Status(IStatus.ERROR, JDIDebugModel.getPluginIdentifier(),
+ DebugException.REQUEST_FAILED, EvaluationMessages.LocalEvaluationEngine_Evaluation_failed___unable_to_initialize_local_variables__4, null)
+ );
+ }
+ field.setValue(local.getValue());
+ }
+ }
+ if (thisObject != null) {
+ IJavaVariable field = snippetObject.getField(ICodeSnippetRequestor.DELEGATE_THIS, false);
+ // internal error if field is not found
+ if (field == null) {
+ throw new DebugException(
+ new Status(IStatus.ERROR, JDIDebugModel.getPluginIdentifier(),
+ DebugException.REQUEST_FAILED, EvaluationMessages.LocalEvaluationEngine_Evaluation_failed___unable_to_initialize___this___context__5, null)
+ );
+ }
+ field.setValue(thisObject);
+ }
+ }
+
+ /**
+ * Interpretts and returns the result of the running the snippet
+ * class file. The type of the result is described by an instance of
+ * java.lang.Class
. The value is interpretted based
+ * on the result type.
+ *
+ * Objects as well as primitve data types (boolean, int, etc.),
+ * have class objects, which are created by the VM. If the class object
+ * represents a primitive data type, then the associated value
+ * is stored in an instance of its "object" class. For example, when
+ * the result type is the class object for int
, the result
+ * object is an instance of java.lang.Integer
, and the
+ * actual int
is stored in the intValue().
+ * When the result type is the class object for java.lang.Integer
+ * the result object is an instance of java.lang.Integer
,
+ * to be interpretted as a