/******************************************************************************* * Copyright (c) 2000, 2011 QNX Software Systems 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: * QNX Software Systems - Initial API and implementation * Freescale Semiconductor - Address watchpoints, https://bugs.eclipse.org/bugs/show_bug.cgi?id=118299 * Patrick Chuong (Texas Instruments) - Update CDT ToggleBreakpointTargetFactory enablement (340177) *******************************************************************************/ package org.eclipse.cdt.debug.core; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.debug.core.cdi.CDIException; import org.eclipse.cdt.debug.core.model.ICAddressBreakpoint; import org.eclipse.cdt.debug.core.model.ICBreakpoint; import org.eclipse.cdt.debug.core.model.ICBreakpointType; import org.eclipse.cdt.debug.core.model.ICFunctionBreakpoint; import org.eclipse.cdt.debug.core.model.ICLineBreakpoint; import org.eclipse.cdt.debug.core.model.ICValue; import org.eclipse.cdt.debug.core.model.ICWatchpoint; import org.eclipse.cdt.debug.core.model.ICWatchpoint2; import org.eclipse.cdt.debug.internal.core.model.CFloatingPointValue; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.IStatusHandler; import org.eclipse.debug.core.model.IBreakpoint; import org.osgi.service.prefs.BackingStoreException; import org.w3c.dom.Document; import com.ibm.icu.text.MessageFormat; /** * Utility methods. */ public class CDebugUtils { public static boolean question(IStatus status, Object source) { Boolean result = Boolean.FALSE; IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status); if (handler != null) { try { result = (Boolean)handler.handleStatus(status, source); } catch (CoreException e) { } } return result.booleanValue(); } public static void info(IStatus status, Object source) { IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status); if (handler != null) { try { handler.handleStatus(status, source); } catch (CoreException e) { } } } public static void error(IStatus status, Object source) { IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status); if (handler != null) { try { handler.handleStatus(status, source); } catch (CoreException e) { } } } public static char[] getByteText(byte b) { return new char[]{ charFromByte((byte)((b >>> 4) & 0x0f)), charFromByte((byte)(b & 0x0f)) }; } public static byte textToByte(char[] text) { byte result = 0; if (text.length == 2) { byte[] bytes = { charToByte(text[0]), charToByte(text[1]) }; result = (byte) ((bytes[0] << 4) + bytes[1]); } return result; } public static char charFromByte(byte value) { if (value >= 0x0 && value <= 0x9) return (char) (value + '0'); if (value >= 0xa && value <= 0xf) return (char) (value - 0xa + 'a'); return '0'; } public static byte charToByte(char ch) { if (Character.isDigit(ch)) { return (byte) (ch - '0'); } if (ch >= 'a' && ch <= 'f') { return (byte) (0xa + ch - 'a'); } if (ch >= 'A' && ch <= 'F') { return (byte) (0xa + ch - 'A'); } return 0; } public static char bytesToChar(byte[] bytes) { try { return (char)Short.parseShort(new String(bytes), 16); } catch (RuntimeException e) { } return 0; } public static byte toByte(char[] bytes, boolean le) { if (bytes.length != 2) return 0; return (byte)Long.parseLong(bytesToString(bytes, le, true), 16); } public static short toUnsignedByte(char[] bytes, boolean le) { if (bytes.length != 2) return 0; return (short)Long.parseLong(bytesToString(bytes, le, false), 16); } public static short toShort(char[] bytes, boolean le) { if (bytes.length != 4) return 0; return (short)Long.parseLong(bytesToString(bytes, le, true), 16); } public static int toUnsignedShort(char[] bytes, boolean le) { if (bytes.length != 4) return 0; return (int)Long.parseLong(bytesToString(bytes, le, false), 16); } public static int toInt(char[] bytes, boolean le) { if (bytes.length != 8) return 0; return (int)Long.parseLong(bytesToString(bytes, le, true), 16); } public static long toUnsignedInt(char[] bytes, boolean le) { if (bytes.length != 8) return 0; return Long.parseLong(bytesToString(bytes, le, false), 16); } private static String bytesToString(char[] bytes, boolean le, boolean signed) { char[] copy = new char[bytes.length]; if (le) { for (int i = 0; i < bytes.length / 2; ++i) { copy[2 * i] = bytes[bytes.length - 2 * i - 2]; copy[2 * i + 1] = bytes[bytes.length - 2 * i - 1]; } } else { System.arraycopy(bytes, 0, copy, 0, copy.length); } return new String(copy); } public static String prependString(String text, int length, char ch) { StringBuffer sb = new StringBuffer(length); if (text.length() > length) { sb.append(text.substring(0, length)); } else { char[] prefix = new char[length - text.length()]; Arrays.fill(prefix, ch); sb.append(prefix); sb.append(text); } return sb.toString(); } public static boolean isReferencedProject(IProject parent, IProject project) { if (parent != null && parent.exists()) { List<IProject> projects = CDebugUtils.getReferencedProjects(project); for (IProject proj : projects) { if (proj.exists() && (proj.equals(project))) return true; } } return false; } /** * Serializes a XML document into a string - encoded in UTF8 format, with platform line separators. * * @param doc document to serialize * @param indent if the xml text should be indented. * * @return the document as a string */ public static String serializeDocument(Document doc, boolean indent) throws IOException, TransformerException { ByteArrayOutputStream s = new ByteArrayOutputStream(); TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ transformer.setOutputProperty(OutputKeys.INDENT, indent ? "yes" : "no"); //$NON-NLS-1$ //$NON-NLS-2$ DOMSource source = new DOMSource(doc); StreamResult outputTarget = new StreamResult(s); transformer.transform(source, outputTarget); return s.toString("UTF8"); //$NON-NLS-1$ } /** * Serializes a XML document into a string - encoded in UTF8 format, with platform line separators. * * @param doc document to serialize * @return the document as a string */ public static String serializeDocument(Document doc) throws IOException, TransformerException { return serializeDocument(doc, true); } public static Number getFloatingPointValue(ICValue value) { if (value instanceof CFloatingPointValue) { try { return ((CFloatingPointValue)value).getFloatingPointValue(); } catch (CDIException e) { } } return null; } public static boolean isNaN(Number value) { if (value instanceof Double) { return ((Double) value).isNaN(); } if (value instanceof Float) { return ((Float) value).isNaN(); } return false; } public static boolean isPositiveInfinity(Number value) { if (value instanceof Double) { return (((Double) value).isInfinite() && value.doubleValue() == Double.POSITIVE_INFINITY); } if (value instanceof Float) { return (((Float) value).isInfinite() && value.floatValue() == Float.POSITIVE_INFINITY); } return false; } public static boolean isNegativeInfinity(Number value) { if (value instanceof Double) { return (((Double) value).isInfinite() && value.doubleValue() == Double.NEGATIVE_INFINITY); } if (value instanceof Float) { return (((Float) value).isInfinite() && value.floatValue() == Float.NEGATIVE_INFINITY); } return false; } public static List<IProject> getReferencedProjects(IProject project) { ArrayList<IProject> list = new ArrayList<IProject>(10); if (project != null && project.exists() && project.isOpen()) { IProject[] refs = new IProject[0]; try { refs = project.getReferencedProjects(); } catch (CoreException e) { } for (int i = 0; i < refs.length; ++i) { if (!project.equals(refs[i]) && refs[i] != null && refs[i].exists() && refs[i].isOpen()) { list.add(refs[i]); getReferencedProjects(project, refs[i], list); } } } return list; } private static void getReferencedProjects(IProject root, IProject project, List<IProject> list) { if (project != null && project.exists() && project.isOpen()) { IProject[] refs = new IProject[0]; try { refs = project.getReferencedProjects(); } catch (CoreException e) { } for (int i = 0; i < refs.length; ++i) { if (!list.contains(refs[i]) && refs[i] != null && !refs[i].equals(root) && refs[i].exists() && refs[i].isOpen()) { list.add(refs[i]); getReferencedProjects(root, refs[i], list); } } } } public static String getBreakpointText(IBreakpoint breakpoint, boolean qualified) throws CoreException { if (breakpoint instanceof ICAddressBreakpoint) { return getAddressBreakpointText((ICAddressBreakpoint)breakpoint, qualified); } if (breakpoint instanceof ICFunctionBreakpoint) { return getFunctionBreakpointText((ICFunctionBreakpoint)breakpoint, qualified); } if (breakpoint instanceof ICLineBreakpoint) { return getLineBreakpointText((ICLineBreakpoint)breakpoint, qualified); } if (breakpoint instanceof ICWatchpoint) { return getWatchpointText((ICWatchpoint)breakpoint, qualified); } // this allow to create new breakpoint without implemention one the interfaces above and still see a label Object message = breakpoint.getMarker().getAttribute(IMarker.MESSAGE); if (message != null) return message.toString(); return ""; //$NON-NLS-1$ } protected static String getLineBreakpointText(ICLineBreakpoint breakpoint, boolean qualified) throws CoreException { StringBuffer label = new StringBuffer(); appendSourceName(breakpoint, label, qualified); appendLineNumber(breakpoint, label); appendBreakpointType(breakpoint, label); appendIgnoreCount(breakpoint, label); appendCondition(breakpoint, label); return label.toString(); } protected static String getWatchpointText(ICWatchpoint watchpoint, boolean qualified) throws CoreException { StringBuffer label = new StringBuffer(); appendSourceName(watchpoint, label, qualified); appendWatchExpression(watchpoint, label); if (watchpoint instanceof ICWatchpoint2) { ICWatchpoint2 wp2 = (ICWatchpoint2)watchpoint; appendWatchMemorySpace(wp2, label); appendWatchRange(wp2, label); } appendIgnoreCount(watchpoint, label); appendCondition(watchpoint, label); return label.toString(); } protected static String getAddressBreakpointText(ICAddressBreakpoint breakpoint, boolean qualified) throws CoreException { StringBuffer label = new StringBuffer(); appendSourceName(breakpoint, label, qualified); appendAddress(breakpoint, label); appendBreakpointType(breakpoint, label); appendIgnoreCount(breakpoint, label); appendCondition(breakpoint, label); return label.toString(); } protected static String getFunctionBreakpointText(ICFunctionBreakpoint breakpoint, boolean qualified) throws CoreException { StringBuffer label = new StringBuffer(); appendSourceName(breakpoint, label, qualified); appendFunction(breakpoint, label); appendBreakpointType(breakpoint, label); appendIgnoreCount(breakpoint, label); appendCondition(breakpoint, label); return label.toString(); } protected static StringBuffer appendSourceName(ICBreakpoint breakpoint, StringBuffer label, boolean qualified) throws CoreException { String handle = breakpoint.getSourceHandle(); if (!isEmpty(handle)) { IPath path = new Path(handle); if (path.isValidPath(handle)) { label.append(qualified ? path.toOSString() : path.lastSegment()); } } return label; } protected static StringBuffer appendLineNumber(ICLineBreakpoint breakpoint, StringBuffer label) throws CoreException { int lineNumber = breakpoint.getLineNumber(); if (lineNumber > 0) { label.append(' '); label.append(MessageFormat.format(DebugCoreMessages.getString("CDebugUtils.0"), new String[]{ Integer.toString(lineNumber) })); //$NON-NLS-1$ } return label; } protected static StringBuffer appendAddress(ICAddressBreakpoint breakpoint, StringBuffer label) throws CoreException { try { label.append(' '); label.append(MessageFormat.format(DebugCoreMessages.getString("CDebugUtils.1"), new String[]{ breakpoint.getAddress() })); //$NON-NLS-1$ } catch (NumberFormatException e) { } return label; } protected static StringBuffer appendFunction(ICFunctionBreakpoint breakpoint, StringBuffer label) throws CoreException { String function = breakpoint.getFunction(); if (function != null && function.trim().length() > 0) { label.append(' '); label.append(MessageFormat.format(DebugCoreMessages.getString("CDebugUtils.2"), new String[]{ function.trim() })); //$NON-NLS-1$ } return label; } protected static StringBuffer appendIgnoreCount(ICBreakpoint breakpoint, StringBuffer label) throws CoreException { int ignoreCount = breakpoint.getIgnoreCount(); if (ignoreCount > 0) { label.append(' '); label.append(MessageFormat.format(DebugCoreMessages.getString("CDebugUtils.3"), new String[]{ Integer.toString(ignoreCount) })); //$NON-NLS-1$ } return label; } protected static void appendCondition(ICBreakpoint breakpoint, StringBuffer buffer) throws CoreException { String condition = breakpoint.getCondition(); if (condition != null && condition.length() > 0) { buffer.append(' '); buffer.append(MessageFormat.format(DebugCoreMessages.getString("CDebugUtils.4"), new String[] { condition })); //$NON-NLS-1$ } } private static void appendWatchExpression(ICWatchpoint watchpoint, StringBuffer label) throws CoreException { String expression = watchpoint.getExpression(); if (expression != null && expression.length() > 0) { label.append(' '); label.append(MessageFormat.format( DebugCoreMessages.getString("CDebugUtils.5"), new String[] { expression })); //$NON-NLS-1$ } } private static void appendWatchMemorySpace(ICWatchpoint2 watchpoint, StringBuffer label) throws CoreException { String memorySpace = watchpoint.getMemorySpace(); if (memorySpace != null && memorySpace.length() > 0) { label.append(' '); label.append(MessageFormat.format( DebugCoreMessages.getString("CDebugUtils.6"), new String[] { memorySpace })); //$NON-NLS-1$ } } private static void appendWatchRange(ICWatchpoint2 watchpoint, StringBuffer label) throws CoreException { String range = watchpoint.getRange().toString(); if (range.length() > 0 && !range.equals("0")) { //$NON-NLS-1$ label.append(' '); label.append(MessageFormat.format(DebugCoreMessages.getString("CDebugUtils.7"), new String[]{ range })); //$NON-NLS-1$ } } protected static StringBuffer appendBreakpointType(ICBreakpoint breakpoint, StringBuffer label) throws CoreException { if (breakpoint instanceof ICBreakpointType) { String typeString = ""; //$NON-NLS-1$ int type = ((ICBreakpointType) breakpoint).getType(); // Need to filter out the TEMPORARY bit-flag to get the real type // The REGULAR type is implicit so we don't report that. switch (type & ~ICBreakpointType.TEMPORARY) { case ICBreakpointType.HARDWARE: typeString = DebugCoreMessages.getString("CDebugUtils.Hardware"); //$NON-NLS-1$ break; case ICBreakpointType.SOFTWARE: typeString = DebugCoreMessages.getString("CDebugUtils.Software"); //$NON-NLS-1$ break; } // Now factor in the TEMPORARY qualifier to form, .e.,g "Hardware/Temporary" // Thing is, a temporary breakpoint should never show in the GUI, so this is // here as a just-in-case. if ((type & ICBreakpointType.TEMPORARY) != 0) { if (typeString.length() > 0) { typeString += "/"; //$NON-NLS-1$ } typeString += DebugCoreMessages.getString("CDebugUtils.Temporary"); //$NON-NLS-1$ } if (typeString.length() > 0) { label.append(' '); label.append(MessageFormat.format( DebugCoreMessages.getString("CDebugUtils.8"), new String[] { typeString })); //$NON-NLS-1$ } } return label; } private static boolean isEmpty(String string) { return (string == null || string.trim().length() == 0); } private static CharsetDecoder fDecoder; public static CharsetDecoder getCharsetDecoder() { String charsetName = CDebugCorePlugin.getDefault().getPluginPreferences().getString(ICDebugConstants.PREF_CHARSET); if (fDecoder == null || !fDecoder.charset().name().equals(charsetName)) { Charset charset = Charset.forName(charsetName); fDecoder = charset.newDecoder(); } return fDecoder; } /** * Note: Moved from AbstractCLaunchDelegate * @since 6.0 */ public static ICProject getCProject(ILaunchConfiguration configuration) throws CoreException { String projectName = getProjectName(configuration); if (projectName != null) { projectName = projectName.trim(); if (projectName.length() > 0) { IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(project); if (cProject != null && cProject.exists()) { return cProject; } } } return null; } /** * Note: Moved from AbstractCLaunchDelegate * @since 6.0 */ public static String getProjectName(ILaunchConfiguration configuration) throws CoreException { return configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null); } /** * Note: Moved from AbstractCLaunchDelegate * @since 6.0 */ public static String getProgramName(ILaunchConfiguration configuration) throws CoreException { return configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, (String)null); } /** * Note: Moved from AbstractCLaunchDelegate * @since 6.0 */ public static IPath getProgramPath(ILaunchConfiguration configuration) throws CoreException { String path = getProgramName(configuration); if (path == null || path.trim().length() == 0) { return null; } return new Path(path); } /** * Returns the ICProject associated with the project setting in the Main tab * of a CDT launch configuration, or throws a CoreException providing a * reason (e.g., the setting is empty, the project no longer exists, the * isn't a CDT one, etc). * * @param config * the launch configuration * @return an ICProject; never null. * @throws CoreException * @since 7.0 */ public static ICProject verifyCProject(ILaunchConfiguration config) throws CoreException { String name = CDebugUtils.getProjectName(config); if (name == null) { throwCoreException(DebugCoreMessages.getString("CDebugUtils.C_Project_not_specified"), //$NON-NLS-1$ ICDTLaunchConfigurationConstants.ERR_UNSPECIFIED_PROJECT); } ICProject cproject = CDebugUtils.getCProject(config); if (cproject == null) { IProject proj = ResourcesPlugin.getWorkspace().getRoot().getProject(name); if (!proj.exists()) { throwCoreException(DebugCoreMessages.getFormattedString("CDebugUtils.Project_NAME_does_not_exist", name), //$NON-NLS-1$ ICDTLaunchConfigurationConstants.ERR_NOT_A_C_PROJECT); } else if (!proj.isOpen()) { throwCoreException(DebugCoreMessages.getFormattedString("CDebugUtils.Project_NAME_is_closed", name), //$NON-NLS-1$ ICDTLaunchConfigurationConstants.ERR_NOT_A_C_PROJECT); } throwCoreException(DebugCoreMessages.getString("CDebugUtils.Not_a_C_CPP_project"), //$NON-NLS-1$ ICDTLaunchConfigurationConstants.ERR_NOT_A_C_PROJECT); } return cproject; } /** * Returns an IPath for the file referenced in the <i>C/C++ Application</i> * setting of a CDT launch configuration. Typically, the file is obtained by * combining the <i>C/C++ Application</i> setting with the <i>Project</i> * setting. If unable to combine and resolve these settings to a valid file, * a CoreException is thrown that provides the reason why. There are many * such possible reasons (a problem with the <i>Project</i> setting, an * empty <i>C/C++ Application</i> setting, the combined settings doesn't * resolve to an existing file, etc). * * @param config * the launch configuration * @param ignoreProjectSetting * if true, resolve the file using only the <i>C/C++ * Application</i> setting. Do not take the <i>Project</i> * setting into account. * @return an IPath; never null * @throws CoreException * @since 7.0 */ public static IPath verifyProgramPath(ILaunchConfiguration config, boolean ignoreProjectSetting) throws CoreException { ICProject cproject = null; if (!ignoreProjectSetting) { cproject = verifyCProject(config); // will throw exception if project setting not valid } IPath programPath = CDebugUtils.getProgramPath(config); if (programPath == null || programPath.isEmpty()) { throwCoreException(DebugCoreMessages.getString("CDebugUtils.Program_file_not_specified"), //$NON-NLS-1$ ICDTLaunchConfigurationConstants.ERR_UNSPECIFIED_PROGRAM); } if (programPath != null) { // this check is here only to avoid warning; compiler can't tell we'll throw an exception above if (!programPath.isAbsolute() && (cproject != null)) { // See if we can brute-force append the program path to the // project location. This allows us to support the program file // being outside the project, even outside the workspace, without // requiring a linked resource (e.g., the setting could be // "..\..\some\dir\myprogram.exe") IPath location = cproject.getProject().getLocation(); if (location != null) { programPath = location.append(programPath); if (!programPath.toFile().exists()) { // Try looking in the project for the file. This // supports linked resources. IFile projFile = null; try { projFile = cproject.getProject().getFile(CDebugUtils.getProgramPath(config)); } catch (IllegalArgumentException exc) { // thrown if relative path that resolves to a root file (e.g., "..\somefile") } if (projFile != null && projFile.exists()) { programPath = projFile.getLocation(); } } } } if (!programPath.toFile().exists()) { throwCoreException( DebugCoreMessages.getString("CDebugUtils.Program_file_does_not_exist"), //$NON-NLS-1$ new FileNotFoundException( DebugCoreMessages.getFormattedString("CDebugUtils.PROGRAM_PATH_not_found", programPath.toOSString())), //$NON-NLS-1$ ICDTLaunchConfigurationConstants.ERR_PROGRAM_NOT_EXIST); } } return programPath; } /** * Variant that expects (requires) the launch configuration to have a valid * <i>Project</i> setting. See * {@link #verifyProgramPath(ILaunchConfiguration, boolean)} * * @since 7.0 */ public static IPath verifyProgramPath(ILaunchConfiguration config) throws CoreException { return verifyProgramPath(config, false); } /** Throws a CoreException. Clutter-reducing utility method. */ private static void throwCoreException(String msg, int code) throws CoreException { throwCoreException(msg, null, code); } /** Throws a CoreException. Clutter-reducing utility method. */ private static void throwCoreException(String msg, Exception innerException, int code) throws CoreException { throw new CoreException(new Status(IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), code, msg, innerException)); } /** * Generic method to fetch an attribute from a Map that has keys of type String. The defaultValue * parameter will be returned if the map does not contain the key, or if the matching value is not * of the correct type. * * @param <V> The type of the value we are looking for. Specified by the type of defaultValue. * @param attributes The map with keys of type String, and values of any type. Cannot be null. * @param key They key for which we want the value. * @param defaultValue The default value to return if the key is not found in the map, or if the value found * is not of the same type as defaultValue. Cannot be null. * @return The value, if found and of the same type as defaultValue. Else, returns defaultValue. * @since 7.1 */ @SuppressWarnings("unchecked") public static <V> V getAttribute(Map<String, ?> attributes, String key, V defaultValue) { Object value = attributes.get(key); if (defaultValue.getClass().isInstance(value)) { return (V) value; } return defaultValue; } /** * Overrides the standard project ICBreakpoint toggle breakpoint factory with * a custom toggle breakpoint factory. The ICBreakpoint toggle breakpoint factory * will be disabled and it is up to the client to contribute it's own toggle * breakpoint factory. * * @param project a project * @param factoryId a breakpoint toggle factory identifier * @since 7.1 */ public static void setToggleBreakpointFactory(IProject project, String factoryId) { try { IEclipsePreferences pref = new ProjectScope(project).getNode(CDebugCorePlugin.PLUGIN_ID); pref.put(ICDebugConstants.PREF_TOGGLE_BREAKPOINT_MODEL_IDENTIFIER, factoryId); pref.flush(); } catch (BackingStoreException e) { CDebugCorePlugin.log(e); } } /** * Returns the toggle breakpoint factory identifier for the project * * @param project the project * @return the toggle breakpoint factory identifier, can be {@code null} * @since 7.1 */ public static String getToggleBreakpointFactory(IProject project) { IEclipsePreferences pref = new ProjectScope(project.getProject()).getNode(CDebugCorePlugin.PLUGIN_ID); return pref.get(ICDebugConstants.PREF_TOGGLE_BREAKPOINT_MODEL_IDENTIFIER, null); } /** * Returns whether the project uses the standard ICBreakpoint toggle breakpoint factory. * * @param project the project * @return {@code true} if the project uses the standard ICBreakpoint breakpoint toggle factory * @since 7.1 */ public static boolean isStandardCBreakpointFactory(IProject project) { return getToggleBreakpointFactory(project) == null; } /** * Returns whether the custom toggle breakpoint factory should be consider when evaluating the * enablement of the standard ICBreakpoint toggle breakpoint factory. * * @return true if the custom model breakpoint system property is set * @since 7.1 * @see ICDebugConstants#PREF_TOGGLE_BREAKPOINT_MODEL_IDENTIFIER */ public static boolean isCustomToggleBreakpointFactory() { String customModel = System.getProperty(ICDebugConstants.PREF_TOGGLE_BREAKPOINT_MODEL_IDENTIFIER, null); return customModel != null && Boolean.valueOf(customModel); } }