Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model')
-rw-r--r--org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ExternalTool.java543
-rw-r--r--org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ExternalToolStorage.java153
-rw-r--r--org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolConstants.java210
-rw-r--r--org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolFilter.java34
-rw-r--r--org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolRunner.java38
-rw-r--r--org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IRunnerContext.java67
-rw-r--r--org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IRunnerLog.java43
-rw-r--r--org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IStorageListener.java50
-rw-r--r--org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ToolUtil.java450
9 files changed, 1588 insertions, 0 deletions
diff --git a/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ExternalTool.java b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ExternalTool.java
new file mode 100644
index 000000000..9ad2ca6aa
--- /dev/null
+++ b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ExternalTool.java
@@ -0,0 +1,543 @@
+package org.eclipse.ui.externaltools.model;
+
+/**********************************************************************
+Copyright (c) 2002 IBM Corp. and others. All rights reserved.
+This file is 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:
+**********************************************************************/
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IActionFilter;
+import org.eclipse.ui.externaltools.internal.model.ExternalToolsPlugin;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+/**
+ * This class represents an external tool that can be run. The tool
+ * can be inside or outside the workspace.
+ * <p>
+ * An external tool consist of a user defined name, the location
+ * of the tool, optional arguments for the tool, and the working
+ * directory.
+ * </p><p>
+ * After the tool has run, part or all of the workspace can be
+ * refreshed to pickup changes made by the tool. This is optional
+ * and does nothing by default
+ * </p><p>
+ * This class is not intended to be extended by clients
+ * </p>
+ */
+public final class ExternalTool implements IAdaptable {
+ private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+ private static final int[] DEFAULT_BUILD_KINDS =
+ {IncrementalProjectBuilder.INCREMENTAL_BUILD,
+ IncrementalProjectBuilder.FULL_BUILD,
+ IncrementalProjectBuilder.AUTO_BUILD};
+
+ private static final ToolWorkbenchAdapter workbenchAdapter = new ToolWorkbenchAdapter();
+ private static final ToolFilterAdapter filterAdapter = new ToolFilterAdapter();
+
+ private String type = EMPTY_STRING;
+ private String name = EMPTY_STRING;
+ private String location = EMPTY_STRING;
+ private String arguments = EMPTY_STRING;
+ private String workDirectory = EMPTY_STRING;
+ private String description = EMPTY_STRING;
+ private String openPerspective = null;
+ private String refreshScope = null;
+ private boolean refreshRecursive = true;
+ private boolean captureOutput = true;
+ private boolean showConsole = true;
+ private boolean runInBackground = true;
+ private boolean promptForArguments = false;
+ private boolean showInMenu = false;
+ private boolean saveDirtyEditors = false;
+ private int[] runForBuildKinds = DEFAULT_BUILD_KINDS;
+ private ArrayList extraAttributes = null;
+
+ /**
+ * Creates a fully initialized external tool.
+ *
+ * @param type the type of external tool.
+ * @param name the name given to the external tool. Must only
+ * contain letters, numbers, hyphens, and spaces.
+ */
+ public ExternalTool(String type, String name) throws CoreException {
+ super();
+
+ if (type != null)
+ this.type = type;
+
+ String errorText = validateToolName(name);
+ if (errorText == null)
+ this.name = name.trim();
+ else
+ throw ExternalToolsPlugin.newError(errorText, null);
+ }
+
+ /**
+ * Validates the specified tool name only includes letters,
+ * numbers, hyphens, and spaces. Must contain at least one
+ * letter or number.
+ *
+ * @param name the proposed name for the external tool
+ * @return a string indicating the invalid format or <code>null</code> if valid.
+ */
+ public static String validateToolName(String name) {
+ IStatus status = ResourcesPlugin.getWorkspace().validateName(name, IResource.FILE);
+ if (status.getCode() != IStatus.OK) {
+ return status.getMessage();
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on IAdaptable.
+ */
+ public Object getAdapter(Class adapter) {
+ if (adapter == IWorkbenchAdapter.class)
+ return workbenchAdapter;
+
+ if (adapter == IActionFilter.class)
+ return filterAdapter;
+
+ return null;
+ }
+
+ /**
+ * Returns the extra attribute value
+ *
+ * @param key the unique attribute name
+ * @return the value of the attribute, or <code>null</code>
+ * if not such attribute name.
+ */
+ public String getExtraAttribute(String key) {
+ if (key == null || key.length() == 0)
+ return null;
+ if (extraAttributes == null)
+ return null;
+
+ for (int i = 0; i < extraAttributes.size(); i++) {
+ Attribute attr = (Attribute)extraAttributes.get(i);
+ if (attr.key.equals(key))
+ return attr.value;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns all the extra attribute keys
+ */
+ public String[] getExtraAttributeKeys() {
+ if (extraAttributes == null)
+ return new String[0];
+
+ String[] results = new String[extraAttributes.size()];
+ for (int i = 0; i < extraAttributes.size(); i++) {
+ Attribute attr = (Attribute)extraAttributes.get(i);
+ results[i] = attr.key;
+ }
+
+ return results;
+ }
+
+ /**
+ * Returns all the extra attribute values
+ */
+ public String[] getExtraAttributeValues() {
+ if (extraAttributes == null)
+ return new String[0];
+
+ String[] results = new String[extraAttributes.size()];
+ for (int i = 0; i < extraAttributes.size(); i++) {
+ Attribute attr = (Attribute)extraAttributes.get(i);
+ results[i] = attr.value;
+ }
+
+ return results;
+ }
+
+ /**
+ * Sets an extra attribute to the tool.
+ *
+ * @param key the unique attribute name
+ * @param value the value for the attribute. If <code>null</code>,
+ * then the existing attribute is removed.
+ */
+ public void setExtraAttribute(String key, String value) {
+ // Exit on invalid key
+ if (key == null || key.length() == 0)
+ return;
+
+ // Init the list but only if not attempting to remove
+ // an extra attribute
+ if (extraAttributes == null) {
+ if (value == null)
+ return;
+ else
+ extraAttributes = new ArrayList(4);
+ }
+
+ // If the extra attribute exist, update it with the
+ // new value, or remove it if the value is null
+ for (int i = 0; i < extraAttributes.size(); i++) {
+ Attribute attr = (Attribute)extraAttributes.get(i);
+ if (attr.key.equals(key)) {
+ if (value == null)
+ extraAttributes.remove(i);
+ else
+ attr.value = value.trim();
+ return;
+ }
+ }
+
+ // Otherwise add the new extra attribute
+ if (value != null)
+ extraAttributes.add(new Attribute(key, value.trim()));
+ }
+
+ /**
+ * Returns the type of external tool.
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Returns the name of the external tool.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the location of the external tool.
+ */
+ public String getLocation() {
+ return location;
+ }
+
+ /**
+ * Returns the arguments for the external tool.
+ */
+ public String getArguments() {
+ return arguments;
+ }
+
+ /**
+ * Returns the working directory to run the external tool in.
+ */
+ public String getWorkingDirectory() {
+ return workDirectory;
+ }
+
+ /**
+ * Returns whether the refresh will be recursive.
+ */
+ public boolean getRefreshRecursive() {
+ return refreshRecursive;
+ }
+
+ /**
+ * Returns the scope of resources to refresh after
+ * the external tool is run, or <code>null</code> if
+ * not specified. The value is in an variable
+ * format.
+ */
+ public String getRefreshScope() {
+ return refreshScope;
+ }
+
+ /**
+ * Returns whether to capture output messages from the
+ * running tool.
+ */
+ public boolean getCaptureOutput() {
+ return captureOutput;
+ }
+
+ /**
+ * Returns whether to show the log console when
+ * the tool is run.
+ */
+ public boolean getShowConsole() {
+ return showConsole;
+ }
+
+ /**
+ * Returns whether to run the external tool in the
+ * background so as not to block the UI.
+ */
+ public boolean getRunInBackground() {
+ return runInBackground;
+ }
+
+ /**
+ * Returns whether to prompt for arguments before
+ * the tool is run.
+ */
+ public boolean getPromptForArguments() {
+ return promptForArguments;
+ }
+
+ /**
+ * Returns whether to show this tool in the
+ * Run > External Tools menu.
+ */
+ public boolean getShowInMenu() {
+ return showInMenu;
+ }
+
+ /**
+ * Returns whether to save all dirty editors before
+ * running this tool.
+ */
+ public boolean getSaveDirtyEditors() {
+ return saveDirtyEditors;
+ }
+
+ /**
+ * Returns the perspective ID to open when this
+ * tool is run, or <code>null</code> if not specified.
+ */
+ public String getOpenPerspective() {
+ return openPerspective;
+ }
+
+ /**
+ * Returns a description of this external tool
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Returns the list of build kinds that this
+ * tool wants to run when used as a builder.
+ * The list of valid build kinds is defined
+ * on <code>IncrementalProjectBuilder</code>.
+ */
+ public int[] getRunForBuildKinds() {
+ return runForBuildKinds;
+ }
+
+ /**
+ * Sets the name of the external tool.
+ */
+ public void rename(String name) throws CoreException {
+ IStatus status= ExternalToolsPlugin.getDefault().getToolRegistry(null).renameTool(this, name);
+ if (!status.isOK()) {
+ // Throw an exception
+ ExternalToolsPlugin.newError(MessageFormat.format("An exception occurred attempting to rename the tool: ", new Object[] {this.getName()}), null);
+ }
+ if (name == null) {
+ this.name = EMPTY_STRING;
+ } else {
+ this.name = name;
+ }
+ }
+
+ /**
+ * Sets the location of the external tool.
+ */
+ public void setLocation(String location) {
+ if (location == null)
+ this.location = EMPTY_STRING;
+ else
+ this.location = location.trim();
+ }
+
+ /**
+ * Sets the arguments for the external tool.
+ */
+ public void setArguments(String arguments) {
+ if (arguments == null)
+ this.arguments = EMPTY_STRING;
+ else
+ this.arguments = arguments.trim();
+ }
+
+ /**
+ * Sets the working directory to run the external tool in.
+ */
+ public void setWorkingDirectory(String workDirectory) {
+ if (workDirectory == null)
+ this.workDirectory = EMPTY_STRING;
+ else
+ this.workDirectory = workDirectory.trim();
+ }
+
+ /**
+ * Sets whether the refresh will be recursive.
+ */
+ public void setRefreshRecursive(boolean refreshRecursive) {
+ this.refreshRecursive = refreshRecursive;
+ }
+
+ /**
+ * Sets the scope of resources to refresh after
+ * the external tool is run, or <code>null</code>
+ * if none. The value is in a variable format.
+ */
+ public void setRefreshScope(String refreshScope) {
+ if (refreshScope == null)
+ this.refreshScope = null;
+ else {
+ this.refreshScope = refreshScope.trim();
+ if (this.refreshScope.length() == 0)
+ this.refreshScope = null;
+ }
+ }
+
+ /**
+ * Sets whether to capture output messages from the
+ * running tool.
+ */
+ public void setCaptureOutput(boolean captureOutput) {
+ this.captureOutput = captureOutput;
+ }
+
+ /**
+ * Sets whether to show the log console when
+ * the tool is run.
+ */
+ public void setShowConsole(boolean showConsole) {
+ this.showConsole = showConsole;
+ }
+
+ /**
+ * Sets whether to run the external tool in the
+ * background so as not to block the UI.
+ */
+ public void setRunInBackground(boolean runInBackground) {
+ this.runInBackground = runInBackground;
+ }
+
+ /**
+ * Sets whether to prompt for arguments before
+ * the tool is run.
+ */
+ public void setPromptForArguments(boolean promptForArguments) {
+ this.promptForArguments = promptForArguments;
+ }
+
+ /**
+ * Sets whether to show this tool in the
+ * Run > External Tools menu.
+ */
+ public void setShowInMenu(boolean showInMenu) {
+ this.showInMenu = showInMenu;
+ }
+
+ /**
+ * Sets whether all dirty editors will be saved
+ * before running this tool.
+ */
+ public void setSaveDirtyEditors(boolean saveDirtyEditors) {
+ this.saveDirtyEditors = saveDirtyEditors;
+ }
+
+ /**
+ * Sets the perspective ID to open when this
+ * tool is run, or <code>null</code> if not specified.
+ */
+ public void setOpenPerspective(String openPerspective) {
+ if (openPerspective == null)
+ this.openPerspective = null;
+ else {
+ this.openPerspective = openPerspective.trim();
+ if (this.openPerspective.length() == 0)
+ this.openPerspective = null;
+ }
+ }
+
+ /**
+ * Sets a description of this external tool
+ */
+ public void setDescription(String description) {
+ if (description == null)
+ this.description = EMPTY_STRING;
+ else
+ this.description = description.trim();
+ }
+
+ /**
+ * Sets the list of build kinds that this
+ * tool wants to run when used as a builder.
+ * The list of valid build kinds is defined
+ * on <code>IncrementalProjectBuilder</code>.
+ */
+ public void setRunForBuildKinds(int[] kinds) {
+ if (kinds == null)
+ this.runForBuildKinds = DEFAULT_BUILD_KINDS;
+ else
+ this.runForBuildKinds = kinds;
+ }
+
+ /**
+ * Internal representation of extra attributes.
+ */
+ private static class Attribute {
+ public String key;
+ public String value;
+
+ public Attribute(String key, String value) {
+ super();
+ this.key = key;
+ this.value = value;
+ }
+ }
+
+ /**
+ * Internal workbench adapter implementation.
+ */
+ private static class ToolWorkbenchAdapter implements IWorkbenchAdapter {
+ public Object[] getChildren(Object o) {
+ return new Object[0];
+ }
+
+ public ImageDescriptor getImageDescriptor(Object o) {
+ String type = ((ExternalTool)o).getType();
+ return ExternalToolsPlugin.getDefault().getTypeRegistry().getToolTypeImageDescriptor(type);
+ }
+
+ public String getLabel(Object o) {
+ return ((ExternalTool)o).getName();
+ }
+
+ public Object getParent(Object o) {
+ String type = ((ExternalTool)o).getType();
+ return ExternalToolsPlugin.getDefault().getTypeRegistry().getToolType(type);
+ }
+ }
+
+ /**
+ * Internal action filter adapter implementation.
+ */
+ private static class ToolFilterAdapter implements IExternalToolFilter {
+ public boolean testAttribute(Object target, String name, String value) {
+ ExternalTool tool = (ExternalTool) target;
+
+ if (IExternalToolFilter.TYPE.equals(name))
+ return tool.getType().equals(value);
+
+ String attrValue = tool.getExtraAttribute(name);
+ if (attrValue != null)
+ return attrValue.equals(value);
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ExternalToolStorage.java b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ExternalToolStorage.java
new file mode 100644
index 000000000..a22e2278c
--- /dev/null
+++ b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ExternalToolStorage.java
@@ -0,0 +1,153 @@
+package org.eclipse.ui.externaltools.model;
+
+/**********************************************************************
+Copyright (c) 2002 IBM Corp. and others. All rights reserved.
+This file is 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:
+**********************************************************************/
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.externaltools.internal.model.ExternalToolsPlugin;
+import org.eclipse.ui.externaltools.internal.model.ToolMessages;
+import org.eclipse.ui.externaltools.internal.registry.ExternalToolRegistry;
+
+/**
+ * Provides utility methods to manager the storage
+ * of external tools.
+ */
+public final class ExternalToolStorage {
+ private static ListenerList listeners = new ListenerList();
+
+ /**
+ * Allows no instance to be created
+ */
+ private ExternalToolStorage() {
+ super();
+ }
+
+ /**
+ * Adds a tool storage listener.
+ *
+ * @param listener the tool storage listener to add
+ */
+ public static void addStorageListener(IStorageListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Deletes the external tool from storage and from
+ * the tools registry.
+ *
+ * @param tool the external tool to be deleted
+ * @param shell the shell to parent any error dialogs,
+ * of <code>null</code> to operate quietly.
+ */
+ public static void deleteTool(ExternalTool tool, Shell shell) {
+ if (tool == null)
+ return;
+
+ ExternalToolRegistry registry = ExternalToolsPlugin.getDefault().getToolRegistry(shell);
+ IStatus results = registry.deleteTool(tool);
+
+ if (handleResults(results, shell, "ExternalToolStorage.deleteErrorTitle", "ExternalToolStorage.deleteErrorMessage")) //$NON-NLS-2$//$NON-NLS-1$
+ return;
+
+ Object list[] = listeners.getListeners();
+ for (int i = 0; i < list.length; i++) {
+ ((IStorageListener)list[i]).toolDeleted(tool);
+ }
+ }
+
+ /**
+ * Handles the display of any error message if the
+ * results were not ok.
+ *
+ * @return <code>true</code> if an error was displayed, <code>false</code> otherwise
+ */
+ private static boolean handleResults(final IStatus results, final Shell shell, final String titleKey, final String msgKey) {
+ if (!results.isOK() && shell != null && !shell.isDisposed()) {
+ shell.getDisplay().syncExec(new Runnable() {
+ public void run() {
+ String title = ToolMessages.getString(titleKey);
+ String msg = ToolMessages.getString(msgKey);
+ ErrorDialog.openError(shell, title, msg, results);
+ }
+ });
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Reloads the tools from storage into the registry.
+ *
+ * @param shell the shell to parent any error dialogs,
+ * of <code>null</code> to operate quietly.
+ */
+ public static void refreshTools(final Shell shell) {
+ final IStatus[] results = new IStatus[1];
+
+ BusyIndicator.showWhile(shell.getDisplay(), new Runnable() {
+ public void run() {
+ results[0] = ExternalToolsPlugin.getDefault().getToolRegistry(shell).reloadTools();
+ }
+ });
+
+ if (handleResults(results[0], shell, "ExternalToolStorage.reloadErrorTitle", "ExternalToolStorage.reloadErrorMessage")) //$NON-NLS-2$//$NON-NLS-1$
+ return;
+
+ Object list[] = listeners.getListeners();
+ for (int i = 0; i < list.length; i++) {
+ ((IStorageListener)list[i]).toolsRefreshed();
+ }
+ }
+
+ /**
+ * Removes a tool storage listener.
+ *
+ * @param listener the tool storage listener to remove
+ */
+ public static void removeStorageListener(IStorageListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Saves the external tool to storage and to
+ * the tools registry.
+ *
+ * @param tool the external tool to be saved
+ * @param shell the shell to parent any error dialogs,
+ * of <code>null</code> to operate quietly.
+ * @return <code>true</code> if save successful, <code>false</code> otherwise.
+ */
+ public static boolean saveTool(ExternalTool tool, Shell shell) {
+ if (tool == null)
+ return false;
+
+ ExternalToolRegistry registry = ExternalToolsPlugin.getDefault().getToolRegistry(shell);
+ boolean exists = registry.hasToolNamed(tool.getName());
+
+ IStatus results = registry.saveTool(tool);
+ if (handleResults(results, shell, "ExternalToolStorage.saveErrorTitle", "ExternalToolStorage.saveErrorMessage")) //$NON-NLS-2$//$NON-NLS-1$
+ return false;
+
+ Object list[] = listeners.getListeners();
+ for (int i = 0; i < list.length; i++) {
+ if (exists)
+ ((IStorageListener)list[i]).toolModified(tool);
+ else
+ ((IStorageListener)list[i]).toolCreated(tool);
+ }
+
+ return true;
+ }
+}
diff --git a/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolConstants.java b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolConstants.java
new file mode 100644
index 000000000..8469d3a80
--- /dev/null
+++ b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolConstants.java
@@ -0,0 +1,210 @@
+package org.eclipse.ui.externaltools.model;
+
+/**********************************************************************
+Copyright (c) 2002 IBM Corp. and others. All rights reserved.
+This file is 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:
+**********************************************************************/
+
+/**
+ * Defines the constants available for client use.
+ * <p>
+ * This interface is not intended to be extended or implemented by clients.
+ * </p>
+ */
+public interface IExternalToolConstants {
+ // ------- Extensions -------
+ /**
+ * Plugin identifier for external tools (value <code>org.eclipse.ui.externaltools</code>).
+ */
+ public static final String PLUGIN_ID = "org.eclipse.ui.externaltools"; //$NON-NLS-1$;
+
+ /**
+ * Extension point to declare types of external tools
+ * (value <code>toolTypes</code>).
+ */
+ public static final String PL_TOOL_TYPES = "toolTypes"; //$NON-NLS-1$
+
+ /**
+ * Extension point to declare argument variables
+ * (value <code>argumentVariables</code>).
+ */
+ public static final String PL_ARGUMENT_VARIABLES = "argumentVariables"; //$NON-NLS-1$
+
+ /**
+ * Extension point to declare file variables
+ * (value <code>fileVariables</code>).
+ */
+ public static final String PL_FILE_VARIABLES = "fileVariables"; //$NON-NLS-1$
+
+ /**
+ * Extension point to declare directory variables
+ * (value <code>directoryVariables</code>).
+ */
+ public static final String PL_DIRECTORY_VARIABLES = "directoryVariables"; //$NON-NLS-1$
+
+ /**
+ * Extension point to declare refresh scope variables
+ * (value <code>refreshVariables</code>).
+ */
+ public static final String PL_REFRESH_VARIABLES = "refreshVariables"; //$NON-NLS-1$
+
+
+ // ------- Views -------
+ /**
+ * External tool view identifier (value <code>org.eclipse.ui.externaltools.ExternalToolView</code>).
+ */
+ public static final String VIEW_ID = PLUGIN_ID + ".ExternalToolView"; //$NON-NLS-1$
+
+ /**
+ * Log Console view identifier (value <code>org.eclipse.ui.externaltools.LogConsoleView</code>).
+ */
+ public static final String LOG_CONSOLE_VIEW_ID = PLUGIN_ID + ".LogConsoleView"; //$NON-NLS-1$
+
+
+ // ------- Tool Types -------
+ /**
+ * External tool type for programs such as executables, batch files,
+ * shell scripts, etc (value <code>programType</code>).
+ */
+ public static final String TOOL_TYPE_PROGRAM = "programType"; //$NON-NLS-1$;
+
+ /**
+ * External tool type for Ant build files (value <code>antBuildType</code>).
+ */
+ public static final String TOOL_TYPE_ANT_BUILD = "antBuildType"; //$NON-NLS-1$;
+
+
+ // ------- Variables -------
+ /**
+ * Variable that expands to the workspace root object (value <code>workspace</code>).
+ */
+ public static final String VAR_WORKSPACE = "workspace"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the absolute path on the system's hard drive
+ * to the workspace directory (value <code>workspace_loc</code>).
+ */
+ public static final String VAR_WORKSPACE_LOC = "workspace_loc"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the project resource (value <code>project</code>).
+ */
+ public static final String VAR_PROJECT = "project"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the absolute path on the system's hard drive
+ * to a project's directory (value <code>project_loc</code>).
+ */
+ public static final String VAR_PROJECT_LOC = "project_loc"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the full path, relative to the workspace root,
+ * of a project (value <code>project_path</code>).
+ */
+ public static final String VAR_PROJECT_PATH = "project_path"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the name of a project (value <code>project_name</code>).
+ */
+ public static final String VAR_PROJECT_NAME = "project_name"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to a resource (value <code>resource</code>).
+ */
+ public static final String VAR_RESOURCE = "resource"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the absolute path on the system's hard drive
+ * to a resource's location (value <code>resource_loc</code>).
+ */
+ public static final String VAR_RESOURCE_LOC = "resource_loc"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the full path, relative to the workspace root,
+ * of a resource (value <code>resource_path</code>).
+ */
+ public static final String VAR_RESOURCE_PATH = "resource_path"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the name of a resource (value <code>resource_name</code>).
+ */
+ public static final String VAR_RESOURCE_NAME = "resource_name"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the container resource (value <code>container</code>).
+ */
+ public static final String VAR_CONTAINER = "container"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the absolute path on the system's hard drive
+ * to a resource's containing directory (value <code>container_loc</code>).
+ */
+ public static final String VAR_CONTAINER_LOC = "container_loc"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the full path, relative to the workspace root,
+ * of a resource's parent (value <code>container_path</code>).
+ */
+ public static final String VAR_CONTAINER_PATH = "container_path"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the name of a resource's parent (value <code>container_name</code>).
+ */
+ public static final String VAR_CONTAINER_NAME = "container_name"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the type of build (value <code>build_type</code>). See
+ * <code>BUILD_TYPE_*</code> constants for possible values.
+ */
+ public static final String VAR_BUILD_TYPE = "build_type"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the working set object (value <code>working_set</code>).
+ */
+ public static final String VAR_WORKING_SET = "working_set"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the current editor cursor column (value <code>editor_cur_col</code>).
+ */
+ public static final String VAR_EDITOR_CUR_COL = "editor_cur_col"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the current editor cursor line (value <code>editor_cur_line</code>).
+ */
+ public static final String VAR_EDITOR_CUR_LINE = "editor_cur_line"; //$NON-NLS-1$
+
+ /**
+ * Variable that expands to the current editor selected text (value <code>editor_sel_text</code>).
+ */
+ public static final String VAR_EDITOR_SEL_TEXT = "editor_sel_text"; //$NON-NLS-1$
+
+
+ // ------- Build Types -------
+ /**
+ * Build type indicating an incremental project build request for
+ * the external tool running as a builder (value <code>incremental</code>).
+ */
+ public static final String BUILD_TYPE_INCREMENTAL = "incremental"; //$NON-NLS-1$
+
+ /**
+ * Build type indicating a full project build request for
+ * the external tool running as a builder (value <code>full</code>).
+ */
+ public static final String BUILD_TYPE_FULL = "full"; //$NON-NLS-1$
+
+ /**
+ * Build type indicating an automatic project build request for
+ * the external tool running as a builder (value <code>incremental</code>).
+ */
+ public static final String BUILD_TYPE_AUTO = "auto"; //$NON-NLS-1$
+
+ /**
+ * Build type indicating an no project build request for
+ * the external tool running as a builder (value <code>none</code>).
+ */
+ public static final String BUILD_TYPE_NONE = "none"; //$NON-NLS-1$
+}
diff --git a/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolFilter.java b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolFilter.java
new file mode 100644
index 000000000..5ec00651f
--- /dev/null
+++ b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolFilter.java
@@ -0,0 +1,34 @@
+package org.eclipse.ui.externaltools.model;
+
+/**********************************************************************
+Copyright (c) 2002 IBM Corp. and others. All rights reserved.
+This file is 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:
+**********************************************************************/
+
+import org.eclipse.ui.IActionFilter;
+
+/**
+ * Describes the public attributes for an external tool and the acceptables values
+ * each may have.
+ * <p>
+ * Beside the attributes defined below, all of the extra attribute keys are
+ * also available. Only use extra attribute keys which have been made public
+ * by clients.
+ * </p><p>
+ * This interface is not to be extended or implemented by clients
+ * </p>
+ *
+ * @see IActionFilter
+ */
+public interface IExternalToolFilter extends IActionFilter {
+ /**
+ * An attribute indicating the external tool type (value <code>"type"</code>).
+ * The attribute value should match one of the external tool types defined in
+ * the external tool's type extension point.
+ */
+ public static final String TYPE = "type"; //$NON-NLS-1$
+}
diff --git a/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolRunner.java b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolRunner.java
new file mode 100644
index 000000000..5014e0f4d
--- /dev/null
+++ b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IExternalToolRunner.java
@@ -0,0 +1,38 @@
+package org.eclipse.ui.externaltools.model;
+
+/**********************************************************************
+Copyright (c) 2002 IBM Corp. and others. All rights reserved.
+This file is 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:
+**********************************************************************/
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.MultiStatus;
+
+/**
+ * The implementation of this interface is responsible for running
+ * an external tool within the specified context.
+ * <p>
+ * Clients using the extension point to define a new external
+ * tool type must provide an implementation of this interface.
+ * </p><p>
+ * The implementation of this interface will be treated like
+ * a singleton. That is, only one instance will be created
+ * per tool type.
+ * </p><p>
+ * This interface is not intended to be extended by clients.
+ * </p>
+ */
+public interface IExternalToolRunner {
+ /**
+ * Runs an external tool using the specified context.
+ *
+ * @param monitor the monitor to report progress or cancellation to
+ * @param runnerContext the context representing the tool to run
+ * @param status a multi status to report any problems while running tool
+ */
+ public void run(IProgressMonitor monitor, IRunnerContext runnerContext, MultiStatus status);
+}
diff --git a/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IRunnerContext.java b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IRunnerContext.java
new file mode 100644
index 000000000..1b12e298c
--- /dev/null
+++ b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IRunnerContext.java
@@ -0,0 +1,67 @@
+package org.eclipse.ui.externaltools.model;
+
+/**********************************************************************
+Copyright (c) 2002 IBM Corp. and others. All rights reserved.
+This file is 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:
+**********************************************************************/
+
+/**
+ * Represents the context of the external tool to run. An implementation
+ * of this interface is provided to the <code>IExternalToolRunner</code>.
+ * <p>
+ * This interface is not be extended nor implemented by clients.
+ * </p>
+ */
+public interface IRunnerContext {
+ /**
+ * Returns whether the external tool runner should capture
+ * output messages from the running tool and log these
+ * messages.
+ */
+ public boolean getCaptureOutput();
+
+ /**
+ * Returns the arguments for the external tool. All
+ * variables embedded in the arguments have been fully
+ * expanded.
+ */
+ public String[] getExpandedArguments();
+
+ /**
+ * Returns the path where the external tool is located. All
+ * variables embedded in the path have been fully
+ * expanded.
+ */
+ public String getExpandedLocation();
+
+ /**
+ * Returns the working directory to run the external tool in.
+ * All variables embedded in the path have been fully
+ * expanded.
+ */
+ public String getExpandedWorkingDirectory();
+
+ /**
+ * Returns the extra attribute value of the external tool.
+ *
+ * @param key the unique attribute name
+ * @return the value of the attribute, or <code>null</code>
+ * if not such attribute name.
+ */
+ public String getExtraAttribute(String key);
+
+ /**
+ * Returns the log the runner can used to log
+ * messages captured from the running tool's output.
+ */
+ public IRunnerLog getLog();
+
+ /**
+ * Returns the name of the external tool.
+ */
+ public String getName();
+}
diff --git a/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IRunnerLog.java b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IRunnerLog.java
new file mode 100644
index 000000000..4245d2d66
--- /dev/null
+++ b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IRunnerLog.java
@@ -0,0 +1,43 @@
+package org.eclipse.ui.externaltools.model;
+
+/**********************************************************************
+Copyright (c) 2002 IBM Corp. and others. All rights reserved.
+This file is 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:
+**********************************************************************/
+
+/**
+ * Provides an API for <code>IExternalToolRunner</code> implementors
+ * to log messages captured from the running tool's output.
+ * <p>
+ * This interface is not be extended nor implemented by clients.
+ * </p>
+ */
+public interface IRunnerLog {
+ public static final int LEVEL_ERROR = 0;
+ public static final int LEVEL_WARNING = 10;
+ public static final int LEVEL_INFO = 20;
+ public static final int LEVEL_VERBOSE = 30;
+ public static final int LEVEL_DEBUG = 40;
+
+ /**
+ * Places the specified message text into the log. Ignored
+ * if the specified message level is higher than the
+ * current filter level.
+ *
+ * @param message the text to add to the log
+ * @param level the message priority
+ */
+ public void append(String message, int level);
+
+ /**
+ * Returns the current level used for filtering
+ * messages. Any calls to <code>append</code> with
+ * a level greater than this filter value will be
+ * ignored.
+ */
+ public int getFilterLevel();
+}
diff --git a/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IStorageListener.java b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IStorageListener.java
new file mode 100644
index 000000000..84c502b76
--- /dev/null
+++ b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/IStorageListener.java
@@ -0,0 +1,50 @@
+package org.eclipse.ui.externaltools.model;
+
+/**********************************************************************
+Copyright (c) 2002 IBM Corp. and others. All rights reserved.
+This file is 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:
+**********************************************************************/
+
+/**
+ * Defines the changes within the external tool storage that
+ * a listeners can be notified of.
+ * <p>
+ * This interface is not to be extended by clients, but can be
+ * implemented by clients.
+ * </p>
+ */
+public interface IStorageListener {
+ /**
+ * Notifies this listener that an external tool has
+ * been removed from the registry and storage.
+ *
+ * @param tool the external tool that was removed
+ */
+ public void toolDeleted(ExternalTool tool);
+
+ /**
+ * Notifies this listener that a new external tool has
+ * been added to the registry and storage.
+ *
+ * @param tool the external tool that was created
+ */
+ public void toolCreated(ExternalTool tool);
+
+ /**
+ * Notifies this listener that an existing external tool
+ * in the registry has been modified and saved to storage.
+ *
+ * @param tool the external tool that was modified
+ */
+ public void toolModified(ExternalTool tool);
+
+ /**
+ * Notifies this listener that the entire external tool
+ * registry was refreshed from storage.
+ */
+ public void toolsRefreshed();
+}
diff --git a/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ToolUtil.java b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ToolUtil.java
new file mode 100644
index 000000000..fbb883868
--- /dev/null
+++ b/org.eclipse.ui.externaltools/External Tools Base/org/eclipse/ui/externaltools/model/ToolUtil.java
@@ -0,0 +1,450 @@
+package org.eclipse.ui.externaltools.model;
+
+/**********************************************************************
+Copyright (c) 2002 IBM Corp. and others. All rights reserved.
+This file is 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:
+**********************************************************************/
+
+import java.util.ArrayList;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.ui.externaltools.internal.model.ExternalToolsPlugin;
+import org.eclipse.ui.externaltools.internal.model.ToolMessages;
+import org.eclipse.ui.externaltools.internal.registry.ArgumentVariable;
+import org.eclipse.ui.externaltools.internal.registry.ArgumentVariableRegistry;
+import org.eclipse.ui.externaltools.internal.registry.PathLocationVariable;
+import org.eclipse.ui.externaltools.internal.registry.PathLocationVariableRegistry;
+import org.eclipse.ui.externaltools.variable.ExpandVariableContext;
+
+/**
+ * General utility class dealing with external tools
+ */
+public final class ToolUtil {
+ /**
+ * Argument parsing constants
+ */
+ private static final char ARG_DELIMITER = ' '; //$NON-NLS-1$
+ private static final char ARG_DBL_QUOTE = '"'; //$NON-NLS-1$
+
+ /**
+ * Variable tag indentifiers
+ */
+ private static final char VAR_TAG_START_CHAR1 = '$'; //$NON-NLS-1$
+ private static final char VAR_TAG_START_CHAR2 = '{'; //$NON-NLS-1$
+ private static final char VAR_TAG_END_CHAR1 = '}'; //$NON-NLS-1$
+ private static final String VAR_TAG_START = "${"; //$NON-NLS-1$
+ private static final String VAR_TAG_END = "}"; //$NON-NLS-1$
+ private static final String VAR_TAG_SEP = ":"; //$NON-NLS-1$
+
+ /**
+ * No instances allowed
+ */
+ private ToolUtil() {
+ super();
+ }
+
+ /**
+ * Builds a variable tag that will be auto-expanded before
+ * the tool is run.
+ *
+ * @param varName the name of a known variable (one of the VAR_* constants for instance)
+ * @param varArgument an optional argument for the variable, <code>null</code> if none
+ */
+ public static String buildVariableTag(String varName, String varArgument) {
+ StringBuffer buf = new StringBuffer();
+ buildVariableTag(varName,varArgument, buf);
+ return buf.toString();
+ }
+
+ /**
+ * Builds a variable tag that will be auto-expanded before
+ * the tool is run.
+ *
+ * @param varName the name of a known variable (one of the VAR_* constants for instance)
+ * @param varArgument an optional argument for the variable, <code>null</code> if none
+ * @param buffer the buffer to write the constructed variable tag
+ */
+ public static void buildVariableTag(String varName, String varArgument, StringBuffer buffer) {
+ buffer.append(VAR_TAG_START);
+ buffer.append(varName);
+ if (varArgument != null && varArgument.length() > 0) {
+ buffer.append(VAR_TAG_SEP);
+ buffer.append(varArgument);
+ }
+ buffer.append(VAR_TAG_END);
+ }
+
+ /**
+ * Expands all the variables found in an individual
+ * argument text.
+ *
+ * @param argument one of the argument text in the list of arguments
+ * @param context the context to use for expanding variables
+ * @param status multi status to report any problems expanding variables
+ * @return the argument text with all variables expanded, or <code>null</code> if not possible
+ */
+ public static String expandArgument(String argument, ExpandVariableContext context, MultiStatus status) {
+ StringBuffer buffer = new StringBuffer();
+
+ int start = 0;
+ while (true) {
+ VariableDefinition varDef = extractVariableTag(argument, start);
+
+ // No more variables found...
+ if (varDef.start == -1) {
+ if (start == 0)
+ buffer.append(argument);
+ else
+ buffer.append(argument.substring(start));
+ break;
+ }
+
+ // Invalid variable format
+ if (varDef.end == -1 || varDef.name == null || varDef.name.length() == 0) {
+ String msg = ToolMessages.getString("ToolUtil.argumentVarFormatWrong"); //$NON-NLS-1$
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+
+ // Copy text between start and variable.
+ if (varDef.start > start)
+ buffer.append(argument.substring(start, varDef.start));
+ start = varDef.end;
+
+ // Lookup the variable if it exist
+ ArgumentVariableRegistry registry;
+ registry = ExternalToolsPlugin.getDefault().getArgumentVariableRegistry();
+ ArgumentVariable variable = registry.getArgumentVariable(varDef.name);
+ if (variable == null) {
+ String msg = ToolMessages.format("ToolUtil.argumentVarMissing", new Object[] {varDef.name}); //$NON-NLS-1$
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+
+ // Expand the variable as text if possible
+ String text = variable.getExpander().getText(varDef.name, varDef.argument, context);
+ if (text == null) {
+ String msg = ToolMessages.format("ToolUtil.argumentVarExpandFailed", new Object[] {varDef.name}); //$NON-NLS-1$
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+ buffer.append(text);
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Returns a list of individual arguments where all
+ * variables have been expanded.
+ *
+ * @param arguments the arguments with leading and trailing
+ * spaces already removed.
+ * @param context the context used to expand the variable(s)
+ * @param status multi status to report any problems expanding variables
+ * @return the list of individual arguments where some elements in the
+ * list maybe <code>null</code> if problems expanding variable(s).
+ */
+ public static String[] expandArguments(String arguments, ExpandVariableContext context, MultiStatus status) {
+ if (arguments == null || arguments.length() == 0)
+ return new String[0];
+
+ String[] argList = parseArgumentsIntoList(arguments);
+ for (int i = 0; i < argList.length; i++)
+ argList[i] = expandArgument(argList[i], context, status);
+
+ return argList;
+ }
+
+ /**
+ * Returns the expanded directory location if represented by a
+ * directory variable. Otherwise, the directory location given is
+ * return unless an unknown variable was detected.
+ *
+ * @param dirLocation a directory location either as a path or a variable
+ * with leading and trailing spaces already removed.
+ * @param context the context used to expand the variable
+ * @param status multi status to report any problems expanding variables
+ * @return the directory location as a string or <code>null</code> if not possible
+ */
+ public static String expandDirectoryLocation(String dirLocation, ExpandVariableContext context, MultiStatus status) {
+ if (dirLocation == null || dirLocation.length() == 0)
+ return ""; //$NON-NLS-1$
+
+ VariableDefinition varDef = extractVariableTag(dirLocation, 0);
+ // Return if no variable found
+ if (varDef.start < 0)
+ return dirLocation;
+
+ // Disallow text before/after variable
+ if (varDef.start != 0 || (varDef.end < dirLocation.length() && varDef.end != -1)) {
+ String msg = ToolMessages.getString("ToolUtil.dirLocVarBetweenText"); //$NON-NLS-1$
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+
+ // Invalid variable format
+ if (varDef.name == null || varDef.name.length() == 0 || varDef.end == -1) {
+ String msg = ToolMessages.getString("ToolUtil.dirLocVarFormatWrong"); //$NON-NLS-1$
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+
+ // Lookup the variable if it exist
+ PathLocationVariableRegistry registry;
+ registry = ExternalToolsPlugin.getDefault().getDirectoryLocationVariableRegistry();
+ PathLocationVariable variable = registry.getPathLocationVariable(varDef.name);
+ if (variable == null) {
+ String msg = ToolMessages.format("ToolUtil.dirLocVarMissing", new Object[] {varDef.name}); //$NON-NLS-1$
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+
+ // Expand the variable into a IPath if possible
+ IPath path = variable.getExpander().getPath(varDef.name, varDef.argument, context);
+ if (path == null) {
+ String msg = ToolMessages.format("ToolUtil.dirLocVarExpandFailed", new Object[] {varDef.name}); //$NON-NLS-1$
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+
+ return path.toOSString();
+ }
+
+ /**
+ * Returns the expanded file location if represented by a
+ * file variable. Otherwise, the file location given is
+ * return unless an unknown variable was detected.
+ *
+ * @param fileLocation a file location either as a path or a variable
+ * with leading and trailing spaces already removed.
+ * @param context the context used to expand the variable
+ * @param status multi status to report any problems expanding variables
+ * @return the file location as a string or <code>null</code> if not possible
+ */
+ public static String expandFileLocation(String fileLocation, ExpandVariableContext context, MultiStatus status) {
+ if (fileLocation == null || fileLocation.length() == 0)
+ return ""; //$NON-NLS-1$
+
+ VariableDefinition varDef = extractVariableTag(fileLocation, 0);
+ // Return if no variable found
+ if (varDef.start < 0)
+ return fileLocation;
+
+ // Disallow text before/after variable
+ if (varDef.start != 0 || (varDef.end < fileLocation.length() && varDef.end != -1)) {
+ String msg = ToolMessages.getString("ToolUtil.fileLocVarBetweenText"); //$NON-NLS-1$
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+
+ // Invalid variable format
+ if (varDef.name == null || varDef.name.length() == 0 || varDef.end == -1) {
+ String msg = ToolMessages.getString("ToolUtil.fileLocVarFormatWrong"); //$NON-NLS-1$
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+
+ // Lookup the variable if it exist
+ PathLocationVariableRegistry registry;
+ registry = ExternalToolsPlugin.getDefault().getFileLocationVariableRegistry();
+ PathLocationVariable variable = registry.getPathLocationVariable(varDef.name);
+ if (variable == null) {
+ String msg = ToolMessages.format("ToolUtil.fileLocVarMissing", new Object[] {varDef.name}); //$NON-NLS-1$
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+
+ // Expand the variable into a IPath if possible
+ IPath path = variable.getExpander().getPath(varDef.name, varDef.argument, context);
+ if (path == null) {
+ String msg = ToolMessages.format("The variable {0} with argument {1} could not be expanded to a valid path.", new Object[] {varDef.name, varDef.argument});
+ status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
+ return null;
+ }
+
+ return path.toString();
+ }
+
+ /**
+ * Extracts from the source text the variable tag's name
+ * and argument.
+ *
+ * @param text the source text to parse for a variable tag
+ * @param start the index in the string to start the search
+ * @return the variable definition
+ */
+ public static VariableDefinition extractVariableTag(String text, int start) {
+ VariableDefinition varDef = new VariableDefinition();
+
+ varDef.start = text.indexOf(VAR_TAG_START, start);
+ if (varDef.start < 0)
+ return varDef;
+ start = varDef.start + VAR_TAG_START.length();
+
+ int end = text.indexOf(VAR_TAG_END, start);
+ if (end < 0)
+ return varDef;
+ varDef.end = end + VAR_TAG_END.length();
+ if (end == start)
+ return varDef;
+
+ int mid = text.indexOf(VAR_TAG_SEP, start);
+ if (mid < 0 || mid > end) {
+ varDef.name = text.substring(start, end);
+ } else {
+ if (mid > start)
+ varDef.name = text.substring(start, mid);
+ mid = mid + VAR_TAG_SEP.length();
+ if (mid < end)
+ varDef.argument = text.substring(mid, end);
+ }
+
+ return varDef;
+ }
+
+ /**
+ * Parses the argument text into an array of individual
+ * arguments using the space character as the delimiter.
+ * An individual argument containing spaces must have a
+ * double quote (") at the start and end. Two double
+ * quotes together is taken to mean an embedded double
+ * quote in the argument text. Variables are treated as
+ * a single unit and therefore spaces and double quotes
+ * inside a variable are copied as is and not parsed.
+ *
+ * @param arguments the arguments as one string
+ * @return the array of arguments
+ */
+ public static String[] parseArgumentsIntoList(String arguments) {
+ if (arguments == null || arguments.length() == 0)
+ return new String[0];
+
+ ArrayList list = new ArrayList(10);
+ boolean inQuotes = false;
+ boolean inVar = false;
+ int start = 0;
+ int end = arguments.length();
+ StringBuffer buffer = new StringBuffer(end);
+
+ while (start < end) {
+ char ch = arguments.charAt(start);
+ start++;
+
+ switch (ch) {
+ case ARG_DELIMITER :
+ if (inQuotes || inVar) {
+ buffer.append(ch);
+ } else {
+ if (buffer.length() > 0) {
+ list.add(buffer.toString());
+ buffer.setLength(0);
+ }
+ }
+ break;
+
+ case ARG_DBL_QUOTE :
+ if (inVar) {
+ buffer.append(ch);
+ } else {
+ if (start < end) {
+ if (arguments.charAt(start) == ARG_DBL_QUOTE) {
+ // Two quotes together represents one quote
+ buffer.append(ch);
+ start++;
+ } else {
+ inQuotes = !inQuotes;
+ }
+ } else {
+ // A lone quote at the end, just drop it.
+ inQuotes = false;
+ }
+ }
+ break;
+
+ case VAR_TAG_START_CHAR1 :
+ buffer.append(ch);
+ if (!inVar && start < end) {
+ if (arguments.charAt(start) == VAR_TAG_START_CHAR2) {
+ buffer.append(VAR_TAG_START_CHAR2);
+ inVar = true;
+ start++;
+ }
+ }
+ break;
+
+ case VAR_TAG_END_CHAR1 :
+ buffer.append(ch);
+ inVar = false;
+ break;
+
+ default :
+ buffer.append(ch);
+ break;
+ }
+
+ }
+
+ if (buffer.length() > 0)
+ list.add(buffer.toString());
+
+ String[] results = new String[list.size()];
+ list.toArray(results);
+ return results;
+ }
+
+
+ /**
+ * Structure to represent a variable definition within a
+ * source string.
+ */
+ public static final class VariableDefinition {
+ /**
+ * Index in the source text where the variable started
+ * or <code>-1</code> if no valid variable start tag
+ * identifier found.
+ */
+ public int start = -1;
+
+ /**
+ * Index in the source text of the character following
+ * the end of the variable or <code>-1</code> if no
+ * valid variable end tag found.
+ */
+ public int end = -1;
+
+ /**
+ * The variable's name found in the source text, or
+ * <code>null</code> if no valid variable found.
+ */
+ public String name = null;
+
+ /**
+ * The variable's argument found in the source text, or
+ * <code>null</code> if no valid variable found or if
+ * the variable did not specify an argument
+ */
+ public String argument = null;
+
+ /**
+ * Create an initialized variable definition.
+ */
+ private VariableDefinition() {
+ super();
+ }
+
+ /**
+ * Create an initialized variable definition.
+ */
+ private VariableDefinition(int start, int end) {
+ super();
+ this.start = start;
+ this.end = end;
+ }
+ }
+}

Back to the top