Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CSettingsManager.java')
-rw-r--r--debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CSettingsManager.java267
1 files changed, 267 insertions, 0 deletions
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CSettingsManager.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CSettingsManager.java
new file mode 100644
index 00000000000..96ee541ef12
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CSettingsManager.java
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Freescale Semiconductor 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:
+ * Freescale Semiconductor - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.core;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.eclipse.cdt.debug.core.CDebugUtils;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.debug.internal.core.model.CDebugTarget;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * Settings manager
+ *
+ * The settings manager stores a set of settings,
+ * (key/value) pairs in the launch configuration so they exist across debug sessions.
+ *
+ * All active settings are stored together in a single configuration entry
+ * (ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_FORMAT).
+ *
+ * Every setting is identified by a string identifier. That string identifier can be used to
+ * store an additional setting, to remove an exiting one or to retrieve a previously stored setting.
+ *
+ * The setting value consists of a String.
+ *
+ * Settings fade out automatically so clients do not necessarily need to delete old settings. This makes it
+ * possible to build the string identifiers with names out of the user application, like function names or
+ * variable names, without the danger of a constantly growing launch configuration.
+ * However it also causes that the settings manager must only be used for configurations and customizations for which
+ * always reasonable defaults exist.
+ *
+ * As cleanup policy the settings manager only keeps a certain number of settings and drops the
+ * least recently used one when more settings are added. The least recently used order is maintained
+ * across debug sessions.
+ *
+ */
+
+public class CSettingsManager {
+
+ /**
+ * the name of the XML node for the list
+ */
+ private static final String CONTENT_LIST = "contentList"; //$NON-NLS-1$
+
+ /**
+ * the name of the XML node for every format entry
+ */
+ private static final String CONTENT = "content"; //$NON-NLS-1$
+
+ /**
+ * the attribute name used to identify the object to store the content for.
+ */
+ private static final String ATTR_CONTENT_ID = "id"; //$NON-NLS-1$
+
+ /**
+ * the attribute name of the actual content
+ */
+ private static final String ATTR_CONTENT_VALUE = "val"; //$NON-NLS-1$
+
+ /**
+ * Number defining how many settings are stored.
+ * Whenever an additional setting is added when there are already MAX_USED_COUNT settings, the
+ * least recently used setting is dropped.
+ *
+ * The actual value is chosen to be high enough for normal use cases, but still low enough to avoid that the launch configuration
+ * gets arbitrarily large
+ */
+ private static int MAX_ELEMENT_COUNT = 100;
+
+ /**
+ * the map used to actually store the format information
+ * as key String are used, values are of type String too.
+ *
+ * The map automatically is limited to MAX_ELEMENT_COUNT
+ * elements, dropping the least recently used one
+ * when more elements are added.
+ */
+ private Map fContentMap = new LinkedHashMap(MAX_ELEMENT_COUNT, 0.75f, true) {
+ private static final long serialVersionUID = 1;
+ protected boolean removeEldestEntry(Map.Entry eldest) {
+ return size() > MAX_ELEMENT_COUNT;
+ }
+ };
+
+ /**
+ * the debug target we store the values for
+ */
+ private CDebugTarget fDebugTarget;
+
+ /**
+ * Store the value for the given id.
+ * @param id used to identify the information. Different objects/topics should use different identifiers.
+ * @param value content to be stored
+ */
+ public synchronized void putValue( String id, String value ) {
+ fContentMap.put(id, value);
+ }
+ /**
+ * remove the stored format for the given id.
+ * @param id used to identify the formatting information. Different objects/topics should use different identifiers.
+ */
+ public synchronized void removeValue( String id ) {
+ fContentMap.remove( id );
+ }
+
+ /** Retrieve the value for the given id.
+ * @param id used to identify the formatting information. Different objects/topics should use different identifiers.
+ * @return returns the entry information for the given id, or null if no such information is available.
+ */
+ public synchronized String getValue( String id ) {
+ String entry= (String) fContentMap.get( id );
+ return entry;
+ }
+
+ /** constructor.
+ * @param debugTarget
+ */
+ public CSettingsManager( CDebugTarget debugTarget ) {
+ fDebugTarget = debugTarget;
+ initialize();
+ }
+
+ /** get the string format of the current content.
+ * Only stores entries which have been used in the last MAX_USED_COUNT debug sessions.
+ * @return
+ */
+ private String getMemento() {
+ Document document = null;
+ try {
+ document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+ Element node = document.createElement( CONTENT_LIST );
+ document.appendChild( node );
+ Set entrySet = fContentMap.entrySet();
+ Iterator it = entrySet.iterator();
+ while ( it.hasNext() ) {
+ Map.Entry entry= (Map.Entry) it.next();
+ String id= (String)entry.getKey();
+ String value= (String)entry.getValue();
+ Element child = document.createElement( CONTENT );
+ child.setAttribute( ATTR_CONTENT_ID, id );
+ child.setAttribute( ATTR_CONTENT_VALUE, value );
+ node.appendChild( child );
+ }
+ return CDebugUtils.serializeDocument( document, false );
+ }
+ catch( ParserConfigurationException e ) {
+ DebugPlugin.log( e );
+ }
+ catch( IOException e ) {
+ DebugPlugin.log( e );
+ }
+ catch( TransformerException e ) {
+ DebugPlugin.log( e );
+ }
+ return null;
+ }
+
+ /** set the current state to the one given by the memento.
+ * @param memento a string representation of the state to be loaded.
+ * @throws CoreException
+ */
+ private void initializeFromMemento( String memento ) throws CoreException {
+ try {
+ fContentMap.clear();
+ DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ StringReader reader = new StringReader( memento );
+ InputSource source = new InputSource( reader );
+ Element root = parser.parse( source ).getDocumentElement();
+ if ( root.getNodeName().equalsIgnoreCase( CONTENT_LIST ) ) {
+ NodeList list = root.getChildNodes();
+ int i = list.getLength() - 1; // backwards to keep least recent access order.
+ for( ; i >= 0; i-- ) {
+ Node node = list.item( i );
+ short type = node.getNodeType();
+ if ( type == Node.ELEMENT_NODE ) {
+ Element elem = (Element)node;
+ if ( elem.getNodeName().equalsIgnoreCase( CONTENT ) ) {
+ String id = elem.getAttribute( ATTR_CONTENT_ID );
+ String value= elem.getAttribute( ATTR_CONTENT_VALUE );
+ if ( id == null || id.length() == 0 ) {
+ DebugPlugin.logMessage( "unexpected entry in CSettingsManager.initializeFromMemento", null ); //$NON-NLS-1$
+ continue;
+ }
+ putValue( id, value );
+ }
+ }
+ }
+ return;
+ }
+ DebugPlugin.logMessage( "unexpected content", null ); //$NON-NLS-1$
+ }
+ catch( ParserConfigurationException e ) {
+ DebugPlugin.log( e );
+ }
+ catch( SAXException e ) {
+ DebugPlugin.log( e );
+ }
+ catch( IOException e ) {
+ DebugPlugin.log( e );
+ }
+ }
+
+ /**
+ * read the stored format from the launch configuration
+ */
+ private void initialize() {
+ ILaunchConfiguration config = getDebugTarget().getLaunch().getLaunchConfiguration();
+ try {
+ String memento = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_FORMAT, "" ); //$NON-NLS-1$
+ if ( memento != null && memento.trim().length() != 0 )
+ initializeFromMemento( memento );
+ }
+ catch( CoreException e ) {
+ DebugPlugin.log( e );
+ }
+ }
+
+ /**
+ * store the current content in the launch configuration.
+ */
+ public synchronized void save() {
+ ILaunchConfiguration config = getDebugTarget().getLaunch().getLaunchConfiguration();
+ try {
+ ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy();
+ wc.setAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_FORMAT, getMemento() );
+ wc.doSave();
+ }
+ catch( CoreException e ) {
+ DebugPlugin.log( e );
+ }
+ }
+
+ /**
+ * accessor to the debug target
+ */
+ IDebugTarget getDebugTarget() {
+ return fDebugTarget;
+ }
+}

Back to the top