/******************************************************************************* * Copyright (c) 2000, 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 API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.debug.ui.actions; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.internal.ui.AbstractDebugCheckboxSelectionDialog; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugModelPresentation; import org.eclipse.jdt.debug.core.IJavaBreakpoint; import org.eclipse.jdt.debug.core.IJavaClassType; import org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint; import org.eclipse.jdt.debug.core.IJavaFieldVariable; import org.eclipse.jdt.debug.core.IJavaObject; import org.eclipse.jdt.debug.core.IJavaType; import org.eclipse.jdt.debug.core.IJavaVariable; import org.eclipse.jdt.debug.core.IJavaWatchpoint; import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants; import org.eclipse.jdt.internal.debug.ui.IJavaDebugHelpContextIds; import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Shell; /** * Action to associate an object with one or more breakpoints. */ public class InstanceFiltersAction extends ObjectActionDelegate { /** * Dialog that allows the user to select one or more breakpoints that should be restricted * to a specific object instance. */ class InstanceFilterDialog extends AbstractDebugCheckboxSelectionDialog { private Object fInput; private String fMessage; private IBaseLabelProvider fLabelProvider; public InstanceFilterDialog(Shell parentShell, Object input, IBaseLabelProvider labelProvider, String message){ super(parentShell); fInput = input; fMessage = message; fLabelProvider = labelProvider; setShellStyle(getShellStyle() | SWT.RESIZE); setShowSelectAllButtons(true); } /* (non-Javadoc) * @see org.eclipse.debug.internal.ui.AbstractDebugCheckboxSelectionDialog#isValid() */ @Override protected boolean isValid() { return true; } /* (non-Javadoc) * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getDialogSettingsId() */ @Override protected String getDialogSettingsId() { return IJavaDebugUIConstants.PLUGIN_ID + ".INSTANCE_FILTERS_ACTION_DIALOG"; //$NON-NLS-1$ } /* (non-Javadoc) * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getHelpContextId() */ @Override protected String getHelpContextId() { return IJavaDebugHelpContextIds.INSTANCE_BREAKPOINT_SELECTION_DIALOG; } /* (non-Javadoc) * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getViewerInput() */ @Override protected Object getViewerInput() { return fInput; } /* (non-Javadoc) * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getViewerLabel() */ @Override protected String getViewerLabel() { return fMessage; } /* (non-Javadoc) * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getLabelProvider() */ @Override protected IBaseLabelProvider getLabelProvider() { return fLabelProvider; } } /** * @see org.eclipse.ui.IActionDelegate#run(IAction) */ @Override public void run(IAction action) { IStructuredSelection selection = getCurrentSelection(); if (selection == null || selection.size() > 1) { return; } Object o = selection.getFirstElement(); if (o instanceof IJavaVariable) { final IJavaVariable var = (IJavaVariable)o; try { IValue value = var.getValue(); if (value instanceof IJavaObject) { final IJavaObject object = (IJavaObject)value; final List<IJavaBreakpoint> breakpoints = getApplicableBreakpoints(var, object); final IDebugModelPresentation modelPresentation= DebugUITools.newDebugModelPresentation(); if (breakpoints.isEmpty()) { MessageDialog.openInformation(JDIDebugUIPlugin.getActiveWorkbenchShell(), ActionMessages.InstanceFiltersAction_0, ActionMessages.InstanceFiltersAction_4); return; } InstanceFilterDialog dialog = new InstanceFilterDialog(JDIDebugUIPlugin.getActiveWorkbenchShell(), breakpoints, modelPresentation, NLS.bind(ActionMessages.InstanceFiltersAction_1, new String[] {var.getName()})){ @Override public void okPressed() { // check if breakpoints have already been restricted to other objects. Object[] checkBreakpoint= getCheckBoxTableViewer().getCheckedElements(); for (int k= 0; k < checkBreakpoint.length; k++) { IJavaBreakpoint breakpoint= (IJavaBreakpoint) checkBreakpoint[k]; try { IJavaObject[] instanceFilters= breakpoint.getInstanceFilters(); boolean sameTarget = false; for (int i = 0; i < instanceFilters.length; i++) { IJavaObject instanceFilter = instanceFilters[i]; if (instanceFilter.getDebugTarget().equals(object.getDebugTarget())) { sameTarget = true; break; } } if (sameTarget) { MessageDialog messageDialog= new MessageDialog(JDIDebugUIPlugin.getActiveWorkbenchShell(), ActionMessages.InstanceFiltersAction_2, null, NLS.bind(ActionMessages.InstanceFiltersAction_3, new String[] { modelPresentation.getText(breakpoint), var.getName()}), MessageDialog.QUESTION, new String[] { ActionMessages.InstanceFiltersAction_Yes_2, ActionMessages.InstanceFiltersAction_Cancel_3}, // 0); if (messageDialog.open() == Window.OK) { for (int i= 0; i < instanceFilters.length; i++) { breakpoint.removeInstanceFilter(instanceFilters[i]); } } else { // if 'cancel', do not close the instance filter dialog return; } } } catch (CoreException e) { JDIDebugUIPlugin.log(e); } } super.okPressed(); } }; dialog.setTitle(ActionMessages.InstanceFiltersAction_2); // determine initial selection List<IJavaBreakpoint> existing = new ArrayList<>(); Iterator<IJavaBreakpoint> iter = breakpoints.iterator(); while (iter.hasNext()) { IJavaBreakpoint bp = iter.next(); IJavaObject[] filters = bp.getInstanceFilters(); for (int i = 0; i < filters.length; i++) { if (filters[i].equals(object)) { existing.add(bp); break; } } } dialog.setInitialSelections(existing.toArray()); if (dialog.open() == Window.OK) { Object[] selectedBreakpoints = dialog.getResult(); if (selectedBreakpoints != null) { // add for (int i = 0; i < selectedBreakpoints.length; i++) { IJavaBreakpoint bp = (IJavaBreakpoint)selectedBreakpoints[i]; bp.addInstanceFilter(object); existing.remove(bp); } // remove iter = existing.iterator(); while (iter.hasNext()) { IJavaBreakpoint bp = iter.next(); bp.removeInstanceFilter(object); } } } } else { // only allowed for objects } } catch (CoreException e) { JDIDebugUIPlugin.log(e); } } } protected List<IJavaBreakpoint> getApplicableBreakpoints(IJavaVariable variable, IJavaObject object) { List<IJavaBreakpoint> breakpoints = new ArrayList<>(); try { // collect names in type hierarchy List<String> superTypeNames = new ArrayList<>(); IJavaType type = object.getJavaType(); while (type instanceof IJavaClassType) { superTypeNames.add(type.getName()); type = ((IJavaClassType)type).getSuperclass(); } IBreakpoint[] allBreakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(); for (int i = 0; i < allBreakpoints.length; i++) { if (allBreakpoints[i] instanceof IJavaBreakpoint) { IJavaBreakpoint jbp = (IJavaBreakpoint)allBreakpoints[i]; IJavaBreakpoint valid = null; if (jbp instanceof IJavaWatchpoint && variable instanceof IJavaFieldVariable) { IJavaWatchpoint wp = (IJavaWatchpoint)jbp; IJavaFieldVariable fv = (IJavaFieldVariable)variable; if (variable.getName().equals(wp.getFieldName()) && fv.getDeclaringType().getName().equals(wp.getTypeName())) { valid = wp; } } else if (superTypeNames.contains(jbp.getTypeName()) || jbp instanceof IJavaExceptionBreakpoint) { valid = jbp; } if (valid != null && valid.supportsInstanceFilters()) { breakpoints.add(valid); } } } } catch (CoreException e) { JDIDebugUIPlugin.log(e); } return breakpoints; } }