Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuc Bourlier2003-10-21 17:44:09 +0000
committerLuc Bourlier2003-10-21 17:44:09 +0000
commitab911fcde82fd45bcc39ac272c5fbda9a69be5fe (patch)
tree444a44edec1192562892a855816e7ade4d7dd83b /org.eclipse.core.variables/src
parent459e7a37e00d381973d431e7b1db2a8051e1dcfd (diff)
downloadeclipse.platform.debug-ab911fcde82fd45bcc39ac272c5fbda9a69be5fe.tar.gz
eclipse.platform.debug-ab911fcde82fd45bcc39ac272c5fbda9a69be5fe.tar.xz
eclipse.platform.debug-ab911fcde82fd45bcc39ac272c5fbda9a69be5fe.zip
Bug 43332 - String Substitution Support - org.eclipse.core.variables
Diffstat (limited to 'org.eclipse.core.variables/src')
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/internal/variables/DynamicVariable.java63
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/internal/variables/ListenerList.java137
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringSubstitutionEngine.java232
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringVariable.java80
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringVariableManager.java537
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/internal/variables/ValueVariable.java126
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/internal/variables/VariablesMessages.java45
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/internal/variables/VariablesMessages.properties16
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/variables/IDynamicVariable.java37
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/variables/IDynamicVariableResolver.java33
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/variables/IStringVariable.java56
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/variables/IStringVariableManager.java157
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariable.java54
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariableInitializer.java30
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariableListener.java45
-rw-r--r--org.eclipse.core.variables/src/org/eclipse/core/variables/VariablesPlugin.java33
16 files changed, 1680 insertions, 1 deletions
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/DynamicVariable.java b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/DynamicVariable.java
new file mode 100644
index 000000000..bf16e73a8
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/DynamicVariable.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.internal.variables;
+
+import java.text.MessageFormat;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.variables.IDynamicVariable;
+import org.eclipse.core.variables.IDynamicVariableResolver;
+import org.eclipse.core.variables.VariablesPlugin;
+
+/**
+ * Dynamic variable
+ */
+public class DynamicVariable extends StringVariable implements IDynamicVariable {
+
+ /**
+ * Resolver, or <code>null</code> until needed
+ */
+ private IDynamicVariableResolver fResolver;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IContextVariable#getValue(java.lang.String)
+ */
+ public String getValue(String argument) throws CoreException {
+ if (fResolver == null) {
+ String name = getConfigurationElement().getAttribute("resolver"); //$NON-NLS-1$
+ if (name == null) {
+ throw new CoreException(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), VariablesPlugin.INTERNAL_ERROR, MessageFormat.format("Contributed context variable {0} must specify a resolver.",new String[]{getName()}), null)); //$NON-NLS-1$
+ }
+ Object object = getConfigurationElement().createExecutableExtension("resolver"); //$NON-NLS-1$
+ if (object instanceof IDynamicVariableResolver) {
+ fResolver = (IDynamicVariableResolver)object;
+ } else {
+ throw new CoreException(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), VariablesPlugin.INTERNAL_ERROR, MessageFormat.format("Contributed context variable resolver for {0} must be an instance of IContextVariableResolver.",new String[]{getName()}), null)); //$NON-NLS-1$
+ }
+ }
+ return fResolver.resolveValue(this, argument);
+ }
+
+ /**
+ * Constructs a new context variable.
+ *
+ * @param name variable name
+ * @param description variable description or <code>null</code>
+ * @param configurationElement configuration element
+ */
+ public DynamicVariable(String name, String description, IConfigurationElement configurationElement) {
+ super(name, description, configurationElement);
+ }
+
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/ListenerList.java b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/ListenerList.java
new file mode 100644
index 000000000..4ece74163
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/ListenerList.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.internal.variables;
+
+
+/**
+ * Local version of org.eclipse.jface.util.ListenerList (modified)s
+ */
+public class ListenerList {
+ /**
+ * The current number of listeners.
+ * Maintains invariant: 0 <= fSize <= listeners.length.
+ */
+ private int fSize;
+
+ /**
+ * The list of listeners. Initially <code>null</code> but initialized
+ * to an array of size capacity the first time a listener is added.
+ * Maintains invariant: listeners != null if and only if fSize != 0
+ */
+ private Object[] fListeners= null;
+
+ /**
+ * The empty array singleton instance, returned by getListeners()
+ * when size == 0.
+ */
+ private static final Object[] EmptyArray= new Object[0];
+
+ /**
+ * Creates a listener list with the given initial capacity.
+ *
+ * @param capacity the number of listeners which this list can initially accept
+ * without growing its internal representation; must be at least 1
+ */
+ public ListenerList(int capacity) {
+ if (capacity < 1) {
+ throw new IllegalArgumentException();
+ }
+ fListeners= new Object[capacity];
+ fSize= 0;
+ }
+
+ /**
+ * Adds a listener to the list.
+ * Has no effect if an identical listener is already registered.
+ *
+ * @param listener a listener
+ */
+ public synchronized void add(Object listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException();
+ }
+ // check for duplicates using identity
+ for (int i= 0; i < fSize; ++i) {
+ if (fListeners[i] == listener) {
+ return;
+ }
+ }
+ // grow array if necessary
+ if (fSize == fListeners.length) {
+ Object[] temp= new Object[(fSize * 2) + 1];
+ System.arraycopy(fListeners, 0, temp, 0, fSize);
+ fListeners= temp;
+ }
+ fListeners[fSize++]= listener;
+ }
+
+ /**
+ * Returns an array containing all the registered listeners.
+ * The resulting array is unaffected by subsequent adds or removes.
+ * If there are no listeners registered, the result is an empty array
+ * singleton instance (no garbage is created).
+ * Use this method when notifying listeners, so that any modifications
+ * to the listener list during the notification will have no effect on the
+ * notification itself.
+ */
+ public synchronized Object[] getListeners() {
+ if (fSize == 0) {
+ return EmptyArray;
+ }
+ Object[] result= new Object[fSize];
+ System.arraycopy(fListeners, 0, result, 0, fSize);
+ return result;
+ }
+
+ /**
+ * Removes a listener from the list.
+ * Has no effect if an identical listener was not already registered.
+ *
+ * @param listener a listener
+ */
+ public synchronized void remove(Object listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException();
+ }
+
+ for (int i= 0; i < fSize; ++i) {
+ if (fListeners[i] == listener) {
+ if (--fSize == 0) {
+ fListeners= new Object[1];
+ } else {
+ if (i < fSize) {
+ fListeners[i]= fListeners[fSize];
+ }
+ fListeners[fSize]= null;
+ }
+ return;
+ }
+ }
+ }
+
+ /**
+ * Removes all the listeners from the list.
+ */
+ public void removeAll() {
+ fListeners= new Object[0];
+ fSize= 0;
+ }
+
+ /**
+ * Returns the number of registered listeners
+ *
+ * @return the number of registered listeners
+ */
+ public int size() {
+ return fSize;
+ }
+}
+
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringSubstitutionEngine.java b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringSubstitutionEngine.java
new file mode 100644
index 000000000..55b9de2d5
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringSubstitutionEngine.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.internal.variables;
+
+import java.text.MessageFormat;
+import java.util.Stack;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.variables.IDynamicVariable;
+import org.eclipse.core.variables.IStringVariableManager;
+import org.eclipse.core.variables.IValueVariable;
+import org.eclipse.core.variables.VariablesPlugin;
+
+/**
+ * Performs string substitution for context and value variables.
+ */
+public class StringSubstitutionEngine {
+
+ // delimiters
+ private static final String VARIABLE_START = "${"; //$NON-NLS-1$
+ private static final char VARIABLE_END = '}'; //$NON-NLS-1$
+ private static final char VARIABLE_ARG = ':'; //$NON-NLS-1$
+ // parsing states
+ private static final int SCAN_FOR_START = 0;
+ private static final int SCAN_FOR_END = 1;
+
+ /**
+ * Resulting string
+ */
+ private StringBuffer fResult;
+
+ /**
+ * whether substitutions were performed
+ */
+ private boolean fSubs;
+
+ /**
+ * Stack of variables to resolve
+ */
+ private Stack fStack;
+
+ class VariableReference {
+
+ // the text inside the variable reference
+ private StringBuffer fText;
+
+ public VariableReference() {
+ fText = new StringBuffer();
+ }
+
+ public void append(String text) {
+ fText.append(text);
+ }
+
+ public String getText() {
+ return fText.toString();
+ }
+
+ }
+
+ /**
+ * Performs recursive string substitution and returns the resulting string.
+ *
+ * @param expression expression to resolve
+ * @param reportUndefinedVariables whether to report undefined variables as an error
+ * @param manager registry of variables
+ * @return the resulting string with all variables recursively
+ * substituted
+ * @exception CoreException if unable to resolve a referenced variable
+ */
+ public String performStringSubstitution(String expression, boolean reportUndefinedVariables, IStringVariableManager manager) throws CoreException {
+ substitute(expression, reportUndefinedVariables, manager);
+ while (fSubs) {
+ substitute(fResult.toString(), reportUndefinedVariables, manager);
+ }
+ return fResult.toString();
+ }
+
+ /**
+ * Makes a substitution pass of the given expression and returns
+ * whether any substitutions were made.
+ *
+ * @param expression source expression
+ * @param reportUndefinedVariables whether to report undefined variables as an error
+ * @exception CoreException if unable to resolve a variable
+ */
+ private void substitute(String expression, boolean reportUndefinedVariables, IStringVariableManager manager) throws CoreException {
+ fResult = new StringBuffer(expression.length());
+ fStack = new Stack();
+ fSubs = false;
+ int pos = 0;
+ int state = SCAN_FOR_START;
+ while (pos < expression.length()) {
+ switch (state) {
+ case SCAN_FOR_START:
+ int start = expression.indexOf(VARIABLE_START, pos);
+ if (start >= 0) {
+ int length = start - pos;
+ // copy non-variable text to the result
+ if (length > 0) {
+ fResult.append(expression.substring(pos, start));
+ }
+ pos = start + 2;
+ state = SCAN_FOR_END;
+ fStack.push(new VariableReference());
+ } else {
+ // done - no more variables
+ fResult.append(expression.substring(pos));
+ pos = expression.length();
+ }
+ break;
+ case SCAN_FOR_END:
+ // be careful of nested variables
+ start = expression.indexOf(VARIABLE_START, pos);
+ int end = expression.indexOf(VARIABLE_END, pos);
+ if (end < 0) {
+ // variables are not completed
+ VariableReference tos = (VariableReference)fStack.peek();
+ tos.append(expression.substring(pos));
+ pos = expression.length();
+ } else {
+ if (start >= 0 && start < end) {
+ // start of a nested variable
+ int length = start - pos;
+ if (length > 0) {
+ VariableReference tos = (VariableReference)fStack.peek();
+ tos.append(expression.substring(pos, start));
+ }
+ pos = start + 2;
+ fStack.push(new VariableReference());
+ } else {
+ // end of variable reference
+ VariableReference tos = (VariableReference)fStack.pop();
+ tos.append(expression.substring(pos, end));
+ pos = end + 1;
+ String value = resolve(tos, reportUndefinedVariables, manager);
+ if (value == null) {
+ value = ""; //$NON-NLS-1$
+ }
+ if (fStack.isEmpty()) {
+ // append to result
+ fResult.append(value);
+ state = SCAN_FOR_START;
+ } else {
+ // append to previous variable
+ tos = (VariableReference)fStack.peek();
+ tos.append(value);
+ }
+ }
+ }
+ break;
+ }
+ }
+ // process incomplete variable references
+ while (!fStack.isEmpty()) {
+ VariableReference tos = (VariableReference)fStack.pop();
+ if (fStack.isEmpty()) {
+ fResult.append(VARIABLE_START);
+ fResult.append(tos.getText());
+ } else {
+ VariableReference var = (VariableReference)fStack.peek();
+ var.append(VARIABLE_START);
+ var.append(tos.getText());
+ }
+ }
+ }
+
+ /**
+ * Resolve and return the value of the given variable reference,
+ * possibly <code>null</code>.
+ *
+ * @param var
+ * @param reportUndefinedVariables whether to report undefined variables as
+ * an error
+ * @param manager variable registry
+ * @return variable value, possibly <code>null</code>
+ * @exception CoreException if unable to resolve a value
+ */
+ private String resolve(VariableReference var, boolean reportUndefinedVariables, IStringVariableManager manager) throws CoreException {
+ String text = var.getText();
+ int pos = text.indexOf(VARIABLE_ARG);
+ String name = null;
+ String arg = null;
+ if (pos > 0) {
+ name = text.substring(0, pos);
+ pos++;
+ if (pos < text.length()) {
+ arg = text.substring(pos);
+ }
+ } else {
+ name = text;
+ }
+ IValueVariable valueVariable = manager.getValueVariable(name);
+ if (valueVariable == null) {
+ IDynamicVariable dynamicVariable = manager.getDynamicVariable(name);
+ if (dynamicVariable == null) {
+ // no variables with the given name
+ if (reportUndefinedVariables) {
+ throw new CoreException(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), VariablesPlugin.INTERNAL_ERROR, MessageFormat.format(VariablesMessages.getString("StringSubstitutionEngine.3"), new String[]{name}), null)); //$NON-NLS-1$
+ } else {
+ // leave as is
+ StringBuffer res = new StringBuffer(var.getText());
+ res.insert(0, VARIABLE_START);
+ res.append(VARIABLE_END);
+ return res.toString();
+ }
+ } else {
+ fSubs = true;
+ return dynamicVariable.getValue(arg);
+ }
+ } else {
+ if (arg == null) {
+ fSubs = true;
+ return valueVariable.getValue();
+ } else {
+ // error - an argument specified for a value variable
+ throw new CoreException(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), VariablesPlugin.INTERNAL_ERROR, MessageFormat.format("Variable {0} does not accept arguments.", new String[]{valueVariable.getName()}), null)); //$NON-NLS-1$
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringVariable.java b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringVariable.java
new file mode 100644
index 000000000..cb7642050
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringVariable.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.internal.variables;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.variables.IStringVariable;
+
+/**
+ * Common implementation of context and value variables
+ */
+public abstract class StringVariable implements IStringVariable {
+
+ /**
+ * Variable name
+ */
+ private String fName;
+
+ /**
+ * Variable description, or <code>null</code>
+ */
+ private String fDescription;
+
+ /**
+ * Configuration element associated with this variable, or <code>null</code>
+ */
+ private IConfigurationElement fConfigurationElement;
+
+ /**
+ * Constructs a new variable with the given name and description.
+ *
+ * @param name variable name
+ * @param description variable description, or <code>null</code>
+ */
+ public StringVariable(String name, String description, IConfigurationElement configurationElement) {
+ fName = name;
+ fDescription = description;
+ fConfigurationElement = configurationElement;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariable#getName()
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariable#getDescription()
+ */
+ public String getDescription() {
+ return fDescription;
+ }
+
+ /**
+ * Returns the configuration element associated with this variable, or <code>null</code>
+ * if none.
+ *
+ * @return configuration element or <code>null</code>
+ */
+ protected IConfigurationElement getConfigurationElement() {
+ return fConfigurationElement;
+ }
+
+ /**
+ * @see IValueVariable#setDescription(String)
+ * @param description
+ */
+ public void setDescription(String description) {
+ fDescription = description;
+ }
+
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringVariableManager.java b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringVariableManager.java
new file mode 100644
index 000000000..05bc6945b
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/StringVariableManager.java
@@ -0,0 +1,537 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.internal.variables;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+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.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.variables.IDynamicVariable;
+import org.eclipse.core.variables.IStringVariable;
+import org.eclipse.core.variables.IStringVariableManager;
+import org.eclipse.core.variables.IValueVariable;
+import org.eclipse.core.variables.IValueVariableListener;
+import org.eclipse.core.variables.VariablesPlugin;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Singleton string variable manager.
+ */
+public class StringVariableManager implements IStringVariableManager {
+
+ /**
+ * Dynamic variables - maps variable names to variables.
+ */
+ private Map fDynamicVariables;
+
+ /**
+ * Value varialbes - maps variable names to variables.
+ */
+ private Map fValueVariables;
+
+ /**
+ * Variable listeners
+ */
+ private ListenerList fListeners;
+
+ // notifications
+ private static final int ADDED = 0;
+ private static final int CHANGED = 1;
+ private static final int REMOVED = 2;
+
+ /**
+ * Singleton variable manager.
+ */
+ private static StringVariableManager fgManager;
+
+ // true during initialization code - supress change notification
+ private boolean fInitializing = false;
+
+ // Variable extension point constants
+ private static final String ATTR_NAME= "name"; //$NON-NLS-1$
+ private static final String ATTR_DESCRIPTION="description"; //$NON-NLS-1$
+ // Persisted variable XML constants
+ private static final String VALUE_VARIABLES_TAG= "valueVariables"; //$NON-NLS-1$
+ private static final String VALUE_VARIABLE_TAG= "valueVariable"; //$NON-NLS-1$
+ private static final String NAME_TAG= "name"; //$NON-NLS-1$
+ private static final String VALUE_TAG= "value"; //$NON-NLS-1$
+ private static final String DESCRIPTION_TAG="description"; //$NON-NLS-1$
+ private static final String INITIALIZED_TAG="contributed"; //$NON-NLS-1$
+ // XML values
+ private static final String TRUE_VALUE= "true"; //$NON-NLS-1$
+ private static final String FALSE_VALUE= "false"; //$NON-NLS-1$
+ // preference store key for value variables
+ private static final String PREF_VALUE_VARIABLES= VariablesPlugin.getUniqueIdentifier() + ".valueVariables"; //$NON-NLS-1$
+
+ /**
+ * Notifies a string variable listener in a safe runnable to handle
+ * exceptions.
+ */
+ class StringVariableNotifier implements ISafeRunnable {
+
+ private IValueVariableListener fListener;
+ private int fType;
+ private IValueVariable[] fVariables;
+
+ /**
+ * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
+ */
+ public void handleException(Throwable exception) {
+ IStatus status = new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), VariablesPlugin.INTERNAL_ERROR, "An exception occurred during string variable change notification", exception); //$NON-NLS-1$
+ VariablesPlugin.log(status);
+ }
+
+ /**
+ * @see org.eclipse.core.runtime.ISafeRunnable#run()
+ */
+ public void run() throws Exception {
+ switch (fType) {
+ case ADDED:
+ fListener.variablesAdded(fVariables);
+ break;
+ case REMOVED:
+ fListener.variablesRemoved(fVariables);
+ break;
+ case CHANGED:
+ fListener.variablesChanged(fVariables);
+ break;
+ }
+ }
+
+ /**
+ * Notifies the given listener of the add/change/remove
+ *
+ * @param listener the listener to notify
+ * @param launch the launch that has changed
+ * @param update the type of change
+ */
+ public void notify(IValueVariable[] variables, int update) {
+ fVariables = variables;
+ fType = update;
+ Object[] copiedListeners= fListeners.getListeners();
+ for (int i= 0; i < copiedListeners.length; i++) {
+ fListener = (IValueVariableListener)copiedListeners[i];
+ Platform.run(this);
+ }
+ fVariables = null;
+ fListener = null;
+ // persist variables whenever there is an add/change/remove
+ storeValueVariables();
+ }
+ }
+
+ /**
+ * Returns a new notifier.
+ *
+ * @return a new notifier
+ */
+ private StringVariableNotifier getNotifier() {
+ return new StringVariableNotifier();
+ }
+
+ /**
+ * Returns the default string variable manager
+ *
+ * @return string variable manager
+ */
+ public static StringVariableManager getDefault() {
+ if (fgManager == null) {
+ fgManager = new StringVariableManager();
+ }
+ return fgManager;
+ }
+
+ /**
+ * Constructs a new string variable manager.
+ */
+ private StringVariableManager() {
+ fListeners = new ListenerList(5);
+ }
+
+ /**
+ * Load contributed variables and persisted variables
+ */
+ private void initialize() {
+ if (fDynamicVariables == null) {
+ fInitializing = true;
+ fDynamicVariables = new HashMap(5);
+ fValueVariables = new HashMap(5);
+ loadPersistedValueVariables();
+ loadContributedValueVariables();
+ loadDynamicVariables();
+ fInitializing = false;
+ }
+ }
+
+ /**
+ * Loads contributed dynamic variables
+ */
+ private void loadDynamicVariables() {
+ IExtensionPoint point= VariablesPlugin.getDefault().getDescriptor().getExtensionPoint(EXTENSION_POINT_DYNAMIC_VARIABLES);
+ IConfigurationElement elements[]= point.getConfigurationElements();
+ for (int i = 0; i < elements.length; i++) {
+ IConfigurationElement element = elements[i];
+ String name= element.getAttribute(ATTR_NAME);
+ if (name == null) {
+ VariablesPlugin.logMessage(MessageFormat.format("Variable extension missing required 'name' attribute: {0}", new String[] {element.getDeclaringExtension().getLabel()}), null); //$NON-NLS-1$
+ continue;
+ }
+ String description= element.getAttribute(ATTR_DESCRIPTION);
+ DynamicVariable variable= new DynamicVariable(name, description, element);
+ fDynamicVariables.put(variable.getName(), variable);
+ }
+ }
+
+ /**
+ * Loads any persisted value varialbes from the preference store.
+ */
+ private void loadPersistedValueVariables() {
+ String variablesString= VariablesPlugin.getDefault().getPluginPreferences().getString(PREF_VALUE_VARIABLES);
+ if (variablesString.length() == 0) {
+ return;
+ }
+ Element root= null;
+ try {
+ ByteArrayInputStream stream= new ByteArrayInputStream(variablesString.getBytes("UTF-8")); //$NON-NLS-1$
+ DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ root = parser.parse(stream).getDocumentElement();
+ } catch (Throwable throwable) {
+ VariablesPlugin.logMessage("An exception occurred while loading persisted value variables.", throwable); //$NON-NLS-1$
+ return;
+ }
+ if (!root.getNodeName().equals(VALUE_VARIABLES_TAG)) {
+ VariablesPlugin.logMessage("Invalid format encountered while loading persisted value variables.", null); //$NON-NLS-1$
+ return;
+ }
+ NodeList list= root.getChildNodes();
+ for (int i= 0, numItems= list.getLength(); i < numItems; i++) {
+ Node node= list.item(i);
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ Element element= (Element) node;
+ if (!element.getNodeName().equals(VALUE_VARIABLE_TAG)) {
+ VariablesPlugin.logMessage(MessageFormat.format("Invalid XML element encountered while loading value variables: {0}", new String[] {node.getNodeName()}), null); //$NON-NLS-1$
+ continue;
+ }
+ String name= element.getAttribute(NAME_TAG);
+ if (name.length() > 0) {
+ String value= element.getAttribute(VALUE_TAG);
+ String description= element.getAttribute(DESCRIPTION_TAG);
+ boolean initialized= TRUE_VALUE.equals(element.getAttribute(INITIALIZED_TAG));
+ ValueVariable variable= new ValueVariable(name, description, null);
+ if (initialized) {
+ variable.setValue(value);
+ }
+ fValueVariables.put(name, variable);
+ } else {
+ VariablesPlugin.logMessage("Invalid variable entry encountered while loading value variables. Variable name is null.", null); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ /**
+ * Loads contributed value variables. This is done after the persisted value
+ * varaibles are restored. Any contributed variables with the same name are
+ * merged with existing persisted values.
+ */
+ private void loadContributedValueVariables() {
+ IExtensionPoint point= VariablesPlugin.getDefault().getDescriptor().getExtensionPoint(EXTENSION_POINT_VALUE_VARIABLES);
+ IConfigurationElement elements[]= point.getConfigurationElements();
+ for (int i = 0; i < elements.length; i++) {
+ IConfigurationElement element = elements[i];
+ String name= element.getAttribute(ATTR_NAME);
+ if (name == null) {
+ VariablesPlugin.logMessage(MessageFormat.format("Variable extension missing required 'name' attribute: {0}", new String[] {element.getDeclaringExtension().getLabel()}), null); //$NON-NLS-1$
+ continue;
+ }
+ String description= element.getAttribute(ATTR_DESCRIPTION);
+ ValueVariable variable= new ValueVariable(name, description, element);
+ // if already present, merge with persisted value
+ ValueVariable existing = (ValueVariable)getValueVariable(name);
+ if (existing != null) {
+ if (existing.isInitialized()) {
+ variable.setValue(existing.getValue());
+ }
+ }
+ fValueVariables.put(variable.getName(), variable);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#getVariables()
+ */
+ public IStringVariable[] getVariables() {
+ initialize();
+ List list = new ArrayList(fDynamicVariables.size() + fValueVariables.size());
+ list.addAll(fDynamicVariables.values());
+ list.addAll(fValueVariables.values());
+ return (IStringVariable[]) list.toArray(new IStringVariable[list.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#getValueVariables()
+ */
+ public IValueVariable[] getValueVariables() {
+ initialize();
+ return (IValueVariable[]) fValueVariables.values().toArray(new IValueVariable[fValueVariables.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#getDynamicVariables()
+ */
+ public IDynamicVariable[] getDynamicVariables() {
+ initialize();
+ return (IDynamicVariable[]) fDynamicVariables.values().toArray(new IDynamicVariable[fDynamicVariables.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#performStringSubstitution(java.lang.String)
+ */
+ public String performStringSubstitution(String expression) throws CoreException {
+ return performStringSubstitution(expression, true);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#newValueVariable(java.lang.String, java.lang.String)
+ */
+ public IValueVariable newValueVariable(String name, String description) {
+ IConfigurationElement element = null;
+ ValueVariable existing = (ValueVariable)getValueVariable(name);
+ if (existing != null && existing.isContributed()) {
+ element = existing.getConfigurationElement();
+ }
+ return new ValueVariable(name, description, element);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#addVariables(org.eclipse.debug.internal.core.stringsubstitution.IValueVariable[])
+ */
+ public void addVariables(IValueVariable[] variables) throws CoreException {
+ initialize();
+ MultiStatus status = new MultiStatus(VariablesPlugin.getUniqueIdentifier(), VariablesPlugin.INTERNAL_ERROR, VariablesMessages.getString("StringVariableManager.26"), null); //$NON-NLS-1$
+ for (int i = 0; i < variables.length; i++) {
+ IValueVariable variable = variables[i];
+ if (getValueVariable(variable.getName()) != null) {
+ status.add(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), VariablesPlugin.INTERNAL_ERROR, MessageFormat.format(VariablesMessages.getString("StringVariableManager.27"), new String[]{variable.getName()}), null)); //$NON-NLS-1$
+ }
+ }
+ if (status.isOK()) {
+ for (int i = 0; i < variables.length; i++) {
+ IValueVariable variable = variables[i];
+ fValueVariables.put(variable.getName(), variable);
+ }
+ IValueVariable[] copy = new IValueVariable[variables.length];
+ System.arraycopy(variables, 0, copy, 0, variables.length);
+ getNotifier().notify(copy, ADDED);
+ return;
+ }
+ throw new CoreException(status);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#removeVariables(org.eclipse.debug.internal.core.stringsubstitution.IValueVariable[])
+ */
+ public void removeVariables(IValueVariable[] variables) {
+ initialize();
+ List removed = new ArrayList(variables.length);
+ for (int i = 0; i < variables.length; i++) {
+ IValueVariable variable = variables[i];
+ if (fValueVariables.remove(variable.getName()) != null) {
+ removed.add(variable);
+ }
+ }
+ if (removed.size() > 0) {
+ getNotifier().notify((IValueVariable[])removed.toArray(new IValueVariable[removed.size()]), REMOVED);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#getDynamicVariable(java.lang.String)
+ */
+ public IDynamicVariable getDynamicVariable(String name) {
+ initialize();
+ return (IDynamicVariable) fDynamicVariables.get(name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#getValueVariable(java.lang.String)
+ */
+ public IValueVariable getValueVariable(String name) {
+ initialize();
+ return (IValueVariable) fValueVariables.get(name);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#addValueVariableListener(org.eclipse.debug.internal.core.stringsubstitution.IValueVariableListener)
+ */
+ public void addValueVariableListener(IValueVariableListener listener) {
+ fListeners.add(listener);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#removeValueVariableListener(org.eclipse.debug.internal.core.stringsubstitution.IValueVariableListener)
+ */
+ public void removeValueVariableListener(IValueVariableListener listener) {
+ fListeners.remove(listener);
+ }
+
+ /**
+ * Returns a memento representing the value variables currently registered.
+ *
+ * @return memento representing the value variables currently registered
+ * @throws IOException if an I/O exception occurs while creating the XML.
+ */
+ private String getValueVariablesAsXML() throws IOException, ParserConfigurationException, TransformerException {
+ IValueVariable[] variables = getValueVariables();
+
+ Document document= getDocument();
+ Element rootElement= document.createElement(VALUE_VARIABLES_TAG);
+ document.appendChild(rootElement);
+ for (int i = 0; i < variables.length; i++) {
+ ValueVariable variable = (ValueVariable)variables[i];
+ Element element= document.createElement(VALUE_VARIABLE_TAG);
+ element.setAttribute(NAME_TAG, variable.getName());
+ String value= variable.getValue();
+ if (value != null) {
+ element.setAttribute(VALUE_TAG, value);
+ }
+ String description= variable.getDescription();
+ if (description != null) {
+ element.setAttribute(DESCRIPTION_TAG, description);
+ }
+ element.setAttribute(INITIALIZED_TAG, variable.isInitialized() ? TRUE_VALUE : FALSE_VALUE);
+ rootElement.appendChild(element);
+ }
+ return serializeDocument(document);
+ }
+
+ private Document getDocument() throws ParserConfigurationException {
+ DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
+ Document doc =docBuilder.newDocument();
+ return doc;
+ }
+
+ /**
+ * 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
+ * @throws TransformerException if an unrecoverable error occurs during the serialization
+ * @throws IOException if the encoding attempted to be used is not supported
+ */
+ private String serializeDocument(Document doc) throws TransformerException, UnsupportedEncodingException {
+ ByteArrayOutputStream s= new ByteArrayOutputStream();
+
+ TransformerFactory factory= TransformerFactory.newInstance();
+ Transformer transformer= factory.newTransformer();
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+
+ DOMSource source= new DOMSource(doc);
+ StreamResult outputTarget= new StreamResult(s);
+ transformer.transform(source, outputTarget);
+
+ return s.toString("UTF8"); //$NON-NLS-1$
+ }
+
+ /**
+ * Saves the value variables currently registered in the
+ * preference store.
+ */
+ private void storeValueVariables() {
+ Preferences prefs= VariablesPlugin.getDefault().getPluginPreferences();
+ String variableString= ""; //$NON-NLS-1$
+ if (!fValueVariables.isEmpty()) {
+ try {
+ variableString= getValueVariablesAsXML();
+ } catch (IOException e) {
+ VariablesPlugin.log(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), IStatus.ERROR, "An exception occurred while storing launch configuration variables.", e)); //$NON-NLS-1$
+ return;
+ } catch (ParserConfigurationException e) {
+ VariablesPlugin.log(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), IStatus.ERROR, "An exception occurred while storing launch configuration variables.", e)); //$NON-NLS-1$
+ return;
+ } catch (TransformerException e) {
+ VariablesPlugin.log(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), IStatus.ERROR, "An exception occurred while storing launch configuration variables.", e)); //$NON-NLS-1$
+ return;
+ }
+ }
+ prefs.setValue(PREF_VALUE_VARIABLES, variableString);
+ VariablesPlugin.getDefault().savePluginPreferences();
+ }
+
+ /**
+ * Fire a change notification for the given variable.
+ *
+ * @param variable the variable that has changed
+ */
+ protected void notifyChanged(ValueVariable variable) {
+ if (!fInitializing) {
+ IValueVariable existing = getValueVariable(variable.getName());
+ if (variable.equals(existing)) {
+ // do not do change notification for unregistered variables
+ getNotifier().notify(new IValueVariable[]{variable}, CHANGED);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#generateVariableExpression(java.lang.String, java.lang.String)
+ */
+ public String generateVariableExpression(String varName, String arg) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("${"); //$NON-NLS-1$
+ buffer.append(varName);
+ if (arg != null) {
+ buffer.append(":"); //$NON-NLS-1$
+ buffer.append(arg);
+ }
+ buffer.append("}"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IStringVariableManager#performStringSubstitution(java.lang.String, boolean)
+ */
+ public String performStringSubstitution(String expression, boolean reportUndefinedVariables) throws CoreException {
+ return new StringSubstitutionEngine().performStringSubstitution(expression, reportUndefinedVariables, this);
+ }
+
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/ValueVariable.java b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/ValueVariable.java
new file mode 100644
index 000000000..5ecb45a93
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/ValueVariable.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.internal.variables;
+
+import java.text.MessageFormat;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.variables.IValueVariable;
+import org.eclipse.core.variables.IValueVariableInitializer;
+import org.eclipse.core.variables.VariablesPlugin;
+
+/**
+ * Implementation of a value variable.
+ */
+public class ValueVariable extends StringVariable implements IValueVariable {
+
+ /**
+ * Variable value or <code>null</code> if none
+ */
+ private String fValue;
+
+ /**
+ * Whether this variable's value has been initialized
+ */
+ private boolean fInitialized = false;
+
+ /**
+ * Constructs a new value variable with the given name, description, and
+ * associated configuration element.
+ *
+ * @param name variable name
+ * @param description variable description, or <code>null</code>
+ * @param configurationElement configuration element or <code>null</code>
+ */
+ public ValueVariable(String name, String description, IConfigurationElement configurationElement) {
+ super(name, description, configurationElement);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IValueVariable#setValue(java.lang.String)
+ */
+ public void setValue(String value) {
+ fValue = value;
+ setInitialized(true);
+ StringVariableManager.getDefault().notifyChanged(this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IValueVariable#getValue()
+ */
+ public String getValue() {
+ if (!isInitialized()) {
+ initialize();
+ }
+ return fValue;
+ }
+
+ /**
+ * Initialize this variable's value.
+ */
+ private void initialize() {
+ if (getConfigurationElement() != null) {
+ // check for a explicit value specified in plug-in XML
+ String value = getConfigurationElement().getAttribute("initialValue"); //$NON-NLS-1$
+ if (value == null) {
+ // check for initializer
+ String className = getConfigurationElement().getAttribute("initializerClass"); //$NON-NLS-1$
+ if (className != null) {
+ try {
+ Object object = getConfigurationElement().createExecutableExtension("initializerClass"); //$NON-NLS-1$
+ if (object instanceof IValueVariableInitializer) {
+ IValueVariableInitializer initializer = (IValueVariableInitializer)object;
+ initializer.initialize(this);
+ } else {
+ VariablesPlugin.logMessage(MessageFormat.format("Unable to initialize variable {0} - initializer must be an instance of IValueVariableInitializer.", new String[]{getName()}), null); //$NON-NLS-1$
+ }
+ } catch (CoreException e) {
+ VariablesPlugin.logMessage(MessageFormat.format("Unable to initialize variable {0}",new String[]{getName()}), e); //$NON-NLS-1$
+ }
+ }
+ } else {
+ setValue(value);
+ }
+ }
+ setInitialized(true);
+ }
+
+ /**
+ * Returns whether this variable has been initialized with a value by one of:
+ * <ul>
+ * <li><code>setValue(String)</code></li>
+ * <li>its configuration element's <code>initialValue</code> attribute</li>
+ * <li>its configuration element's initializer</li>
+ * </ul>
+ * @return whether this variable has been initialized with a value
+ */
+ protected boolean isInitialized() {
+ return fInitialized;
+ }
+
+ /**
+ * Sets whether this variable has been initialized with a value.
+ *
+ * @param initialized whether this variable has been initialized
+ */
+ protected void setInitialized(boolean initialized) {
+ fInitialized = initialized;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.stringsubstitution.IValueVariable#isContributed()
+ */
+ public boolean isContributed() {
+ return getConfigurationElement() != null;
+ }
+
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/VariablesMessages.java b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/VariablesMessages.java
new file mode 100644
index 000000000..3a8ac8c86
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/VariablesMessages.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.internal.variables;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * StringSubstitutionMessages
+ */
+public class VariablesMessages {
+
+ private static final String BUNDLE_NAME = "org.eclipse.core.internal.variables.VariablesMessages"; //$NON-NLS-1$
+
+ private static final ResourceBundle RESOURCE_BUNDLE =
+ ResourceBundle.getBundle(BUNDLE_NAME);
+
+ /**
+ *
+ */
+ private VariablesMessages() {
+
+ // TODO Auto-generated constructor stub
+ }
+ /**
+ * @param key
+ * @return
+ */
+ public static String getString(String key) {
+ // TODO Auto-generated method stub
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/VariablesMessages.properties b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/VariablesMessages.properties
new file mode 100644
index 000000000..e812fb2b9
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/internal/variables/VariablesMessages.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2000, 2003 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
+###############################################################################
+
+StringSubstitutionEngine.3=Reference to undefined variable {0}
+
+StringVariableManager.26=Variables with the specified names are already registered.
+StringVariableManager.27=Variable named {0} already registered
+
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/variables/IDynamicVariable.java b/org.eclipse.core.variables/src/org/eclipse/core/variables/IDynamicVariable.java
new file mode 100644
index 000000000..4e6789a8d
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/variables/IDynamicVariable.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.variables;
+
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * A dynamic variable is a variable whose value is computed dynamically
+ * by a resolver at the time a string substitution is performed. A dynamic
+ * variable is contributed by an extension.
+ *
+ * TODO: example extension
+ *
+ * @since 3.0
+ */
+public interface IDynamicVariable extends IStringVariable {
+
+ /**
+ * Returns the value of this variable when referenced with the given
+ * argument, possibly <code>null</code>.
+ *
+ * @param argument argument present in variable expression or <code>null</code>
+ * if none
+ * @return value of this variable when referenced with the given argument, possibly
+ * <code>null</code>
+ * @throws CoreException if unable to resolve a value for this variable
+ */
+ public String getValue(String argument) throws CoreException;
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/variables/IDynamicVariableResolver.java b/org.eclipse.core.variables/src/org/eclipse/core/variables/IDynamicVariableResolver.java
new file mode 100644
index 000000000..6187525d2
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/variables/IDynamicVariableResolver.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.variables;
+
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * Resolves the value for a dynamic variable. A dynamic variable extension
+ * contributes a resolver which must implement this interface.
+ *
+ * @since 3.0
+ */
+public interface IDynamicVariableResolver {
+
+ /**
+ * Resolves and returns a value for the specified variable when referenced
+ * with the given argument, possibly <code>null</code>
+ *
+ * @param variable variable to resolve a value for
+ * @param argument argument present in expression or <code>null</code> if none
+ * @return variable value, possibly <code>null</code>
+ * @throws CoreException if unable to resolve a value for the given variable
+ */
+ public String resolveValue(IDynamicVariable variable, String argument) throws CoreException;
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/variables/IStringVariable.java b/org.eclipse.core.variables/src/org/eclipse/core/variables/IStringVariable.java
new file mode 100644
index 000000000..69bab0a3b
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/variables/IStringVariable.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.variables;
+
+
+/**
+ * A variable that can be referenced in an expression, which resolves to a string
+ * value. Variables are referenced in expressions via their name, in the following
+ * format.
+ * <pre>
+ * ${varname} or ${varname:argument}
+ * </pre>
+ * <p>
+ * A variable is identified by its name, and optionally accepts an argument. When an
+ * argument is present, a colon seperates the variable name from its argument.
+ * </p>
+ * <p>
+ * Variables can be contributed by extensions or programmatically. There are two
+ * kinds of variables.
+ * <ul>
+ * <li><code>IValueVariable</code> - variables that have a value (with getter and setter), and
+ * accept no arguments. The value of this type of variable is resolved at the time
+ * its value is set via its setter API.</li>
+ * <li><code>IDynamicVariable</code> - variables whose value is resolved at the time
+ * a string substitution is performed by a contributed resolver. Dynamic variables
+ * may accept an argument.</li>
+ * </ul>
+ * </p>
+ * @since 3.0
+ */
+public interface IStringVariable {
+
+ /**
+ * Returns the name of this variable. A variable is uniquely identified by
+ * its name.
+ *
+ * @return variable name
+ */
+ public String getName();
+
+ /**
+ * Returns a human readable description of this variable, possibly <code>null</code>
+ *
+ * @return a description of this variable, or <code>null</code> if none
+ */
+ public String getDescription();
+
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/variables/IStringVariableManager.java b/org.eclipse.core.variables/src/org/eclipse/core/variables/IStringVariableManager.java
new file mode 100644
index 000000000..06d2b33f8
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/variables/IStringVariableManager.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.variables;
+
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * Regisitry for string variables.
+ *
+ * @since 3.0
+ */
+public interface IStringVariableManager {
+
+ /**
+ * Simple identifier constant (value <code>"dynamicVariables"</code>) for the
+ * context variables extension point.
+ */
+ public static final String EXTENSION_POINT_DYNAMIC_VARIABLES = "dynamicVariables"; //$NON-NLS-1$
+
+ /**
+ * Simple identifier constant (value <code>"valueVariables"</code>) for the
+ * value variables extension point.
+ */
+ public static final String EXTENSION_POINT_VALUE_VARIABLES = "valueVariables"; //$NON-NLS-1$
+
+ /**
+ * Returns all registered variables.
+ *
+ * @return a collection of all registered variables
+ */
+ public IStringVariable[] getVariables();
+
+ /**
+ * Returns all registered value variables.
+ *
+ * @return a collection of all registered value variables
+ */
+ public IValueVariable[] getValueVariables();
+
+ /**
+ * Returns the value variable with the given name, or <code>null</code>
+ * if none.
+ *
+ * @param name variable name
+ * @return the value variable with the given name, or <code>null</code>
+ * if none
+ */
+ public IValueVariable getValueVariable(String name);
+
+ /**
+ * Returns all registered dynamic variables.
+ *
+ * @return a collection of all registered dynamic variables
+ */
+ public IDynamicVariable[] getDynamicVariables();
+
+ /**
+ * Returns the dynamic variable with the given name or <code>null</code>
+ * if none.
+ *
+ * @param name variable name
+ * @return the dynamic variable with the given name or <code>null</code>
+ * if none
+ */
+ public IDynamicVariable getDynamicVariable(String name);
+
+ /**
+ * Recursively resolves and replaces all variable references in the given
+ * expression with their corresponding values. Reports errors for references
+ * to undefined variables (equivalent to calling
+ * <code>performStringSubstitution(expression, true)</code>).
+ *
+ * @param expression expression referencing variables
+ * @return expression with variable references replaced with variable values
+ * @throws CoreException if unable to resolve the value of one or more variables
+ */
+ public String performStringSubstitution(String expression) throws CoreException;
+
+ /**
+ * Recursively resolves and replaces all variable references in the given
+ * expression with their corresponding values. Allows the client to control
+ * whether references to undefeind variables are reported as an error (i.e.
+ * an exception is thrown).
+ *
+ * @param expression expression referencing variables
+ * @param reportUndefinedVariables whether a reference to an undefined variable
+ * is to be considered an error (i.e. throw an exception)
+ * @return expression with variable references replaced with variable values
+ * @throws CoreException if unable to resolve the value of one or more variables
+ */
+ public String performStringSubstitution(String expression, boolean reportUndefinedVariables) throws CoreException;
+
+ /**
+ * Returns a new value variable with the given name and description.
+ *
+ * @param name variable name, cannot be <code>null</code>
+ * @param description variable description, possibly <code>null</code>
+ * @return a new variable
+ * @exception CoreException if a variable already exists with the given name
+ */
+ public IValueVariable newValueVariable(String name, String description);
+
+ /**
+ * Adds the given variables to the variable registry.
+ *
+ * @param variables the variables to add
+ * @throws CoreException if one or more variables to add has a name collision with
+ * an existing variable
+ */
+ public void addVariables(IValueVariable[] variables) throws CoreException;
+
+ /**
+ * Removes the given variables from the registry. Has no effect for unregistered
+ * variables.
+ *
+ * @param variables variables to remove
+ */
+ public void removeVariables(IValueVariable[] variables);
+
+ /**
+ * Registers the given listener for value variable notifications. Has no effect
+ * if an identical listener is already registered.
+ *
+ * @param listener value variable listener to add
+ */
+ public void addValueVariableListener(IValueVariableListener listener);
+
+ /**
+ * Removes the given listener from the list of registered value variable
+ * listeners. Has no effect if an identical listener is not already registered.
+ *
+ * @param listener value variable listener to remove
+ */
+ public void removeValueVariableListener(IValueVariableListener listener);
+
+ /**
+ * Convenience method that returns an expression referencing the given
+ * variable and optional argument. For example, calling the method with
+ * a <code>varName</code> of <code>my_var</code> and an <code>argument</code>
+ * of <code>my_arg</code> results in the string <code>$(my_var:my_arg}</code>.
+ *
+ * @param varName variable name
+ * @param arg argument text or <code>null</code>
+ * @return an expression referencing the given variable and
+ * optional argument
+ */
+ public String generateVariableExpression(String varName, String arg);
+
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariable.java b/org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariable.java
new file mode 100644
index 000000000..9ffed0fed
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariable.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.variables;
+
+/**
+ * A variable with a value that can be set and retrieved. The context in which
+ * a value variable is referenced does not effect the value of the variable.
+ * A value variable can be contributed by an extension or created programmatically.
+ * A contributor may optionally specify an initial value for a variable, or
+ * provide a delegate that will initialie the variable with a value.
+ *
+ * TODO: example plug-in XML
+ *
+ * @since 3.0
+ */
+public interface IValueVariable extends IStringVariable {
+
+ /**
+ * Sets the value of this variable to the given value. A value of
+ * <code>null</code> indicates the value of this variable is undefined.
+ *
+ * @param value variable value, possibly <code>null</code>
+ */
+ public void setValue(String value);
+
+ /**
+ * Returns the value of this variable, or <code>null</code> if none.
+ *
+ * @return the value of this variable, or <code>null</code> if none
+ */
+ public String getValue();
+
+ /**
+ * Returns whether this variable was contributed by an extension.
+ *
+ * @return whether this variable was contributed by an extension
+ */
+ public boolean isContributed();
+
+ /**
+ * Sets the description of this variable to the given value.
+ *
+ * @param description variable description, possibly <code>null</code>
+ */
+ public void setDescription(String description);
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariableInitializer.java b/org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariableInitializer.java
new file mode 100644
index 000000000..16cc8feb6
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariableInitializer.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.variables;
+
+/**
+ * Value variable initializers compute an initial value for a value
+ * variable contributed by an extension, which is not defined with an initial
+ * value. This provides a mechnism for programatically computing the initial
+ * value of a value variable.
+ * <p>
+ * Clients may implement this interface.
+ * </p>
+ * @since 3.0
+ */
+public interface IValueVariableInitializer {
+ /**
+ * Initializes the specified variable.
+ *
+ * @param variable variable to initialize
+ */
+ public void initialize(IValueVariable variable);
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariableListener.java b/org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariableListener.java
new file mode 100644
index 000000000..10a26f82e
--- /dev/null
+++ b/org.eclipse.core.variables/src/org/eclipse/core/variables/IValueVariableListener.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ *******************************************************************************/
+package org.eclipse.core.variables;
+
+/**
+ * A string variable listener is notified of variables as they are added
+ * and removed from the string variable manager. As well, listeners are
+ * notified when a value variable changes value.
+ *
+ * since 3.0
+ */
+public interface IValueVariableListener {
+
+ /**
+ * Notification the given variables have been added to the variable
+ * manager.
+ *
+ * @param variables added variables
+ */
+ public void variablesAdded(IValueVariable[] variables);
+
+ /**
+ * Notification the given variables have been removed from the variable
+ * manager.
+ *
+ * @param variables removed variables
+ */
+ public void variablesRemoved(IValueVariable[] variables);
+
+ /**
+ * Notification the given variables have been changed value.
+ *
+ * @param variables changed variables
+ */
+ public void variablesChanged(IValueVariable[] variables);
+
+}
diff --git a/org.eclipse.core.variables/src/org/eclipse/core/variables/VariablesPlugin.java b/org.eclipse.core.variables/src/org/eclipse/core/variables/VariablesPlugin.java
index 1d9dbec32..049764787 100644
--- a/org.eclipse.core.variables/src/org/eclipse/core/variables/VariablesPlugin.java
+++ b/org.eclipse.core.variables/src/org/eclipse/core/variables/VariablesPlugin.java
@@ -11,6 +11,7 @@
package org.eclipse.core.variables;
+import org.eclipse.core.internal.variables.StringVariableManager;
import org.eclipse.core.runtime.IPluginDescriptor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Plugin;
@@ -70,7 +71,26 @@ public class VariablesPlugin extends Plugin {
* @param t throwable to log
*/
public static void log(Throwable t) {
- IStatus status= new Status(IStatus.ERROR, PI_CORE_VARIABLES, INTERNAL_ERROR, "Error logged from Core Variables: ", t); //$NON-NLS-1$
+ log(new Status(IStatus.ERROR, PI_CORE_VARIABLES, INTERNAL_ERROR, "Error logged from Core Variables: ", t)); //$NON-NLS-1$
+ }
+
+ /**
+ * Logs the given message with this plug-in's log and the given
+ * throwable or <code>null</code> if none.
+ * @param message the message to log
+ * @param throwable the exception that occurred or <code>null</code> if none
+ */
+ public static void logMessage(String message, Throwable throwable) {
+ log(new Status(IStatus.ERROR, getUniqueIdentifier(), INTERNAL_ERROR, message, throwable));
+ }
+
+ /**
+ * Logs the specified status with this plug-in's log.
+ *
+ * @param status status to log
+ * @since 2.0
+ */
+ public static void log(IStatus status) {
getDefault().getLog().log(status);
}
@@ -86,4 +106,15 @@ public class VariablesPlugin extends Plugin {
}
return getDefault().getDescriptor().getUniqueIdentifier();
}
+
+ /**
+ * Returns the string variable manager.
+ *
+ * @return the string variable manager
+ * @since 3.0
+ */
+ public IStringVariableManager getStringVariableManager() {
+ return StringVariableManager.getDefault();
+ }
+
}

Back to the top