blob: a0abcef9aa44f520c9c74d4583dd1687ab9fb214 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.debug.core.logicalstructures;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
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.DebugPlugin;
import org.eclipse.debug.core.IStatusHandler;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
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.IJavaType;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
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.model.JDIReferenceType;
public class JavaLogicalStructure {
// stack frame context provider
public static final int INFO_EVALUATION_STACK_FRAME = 111;
private static IStatus fgNeedStackFrame = new Status(IStatus.INFO, JDIDebugPlugin.getUniqueIdentifier(), INFO_EVALUATION_STACK_FRAME, "Provides thread context for an evaluation", null); //$NON-NLS-1$
private static IStatusHandler fgStackFrameProvider;
/**
* Fully qualified type name.
*/
private final String fType;
/**
* Indicate if this java logical structure should be used on object
* instance of subtype of the specified type.
*/
private final boolean fSubtypes;
/**
* Code snippet to evaluate to create the logical value.
*/
private final String fValue;
/**
* Name and associated code snippet of the variables of the logical value.
*/
private final String[][] fVariables;
/**
* Performs the evaluations.
*/
static class EvaluationBlock implements IEvaluationListener {
private IJavaObject fEvaluationValue;
private IJavaReferenceType fEvaluationType;
private IJavaThread fThread;
private IAstEvaluationEngine fEvaluationEngine;
private IEvaluationResult fResult;
public EvaluationBlock(IJavaObject value, IJavaReferenceType type, IJavaThread thread, IAstEvaluationEngine evaluationEngine) {
fEvaluationValue= value;
fEvaluationType= type;
fThread= thread;
fEvaluationEngine= evaluationEngine;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.debug.eval.IEvaluationListener#evaluationComplete(org.eclipse.jdt.debug.eval.IEvaluationResult)
*/
public void evaluationComplete(IEvaluationResult result) {
synchronized(this) {
fResult= result;
this.notify();
}
}
public IJavaValue evaluate(String snippet) throws DebugException {
ICompiledExpression compiledExpression= fEvaluationEngine.getCompiledExpression(snippet, fEvaluationType);
if (compiledExpression.hasErrors()) {
String[] errorMessages = compiledExpression.getErrorMessages();
for (int i = 0; i < errorMessages.length; i++) {
JDIDebugPlugin.logDebugMessage(errorMessages[i]);
}
return null;
}
fResult= null;
fEvaluationEngine.evaluateExpression(compiledExpression, fEvaluationValue, fThread, this, DebugEvent.EVALUATION_IMPLICIT, false);
synchronized(this) {
if (fResult == null) {
try {
this.wait();
} catch (InterruptedException e) {
}
}
}
if (fResult == null) {
return null;
}
if (fResult.hasErrors()) {
DebugException exception = fResult.getException();
if (exception != null) {
JDIDebugPlugin.log(exception);
}
return null;
}
return fResult.getValue();
}
}
public JavaLogicalStructure(String type, boolean subtypes, String value, String[][] variables) {
fType= type;
fSubtypes= subtypes;
fValue= value;
fVariables= variables;
}
/**
* @see org.eclipse.debug.core.model.ILogicalStructureTypeDelegate#providesLogicalStructure(IValue)
*/
public boolean providesLogicalStructure(IJavaObject value) {
return getType(value) != null;
}
/**
* @see org.eclipse.debug.core.model.ILogicalStructureTypeDelegate#getLogicalStructure(IValue)
*/
public IJavaValue getLogicalStructure(IJavaObject value) {
try {
IJavaReferenceType type = getType(value);
if (type == null) {
return null;
}
IJavaStackFrame stackFrame= getStackFrame(value);
if (stackFrame == null) {
return null;
}
// find the project the snippets will be compiled in.
ISourceLocator locator= value.getLaunch().getSourceLocator();
Object sourceElement= null;
if (locator instanceof ISourceLookupDirector) {
if (type instanceof JDIReferenceType) {
String[] sourcePaths= ((JDIReferenceType) type).getSourcePaths(null);
if (sourcePaths.length > 0) {
sourceElement= ((ISourceLookupDirector) locator).getSourceElement(sourcePaths[0]);
}
}
}
if (sourceElement == null) {
sourceElement = locator.getSourceElement(stackFrame);
}
if (!(sourceElement instanceof IJavaElement) && sourceElement instanceof IAdaptable) {
sourceElement = ((IAdaptable)sourceElement).getAdapter(IJavaElement.class);
}
IJavaProject project= null;
if (sourceElement instanceof IJavaElement) {
project= ((IJavaElement) sourceElement).getJavaProject();
} else if (sourceElement instanceof IResource) {
IJavaProject resourceProject = JavaCore.create(((IResource)sourceElement).getProject());
if (resourceProject.exists()) {
project= resourceProject;
}
}
if (project == null) {
return null;
}
IAstEvaluationEngine evaluationEngine= JDIDebugPlugin.getDefault().getEvaluationEngine(project, (IJavaDebugTarget)stackFrame.getDebugTarget());
EvaluationBlock evaluationBlock= new EvaluationBlock(value, type, (IJavaThread)stackFrame.getThread(), evaluationEngine);
if (fValue == null) {
// evaluate each variable
IJavaVariable[] variables= new IJavaVariable[fVariables.length];
for (int i= 0; i < fVariables.length; i++) {
variables[i]= new JDIPlaceholderVariable(fVariables[i][0], evaluationBlock.evaluate(fVariables[i][1]));
}
return new LogicalObjectStructureValue(value, variables);
}
// evaluate the logical value
return evaluationBlock.evaluate(fValue);
} catch (CoreException e) {
JDIDebugPlugin.log(e);
}
return null;
}
private IJavaReferenceType getType(IJavaObject value) {
try {
IJavaType type= value.getJavaType();
if (!(type instanceof IJavaClassType)) {
return null;
}
IJavaClassType classType= (IJavaClassType) type;
if (classType.getName().equals(fType)) {
// found the type
return classType;
}
if (!fSubtypes) {
// if not checking the subtypes, stop here
return null;
}
IJavaClassType superClass= classType.getSuperclass();
while (superClass != null) {
if (superClass.getName().equals(fType)) {
// found the type, it's a super class
return superClass;
}
superClass= superClass.getSuperclass();
}
IJavaInterfaceType[] superInterfaces= classType.getAllInterfaces();
for (int i= 0; i < superInterfaces.length; i++) {
if (superInterfaces[i].getName().equals(fType)) {
// found the type, it's a super interface
return superInterfaces[i];
}
}
} catch (DebugException e) {
JDIDebugPlugin.log(e);
return null;
}
return null;
}
/**
* Return the current stack frame context, or a valid stack frame for the given value.
*/
private IJavaStackFrame getStackFrame(IValue value) throws CoreException {
IStatusHandler handler = getStackFrameProvider();
if (handler != null) {
IJavaStackFrame stackFrame = (IJavaStackFrame)handler.handleStatus(fgNeedStackFrame, value);
if (stackFrame != null) {
return stackFrame;
}
}
IDebugTarget target = value.getDebugTarget();
IJavaDebugTarget javaTarget = (IJavaDebugTarget) target.getAdapter(IJavaDebugTarget.class);
if (javaTarget != null) {
IThread[] threads = javaTarget.getThreads();
for (int i = 0; i < threads.length; i++) {
IThread thread = threads[i];
if (thread.isSuspended()) {
return (IJavaStackFrame)thread.getTopStackFrame();
}
}
}
return null;
}
private static IStatusHandler getStackFrameProvider() {
if (fgStackFrameProvider == null) {
fgStackFrameProvider = DebugPlugin.getDefault().getStatusHandler(fgNeedStackFrame);
}
return fgStackFrameProvider;
}
}