blob: 9c674f4b9f979c0a57f1c91b3517e2b5ab4ef2e8 [file] [log] [blame]
package org.eclipse.jdt.internal.debug.ui.actions;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.ITypeNameRequestor;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.debug.core.IJavaBreakpoint;
import org.eclipse.jdt.debug.core.IJavaFieldVariable;
import org.eclipse.jdt.debug.core.IJavaWatchpoint;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.internal.corext.util.TypeInfo;
import org.eclipse.jdt.internal.corext.util.TypeInfoRequestor;
import org.eclipse.jdt.internal.debug.ui.BreakpointUtils;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.texteditor.ITextEditor;
public class ManageWatchpointActionDelegate extends AbstractManageBreakpointActionDelegate {
/**
* @see IActionDelegate#run(IAction)
*/
public void run(IAction action) {
updateForRun();
if (getBreakpoint() == null) {
try {
IMember element= getMember();
if (element == null || !enableForMember(element)) {
beep();
return;
}
IType type = element.getDeclaringType();
int start = -1;
int end = -1;
ISourceRange range = element.getNameRange();
if (range != null) {
start = range.getOffset();
end = start + range.getLength();
}
Map attributes = new HashMap(10);
BreakpointUtils.addJavaBreakpointAttributes(attributes, element);
setBreakpoint(JDIDebugModel.createWatchpoint(BreakpointUtils.getBreakpointResource(type),type.getFullyQualifiedName(), element.getElementName(), -1, start, end, 0, true, attributes));
} catch (JavaModelException e) {
JDIDebugUIPlugin.log(e);
MessageDialog.openError(JDIDebugUIPlugin.getActiveWorkbenchShell(), ActionMessages.getString("ManageWatchpointAction.Problems_adding_watchpoint_7"), ActionMessages.getString("ManageWatchpointAction.The_selected_field_is_not_visible_in_the_currently_selected_debug_context._A_stack_frame_or_suspended_thread_which_contains_the_declaring_type_of_this_field_must_be_selected_1")); //$NON-NLS-1$ //$NON-NLS-2$
} catch (CoreException x) {
JDIDebugUIPlugin.log(x);
MessageDialog.openError(JDIDebugUIPlugin.getActiveWorkbenchShell(), ActionMessages.getString("ManageWatchpointAction.Problems_adding_watchpoint_7"), x.getMessage()); //$NON-NLS-1$
}
} else {
// remove breakpoint
try {
IBreakpointManager breakpointManager= DebugPlugin.getDefault().getBreakpointManager();
breakpointManager.removeBreakpoint(getBreakpoint(), true);
} catch (CoreException x) {
JDIDebugUIPlugin.log(x);
MessageDialog.openError(JDIDebugUIPlugin.getActiveWorkbenchShell(), ActionMessages.getString("ManageWatchpointAction.Problems_removing_watchpoint_8"), x.getMessage()); //$NON-NLS-1$
}
}
}
protected IJavaBreakpoint getBreakpoint(IMember selectedField) {
IBreakpointManager breakpointManager= DebugPlugin.getDefault().getBreakpointManager();
IBreakpoint[] breakpoints= breakpointManager.getBreakpoints(JDIDebugModel.getPluginIdentifier());
for (int i= 0; i < breakpoints.length; i++) {
IBreakpoint breakpoint= breakpoints[i];
if (breakpoint instanceof IJavaWatchpoint) {
try {
if (equalFields(selectedField, (IJavaWatchpoint)breakpoint))
return (IJavaBreakpoint)breakpoint;
} catch (CoreException e) {
JDIDebugUIPlugin.log(e);
}
}
}
return null;
}
/**
* Compare two fields. The default <code>equals()</code>
* method for <code>IField</code> doesn't give the comparison desired.
*/
private boolean equalFields(IMember breakpointField, IJavaWatchpoint watchpoint) throws CoreException {
return (breakpointField.getElementName().equals(watchpoint.getFieldName()) &&
breakpointField.getDeclaringType().getFullyQualifiedName().equals(watchpoint.getTypeName()));
}
protected IMember getMember(ISelection s) {
if (s instanceof IStructuredSelection) {
IStructuredSelection ss= (IStructuredSelection) s;
if (ss.size() == 1) {
Object o= ss.getFirstElement();
if (o instanceof IField) {
return (IField) o;
} else if (o instanceof IJavaFieldVariable) {
return getField((IJavaFieldVariable) o);
}
}
}
return null;
}
/**
* Return the associated IField (Java model) for the given
* IJavaFieldVariable (JDI model)
*/
protected IField getField(IJavaFieldVariable variable) {
String varName= null;
try {
varName= variable.getName();
} catch (DebugException x) {
JDIDebugUIPlugin.log(x);
return null;
}
IField field;
List types= searchForDeclaringType(variable);
Iterator iter= types.iterator();
while (iter.hasNext()) {
IType type= (IType)iter.next();
field= type.getField(varName);
if (field.exists()) {
return field;
}
}
return null;
}
/**
* Returns a list of matching types (IType - Java model) that correspond to the
* declaring type (ReferenceType - JDI model) of the given variable.
*/
protected List searchForDeclaringType(IJavaFieldVariable variable) {
List types= new ArrayList();
ILaunch launch = variable.getDebugTarget().getLaunch();
if (launch == null) {
return types;
}
ILaunchConfiguration configuration= launch.getLaunchConfiguration();
IJavaProject[] javaProjects = null;
IWorkspace workspace= ResourcesPlugin.getWorkspace();
if (configuration != null) {
// Launch configuration support
try {
String projectName= configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$
if (projectName.length() != 0) {
javaProjects= new IJavaProject[] {JavaCore.create(workspace.getRoot().getProject(projectName))};
} else {
IProject[] projects= ResourcesPlugin.getWorkspace().getRoot().getProjects();
IProject project;
List projectList= new ArrayList();
for (int i= 0, numProjects= projects.length; i < numProjects; i++) {
project= projects[i];
if (project.isAccessible() && project.hasNature(JavaCore.NATURE_ID)) {
projectList.add(JavaCore.create(project));
}
}
javaProjects= new IJavaProject[projectList.size()];
projectList.toArray(javaProjects);
}
} catch (CoreException e) {
JDIDebugUIPlugin.log(e);
}
}
if (javaProjects == null) {
return types;
}
SearchEngine engine= new SearchEngine();
IJavaSearchScope scope= engine.createJavaSearchScope(javaProjects, true);
String declaringType= null;
try {
declaringType= variable.getDeclaringType().getName();
} catch (DebugException x) {
JDIDebugUIPlugin.log(x);
return types;
}
ArrayList typeRefsFound= new ArrayList(3);
ITypeNameRequestor requestor= new TypeInfoRequestor(typeRefsFound);
try {
engine.searchAllTypeNames(workspace,
getPackage(declaringType),
getTypeName(declaringType),
IJavaSearchConstants.EXACT_MATCH,
true,
IJavaSearchConstants.CLASS,
scope,
requestor,
IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
null);
} catch (JavaModelException x) {
JDIDebugUIPlugin.log(x);
return types;
}
Iterator iter= typeRefsFound.iterator();
TypeInfo typeInfo= null;
while (iter.hasNext()) {
typeInfo= (TypeInfo)iter.next();
try {
types.add(typeInfo.resolveType(scope));
} catch (JavaModelException jme) {
JDIDebugUIPlugin.log(jme);
}
}
return types;
}
/**
* Returns the package name of the given fully qualified type name.
* The package name is assumed to be the dot-separated prefix of the
* type name.
*/
protected char[] getPackage(String fullyQualifiedName) {
int index= fullyQualifiedName.lastIndexOf('.');
if (index == -1) {
return new char[0];
}
return fullyQualifiedName.substring(0, index).toCharArray();
}
/**
* Returns a simple type name from the given fully qualified type name.
* The type name is assumed to be the last contiguous segment of the
* fullyQualifiedName not containing a '.' or '$'
*/
protected char[] getTypeName(String fullyQualifiedName) {
int index= fullyQualifiedName.lastIndexOf('.');
String typeName= fullyQualifiedName.substring(index + 1);
int lastInnerClass= typeName.lastIndexOf('$');
if (lastInnerClass != -1) {
typeName= typeName.substring(lastInnerClass + 1);
}
return typeName.toCharArray();
}
/**
* @see AbstractManageBreakpointActionDelegate#enableForMember(IMember)
*/
protected boolean enableForMember(IMember member) {
return member instanceof IField;
}
protected void setEnabledState(ITextEditor editor) {
if (getAction() != null && getPage() != null) {
IWorkbenchPart part = getPage().getActivePart();
if (part == null) {
getAction().setEnabled(false);
} else if (part != getPage().getActiveEditor()) {
ISelectionProvider sp= part.getSite().getSelectionProvider();
getAction().setEnabled(sp != null && enableForMember(getMember(sp.getSelection())));
} else { //dealing with active editor
if (getPage().getActiveEditor() instanceof ITextEditor) {
super.setEnabledState((ITextEditor)getPage().getActiveEditor());
} else {
getAction().setEnabled(false);
}
}
}
}
}