blob: 8fb23090ce291827b66b681a0f01c1c28e0f080e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2015 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 implementation
*******************************************************************************/
package org.eclipse.jdt.internal.debug.ui.actions;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.actions.IVariableValueEditor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.debug.eval.IAstEvaluationEngine;
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.ui.JDIDebugUIPlugin;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.progress.UIJob;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.InvocationException;
import com.sun.jdi.ObjectReference;
/**
* A variable value editor which prompts the user to enter an expression
* for evaluation. The result of the evaluation is assigned to the variable.
*/
public class JavaObjectValueEditor implements IVariableValueEditor {
/* (non-Javadoc)
* @see org.eclipse.debug.ui.actions.IVariableValueEditor#editVariable(org.eclipse.debug.core.model.IVariable, org.eclipse.swt.widgets.Shell)
*/
@Override
public boolean editVariable(IVariable variable, Shell shell) {
try {
IJavaVariable javaVariable = (IJavaVariable) variable;
String signature = javaVariable.getSignature();
if ("Ljava/lang/String;".equals(signature)) { //$NON-NLS-1$
StringValueInputDialog dialog= new StringValueInputDialog(shell, javaVariable);
if (dialog.open() == Window.OK) {
String result = dialog.getResult();
if (dialog.isUseLiteralValue()) {
variable.setValue(result);
} else {
setValue(variable, result);
}
}
} else {
ExpressionInputDialog dialog= new ExpressionInputDialog(shell, javaVariable);
if (dialog.open() == Window.OK) {
String result = dialog.getResult();
setValue(variable, result);
}
}
} catch (DebugException e) {
handleException(e);
}
return true;
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.actions.IVariableValueEditor#saveVariable(org.eclipse.debug.core.model.IVariable, java.lang.String, org.eclipse.swt.widgets.Shell)
*/
@Override
public boolean saveVariable(IVariable variable, String expression, Shell shell) {
IJavaVariable javaVariable = (IJavaVariable) variable;
String signature= null;
try {
signature = javaVariable.getSignature();
if ("Ljava/lang/String;".equals(signature)) { //$NON-NLS-1$
return false;
}
setValue(variable, expression);
} catch (DebugException e) {
handleException(e);
}
return true;
}
/**
* Evaluates the given expression and sets the given variable's value
* using the result.
*
* @param variable the variable whose value should be set
* @param expression the expression to evaluate
* @throws DebugException if an exception occurs evaluating the expression
* or setting the variable's value
*/
protected void setValue(final IVariable variable, final String expression){
UIJob job = new UIJob("Setting Variable Value"){ //$NON-NLS-1$
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
try {
IValue newValue = evaluate(expression);
if (newValue != null) {
variable.setValue(newValue);
} else {
variable.setValue(expression);
}
} catch (DebugException de) {
handleException(de);
}
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule();
}
/**
* Handles the given exception, which occurred during edit/save.
*/
protected void handleException(DebugException e) {
Throwable cause = e.getStatus().getException();
if (cause instanceof InvalidTypeException) {
IStatus status = new Status(IStatus.ERROR, JDIDebugUIPlugin.getUniqueIdentifier(), IDebugUIConstants.INTERNAL_ERROR, cause.getMessage(), null);
JDIDebugUIPlugin.statusDialog(ActionMessages.JavaObjectValueEditor_3, status);
} else {
JDIDebugUIPlugin.statusDialog(e.getStatus());
}
}
/**
* Evaluates the given snippet. Reports any errors to the user.
* @param stringValue the snippet to evaluate
* @return the value that was computed or <code>null</code> if any errors occurred.
*/
private IValue evaluate(String stringValue) throws DebugException {
IAdaptable adaptable = DebugUITools.getDebugContext();
IJavaStackFrame frame = adaptable.getAdapter(IJavaStackFrame.class);
if (frame != null) {
IJavaThread thread = (IJavaThread) frame.getThread();
IJavaProject project= getProject(frame);
if (project != null) {
final IEvaluationResult[] results= new IEvaluationResult[1];
IAstEvaluationEngine engine = JDIDebugPlugin.getDefault().getEvaluationEngine(project, (IJavaDebugTarget) thread.getDebugTarget());
IEvaluationListener listener= new IEvaluationListener() {
@Override
public void evaluationComplete(IEvaluationResult result) {
synchronized (JavaObjectValueEditor.this) {
results[0]= result;
JavaObjectValueEditor.this.notifyAll();
}
}
};
synchronized(this) {
engine.evaluate(stringValue, frame, listener, DebugEvent.EVALUATION_IMPLICIT, false);
try {
this.wait();
} catch (InterruptedException e) {
if (results[0] == null){
IStatus status= new Status(IStatus.ERROR, JDIDebugUIPlugin.getUniqueIdentifier(), IStatus.ERROR, ActionMessages.JavaObjectValueEditor_0, e);
throw new DebugException(status);
}
}
}
IEvaluationResult result= results[0];
if (result == null) {
return null;
}
if (result.hasErrors()) {
DebugException exception = result.getException();
StringBuffer buffer = new StringBuffer();
if (exception == null) {
String[] messages = result.getErrorMessages();
for (int i = 0; i < messages.length; i++) {
buffer.append(messages[i]).append("\n "); //$NON-NLS-1$
}
} else {
buffer.append(EvaluateAction.getExceptionMessage(exception));
}
IStatus status= new Status(IStatus.ERROR, JDIDebugUIPlugin.getUniqueIdentifier(), IStatus.ERROR, buffer.toString(), null);
throw new DebugException(status);
}
return result.getValue();
}
}
return null;
}
/**
* (copied from EvaluateAction)
*/
protected String getExceptionMessage(Throwable exception) {
if (exception instanceof CoreException) {
CoreException ce = (CoreException)exception;
Throwable throwable= ce.getStatus().getException();
if (throwable instanceof com.sun.jdi.InvocationException) {
return getInvocationExceptionMessage((com.sun.jdi.InvocationException)throwable);
} else if (throwable instanceof CoreException) {
// Traverse nested CoreExceptions
return getExceptionMessage(throwable);
}
return ce.getStatus().getMessage();
}
String message= NLS.bind(ActionMessages.Evaluate_error_message_direct_exception, new Object[] { exception.getClass() });
if (exception.getMessage() != null) {
message= NLS.bind(ActionMessages.Evaluate_error_message_exception_pattern, new Object[] { message, exception.getMessage() });
}
return message;
}
/**
* Returns a message for the exception wrapped in an invocation exception
*/
protected String getInvocationExceptionMessage(com.sun.jdi.InvocationException exception) {
InvocationException ie= exception;
ObjectReference ref= ie.exception();
return NLS.bind(ActionMessages.Evaluate_error_message_wrapped_exception, new Object[] { ref.referenceType().name() });
}
/**
* Return the project associated with the given stack frame.
* (copied from JavaWatchExpressionDelegate)
*/
private IJavaProject getProject(IJavaStackFrame javaStackFrame) {
return JavaDebugUtils.resolveJavaProject(javaStackFrame);
}
}