diff options
author | Luc Bourlier | 2003-10-21 17:44:09 +0000 |
---|---|---|
committer | Luc Bourlier | 2003-10-21 17:44:09 +0000 |
commit | ab911fcde82fd45bcc39ac272c5fbda9a69be5fe (patch) | |
tree | 444a44edec1192562892a855816e7ade4d7dd83b /org.eclipse.core.variables/src | |
parent | 459e7a37e00d381973d431e7b1db2a8051e1dcfd (diff) | |
download | eclipse.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')
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(); + } + } |