1 /******************************************************************************* 2 * Copyright (c) 2000, 2015 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.jdt.internal.debug.ui.actions; 15 16 import java.util.ArrayList; 17 import java.util.Iterator; 18 import java.util.List; 19 20 import org.eclipse.core.runtime.CoreException; 21 import org.eclipse.debug.core.DebugPlugin; 22 import org.eclipse.debug.core.model.IBreakpoint; 23 import org.eclipse.debug.core.model.IValue; 24 import org.eclipse.debug.internal.ui.AbstractDebugCheckboxSelectionDialog; 25 import org.eclipse.debug.ui.DebugUITools; 26 import org.eclipse.debug.ui.IDebugModelPresentation; 27 import org.eclipse.jdt.debug.core.IJavaBreakpoint; 28 import org.eclipse.jdt.debug.core.IJavaClassType; 29 import org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint; 30 import org.eclipse.jdt.debug.core.IJavaFieldVariable; 31 import org.eclipse.jdt.debug.core.IJavaObject; 32 import org.eclipse.jdt.debug.core.IJavaType; 33 import org.eclipse.jdt.debug.core.IJavaVariable; 34 import org.eclipse.jdt.debug.core.IJavaWatchpoint; 35 import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants; 36 import org.eclipse.jdt.internal.debug.ui.IJavaDebugHelpContextIds; 37 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; 38 import org.eclipse.jface.action.IAction; 39 import org.eclipse.jface.dialogs.MessageDialog; 40 import org.eclipse.jface.viewers.IBaseLabelProvider; 41 import org.eclipse.jface.viewers.IStructuredSelection; 42 import org.eclipse.jface.window.Window; 43 import org.eclipse.osgi.util.NLS; 44 import org.eclipse.swt.SWT; 45 import org.eclipse.swt.widgets.Shell; 46 47 /** 48 * Action to associate an object with one or more breakpoints. 49 */ 50 public class InstanceFiltersAction extends ObjectActionDelegate { 51 52 /** 53 * Dialog that allows the user to select one or more breakpoints that should be restricted 54 * to a specific object instance. 55 */ 56 class InstanceFilterDialog extends AbstractDebugCheckboxSelectionDialog { 57 58 private Object fInput; 59 private String fMessage; 60 private IBaseLabelProvider fLabelProvider; 61 InstanceFilterDialog(Shell parentShell, Object input, IBaseLabelProvider labelProvider, String message)62 public InstanceFilterDialog(Shell parentShell, Object input, IBaseLabelProvider labelProvider, String message){ 63 super(parentShell); 64 fInput = input; 65 fMessage = message; 66 fLabelProvider = labelProvider; 67 setShellStyle(getShellStyle() | SWT.RESIZE); 68 setShowSelectAllButtons(true); 69 } 70 71 /* (non-Javadoc) 72 * @see org.eclipse.debug.internal.ui.AbstractDebugCheckboxSelectionDialog#isValid() 73 */ 74 @Override isValid()75 protected boolean isValid() { 76 return true; 77 } 78 79 /* (non-Javadoc) 80 * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getDialogSettingsId() 81 */ 82 @Override getDialogSettingsId()83 protected String getDialogSettingsId() { 84 return IJavaDebugUIConstants.PLUGIN_ID + ".INSTANCE_FILTERS_ACTION_DIALOG"; //$NON-NLS-1$ 85 } 86 87 /* (non-Javadoc) 88 * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getHelpContextId() 89 */ 90 @Override getHelpContextId()91 protected String getHelpContextId() { 92 return IJavaDebugHelpContextIds.INSTANCE_BREAKPOINT_SELECTION_DIALOG; 93 } 94 95 /* (non-Javadoc) 96 * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getViewerInput() 97 */ 98 @Override getViewerInput()99 protected Object getViewerInput() { 100 return fInput; 101 } 102 103 /* (non-Javadoc) 104 * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getViewerLabel() 105 */ 106 @Override getViewerLabel()107 protected String getViewerLabel() { 108 return fMessage; 109 } 110 111 /* (non-Javadoc) 112 * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getLabelProvider() 113 */ 114 @Override getLabelProvider()115 protected IBaseLabelProvider getLabelProvider() { 116 return fLabelProvider; 117 } 118 } 119 120 /** 121 * @see org.eclipse.ui.IActionDelegate#run(IAction) 122 */ 123 @Override run(IAction action)124 public void run(IAction action) { 125 IStructuredSelection selection = getCurrentSelection(); 126 if (selection == null || selection.size() > 1) { 127 return; 128 } 129 130 Object o = selection.getFirstElement(); 131 if (o instanceof IJavaVariable) { 132 final IJavaVariable var = (IJavaVariable)o; 133 try { 134 IValue value = var.getValue(); 135 if (value instanceof IJavaObject) { 136 final IJavaObject object = (IJavaObject)value; 137 final List<IJavaBreakpoint> breakpoints = getApplicableBreakpoints(var, object); 138 final IDebugModelPresentation modelPresentation= DebugUITools.newDebugModelPresentation(); 139 140 if (breakpoints.isEmpty()) 141 { 142 MessageDialog.openInformation(JDIDebugUIPlugin.getActiveWorkbenchShell(), ActionMessages.InstanceFiltersAction_0, ActionMessages.InstanceFiltersAction_4); 143 return; 144 } 145 146 InstanceFilterDialog dialog = new InstanceFilterDialog(JDIDebugUIPlugin.getActiveWorkbenchShell(), breakpoints, modelPresentation, NLS.bind(ActionMessages.InstanceFiltersAction_1, new String[] {var.getName()})){ 147 @Override 148 public void okPressed() { 149 // check if breakpoints have already been restricted to other objects. 150 Object[] checkBreakpoint= getCheckBoxTableViewer().getCheckedElements(); 151 for (int k= 0; k < checkBreakpoint.length; k++) { 152 IJavaBreakpoint breakpoint= (IJavaBreakpoint) checkBreakpoint[k]; 153 try { 154 IJavaObject[] instanceFilters= breakpoint.getInstanceFilters(); 155 boolean sameTarget = false; 156 for (int i = 0; i < instanceFilters.length; i++) { 157 IJavaObject instanceFilter = instanceFilters[i]; 158 if (instanceFilter.getDebugTarget().equals(object.getDebugTarget())) { 159 sameTarget = true; 160 break; 161 } 162 } 163 if (sameTarget) { 164 MessageDialog messageDialog= new MessageDialog(JDIDebugUIPlugin.getActiveWorkbenchShell(), ActionMessages.InstanceFiltersAction_2, 165 null, NLS.bind(ActionMessages.InstanceFiltersAction_3, new String[] { modelPresentation.getText(breakpoint), var.getName()}), 166 MessageDialog.QUESTION, new String[] { ActionMessages.InstanceFiltersAction_Yes_2, ActionMessages.InstanceFiltersAction_Cancel_3}, // 167 0); 168 if (messageDialog.open() == Window.OK) { 169 for (int i= 0; i < instanceFilters.length; i++) { 170 breakpoint.removeInstanceFilter(instanceFilters[i]); 171 } 172 } else { 173 // if 'cancel', do not close the instance filter dialog 174 return; 175 } 176 } 177 } catch (CoreException e) { 178 JDIDebugUIPlugin.log(e); 179 } 180 } 181 super.okPressed(); 182 } 183 }; 184 dialog.setTitle(ActionMessages.InstanceFiltersAction_2); 185 186 // determine initial selection 187 List<IJavaBreakpoint> existing = new ArrayList<>(); 188 Iterator<IJavaBreakpoint> iter = breakpoints.iterator(); 189 while (iter.hasNext()) { 190 IJavaBreakpoint bp = iter.next(); 191 IJavaObject[] filters = bp.getInstanceFilters(); 192 for (int i = 0; i < filters.length; i++) { 193 if (filters[i].equals(object)) { 194 existing.add(bp); 195 break; 196 } 197 } 198 } 199 dialog.setInitialSelections(existing.toArray()); 200 201 if (dialog.open() == Window.OK) { 202 Object[] selectedBreakpoints = dialog.getResult(); 203 if (selectedBreakpoints != null) { 204 // add 205 for (int i = 0; i < selectedBreakpoints.length; i++) { 206 IJavaBreakpoint bp = (IJavaBreakpoint)selectedBreakpoints[i]; 207 bp.addInstanceFilter(object); 208 existing.remove(bp); 209 } 210 // remove 211 iter = existing.iterator(); 212 while (iter.hasNext()) { 213 IJavaBreakpoint bp = iter.next(); 214 bp.removeInstanceFilter(object); 215 } 216 } 217 } 218 } else { 219 // only allowed for objects 220 } 221 } catch (CoreException e) { 222 JDIDebugUIPlugin.log(e); 223 } 224 } 225 } 226 getApplicableBreakpoints(IJavaVariable variable, IJavaObject object)227 protected List<IJavaBreakpoint> getApplicableBreakpoints(IJavaVariable variable, IJavaObject object) { 228 List<IJavaBreakpoint> breakpoints = new ArrayList<>(); 229 230 try { 231 // collect names in type hierarchy 232 List<String> superTypeNames = new ArrayList<>(); 233 IJavaType type = object.getJavaType(); 234 while (type instanceof IJavaClassType) { 235 superTypeNames.add(type.getName()); 236 type = ((IJavaClassType)type).getSuperclass(); 237 } 238 239 IBreakpoint[] allBreakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(); 240 for (int i = 0; i < allBreakpoints.length; i++) { 241 if (allBreakpoints[i] instanceof IJavaBreakpoint) { 242 IJavaBreakpoint jbp = (IJavaBreakpoint)allBreakpoints[i]; 243 IJavaBreakpoint valid = null; 244 if (jbp instanceof IJavaWatchpoint && variable instanceof IJavaFieldVariable) { 245 IJavaWatchpoint wp = (IJavaWatchpoint)jbp; 246 IJavaFieldVariable fv = (IJavaFieldVariable)variable; 247 if (variable.getName().equals(wp.getFieldName()) && fv.getDeclaringType().getName().equals(wp.getTypeName())) { 248 valid = wp; 249 } 250 } else if (superTypeNames.contains(jbp.getTypeName()) || jbp instanceof IJavaExceptionBreakpoint) { 251 valid = jbp; 252 } 253 if (valid != null && valid.supportsInstanceFilters()) { 254 breakpoints.add(valid); 255 } 256 } 257 } 258 } catch (CoreException e) { 259 JDIDebugUIPlugin.log(e); 260 } 261 262 return breakpoints; 263 } 264 265 } 266