diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 4b2ef90c62c..123021d0414 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,12 @@ +2005-03-03 Alain Magloire + Part of plan item 79518: for PathEntry variable manager. + * model/org/eclipse/cdt/internal/core/model/PathEntryManager.java + * src/org/eclipse/cdt/core/CCorePlugin.java + * src/org/eclipse/cdt/core/resources/IPathEntryVariableChangeListener.java + * src/org/eclipse/cdt/core/resources/IPathEntryVariableManager.java + * src/org/eclipse/cdt/core/resources/PathEntryVariableManager.java + * src/org/eclipse/cdt/internal/core/PathEntryVariableManager.java + 2005-03-03 Vladimir Hirsl Small change for enabling generation of path entry container change events. * model/org/eclipse/cdt/core/model/PathEntryContainerChanged.java diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java index 6257daab466..a71d1c33973 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java @@ -459,7 +459,6 @@ public class PathEntryManager implements IPathEntryStoreListener, IElementChange if (hasPathEntryProblemMarkersChange(project, problems)) { generateMarkers(project, problems); } - } // Check for duplication in the sources @@ -1805,11 +1804,9 @@ public class PathEntryManager implements IPathEntryStoreListener, IElementChange * Record a new marker denoting a pathentry problem */ void createPathEntryProblemMarker(IProject project, ICModelStatus status) { - - IMarker marker = null; int severity = code2Severity(status); try { - marker = project.createMarker(ICModelMarker.PATHENTRY_PROBLEM_MARKER); + IMarker marker = project.createMarker(ICModelMarker.PATHENTRY_PROBLEM_MARKER); marker.setAttributes(new String[]{IMarker.MESSAGE, IMarker.SEVERITY, IMarker.LOCATION, ICModelMarker.PATHENTRY_FILE_FORMAT,}, new Object[]{status.getMessage(), new Integer(severity), "pathentry",//$NON-NLS-1$ "false",//$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java index 1b13e0b9853..76ee1d7a10b 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java @@ -25,10 +25,12 @@ import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.core.parser.IScannerInfoProvider; import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.core.resources.IPathEntryVariableManager; import org.eclipse.cdt.core.resources.ScannerProvider; import org.eclipse.cdt.core.search.SearchEngine; import org.eclipse.cdt.internal.core.CDTLogWriter; import org.eclipse.cdt.internal.core.CDescriptorManager; +import org.eclipse.cdt.internal.core.PathEntryVariableManager; import org.eclipse.cdt.internal.core.model.BufferManager; import org.eclipse.cdt.internal.core.model.CModelManager; import org.eclipse.cdt.internal.core.model.DeltaProcessor; @@ -116,7 +118,9 @@ public class CCorePlugin extends Plugin { private CDescriptorManager fDescriptorManager = new CDescriptorManager(); private CoreModel fCoreModel; - + + private PathEntryVariableManager fPathEntryVariableManager; + // -------- static methods -------- static { @@ -215,6 +219,11 @@ public class CCorePlugin extends Plugin { if (cdtLog != null) { cdtLog.shutdown(); } + + if (fPathEntryVariableManager != null) { + fPathEntryVariableManager.shutdown(); + } + savePluginPreferences(); } finally { super.stop(context); @@ -245,6 +254,9 @@ public class CCorePlugin extends Plugin { getPluginPreferences().setDefault(PREF_USE_STRUCTURAL_PARSE_MODE, false); // Start file type manager + fPathEntryVariableManager = new PathEntryVariableManager(); + fPathEntryVariableManager.startup(); + } @@ -598,6 +610,10 @@ public class CCorePlugin extends Plugin { return fCoreModel; } + public IPathEntryVariableManager getPathEntryVariableManager() { + return fPathEntryVariableManager; + } + /** * @param project * @return @@ -853,9 +869,9 @@ public class CCorePlugin extends Plugin { /** * Configure the plugin with respect to option settings defined in ".options" file */ - public void configurePluginDebugOptions(){ + public void configurePluginDebugOptions() { - if(CCorePlugin.getDefault().isDebugging()){ + if(CCorePlugin.getDefault().isDebugging()) { String option = Platform.getDebugOption(PARSER); if(option != null) Util.VERBOSE_PARSER = option.equalsIgnoreCase("true") ; //$NON-NLS-1$ @@ -903,8 +919,7 @@ public class CCorePlugin extends Plugin { return getPluginPreferences().getBoolean(PREF_USE_STRUCTURAL_PARSE_MODE); } - public CDOM getDOM() - { + public CDOM getDOM() { return CDOM.getInstance(); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryVariableChangeListener.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryVariableChangeListener.java new file mode 100644 index 00000000000..e4ffddec3a9 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryVariableChangeListener.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.core.resources; + +import java.util.EventListener; + + +/** + * An interface to be implemented by objects interested in path variable + * creation, removal and value change events. + * + *
Clients may implement this interface.
+ * + * @since 3.0 + */ +public interface IPathEntryVariableChangeListener extends EventListener { + /** + * Notification that a path variable has changed. + *
+ * This method is called when a path variable is added, removed or has its value
+ * changed in the observed IPathVariableManager
object.
+ *
+ *
null
.
+ * null
.null
.
+ * null
, or if it is
+ * defined but the given value is equal to its current value.
+ * If a variable is effectively changed, created or removed by a call to + * this method, notification will be sent to all registered listeners.
+ * + * @param name the name of the variable + * @param value the value for the variable (may benull
)
+ * @exception CoreException if this method fails. Reasons include:
+ * null
.
+ *
+ * @param name the name of the variable to return the value for
+ * @return the value for the variable, or null
if there is no
+ * variable defined with the given name
+ */
+ public String getValue(String name);
+
+ /**
+ * Returns an array containing all defined variable names.
+ *
+ * @return an array containing all defined variable names
+ */
+ public String[] getVariableNames();
+
+ /**
+ * Registers the given listener to receive notification of changes to
+ * variables. The listener will be notified whenever a variable has been
+ * added, removed or had its value changed. Has no effect if an identical
+ * variable change listener is already registered.
+ *
+ * @param listener the listener
+ * @see IPathEntryVariableChangeListener
+ */
+ public void addChangeListener(IPathEntryVariableChangeListener listener);
+
+ /**
+ * Removes the given variable change listener from the listeners list.
+ * Has no effect if an identical listener is not registered.
+ *
+ * @param listener the listener
+ * @see IPathEntryVariableChangeListener
+ */
+ public void removeChangeListener(IPathEntryVariableChangeListener listener);
+
+ /**
+ * Resolves a String
potentially containing a
+ * variable reference, replacing the variable reference
+ * (if any) with the variable's value (which is a concrete absolute path).
+ *
+ * If the given String is null
then null
will be
+ * returned. In all other cases the result will be non-null
.
+ *
+ * For example, consider the following collection of path variables: + *
+ *The following paths would be resolved as: + *
c:/bin => c:/bin
+ *c:${TEMP} => c:/temp
+ */TEMP => /TEMP
+ *${TEMP}/foo => /temp/foo
+ *${BACKUP} => /tmp/backup
+ *${BACKUP}/bar.txt => /tmp/backup/bar.txt
+ *SOMEPATH/foo => SOMEPATH/foo
+ * + * @param path the path to be resolved + * @return the resolved path ornull
+ */
+ public String resolvePath(String path);
+
+ /**
+ * Returns true
if the given variable is defined and
+ * false
otherwise. Returns false
if the given
+ * name is not a valid path variable name.
+ *
+ * @param name the variable's name
+ * @return true
if the variable exists, false
+ * otherwise
+ */
+ public boolean isDefined(String name);
+
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/PathEntryVariableChangeEvent.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/PathEntryVariableChangeEvent.java
new file mode 100644
index 00000000000..df0695f348f
--- /dev/null
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/PathEntryVariableChangeEvent.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * QNX Software Systems - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.core.resources;
+
+import java.util.EventObject;
+
+/**
+ * Describes a change in path variable.
+ */
+public class PathEntryVariableChangeEvent extends EventObject {
+ private static final long serialVersionUID = 1L;
+
+ /** Event type constant (value = 1) that denotes a value change . */
+ public final static int VARIABLE_CHANGED = 1;
+
+ /** Event type constant (value = 2) that denotes a variable creation. */
+ public final static int VARIABLE_CREATED = 2;
+
+ /** Event type constant (value = 3) that denotes a variable deletion. */
+ public final static int VARIABLE_DELETED = 3;
+
+
+ /**
+ * The name of the changed variable.
+ */
+ private String variableName;
+
+ /**
+ * The value of the changed variable (may be null).
+ */
+ private String value;
+
+ /** The event type. */
+ private int type;
+
+ /**
+ * Constructor for this class.
+ */
+ public PathEntryVariableChangeEvent(IPathEntryVariableManager source, String variableName, String value, int type) {
+ super(source);
+ if (type < VARIABLE_CHANGED || type > VARIABLE_DELETED)
+ throw new IllegalArgumentException("Invalid event type: " + type); //$NON-NLS-1$
+ this.variableName = variableName;
+ this.value = value;
+ this.type = type;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public String getVariableName() {
+ return variableName;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Return a string representation of this object.
+ */
+ public String toString() {
+ String[] typeStrings = {"VARIABLE_CHANGED", "VARIABLE_CREATED", "VARIABLE_DELETED"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ StringBuffer sb = new StringBuffer(getClass().getName());
+ sb.append("[variable = "); //$NON-NLS-1$
+ sb.append(variableName);
+ sb.append(", type = "); //$NON-NLS-1$
+ sb.append(typeStrings[type - 1]);
+ if (type != VARIABLE_DELETED) {
+ sb.append(", value = "); //$NON-NLS-1$
+ sb.append(value);
+ }
+ sb.append("]"); //$NON-NLS-1$
+ return sb.toString();
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/PathEntryVariableManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/PathEntryVariableManager.java
new file mode 100644
index 00000000000..8bada30ee24
--- /dev/null
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/PathEntryVariableManager.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * QNX Software Systems - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.core;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.resources.IPathEntryVariableChangeListener;
+import org.eclipse.cdt.core.resources.IPathEntryVariableManager;
+import org.eclipse.cdt.core.resources.PathEntryVariableChangeEvent;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+
+
+
+/**
+ * Core's implementation of IPathEntryVariableManager.
+ */
+public class PathEntryVariableManager implements IPathEntryVariableManager {
+
+ private Set listeners;
+ private Preferences preferences;
+
+ static final String VARIABLE_PREFIX = "pathEntryVariable."; //$NON-NLS-1$
+
+ /**
+ * Constructor for the class.
+ */
+ public PathEntryVariableManager() {
+ this.listeners = Collections.synchronizedSet(new HashSet());
+ this.preferences = CCorePlugin.getDefault().getPluginPreferences();
+ }
+
+ /**
+ * Note that if a user changes the key in the preferences file to be invalid
+ * and then calls #getValue using that key, they will get the value back for
+ * that. But then if they try and call #setValue using the same key it will throw
+ * an exception. We may want to revisit this behaviour in the future.
+ *
+ * @see org.eclipse.core.resources.IPathEntryVariableManager#getValue(String)
+ */
+ public String getValue(String varName) {
+ String key = getKeyForName(varName);
+ String value = preferences.getString(key);
+ return value.length() == 0 ? null : value;
+ }
+
+ /**
+ * @see org.eclipse.core.resources.IPathEntryVariableManager#setValue(String, IPath)
+ */
+ public void setValue(String varName, String newValue) throws CoreException {
+ int eventType;
+ // read previous value and set new value atomically in order to generate the right event
+ synchronized (this) {
+ String currentValue = getValue(varName);
+ boolean variableExists = currentValue != null;
+ if (!variableExists && newValue == null) {
+ return;
+ }
+ if (variableExists && currentValue.equals(newValue)) {
+ return;
+ }
+ if (newValue == null) {
+ preferences.setToDefault(getKeyForName(varName));
+ eventType = PathEntryVariableChangeEvent.VARIABLE_DELETED;
+ } else {
+ preferences.setValue(getKeyForName(varName), newValue);
+ eventType = variableExists ? PathEntryVariableChangeEvent.VARIABLE_CHANGED : PathEntryVariableChangeEvent.VARIABLE_CREATED;
+ }
+ }
+ // notify listeners from outside the synchronized block to avoid deadlocks
+ fireVariableChangeEvent(varName, newValue, eventType);
+ }
+
+ /**
+ * Return a key to use in the Preferences.
+ */
+ private String getKeyForName(String varName) {
+ return VARIABLE_PREFIX + varName;
+ }
+
+ /**
+ * @see org.eclipse.core.resources.IPathEntryVariableManager#resolvePath(IPath)
+ */
+ public String resolvePath(String variable) {
+ if (variable == null || variable.length() == 0 || variable.indexOf('$') == -1) {
+ return variable;
+ }
+ String value = expandVariable(variable);
+ return value == null ? variable : value;
+ }
+
+ /**
+ * Fires a property change event corresponding to a change to the
+ * current value of the variable with the given name.
+ *
+ * @param name the name of the variable, to be used as the variable
+ * in the event object
+ * @param value the current value of the path variable or null
if
+ * the variable was deleted
+ * @param type one of IPathVariableChangeEvent.VARIABLE_CREATED
,
+ * PathEntryVariableChangeEvent.VARIABLE_CHANGED
, or
+ * PathEntryVariableChangeEvent.VARIABLE_DELETED
+ * @see PathEntryVariableChangeEvent
+ * @see PathEntryVariableChangeEvent#VARIABLE_CREATED
+ * @see PathEntryVariableChangeEvent#VARIABLE_CHANGED
+ * @see PathEntryVariableChangeEvent#VARIABLE_DELETED
+ */
+ private void fireVariableChangeEvent(String name, String value, int type) {
+ if (this.listeners.size() == 0)
+ return;
+ // use a separate collection to avoid interference of simultaneous additions/removals
+ Object[] listenerArray = this.listeners.toArray();
+ final PathEntryVariableChangeEvent pve = new PathEntryVariableChangeEvent(this, name, value, type);
+ for (int i = 0; i < listenerArray.length; ++i) {
+ final IPathEntryVariableChangeListener l = (IPathEntryVariableChangeListener) listenerArray[i];
+ ISafeRunnable job = new ISafeRunnable() {
+ public void handleException(Throwable exception) {
+ // already being logged in Platform#run()
+ }
+
+ public void run() throws Exception {
+ l.pathVariableChanged(pve);
+ }
+ };
+ Platform.run(job);
+ }
+ }
+
+ /**
+ * @see org.eclipse.core.resources.IPathVariableManager#getPathVariableNames()
+ */
+ public String[] getVariableNames() {
+ List result = new LinkedList();
+ String[] names = preferences.propertyNames();
+ for (int i = 0; i < names.length; i++) {
+ if (names[i].startsWith(VARIABLE_PREFIX)) {
+ String key = names[i].substring(VARIABLE_PREFIX.length());
+ result.add(key);
+ }
+ }
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+ /**
+ * @see org.eclipse.core.resources.
+ * IPathEntryVariableManager#addChangeListener(IPathEntryVariableChangeListener)
+ */
+ public void addChangeListener(IPathEntryVariableChangeListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * @see org.eclipse.core.resources.
+ * IPathEntryVariableManager#removeChangeListener(IPathEntryVariableChangeListener)
+ */
+ public void removeChangeListener(IPathEntryVariableChangeListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * @see org.eclipse.core.resources.IPathVariableManager#isDefined(String)
+ */
+ public boolean isDefined(String varName) {
+ return getValue(varName) != null;
+ }
+
+ public void startup() {
+ }
+
+ public void shutdown() {
+ }
+
+ /**
+ * Expand the variable with the format ${key}. example:
+ * with variable HOME=/foobar
+ * ${HOME}/project
+ * The the return value will be /foobar/project.
+ */
+ protected String expandVariable(String variable) {
+ StringBuffer sb = new StringBuffer();
+ StringBuffer param = new StringBuffer();
+ char prev = '\n';
+ char ch = prev;
+ boolean inMacro = false;
+ boolean inSingleQuote = false;
+
+ for (int i = 0; i < variable.length(); i++) {
+ ch = variable.charAt(i);
+ switch (ch) {
+ case '\'':
+ if (prev != '\\') {
+ inSingleQuote = !inSingleQuote;
+ }
+ break;
+
+ case '$' :
+ if (!inSingleQuote && prev != '\\') {
+ if (i < variable.length() && variable.indexOf('}', i) > 0) {
+ char c = variable.charAt(i + 1);
+ if (c == '{') {
+ param.setLength(0);
+ inMacro = true;
+ prev = ch;
+ continue;
+ }
+ }
+ }
+ break;
+
+ case '}' :
+ if (inMacro) {
+ inMacro = false;
+ String p = param.toString();
+ String v = getValue(p);
+ if (v != null) {
+ sb.append(v);
+ }
+ param.setLength(0);
+ /* Skip the trailing } */
+ prev = ch;
+ continue;
+ }
+ break;
+ } /* switch */
+
+ if (!inMacro) {
+ sb.append(ch);
+ } else {
+ /* Do not had the '{' */
+ if (!(ch == '{' && prev == '$')) {
+ param.append(ch);
+ }
+ }
+ prev = (ch == '\\' && prev == '\\') ? '\n' : ch;
+ } /* for */
+ return sb.toString();
+ }
+
+
+}
\ No newline at end of file