cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointAttributeTranslator.java
changeset 117 09f3d307f081
equal deleted inserted replaced
116:05ea843f7d56 117:09f3d307f081
       
     1 /*******************************************************************************
       
     2  * Copyright (c) 2009 Nokia and others.
       
     3  * All rights reserved. This program and the accompanying materials
       
     4  * are made available under the terms of the Eclipse Public License v1.0
       
     5  * which accompanies this distribution, and is available at
       
     6  * http://www.eclipse.org/legal/epl-v10.html
       
     7  *
       
     8  * Contributors:
       
     9  * 	Nokia - Initial API and implementation. Nov, 2009.
       
    10  *******************************************************************************/
       
    11 package org.eclipse.cdt.dsf.mi.service;
       
    12 
       
    13 import java.util.ArrayList;
       
    14 import java.util.HashMap;
       
    15 import java.util.HashSet;
       
    16 import java.util.List;
       
    17 import java.util.Map;
       
    18 import java.util.Set;
       
    19 
       
    20 import org.eclipse.cdt.debug.core.model.ICBreakpoint;
       
    21 import org.eclipse.cdt.debug.core.model.ICBreakpointExtension;
       
    22 import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
       
    23 import org.eclipse.cdt.debug.core.model.ICWatchpoint;
       
    24 import org.eclipse.cdt.debug.internal.core.breakpoints.BreakpointProblems;
       
    25 import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
       
    26 import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
       
    27 import org.eclipse.cdt.dsf.datamodel.DMContexts;
       
    28 import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator;
       
    29 import org.eclipse.cdt.dsf.debug.service.IBreakpointAttributeTranslatorExtension;
       
    30 import org.eclipse.cdt.dsf.debug.service.IDsfBreakpointExtension;
       
    31 import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
       
    32 import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator.BreakpointEventType;
       
    33 import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator.ITargetBreakpointInfo;
       
    34 import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
       
    35 import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
       
    36 import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
       
    37 import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
       
    38 import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
       
    39 import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
       
    40 import org.eclipse.cdt.dsf.service.DsfServicesTracker;
       
    41 import org.eclipse.cdt.dsf.service.DsfSession;
       
    42 import org.eclipse.core.resources.IMarker;
       
    43 import org.eclipse.core.resources.IResource;
       
    44 import org.eclipse.core.runtime.CoreException;
       
    45 import org.eclipse.core.runtime.IProgressMonitor;
       
    46 import org.eclipse.core.runtime.IStatus;
       
    47 import org.eclipse.core.runtime.Platform;
       
    48 import org.eclipse.core.runtime.Status;
       
    49 import org.eclipse.core.runtime.jobs.Job;
       
    50 import org.eclipse.debug.core.DebugException;
       
    51 import org.eclipse.debug.core.model.IBreakpoint;
       
    52 
       
    53 public class MIBreakpointAttributeTranslator implements IBreakpointAttributeTranslatorExtension {
       
    54 
       
    55     private final static String GDB_DEBUG_MODEL_ID = "org.eclipse.cdt.dsf.gdb"; //$NON-NLS-1$
       
    56 
       
    57     // Extra breakpoint attributes
       
    58     private static final String ATTR_DEBUGGER_PATH = GdbPlugin.PLUGIN_ID + ".debuggerPath";   //$NON-NLS-1$
       
    59     private static final String ATTR_THREAD_FILTER = GdbPlugin.PLUGIN_ID + ".threadFilter";   //$NON-NLS-1$
       
    60 //    private static final String ATTR_THREAD_ID     = GdbPlugin.PLUGIN_ID + ".threadID";       //$NON-NLS-1$
       
    61 
       
    62 	private DsfServicesTracker	dsfServicesTracker;
       
    63 	private DsfSession			dsfSession;
       
    64 	private BreakpointsMediator	breakpointsMediator;
       
    65 	private String				debugModelId;
       
    66 
       
    67 	/**
       
    68 	 * Manage breakpoint problem markers. <br>
       
    69 	 * It's better be done by MIBreakpoints service so that it's accessible by
       
    70 	 * the MIBreakpoints service too. But to minimize change to MIBreakpoints in
       
    71 	 * this iteration, I just put it here..... 11/18/09
       
    72 	 */
       
    73     private Map<ICBreakpoint, IMarker> fBreakpointMarkerProblems =
       
    74         new HashMap<ICBreakpoint, IMarker>();
       
    75 
       
    76 	public MIBreakpointAttributeTranslator(DsfSession dsfSession, String debugModelId) {
       
    77 		super();
       
    78 		this.dsfSession = dsfSession;
       
    79 		this.debugModelId = debugModelId;
       
    80 		
       
    81 		dsfServicesTracker = new DsfServicesTracker(GdbPlugin.getDefault().getBundle().getBundleContext(), dsfSession.getId());
       
    82 	}
       
    83 
       
    84 	public boolean canUpdateAttributes(IBreakpointDMContext bp, Map<String, Object> delta) {
       
    85 		/*
       
    86 		 * This method decides whether we need to re-install the breakpoint
       
    87 		 * based on the attributes change (refer to caller in
       
    88 		 * BreakpointsMediator).
       
    89 		 */         
       
    90         // Check if there is any modified attribute
       
    91         if (delta == null || delta.size() == 0)
       
    92             return true;
       
    93 
       
    94         // Check the "critical" attributes
       
    95         if (delta.containsKey(ATTR_DEBUGGER_PATH)            // File name
       
    96         ||  delta.containsKey(MIBreakpoints.LINE_NUMBER)     // Line number
       
    97         ||  delta.containsKey(MIBreakpoints.FUNCTION)        // Function name
       
    98         ||  delta.containsKey(MIBreakpoints.ADDRESS)         // Absolute address
       
    99         ||  delta.containsKey(ATTR_THREAD_FILTER)            // Thread ID
       
   100         ||  delta.containsKey(MIBreakpoints.EXPRESSION)      // Watchpoint expression
       
   101         ||  delta.containsKey(MIBreakpoints.READ)            // Watchpoint type
       
   102         ||  delta.containsKey(MIBreakpoints.WRITE)) {        // Watchpoint type
       
   103             return false;
       
   104         }
       
   105 
       
   106         // for other attrs (ICBreakpoint.INSTALL_COUNT, ICBreakpoint.IGNORE_COUNT,
       
   107         // ICBreakpoint.CONDITION, etc), we can update them.
       
   108         return true;
       
   109 	}
       
   110 
       
   111 	public void dispose() {
       
   112 		if (dsfServicesTracker != null)
       
   113 			dsfServicesTracker.dispose();
       
   114 		dsfSession = null;
       
   115 		
       
   116 		clearBreakpointProblemMarkers();
       
   117 	}
       
   118 
       
   119 	public List<Map<String, Object>> getBreakpointAttributes(IBreakpoint bp, boolean bpManagerEnabled)
       
   120 			throws CoreException {
       
   121 		// deprecated
       
   122 		List<Map<String, Object>> retVal = new ArrayList<Map<String, Object>>();
       
   123 		return retVal;
       
   124 	}
       
   125 
       
   126 	public void initialize(BreakpointsMediator mediator) {
       
   127 		breakpointsMediator = mediator;
       
   128 	}
       
   129 
       
   130 	public boolean supportsBreakpoint(IBreakpoint bp) {
       
   131         if (bp instanceof ICBreakpoint && bp.getModelIdentifier().equals(debugModelId)) {
       
   132             IMarker marker = bp.getMarker();
       
   133             if (marker != null) {
       
   134                 return true;
       
   135             }
       
   136         }
       
   137         return false;
       
   138 	}
       
   139 
       
   140 	public void updateBreakpointStatus(IBreakpoint bp) {
       
   141 		// obsolet, do nothing.
       
   142 	}
       
   143 
       
   144 	public void updateBreakpointsStatus(Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> bpsInfo,
       
   145 			BreakpointEventType eventType) {
       
   146 		for (IBreakpoint bp : bpsInfo.keySet()) {
       
   147 			if (! (bp instanceof ICBreakpoint))	// not C breakpoints, bail out.
       
   148 				return;
       
   149 			
       
   150 			final ICBreakpoint icbp = (ICBreakpoint) bp;
       
   151 
       
   152 			Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBpPerContext = bpsInfo.get(bp);
       
   153 			
       
   154 			switch (eventType) {
       
   155 			case ADDED: {
       
   156 				int installCountTotal = 0;
       
   157 				StringBuffer errMsg = new StringBuffer();
       
   158 				for (ITargetBreakpointInfo[] tbpInfos : targetBpPerContext.values()) {
       
   159 					// For each BpTargetDMContext, we increment the installCount for each
       
   160 					// target BP that has been successfully installed.
       
   161 					int installCountPerContext = 0;
       
   162 					for (ITargetBreakpointInfo tbp : tbpInfos) {
       
   163 						if (tbp.getTargetBreakpoint() != null)
       
   164 							installCountPerContext++;
       
   165 						else // failure in installation
       
   166 							errMsg.append(tbp.getStatus().getMessage()).append('\n');
       
   167 					}
       
   168 					installCountTotal += installCountPerContext;
       
   169 				}
       
   170 
       
   171 				for (int i=0; i < installCountTotal; i++)
       
   172 					try {
       
   173 						// this will eventually carried out in a workspace runnable.
       
   174 						icbp.incrementInstallCount();
       
   175 					} catch (CoreException e) {
       
   176 						GdbPlugin.getDefault().getLog().log(e.getStatus());
       
   177 					}
       
   178 				
       
   179 				if (errMsg.length() > 0)
       
   180 					addBreakpointProblemMarker(icbp, errMsg.toString(), IMarker.SEVERITY_WARNING);
       
   181 				else // no error, clean message if any.
       
   182 					removeBreakpointProblemMarker(icbp);
       
   183 				
       
   184 				break;
       
   185 				}
       
   186 			case MODIFIED:
       
   187 				break;
       
   188 
       
   189 			case REMOVED: {
       
   190 				int removeCountTotal = 0;
       
   191 				for (ITargetBreakpointInfo[] tbpInfos : targetBpPerContext.values()) {
       
   192 					// For each BpTargetDMContext, we decrement the installCount for each
       
   193 					// target BP that we tried to remove, even if the removal failed. That's
       
   194 					// because I've not seen a way to tell platform that removal fails 
       
   195 					// and the BP should be kept in UI.
       
   196 					removeCountTotal += tbpInfos.length;
       
   197 				}
       
   198 
       
   199 				for (int i=0; i < removeCountTotal; i++)
       
   200 					try {
       
   201 						if (icbp.isRegistered())	// not deleted in UI
       
   202 							icbp.decrementInstallCount();
       
   203 					} catch (CoreException e) {
       
   204 						GdbPlugin.getDefault().getLog().log(e.getStatus());
       
   205 					}
       
   206 				break;
       
   207 				}
       
   208 			}
       
   209 		}
       
   210 	}
       
   211 
       
   212 	public Map<String, Object> convertAttributes(Map<String, Object> platformAttrs) {
       
   213 		Map<String, Object> targetAttrs = new HashMap<String, Object>();
       
   214 
       
   215 		if (platformAttrs.containsKey(MIBreakpoints.BREAKPOINT_TYPE))
       
   216 			targetAttrs.put(MIBreakpoints.BREAKPOINT_TYPE,      platformAttrs.get(MIBreakpoints.BREAKPOINT_TYPE));
       
   217         	
       
   218 		if (platformAttrs.containsKey(ICWatchpoint.EXPRESSION))
       
   219 			targetAttrs.put(MIBreakpoints.EXPRESSION,      platformAttrs.get(ICWatchpoint.EXPRESSION));
       
   220 		if (platformAttrs.containsKey(ICWatchpoint.READ))
       
   221 			targetAttrs.put(MIBreakpoints.READ,            platformAttrs.get(ICWatchpoint.READ));
       
   222 		if (platformAttrs.containsKey(ICWatchpoint.WRITE))
       
   223 			targetAttrs.put(MIBreakpoints.WRITE,           platformAttrs.get(ICWatchpoint.WRITE));
       
   224 
       
   225 		if (platformAttrs.containsKey(ICBreakpoint.SOURCE_HANDLE))
       
   226 			targetAttrs.put(MIBreakpoints.FILE_NAME,       platformAttrs.get(ICBreakpoint.SOURCE_HANDLE));
       
   227 
       
   228 		if (platformAttrs.containsKey(IMarker.LINE_NUMBER))
       
   229 			targetAttrs.put(MIBreakpoints.LINE_NUMBER,     platformAttrs.get(IMarker.LINE_NUMBER));
       
   230 		if (platformAttrs.containsKey(ICLineBreakpoint.FUNCTION))
       
   231 			targetAttrs.put(MIBreakpoints.FUNCTION,        platformAttrs.get(ICLineBreakpoint.FUNCTION));
       
   232 		if (platformAttrs.containsKey(ICLineBreakpoint.ADDRESS))
       
   233 			targetAttrs.put(MIBreakpoints.ADDRESS,         platformAttrs.get(ICLineBreakpoint.ADDRESS));
       
   234 		
       
   235 		if (platformAttrs.containsKey(ICBreakpoint.CONDITION))
       
   236 			targetAttrs.put(MIBreakpoints.CONDITION,           platformAttrs.get(ICBreakpoint.CONDITION));
       
   237 		if (platformAttrs.containsKey(ICBreakpoint.IGNORE_COUNT))
       
   238 			targetAttrs.put(MIBreakpoints.IGNORE_COUNT,        platformAttrs.get(ICBreakpoint.IGNORE_COUNT));
       
   239 		if (platformAttrs.containsKey(ICBreakpoint.ENABLED))
       
   240 			targetAttrs.put(MIBreakpoints.IS_ENABLED,          platformAttrs.get(ICBreakpoint.ENABLED));
       
   241 		
       
   242 		return targetAttrs;
       
   243 	}
       
   244 
       
   245     @SuppressWarnings("unchecked")
       
   246 	public void resolveBreakpoint(IBreakpointsTargetDMContext context, IBreakpoint breakpoint, 
       
   247     		Map<String, Object> bpAttributes, final DataRequestMonitor<List<Map<String, Object>>> drm) {
       
   248 		
       
   249     	assert dsfSession.getExecutor().isInExecutorThread();
       
   250     	
       
   251     	// Create a copy as we don't want to change "bpAttributes".
       
   252 		final Map<String, Object>	targetBPAttrBase = new HashMap<String, Object>(bpAttributes);
       
   253 		
       
   254 		final Set<String> threads = (Set<String>) targetBPAttrBase.get(ATTR_THREAD_FILTER);
       
   255 
       
   256 		final List<Map<String, Object>>	targetBPList = new ArrayList<Map<String, Object>>();
       
   257 
       
   258 		// get debugger path (compilation-path) for source file, if any.
       
   259 		determineDebuggerPath(context, targetBPAttrBase, new RequestMonitor(dsfSession.getExecutor(), drm){
       
   260 			@Override
       
   261 			protected void handleSuccess() {
       
   262 				// Create attribute list for each thread
       
   263 				for (String thread : threads) {
       
   264 					Map<String, Object> targetBP = new HashMap<String, Object>(targetBPAttrBase);
       
   265 					targetBP.put(MIBreakpointDMData.THREAD_ID, thread);
       
   266 					targetBPList.add(targetBP);
       
   267 				}
       
   268 
       
   269 				drm.setData(targetBPList);
       
   270 				drm.done();
       
   271 			}});
       
   272 	}
       
   273 
       
   274     /**
       
   275      * determineDebuggerPath
       
   276      * 
       
   277      * Adds the path to the source file to the set of attributes
       
   278      * (for the debugger).
       
   279      * 
       
   280      * @param dmc
       
   281      * @param targetAttrs
       
   282      * @param rm
       
   283      */
       
   284     private void determineDebuggerPath(IBreakpointsTargetDMContext dmc,
       
   285             final Map<String, Object> targetAttrs, final RequestMonitor rm)
       
   286     {
       
   287         String hostPath = (String) targetAttrs.get(MIBreakpoints.FILE_NAME);
       
   288 
       
   289         if (hostPath != null) {
       
   290             ISourceLookup sourceService   = dsfServicesTracker.getService(ISourceLookup.class);
       
   291 
       
   292             ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(dmc, ISourceLookupDMContext.class);
       
   293             if (srcDmc != null) {
       
   294                 sourceService.getDebuggerPath(srcDmc, hostPath,
       
   295                     new DataRequestMonitor<String>(dsfSession.getExecutor(), rm) {
       
   296                         @Override
       
   297                         protected void handleSuccess() {
       
   298                             targetAttrs.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(getData()));
       
   299                             rm.done();
       
   300                         }
       
   301                     });
       
   302             } else {
       
   303                 // Source lookup not available for given context, use the host
       
   304                 // path for the debugger path.
       
   305                 targetAttrs.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(hostPath));
       
   306                 rm.done();
       
   307             }
       
   308         } else {
       
   309             // Some types of breakpoints do not require a path
       
   310             // (e.g. watchpoints)
       
   311             rm.done();
       
   312         }
       
   313     }
       
   314 
       
   315     /**
       
   316      * See bug232415
       
   317      * 
       
   318      * @param path	the absolute path to the source file
       
   319      * @return
       
   320      */
       
   321     private String adjustDebuggerPath(String path) {
       
   322     	String result = path;
       
   323     	// Make it MinGW-specific
       
   324     	if (Platform.getOS().startsWith("win")) { //$NON-NLS-1$
       
   325         	if (!path.startsWith("/")) { //$NON-NLS-1$
       
   326         		result = path.substring(path.lastIndexOf('\\') + 1);
       
   327         	}
       
   328     	}
       
   329     	return result;
       
   330     }
       
   331 
       
   332 	/**
       
   333 	 * Get the list of threads from the platform breakpoint attributes
       
   334 	 * 
       
   335 	 * @param context
       
   336 	 *            if the context is not null, only get threads that are children
       
   337 	 *            of this context. otherwise get all threads.
       
   338 	 * @param breakpoint
       
   339 	 * @return
       
   340 	 */
       
   341     private Set<String> extractThreads(IBreakpointsTargetDMContext context, ICBreakpoint breakpoint) {
       
   342         Set<String> results = new HashSet<String>();
       
   343 
       
   344         // Find the ancestor
       
   345         List<IExecutionDMContext[]> threads = new ArrayList<IExecutionDMContext[]>(1);
       
   346 
       
   347         try {
       
   348             // Retrieve the targets
       
   349             IDsfBreakpointExtension filterExtension = getFilterExtension(breakpoint);
       
   350             IContainerDMContext[] targets = filterExtension.getTargetFilters();
       
   351 
       
   352             // If no target is present, breakpoint applies to all.
       
   353             if (targets.length == 0) {
       
   354                 results.add("0"); //$NON-NLS-1$    
       
   355                 return results;
       
   356             }
       
   357 
       
   358             // Extract the thread IDs (if there is none, we are covered)
       
   359             for (IContainerDMContext ctxt : targets) {
       
   360                 if (context == null || 
       
   361                 	DMContexts.isAncestorOf(ctxt, context)) {
       
   362                     threads.add(filterExtension.getThreadFilters(ctxt));
       
   363                 }
       
   364             }
       
   365         } catch (CoreException e1) {
       
   366         }
       
   367 
       
   368         if (supportsThreads(breakpoint)) {
       
   369             for (IExecutionDMContext[] targetThreads : threads) {
       
   370                 if (targetThreads != null) {
       
   371                     for (IExecutionDMContext thread : targetThreads) {
       
   372                         if (thread instanceof IMIExecutionDMContext) {
       
   373                         	IMIExecutionDMContext dmc = (IMIExecutionDMContext) thread;
       
   374                             results.add(((Integer) dmc.getThreadId()).toString());
       
   375                         }
       
   376                     }
       
   377                 } else {
       
   378                     results.add("0"); //$NON-NLS-1$    
       
   379                     break;
       
   380                 }
       
   381             }
       
   382         } else {
       
   383             results.add("0"); //$NON-NLS-1$
       
   384         }
       
   385 
       
   386         return results;
       
   387     }
       
   388 
       
   389     /**
       
   390      * Indicates if the back-end supports multiple threads for
       
   391      * this type of breakpoint
       
   392      * 
       
   393      * @param breakpoint
       
   394      */
       
   395     protected boolean supportsThreads(ICBreakpoint breakpoint) {
       
   396 
       
   397         return !(breakpoint instanceof ICWatchpoint);
       
   398     }
       
   399 
       
   400     /**
       
   401      * @param bp
       
   402      * @return
       
   403      * @throws CoreException
       
   404      */
       
   405     private IDsfBreakpointExtension getFilterExtension(ICBreakpoint bp) throws CoreException {
       
   406         return (IDsfBreakpointExtension) bp.getExtension(GDB_DEBUG_MODEL_ID, ICBreakpointExtension.class);
       
   407     }
       
   408 
       
   409 	public Map<String, Object> getAllBreakpointAttributes(IBreakpoint breakpoint, boolean bpManagerEnabled) throws CoreException {
       
   410 
       
   411 		assert ! dsfSession.getExecutor().isInExecutorThread();
       
   412 
       
   413 		// Check that the marker exists and retrieve its attributes.
       
   414 		// Due to accepted race conditions, the breakpoint marker may become
       
   415 		// null while this method is being invoked. In this case throw an exception
       
   416 		// and let the caller handle it.
       
   417 		IMarker marker = breakpoint.getMarker();
       
   418 		if (marker == null || !marker.exists()) {
       
   419 			throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED,
       
   420 					"Breakpoint marker does not exist", null));
       
   421 		}
       
   422 		
       
   423 		// Suppress cast warning: platform is still on Java 1.3
       
   424 		@SuppressWarnings("unchecked")
       
   425 		Map<String, Object> attributes = marker.getAttributes();
       
   426 
       
   427 		Map<String, Object>	targetAttrs = convertAttributes(attributes);
       
   428 
       
   429 		// Determine breakpoint type.
       
   430         if (breakpoint instanceof ICWatchpoint)
       
   431             targetAttrs.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.WATCHPOINT);
       
   432         else if (breakpoint instanceof ICLineBreakpoint)
       
   433             targetAttrs.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
       
   434         else {
       
   435 	    	// catchpoint?
       
   436 	    }
       
   437         	
       
   438 		// Adjust for "skip-all"
       
   439 		if (!bpManagerEnabled) {
       
   440 		    targetAttrs.put(MIBreakpoints.IS_ENABLED, false);
       
   441 		}
       
   442 
       
   443 		Set<String> threads = extractThreads(null, (ICBreakpoint) breakpoint);
       
   444         targetAttrs.put(ATTR_THREAD_FILTER, threads);
       
   445         
       
   446         return targetAttrs;
       
   447 	}
       
   448 
       
   449 	public boolean canUpdateAttributes(IBreakpoint bp, IBreakpointsTargetDMContext context, Map<String, Object> attrDelta) {
       
   450 		boolean yesWeCan;
       
   451 		
       
   452 		if (attrDelta.containsKey(MIBreakpoints.IS_ENABLED) && bp != null) {
       
   453 			// GDB special: 
       
   454 			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=261082
       
   455 			//
       
   456 			Map<String, Object> delta = new HashMap<String, Object>(attrDelta);
       
   457 			
       
   458 			delta.remove(MIBreakpoints.IS_ENABLED);
       
   459 			
       
   460 			yesWeCan = canUpdateAttributes(null, delta);
       
   461 			
       
   462 			if (yesWeCan) {
       
   463 				// other attribute change indicates we can. Now check the ENABLE.
       
   464 				// if the breakpoint is already installed in the "context" (a process), 
       
   465 				// we can. Otherwise no.
       
   466 				ITargetBreakpointInfo[] targetBPs = breakpointsMediator.getTargetBreakpoints(context, bp);
       
   467 				yesWeCan = targetBPs != null && targetBPs.length > 0;
       
   468 			}
       
   469 		}
       
   470 		else 
       
   471 			yesWeCan = canUpdateAttributes(null, attrDelta);
       
   472 		
       
   473 		return yesWeCan;
       
   474 	}
       
   475 
       
   476     private void addBreakpointProblemMarker(final ICBreakpoint breakpoint, final String description, final int severity) {
       
   477 
       
   478         new Job("Add Breakpoint Problem Marker") { //$NON-NLS-1$
       
   479         	{setSystem(true); };
       
   480         	
       
   481             @Override
       
   482             protected IStatus run(IProgressMonitor monitor) {
       
   483                 
       
   484                 if (breakpoint instanceof ICLineBreakpoint) {
       
   485                 	// If we have already have a problem marker on this breakpoint
       
   486                 	// we should remove it first.
       
   487                     IMarker marker = fBreakpointMarkerProblems.remove(breakpoint);
       
   488                     if (marker != null) {
       
   489                         try {
       
   490                             marker.delete();
       
   491                         } catch (CoreException e) {
       
   492                         }
       
   493                 	}
       
   494 
       
   495                     ICLineBreakpoint lineBreakpoint = (ICLineBreakpoint) breakpoint;
       
   496                     try {
       
   497                         // Locate the workspace resource via the breakpoint marker
       
   498                         IMarker breakpoint_marker = lineBreakpoint.getMarker();
       
   499                         IResource resource = breakpoint_marker.getResource();
       
   500 
       
   501                         // Add a problem marker to the resource
       
   502                         IMarker problem_marker = resource.createMarker(BreakpointProblems.BREAKPOINT_PROBLEM_MARKER_ID);
       
   503                         int line_number = lineBreakpoint.getLineNumber();
       
   504                         problem_marker.setAttribute(IMarker.LOCATION,    String.valueOf(line_number));
       
   505                         problem_marker.setAttribute(IMarker.MESSAGE,     description);
       
   506                         problem_marker.setAttribute(IMarker.SEVERITY,    severity);
       
   507                         problem_marker.setAttribute(IMarker.LINE_NUMBER, line_number);
       
   508 
       
   509                         // And save the baby
       
   510                         fBreakpointMarkerProblems.put(breakpoint, problem_marker);
       
   511                     } catch (CoreException e) {
       
   512                     }
       
   513                 }
       
   514                 return Status.OK_STATUS;
       
   515             }
       
   516         }.schedule();
       
   517     }
       
   518 
       
   519     private void removeBreakpointProblemMarker(final ICBreakpoint breakpoint) {
       
   520 
       
   521         new Job("Remove Breakpoint Problem Marker") { //$NON-NLS-1$
       
   522         	{setSystem(true); };
       
   523             @Override
       
   524             protected IStatus run(IProgressMonitor monitor) {
       
   525                 
       
   526                 IMarker marker = fBreakpointMarkerProblems.remove(breakpoint);
       
   527                 if (marker != null) {
       
   528                     try {
       
   529                         marker.delete();
       
   530                     } catch (CoreException e) {
       
   531                     }
       
   532                 }
       
   533 
       
   534                 return Status.OK_STATUS;
       
   535             }
       
   536         }.schedule();
       
   537     }
       
   538 
       
   539     /**
       
   540      */
       
   541     private void clearBreakpointProblemMarkers()
       
   542     {
       
   543         new Job("Clear Breakpoint problem markers") { //$NON-NLS-1$
       
   544         	{ setSystem(true); };
       
   545             @Override
       
   546             protected IStatus run(IProgressMonitor monitor) {
       
   547                 for (IMarker marker : fBreakpointMarkerProblems.values()) {
       
   548                 	if (marker != null) {
       
   549                 		try {
       
   550 							marker.delete();
       
   551 						} catch (CoreException e) {
       
   552 						}
       
   553                 	}
       
   554                 }
       
   555                 fBreakpointMarkerProblems.clear();
       
   556                 return Status.OK_STATUS;
       
   557             }
       
   558         }.schedule();
       
   559     }
       
   560 }
       
   561