From: axelcl <axelcl>
Date: Sun, 5 Jun 2005 21:04:09 +0000 (+0000)
Subject: Created a separated 'externaltools' plugin: initial check-in
X-Git-Url: http://secure.phpeclipse.com?hp=aaf64ad503e60ac976db0c92f55578a4ace6530b

Created a separated 'externaltools' plugin: initial check-in
---

diff --git a/net.sourceforge.phpeclipse.externaltools/.classpath b/net.sourceforge.phpeclipse.externaltools/.classpath
new file mode 100644
index 0000000..065ac06
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/net.sourceforge.phpeclipse.externaltools/.project b/net.sourceforge.phpeclipse.externaltools/.project
new file mode 100644
index 0000000..cbbdf73
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>net.sourceforge.phpeclipse.externaltools</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/net.sourceforge.phpeclipse.externaltools/build.properties b/net.sourceforge.phpeclipse.externaltools/build.properties
new file mode 100644
index 0000000..a89cdd9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/build.properties
@@ -0,0 +1,6 @@
+source.externaltools.jar = src/
+output.externaltools.jar = bin/
+bin.includes = plugin.xml,\
+               externaltools.jar
+src.includes = src/,\
+               build.properties
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/activate.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/activate.gif
new file mode 100644
index 0000000..7a1511d
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/activate.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/add_co.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/add_co.gif
new file mode 100644
index 0000000..dad7260
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/add_co.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/deactivate.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/deactivate.gif
new file mode 100644
index 0000000..740419b
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/deactivate.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/element.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/element.gif
new file mode 100644
index 0000000..06d0079
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/element.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/elements.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/elements.gif
new file mode 100644
index 0000000..76b351e
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/elements.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/error.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/error.gif
new file mode 100644
index 0000000..c2bfdd6
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/error.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/gotoobj_tsk.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/gotoobj_tsk.gif
new file mode 100644
index 0000000..082e49f
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/gotoobj_tsk.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/moveDown.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/moveDown.gif
new file mode 100644
index 0000000..8392f33
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/moveDown.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/moveUp.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/moveUp.gif
new file mode 100644
index 0000000..9b278e6
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/moveUp.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/properties.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/properties.gif
new file mode 100644
index 0000000..ec0cba1
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/properties.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/refresh.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/refresh.gif
new file mode 100644
index 0000000..a063c23
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/refresh.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/removeAll_co.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/removeAll_co.gif
new file mode 100644
index 0000000..2c069ab
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/removeAll_co.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/remove_co.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/remove_co.gif
new file mode 100644
index 0000000..12a9167
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/remove_co.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/run_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/run_tool.gif
new file mode 100644
index 0000000..2088548
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/run_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/search.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/search.gif
new file mode 100644
index 0000000..6dc3ebe
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/clcl16/search.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/ctool16/external_tools.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/ctool16/external_tools.gif
new file mode 100644
index 0000000..2133b45
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/ctool16/external_tools.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/cview16/external_tools.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/cview16/external_tools.gif
new file mode 100644
index 0000000..2133b45
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/cview16/external_tools.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/cview16/log_console_view.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/cview16/log_console_view.gif
new file mode 100644
index 0000000..3200ac3
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/cview16/log_console_view.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/copy_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/copy_tool.gif
new file mode 100644
index 0000000..c7a98e8
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/copy_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/del_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/del_tool.gif
new file mode 100644
index 0000000..a6bfcfd
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/del_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/new_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/new_tool.gif
new file mode 100644
index 0000000..813cb2f
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/new_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/paste_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/paste_tool.gif
new file mode 100644
index 0000000..0dd5d21
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/paste_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/prop_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/prop_tool.gif
new file mode 100644
index 0000000..eb165ff
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/prop_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/refresh.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/refresh.gif
new file mode 100644
index 0000000..b2281b4
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/refresh.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/rename_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/rename_tool.gif
new file mode 100644
index 0000000..99f3092
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/rename_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/run_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/run_tool.gif
new file mode 100644
index 0000000..a281bc1
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/run_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/runwith_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/runwith_tool.gif
new file mode 100644
index 0000000..a281bc1
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/dlcl16/runwith_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/dtool16/external_tools.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/dtool16/external_tools.gif
new file mode 100644
index 0000000..fae592d
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/dtool16/external_tools.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/copy_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/copy_tool.gif
new file mode 100644
index 0000000..41bf445
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/copy_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/del_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/del_tool.gif
new file mode 100644
index 0000000..34643b8
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/del_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/new_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/new_tool.gif
new file mode 100644
index 0000000..234594a
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/new_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/paste_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/paste_tool.gif
new file mode 100644
index 0000000..6e76152
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/paste_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/prop_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/prop_tool.gif
new file mode 100644
index 0000000..eb165ff
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/prop_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/refresh.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/refresh.gif
new file mode 100644
index 0000000..919423d
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/refresh.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/rename_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/rename_tool.gif
new file mode 100644
index 0000000..8337ba9
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/rename_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/run_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/run_tool.gif
new file mode 100644
index 0000000..053738c
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/run_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/runwith_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/runwith_tool.gif
new file mode 100644
index 0000000..053738c
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/elcl16/runwith_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/etool16/external_tools.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/etool16/external_tools.gif
new file mode 100644
index 0000000..f7472c9
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/etool16/external_tools.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/eview16/external_tools.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/eview16/external_tools.gif
new file mode 100644
index 0000000..f7472c9
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/eview16/external_tools.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/eview16/log_console_view.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/eview16/log_console_view.gif
new file mode 100644
index 0000000..3f6fff3
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/eview16/log_console_view.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/builder.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/builder.gif
new file mode 100644
index 0000000..20e7bae
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/builder.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/classpath.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/classpath.gif
new file mode 100644
index 0000000..f966fc3
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/classpath.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/external_tools.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/external_tools.gif
new file mode 100644
index 0000000..2133b45
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/external_tools.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/file_obj.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/file_obj.gif
new file mode 100644
index 0000000..6b86d07
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/file_obj.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/invalid_build_tool.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/invalid_build_tool.gif
new file mode 100644
index 0000000..b04020b
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/invalid_build_tool.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/jar_l_obj.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/jar_l_obj.gif
new file mode 100644
index 0000000..11e04e2
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/jar_l_obj.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/main_tab.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/main_tab.gif
new file mode 100644
index 0000000..f9fb6b0
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/main_tab.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/options_tab.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/options_tab.gif
new file mode 100644
index 0000000..8670a38
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/options_tab.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/prop_ps.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/prop_ps.gif
new file mode 100644
index 0000000..ec0cba1
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/prop_ps.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/ttype_program.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/ttype_program.gif
new file mode 100644
index 0000000..2133b45
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/ttype_program.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/type.gif b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/type.gif
new file mode 100644
index 0000000..2db7604
Binary files /dev/null and b/net.sourceforge.phpeclipse.externaltools/icons/full/obj16/type.gif differ
diff --git a/net.sourceforge.phpeclipse.externaltools/plugin.properties b/net.sourceforge.phpeclipse.externaltools/plugin.properties
new file mode 100644
index 0000000..1acd37f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/plugin.properties
@@ -0,0 +1,32 @@
+LaunchConfigurationTypePHPApplication.name=PHP Application
+
+ExtPoint.configurationDuplicationMaps = Launch Configuration Duplication Maps
+ExtPoint.toolTypes = External Tool Types
+ExtPoint.argumentVariables  = Argument Variables
+ExtPoint.directoryVariables = Directory Variables
+ExtPoint.fileVariables = File Variables
+ExtPoint.refreshVariables = Refresh Scope Variables
+ExternalToolsLaunchGroup.label = &External Tools
+ToolType.programName = Program
+ToolType.programDescription = An external tool that runs an application, a batch file, etc.
+Menu.run = &Run
+ActionSet.externalTools = External Tools
+Action.externalTools = &External Tools
+Action.externalToolsTip = Run Last Tool
+PropertyPage.main = Main
+PropertyPage.option = Options
+PropertyPage.refresh = Refresh Scope
+PropertyPage.antTargets = Targets
+PropertyPage.externalToolsBuilders = PHP Launch Builders
+CategoryView.externalTools = PHP Launchers
+CategoryNewWizard.externalTools = PHP Launchers
+NewWizard.programName = Program
+NewWizard.programDescription = Create an external tool to run an application, a batch file, etc.
+Builder.externalTools = Integrated PHP Launcher Builder
+View.externalToolView = PHP Launchers
+View.logConsole = Log Console
+PreferencePage.externalToolsPreferences = PHP Launchers
+PreferencePage.antConsolePreferences = Console
+PreferencePage.antRuntimePreferences = Runtime
+
+Program.externalTools = PHP Program
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.externaltools/plugin.xml b/net.sourceforge.phpeclipse.externaltools/plugin.xml
new file mode 100644
index 0000000..b570732
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/plugin.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+   id="net.sourceforge.phpeclipse.externaltools"
+   name="ExternalTools Plug-in"
+   version="1.1.5"
+   provider-name="phpeclipse.de"
+   class="net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin">
+
+   <runtime>
+      <library name="externaltools.jar">
+         <export name="*"/>
+      </library>
+   </runtime>
+
+   <requires>
+      <import plugin="org.eclipse.ui"/>
+      <import plugin="org.eclipse.ui.ide"/>
+      <import plugin="org.eclipse.core.resources"/>
+      <import plugin="org.eclipse.core.runtime"/>
+      <import plugin="org.eclipse.debug.core"/>
+      <import plugin="org.eclipse.debug.ui"/>
+      <import plugin="org.eclipse.ui.externaltools"/>
+      <import plugin="net.sourceforge.phpeclipse"/>
+      <import plugin="net.sourceforge.phpeclipse.ui"/>
+   </requires>
+
+
+<!-- external tools -->
+
+<!-- extension point definitions -->
+	<extension-point id="configurationDuplicationMaps" name="%ExtPoint.configurationDuplicationMaps"/>
+	<extension-point id="argumentVariables" name="%ExtPoint.argumentVariables"/>
+	<extension-point id="directoryVariables" name="%ExtPoint.directoryVariables"/>
+	<extension-point id="fileVariables" name="%ExtPoint.fileVariables"/>
+	<extension-point id="refreshVariables" name="%ExtPoint.refreshVariables"/>
+	
+<!-- Extensions -->
+	<extension point="org.eclipse.ui.actionSets">
+		<actionSet
+			id="net.sourceforge.phpdt.externaltools.ExternalToolsSet"
+			label="%ActionSet.externalTools"
+			visible="true">
+			<menu id="org.eclipse.ui.run" 
+				label="%Menu.run" 
+				path="additions"> 
+				<separator name="ExternalToolsGroup"/> 
+			</menu> 
+	<!--		<action
+				id="net.sourceforge.phpdt.externaltools.ExternalToolMenuDelegateMenu"
+				label="%Action.externalTools"
+				menubarPath="org.eclipse.ui.run/ExternalToolsGroup"
+				disabledIcon="icons/full/dtool16/external_tools.gif"
+				icon="icons/full/etool16/external_tools.gif"
+				hoverIcon="icons/full/ctool16/external_tools.gif"
+				pulldown="true"
+				class="net.sourceforge.phpdt.externaltools.internal.menu.ExternalToolMenuDelegate">
+			</action> 
+			<action
+				id="net.sourceforge.phpdt.externaltools.ExternalToolMenuDelegateToolbar"
+				label="%Action.externalTools"
+				toolbarPath="Normal/additions"
+				disabledIcon="icons/full/dtool16/external_tools.gif"
+				icon="icons/full/etool16/external_tools.gif"
+				hoverIcon="icons/full/ctool16/external_tools.gif"
+				tooltip="%Action.externalToolsTip"
+				pulldown="true"
+				class="net.sourceforge.phpdt.externaltools.internal.menu.ExternalToolMenuDelegate">
+			</action> -->
+		</actionSet>
+	</extension>
+
+    <!-- Launch Configuration Extensions -->
+    <extension point="org.eclipse.debug.core.launchConfigurationTypes">
+    	<launchConfigurationType
+	    	id = "net.sourceforge.phpdt.externaltools.ProgramLaunchConfigurationType"
+    		name = "%Program.externalTools"
+    		delegate = "net.sourceforge.phpdt.externaltools.internal.program.launchConfigurations.ProgramLaunchDelegate"
+    		modes = "run"
+    		category = "org.eclipse.ui.externaltools">
+    	</launchConfigurationType>
+    	<launchConfigurationType
+	    	id = "net.sourceforge.phpdt.externaltools.ProgramBuilderLaunchConfigurationType"
+    		name = "%Program.externalTools"
+    		delegate = "net.sourceforge.phpdt.externaltools.internal.program.launchConfigurations.ProgramLaunchDelegate"
+    		modes = "run"
+    		category = "org.eclipse.ui.externaltools.builder">
+    	</launchConfigurationType>
+    </extension>
+    
+    <extension point = "net.sourceforge.phpeclipse.externaltools.configurationDuplicationMaps">
+    	<configurationMap
+    		sourceType="net.sourceforge.phpdt.externaltools.ProgramLaunchConfigurationType"
+    		builderType="net.sourceforge.phpdt.externaltools.ProgramBuilderLaunchConfigurationType">
+    	</configurationMap>
+    </extension>
+    
+    <extension point = "org.eclipse.debug.ui.launchConfigurationTabGroups">
+		<launchConfigurationTabGroup
+			id="net.sourceforge.phpdt.externaltools.launchConfigurationTabGroup.program"
+			type ="net.sourceforge.phpdt.externaltools.ProgramLaunchConfigurationType"
+			class="net.sourceforge.phpdt.externaltools.internal.program.launchConfigurations.ProgramTabGroup">
+		</launchConfigurationTabGroup>
+		<launchConfigurationTabGroup
+			id="net.sourceforge.phpdt.externaltools.launchConfigurationTabGroup.program.builder"
+			type ="net.sourceforge.phpdt.externaltools.ProgramBuilderLaunchConfigurationType"
+			class="net.sourceforge.phpdt.externaltools.internal.program.launchConfigurations.ProgramBuilderTabGroup">
+		</launchConfigurationTabGroup>
+	</extension>
+	
+	<extension point="org.eclipse.debug.ui.launchConfigurationTypeImages">
+		<launchConfigurationTypeImage
+			id="net.sourceforge.phpdt.externaltools.launchConfigurationTypeImage.program"
+			configTypeID="net.sourceforge.phpdt.externaltools.ProgramLaunchConfigurationType"
+			icon="icons/full/obj16/external_tools.gif">
+		</launchConfigurationTypeImage>	
+		<launchConfigurationTypeImage
+			id="net.sourceforge.phpdt.externaltools.launchConfigurationTypeImage.program.builder"
+			configTypeID="net.sourceforge.phpdt.externaltools.ProgramBuilderLaunchConfigurationType"
+			icon="icons/full/obj16/external_tools.gif">
+		</launchConfigurationTypeImage>	
+	</extension>
+ 
+	<!-- Variable Extensions --> 
+	<extension point="net.sourceforge.phpeclipse.externaltools.fileVariables">
+		<variable
+			tag="workspace_loc"
+			description="Expands to the workspace root's absolute file system path."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.WorkspaceExpander">
+		</variable>
+		<variable
+			tag="resource_loc"
+			description="Expands to the resource's absolute file system path."
+			componentClass="net.sourceforge.phpdt.externaltools.variable.SpecificFileResourceComponent"
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ResourceExpander">
+		</variable>
+	</extension>
+	
+	<extension point="net.sourceforge.phpeclipse.externaltools.argumentVariables">
+		<variable
+			tag="workspace_loc"
+			description="Expands to the workspace root's absolute file system path."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.WorkspaceExpander">
+		</variable>
+		<variable
+			tag="file_loc"
+			description="Expands to the full file name"
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.FileExpander">
+		</variable>
+		<variable
+			tag="file_url"
+			description="Expands to an URL with the localhost preference settings"
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.UrlExpander">
+		</variable>
+		<variable
+			tag="localhost_url"
+			description="Expands to the localhost preference settings."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.LocalhostExpander">
+		</variable>
+		<variable
+			tag="project_loc"
+			description="Expands to the selected resource's project absolute file system path."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ResourceProjectExpander">
+		</variable>
+		<variable
+			tag="project_path"
+			description="Expands to the full path, relative to the workspace root, of the selected project"
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ProjectExpander">
+		</variable>
+		<variable
+			tag="project_name"
+			description="Expands to the name of the selected project"
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ProjectNameExpander">
+		</variable>
+		<variable
+			tag="resource_loc"
+			description="Expands to the resource's absolute file system path."
+			componentClass="net.sourceforge.phpdt.externaltools.variable.SpecificFileResourceComponent"
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ResourceExpander">
+		</variable>
+		<variable
+			tag="container_loc"
+			description="Expands to the selected resource's containing folder absolute file system path."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ResourceContainerExpander">
+		</variable>
+		<variable
+			tag="build_type"
+			description="Expands to the type of build"
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.BuildTypeExpander">
+		</variable>
+	</extension>
+
+	<extension point="net.sourceforge.phpeclipse.externaltools.directoryVariables">
+		<variable
+			tag="workspace_loc"
+			description="Expands to the workspace root's absolute file system path."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.WorkspaceExpander">
+		</variable>
+		<variable
+			tag="project_loc"
+			description="Expands to the selected resource's project absolute file system path."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ResourceProjectExpander">
+		</variable>
+		<variable
+			tag="container_loc"
+			description="Expands to the selected resource's containing folder absolute file system path."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ResourceContainerExpander">
+		</variable>
+		<variable
+			tag="resource_loc"
+			description="Expands to a resource's absolute file system path."
+			componentClass="net.sourceforge.phpdt.externaltools.variable.SpecificFolderResourceComponent"
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ResourceExpander">
+		</variable>
+	</extension>
+ 
+	<extension point="net.sourceforge.phpeclipse.externaltools.refreshVariables">
+		<variable
+			tag="workspace"
+			description="Expands to the workspace root."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.WorkspaceExpander">
+		</variable>
+		<variable
+			tag="project"
+			description="Expands to the project of the selected resource."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ResourceProjectExpander">
+		</variable>
+		<variable
+			tag="container"
+			description="Expands to the folder containing the selected resource."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ResourceContainerExpander">
+		</variable>
+		<variable
+			tag="resource"
+			description="Expands to a resource."
+			componentClass="net.sourceforge.phpdt.externaltools.variable.ResourceComponent"
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.ResourceExpander">
+		</variable>
+		<variable
+			tag="working_set"
+			description="Expands to the group of resources in a working set."
+			expanderClass="net.sourceforge.phpdt.externaltools.variable.WorkingSetExpander">
+		</variable>
+	</extension>
+	
+</plugin>
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/group/IGroupDialogPage.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/group/IGroupDialogPage.java
new file mode 100644
index 0000000..d441165
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/group/IGroupDialogPage.java
@@ -0,0 +1,62 @@
+package net.sourceforge.phpdt.externaltools.group;
+
+/**********************************************************************
+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.jface.dialogs.IMessageProvider;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+
+/**
+ * Represents the API for a group of visual components
+ * to access the dialog page that contains it.
+ * <p>
+ * This interface is not intended to be extended
+ * nor implemented by clients.
+ * </p>
+ */
+public interface IGroupDialogPage extends IMessageProvider {
+	/**
+	 * Sets the <code>GridData</code> on the specified button to
+	 * be one that is spaced for the current dialog page units.
+	 * 
+	 * @param button the button to set the <code>GridData</code>
+	 * @return the <code>GridData</code> set on the specified button
+	 */
+	public GridData setButtonGridData(Button button);
+
+	/**
+	 * Sets the message for this page with an indication of what type
+	 * of message it is.
+	 * <p>
+	 * The valid message types are one of <code>NONE</code>, 
+	 * <code>INFORMATION</code>, <code>WARNING</code>, or <code>ERROR</code>.
+	 * </p>
+	 *
+	 * @param newMessage the message, or <code>null</code> to clear the message
+	 * @param newType the message type
+	 */
+	public void setMessage(String newMessage, int newType);
+
+	/**
+	 * Updates the page's valid state using the group's
+	 * current valid state. This will cause the dialog's
+	 * buttons dependent on the page's valid state to
+	 * update to reflect the new state.
+	 */
+	public void updateValidState();
+	
+	/**
+	 * Converts a height in characters to a height in pixels.
+	 * 
+	 * @param chars the height in characters to be converted
+	 * @return the corresponding height in pixels
+	 */
+	public int convertHeightHint(int chars);
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/dialog/ExternalToolVariableForm.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/dialog/ExternalToolVariableForm.java
new file mode 100644
index 0000000..5a9de70
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/dialog/ExternalToolVariableForm.java
@@ -0,0 +1,221 @@
+package net.sourceforge.phpdt.externaltools.internal.dialog;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.group.IGroupDialogPage;
+import net.sourceforge.phpdt.externaltools.internal.registry.ExternalToolVariable;
+import net.sourceforge.phpdt.externaltools.model.ToolUtil;
+import net.sourceforge.phpdt.externaltools.variable.IVariableComponent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+
+/**
+ * Visual grouping of controls that allows the user to
+ * select a variable and configure it with extra
+ * information.
+ */
+public class ExternalToolVariableForm {
+	private static final int VISIBLE_ITEM_COUNT = 9;
+	
+	private String variableListLabelText;
+	private ExternalToolVariable[] variables;
+	private IVariableComponent[] components;
+	private IGroupDialogPage page;
+	
+	private Label variableListLabel;
+	private List variableList;
+	private Composite variableComposite;
+	private StackLayout variableLayout;
+	private int activeComponentIndex = -1;
+	
+	/**
+	 * Creates the visual grouping
+	 * 
+	 * @param variableListLabelText the label text to use for identifying the list of variables
+	 * @param variables the collection of variables to display to the user
+	 */
+	public ExternalToolVariableForm(String variableListLabelText, ExternalToolVariable[] variables) {
+		super();
+		this.variableListLabelText = variableListLabelText;
+		this.variables = variables;
+		this.components = new IVariableComponent[variables.length];
+	}
+
+	public Composite createContents(Composite parent, IGroupDialogPage page) {
+		Font font = parent.getFont();
+		
+		this.page = page;
+		
+		Composite mainComposite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 1;
+		GridData data = new GridData(GridData.FILL_BOTH);
+		mainComposite.setLayout(layout);
+		mainComposite.setLayoutData(data);
+
+		variableListLabel = new Label(mainComposite, SWT.NONE);
+		variableListLabel.setText(variableListLabelText);
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 1;
+		variableListLabel.setLayoutData(data);
+		variableListLabel.setFont(font);
+		
+		variableList = new List(mainComposite, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.heightHint = variableList.getItemHeight() * VISIBLE_ITEM_COUNT;
+		variableList.setLayoutData(data);
+		variableList.setFont(font);
+
+		variableComposite = new Composite(mainComposite, SWT.NONE);
+		variableLayout = new StackLayout();
+		variableLayout.marginWidth = 0;
+		variableLayout.marginHeight = 0;
+		data = new GridData(GridData.FILL_BOTH);
+		variableComposite.setLayout(variableLayout);
+		variableComposite.setLayoutData(data);
+		variableComposite.setFont(font);
+		
+		createVariableComponents(data);
+		
+		populateVariableList();
+		
+		variableList.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				updateVariableComposite(null, false);
+			}
+		});
+		
+		setEnabled(true);
+		return mainComposite;
+	}
+	
+	/**
+	 * Creates the visual component for each variable
+	 * and determine the initial size so the form
+	 * can be layout properly.
+	 */
+	private void createVariableComponents(GridData data) {
+		for (int i = 0; i < variables.length; i++) {
+			ExternalToolVariable var = variables[i];
+			components[i] = var.getComponent();
+			components[i].createContents(variableComposite, var.getTag(), page);
+			Control control = components[i].getControl();
+			if (control != null) {
+				Point newSize = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
+				data.widthHint = Math.max(newSize.x, data.widthHint);
+				data.heightHint = Math.max(newSize.y, data.heightHint);
+			}
+		}
+	}
+	
+	/**
+	 * Returns the formatted variable or <code>null</code> if
+	 * none selected.
+	 */
+	public String getSelectedVariable() {
+		if (activeComponentIndex != -1) {
+			String varValue = components[activeComponentIndex].getVariableValue();
+			return ToolUtil.buildVariableTag(variables[activeComponentIndex].getTag(), varValue);
+		}
+
+		return null;
+	}
+
+	/**
+	 * Returns whether the current variable selection is
+	 * valid, including the selected variable value.
+	 */
+	public boolean isValid() {
+		if (activeComponentIndex != -1)
+			return components[activeComponentIndex].isValid();
+		
+		return true;
+	}
+
+	private void populateVariableList() {
+		String[] items = new String[variables.length];
+		StringBuffer buffer = new StringBuffer(80);
+		for (int i = 0; i < variables.length; i++) {
+			ToolUtil.buildVariableTag(variables[i].getTag(), null, buffer);
+			buffer.append(" - "); //$NON-NLS-1$
+			buffer.append(variables[i].getDescription());
+			items[i] = buffer.toString();
+			buffer.setLength(0);
+		}
+		variableList.setItems(items);
+	}
+
+	public void selectVariable(String varName, String varValue) {	
+		if (varName != null && varName.length() > 0) {
+			for (int i = 0; i < variables.length; i++) {
+				if (varName.equals(variables[i].getTag())) {
+					variableList.select(i);
+					updateVariableComposite(varValue, true);
+					return;
+				}
+			}
+		}
+		
+		variableList.deselectAll();
+		updateVariableComposite(varValue, false);
+	}
+	
+	private void setComponentVisible(int index) {
+		if (index == -1)
+			variableLayout.topControl = null;
+		else
+			variableLayout.topControl = components[index].getControl();
+		variableComposite.layout();
+	}
+	
+	/**
+	 * Enables or disables the variable form controls.
+	 */
+	public void setEnabled(boolean enabled) {
+		variableListLabel.setEnabled(enabled);
+		variableList.setEnabled(enabled);
+		if (enabled && variableList.getSelection().length == 0) {
+			if (variableList.getItemCount() > 0) {
+				variableList.select(0);
+				activeComponentIndex= 0;
+			}
+		}
+		variableComposite.setVisible(enabled);
+	}
+	
+	private void updateVariableComposite(String value, boolean setValue) {
+		activeComponentIndex = variableList.getSelectionIndex();
+		setComponentVisible(activeComponentIndex);
+		if (activeComponentIndex != -1 && setValue)
+			components[activeComponentIndex].setVariableValue(value);
+	}
+
+	/**
+	 * Validates the current variable selection is and
+	 * its value are acceptable.
+	 */
+	public void validate() {
+		if (activeComponentIndex != -1)
+			components[activeComponentIndex].validate();
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ColorManager.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ColorManager.java
new file mode 100644
index 0000000..c82cdb4
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ColorManager.java
@@ -0,0 +1,53 @@
+package net.sourceforge.phpdt.externaltools.internal.model;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Generic color manager.
+ */
+public class ColorManager {	
+	
+	private static ColorManager fgColorManager;
+	
+	private ColorManager() {
+	}
+	
+	public static ColorManager getDefault() {
+		if (fgColorManager == null) {
+			fgColorManager= new ColorManager();
+		}
+		return fgColorManager;
+	}
+	
+	protected Map fColorTable= new HashMap(10);
+	
+	public Color getColor(RGB rgb) {
+		Color color= (Color) fColorTable.get(rgb);
+		if (color == null) {
+			color= new Color(Display.getCurrent(), rgb);
+			fColorTable.put(rgb, color);
+		}
+		return color;
+	}
+	
+	public void dispose() {
+		Iterator e= fColorTable.values().iterator();
+		while (e.hasNext())
+			((Color) e.next()).dispose();
+	}
+}
+
+
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ExternalToolsImages.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ExternalToolsImages.java
new file mode 100644
index 0000000..24abd4b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ExternalToolsImages.java
@@ -0,0 +1,196 @@
+package net.sourceforge.phpdt.externaltools.internal.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.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+
+import net.sourceforge.phpdt.externaltools.internal.ui.IExternalToolsUIConstants;
+import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.externaltools.internal.model.ExternalToolsPlugin;
+
+/**
+ * The images provided by the external tools plugin.
+ */
+public class ExternalToolsImages {
+
+	/** 
+	 * The image registry containing <code>Image</code>s.
+	 */
+	private static ImageRegistry imageRegistry;
+	
+	/**
+	 * A table of all the <code>ImageDescriptor</code>s.
+	 */
+	private static HashMap imageDescriptors;
+
+	private static final String ATTR_LAUNCH_CONFIG_TYPE_ICON = "icon"; //$NON-NLS-1$
+	private static final String ATTR_LAUNCH_CONFIG_TYPE_ID = "configTypeID"; //$NON-NLS-1$
+	
+	/* Declare Common paths */
+	private static URL ICON_BASE_URL= null;
+
+//	static {
+//		String pathSuffix = "icons/externaltools/full/"; //$NON-NLS-1$
+//			
+//		try {
+//			ICON_BASE_URL= new URL(PHPeclipsePlugin.getDefault().getDescriptor().getInstallURL(), pathSuffix);
+//		} catch (MalformedURLException e) {
+//			// do nothing
+//		}
+//	}
+	static {
+		String pathSuffix = "icons/full/"; //$NON-NLS-1$	
+		ICON_BASE_URL= ExternalToolsPlugin.getDefault().getBundle().getEntry(pathSuffix);
+	}
+
+	// Use IPath and toOSString to build the names to ensure they have the slashes correct
+	private final static String CTOOL= "ctool16/"; //basic colors - size 16x16 //$NON-NLS-1$
+	private final static String LOCALTOOL= "clcl16/"; //basic colors - size 16x16 //$NON-NLS-1$
+	private final static String DLCL= "dlcl16/"; //disabled - size 16x16 //$NON-NLS-1$
+	private final static String ELCL= "elcl16/"; //enabled - size 16x16 //$NON-NLS-1$
+	private final static String OBJECT= "obj16/"; //basic colors - size 16x16 //$NON-NLS-1$
+	private final static String WIZBAN= "wizban/"; //basic colors - size 16x16 //$NON-NLS-1$
+	private final static String OVR= "ovr16/"; //basic colors - size 7x8 //$NON-NLS-1$
+	private final static String VIEW= "cview16/"; // views //$NON-NLS-1$
+	
+	/**
+	 * Declare all images
+	 */
+	private static void declareImages() {
+		// Ant View Actions
+		declareRegistryImage(IExternalToolsUIConstants.IMG_REMOVE, LOCALTOOL + "remove_co.gif"); //$NON-NLS-1$
+		declareRegistryImage(IExternalToolsUIConstants.IMG_REMOVE_ALL, LOCALTOOL + "removeAll_co.gif"); //$NON-NLS-1$
+		declareRegistryImage(IExternalToolsUIConstants.IMG_ADD, LOCALTOOL + "add_co.gif"); //$NON-NLS-1$
+		declareRegistryImage(IExternalToolsUIConstants.IMG_RUN, LOCALTOOL + "run_tool.gif"); //$NON-NLS-1$
+		declareRegistryImage(IExternalToolsUIConstants.IMG_SEARCH, LOCALTOOL + "search.gif"); //$NON-NLS-1$
+		declareRegistryImage(IExternalToolsUIConstants.IMG_MOVE_UP, LOCALTOOL + "moveUp.gif"); //$NON-NLS-1$
+		declareRegistryImage(IExternalToolsUIConstants.IMG_MOVE_DOWN, LOCALTOOL + "moveDown.gif"); //$NON-NLS-1$
+		declareRegistryImage(IExternalToolsUIConstants.IMG_ACTIVATE, LOCALTOOL + "activate.gif"); //$NON-NLS-1$
+		declareRegistryImage(IExternalToolsUIConstants.IMG_DEACTIVATE, LOCALTOOL + "deactivate.gif"); //$NON-NLS-1$
+		declareRegistryImage(IExternalToolsUIConstants.IMG_GO_TO_FILE, LOCALTOOL + "gotoobj_tsk.gif"); //$NON-NLS-1$
+		// Ant View Labels
+//		declareRegistryImage(IExternalToolsUIConstants.IMG_ANT_PROJECT, OBJECT + "file_obj.gif"); //$NON-NLS-1$
+//		declareRegistryImage(IExternalToolsUIConstants.IMG_ANT_PROJECT_ERROR, LOCALTOOL + "ant_project_err.gif"); //$NON-NLS-1$
+//		declareRegistryImage(IExternalToolsUIConstants.IMG_ANT_TARGET, LOCALTOOL + "ant_target.gif"); //$NON-NLS-1$
+//		declareRegistryImage(IExternalToolsUIConstants.IMG_ANT_TARGET_ERROR, LOCALTOOL + "error.gif"); //$NON-NLS-1$
+//		declareRegistryImage(IExternalToolsUIConstants.IMG_ANT_TARGET_ELEMENTS, LOCALTOOL + "elements.gif"); //$NON-NLS-1$
+//		declareRegistryImage(IExternalToolsUIConstants.IMG_ANT_TARGET_ELEMENT, LOCALTOOL + "element.gif"); //$NON-NLS-1$
+		// Wizards
+		declareRegistryImage(IExternalToolConstants.IMG_WIZBAN_EXTERNAL_TOOLS, WIZBAN + "ext_tools_wiz.gif"); //$NON-NLS-1$
+		
+		// Actions
+		declareRegistryImage(IExternalToolConstants.IMG_ACTION_REFRESH, LOCALTOOL + "refresh.gif"); //$NON-NLS-1$
+		
+		// Objects
+		declareRegistryImage(IExternalToolConstants.IMG_TAB_MAIN, OBJECT + "main_tab.gif"); //$NON-NLS-1$
+		declareRegistryImage(IExternalToolConstants.IMG_TAB_OPTIONS, OBJECT + "options_tab.gif"); //$NON-NLS-1$
+		
+		//ANT object
+		declareRegistryImage(IExternalToolConstants.IMG_TAB_ANT_TARGETS, LOCALTOOL + "ant_tsk_check.gif"); //$NON-NLS-1$
+	}
+
+	/**
+	 * Declare an Image in the registry table.
+	 * @param key 	The key to use when registering the image
+	 * @param path	The path where the image can be found. This path is relative to where
+	 *				this plugin class is found (i.e. typically the packages directory)
+	 */
+	private final static void declareRegistryImage(String key, String path) {
+		ImageDescriptor desc= ImageDescriptor.getMissingImageDescriptor();
+		try {
+			desc= ImageDescriptor.createFromURL(makeIconFileURL(path));
+		} catch (MalformedURLException me) {
+			//ExternalToolsPlugin.log(me);
+		}
+		imageRegistry.put(key, desc);
+		imageDescriptors.put(key, desc);
+	}
+	
+	/**
+	 * Returns the ImageRegistry.
+	 */
+	public static ImageRegistry getImageRegistry() {
+		if (imageRegistry == null) {
+			initializeImageRegistry();
+		}
+		return imageRegistry;
+	}
+
+	/**
+	 *	Initialize the image registry by declaring all of the required
+	 *	graphics. This involves creating JFace image descriptors describing
+	 *	how to create/find the image should it be needed.
+	 *	The image is not actually allocated until requested.
+	 *
+	 * 	Prefix conventions
+	 *		Wizard Banners			WIZBAN_
+	 *		Preference Banners		PREF_BAN_
+	 *		Property Page Banners	PROPBAN_
+	 *		Color toolbar			CTOOL_
+	 *		Enable toolbar			ETOOL_
+	 *		Disable toolbar			DTOOL_
+	 *		Local enabled toolbar	ELCL_
+	 *		Local Disable toolbar	DLCL_
+	 *		Object large			OBJL_
+	 *		Object small			OBJS_
+	 *		View 					VIEW_
+	 *		Product images			PROD_
+	 *		Misc images				MISC_
+	 *
+	 *	Where are the images?
+	 *		The images (typically gifs) are found in the same location as this plugin class.
+	 *		This may mean the same package directory as the package holding this class.
+	 *		The images are declared using this.getClass() to ensure they are looked up via
+	 *		this plugin class.
+	 *	@see JFace's ImageRegistry
+	 */
+	public static ImageRegistry initializeImageRegistry() {
+		imageRegistry= new ImageRegistry(PHPeclipsePlugin.getStandardDisplay());
+		imageDescriptors = new HashMap(30);
+		declareImages();
+		return imageRegistry;
+	}
+
+	/**
+	 * Returns the <code>Image<code> identified by the given key,
+	 * or <code>null</code> if it does not exist.
+	 */
+	public static Image getImage(String key) {
+		return getImageRegistry().get(key);
+	}
+	
+	/**
+	 * Returns the <code>ImageDescriptor<code> identified by the given key,
+	 * or <code>null</code> if it does not exist.
+	 */
+	public static ImageDescriptor getImageDescriptor(String key) {
+		if (imageDescriptors == null) {
+			initializeImageRegistry();
+		}
+		return (ImageDescriptor)imageDescriptors.get(key);
+	}
+	
+	private static URL makeIconFileURL(String iconPath) throws MalformedURLException {
+		if (ICON_BASE_URL == null) {
+			throw new MalformedURLException();
+		}
+			
+		return new URL(ICON_BASE_URL, iconPath);
+	}
+}
+
+
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ExternalToolsModelMessages.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ExternalToolsModelMessages.java
new file mode 100644
index 0000000..7e56a8b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ExternalToolsModelMessages.java
@@ -0,0 +1,61 @@
+package net.sourceforge.phpdt.externaltools.internal.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.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Utility class which helps managing messages
+ */
+public final class ExternalToolsModelMessages {
+	private static final String RESOURCE_BUNDLE= "net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsModelMessages"; //$NON-NLS-1$
+	private static ResourceBundle bundle = ResourceBundle.getBundle(RESOURCE_BUNDLE);
+	
+	private ExternalToolsModelMessages(){
+		// prevent instantiation of class
+	}
+	
+	/**
+	 * Returns the formatted message for the given key in
+	 * the resource bundle. 
+	 *
+	 * @param key the message name
+	 * @param args the message arguments
+	 * @return the formatted message
+	 */	
+	public static String format(String key, Object[] args) {
+		return MessageFormat.format(getString(key), args);
+	}
+	
+	/**
+	 * Returns the message with the given key in
+	 * the resource bundle. If there isn't any value under
+	 * the given key, the key is returned.
+	 *
+	 * @param key the message name
+	 * @return the message
+	 */	
+	public static String getString(String key) {
+		try {
+			return bundle.getString(key);
+		} catch (MissingResourceException e) {
+			return key;
+		}
+	}
+	
+	/**
+	 * Returns the resource bundle for the plug-in
+	 */
+	public static ResourceBundle getResourceBundle() {
+		return bundle;
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ExternalToolsModelMessages.properties b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ExternalToolsModelMessages.properties
new file mode 100644
index 0000000..a16efff
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ExternalToolsModelMessages.properties
@@ -0,0 +1,300 @@
+# ======================================================================
+# 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:
+# ======================================================================
+
+# =======================================================================
+# Base External Tool
+# =======================================================================
+
+ExternalTool.nameMustContainOneChar = The external tool name must contain at least one letter or number.
+ExternalTool.nameContainsInvalidChar = The external tool name must contain only letters, numbers, hyphens, and spaces.
+
+ToolUtil.dirLocVarBetweenText = The variable for the directory location cannot have any other text before or after itself.
+ToolUtil.dirLocVarFormatWrong = The variable for the directory location is not in a valid format.
+ToolUtil.dirLocVarMissing = The variable named ''{0}'' for the directory location does not exist.
+ToolUtil.dirLocVarExpandFailed = The variable named ''{0}'' for the directory location could not be expanded.
+ToolUtil.fileLocVarBetweenText = The variable for the file location cannot have any other text before or after itself.
+ToolUtil.fileLocVarFormatWrong = The variable for the file location is not in a valid format.
+ToolUtil.fileLocVarMissing = The variable named ''{0}'' for the file location does not exist.
+ToolUtil.fileLocVarExpandFailed = The variable named ''{0}'' for the file location could not be expanded.
+ToolUtil.argumentVarFormatWrong = A variable for the arguments is not in a valid format.
+ToolUtil.argumentVarMissing = The variable named ''{0}'' for the arguments does not exist.
+ToolUtil.argumentVarExpandFailed = The variable named ''{0}'' for the arguments could not be expanded.
+
+ExternalToolRegistry.loadToolFailure = Press the Details button for more information.
+ExternalToolRegistry.fileNotFoundError = Could not find external tool storage file.
+ExternalToolRegistry.ioLoadError = Problems reading external tool storage file.
+ExternalToolRegistry.ioSaveError = Problems writing external tool storage file.
+ExternalToolRegistry.loadErrorTitle = Problem Loading External Tools.
+ExternalToolRegistry.loadErrorMessage = Could not load all external tools.
+ExternalToolRegistry.noToolFilename = External tool filename for storage not specified.
+ExternalToolRegistry.deleteToolFileFailed = Could not delete external tool file ''{0}''.
+
+ExternalToolStorage.deleteErrorTitle = Problem Deleting External Tool.
+ExternalToolStorage.deleteErrorMessage = Could not delete external tool. Refresh list and try again.
+ExternalToolStorage.reloadErrorTitle = Problem Refreshing External Tools
+ExternalToolStorage.reloadErrorMessage = Could not load all external tools.
+ExternalToolStorage.saveErrorTitle = Problem Saving External Tool.
+ExternalToolStorage.saveErrorMessage = Could not save external tool. Please try again.
+
+NewExternalToolAction.text = &New
+NewExternalToolAction.toolTip = New External Tool Wizard
+
+CopyExternalToolAction.text = &Copy
+CopyExternalToolAction.toolTip = Copy External Tool
+
+PasteExternalToolAction.text = &Paste
+PasteExternalToolAction.toolTip = Paste External Tool
+
+DeleteExternalToolAction.text = &Delete
+DeleteExternalToolAction.toolTip = Delete External Tool
+DeleteExternalToolAction.confirmToolDeleteTitle = Confirm External Tool Delete
+DeleteExternalToolAction.confirmToolDeleteMsg = Are you sure want to delete ''{0}''?
+
+RenameExternalToolAction.text = Rena&me
+RenameExternalToolAction.toolTip = Rename External Tool
+
+RefreshViewAction.text = Re&fresh
+RefreshViewAction.toolTip = Refresh External Tool View
+
+RunExternalToolAction.text = R&un
+RunExternalToolAction.toolTip = Run External Tool
+
+RunWithExternalToolAction.text = Run &With...
+RunWithExternalToolAction.toolTip = Prompt for Arguments and Run External Tool
+
+EditExternalToolPropertiesAction.text = P&roperties
+EditExternalToolPropertiesAction.toolTip = Edit External Tool Properties
+
+ExternalToolMainGroup.locationLabel = &Location:
+ExternalToolMainGroup.locationBrowseLabel = B&rowse...
+ExternalToolMainGroup.descriptionLabel = D&escription:
+ExternalToolMainGroup.nameLabel = Na&me:
+ExternalToolMainGroup.workDirLabel = &Working Directory:
+ExternalToolMainGroup.workDirBrowseLabel = Br&owse...
+ExternalToolMainGroup.nameRequired = External tool name cannot be empty.
+ExternalToolMainGroup.nameAlreadyExist = Another external tool exists with the same name.
+ExternalToolMainGroup.locationRequired = External tool location cannot be empty.
+ExternalToolMainGroup.invalidLocation = External tool location does not exist or is invalid.
+ExternalToolMainGroup.invalidWorkDir = External tool working directory does not exist or is invalid.
+
+ExternalToolOptionGroup.captureOutputLabel = &Capture output messages from running tool
+ExternalToolOptionGroup.showConsoleLabel = &Show console when tool is run
+ExternalToolOptionGroup.runBackgroundLabel = &Run tool in background
+ExternalToolOptionGroup.openPerspLabel = &Open perspective when tool is run:
+ExternalToolOptionGroup.argumentLabel = Ar&guments:
+ExternalToolOptionGroup.argumentInstruction = Note: Enclose an argument containing spaces using double-quotes ("). Not\napplicable for variables.
+ExternalToolOptionGroup.argumentVariableLabel = &Variables...
+ExternalToolOptionGroup.promptArgLabel = &Prompt for arguments before running tool
+ExternalToolOptionGroup.showInMenuLabel = S&how in Run > External Tools menu
+ExternalToolOptionGroup.saveDirtyEditorsLabel = Save dirty &editors before running tool
+
+ExternalToolRefreshGroup.refreshLabel = &Refresh resources after running tool
+ExternalToolRefreshGroup.recursiveLabel = Recursively &include sub-folders
+ExternalToolRefreshGroup.scopeLabel = Choose &Scope Variable:
+
+ExternalToolNewWizard.shellTitle = New External Tool
+ExternalToolNewWizard.optionPageTitle = Options
+ExternalToolNewWizard.optionPageDescription = Configure the options when the external tool is run.
+ExternalToolNewWizard.refreshPageTitle = Refresh Scope
+ExternalToolNewWizard.refreshPageDescription = Specify which resources to refresh after the external tool is run.
+
+ExternalToolVariable.componentErrorMessage = Problem displaying UI component of selected variable.
+
+ResourceComponent.selectedResLabel = &Use selected resource
+ResourceComponent.specificResLabel = Us&e specific resource:
+ResourceComponent.selectionRequired = A specific resource must be selected from the list.
+
+RunExternalToolAction.openPerspProblem = Failed to open the perspective.
+RunExternalToolAction.openPerspTitle = Open Perspective Problem
+RunExternalToolAction.runProblem = Could not run the external tool.
+RunExternalToolAction.runErrorTitle = Run Tool Problem
+RunExternalToolAction.internalError = External tool runner internal error
+
+DefaultRunnerContext.runningExternalTool = Running external tool...
+DefaultRunnerContext.invalidLocation = The file does not exist for the external tool named {0}.
+DefaultRunnerContext.invalidDirectory = The working directory does not exist for the external tool named {0}.
+DefaultRunnerContext.refreshResources = Refresh resources...
+DefaultRunnerContext.noToolRunner = The no valid runner provided for the external tool named {0}.
+DefaultRunnerContext.invalidRefreshVarFormat = Invalid refresh scope variable format for the external tool named {0}.
+DefaultRunnerContext.noRefreshVarNamed = Could not find refresh scope variable called ''{1}'' for the external tool named {0}.
+
+ExternalToolMenuDelegate.showView = Show External Tools View
+ExternalToolMenuDelegate.runRecent = Run Last Tool
+ExternalToolMenuDelegate.configure = Configure...
+
+
+# =======================================================================
+# Program External Tool Type
+# =======================================================================
+
+ProgramRunner.runningToolLabel = Running external tool: {0}
+ProgramRunner.internalErrorMessage = Internal error
+ProgramRunner.callingRuntimeExec = Calling runtime exec with:\n
+ProgramRunner.program = Program: {0}\n
+ProgramRunner.argument = Argument: {0}\n
+ProgramRunner.workDir = Working Directory: {0}\n
+
+
+# =======================================================================
+# OLD STUFF
+# =======================================================================
+
+ConfigurationDialog.shellTitle = External Tools Configuration
+ConfigurationDialog.dialogTitle = External Tools
+ConfigurationDialog.dialogMessage = Configure an external tool to run a program, batch file, or Ant build file.
+ConfigurationDialog.toolList = &Tools:
+ConfigurationDialog.newButton = &New...
+ConfigurationDialog.editButton = &Edit...
+ConfigurationDialog.removeButton = &Remove
+ConfigurationDialog.upButton = &Up
+ConfigurationDialog.downButton = &Down
+ConfigurationDialog.details = Det&ails:
+ConfigurationDialog.detailMessage = Location: {0}\nArguments: {1}\nDirectory: {2}
+
+EditDialog.newShellTitle = New External Tool
+EditDialog.editShellTitle = Edit External Tool
+EditDialog.dialogTitle = External Tool
+EditDialog.newDialogMessage = Create an external tool to run a program, batch file, or Ant build file.
+EditDialog.editDialogMessage = Edit an external tool to run a program, batch file, or Ant build file.
+EditDialog.howToSelectAntTargets = To choose Ant targets, press the ''Browse Variables'' button and select ''Ant targets''.
+EditDialog.nameLabel = &Name:
+EditDialog.locationLabel = Tool &Location:
+EditDialog.argumentLabel = Tool &Arguments:
+EditDialog.dirLabel = Working &Directory:
+EditDialog.refreshOption = After running, &refresh:
+EditDialog.browseWkspButton1 = Browse &Workspace...
+EditDialog.browseFileSysButton1 = Browse &File System...
+EditDialog.browseVarsButton = Browse &Variables...
+EditDialog.directoryBrowseButton = Browse &Options...
+EditDialog.refreshOptionButton = Browse O&ptions...
+EditDialog.browseWorkspaceTitle = Browse Workspace
+EditDialog.selectTool = &Select the external tool to use:
+EditDialog.selectResource = &Select the resource to use:
+EditDialog.selectContainer = &Select the container to use:
+EditDialog.selectDirectory = &Select the working directory to use:
+EditDialog.selectTargets = &Select the Ant targets to use:
+EditDialog.selectFolder = &Select the folder to use:
+EditDialog.browseVarTitle = Browse Variables
+EditDialog.browseDirTitle = Browse Working Directory Options
+EditDialog.selectVar = &Select a variable to use:
+EditDialog.selectDir = &Select a working directory option:
+EditDialog.dirBrowseWorkspace = Browse workspace
+EditDialog.dirBrowseFileSystem = Browse file system
+EditDialog.varWorkspaceLocLabel = Workspace location
+EditDialog.varProjectLocLabel = Selected resource's project location
+EditDialog.varContainerLocLabel = Selected resource's container location
+EditDialog.varResourceLocLabel = Selected resource location
+EditDialog.varProjectPathLabel = Selected resource's project full path
+EditDialog.varContainerPathLabel = Selected resource's container full path
+EditDialog.varResourcePathLabel = Selected resource full path
+EditDialog.varProjectNameLabel = Selected resource's project name
+EditDialog.varContainerNameLabel = Selected resource's container name
+EditDialog.varResourceNameLabel = Selected resource name
+EditDialog.varProjectXLocLabel = Specific resource's project location
+EditDialog.varContainerXLocLabel = Specific resource's container location
+EditDialog.varResourceXLocLabel = Specific resource location
+EditDialog.varProjectXPathLabel = Specific resource's project full path
+EditDialog.varContainerXPathLabel = Specific resource's container full path
+EditDialog.varResourceXPathLabel = Specific resource full path
+EditDialog.varProjectXNameLabel = Specific resource's project name
+EditDialog.varContainerXNameLabel = Specific resource's container name
+EditDialog.varResourceXNameLabel = Specific resource name
+EditDialog.varBuildTypeNameLabel = Build type
+EditDialog.varAntTargetLabel = Ant targets
+EditDialog.browseProjectTitle = Browse Projects
+EditDialog.selectProject = &Select a project to use:
+EditDialog.noToolName = Enter a name for the tool
+EditDialog.noToolLocation = Enter a location for the tool
+EditDialog.missingToolLocation = Tool location does not exist or is invalid
+EditDialog.missingToolDirectory = Tool working directory does not exist or is invalid
+EditDialog.refreshScopeNone = Nothing
+EditDialog.refreshScopeWorkspace = Workspace
+EditDialog.refreshScopeProject = Current project
+EditDialog.refreshScopeProjectX = Project named {0}
+EditDialog.refreshScopeWorkingSet = Working set named {0}
+EditDialog.browseRefreshTitle = Browse Refresh Scopes
+EditDialog.selectRefresh = &Select the refresh scope to use:
+EditDialog.refreshNothingLabel = Nothing
+EditDialog.refreshWorkspaceLabel = Current workspace
+EditDialog.refreshProjectLabel = Current project
+EditDialog.refreshProjectXLabel = Specific project
+EditDialog.refreshWorkingSetLabel = Specific working set
+EditDialog.showLogLabel = S&how execution log on console
+EditDialog.errorTitle = Edit External Tool Problem
+EditDialog.errorReadAntFile = Problems reading Ant build file: {0}
+EditDialog.noAntTargets = Could not find any targets in Ant build file: {0}
+
+ExternalToolsRegistry.saveStateErrorTitle = Problem Saving External Tool
+ExternalToolsRegistry.saveStateError = Could not write external tool configurations to disk.\n\nPlease try again.
+
+BuilderPropertyPage.description = Add external tools to the build order.
+BuilderPropertyPage.newButton = &New...
+BuilderPropertyPage.editButton = &Edit...
+BuilderPropertyPage.removeButton = &Remove
+BuilderPropertyPage.upButton = &Up
+BuilderPropertyPage.downButton = &Down
+BuilderPropertyPage.statusMessage = Internal error
+BuilderPropertyPage.errorTitle = External Tool Builder Problem
+BuilderPropertyPage.errorMessage = Internal error
+BuilderPropertyPage.invalidBuildTool = Invalid External Tool Builder
+BuilderPropertyPage.missingBuilder = Missing builder ({0})
+
+ExternalToolsAction.configure = &Configure...
+
+LogConsoleDocument.externalTool = External Tool
+
+LogConsoleView.copy = &Copy@Ctrl+C
+LogConsoleView.expandAll = &Expand All
+LogConsoleView.selectAll = Select &All@Ctrl+A
+LogConsoleView.clearOutput = Clear Output
+LogConsoleView.hideOutputStructureTree = Hide Output Structure Tree
+LogConsoleView.showOutputStructureTree = Show Output Structure Tree
+LogConsoleView.showTree = &Show Tree
+LogConsoleView.showSelectedElementOnly = Show Output of Selected Element Only
+LogConsoleView.showCompleteOutput = Show Complete Output
+LogConsoleView.findAction.label = Find/Replace
+
+LogTreeLabelProvider.invalidItemName = Invalid item name
+
+ToolsPreferencePage.errorColor = &Error:
+ToolsPreferencePage.warningColor = &Warning:
+ToolsPreferencePage.infoColor = I&nformation:
+ToolsPreferencePage.verboseColor = Ve&rbose:
+ToolsPreferencePage.debugColor = Deb&ug:
+ToolsPreferencePage.font = Console font setting:
+ToolsPreferencePage.description = Console text color settings.
+
+BuildCanceledException.canceled = Canceled
+
+AntUtil.antFileNotFound = Could not open Ant build file.
+AntUtil.parserConfigError = Internal parser configuration error.
+AntUtil.ioError = Could not read content of Ant build file.
+AntUtil.formatError = Could not parse content of Ant build file.
+AntUtil.invalidAntBuildFile = Invalid content format of Ant build file.
+
+AntAction.runErrorTitle = Run Ant Problem
+AntAction.errorReadAntFile = Problems reading Ant build file: {0}
+AntAction.noAntTargets = Could not find any targets in Ant build file: {0}
+
+AntLaunchWizard.shellTitle = Run Ant
+AntLaunchWizard.dialogTitle = Run
+AntLaunchWizard.dialogDescription = Run an Ant build file
+AntLaunchWizard.runningAnt = Running Ant
+AntLaunchWizard.runAntProblem = A problem occurred executing the Ant file. See the log console for details.
+AntLaunchWizard.runErrorTitle = Run Ant Problem
+AntLaunchWizard.internalAntError = Ant runner internal error
+
+AntLaunchWizardPage.targetLabel = Available &targets:
+AntLaunchWizardPage.argsLabel = &Arguments:
+AntLaunchWizardPage.showLogLabel = S&how execution log in console
+
+AntTargetLabelProvider.defaultTarget = Default
+
+ExternalToolsDialog.External_Tools_1=External Tools
+ExternalToolsDialog.Create,_manage,_and_run_external_tools_2=Create, manage, and run external tools
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/IHelpContextIds.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/IHelpContextIds.java
new file mode 100644
index 0000000..1517fc2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/IHelpContextIds.java
@@ -0,0 +1,58 @@
+package net.sourceforge.phpdt.externaltools.internal.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:
+**********************************************************************/
+
+/**
+ * Help context ids for the external tools.
+ * <p>
+ * This interface contains constants only; it is not intended to be implemented
+ * or extended.
+ * </p>
+ */
+public interface IHelpContextIds {
+	public static final String PREFIX = "net.sourceforge.phpdt.externaltools."; //$NON-NLS-1$
+
+	// Actions
+	public static final String NEW_TOOL_ACTION = PREFIX + "new_tool_action_context"; //$NON-NLS-1$
+	public static final String DUPLICATE_TOOL_ACTION = PREFIX + "duplicate_tool_action_context"; //$NON-NLS-1$
+	public static final String DELETE_TOOL_ACTION = PREFIX + "delete_tool_action_context"; //$NON-NLS-1$
+	public static final String RENAME_TOOL_ACTION = PREFIX + "rename_tool_action_context"; //$NON-NLS-1$
+	public static final String REFRESH_VIEW_ACTION = PREFIX + "refresh_view_action_context"; //$NON-NLS-1$
+	public static final String RUN_TOOL_ACTION = PREFIX + "run_tool_action_context"; //$NON-NLS-1$
+	public static final String RUN_WITH_TOOL_ACTION = PREFIX + "run_with_tool_action_context"; //$NON-NLS-1$
+	public static final String EDIT_TOOL_PROPERTIES_ACTION = PREFIX + "edit_tool_properties_action_context"; //$NON-NLS-1$
+	//public static final String ANT_ACTION = PREFIX + "ant_action_context"; //$NON-NLS-1$
+	
+	// Dialogs
+	public static final String RESOURCE_SELECTION_DIALOG = PREFIX + "resource_selection_dialog_context"; //$NON-NLS-1$
+
+	// Preference Pages
+	//public static final String ANT_PREFERENCE_PAGE = PREFIX + "ant_preference_page_context"; //$NON-NLS-1$
+	public static final String ADD_TASK_DIALOG = PREFIX + "add_task_dialog_context"; //$NON-NLS-1$
+
+	// Property Pages
+	public static final String TOOL_MAIN_PROPERTY_PAGE = PREFIX + "tool_main_property_page_context"; //$NON-NLS-1$
+	public static final String TOOL_OPTION_PROPERTY_PAGE = PREFIX + "tool_option_property_page_context"; //$NON-NLS-1$
+	public static final String TOOL_REFRESH_PROPERTY_PAGE = PREFIX + "tool_refresh_property_page_context"; //$NON-NLS-1$
+	public static final String ANT_TARGETS_PROPERTY_PAGE = PREFIX + "ant_targets_property_page_context"; //$NON-NLS-1$
+	
+	// Views
+	public static final String EXTERNAL_TOOLS_VIEW = PREFIX + "external_tools_view_context"; //$NON-NLS-1$
+
+	// Wizards
+//	public static final String ANT_LAUNCH_WIZARD = PREFIX + "ant_launch_wizard_context"; //$NON-NLS-1$
+	
+	// Wizard Pages
+	public static final String TOOL_MAIN_WIZARD_PAGE = PREFIX + "tool_main_wizard_page_context"; //$NON-NLS-1$
+	public static final String TOOL_OPTION_WIZARD_PAGE = PREFIX + "tool_option_wizard_page_context"; //$NON-NLS-1$
+	public static final String TOOL_REFRESH_WIZARD_PAGE = PREFIX + "tool_refresh_wizard_page_context"; //$NON-NLS-1$
+//	public static final String ANT_TARGETS_WIZARD_PAGE = PREFIX + "ant_targets_wizard_page_context"; //$NON-NLS-1$
+//	public static final String ANT_LAUNCH_WIZARD_PAGE = PREFIX + "ant_launch_wizard_page_context"; //$NON-NLS-1$
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/IPreferenceConstants.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/IPreferenceConstants.java
new file mode 100644
index 0000000..c6b52fb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/IPreferenceConstants.java
@@ -0,0 +1,31 @@
+package net.sourceforge.phpdt.externaltools.internal.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:
+**********************************************************************/
+
+/**
+ * Constants used to identify user preferences.
+ */
+public interface IPreferenceConstants {
+	
+	public static final String PROMPT_FOR_MIGRATION = "externaltools.builders.promptForMigration"; //$NON-NLS-1$
+	
+	public static final String CONSOLE_ERROR_RGB = "externaltools.console.errorColor"; //$NON-NLS-1$
+	public static final String CONSOLE_WARNING_RGB = "externaltools.console.warningColor"; //$NON-NLS-1$
+ 	public static final String CONSOLE_INFO_RGB = "externaltools.console.infoColor"; //$NON-NLS-1$
+ 	public static final String CONSOLE_VERBOSE_RGB = "externaltools.console.verboseColor"; //$NON-NLS-1$
+ 	public static final String CONSOLE_DEBUG_RGB = "externaltools.console.debugColor"; //$NON-NLS-1$
+ 	
+	public static final String ANTVIEW_INCLUDE_ERROR_SEARCH_RESULTS = "externaltools.antview.includeErrorSearchResults"; //$NON-NLS-1$
+	public static final String ANTVIEW_LAST_SEARCH_STRING = "externaltools.antview.lastSearchString"; //$NON-NLS-1$
+	public static final String ANTVIEW_LAST_WORKINGSET_SEARCH_SCOPE = "externaltools.antview.lastSearchScope"; //$NON-NLS-1$
+	public static final String ANTVIEW_USE_WORKINGSET_SEARCH_SCOPE = "externaltools.antview.useWorkingSetSearchScope"; //$NON-NLS-1$
+	
+	public static final String ANT_FIND_BUILD_FILE_NAMES = "ant.findBuildFileNames"; //$NON-NLS-1$
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ToolMessages.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ToolMessages.java
new file mode 100644
index 0000000..c2b9bf7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/ToolMessages.java
@@ -0,0 +1,61 @@
+package net.sourceforge.phpdt.externaltools.internal.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.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Utility class which helps managing messages
+ */
+public final class ToolMessages {
+	private static final String RESOURCE_BUNDLE= "net.sourceforge.phpdt.externaltools.internal.model.messages"; //$NON-NLS-1$
+	private static ResourceBundle bundle = ResourceBundle.getBundle(RESOURCE_BUNDLE);
+	
+	private ToolMessages(){
+		// prevent instantiation of class
+	}
+	
+	/**
+	 * Returns the formatted message for the given key in
+	 * the resource bundle. 
+	 *
+	 * @param key the message name
+	 * @param args the message arguments
+	 * @return the formatted message
+	 */	
+	public static String format(String key, Object[] args) {
+		return MessageFormat.format(getString(key), args);
+	}
+	
+	/**
+	 * Returns the message with the given key in
+	 * the resource bundle. If there isn't any value under
+	 * the given key, the key is returned.
+	 *
+	 * @param key the message name
+	 * @return the message
+	 */	
+	public static String getString(String key) {
+		try {
+			return bundle.getString(key);
+		} catch (MissingResourceException e) {
+			return key;
+		}
+	}
+	
+	/**
+	 * Returns the resource bundle for the plug-in
+	 */
+	public static ResourceBundle getResourceBundle() {
+		return bundle;
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/VariableContextManager.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/VariableContextManager.java
new file mode 100644
index 0000000..686413e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/VariableContextManager.java
@@ -0,0 +1,171 @@
+package net.sourceforge.phpdt.externaltools.internal.model;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import java.util.Map;
+
+import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.ISelectionService;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.externaltools.internal.model.ExternalToolBuilder;
+
+/**
+ * Maintains the context used to expand variables. The context is based on
+ * the selected resource, unless a build is in progress - in which case
+ * the context is based on the project being built..
+ */
+public class VariableContextManager implements IWindowListener, ISelectionListener {
+
+	// singleton
+	private static VariableContextManager fgDefault;
+	
+	private IResource fSelectedResource = null;
+	
+	private boolean fBuilding = false;
+	private IProject fProject = null;
+	private int fKind;
+	
+	private VariableContextManager() {
+		IWorkbench workbench = PlatformUI.getWorkbench();
+		if (workbench != null) { //may be running headless
+			workbench.addWindowListener(this);
+			IWorkbenchWindow activeWindow = workbench.getActiveWorkbenchWindow();
+			if (activeWindow != null) {
+				windowActivated(activeWindow);
+			}
+		} 
+	}
+	
+	/**
+	 * Returns the singleton resource selection manager
+	 * 
+	 * @return VariableContextManager
+	 */
+	public static VariableContextManager getDefault() {
+		if (fgDefault == null) {
+			fgDefault = new VariableContextManager(); 
+		}
+		return fgDefault;
+	}
+	
+	/**
+	 * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
+	 */
+	public void windowActivated(IWorkbenchWindow window) {
+		fSelectedResource = null;
+		ISelectionService service = window.getSelectionService(); 
+		service.addSelectionListener(this);
+		IWorkbenchPage page = window.getActivePage();
+		if (page != null) {
+			IWorkbenchPart part = page.getActivePart();
+			if (part != null) {				
+				ISelection selection = service.getSelection();
+				if (selection != null) {
+					selectionChanged(part, selection);
+				}
+			}
+		}
+	}
+
+	/**
+	 * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
+	 */
+	public void windowClosed(IWorkbenchWindow window) {
+		window.getSelectionService().removeSelectionListener(this);
+	}
+
+	/**
+	 * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
+	 */
+	public void windowDeactivated(IWorkbenchWindow window) {
+		window.getSelectionService().removeSelectionListener(this);
+	}
+
+	/**
+	 * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
+	 */
+	public void windowOpened(IWorkbenchWindow window) {
+	}
+
+	/**
+	 * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
+	 */
+	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+		IResource selectedResource = null;
+		if (selection instanceof IStructuredSelection) {
+			Object result = ((IStructuredSelection)selection).getFirstElement();
+			if (result instanceof IResource) {
+				selectedResource = (IResource) result;
+			} else if (result instanceof IAdaptable) {
+				selectedResource = (IResource)((IAdaptable) result).getAdapter(IResource.class);
+			}
+		}
+		
+		if (selectedResource == null) {
+			// If the active part is an editor, get the file resource used as input.
+			if (part instanceof IEditorPart) {
+				IEditorPart editorPart = (IEditorPart) part;
+				IEditorInput input = editorPart.getEditorInput();
+				selectedResource = (IResource) input.getAdapter(IResource.class);
+			} 
+		}
+		
+		fSelectedResource = selectedResource;
+	}
+	
+	/**
+	 * Returns the active variable context. The context is that of the selected
+	 * resource, or a project being built.
+	 * 
+	 * @return variable context
+	 */
+	public ExpandVariableContext getVariableContext() {
+		if (fBuilding) {
+			return new ExpandVariableContext(fProject, fKind);
+		} else {
+			return new ExpandVariableContext(fSelectedResource);
+		}
+	}
+	
+	/**
+	 * Notification that the given project is being built.
+	 * 
+	 * @param project
+	 * @param kind
+	 * @see ExternalToolBuilder#build(int, Map, IProgressMonitor)
+	 */
+	public void buildStarted(IProject project, int kind) {
+		fBuilding = true;
+		fProject = project;
+		fKind = kind;
+	}
+	
+	/**
+	 * Notification the building the current project has completed.
+	 * @see ExternalToolBuilder#build(int, Map, IProgressMonitor)
+	 */
+	public void buildEnded() {
+		fBuilding = false;
+		fProject= null;
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/messages.properties b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/messages.properties
new file mode 100644
index 0000000..875ed09
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/model/messages.properties
@@ -0,0 +1,332 @@
+# ======================================================================
+# 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:
+# ======================================================================
+
+# =======================================================================
+# Base External Tool
+# =======================================================================
+
+ExternalTool.nameMustContainOneChar = The external tool name must contain at least one letter or number.
+ExternalTool.nameContainsInvalidChar = The external tool name must contain only letters, numbers, hyphens, and spaces.
+
+ToolUtil.dirLocVarBetweenText = The variable for the directory location cannot have any other text before or after itself.
+ToolUtil.dirLocVarFormatWrong = The variable for the directory location is not in a valid format.
+ToolUtil.dirLocVarMissing = The variable named ''{0}'' for the directory location does not exist.
+ToolUtil.dirLocVarExpandFailed = The variable named ''{0}'' for the directory location could not be expanded.
+ToolUtil.fileLocVarBetweenText = The variable for the file location cannot have any other text before or after itself.
+ToolUtil.fileLocVarFormatWrong = The variable for the file location is not in a valid format.
+ToolUtil.fileLocVarMissing = The variable named ''{0}'' for the file location does not exist.
+ToolUtil.fileLocVarExpandFailed = The variable named ''{0}'' for the file location could not be expanded.
+ToolUtil.argumentVarFormatWrong = A variable for the arguments is not in a valid format.
+ToolUtil.argumentVarMissing = The variable named ''{0}'' for the arguments does not exist.
+ToolUtil.argumentVarExpandFailed = The variable named ''{0}'' for the arguments could not be expanded.
+
+ExternalToolRegistry.loadToolFailure = Press the Details button for more information.
+ExternalToolRegistry.fileNotFoundError = Could not find external tool storage file.
+ExternalToolRegistry.ioLoadError = Problems reading external tool storage file.
+ExternalToolRegistry.ioSaveError = Problems writing external tool storage file.
+ExternalToolRegistry.loadErrorTitle = Problem Loading External Tools.
+ExternalToolRegistry.loadErrorMessage = Could not load all external tools.
+ExternalToolRegistry.noToolFilename = External tool filename for storage not specified.
+ExternalToolRegistry.deleteToolFileFailed = Could not delete external tool file ''{0}''.
+
+ExternalToolStorage.deleteErrorTitle = Problem Deleting External Tool.
+ExternalToolStorage.deleteErrorMessage = Could not delete external tool. Refresh list and try again.
+ExternalToolStorage.reloadErrorTitle = Problem Refreshing External Tools
+ExternalToolStorage.reloadErrorMessage = Could not load all external tools.
+ExternalToolStorage.saveErrorTitle = Problem Saving External Tool.
+ExternalToolStorage.saveErrorMessage = Could not save external tool. Please try again.
+
+NewExternalToolAction.text = &New
+NewExternalToolAction.toolTip = New External Tool Wizard
+
+CopyExternalToolAction.text = &Copy
+CopyExternalToolAction.toolTip = Copy External Tool
+
+PasteExternalToolAction.text = &Paste
+PasteExternalToolAction.toolTip = Paste External Tool
+
+DeleteExternalToolAction.text = &Delete
+DeleteExternalToolAction.toolTip = Delete External Tool
+DeleteExternalToolAction.confirmToolDeleteTitle = Confirm External Tool Delete
+DeleteExternalToolAction.confirmToolDeleteMsg = Are you sure want to delete ''{0}''?
+
+RenameExternalToolAction.text = Rena&me
+RenameExternalToolAction.toolTip = Rename External Tool
+
+RefreshViewAction.text = Re&fresh
+RefreshViewAction.toolTip = Refresh External Tool View
+
+RunExternalToolAction.text = R&un
+RunExternalToolAction.toolTip = Run External Tool
+
+RunWithExternalToolAction.text = Run &With...
+RunWithExternalToolAction.toolTip = Prompt for Arguments and Run External Tool
+
+EditExternalToolPropertiesAction.text = P&roperties
+EditExternalToolPropertiesAction.toolTip = Edit External Tool Properties
+
+ExternalToolMainGroup.locationLabel = &Location:
+ExternalToolMainGroup.locationBrowseLabel = B&rowse...
+ExternalToolMainGroup.descriptionLabel = D&escription:
+ExternalToolMainGroup.nameLabel = Na&me:
+ExternalToolMainGroup.workDirLabel = &Working Directory:
+ExternalToolMainGroup.workDirBrowseLabel = Br&owse...
+ExternalToolMainGroup.nameRequired = External tool name cannot be empty.
+ExternalToolMainGroup.nameAlreadyExist = Another external tool exists with the same name.
+ExternalToolMainGroup.locationRequired = External tool location cannot be empty.
+ExternalToolMainGroup.invalidLocation = External tool location does not exist or is invalid.
+ExternalToolMainGroup.invalidWorkDir = External tool working directory does not exist or is invalid.
+
+ExternalToolOptionGroup.captureOutputLabel = &Capture output messages from running tool
+ExternalToolOptionGroup.showConsoleLabel = &Show console when tool is run
+ExternalToolOptionGroup.runBackgroundLabel = &Run tool in background
+ExternalToolOptionGroup.openPerspLabel = &Open perspective when tool is run:
+ExternalToolOptionGroup.argumentLabel = Ar&guments:
+ExternalToolOptionGroup.argumentInstruction = Note: Enclose an argument containing spaces using double-quotes ("). Not\napplicable for variables.
+ExternalToolOptionGroup.argumentVariableLabel = &Variables...
+ExternalToolOptionGroup.promptArgLabel = &Prompt for arguments before running tool
+ExternalToolOptionGroup.showInMenuLabel = S&how in Run > External Tools menu
+ExternalToolOptionGroup.saveDirtyEditorsLabel = Save dirty &editors before running tool
+
+ExternalToolRefreshGroup.refreshLabel = &Refresh resources after running tool
+ExternalToolRefreshGroup.recursiveLabel = Recursively &include sub-folders
+ExternalToolRefreshGroup.scopeLabel = Choose &Scope Variable:
+
+ExternalToolNewWizard.shellTitle = New External Tool
+ExternalToolNewWizard.optionPageTitle = Options
+ExternalToolNewWizard.optionPageDescription = Configure the options when the external tool is run.
+ExternalToolNewWizard.refreshPageTitle = Refresh Scope
+ExternalToolNewWizard.refreshPageDescription = Specify which resources to refresh after the external tool is run.
+
+ExternalToolVariable.componentErrorMessage = Problem displaying UI component of selected variable.
+
+ResourceComponent.selectedResLabel = &Use selected resource
+ResourceComponent.specificResLabel = Us&e specific resource:
+ResourceComponent.selectionRequired = A specific resource must be selected from the list.
+
+RunExternalToolAction.openPerspProblem = Failed to open the perspective.
+RunExternalToolAction.openPerspTitle = Open Perspective Problem
+RunExternalToolAction.runProblem = Could not run the external tool.
+RunExternalToolAction.runErrorTitle = Run Tool Problem
+RunExternalToolAction.internalError = External tool runner internal error
+
+DefaultRunnerContext.runningExternalTool = Running external tool...
+DefaultRunnerContext.invalidLocation = The file does not exist for the external tool named {0}.
+DefaultRunnerContext.invalidDirectory = The working directory does not exist for the external tool named {0}.
+DefaultRunnerContext.refreshResources = Refresh resources...
+DefaultRunnerContext.noToolRunner = The no valid runner provided for the external tool named {0}.
+DefaultRunnerContext.invalidRefreshVarFormat = Invalid refresh scope variable format for the external tool named {0}.
+DefaultRunnerContext.noRefreshVarNamed = Could not find refresh scope variable called ''{1}'' for the external tool named {0}.
+
+ExternalToolMenuDelegate.showView = Show External Tools View
+ExternalToolMenuDelegate.runRecent = Run Last Tool
+ExternalToolMenuDelegate.configure = Configure...
+
+
+# =======================================================================
+# Program External Tool Type
+# =======================================================================
+
+ProgramRunner.runningToolLabel = Running external tool: {0}
+ProgramRunner.internalErrorMessage = Internal error
+ProgramRunner.callingRuntimeExec = Calling runtime exec with:\n
+ProgramRunner.program = Program: {0}\n
+ProgramRunner.argument = Argument: {0}\n
+ProgramRunner.workDir = Working Directory: {0}\n
+
+
+# =======================================================================
+# Ant Build File External Tool Type
+# =======================================================================
+
+AntFileRunner.callingAntRunner = Calling Ant runner with:\n
+AntFileRunner.antFile = Ant build file: {0}\n
+AntFileRunner.argument = Argument: {0}\n
+AntFileRunner.target = Target: {0}\n
+
+AntTargetsGroup.availableTargetsLabel = A&vailable targets:
+AntTargetsGroup.activeTargetsLabel = A&ctive targets:
+AntTargetsGroup.addLabel = >
+AntTargetsGroup.removeLabel = <
+AntTargetsGroup.addAllLabel = >>
+AntTargetsGroup.removeAllLabel = <<
+AntTargetsGroup.descriptionLabel = &Target description:
+AntTargetsGroup.upLabel = U&p
+AntTargetsGroup.downLabel = D&own
+AntTargetsGroup.getTargetsTitle = Problem retrieving targets
+AntTargetsGroup.getTargetsProblem = Could not retrieve targets.
+AntTargetsGroup.runDefaultTargetLabel = R&un default target ({0})
+AntTargetsGroup.runDefaultTargetUnknownLabel = R&un default target
+AntTargetsGroup.showSubTargetsLabel = S&how sub-targets
+
+AntExternalToolNewWizard.antTargetsPageTitle = Ant Targets
+AntExternalToolNewWizard.antTargetsPageDescription = Specify which Ant targets to execute when the external tool is run.
+AntExternalToolNewWizard.promptForArgumentLabel = &Prompt for targets and arguments before running tool
+
+AntOptionGroupPropertyPage.promptForArgumentLabel = &Prompt for targets and arguments before running tool
+
+
+
+# =======================================================================
+# OLD STUFF
+# =======================================================================
+
+ConfigurationDialog.shellTitle = External Tools Configuration
+ConfigurationDialog.dialogTitle = External Tools
+ConfigurationDialog.dialogMessage = Configure an external tool to run a program, batch file, or Ant build file.
+ConfigurationDialog.toolList = &Tools:
+ConfigurationDialog.newButton = &New...
+ConfigurationDialog.editButton = &Edit...
+ConfigurationDialog.removeButton = &Remove
+ConfigurationDialog.upButton = &Up
+ConfigurationDialog.downButton = &Down
+ConfigurationDialog.details = Det&ails:
+ConfigurationDialog.detailMessage = Location: {0}\nArguments: {1}\nDirectory: {2}
+
+EditDialog.newShellTitle = New External Tool
+EditDialog.editShellTitle = Edit External Tool
+EditDialog.dialogTitle = External Tool
+EditDialog.newDialogMessage = Create an external tool to run a program, batch file, or Ant build file.
+EditDialog.editDialogMessage = Edit an external tool to run a program, batch file, or Ant build file.
+EditDialog.howToSelectAntTargets = To choose Ant targets, press the ''Browse Variables'' button and select ''Ant targets''.
+EditDialog.nameLabel = &Name:
+EditDialog.locationLabel = Tool &Location:
+EditDialog.argumentLabel = Tool &Arguments:
+EditDialog.dirLabel = Working &Directory:
+EditDialog.refreshOption = After running, &refresh:
+EditDialog.browseWkspButton1 = Browse &Workspace...
+EditDialog.browseFileSysButton1 = Browse &File System...
+EditDialog.browseVarsButton = Browse &Variables...
+EditDialog.directoryBrowseButton = Browse &Options...
+EditDialog.refreshOptionButton = Browse O&ptions...
+EditDialog.browseWorkspaceTitle = Browse Workspace
+EditDialog.selectTool = &Select the external tool to use:
+EditDialog.selectResource = &Select the resource to use:
+EditDialog.selectContainer = &Select the container to use:
+EditDialog.selectDirectory = &Select the working directory to use:
+EditDialog.selectTargets = &Select the Ant targets to use:
+EditDialog.selectFolder = &Select the folder to use:
+EditDialog.browseVarTitle = Browse Variables
+EditDialog.browseDirTitle = Browse Working Directory Options
+EditDialog.selectVar = &Select a variable to use:
+EditDialog.selectDir = &Select a working directory option:
+EditDialog.dirBrowseWorkspace = Browse workspace
+EditDialog.dirBrowseFileSystem = Browse file system
+EditDialog.varWorkspaceLocLabel = Workspace location
+EditDialog.varProjectLocLabel = Selected resource's project location
+EditDialog.varContainerLocLabel = Selected resource's container location
+EditDialog.varResourceLocLabel = Selected resource location
+EditDialog.varProjectPathLabel = Selected resource's project full path
+EditDialog.varContainerPathLabel = Selected resource's container full path
+EditDialog.varResourcePathLabel = Selected resource full path
+EditDialog.varProjectNameLabel = Selected resource's project name
+EditDialog.varContainerNameLabel = Selected resource's container name
+EditDialog.varResourceNameLabel = Selected resource name
+EditDialog.varProjectXLocLabel = Specific resource's project location
+EditDialog.varContainerXLocLabel = Specific resource's container location
+EditDialog.varResourceXLocLabel = Specific resource location
+EditDialog.varProjectXPathLabel = Specific resource's project full path
+EditDialog.varContainerXPathLabel = Specific resource's container full path
+EditDialog.varResourceXPathLabel = Specific resource full path
+EditDialog.varProjectXNameLabel = Specific resource's project name
+EditDialog.varContainerXNameLabel = Specific resource's container name
+EditDialog.varResourceXNameLabel = Specific resource name
+EditDialog.varBuildTypeNameLabel = Build type
+EditDialog.varAntTargetLabel = Ant targets
+EditDialog.browseProjectTitle = Browse Projects
+EditDialog.selectProject = &Select a project to use:
+EditDialog.noToolName = Enter a name for the tool
+EditDialog.noToolLocation = Enter a location for the tool
+EditDialog.missingToolLocation = Tool location does not exist or is invalid
+EditDialog.missingToolDirectory = Tool working directory does not exist or is invalid
+EditDialog.refreshScopeNone = Nothing
+EditDialog.refreshScopeWorkspace = Workspace
+EditDialog.refreshScopeProject = Current project
+EditDialog.refreshScopeProjectX = Project named {0}
+EditDialog.refreshScopeWorkingSet = Working set named {0}
+EditDialog.browseRefreshTitle = Browse Refresh Scopes
+EditDialog.selectRefresh = &Select the refresh scope to use:
+EditDialog.refreshNothingLabel = Nothing
+EditDialog.refreshWorkspaceLabel = Current workspace
+EditDialog.refreshProjectLabel = Current project
+EditDialog.refreshProjectXLabel = Specific project
+EditDialog.refreshWorkingSetLabel = Specific working set
+EditDialog.showLogLabel = S&how execution log on console
+EditDialog.errorTitle = Edit External Tool Problem
+EditDialog.errorReadAntFile = Problems reading Ant build file: {0}
+EditDialog.noAntTargets = Could not find any targets in Ant build file: {0}
+
+ExternalToolsRegistry.saveStateErrorTitle = Problem Saving External Tool
+ExternalToolsRegistry.saveStateError = Could not write external tool configurations to disk.\n\nPlease try again.
+
+BuilderPropertyPage.description = Add external tools to the build order.
+BuilderPropertyPage.newButton = &New...
+BuilderPropertyPage.editButton = &Edit...
+BuilderPropertyPage.removeButton = &Remove
+BuilderPropertyPage.upButton = &Up
+BuilderPropertyPage.downButton = &Down
+BuilderPropertyPage.statusMessage = Internal error
+BuilderPropertyPage.errorTitle = External Tool Builder Problem
+BuilderPropertyPage.errorMessage = Internal error
+BuilderPropertyPage.invalidBuildTool = Invalid External Tool Builder
+BuilderPropertyPage.missingBuilder = Missing builder ({0})
+
+ExternalToolsAction.configure = &Configure...
+
+LogConsoleDocument.externalTool = External Tool
+
+LogConsoleView.copy = &Copy@Ctrl+C
+LogConsoleView.expandAll = &Expand All
+LogConsoleView.selectAll = Select &All@Ctrl+A
+LogConsoleView.clearOutput = Clear Output
+LogConsoleView.hideOutputStructureTree = Hide Output Structure Tree
+LogConsoleView.showOutputStructureTree = Show Output Structure Tree
+LogConsoleView.showTree = &Show Tree
+LogConsoleView.showSelectedElementOnly = Show Output of Selected Element Only
+LogConsoleView.showCompleteOutput = Show Complete Output
+LogConsoleView.findAction.label = Find/Replace
+
+LogTreeLabelProvider.invalidItemName = Invalid item name
+
+ToolsPreferencePage.errorColor = &Error:
+ToolsPreferencePage.warningColor = &Warning:
+ToolsPreferencePage.infoColor = I&nformation:
+ToolsPreferencePage.verboseColor = Ve&rbose:
+ToolsPreferencePage.debugColor = Deb&ug:
+ToolsPreferencePage.font = Console font setting:
+ToolsPreferencePage.description = Console text color settings.
+
+BuildCanceledException.canceled = Canceled
+
+AntUtil.antFileNotFound = Could not open Ant build file.
+AntUtil.parserConfigError = Internal parser configuration error.
+AntUtil.ioError = Could not read content of Ant build file.
+AntUtil.formatError = Could not parse content of Ant build file.
+AntUtil.invalidAntBuildFile = Invalid content format of Ant build file.
+
+AntAction.runErrorTitle = Run Ant Problem
+AntAction.errorReadAntFile = Problems reading Ant build file: {0}
+AntAction.noAntTargets = Could not find any targets in Ant build file: {0}
+
+AntLaunchWizard.shellTitle = Run Ant
+AntLaunchWizard.dialogTitle = Run
+AntLaunchWizard.dialogDescription = Run an Ant build file
+AntLaunchWizard.runningAnt = Running Ant
+AntLaunchWizard.runAntProblem = A problem occurred executing the Ant file. See the log console for details.
+AntLaunchWizard.runErrorTitle = Run Ant Problem
+AntLaunchWizard.internalAntError = Ant runner internal error
+
+AntLaunchWizardPage.targetLabel = Available &targets:
+AntLaunchWizardPage.argsLabel = &Arguments:
+AntLaunchWizardPage.showLogLabel = S&how execution log in console
+
+AntTargetLabelProvider.defaultTarget = Default
+
+ExternalToolsDialog.External_Tools_1=External Tools
+ExternalToolsDialog.Create,_manage,_and_run_external_tools_2=Create, manage, and run external tools
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/BackgroundResourceRefresher.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/BackgroundResourceRefresher.java
new file mode 100644
index 0000000..3b1136a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/BackgroundResourceRefresher.java
@@ -0,0 +1,107 @@
+package net.sourceforge.phpdt.externaltools.internal.program.launchConfigurations;
+
+/**********************************************************************
+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.lang.reflect.InvocationTargetException;
+
+import net.sourceforge.phpdt.externaltools.launchConfigurations.ExternalToolsUtil;
+import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+
+/**
+ * Refreshes resources as specified by a lanunch configuration, when 
+ * an associated process terminates.
+ */
+public class BackgroundResourceRefresher implements IDebugEventSetListener, Runnable, IRunnableWithProgress  {
+
+	private ExpandVariableContext fContext;
+	private ILaunchConfiguration fConfiguration;
+	private IProcess fProcess;
+	
+	public BackgroundResourceRefresher(ILaunchConfiguration configuration, IProcess process, ExpandVariableContext context) {
+		fConfiguration = configuration;
+		fProcess = process;
+		fContext = context;
+	}
+	
+	/**
+	 * If the process has already terminated, resource refreshing is done
+	 * immediately in the current thread. Otherwise, refreshing is done when the
+	 * process terminates.
+	 */
+	public void startBackgroundRefresh() {
+		synchronized (fProcess) {
+			if (fProcess.isTerminated()) {
+				refresh();
+			} else {
+				DebugPlugin.getDefault().addDebugEventListener(this);
+			}
+		}
+	}
+	
+	/**
+	 * @see org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse.debug.core.DebugEvent)
+	 */
+	public void handleDebugEvents(DebugEvent[] events) {
+		for (int i = 0; i < events.length; i++) {
+			DebugEvent event = events[i];
+			if (event.getSource() == fProcess && event.getKind() == DebugEvent.TERMINATE) {
+				DebugPlugin.getDefault().removeDebugEventListener(this);
+				refresh();
+				break;
+			}
+		}
+	}
+	
+	/**
+	 * Submits a runnable to do the refresh
+	 */
+	protected void refresh() {
+		PHPeclipsePlugin.getStandardDisplay().asyncExec(this);
+	}
+	
+	/** 
+	 * Creates a dialog to run the refresh
+	 * 
+	 * @see java.lang.Runnable#run()
+	 */
+	public void run() {
+		ProgressMonitorDialog dialog = new ProgressMonitorDialog(PHPeclipsePlugin.getStandardDisplay().getActiveShell());
+		try {
+			dialog.run(true, true, this);
+		} catch (InvocationTargetException e) {
+			// report the exception
+		} catch (InterruptedException e) {
+		}
+	}
+	/**
+	 * Peforms the refresh
+	 * 
+	 * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+		try {
+			ExternalToolsUtil.refreshResources(fConfiguration, fContext, monitor);
+		} catch (CoreException e) {
+			throw new InvocationTargetException(e);
+		}				
+	}
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramBuilderTabGroup.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramBuilderTabGroup.java
new file mode 100644
index 0000000..46c3b6d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramBuilderTabGroup.java
@@ -0,0 +1,29 @@
+package net.sourceforge.phpdt.externaltools.internal.program.launchConfigurations;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import net.sourceforge.phpdt.externaltools.launchConfigurations.ExternalToolsRefreshTab;
+
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+
+public class ProgramBuilderTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+	/**
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTabGroup#createTabs(org.eclipse.debug.ui.ILaunchConfigurationDialog, java.lang.String)
+	 */
+	public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+		ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
+			new ProgramMainTab(),
+			new ExternalToolsRefreshTab(),
+		};
+		setTabs(tabs);
+	}
+	
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramLaunchDelegate.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramLaunchDelegate.java
new file mode 100644
index 0000000..7df974e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramLaunchDelegate.java
@@ -0,0 +1,138 @@
+package net.sourceforge.phpdt.externaltools.internal.program.launchConfigurations;
+
+/**********************************************************************
+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.io.File;
+
+import net.sourceforge.phpdt.externaltools.launchConfigurations.ExternalToolsUtil;
+import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.model.ILaunchConfigurationDelegate;
+import org.eclipse.debug.core.model.IProcess;
+
+/**
+ * Launch delegate for a program.
+ */
+public class ProgramLaunchDelegate implements ILaunchConfigurationDelegate {
+
+	/**
+	 * Constructor for ProgramLaunchDelegate.
+	 */
+	public ProgramLaunchDelegate() {
+		super();
+	}
+
+	/**
+	 * @see org.eclipse.debug.core.model.ILaunchConfigurationDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
+		
+		if (monitor.isCanceled()) {
+			return;
+		}
+		
+		// get variable context
+		ExpandVariableContext resourceContext = ExternalToolsUtil.getVariableContext();
+
+		if (monitor.isCanceled()) {
+			return;
+		}
+		
+		// resolve location
+		IPath location = ExternalToolsUtil.getLocation(configuration, resourceContext);
+		
+		if (monitor.isCanceled()) {
+			return;
+		}		
+		
+		// resolve working directory
+		IPath workingDirectory = ExternalToolsUtil.getWorkingDirectory(configuration, resourceContext);
+		
+		if (monitor.isCanceled()) {
+			return;
+		}
+		
+		// resolve arguments
+		String[] arguments = ExternalToolsUtil.getArguments(configuration, resourceContext);
+		
+		if (monitor.isCanceled()) {
+			return;
+		}
+		
+		int cmdLineLength = 1;
+		if (arguments != null) {
+			cmdLineLength += arguments.length;
+		}
+		String[] cmdLine = new String[cmdLineLength];
+		cmdLine[0] = location.toOSString();
+		if (arguments != null) {
+			System.arraycopy(arguments, 0, cmdLine, 1, arguments.length);
+		}
+		
+		File workingDir = null;
+		if (workingDirectory != null) {
+			workingDir = workingDirectory.toFile();
+		}
+		
+		if (monitor.isCanceled()) {
+			return;
+		}
+				
+		Process p = DebugPlugin.exec(cmdLine, workingDir);
+		IProcess process = null;
+		if (p != null) {
+			process = DebugPlugin.newProcess(launch, p, location.toOSString());
+		}
+		process.setAttribute(IProcess.ATTR_CMDLINE, renderCommandLine(cmdLine));
+		
+		if (ExternalToolsUtil.isBackground(configuration)) {
+			// refresh resources after process finishes
+			if (ExternalToolsUtil.getRefreshScope(configuration) != null) {
+				BackgroundResourceRefresher refresher = new BackgroundResourceRefresher(configuration, process, resourceContext);
+				refresher.startBackgroundRefresh();
+			}				
+		} else {
+			// wait for process to exit
+			while (!process.isTerminated()) {
+				try {
+					if (monitor.isCanceled()) {
+						process.terminate();
+						break;
+					}
+					Thread.sleep(50);
+				} catch (InterruptedException e) {
+				}
+			}
+			
+			// refresh resources
+			ExternalToolsUtil.refreshResources(configuration, resourceContext, monitor);
+		}
+		
+	
+	}
+	
+	protected static String renderCommandLine(String[] commandLine) {
+		if (commandLine.length < 1)
+			return ""; //$NON-NLS-1$
+		StringBuffer buf= new StringBuffer(commandLine[0]);
+		for (int i= 1; i < commandLine.length; i++) {
+			buf.append(' ');
+			buf.append(commandLine[i]);
+		}	
+		return buf.toString();
+	}	
+	
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramMainTab.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramMainTab.java
new file mode 100644
index 0000000..6217692
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramMainTab.java
@@ -0,0 +1,34 @@
+package net.sourceforge.phpdt.externaltools.internal.program.launchConfigurations;
+
+import net.sourceforge.phpdt.externaltools.internal.ui.FileSelectionDialog;
+import net.sourceforge.phpdt.externaltools.launchConfigurations.ExternalToolsMainTab;
+import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+import net.sourceforge.phpdt.externaltools.model.ToolUtil;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+public class ProgramMainTab extends ExternalToolsMainTab {
+
+	/**
+	 * Prompts the user for a program location within the workspace and sets the
+	 * location as a String containing the workspace_loc variable or
+	 * <code>null</code> if no location was obtained from the user.
+	 */
+	protected void handleWorkspaceLocationButtonSelected() {
+		FileSelectionDialog dialog;
+		dialog = new FileSelectionDialog(getShell(), ResourcesPlugin.getWorkspace().getRoot(), "&Select a program");
+		dialog.open();
+		IFile file = dialog.getResult();
+		if (file == null) {
+			return;
+		}
+		StringBuffer buf = new StringBuffer();
+		ToolUtil.buildVariableTag(IExternalToolConstants.VAR_WORKSPACE_LOC, file.getFullPath().toString(), buf);
+		String text= buf.toString();
+		if (text != null) {
+			locationField.setText(text);
+		}
+	}
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramTabGroup.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramTabGroup.java
new file mode 100644
index 0000000..19d81a9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/program/launchConfigurations/ProgramTabGroup.java
@@ -0,0 +1,30 @@
+package net.sourceforge.phpdt.externaltools.internal.program.launchConfigurations;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import net.sourceforge.phpdt.externaltools.launchConfigurations.ExternalToolsRefreshTab;
+
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+
+public class ProgramTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+	/**
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTabGroup#createTabs(org.eclipse.debug.ui.ILaunchConfigurationDialog, java.lang.String)
+	 */
+	public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+		ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
+			new ProgramMainTab(),
+			new ExternalToolsRefreshTab(),
+			new CommonTab()
+		};
+		setTabs(tabs);
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ArgumentVariable.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ArgumentVariable.java
new file mode 100644
index 0000000..e3fc7b2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ArgumentVariable.java
@@ -0,0 +1,66 @@
+package net.sourceforge.phpdt.externaltools.internal.registry;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
+import net.sourceforge.phpdt.externaltools.variable.IVariableTextExpander;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+
+/**
+ * Represents the variable for the argument
+ */
+public final class ArgumentVariable extends ExternalToolVariable {
+	private static final DefaultTextExpander defaultExpander = new DefaultTextExpander();
+	
+	private IVariableTextExpander expander = null;
+
+	/**
+	 * Creates an argument variable
+	 * 
+	 * @param tag the variable tag
+	 * @param description a short description of what the variable will expand to
+	 * @param element the configuration element
+	 */
+	/*package*/ ArgumentVariable(String tag, String description, IConfigurationElement element) {
+		super(tag, description, element);
+	}
+
+	/**
+	 * Returns the object that can expand the variable
+	 * as text.
+	 */
+	public IVariableTextExpander getExpander() {
+		if (expander == null) {
+			try {
+				expander = (IVariableTextExpander) createObject(ExternalToolVariableRegistry.TAG_EXPANDER_CLASS);
+			} catch (ClassCastException exception) {
+			}
+			if (expander == null) {
+				expander = defaultExpander;
+			}
+		}
+		return expander;
+	}
+
+
+	/**
+	 * Default variable text expander implementation which does
+	 * not expand variables, but just returns <code>null</code>.
+	 */	
+	private static final class DefaultTextExpander implements IVariableTextExpander {
+		/* (non-Javadoc)
+		 * Method declared on IVariableTextExpander.
+		 */
+		public String getText(String varTag, String varValue, ExpandVariableContext context) {
+			return null;
+		}
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ArgumentVariableRegistry.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ArgumentVariableRegistry.java
new file mode 100644
index 0000000..5e02868
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ArgumentVariableRegistry.java
@@ -0,0 +1,51 @@
+package net.sourceforge.phpdt.externaltools.internal.registry;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+
+/**
+ * Registry of all available argument variables.
+ */
+public class ArgumentVariableRegistry extends ExternalToolVariableRegistry {
+
+	/**
+	 * Creates the registry and loads the variables.
+	 */
+	public ArgumentVariableRegistry() {
+		super(IExternalToolConstants.EXTENSION_POINT_ARGUMENT_VARIABLES);
+	}
+
+	/**
+	 * Returns the argument variable for the given tag
+	 * or <code>null</code> if none.
+	 */
+	public ArgumentVariable getArgumentVariable(String tag) {
+		return (ArgumentVariable) findVariable(tag);
+	}
+	
+	/**
+	 * Returns the list of argument variables in the registry.
+	 */
+	public ArgumentVariable[] getArgumentVariables() {
+		ArgumentVariable[] results = new ArgumentVariable[getVariableCount()];
+		copyVariables(results);
+		return results;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on ExternalToolVariableRegistry.
+	 */
+	protected ExternalToolVariable newVariable(String tag, String description, IConfigurationElement element) {
+		return new ArgumentVariable(tag, description, element);
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ExternalToolMigration.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ExternalToolMigration.java
new file mode 100644
index 0000000..115ea90
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ExternalToolMigration.java
@@ -0,0 +1,363 @@
+package net.sourceforge.phpdt.externaltools.internal.registry;
+
+/**********************************************************************
+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.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+import net.sourceforge.phpdt.externaltools.model.ToolUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.WorkbenchException;
+import org.eclipse.ui.XMLMemento;
+
+/**
+ * Responsible reading an old external tool format and creating
+ * and migrating it to create a new external tool.
+ */
+public final class ExternalToolMigration {
+	private static final String SEPERATOR = ";"; //$NON-NLS-1$	
+	private static final String STATE_FILE_NAME_OLD = "oldexternaltools.xml"; //$NON-NLS-1$
+	private static final String STATE_FILE_NAME = "externaltools.xml"; //$NON-NLS-1$
+	private static final String TAG_EXTERNALTOOLS = "externaltools"; //$NON-NLS-1$
+	private static final String TAG_TOOL = "tool"; //$NON-NLS-1$
+	private static final String TAG_ENTRY = "entry"; //$NON-NLS-1$
+	//private static final String TAG_KEY = "key"; //$NON-NLS-1$
+	private static final String TAG_VALUE = "value"; //$NON-NLS-1$
+
+	/*
+	 * Ant tags
+	 */
+	//public static final String RUN_TARGETS_ATTRIBUTE = IExternalToolConstants.TOOL_TYPE_ANT_BUILD + ".runTargets"; //$NON-NLS-1$;
+
+	/*
+	 * 2.0 External Tool Tags
+	 */
+	private static final String TAG_TOOL_TYPE = "!{tool_type}"; //$NON-NLS-1$
+	private static final String TAG_TOOL_NAME = "!{tool_name}"; //$NON-NLS-1$
+	private static final String TAG_TOOL_LOCATION = "!{tool_loc}"; //$NON-NLS-1$
+	private static final String TAG_TOOL_ARGUMENTS = "!{tool_args}"; //$NON-NLS-1$
+	private static final String TAG_TOOL_DIRECTORY = "!{tool_dir}"; //$NON-NLS-1$
+	private static final String TAG_TOOL_REFRESH = "!{tool_refresh}"; //$NON-NLS-1$
+	private static final String TAG_TOOL_SHOW_LOG = "!{tool_show_log}"; //$NON-NLS-1$
+	private static final String TAG_TOOL_BUILD_TYPES = "!{tool_build_types}"; //$NON-NLS-1$
+	private static final String TAG_TOOL_BLOCK = "!{tool_block}"; //$NON-NLS-1$
+
+	// Known kind of tools
+	private static final String TOOL_TYPE_PROGRAM = "net.sourceforge.phpdt.externaltools.type.program"; //$NON-NLS-1$
+	//private static final String TOOL_TYPE_ANT = "org.eclipse.ui.externaltools.type.ant"; //$NON-NLS-1$
+
+	/*
+	 * 2.1 External Tool Keys
+	 */
+	private static final String TAG_EXTERNAL_TOOL = "externalTool"; //$NON-NLS-1$
+	private static final String TAG_TYPE = "type"; //$NON-NLS-1$
+	private static final String TAG_NAME = "name"; //$NON-NLS-1$
+	private static final String TAG_LOCATION = "location"; //$NON-NLS-1$
+	private static final String TAG_WORK_DIR = "workDirectory"; //$NON-NLS-1$
+	private static final String TAG_CAPTURE_OUTPUT = "captureOutput"; //$NON-NLS-1$
+	private static final String TAG_SHOW_CONSOLE = "showConsole"; //$NON-NLS-1$
+	private static final String TAG_RUN_BKGRND = "runInBackground"; //$NON-NLS-1$
+	private static final String TAG_OPEN_PERSP = "openPerspective"; //$NON-NLS-1$
+	private static final String TAG_PROMPT_ARGS = "promptForArguments"; //$NON-NLS-1$
+	private static final String TAG_SHOW_MENU = "showInMenu"; //$NON-NLS-1$
+	private static final String TAG_SAVE_DIRTY = "saveDirtyEditors"; //$NON-NLS-1$
+	private static final String TAG_ARGS = "arguments"; //$NON-NLS-1$
+	private static final String TAG_REFRESH_SCOPE = "refreshScope"; //$NON-NLS-1$
+	private static final String TAG_REFRESH_RECURSIVE = "refreshRecursive"; //$NON-NLS-1$
+	private static final String TAG_RUN_BUILD_KINDS = "runForBuildKinds"; //$NON-NLS-1$
+	private static final String TAG_EXTRA_ATTR = "extraAttribute"; //$NON-NLS-1$
+	private static final String TAG_KEY = "key"; //$NON-NLS-1$
+	private static final String TAG_VERSION = "version"; //$NON-NLS-1$
+
+	private static final String BUILD_TYPE_SEPARATOR = ","; //$NON-NLS-1$
+	private static final String EXTRA_ATTR_SEPARATOR = "="; //$NON-NLS-1$
+
+	private static final String VERSION_21 = "2.1"; //$NON-NLS-1$;
+
+	private static final String TRUE = "true"; //$NON-NLS-1$
+	private static final String FALSE = "false"; //$NON-NLS-1$
+
+	/**
+	 * Allows no instances.
+	 */
+	private ExternalToolMigration() {
+		super();
+	}
+
+	/**
+	 * Loads the external tools from storage and
+	 * adds them to the registry.
+	 */
+	/*package*/
+	// This method is not called. It is left here in case 
+	// we decide to do tool migration in the future
+	private static void readInOldTools() {
+		readIn20Tools();
+		readIn21Tools();
+	}
+
+	private static void readIn21Tools() {
+	}
+
+	public static void readIn20Tools() {
+		boolean migrationSuccessful = true;
+		IPath path = PHPeclipsePlugin.getDefault().getStateLocation();
+		File file = path.append(STATE_FILE_NAME).toFile();
+		if (!file.exists())
+			return;
+
+		InputStreamReader reader = null;
+		try {
+			FileInputStream input = new FileInputStream(file);
+			reader = new InputStreamReader(input, "utf-8"); //$NON-NLS-1$
+			XMLMemento memento = XMLMemento.createReadRoot(reader);
+
+			// Get the external tool children element
+			IMemento[] tools = memento.getChildren(TAG_TOOL);
+			for (int i = 0; i < tools.length; i++) {
+				HashMap args = new HashMap();
+				IMemento[] entries = tools[i].getChildren(TAG_ENTRY);
+				for (int j = 0; j < entries.length; j++) {
+					String key = entries[j].getString(TAG_KEY);
+					if (key != null) {
+						String value = entries[j].getTextData();
+						args.put(key, value);
+					}
+				}
+				ILaunchConfigurationWorkingCopy config = configFromArgumentMap(args);
+				if (config != null) {
+					try {
+						config.doSave();
+					} catch (CoreException e) {
+						// TODO: Decide what to do when saving fails.
+					}
+				}
+			}
+		} catch (FileNotFoundException e) {
+			// Silently ignore this...
+		} catch (IOException e) {
+			ExternalToolsPlugin.getDefault().log("File I/O error with reading old external tools.", e); 
+			migrationSuccessful = false;
+		} catch (WorkbenchException e) {
+      PHPeclipsePlugin.getDefault().getLog().log(e.getStatus());
+			System.err.println("Error reading old external tools. See .log file for more details"); 
+			migrationSuccessful = false;
+		} finally {
+			if (reader != null) {
+				try {
+					reader.close();
+				} catch (IOException e) {
+					ExternalToolsPlugin.getDefault().log("Unable to close external tool old state reader.", e); 
+				}
+			}
+		}
+
+		if (migrationSuccessful) {
+			if (!file.renameTo(path.append(STATE_FILE_NAME_OLD).toFile())) {
+				ExternalToolsPlugin.getDefault().log("Unable to rename old external tool state file. Please rename externaltools.xml to oldexternaltools.xml manually.", null); 
+				System.err.println("Unable to rename old external tool state file. Please rename externaltools.xml to oldexternaltools.xml manually."); 
+			}
+		}
+	}
+
+	/**
+	 * Returns a  launch configuration working copy from the argument map or
+	 * <code>null</code> if the given map cannot be interpreted as a 2.0 or 2.1
+	 * branch external tool. The returned working copy will be unsaved and its
+	 * location will be set to the metadata area.
+	 */
+	public static ILaunchConfigurationWorkingCopy configFromArgumentMap(Map args) {
+		String version = (String) args.get(TAG_VERSION);
+		if (VERSION_21.equals(version)) {
+			return configFrom21ArgumentMap(args);
+		}
+		return configFrom20ArgumentMap(args);
+	}
+
+	public static ILaunchConfigurationWorkingCopy configFrom21ArgumentMap(Map commandArgs) {
+		String name = (String) commandArgs.get(TAG_NAME);
+		String type = (String) commandArgs.get(TAG_TYPE);
+		
+		ILaunchConfigurationWorkingCopy config = newConfig(type, name);
+		if (config == null) {
+			return null;
+		}
+		
+		config.setAttribute(IExternalToolConstants.ATTR_LOCATION, (String) commandArgs.get(TAG_LOCATION));
+		config.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, (String) commandArgs.get(TAG_WORK_DIR));
+		config.setAttribute(IExternalToolConstants.ATTR_CAPTURE_OUTPUT, TRUE.equals((String) commandArgs.get(TAG_CAPTURE_OUTPUT)));
+		config.setAttribute(IExternalToolConstants.ATTR_SHOW_CONSOLE, TRUE.equals((String) commandArgs.get(TAG_SHOW_CONSOLE)));
+		config.setAttribute(IExternalToolConstants.ATTR_RUN_IN_BACKGROUND, TRUE.equals((String) commandArgs.get(TAG_RUN_BKGRND)));
+		config.setAttribute(IExternalToolConstants.ATTR_PROMPT_FOR_ARGUMENTS, TRUE.equals((String) commandArgs.get(TAG_PROMPT_ARGS)));
+		config.setAttribute(IExternalToolConstants.ATTR_REFRESH_SCOPE, (String) commandArgs.get(TAG_REFRESH_SCOPE));
+		config.setAttribute(IExternalToolConstants.ATTR_REFRESH_RECURSIVE, TRUE.equals((String) commandArgs.get(TAG_REFRESH_RECURSIVE)));
+
+		config.setAttribute(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, (String) commandArgs.get(TAG_RUN_BUILD_KINDS));
+		
+		String args = (String) commandArgs.get(TAG_ARGS);
+		if (args != null) {
+			config.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, args);
+		}
+
+		String extraAttributes = (String) commandArgs.get(TAG_EXTRA_ATTR);
+		if (extraAttributes != null) {
+			StringTokenizer tokenizer = new StringTokenizer(extraAttributes, EXTRA_ATTR_SEPARATOR);
+			while (tokenizer.hasMoreTokens()) {
+				String key = tokenizer.nextToken();
+				if (!tokenizer.hasMoreTokens())
+					break;
+				String value = tokenizer.nextToken();
+//				if (key.equals(RUN_TARGETS_ATTRIBUTE)) {
+//					// 2.1 implementation only defined 1 "extra attribute"
+//					config.setAttribute(IExternalToolConstants.ATTR_ANT_TARGETS, value);
+//				}
+			}
+		}
+		return config;
+	}
+
+	/**
+	 * Creates an external tool from the map.
+	 */
+	public static ILaunchConfigurationWorkingCopy configFrom20ArgumentMap(Map args) {
+		// Update the type...
+		String type = (String) args.get(TAG_TOOL_TYPE);
+//		if (TOOL_TYPE_ANT.equals(type))
+//			type = IExternalToolConstants.TOOL_TYPE_ANT_BUILD;
+//		else
+			type = IExternalToolConstants.TOOL_TYPE_PROGRAM;
+
+		String name = (String) args.get(TAG_TOOL_NAME);
+		
+		ILaunchConfigurationWorkingCopy config = newConfig(type, name);
+		if (config == null) {
+			return null;
+		}
+
+		// Update the location...
+		String location = (String) args.get(TAG_TOOL_LOCATION);
+		if (location != null) {
+			ToolUtil.VariableDefinition varDef = ToolUtil.extractVariableTag(location, 0);
+			if (IExternalToolConstants.VAR_WORKSPACE_LOC.equals(varDef.name)) {
+				location = ToolUtil.buildVariableTag(IExternalToolConstants.VAR_RESOURCE_LOC, varDef.argument);
+			}
+			config.setAttribute(IExternalToolConstants.ATTR_LOCATION, location);
+		}
+
+		// Update the refresh scope...
+		String refresh = (String) args.get(TAG_TOOL_REFRESH);
+		if (refresh != null) {
+			ToolUtil.VariableDefinition varDef = ToolUtil.extractVariableTag(refresh, 0);
+			if ("none".equals(varDef.name)) { //$NON-NLS-1$
+				refresh = null;
+			}
+			config.setAttribute(IExternalToolConstants.ATTR_REFRESH_SCOPE, refresh);
+		}
+
+		// Update the arguments
+		String arguments = (String) args.get(TAG_TOOL_ARGUMENTS);
+		String targetNames = null;
+		if (arguments != null) {
+			int start = 0;
+			ArrayList targets = new ArrayList();
+			StringBuffer buffer = new StringBuffer();
+			ToolUtil.VariableDefinition varDef = ToolUtil.extractVariableTag(arguments, start);
+			while (varDef.end != -1) {
+				if ("ant_target".equals(varDef.name) && varDef.argument != null) { //$NON-NLS-1$
+					targets.add(varDef.argument);
+					buffer.append(arguments.substring(start, varDef.start));
+				} else {
+					buffer.append(arguments.substring(start, varDef.end));
+				}
+				start = varDef.end;
+				varDef = ToolUtil.extractVariableTag(arguments, start);
+			}
+			buffer.append(arguments.substring(start, arguments.length()));
+			arguments = buffer.toString();
+
+			buffer.setLength(0);
+			for (int i = 0; i < targets.size(); i++) {
+				String target = (String) targets.get(i);
+				if (target != null && target.length() > 0) {
+					buffer.append(target);
+					buffer.append(","); //$NON-NLS-1$
+				}
+			}
+			targetNames = buffer.toString();
+		}
+		if (targetNames != null && targetNames.length() > 0) {
+			config.setAttribute(IExternalToolConstants.ATTR_ANT_TARGETS, targetNames);
+		}
+
+		// Collect the rest of the information
+		config.setAttribute(IExternalToolConstants.ATTR_SHOW_CONSOLE, TRUE.equals((String) args.get(TAG_TOOL_SHOW_LOG)));
+		config.setAttribute(IExternalToolConstants.ATTR_CAPTURE_OUTPUT, TRUE.equals((String) args.get(TAG_TOOL_SHOW_LOG)));
+		config.setAttribute(IExternalToolConstants.ATTR_RUN_IN_BACKGROUND, FALSE.equals((String) args.get(TAG_TOOL_BLOCK)));
+		config.setAttribute(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, (String) args.get(TAG_TOOL_BUILD_TYPES));
+		config.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, arguments);
+		config.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, (String) args.get(TAG_TOOL_DIRECTORY));
+		return config;
+	}
+
+	/**
+	 * Returns a new working copy with the given external tool name and external
+	 * tool type or <code>null</code> if no config could be created.
+	 */
+	private static ILaunchConfigurationWorkingCopy newConfig(String type, String name) {
+		if (type == null || name == null) {
+			return null;
+		}
+		ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
+		ILaunchConfigurationType configType;
+//		if (IExternalToolConstants.TOOL_TYPE_ANT_BUILD.equals(type)) {
+//			configType = manager.getLaunchConfigurationType(IExternalToolConstants.ID_ANT_BUILDER_LAUNCH_CONFIGURATION_TYPE);
+//		} else 
+		if (IExternalToolConstants.TOOL_TYPE_PROGRAM.equals(type)) {
+			configType = manager.getLaunchConfigurationType(IExternalToolConstants.ID_PROGRAM_BUILDER_LAUNCH_CONFIGURATION_TYPE);
+		} else {
+			return null;
+		}
+		try {
+			return configType.newInstance(null, name);
+		} catch (CoreException e) {
+			return null;
+		}
+	}
+	
+	/**
+	 * Returns the tool name extracted from the given command argument map.
+	 * Extraction is attempted using 2.0 and 2.1 external tool formats.
+	 */
+	public static String getNameFromCommandArgs(Map commandArgs) {
+		String name= (String) commandArgs.get(TAG_NAME);
+		if (name == null) {
+			name= (String) commandArgs.get(TAG_TOOL_NAME);
+		}
+		return name;
+	}
+	
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ExternalToolVariable.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ExternalToolVariable.java
new file mode 100644
index 0000000..6fbbefb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ExternalToolVariable.java
@@ -0,0 +1,156 @@
+package net.sourceforge.phpdt.externaltools.internal.registry;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.group.IGroupDialogPage;
+import net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsModelMessages;
+import net.sourceforge.phpdt.externaltools.variable.IVariableComponent;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.jface.resource.JFaceColors;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Abtract representation of the different variables.
+ */
+public abstract class ExternalToolVariable {
+	private static final IVariableComponent defaultComponent = new DefaultVariableComponent(false);
+	
+	private String tag;
+	private String description;
+	private IConfigurationElement element;
+
+	/**
+	 * Creates an variable definition
+	 * 
+	 * @param tag the variable tag
+	 * @param description a short description of what the variable will expand to
+	 * @param element the configuration element
+	 */
+	/*package*/ ExternalToolVariable(String tag, String description, IConfigurationElement element) {
+		super();
+		this.tag = tag;
+		this.description = description;
+		this.element = element;
+	}
+	
+	/**
+	 * Creates an instance of the class specified by
+	 * the given element attribute name. Can return
+	 * <code>null</code> if none or if problems creating
+	 * the instance.
+	 */
+	protected final Object createObject(String attributeName) {
+		try {
+			return element.createExecutableExtension(attributeName);
+		} catch (CoreException e) {
+      PHPeclipsePlugin.getDefault().getLog().log(e.getStatus());
+			return null;
+		}
+	}
+	
+	/**
+	 * Returns the component class to allow
+	 * visual editing of the variable's value.
+	 */
+	public final IVariableComponent getComponent() {
+		String className = element.getAttribute(ExternalToolVariableRegistry.TAG_COMPONENT_CLASS);
+		if (className == null || className.trim().length() == 0)
+			return defaultComponent;
+			
+		Object component = createObject(ExternalToolVariableRegistry.TAG_COMPONENT_CLASS);
+		if (component == null)
+			return new DefaultVariableComponent(true);
+		else
+			return (IVariableComponent)component;
+	}
+	
+	/**
+	 * Returns the variable's description
+	 */
+	public final String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Returns the variable's tag
+	 */
+	public final String getTag() {
+		return tag;
+	}
+
+
+	/**
+	 * Default variable component implementation which does not
+	 * allow variable value editing visually.
+	 */	
+	private static final class DefaultVariableComponent implements IVariableComponent {
+		private boolean showError = false;
+		private Label message = null;
+		
+		public DefaultVariableComponent(boolean showError) {
+			super();
+			this.showError = showError;
+		}
+		
+		/* (non-Javadoc)
+		 * Method declared on IVariableComponent.
+		 */
+		public Control getControl() {
+			return message;
+		}
+				
+		/* (non-Javadoc)
+		 * Method declared on IVariableComponent.
+		 */
+		public void createContents(Composite parent, String varTag, IGroupDialogPage page) {
+			if (showError) {
+				message = new Label(parent, SWT.NONE);
+				GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+				message.setLayoutData(data);
+				message.setFont(parent.getFont());
+				message.setText(ExternalToolsModelMessages.getString("ExternalToolVariable.componentErrorMessage")); //$NON-NLS-1$
+				message.setForeground(JFaceColors.getErrorText(message.getDisplay()));
+			}
+		}
+		
+		/* (non-Javadoc)
+		 * Method declared on IVariableComponent.
+		 */
+		public String getVariableValue() {
+			return null;
+		}
+		
+		/* (non-Javadoc)
+		 * Method declared on IVariableComponent.
+		 */
+		public boolean isValid() {
+			return true;
+		}
+		
+		/* (non-Javadoc)
+		 * Method declared on IVariableComponent.
+		 */
+		public void setVariableValue(String varValue) {
+		}
+
+		/* (non-Javadoc)
+		 * Method declared on IVariableComponent.
+		 */
+		public void validate() {
+		}
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ExternalToolVariableRegistry.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ExternalToolVariableRegistry.java
new file mode 100644
index 0000000..d1b6b90
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/ExternalToolVariableRegistry.java
@@ -0,0 +1,137 @@
+package net.sourceforge.phpdt.externaltools.internal.registry;
+
+/**********************************************************************
+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.HashMap;
+
+import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+import net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * General registry reader for external tool variables.
+ */
+public abstract class ExternalToolVariableRegistry {
+	// Format of the variable extension points
+	// <extension point="org.eclipse.ui.externalTools.***Variables>
+	//		<variable
+	//			tag={string}
+	//			description={string}
+	//			componentClass={string:IVariableComponent}
+	//			expanderClass={string:IVariable***Expander}>
+	//		</variable>
+	// </extension>
+	//
+	
+	/**
+	 * Element and attribute tags of a variable extension.
+	 */
+	/*package*/ static final String TAG_VARIABLE = "variable"; //$NON-NLS-1$
+	/*package*/ static final String TAG_TAG = "tag"; //$NON-NLS-1$
+	/*package*/ static final String TAG_DESCRIPTION = "description"; //$NON-NLS-1$
+	/*package*/ static final String TAG_COMPONENT_CLASS = "componentClass"; //$NON-NLS-1$
+	/*package*/ static final String TAG_EXPANDER_CLASS = "expanderClass"; //$NON-NLS-1$
+
+
+	/**
+	 * Table of variables where the key is the variable tag
+	 * and the value is the corresponding variable.
+	 */
+	private HashMap variables;
+	
+	/**
+	 * The extension point id to read the variables from
+	 */
+	private String extensionPointId;
+	
+	/**
+	 * The 
+	/**
+	 * Creates a new registry and loads the variables.
+	 */
+	public ExternalToolVariableRegistry(String extensionPointId) {
+		super();
+		this.extensionPointId = extensionPointId;
+		loadVariables();
+	}
+	
+	/**
+	 * Returns the variables in the registry
+	 */
+	protected final void copyVariables(Object[] results) {
+		variables.values().toArray(results);
+	}
+
+	/**
+	 * Returns the variable for the specified tag, or
+	 * <code>null</code> if none found.
+	 */
+	protected final ExternalToolVariable findVariable(String tag) {
+		return (ExternalToolVariable) variables.get(tag);
+	}
+
+	/**
+	 * Returns the number of variables in the registry.
+	 */
+	public final int getVariableCount() {
+		return variables.size();
+	}
+	
+	/**
+	 * Load the available variables
+	 */
+	private void loadVariables() {
+		variables = new HashMap();
+		IExtensionRegistry registry= Platform.getExtensionRegistry();
+//		IPluginRegistry registry = Platform.getPluginRegistry();
+		IExtensionPoint point = registry.getExtensionPoint(IExternalToolConstants.PLUGIN_ID, extensionPointId);
+		if (point != null) {
+			IExtension[] extensions = point.getExtensions();
+			for (int i = 0; i < extensions.length; i++) {
+				IConfigurationElement[] elements = extensions[i].getConfigurationElements();
+				for (int j = 0; j < elements.length; j++) {
+					IConfigurationElement element = elements[j];
+					if (element.getName().equals(TAG_VARIABLE)) {
+						String tag = element.getAttribute(TAG_TAG);
+						String description = element.getAttribute(TAG_DESCRIPTION);
+						String className = element.getAttribute(TAG_EXPANDER_CLASS);
+						
+						boolean valid = true;
+						if (tag == null || tag.length() == 0) {
+							valid = false;
+							ExternalToolsPlugin.getDefault().log("Missing tag attribute value for variable element.", null); //$NON-NLS-1$
+						}
+						if (description == null || description.length() == 0) {
+							valid = false;
+							ExternalToolsPlugin.getDefault().log("Missing description attribute value for variable element.", null); //$NON-NLS-1$
+						}
+						if (className == null || className.length() == 0) {
+							valid = false;
+							ExternalToolsPlugin.getDefault().log("Missing expander class attribute value for variable element.", null); //$NON-NLS-1$
+						}
+
+						if (valid)
+							variables.put(tag, newVariable(tag, description, element));
+					}
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Creates a new variable from the specified information.
+	 */
+	protected abstract ExternalToolVariable newVariable(String tag, String description, IConfigurationElement element);
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/PathLocationVariable.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/PathLocationVariable.java
new file mode 100644
index 0000000..4385da3
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/PathLocationVariable.java
@@ -0,0 +1,63 @@
+package net.sourceforge.phpdt.externaltools.internal.registry;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
+import net.sourceforge.phpdt.externaltools.variable.IVariableLocationExpander;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Represents the variable for the path location
+ */
+public final class PathLocationVariable extends ExternalToolVariable {
+	private static final DefaultLocationExpander defaultExpander = new DefaultLocationExpander();
+	
+	private IVariableLocationExpander expander = null;
+
+	/**
+	 * Creates a path location variable
+	 * 
+	 * @param tag the variable tag
+	 * @param description a short description of what the variable will expand to
+	 * @param element the configuration element
+	 */
+	/*package*/ PathLocationVariable(String tag, String description, IConfigurationElement element) {
+		super(tag, description, element);
+	}
+
+	/**
+	 * Returns the object that can expand the variable
+	 * into a path location.
+	 */
+	public IVariableLocationExpander getExpander() {
+		if (expander == null) {
+			expander = (IVariableLocationExpander) createObject(ExternalToolVariableRegistry.TAG_EXPANDER_CLASS);
+			if (expander == null)
+				expander = defaultExpander;
+		}
+		return expander;
+	}
+
+
+	/**
+	 * Default variable location implementation which does 
+	 * not expand variables, but just returns <code>null</code>.
+	 */	
+	private static final class DefaultLocationExpander implements IVariableLocationExpander {
+		/* (non-Javadoc)
+		 * Method declared on IVariableLocationExpander.
+		 */
+		public IPath getPath(String varTag, String varValue, ExpandVariableContext context) {
+			return null;
+		}
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/PathLocationVariableRegistry.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/PathLocationVariableRegistry.java
new file mode 100644
index 0000000..1a2fa3e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/PathLocationVariableRegistry.java
@@ -0,0 +1,49 @@
+package net.sourceforge.phpdt.externaltools.internal.registry;
+
+/**********************************************************************
+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.IConfigurationElement;
+
+/**
+ * Registry of all available path location variables.
+ */
+public class PathLocationVariableRegistry extends ExternalToolVariableRegistry {
+
+	/**
+	 * Creates the registry and loads the variables.
+	 */
+	public PathLocationVariableRegistry(String extensionPointId) {
+		super(extensionPointId);
+	}
+
+	/**
+	 * Returns the path location variable for the given tag
+	 * or <code>null</code> if none.
+	 */
+	public PathLocationVariable getPathLocationVariable(String tag) {
+		return (PathLocationVariable) findVariable(tag);
+	}
+	
+	/**
+	 * Returns the list of path location variables in the registry.
+	 */
+	public PathLocationVariable[] getPathLocationVariables() {
+		PathLocationVariable[] results = new PathLocationVariable[getVariableCount()];
+		copyVariables(results);
+		return results;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on ExternalToolVariableRegistry.
+	 */
+	protected ExternalToolVariable newVariable(String tag, String description, IConfigurationElement element) {
+		return new PathLocationVariable(tag, description, element);
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/RefreshScopeVariable.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/RefreshScopeVariable.java
new file mode 100644
index 0000000..ea634ec
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/RefreshScopeVariable.java
@@ -0,0 +1,63 @@
+package net.sourceforge.phpdt.externaltools.internal.registry;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
+import net.sourceforge.phpdt.externaltools.variable.IVariableResourceExpander;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IConfigurationElement;
+
+/**
+ * Represents the variable for a refresh scope.
+ */
+public final class RefreshScopeVariable extends ExternalToolVariable {
+	private static final DefaultResourceExpander defaultExpander = new DefaultResourceExpander();
+	
+	private IVariableResourceExpander expander = null;
+
+	/**
+	 * Creates a refresh scope variable
+	 * 
+	 * @param tag the variable tag
+	 * @param description a short description of what the variable will expand to
+	 * @param element the configuration element
+	 */
+	/*package*/ RefreshScopeVariable(String tag, String description, IConfigurationElement element) {
+		super(tag, description, element);
+	}
+
+	/**
+	 * Returns the object that can expand the variable
+	 * as resources.
+	 */
+	public IVariableResourceExpander getExpander() {
+		if (expander == null) {
+			expander = (IVariableResourceExpander) createObject(ExternalToolVariableRegistry.TAG_EXPANDER_CLASS);
+			if (expander == null)
+				expander = defaultExpander;
+		}
+		return expander;
+	}
+
+
+	/**
+	 * Default variable resource expander implementation which does
+	 * not expand variables, but just returns <code>null</code>.
+	 */	
+	private static final class DefaultResourceExpander implements IVariableResourceExpander {
+		/* (non-Javadoc)
+		 * Method declared on IVariableResourceExpander.
+		 */
+		public IResource[] getResources(String varTag, String varValue, ExpandVariableContext context) {
+			return null;
+		}
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/RefreshScopeVariableRegistry.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/RefreshScopeVariableRegistry.java
new file mode 100644
index 0000000..d0b3d99
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/registry/RefreshScopeVariableRegistry.java
@@ -0,0 +1,51 @@
+package net.sourceforge.phpdt.externaltools.internal.registry;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+
+/**
+ * Registry of all available refresh scope variables.
+ */
+public class RefreshScopeVariableRegistry extends ExternalToolVariableRegistry {
+
+	/**
+	 * Creates the registry and loads the variables.
+	 */
+	public RefreshScopeVariableRegistry() {
+		super(IExternalToolConstants.EXTENSION_POINT_REFRESH_VARIABLES);
+	}
+
+	/**
+	 * Returns the refresh scope variable for the given tag
+	 * or <code>null</code> if none.
+	 */
+	public RefreshScopeVariable getRefreshVariable(String tag) {
+		return (RefreshScopeVariable) findVariable(tag);
+	}
+	
+	/**
+	 * Returns the list of refresh scope variables in the registry.
+	 */
+	public RefreshScopeVariable[] getRefreshVariables() {
+		RefreshScopeVariable[] results = new RefreshScopeVariable[getVariableCount()];
+		copyVariables(results);
+		return results;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on ExternalToolVariableRegistry.
+	 */
+	protected ExternalToolVariable newVariable(String tag, String description, IConfigurationElement element) {
+		return new RefreshScopeVariable(tag, description, element);
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/ExternalToolsContentProvider.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/ExternalToolsContentProvider.java
new file mode 100644
index 0000000..1227293
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/ExternalToolsContentProvider.java
@@ -0,0 +1,64 @@
+package net.sourceforge.phpdt.externaltools.internal.ui;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Content provider that maintains a generic list of objects which are shown in
+ * a table viewer.
+ */
+public class ExternalToolsContentProvider implements IStructuredContentProvider {
+	protected List elements = new ArrayList();
+	protected TableViewer viewer;
+
+	public void add(Object o) {
+		if (elements.contains(o)) {
+			return;
+		}
+		elements.add(o);
+		viewer.add(o);
+	}
+
+	public void dispose() {
+	}
+
+	public Object[] getElements(Object inputElement) {
+		return (Object[]) elements.toArray(new Object[elements.size()]);
+	}
+
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		this.viewer = (TableViewer) viewer;
+		elements.clear();
+		if (newInput != null) {
+			if (newInput instanceof List) {
+				elements.addAll((List) newInput);
+			} else {
+				elements.addAll(Arrays.asList((Object[]) newInput));
+			}
+		}
+	}
+
+	public void remove(Object o) {
+		elements.remove(o);
+		viewer.remove(o);
+	}
+	
+	public void remove(IStructuredSelection selection) {
+		Object[] array= selection.toArray();
+		elements.removeAll(Arrays.asList(array));
+		viewer.remove(array);
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/FileSelectionDialog.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/FileSelectionDialog.java
new file mode 100644
index 0000000..01f95f9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/FileSelectionDialog.java
@@ -0,0 +1,210 @@
+package net.sourceforge.phpdt.externaltools.internal.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.externaltools.model.StringMatcher;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+/**
+ * Dialog for selecting a file in the workspace. Derived from 
+ * org.eclipse.ui.dialogs.ResourceSelectionDialog
+ */
+public class FileSelectionDialog extends MessageDialog {
+	// the root element to populate the viewer with
+	private IAdaptable					root;
+
+	// the visual selection widget group
+	private TreeAndListGroup	selectionGroup;
+	// constants
+	private final static int			SIZING_SELECTION_WIDGET_WIDTH = 400;
+	private final static int			SIZING_SELECTION_WIDGET_HEIGHT = 300;
+	/**
+	 * The file selected by the user.
+	 */
+	private IFile result= null;
+	/**
+	 * String matcher used to filter content
+	 */
+	private StringMatcher stringMatcher= null;
+/**
+ * Creates a resource selection dialog rooted at the given element.
+ *
+ * @param parentShell the parent shell
+ * @param rootElement the root element to populate this dialog with
+ * @param message the message to be displayed at the top of this dialog, or
+ *    <code>null</code> to display a default message
+ */
+public FileSelectionDialog(Shell parentShell, IAdaptable rootElement, String message) {
+	super(parentShell, "Add Build File", null, message, MessageDialog.NONE, new String[] {"Ok", "Cancel"}, 0);
+	root = rootElement;
+	setShellStyle(getShellStyle() | SWT.RESIZE);
+}
+/**
+ * Limits the files displayed in this dialog to files matching the given
+ * pattern. The string can be a filename or a regular expression containing
+ * '*' for any series of characters or '?' for any single character.
+ * 
+ * @param pattern a pattern used to filter the displayed files or
+ * <code>null</code> to display all files. If a pattern is supplied, only files
+ * whose names match the given pattern will be available for selection.
+ * @param ignoreCase if true, case is ignored. If the pattern argument is
+ * <code>null</code>, this argument is ignored.
+ */
+public void setFileFilter(String pattern, boolean ignoreCase) {
+	if (pattern != null) {
+		stringMatcher= new StringMatcher(pattern, ignoreCase, false);
+	} else {
+		stringMatcher= null;
+	}
+}
+/* (non-Javadoc)
+ * Method declared in Window.
+ */
+protected void configureShell(Shell shell) {
+	super.configureShell(shell);
+	//WorkbenchHelp.setHelp(shell, IHelpContextIds.RESOURCE_SELECTION_DIALOG);
+}
+
+protected void createButtonsForButtonBar(Composite parent) {
+	super.createButtonsForButtonBar(parent);
+	initializeDialog();
+}
+/* (non-Javadoc)
+ * Method declared on Dialog.
+ */
+protected Control createDialogArea(Composite parent) {
+	// page group
+	Composite composite = (Composite) super.createDialogArea(parent);
+
+	//create the input element, which has the root resource
+	//as its only child
+
+	selectionGroup =
+		new TreeAndListGroup(
+			composite,
+			root,
+			getResourceProvider(IResource.FOLDER | IResource.PROJECT | IResource.ROOT),
+			new WorkbenchLabelProvider(),
+			getResourceProvider(IResource.FILE),
+			new WorkbenchLabelProvider(),
+			SWT.NONE,
+			// since this page has no other significantly-sized
+			// widgets we need to hardcode the combined widget's
+			// size, otherwise it will open too small
+			SIZING_SELECTION_WIDGET_WIDTH,
+			SIZING_SELECTION_WIDGET_HEIGHT);
+
+	composite.addControlListener(new ControlListener() {
+		public void controlMoved(ControlEvent e) {};
+		public void controlResized(ControlEvent e) {
+			//Also try and reset the size of the columns as appropriate
+			TableColumn[] columns = selectionGroup.getListTable().getColumns();
+			for (int i = 0; i < columns.length; i++) {
+				columns[i].pack();
+			}
+		}
+	});
+
+	return composite;
+}
+/**
+ * Returns a content provider for <code>IResource</code>s that returns
+ * only children of the given resource type.
+ */
+private ITreeContentProvider getResourceProvider(final int resourceType) {
+	return new WorkbenchContentProvider() {
+		public Object[] getChildren(Object o) {
+			if (o instanceof IContainer) {
+				IResource[] members = null;
+				try {
+					members = ((IContainer)o).members();
+					List accessibleMembers= new ArrayList(members.length);
+					for (int i = 0; i < members.length; i++) {
+						IResource resource = members[i];
+						if (resource.isAccessible()) {
+							accessibleMembers.add(resource);
+						}
+					}
+					members= (IResource[])accessibleMembers.toArray(new IResource[accessibleMembers.size()]);
+				} catch (CoreException e) {
+					//just return an empty set of children
+					return new Object[0];
+				}
+
+				//filter out the desired resource types
+				ArrayList results = new ArrayList();
+				for (int i = 0; i < members.length; i++) {
+					//And the test bits with the resource types to see if they are what we want
+					if ((members[i].getType() & resourceType) > 0) {
+						if (members[i].getType() == IResource.FILE &&
+								stringMatcher != null &&
+								!stringMatcher.match(members[i].getName())) {
+							continue;
+						}
+						results.add(members[i]);
+					}
+				}
+				return results.toArray();
+			} else {
+				return new Object[0];
+			}
+		}
+	};
+}
+/**
+ * Initializes this dialog's controls.
+ */
+private void initializeDialog() {
+	selectionGroup.addSelectionChangedListener(new ISelectionChangedListener() {
+		public void selectionChanged(SelectionChangedEvent event) {
+			getOkButton().setEnabled(!selectionGroup.getListTableSelection().isEmpty());
+		}
+	});
+
+	getOkButton().setEnabled(false);
+}
+
+/**
+ * Returns this dialog's OK button.
+ */
+protected Button getOkButton() {
+	return getButton(0);
+}
+/**
+ * Returns the file the user chose or <code>null</code> if none.
+ */
+public IFile getResult() {
+	return result;
+}
+
+protected void buttonPressed(int buttonId) {
+	if (buttonId == 0) {
+		Object resource= selectionGroup.getListTableSelection().getFirstElement();
+		if (resource instanceof IFile) {
+			result = (IFile) resource;
+		}
+	}
+	super.buttonPressed(buttonId);
+}
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/IExternalToolsUIConstants.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/IExternalToolsUIConstants.java
new file mode 100644
index 0000000..10b049e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/IExternalToolsUIConstants.java
@@ -0,0 +1,39 @@
+package net.sourceforge.phpdt.externaltools.internal.ui;
+
+/**********************************************************************
+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
+**********************************************************************/
+
+import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+
+
+public interface IExternalToolsUIConstants {
+	
+	// Action images
+	public static final String IMG_REMOVE= IExternalToolConstants.PLUGIN_ID + ".remove"; //$NON-NLS-1$
+	public static final String IMG_MOVE_UP = IExternalToolConstants.PLUGIN_ID + ".moveUp"; //$NON-NLS-1$
+	public static final String IMG_MOVE_DOWN = IExternalToolConstants.PLUGIN_ID + ".moveDown"; //$NON-NLS-1$
+	public static final String IMG_ACTIVATE = IExternalToolConstants.PLUGIN_ID + ".activate"; //$NON-NLS-1$
+	public static final String IMG_DEACTIVATE = IExternalToolConstants.PLUGIN_ID + ".deactivate"; //$NON-NLS-1$
+	public static final String IMG_REMOVE_ALL= IExternalToolConstants.PLUGIN_ID + ".removeAll"; //$NON-NLS-1$
+	public static final String IMG_ADD= IExternalToolConstants.PLUGIN_ID + ".add"; //$NON-NLS-1$
+	public static final String IMG_RUN= IExternalToolConstants.PLUGIN_ID + ".run"; //$NON-NLS-1$
+	public static final String IMG_SEARCH= IExternalToolConstants.PLUGIN_ID + ".search"; //$NON-NLS-1$
+	public static final String IMG_GO_TO_FILE= IExternalToolConstants.PLUGIN_ID + ".goToFile"; //$NON-NLS-1$
+	
+	// Label images
+//	public static final String IMG_ANT_PROJECT= IExternalToolConstants.PLUGIN_ID + ".antProject"; //$NON-NLS-1$
+//	public static final String IMG_ANT_PROJECT_ERROR = IExternalToolConstants.PLUGIN_ID + ".antProjectError"; //$NON-NLS-1$
+//	public static final String IMG_ANT_TARGET= IExternalToolConstants.PLUGIN_ID + ".antTarget"; //$NON-NLS-1$
+//	public static final String IMG_ANT_TARGET_ERROR = IExternalToolConstants.PLUGIN_ID + ".antTargetError"; //$NON-NLS-1$
+//	public static final String IMG_ANT_TARGET_ELEMENTS= IExternalToolConstants.PLUGIN_ID + ".antTargetElements"; //$NON-NLS-1$
+//	public static final String IMG_ANT_TARGET_ELEMENT= IExternalToolConstants.PLUGIN_ID + ".antTargetElement"; //$NON-NLS-1$
+
+	public static final String DIALOGSTORE_LASTEXTJAR= IExternalToolConstants.PLUGIN_ID + ".lastextjar"; //$NON-NLS-1$
+	public static final String DIALOGSTORE_LASTEXTFILE= IExternalToolConstants.PLUGIN_ID + ".lastextfile"; //$NON-NLS-1$
+	public static final String DIALOGSTORE_LASTFOLDER= IExternalToolConstants.PLUGIN_ID + ".lastfolder"; //$NON-NLS-1$
+	public static final String DIALOGSTORE_LASTANTHOME= IExternalToolConstants.PLUGIN_ID + ".lastanthome"; //$NON-NLS-1$
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/MessageDialogWithToggle.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/MessageDialogWithToggle.java
new file mode 100644
index 0000000..959db60
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/MessageDialogWithToggle.java
@@ -0,0 +1,209 @@
+package net.sourceforge.phpdt.externaltools.internal.ui;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * An message dialog which allows the user to set a boolean preference.
+ * 
+ * This is typically used to set a preference that determines if the dialog
+ * should be shown in the future
+ */
+public class MessageDialogWithToggle extends MessageDialog {
+	
+	/**
+	 * The preference key which is set by the toggle button.
+	 * This key must be a boolean preference in the preference store.
+	 */
+	private String fPreferenceKey = null;
+	/**
+	 * The message displayed to the user, with the toggle button
+	 */
+	private String fToggleMessage = null;
+	private Button fToggleButton = null;
+	/**
+	 * The preference store which will be affected by the toggle button
+	 */
+	IPreferenceStore fStore = null;
+
+	public MessageDialogWithToggle(Shell parentShell, String dialogTitle, Image image, String message, int dialogImageType, String[] dialogButtonLabels, int defaultIndex, String preferenceKey, String toggleMessage, IPreferenceStore store) {
+		super(parentShell, dialogTitle, image, message, dialogImageType, dialogButtonLabels, defaultIndex);
+		fStore = store;
+		fPreferenceKey = preferenceKey;
+		fToggleMessage = toggleMessage;
+	}
+	
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogArea = (Composite) super.createDialogArea(parent);
+		fToggleButton = createCheckButton(dialogArea, fToggleMessage);
+		getToggleButton().setSelection(fStore.getBoolean(fPreferenceKey));
+		return dialogArea;
+	}
+
+	/**
+	 * Creates a button with the given label and sets the default
+	 * configuration data.
+	 */
+	protected Button createCheckButton(Composite parent, String label) {
+		Button button= new Button(parent, SWT.CHECK | SWT.LEFT);
+		button.setText(label);
+
+		GridData data = new GridData(SWT.NONE);
+		data.horizontalSpan= 2;
+		data.horizontalAlignment= GridData.CENTER;
+		button.setLayoutData(data);
+		button.setFont(parent.getFont());
+
+		return button;
+	}
+
+	/**
+	 * When the OK button is pressed, store the preference.
+	 * 
+	 * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
+	 */
+	protected void buttonPressed(int id) {
+		if (id == IDialogConstants.OK_ID) {  // was the OK button pressed?
+			storePreference();
+		}
+		super.buttonPressed(id);
+	}
+
+	/**
+	 * Store the preference based on the user's selection
+	 */
+	protected void storePreference() {
+		fStore.setValue(fPreferenceKey, getToggleButton().getSelection());
+	}
+
+	/**
+	 * Returns the button used to toggle the dialog preference
+	 * 
+	 * @return Button the preference toggle button
+	 */
+	protected Button getToggleButton() {
+		return fToggleButton;
+	}
+	
+	/**
+	 * Convenience method to open a simple confirm (OK/Cancel) dialog.
+	 *
+	 * @param parent the parent shell of the dialog, or <code>null</code> if none
+	 * @param title the dialog's title, or <code>null</code> if none
+	 * @param message the message
+	 * @return <code>true</code> if the user presses the OK button,
+	 *    <code>false</code> otherwise
+	 */
+	public static boolean openConfirm(Shell parent, String title, String message, String preferenceKey, String toggleMessage, IPreferenceStore store) {
+		MessageDialogWithToggle dialog = new MessageDialogWithToggle(
+			parent,
+			title,
+			null,	// accept the default window icon
+			message,
+			QUESTION,
+			new String[] {IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL},
+			0,		// OK is the default
+			preferenceKey,
+			toggleMessage,
+			store);
+		return dialog.open() == 0;
+	}
+	/**
+	 * Convenience method to open a standard error dialog.
+	 *
+	 * @param parent the parent shell of the dialog, or <code>null</code> if none
+	 * @param title the dialog's title, or <code>null</code> if none
+	 * @param message the message
+	 */
+	public static void openError(Shell parent, String title, String message, String preferenceKey, String toggleMessage, IPreferenceStore store) {
+		MessageDialogWithToggle dialog = new MessageDialogWithToggle(
+			parent,
+			title,
+			null,	// accept the default window icon
+			message,
+			ERROR,
+			new String[] {IDialogConstants.OK_LABEL},
+			0,		// ok is the default
+			preferenceKey,
+			toggleMessage,
+			store);
+		dialog.open();
+	}
+	/**
+	 * Convenience method to open a standard information dialog.
+	 *
+	 * @param parent the parent shell of the dialog, or <code>null</code> if none
+	 * @param title the dialog's title, or <code>null</code> if none
+	 * @param message the message
+	 */
+	public static void openInformation(
+		Shell parent,
+		String title,
+		String message, String preferenceKey, String toggleMessage, IPreferenceStore store) {
+			MessageDialogWithToggle dialog =
+				new MessageDialogWithToggle(parent, title, null, // accept the default window icon
+		message, INFORMATION, new String[] { IDialogConstants.OK_LABEL }, 0,		// ok is the default 
+		preferenceKey, toggleMessage, store);
+		dialog.open();
+	}
+	/**
+	 * Convenience method to open a simple Yes/No question dialog.
+	 *
+	 * @param parent the parent shell of the dialog, or <code>null</code> if none
+	 * @param title the dialog's title, or <code>null</code> if none
+	 * @param message the message
+	 * @return <code>true</code> if the user presses the OK button,
+	 *    <code>false</code> otherwise
+	 */
+	public static boolean openQuestion(Shell parent, String title, String message, String preferenceKey, String toggleMessage, IPreferenceStore store) {
+		MessageDialogWithToggle dialog = new MessageDialogWithToggle(
+			parent,
+			title,
+			null,	// accept the default window icon
+			message,
+			QUESTION,
+			new String[] {IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL},
+			0,		// yes is the default
+			preferenceKey,
+			toggleMessage,
+			store);
+		return dialog.open() == 0;
+	}
+	/**
+	 * Convenience method to open a standard warning dialog.
+	 *
+	 * @param parent the parent shell of the dialog, or <code>null</code> if none
+	 * @param title the dialog's title, or <code>null</code> if none
+	 * @param message the message
+	 */
+	public static void openWarning(Shell parent, String title, String message, String preferenceKey, String toggleMessage, IPreferenceStore store) {
+		MessageDialogWithToggle dialog = new MessageDialogWithToggle(
+			parent,
+			title,
+			null,	// accept the default window icon
+			message,
+			WARNING,
+			new String[] {IDialogConstants.OK_LABEL},
+			0,		// ok is the default
+			preferenceKey,
+			toggleMessage,
+			store);
+		dialog.open();
+	}
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/MessageLine.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/MessageLine.java
new file mode 100644
index 0000000..b724f3b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/MessageLine.java
@@ -0,0 +1,92 @@
+package net.sourceforge.phpdt.externaltools.internal.ui;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * A message line displaying a status.
+ */
+public class MessageLine extends CLabel {
+
+	private static final RGB ERROR_BACKGROUND_RGB = new RGB(230, 226, 221);
+
+	private Color fNormalMsgAreaBackground;
+	private Color fErrorMsgAreaBackground;
+
+	/**
+	 * Creates a new message line as a child of the given parent.
+	 */
+	public MessageLine(Composite parent) {
+		this(parent, SWT.LEFT);
+	}
+
+	/**
+	 * Creates a new message line as a child of the parent and with the given SWT stylebits.
+	 */
+	public MessageLine(Composite parent, int style) {
+		super(parent, style);
+		fNormalMsgAreaBackground= getBackground();
+		fErrorMsgAreaBackground= null;
+	}
+
+
+	private Image findImage(IStatus status) {
+		if (status.isOK()) {
+			return null;
+		} else if (status.matches(IStatus.ERROR)) {
+			return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
+		} else if (status.matches(IStatus.WARNING)) {
+			return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_WARN_TSK);
+		} else if (status.matches(IStatus.INFO)) {
+			return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_INFO_TSK);
+		}
+		return null;
+	}
+
+	/**
+	 * Sets the message and image to the given status.
+	 * <code>null</code> is a valid argument and will set the empty text and no image
+	 */
+	public void setErrorStatus(IStatus status) {
+		if (status != null) {
+			String message= status.getMessage();
+			if (message != null && message.length() > 0) {
+				setText(message);
+				setImage(findImage(status));
+				if (fErrorMsgAreaBackground == null) {
+					fErrorMsgAreaBackground= new Color(getDisplay(), ERROR_BACKGROUND_RGB);
+				}
+				setBackground(fErrorMsgAreaBackground);
+				return;
+			}
+		}
+		setText(""); //$NON-NLS-1$
+		setImage(null);
+		setBackground(fNormalMsgAreaBackground);
+	}
+
+	/*
+	 * @see Widget#dispose()
+	 */
+	public void dispose() {
+		if (fErrorMsgAreaBackground != null) {
+			fErrorMsgAreaBackground.dispose();
+			fErrorMsgAreaBackground= null;
+		}
+		super.dispose();
+	}
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/StatusDialog.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/StatusDialog.java
new file mode 100644
index 0000000..5b19da3
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/StatusDialog.java
@@ -0,0 +1,163 @@
+package net.sourceforge.phpdt.externaltools.internal.ui;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * An abstract base class for dialogs with a status bar and ok/cancel buttons.
+ * The status message must be passed over as StatusInfo object and can be
+ * an error, warning or ok. The OK button is enabled or disabled depending
+ * on the status.
+ */
+public abstract class StatusDialog extends Dialog {
+
+	private Button fOkButton;
+	private MessageLine fStatusLine;
+	private IStatus fLastStatus;
+	private String fTitle;
+	private Image fImage;
+
+	private boolean fStatusLineAboveButtons;
+
+	/**
+	 * Creates an instane of a status dialog.
+	 */
+	public StatusDialog(Shell parent) {
+		super(parent);
+		fStatusLineAboveButtons= false;
+		fLastStatus= new StatusInfo();
+	}
+
+	/**
+	 * Specifies whether status line appears to the left of the buttons (default)
+	 * or above them.
+	 *
+	 * @param aboveButtons if <code>true</code> status line is placed above buttons; if
+	 * 	<code>false</code> to the right
+	 */
+	public void setStatusLineAboveButtons(boolean aboveButtons) {
+		fStatusLineAboveButtons= aboveButtons;
+	}
+
+	/**
+	 * Update the dialog's status line to reflect the given status.
+	 * It is save to call this method before the dialog has been opened.
+	 */
+	protected void updateStatus(IStatus status) {
+		fLastStatus= status;
+		if (fStatusLine != null && !fStatusLine.isDisposed()) {
+			updateButtonsEnableState(status);
+			fStatusLine.setErrorStatus(status);
+		}
+	}
+
+	/**
+	 * Returns the last status.
+	 */
+	public IStatus getStatus() {
+		return fLastStatus;
+	}
+
+	/**
+	 * Updates the status of the ok button to reflect the given status.
+	 * Subclasses may override this method to update additional buttons.
+	 * @param status the status.
+	 */
+	protected void updateButtonsEnableState(IStatus status) {
+		if (fOkButton != null && !fOkButton.isDisposed())
+			fOkButton.setEnabled(!status.matches(IStatus.ERROR));
+	}
+
+	/*
+	 * @see Window#create(Shell)
+	 */
+	protected void configureShell(Shell shell) {
+		super.configureShell(shell);
+		if (fTitle != null)
+			shell.setText(fTitle);
+	}
+
+	/*
+	 * @see Window#create()
+	 */
+	public void create() {
+		super.create();
+		if (fLastStatus != null) {
+			// policy: dialogs are not allowed to come up with an error message
+			if (fLastStatus.matches(IStatus.ERROR)) {
+				StatusInfo status= new StatusInfo();
+				status.setError(""); //$NON-NLS-1$
+				fLastStatus= status;
+			}
+			updateStatus(fLastStatus);
+		}
+	}
+
+	/*
+	 * @see Dialog#createButtonsForButtonBar(Composite)
+	 */
+	protected void createButtonsForButtonBar(Composite parent) {
+		fOkButton= createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+
+	/*
+	 * @see Dialog#createButtonBar(Composite)
+	 */
+	protected Control createButtonBar(Composite parent) {
+		Composite composite= new Composite(parent, SWT.NULL);
+		GridLayout layout= new GridLayout();
+		layout.numColumns= 1;
+		layout.marginHeight= 0;
+		layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		fStatusLine= new MessageLine(composite);
+		fStatusLine.setAlignment(SWT.LEFT);
+		fStatusLine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		fStatusLine.setErrorStatus(null); //$NON-NLS-1$
+
+		super.createButtonBar(composite);
+		return composite;
+	}
+
+	/**
+	 * Sets the title for this dialog.
+	 * @param title the title.
+	 */
+	public void setTitle(String title) {
+		fTitle= title != null ? title : ""; //$NON-NLS-1$
+		Shell shell= getShell();
+		if ((shell != null) && !shell.isDisposed())
+			shell.setText(fTitle);
+	}
+
+	/**
+	 * Sets the image for this dialog.
+	 * @param image the image.
+	 */
+	public void setImage(Image image) {
+		fImage= image;
+		Shell shell= getShell();
+		if ((shell != null) && !shell.isDisposed())
+			shell.setImage(fImage);
+	}
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/StatusInfo.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/StatusInfo.java
new file mode 100644
index 0000000..418cef8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/StatusInfo.java
@@ -0,0 +1,169 @@
+package net.sourceforge.phpdt.externaltools.internal.ui;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.util.Assert;
+
+/**
+ * A settable IStatus.
+ * Can be an error, warning, info or ok. For error, info and warning states,
+ * a message describes the problem.
+ */
+public class StatusInfo implements IStatus {
+
+	private String fStatusMessage;
+	private int fSeverity;
+
+	/**
+	 * Creates a status set to OK (no message)
+	 */
+	public StatusInfo() {
+		this(OK, null);
+	}
+
+	/**
+	 * Creates a status .
+	 * @param severity The status severity: ERROR, WARNING, INFO and OK.
+	 * @param message The message of the status. Applies only for ERROR,
+	 * WARNING and INFO.
+	 */
+	public StatusInfo(int severity, String message) {
+		fStatusMessage= message;
+		fSeverity= severity;
+	}
+
+	/**
+	 *  Returns if the status' severity is OK.
+	 */
+	public boolean isOK() {
+		return fSeverity == IStatus.OK;
+	}
+
+	/**
+	 *  Returns if the status' severity is WARNING.
+	 */
+	public boolean isWarning() {
+		return fSeverity == IStatus.WARNING;
+	}
+
+	/**
+	 *  Returns if the status' severity is INFO.
+	 */
+	public boolean isInfo() {
+		return fSeverity == IStatus.INFO;
+	}
+
+	/**
+	 *  Returns if the status' severity is ERROR.
+	 */
+	public boolean isError() {
+		return fSeverity == IStatus.ERROR;
+	}
+
+	/**
+	 * @see IStatus#getMessage
+	 */
+	public String getMessage() {
+		return fStatusMessage;
+	}
+
+	/**
+	 * Sets the status to ERROR.
+	 * @param The error message (can be empty, but not null)
+	 */
+	public void setError(String errorMessage) {
+		Assert.isNotNull(errorMessage);
+		fStatusMessage= errorMessage;
+		fSeverity= IStatus.ERROR;
+	}
+
+	/**
+	 * Sets the status to WARNING.
+	 * @param The warning message (can be empty, but not null)
+	 */
+	public void setWarning(String warningMessage) {
+		Assert.isNotNull(warningMessage);
+		fStatusMessage= warningMessage;
+		fSeverity= IStatus.WARNING;
+	}
+
+	/**
+	 * Sets the status to INFO.
+	 * @param The info message (can be empty, but not null)
+	 */
+	public void setInfo(String infoMessage) {
+		Assert.isNotNull(infoMessage);
+		fStatusMessage= infoMessage;
+		fSeverity= IStatus.INFO;
+	}
+
+	/**
+	 * Sets the status to OK.
+	 */
+	public void setOK() {
+		fStatusMessage= null;
+		fSeverity= IStatus.OK;
+	}
+
+	/*
+	 * @see IStatus#matches(int)
+	 */
+	public boolean matches(int severityMask) {
+		return (fSeverity & severityMask) != 0;
+	}
+
+	/**
+	 * Returns always <code>false</code>.
+	 * @see IStatus#isMultiStatus()
+	 */
+	public boolean isMultiStatus() {
+		return false;
+	}
+
+	/*
+	 * @see IStatus#getSeverity()
+	 */
+	public int getSeverity() {
+		return fSeverity;
+	}
+
+	/*
+	 * @see IStatus#getPlugin()
+	 */
+	public String getPlugin() {
+		return IExternalToolConstants.PLUGIN_ID;
+	}
+
+	/**
+	 * Returns always <code>null</code>.
+	 * @see IStatus#getException()
+	 */
+	public Throwable getException() {
+		return null;
+	}
+
+	/**
+	 * Returns always the error severity.
+	 * @see IStatus#getCode()
+	 */
+	public int getCode() {
+		return fSeverity;
+	}
+
+	/**
+	 * Returns always <code>null</code>.
+	 * @see IStatus#getChildren()
+	 */
+	public IStatus[] getChildren() {
+		return new IStatus[0];
+	}
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/TreeAndListGroup.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/TreeAndListGroup.java
new file mode 100644
index 0000000..9da2dea
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/internal/ui/TreeAndListGroup.java
@@ -0,0 +1,287 @@
+package net.sourceforge.phpdt.externaltools.internal.ui;
+
+/**********************************************************************
+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
+**********************************************************************/
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Tree;
+
+/**
+ * This class was derived from org.eclipse.ui.internal.misc.CheckboxTreeAndListGroup
+ *
+ */
+public class TreeAndListGroup implements ISelectionChangedListener {
+	private Object root;
+	private Object currentTreeSelection;
+	private Collection listeners = new HashSet();
+
+	private ITreeContentProvider treeContentProvider;
+	private IStructuredContentProvider listContentProvider;
+	private ILabelProvider treeLabelProvider;
+	private ILabelProvider listLabelProvider;
+
+	// widgets
+	private TreeViewer treeViewer;
+	private TableViewer listViewer;
+	private boolean allowMultiselection= false;
+
+	/**
+	 *	Create an instance of this class.  Use this constructor if you wish to specify
+	 *	the width and/or height of the combined widget (to only hardcode one of the
+	 *	sizing dimensions, specify the other dimension's value as -1)
+	 *
+	 *	@param parent org.eclipse.swt.widgets.Composite
+	 *	@param style int
+	 *  @param rootObject java.lang.Object
+	 *	@param childPropertyName java.lang.String
+	 *	@param parentPropertyName java.lang.String
+	 *	@param listPropertyName java.lang.String
+	 *	@param width int
+	 *	@param height int
+	 */
+	public TreeAndListGroup(Composite parent, Object rootObject, ITreeContentProvider treeContentProvider, ILabelProvider treeLabelProvider, IStructuredContentProvider listContentProvider, ILabelProvider listLabelProvider, int style, int width, int height) {
+
+		root = rootObject;
+		this.treeContentProvider = treeContentProvider;
+		this.listContentProvider = listContentProvider;
+		this.treeLabelProvider = treeLabelProvider;
+		this.listLabelProvider = listLabelProvider;
+		createContents(parent, width, height, style);
+	}
+	/**
+	 * This method must be called just before this window becomes visible.
+	 */
+	public void aboutToOpen() {
+		currentTreeSelection = null;
+
+		//select the first element in the list
+		Object[] elements = treeContentProvider.getElements(root);
+		Object primary = elements.length > 0 ? elements[0] : null;
+		if (primary != null) {
+			treeViewer.setSelection(new StructuredSelection(primary));
+		}
+		treeViewer.getControl().setFocus();
+	}
+	/**
+	 *	Add the passed listener to collection of clients
+	 *	that listen for changes to list viewer selection state
+	 *
+	 *	@param listener ISelectionChangedListener
+	 */
+	public void addSelectionChangedListener(ISelectionChangedListener listener) {
+		listeners.add(listener);
+	}
+
+	/**
+	 *	Notify				all checked state listeners that the passed element
+	 *has had its checked state changed to the passed state
+		 */
+	protected void notifySelectionListeners(SelectionChangedEvent event) {
+		Iterator listenersEnum = listeners.iterator();
+		while (listenersEnum.hasNext()) {
+			 ((ISelectionChangedListener) listenersEnum.next()).selectionChanged(event);
+		}
+	}
+
+	/**
+	 *	Lay out and initialize self's visual components.
+	 *
+	 *	@param parent org.eclipse.swt.widgets.Composite
+	 *	@param width int
+	 *	@param height int
+	 */
+	protected void createContents(Composite parent, int width, int height, int style) {
+		// group pane
+		Composite composite = new Composite(parent, style);
+		composite.setFont(parent.getFont());
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.makeColumnsEqualWidth = true;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		createTreeViewer(composite, width / 2, height);
+		createListViewer(composite, width / 2, height);
+
+		initialize();
+	}
+	/**
+	 *	Create this group's list viewer.
+	 */
+	protected void createListViewer(Composite parent, int width, int height) {
+		int style;
+		if (allowMultiselection) {
+			style= SWT.MULTI;
+		} else {
+			style= SWT.SINGLE;
+		}
+		listViewer = new TableViewer(parent, SWT.BORDER | style);
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = width;
+		data.heightHint = height;
+		listViewer.getTable().setLayoutData(data);
+		listViewer.getTable().setFont(parent.getFont());
+		listViewer.setContentProvider(listContentProvider);
+		listViewer.setLabelProvider(listLabelProvider);
+		listViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				notifySelectionListeners(event);
+			}
+		});
+	}
+	/**
+	 *	Create this group's tree viewer.
+	 */
+	protected void createTreeViewer(Composite parent, int width, int height) {
+		Tree tree = new Tree(parent, SWT.BORDER);
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = width;
+		data.heightHint = height;
+		tree.setLayoutData(data);
+		tree.setFont(parent.getFont());
+
+		treeViewer = new TreeViewer(tree);
+		treeViewer.setContentProvider(treeContentProvider);
+		treeViewer.setLabelProvider(treeLabelProvider);
+		treeViewer.addSelectionChangedListener(this);
+	}
+	
+	public Table getListTable() {
+		return listViewer.getTable();
+	}
+	
+	public IStructuredSelection getListTableSelection() {
+		ISelection selection=  this.listViewer.getSelection();
+		if (selection instanceof IStructuredSelection) {
+			return (IStructuredSelection)selection;
+		} else {
+			return StructuredSelection.EMPTY;
+		}
+	}
+	
+	protected void initialListItem(Object element) {
+		Object parent = treeContentProvider.getParent(element);
+		selectAndRevealFolder(parent);
+	}
+	
+	public void selectAndRevealFolder(Object treeElement) {
+		treeViewer.reveal(treeElement);
+		IStructuredSelection selection = new StructuredSelection(treeElement);
+		treeViewer.setSelection(selection);
+	}
+	
+	public void selectAndRevealFile(Object treeElement) {
+		listViewer.reveal(treeElement);
+		IStructuredSelection selection = new StructuredSelection(treeElement);
+		listViewer.setSelection(selection);
+	}
+
+	/**
+	 *	Initialize this group's viewers after they have been laid out.
+	 */
+	protected void initialize() {
+		treeViewer.setInput(root);
+	}
+
+	/**
+	 *	Handle the selection of an item in the tree viewer
+	 *
+	 *	@param selection ISelection
+	 */
+	public void selectionChanged(SelectionChangedEvent event) {
+		IStructuredSelection selection = (IStructuredSelection) event.getSelection();
+		Object selectedElement = selection.getFirstElement();
+		if (selectedElement == null) {
+			currentTreeSelection = null;
+			listViewer.setInput(currentTreeSelection);
+			return;
+		}
+
+		// ie.- if not an item deselection
+		if (selectedElement != currentTreeSelection) {
+			listViewer.setInput(selectedElement);
+		}
+
+		currentTreeSelection = selectedElement;
+	}
+	/**
+	 *	Set the list viewer's providers to those passed
+	 *
+	 *	@param contentProvider ITreeContentProvider
+	 *	@param labelProvider ILabelProvider
+	 */
+	public void setListProviders(IStructuredContentProvider contentProvider, ILabelProvider labelProvider) {
+		listViewer.setContentProvider(contentProvider);
+		listViewer.setLabelProvider(labelProvider);
+	}
+	/**
+	 *	Set the sorter that is to be applied to self's list viewer
+	 */
+	public void setListSorter(ViewerSorter sorter) {
+		listViewer.setSorter(sorter);
+	}
+	/**
+	 * Set the root of the widget to be new Root. Regenerate all of the tables and lists from this
+	 * value.
+	 * @param newRoot
+	 */
+	public void setRoot(Object newRoot) {
+		this.root = newRoot;
+		initialize();
+	}
+
+	/**
+	 *	Set the tree viewer's providers to those passed
+	 *
+	 *	@param contentProvider ITreeContentProvider
+	 *	@param labelProvider ILabelProvider
+	 */
+	public void setTreeProviders(ITreeContentProvider contentProvider, ILabelProvider labelProvider) {
+		treeViewer.setContentProvider(contentProvider);
+		treeViewer.setLabelProvider(labelProvider);
+	}
+	/**
+	 *	Set the sorter that is to be applied to self's tree viewer
+	 */
+	public void setTreeSorter(ViewerSorter sorter) {
+		treeViewer.setSorter(sorter);
+	}
+
+	/**
+	 * Set the focus on to the list widget.
+	 */
+	public void setFocus() {
+
+		this.treeViewer.getTree().setFocus();
+	}
+	
+	public void setAllowMultiselection(boolean allowMultiselection) {
+		this.allowMultiselection= allowMultiselection;
+		
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsLaunchConfigurationMessages.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsLaunchConfigurationMessages.java
new file mode 100644
index 0000000..56b3319
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsLaunchConfigurationMessages.java
@@ -0,0 +1,30 @@
+package net.sourceforge.phpdt.externaltools.launchConfigurations;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class ExternalToolsLaunchConfigurationMessages {
+
+	private static final String BUNDLE_NAME = "net.sourceforge.phpdt.externaltools.launchConfigurations.ExternalToolsLaunchConfigurationMessages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE =
+		ResourceBundle.getBundle(BUNDLE_NAME);
+
+	private ExternalToolsLaunchConfigurationMessages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsLaunchConfigurationMessages.properties b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsLaunchConfigurationMessages.properties
new file mode 100644
index 0000000..c70c6f9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsLaunchConfigurationMessages.properties
@@ -0,0 +1,45 @@
+######################################################################
+# Copyright (c) 2002 IBM Corp. 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 implementation
+######################################################################
+
+ExternalToolsMainTab.Descri&ption__1=Descri&ption:
+ExternalToolsMainTab.&Location___2=&Location: 
+ExternalToolsMainTab.&Browse_Workspace..._3=&Browse Workspace...
+ExternalToolsMainTab.Brows&e_File_System..._4=Brows&e File System...
+ExternalToolsMainTab.Working_&Directory__5=Working &Directory:
+ExternalToolsMainTab.Browse_Wor&kspace..._6=Browse Wor&kspace...
+ExternalToolsMainTab.Browse_F&ile_System..._7=Browse F&ile System...
+ExternalToolsMainTab.Error_reading_configuration_10=Error reading configuration
+ExternalToolsMainTab.&Main_17=Main
+ExternalToolsMainTab.External_tool_location_cannot_be_empty_18=External tool location cannot be empty
+ExternalToolsMainTab.External_tool_location_does_not_exist_19=External tool location does not exist
+ExternalToolsMainTab.External_tool_location_specified_is_not_a_file_20=External tool location specified is not a file
+ExternalToolsMainTab.External_tool_working_directory_does_not_exist_or_is_invalid_21=External tool working directory does not exist or is invalid
+ExternalToolsMainTab.Select_a_resource_22=Select a resource:
+ExternalToolsMainTab.&Select_a_directory__23=&Select a working directory:
+
+ExternalToolsOptionTab.&Arguments___1=&Arguments: 
+ExternalToolsOptionTab.Varia&bles..._2=Varia&bles...
+ExternalToolsOptionTab.Note__Enclose_an_argument_containing_spaces_using_double-quotes_(__)._Not_applicable_for_variables._3=Note: Enclose an argument containing spaces using double-quotes (\").\nNot applicable for variables.
+ExternalToolsOptionTab.Run_tool_in_bac&kground_4=&Run tool in background
+ExternalToolsOptionTab.Error_reading_configuration_7=Error reading configuration
+ExternalToolsOptionTab.Option&s_9=Options
+ExternalToolsOptionTab.Select_variable_10=Select variable
+ExternalToolsOptionTab.&Choose_a_variable__11=&Choose a variable:
+ExternalToolsOptionTab.Invalid_selection_12=Invalid selection
+
+ExternalToolsRefreshTab.Recursively_&include_sub-folders_1=Recursively &include sub-folders
+ExternalToolsRefreshTab.Choose_scope_v&ariable___2=Choose scope v&ariable: 
+ExternalToolsRefreshTab.Exception_reading_launch_configuration_3=Exception reading launch configuration
+ExternalToolsRefreshTab.Refres&h_6=Refresh
+ExternalToolsRefreshTab.&Refresh_resources_after_running_tool_1=&Refresh resources after running tool
+
+ExternalToolsUtil.Location_not_specified_by_{0}_1=Location not specified by {0}
+ExternalToolsUtil.Exception(s)_occurred_during_refresh._2=Exception(s) occurred during refresh.
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsMainTab.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsMainTab.java
new file mode 100644
index 0000000..7e823ba
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsMainTab.java
@@ -0,0 +1,599 @@
+package net.sourceforge.phpdt.externaltools.launchConfigurations;
+
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2002 IBM Corp. 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
+ **********************************************************************************************************************************/
+
+import java.io.File;
+
+import net.sourceforge.phpdt.externaltools.group.IGroupDialogPage;
+import net.sourceforge.phpdt.externaltools.internal.dialog.ExternalToolVariableForm;
+import net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsImages;
+import net.sourceforge.phpdt.externaltools.internal.registry.ExternalToolVariable;
+import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+import net.sourceforge.phpdt.externaltools.model.ToolUtil;
+import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+import org.eclipse.ui.dialogs.ResourceSelectionDialog;
+import org.eclipse.ui.dialogs.SelectionDialog;
+
+public class ExternalToolsMainTab extends AbstractLaunchConfigurationTab {
+
+  protected Combo locationField;
+
+  protected Text workDirectoryField;
+
+  protected Button fileLocationButton;
+
+  protected Button workspaceLocationButton;
+
+  protected Button fileWorkingDirectoryButton;
+
+  protected Button workspaceWorkingDirectoryButton;
+
+  protected Button runBackgroundButton;
+
+  protected Text argumentField;
+
+  protected Button variableButton;
+
+  protected SelectionAdapter selectionAdapter;
+
+  protected ModifyListener modifyListener = new ModifyListener() {
+    public void modifyText(ModifyEvent e) {
+      updateLaunchConfigurationDialog();
+    }
+  };
+
+  /**
+   * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
+   */
+  public void createControl(Composite parent) {
+    Composite mainComposite = new Composite(parent, SWT.NONE);
+    setControl(mainComposite);
+    GridLayout layout = new GridLayout();
+    layout.numColumns = 2;
+    GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+    mainComposite.setLayout(layout);
+    mainComposite.setLayoutData(gridData);
+    mainComposite.setFont(parent.getFont());
+    createLocationComponent(mainComposite);
+    createWorkDirectoryComponent(mainComposite);
+    createArgumentComponent(mainComposite);
+    createVerticalSpacer(mainComposite, 2);
+    createRunBackgroundComponent(mainComposite);
+  }
+
+  /**
+   * Creates the controls needed to edit the location attribute of an external tool
+   * 
+   * @param parent
+   *          the composite to create the controls in
+   */
+  protected void createLocationComponent(Composite parent) {
+    Font font = parent.getFont();
+
+    Composite composite = new Composite(parent, SWT.NONE);
+    GridLayout layout = new GridLayout();
+    layout.marginWidth = 0;
+    layout.marginHeight = 0;
+    layout.numColumns = 1;
+    GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+    composite.setLayout(layout);
+    composite.setLayoutData(gridData);
+
+    Label label = new Label(composite, SWT.NONE);
+    label.setText(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsMainTab.&Location___2")); //$NON-NLS-1$
+    label.setFont(font);
+
+    final IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
+    locationField = new Combo(composite, SWT.DROP_DOWN | SWT.BORDER);
+    GridData data = new GridData(GridData.FILL_HORIZONTAL);
+    data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+    locationField.setLayoutData(data);
+    locationField.setFont(font);
+    locationField.add(store.getString(PHPeclipsePlugin.PHP_RUN_PREF), 0);
+    locationField.add(store.getString(PHPeclipsePlugin.APACHE_RUN_PREF), 1);
+    locationField.add(store.getString(PHPeclipsePlugin.MYSQL_RUN_PREF), 2);
+    locationField.add(store.getString(PHPeclipsePlugin.XAMPP_START_PREF), 3);
+    locationField.add(store.getString(PHPeclipsePlugin.XAMPP_STOP_PREF), 4);
+    Composite buttonComposite = new Composite(parent, SWT.NONE);
+    layout = new GridLayout();
+    layout.marginWidth = 0;
+    layout.marginHeight = 0;
+    layout.numColumns = 1;
+    gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
+    buttonComposite.setLayout(layout);
+    buttonComposite.setLayoutData(gridData);
+    buttonComposite.setFont(font);
+
+    createVerticalSpacer(buttonComposite, 1);
+
+    workspaceLocationButton = createPushButton(buttonComposite, ExternalToolsLaunchConfigurationMessages
+        .getString("ExternalToolsMainTab.&Browse_Workspace..._3"), null); //$NON-NLS-1$
+    workspaceLocationButton.addSelectionListener(new SelectionAdapter() {
+      public void widgetSelected(SelectionEvent evt) {
+        handleWorkspaceLocationButtonSelected();
+      }
+    });
+    fileLocationButton = createPushButton(buttonComposite, ExternalToolsLaunchConfigurationMessages
+        .getString("ExternalToolsMainTab.Brows&e_File_System..._4"), null); //$NON-NLS-1$
+    fileLocationButton.addSelectionListener(new SelectionAdapter() {
+      public void widgetSelected(SelectionEvent evt) {
+        handleLocationButtonSelected();
+      }
+    });
+  }
+
+  /**
+   * Creates the controls needed to edit the working directory attribute of an external tool
+   * 
+   * @param parent
+   *          the composite to create the controls in
+   */
+  protected void createWorkDirectoryComponent(Composite parent) {
+    Font font = parent.getFont();
+
+    Composite composite = new Composite(parent, SWT.NONE);
+    GridLayout layout = new GridLayout();
+    layout.marginWidth = 0;
+    layout.marginHeight = 0;
+    layout.numColumns = 1;
+    GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+    composite.setLayout(layout);
+    composite.setLayoutData(gridData);
+
+    Label label = new Label(composite, SWT.NONE);
+    label.setText(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsMainTab.Working_&Directory__5")); //$NON-NLS-1$
+    label.setFont(font);
+
+    workDirectoryField = new Text(composite, SWT.BORDER);
+    GridData data = new GridData(GridData.FILL_HORIZONTAL);
+    data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+    workDirectoryField.setLayoutData(data);
+    workDirectoryField.setFont(font);
+
+    Composite buttonComposite = new Composite(parent, SWT.NONE);
+    layout = new GridLayout();
+    layout.marginWidth = 0;
+    layout.marginHeight = 0;
+    layout.numColumns = 1;
+    gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
+    buttonComposite.setLayout(layout);
+    buttonComposite.setLayoutData(gridData);
+    buttonComposite.setFont(font);
+
+    createVerticalSpacer(buttonComposite, 1);
+    workspaceWorkingDirectoryButton = createPushButton(buttonComposite, ExternalToolsLaunchConfigurationMessages
+        .getString("ExternalToolsMainTab.Browse_Wor&kspace..._6"), null); //$NON-NLS-1$
+    workspaceWorkingDirectoryButton.addSelectionListener(new SelectionAdapter() {
+      public void widgetSelected(SelectionEvent evt) {
+        handleWorkspaceWorkingDirectoryButtonSelected();
+      }
+    });
+    fileWorkingDirectoryButton = createPushButton(buttonComposite, ExternalToolsLaunchConfigurationMessages
+        .getString("ExternalToolsMainTab.Browse_F&ile_System..._7"), null); //$NON-NLS-1$
+    fileWorkingDirectoryButton.addSelectionListener(new SelectionAdapter() {
+      public void widgetSelected(SelectionEvent evt) {
+        handleFileWorkingDirectoryButtonSelected();
+      }
+    });
+  }
+
+  /**
+   * Creates the controls needed to edit the argument and prompt for argument attributes of an external tool
+   * 
+   * @param parent
+   *          the composite to create the controls in
+   */
+  protected void createArgumentComponent(Composite parent) {
+    Font font = parent.getFont();
+
+    Label label = new Label(parent, SWT.NONE);
+    label.setText(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsOptionTab.&Arguments___1")); //$NON-NLS-1$
+    GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+    data.horizontalSpan = 2;
+    label.setLayoutData(data);
+    label.setFont(font);
+
+    argumentField = new Text(parent, SWT.BORDER);
+    data = new GridData(GridData.FILL_HORIZONTAL);
+    data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+    argumentField.setLayoutData(data);
+    argumentField.setFont(font);
+    argumentField.addModifyListener(new ModifyListener() {
+      public void modifyText(ModifyEvent e) {
+        updateLaunchConfigurationDialog();
+      }
+    });
+
+    variableButton = createPushButton(parent, ExternalToolsLaunchConfigurationMessages
+        .getString("ExternalToolsOptionTab.Varia&bles..._2"), null); //$NON-NLS-1$
+    variableButton.addSelectionListener(new SelectionAdapter() {
+      public void widgetSelected(SelectionEvent e) {
+        VariableSelectionDialog dialog = new VariableSelectionDialog(getShell());
+        if (dialog.open() == SelectionDialog.OK) {
+          argumentField.insert(dialog.getForm().getSelectedVariable());
+        }
+      }
+    });
+
+    Label instruction = new Label(parent, SWT.NONE);
+    instruction
+        .setText(ExternalToolsLaunchConfigurationMessages
+            .getString("ExternalToolsOptionTab.Note__Enclose_an_argument_containing_spaces_using_double-quotes_(__)._Not_applicable_for_variables._3")); //$NON-NLS-1$
+    data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+    data.horizontalSpan = 2;
+    instruction.setLayoutData(data);
+    instruction.setFont(font);
+  }
+
+  /**
+   * Creates the controls needed to edit the run in background attribute of an external tool
+   * 
+   * @param parent
+   *          the composite to create the controls in
+   */
+  protected void createRunBackgroundComponent(Composite parent) {
+    runBackgroundButton = new Button(parent, SWT.CHECK);
+    runBackgroundButton.setText(ExternalToolsLaunchConfigurationMessages
+        .getString("ExternalToolsOptionTab.Run_tool_in_bac&kground_4")); //$NON-NLS-1$
+    GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+    runBackgroundButton.setLayoutData(data);
+    runBackgroundButton.setFont(parent.getFont());
+    runBackgroundButton.addSelectionListener(getSelectionAdapter());
+  }
+
+  /**
+   * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+   */
+  public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+    configuration.setAttribute(IExternalToolConstants.ATTR_RUN_IN_BACKGROUND, false);
+  }
+
+  /**
+   * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
+   */
+  public void initializeFrom(ILaunchConfiguration configuration) {
+    updateLocation(configuration);
+    updateWorkingDirectory(configuration);
+    updateArgument(configuration);
+    updateRunBackground(configuration);
+  }
+
+  protected void updateWorkingDirectory(ILaunchConfiguration configuration) {
+    String workingDir = ""; //$NON-NLS-1$
+    try {
+      workingDir = configuration.getAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, ""); //$NON-NLS-1$
+    } catch (CoreException ce) {
+      ExternalToolsPlugin.getDefault().log(
+          ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsMainTab.Error_reading_configuration_10"), ce); //$NON-NLS-1$
+    }
+    workDirectoryField.setText(workingDir);
+    workDirectoryField.addModifyListener(modifyListener);
+
+  }
+
+  protected void updateLocation(ILaunchConfiguration configuration) {
+    String location = ""; //$NON-NLS-1$
+    try {
+      location = configuration.getAttribute(IExternalToolConstants.ATTR_LOCATION, ""); //$NON-NLS-1$
+    } catch (CoreException ce) {
+      ExternalToolsPlugin.getDefault().log(
+          ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsMainTab.Error_reading_configuration_10"), ce); //$NON-NLS-1$
+    }
+    locationField.setText(location);
+    locationField.addModifyListener(modifyListener);
+  }
+
+  protected void updateArgument(ILaunchConfiguration configuration) {
+    String arguments = ""; //$NON-NLS-1$
+    try {
+      arguments = configuration.getAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, ""); //$NON-NLS-1$
+    } catch (CoreException ce) {
+      ExternalToolsPlugin.getDefault().log(
+          ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsOptionTab.Error_reading_configuration_7"), ce); //$NON-NLS-1$
+    }
+    argumentField.setText(arguments);
+  }
+
+  protected void updateRunBackground(ILaunchConfiguration configuration) {
+    boolean runInBackgroud = true;
+    try {
+      runInBackgroud = configuration.getAttribute(IExternalToolConstants.ATTR_RUN_IN_BACKGROUND, false);
+    } catch (CoreException ce) {
+      ExternalToolsPlugin.getDefault().log(
+          ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsOptionTab.Error_reading_configuration_7"), ce); //$NON-NLS-1$
+    }
+    runBackgroundButton.setSelection(runInBackgroud);
+  }
+
+  /**
+   * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+   */
+  public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+    String location = locationField.getText().trim();
+    if (location.length() == 0) {
+      configuration.setAttribute(IExternalToolConstants.ATTR_LOCATION, (String) null);
+    } else {
+      configuration.setAttribute(IExternalToolConstants.ATTR_LOCATION, location);
+    }
+
+    String workingDirectory = workDirectoryField.getText().trim();
+    if (workingDirectory.length() == 0) {
+      configuration.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, (String) null);
+    } else {
+      configuration.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, workingDirectory);
+    }
+
+    setAttribute(IExternalToolConstants.ATTR_RUN_IN_BACKGROUND, configuration, runBackgroundButton.getSelection(), false);
+
+    String arguments = argumentField.getText().trim();
+    if (arguments.length() == 0) {
+      configuration.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, (String) null);
+    } else {
+      configuration.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, arguments);
+    }
+  }
+
+  /**
+   * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+   */
+  public String getName() {
+    return ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsMainTab.&Main_17"); //$NON-NLS-1$
+  }
+
+  /**
+   * @see ILaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
+   */
+  public boolean isValid(ILaunchConfiguration launchConfig) {
+    setErrorMessage(null);
+    setMessage(null);
+    return validateLocation() && validateWorkDirectory();
+  }
+
+  /**
+   * Validates the content of the location field.
+   */
+  protected boolean validateLocation() {
+    String value = locationField.getText().trim();
+    if (value.length() < 1) {
+      setErrorMessage(ExternalToolsLaunchConfigurationMessages
+          .getString("ExternalToolsMainTab.External_tool_location_cannot_be_empty_18")); //$NON-NLS-1$
+      setMessage(null);
+      return false;
+    }
+
+    // Translate field contents to the actual file location so we
+    // can check to ensure the file actually exists.
+    MultiStatus multiStatus = new MultiStatus(IExternalToolConstants.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
+    value = ToolUtil.expandFileLocation(value, ExpandVariableContext.EMPTY_CONTEXT, multiStatus);
+    if (!multiStatus.isOK()) {
+      IStatus[] children = multiStatus.getChildren();
+      if (children.length > 0) {
+        setErrorMessage(children[0].getMessage());
+        setMessage(null);
+      }
+      return false;
+    }
+
+    File file = new File(value);
+    if (!file.exists()) { // The file does not exist.
+      setErrorMessage(ExternalToolsLaunchConfigurationMessages
+          .getString("ExternalToolsMainTab.External_tool_location_does_not_exist_19")); //$NON-NLS-1$
+      return false;
+    }
+    if (!file.isFile()) {
+      setErrorMessage(ExternalToolsLaunchConfigurationMessages
+          .getString("ExternalToolsMainTab.External_tool_location_specified_is_not_a_file_20")); //$NON-NLS-1$
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Validates the content of the working directory field.
+   */
+  protected boolean validateWorkDirectory() {
+
+    String value = workDirectoryField.getText().trim();
+    if (value.length() > 0) {
+      // Translate field contents to the actual directory location so we
+      // can check to ensure the directory actually exists.
+      MultiStatus multiStatus = new MultiStatus(IExternalToolConstants.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
+      value = ToolUtil.expandDirectoryLocation(value, ExpandVariableContext.EMPTY_CONTEXT, multiStatus);
+      if (!multiStatus.isOK()) {
+        IStatus[] children = multiStatus.getChildren();
+        if (children.length > 0) {
+          setErrorMessage(children[0].getMessage());
+        }
+        return false;
+      }
+
+      File file = new File(value);
+      if (!file.exists()) { // The directory does not exist.
+        setErrorMessage(ExternalToolsLaunchConfigurationMessages
+            .getString("ExternalToolsMainTab.External_tool_working_directory_does_not_exist_or_is_invalid_21")); //$NON-NLS-1$
+        return false;
+      }
+    }
+    return true;
+  }
+
+  protected void handleLocationButtonSelected() {
+    FileDialog fileDialog = new FileDialog(getShell(), SWT.NONE);
+    fileDialog.setFileName(locationField.getText());
+    String text = fileDialog.open();
+    if (text != null) {
+      locationField.setText(text);
+    }
+  }
+
+  /**
+   * Prompts the user for a workspace location within the workspace and sets the location as a String containing the workspace_loc
+   * variable or <code>null</code> if no location was obtained from the user.
+   */
+  protected void handleWorkspaceLocationButtonSelected() {
+    ResourceSelectionDialog dialog;
+    dialog = new ResourceSelectionDialog(getShell(), ResourcesPlugin.getWorkspace().getRoot(),
+        ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsMainTab.Select_a_resource_22")); //$NON-NLS-1$
+    dialog.open();
+    Object[] results = dialog.getResult();
+    if (results == null || results.length < 1) {
+      return;
+    }
+    IResource resource = (IResource) results[0];
+    StringBuffer buf = new StringBuffer();
+    ToolUtil.buildVariableTag(IExternalToolConstants.VAR_WORKSPACE_LOC, resource.getFullPath().toString(), buf);
+    String text = buf.toString();
+    if (text != null) {
+      locationField.setText(text);
+    }
+  }
+
+  /**
+   * Prompts the user for a working directory location within the workspace and sets the working directory as a String containing
+   * the workspace_loc variable or <code>null</code> if no location was obtained from the user.
+   */
+  protected void handleWorkspaceWorkingDirectoryButtonSelected() {
+    ContainerSelectionDialog containerDialog;
+    containerDialog = new ContainerSelectionDialog(getShell(), ResourcesPlugin.getWorkspace().getRoot(), false,
+        ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsMainTab.&Select_a_directory__23")); //$NON-NLS-1$
+    containerDialog.open();
+    Object[] resource = containerDialog.getResult();
+    String text = null;
+    if (resource != null && resource.length > 0) {
+      text = ToolUtil.buildVariableTag(IExternalToolConstants.VAR_RESOURCE_LOC, ((IPath) resource[0]).toString());
+    }
+    if (text != null) {
+      workDirectoryField.setText(text);
+    }
+  }
+
+  protected void handleFileWorkingDirectoryButtonSelected() {
+    DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.SAVE);
+    dialog.setMessage(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsMainTab.&Select_a_directory__23")); //$NON-NLS-1$
+    dialog.setFilterPath(workDirectoryField.getText());
+    String text = dialog.open();
+    if (text != null) {
+      workDirectoryField.setText(text);
+    }
+  }
+
+  /**
+   * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getImage()
+   */
+  public Image getImage() {
+    return ExternalToolsImages.getImage(IExternalToolConstants.IMG_TAB_MAIN);
+  }
+
+  /**
+   * Method getSelectionAdapter.
+   * 
+   * @return SelectionListener
+   */
+  protected SelectionListener getSelectionAdapter() {
+    if (selectionAdapter == null) {
+      selectionAdapter = new SelectionAdapter() {
+        public void widgetSelected(SelectionEvent e) {
+          updateLaunchConfigurationDialog();
+        }
+      };
+    }
+    return selectionAdapter;
+  }
+
+  private class VariableSelectionDialog extends SelectionDialog {
+    private ExternalToolVariableForm form;
+
+    private VariableSelectionDialog(Shell parent) {
+      super(parent);
+      setTitle(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsOptionTab.Select_variable_10")); //$NON-NLS-1$
+    }
+
+    protected Control createDialogArea(Composite parent) {
+      // Create the dialog area
+      Composite composite = (Composite) super.createDialogArea(parent);
+      ExternalToolVariable[] variables = ExternalToolsPlugin.getDefault().getArgumentVariableRegistry().getArgumentVariables();
+      form = new ExternalToolVariableForm(ExternalToolsLaunchConfigurationMessages
+          .getString("ExternalToolsOptionTab.&Choose_a_variable__11"), variables); //$NON-NLS-1$
+      form.createContents(composite, new IGroupDialogPage() {
+        public GridData setButtonGridData(Button button) {
+          GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+          data.heightHint = convertVerticalDLUsToPixels(IDialogConstants.BUTTON_HEIGHT);
+          int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
+          data.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
+          button.setLayoutData(data);
+          return data;
+        }
+
+        public void setMessage(String newMessage, int newType) {
+          VariableSelectionDialog.this.setMessage(newMessage);
+        }
+
+        public void updateValidState() {
+        }
+
+        public int convertHeightHint(int chars) {
+          return convertHeightInCharsToPixels(chars);
+        }
+
+        public String getMessage() {
+          if (!form.isValid()) {
+            return ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsOptionTab.Invalid_selection_12"); //$NON-NLS-1$
+          }
+          return null;
+        }
+
+        public int getMessageType() {
+          if (!form.isValid()) {
+            return IMessageProvider.ERROR;
+          }
+          return 0;
+        }
+      });
+      return composite;
+    }
+
+    private ExternalToolVariableForm getForm() {
+      return form;
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsRefreshTab.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsRefreshTab.java
new file mode 100644
index 0000000..a097c92
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsRefreshTab.java
@@ -0,0 +1,253 @@
+package net.sourceforge.phpdt.externaltools.launchConfigurations;
+
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import net.sourceforge.phpdt.externaltools.group.IGroupDialogPage;
+import net.sourceforge.phpdt.externaltools.internal.dialog.ExternalToolVariableForm;
+import net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsImages;
+import net.sourceforge.phpdt.externaltools.internal.registry.ExternalToolVariable;
+import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+import net.sourceforge.phpdt.externaltools.model.ToolUtil;
+import net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+
+public class ExternalToolsRefreshTab extends AbstractLaunchConfigurationTab implements IGroupDialogPage {
+
+	private ExternalToolVariableForm variableForm;
+	
+	protected Button refreshField;
+	protected Button recursiveField;
+	
+	/**
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createControl(Composite parent) {
+		Composite mainComposite = new Composite(parent, SWT.NONE);
+		setControl(mainComposite);
+		
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+		mainComposite.setLayout(layout);
+		mainComposite.setLayoutData(gridData);
+		mainComposite.setFont(parent.getFont());
+		createVerticalSpacer(mainComposite, 1);
+		createRefreshComponent(mainComposite);
+		createRecursiveComponent(mainComposite);
+		createScopeComponent(mainComposite);
+	}
+	
+	/**
+	 * Creates the controls needed to edit the refresh recursive
+	 * attribute of an external tool
+	 * 
+	 * @param parent the composite to create the controls in
+	 */
+	protected void createRecursiveComponent(Composite parent) {
+		recursiveField = new Button(parent, SWT.CHECK);
+		recursiveField.setText(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsRefreshTab.Recursively_&include_sub-folders_1")); //$NON-NLS-1$
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		recursiveField.setLayoutData(data);
+		recursiveField.setFont(parent.getFont());
+		recursiveField.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				updateLaunchConfigurationDialog();
+			}
+		});
+	}
+	
+	/**
+	 * Creates the controls needed to edit the refresh scope
+	 * attribute of an external tool
+	 * 
+	 * @param parent the composite to create the controls in
+	 */
+	protected void createRefreshComponent(Composite parent) {
+		refreshField = new Button(parent, SWT.CHECK);
+		refreshField.setText(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsRefreshTab.&Refresh_resources_after_running_tool_1")); //$NON-NLS-1$
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		refreshField.setLayoutData(data);
+		refreshField.setFont(parent.getFont());
+		refreshField.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				updateEnabledState();
+				updateLaunchConfigurationDialog();
+			}
+		});
+	}
+	
+	/**
+	 * Creates the controls needed to edit the refresh scope variable
+	 * attribute of an external tool
+	 * 
+	 * @param parent the composite to create the controls in
+	 */
+	protected void createScopeComponent(Composite parent) {
+		String label = ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsRefreshTab.Choose_scope_v&ariable___2"); //$NON-NLS-1$
+		ExternalToolVariable[] vars = ExternalToolsPlugin.getDefault().getRefreshVariableRegistry().getRefreshVariables();
+		variableForm = new ExternalToolVariableForm(label, vars);
+		variableForm.createContents(parent, this);
+	}
+	
+
+	/**
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+	 */
+	public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+	}
+
+	/**
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
+	 */
+	public void initializeFrom(ILaunchConfiguration configuration) {
+		updateRefresh(configuration);
+		updateRecursive(configuration);
+		updateScope(configuration);
+	}
+	/**
+	 * Method udpateScope.
+	 * @param configuration
+	 */
+	private void updateScope(ILaunchConfiguration configuration) {
+		String scope = null;
+		try {
+			scope= configuration.getAttribute(IExternalToolConstants.ATTR_REFRESH_SCOPE, (String)null);
+		} catch (CoreException ce) {
+			ExternalToolsPlugin.getDefault().log(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsRefreshTab.Exception_reading_launch_configuration_3"), ce); //$NON-NLS-1$
+		}
+		String varName = null;
+		String varValue = null;
+		if (scope != null) {
+			ToolUtil.VariableDefinition varDef = ToolUtil.extractVariableTag(scope, 0);
+			varName = varDef.name;
+			varValue = varDef.argument;
+		}
+		variableForm.selectVariable(varName, varValue);
+	}
+	/**
+	 * Method updateRecursive.
+	 * @param configuration
+	 */
+	private void updateRecursive(ILaunchConfiguration configuration) {
+		boolean recursive= true;
+		try {
+			recursive= configuration.getAttribute(IExternalToolConstants.ATTR_REFRESH_RECURSIVE, false);
+		} catch (CoreException ce) {
+			ExternalToolsPlugin.getDefault().log(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsRefreshTab.Exception_reading_launch_configuration_3"), ce); //$NON-NLS-1$
+		}
+		recursiveField.setSelection(recursive);
+	}
+	/**
+	 * Method updateRefresh.
+	 * @param configuration
+	 */
+	private void updateRefresh(ILaunchConfiguration configuration) {
+		String scope= null;
+		try {
+			scope= configuration.getAttribute(IExternalToolConstants.ATTR_REFRESH_SCOPE, (String)null);
+		} catch (CoreException ce) {
+			ExternalToolsPlugin.getDefault().log(ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsRefreshTab.Exception_reading_launch_configuration_3"), ce); //$NON-NLS-1$
+		}
+		refreshField.setSelection(scope != null);
+		updateEnabledState();		
+	}
+
+	/**
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+	 */
+	public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+
+		if (refreshField.getSelection()) {
+			configuration.setAttribute(IExternalToolConstants.ATTR_REFRESH_SCOPE, variableForm.getSelectedVariable());
+		} else {
+			configuration.setAttribute(IExternalToolConstants.ATTR_REFRESH_SCOPE, (String)null);
+		}
+		
+		setAttribute(IExternalToolConstants.ATTR_REFRESH_RECURSIVE, configuration, recursiveField.getSelection(), false);
+	}
+
+	/**
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+	 */
+	public String getName() {
+		return ExternalToolsLaunchConfigurationMessages.getString("ExternalToolsRefreshTab.Refres&h_6"); //$NON-NLS-1$
+	}
+	
+	/**
+	 * Updates the enablement state of the fields.
+	 */
+	protected void updateEnabledState() {
+		if (refreshField != null) {
+			if (recursiveField != null) {
+				recursiveField.setEnabled(refreshField.getSelection());
+			}
+			if (variableForm != null) {
+				variableForm.setEnabled(refreshField.getSelection());
+			}
+		}
+	}
+	/**
+	 * @see net.sourceforge.phpdt.externaltools.group.IGroupDialogPage#convertHeightHint(int)
+	 */
+	public int convertHeightHint(int chars) {
+		return 0;
+	}
+
+	/**
+	 * @see net.sourceforge.phpdt.externaltools.group.IGroupDialogPage#setButtonGridData(org.eclipse.swt.widgets.Button)
+	 */
+	public GridData setButtonGridData(Button button) {
+		return null;
+	}
+
+	/**
+	 * @see net.sourceforge.phpdt.externaltools.group.IGroupDialogPage#setMessage(java.lang.String, int)
+	 */
+	public void setMessage(String newMessage, int newType) {
+		setMessage(newMessage);
+	}
+
+	/**
+	 * @see net.sourceforge.phpdt.externaltools.group.IGroupDialogPage#updateValidState()
+	 */
+	public void updateValidState() {
+		updateLaunchConfigurationDialog();
+	}
+
+	/**
+	 * @see org.eclipse.jface.dialogs.IMessageProvider#getMessageType()
+	 */
+	public int getMessageType() {
+		if (getErrorMessage() != null) {
+			return IMessageProvider.ERROR;
+		} else if (getMessage() != null) {
+			return IMessageProvider.WARNING;
+		}
+		return IMessageProvider.NONE;
+	}
+	/**
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getImage()
+	 */
+	public Image getImage() {
+		return ExternalToolsImages.getImage(IExternalToolConstants.IMG_ACTION_REFRESH);
+	}
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsUtil.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsUtil.java
new file mode 100644
index 0000000..c5c5555
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/launchConfigurations/ExternalToolsUtil.java
@@ -0,0 +1,363 @@
+package net.sourceforge.phpdt.externaltools.launchConfigurations;
+
+/**********************************************************************
+ 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.io.File;
+import java.text.MessageFormat;
+import java.util.Map;
+
+import net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsModelMessages;
+import net.sourceforge.phpdt.externaltools.internal.model.VariableContextManager;
+import net.sourceforge.phpdt.externaltools.internal.registry.ExternalToolMigration;
+import net.sourceforge.phpdt.externaltools.internal.registry.RefreshScopeVariable;
+import net.sourceforge.phpdt.externaltools.internal.registry.RefreshScopeVariableRegistry;
+import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+import net.sourceforge.phpdt.externaltools.model.ToolUtil;
+import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
+import net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+
+/**
+ * Utilities for external tool launch configurations.
+ * <p>
+ * This class it not intended to be instantiated.
+ * </p>
+ */
+public class ExternalToolsUtil {
+
+  private static final String LAUNCH_CONFIG_HANDLE = "LaunchConfigHandle"; //$NON-NLS-1$
+
+  /**
+   * Not to be instantiated.
+   */
+  private ExternalToolsUtil() {
+  };
+
+  /**
+   * Throws a core exception with an error status object built from the given message, lower level exception, and error code.
+   * 
+   * @param message
+   *          the status message
+   * @param exception
+   *          lower level exception associated with the error, or <code>null</code> if none
+   * @param code
+   *          error code
+   */
+  protected static void abort(String message, Throwable exception, int code) throws CoreException {
+    throw new CoreException(new Status(IStatus.ERROR, IExternalToolConstants.PLUGIN_ID, code, message, exception));
+  }
+
+  /**
+   * Returns active variable context. The active variable context is used to expand variable expressions. If the workspace is
+   * currently being built, the context is associated with the project being built. Otherwise, the context is associated with the
+   * selected resource.
+   * 
+   * @return active variable context
+   */
+  public static ExpandVariableContext getVariableContext() {
+    return VariableContextManager.getDefault().getVariableContext();
+  }
+
+  /**
+   * Expands and returns the location attribute of the given launch configuration, based on the given variable context. The location
+   * is verified to point to an existing file, in the local file system.
+   * 
+   * @param configuration
+   *          launch configuration
+   * @param context
+   *          context used to expand variables
+   * @return an absolute path to a file in the local file system
+   * @throws CoreException
+   *           if unable to retrieve the associated launch configuration attribute, if unable to resolve any variables, or if the
+   *           resolved location does not point to an existing file in the local file system
+   */
+  public static IPath getLocation(ILaunchConfiguration configuration, ExpandVariableContext context) throws CoreException {
+    String location = configuration.getAttribute(IExternalToolConstants.ATTR_LOCATION, (String) null);
+    if (location == null) {
+      abort(MessageFormat.format(ExternalToolsLaunchConfigurationMessages
+          .getString("ExternalToolsUtil.Location_not_specified_by_{0}_1"), new String[] { configuration.getName() }), null, 0); //$NON-NLS-1$
+    } else {
+      MultiStatus status = new MultiStatus(IExternalToolConstants.PLUGIN_ID, 0, ExternalToolsModelMessages
+          .getString("RunExternalToolAction.runProblem"), null); //$NON-NLS-1$;
+      String expandedLocation = ToolUtil.expandFileLocation(location, context, status);
+      if (status.isOK()) {
+        if (expandedLocation == null || expandedLocation.length() == 0) {
+          String msg = ExternalToolsModelMessages.format(
+              "DefaultRunnerContext.invalidLocation", new Object[] { configuration.getName() }); //$NON-NLS-1$
+          abort(msg, null, 0);
+        } else {
+          File file = new File(expandedLocation);
+          if (file.isFile()) {
+            return new Path(expandedLocation);
+          } else {
+            String msg = ExternalToolsModelMessages.format(
+                "DefaultRunnerContext.invalidLocation", new Object[] { configuration.getName() }); //$NON-NLS-1$
+            abort(msg, null, 0);
+          }
+        }
+      } else {
+        throw new CoreException(status);
+      }
+    }
+    // execution will not reach here
+    return null;
+  }
+
+  /**
+   * Expands and returns the working directory attribute of the given launch configuration, based on the given variable context.
+   * Returns <code>null</code> if a working directory is not specified. If specified, the working is verified to point to an
+   * existing directory in the local file system.
+   * 
+   * @param configuration
+   *          launch configuration
+   * @param context
+   *          context used to expand variables
+   * @return an absolute path to a direcoty in the local file system, or <code>null</code> if unspecified
+   * @throws CoreException
+   *           if unable to retrieve the associated launch configuration attribute, if unable to resolve any variables, or if the
+   *           resolved location does not point to an existing directory in the local file system
+   */
+  public static IPath getWorkingDirectory(ILaunchConfiguration configuration, ExpandVariableContext context) throws CoreException {
+    String location = configuration.getAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, (String) null);
+    if (location != null) {
+      MultiStatus status = new MultiStatus(IExternalToolConstants.PLUGIN_ID, 0, ExternalToolsModelMessages
+          .getString("RunExternalToolAction.runProblem"), null); //$NON-NLS-1$;
+      String expandedLocation = ToolUtil.expandDirectoryLocation(location, context, status);
+      if (status.isOK()) {
+        if (expandedLocation != null && expandedLocation.length() > 0) {
+          File path = new File(expandedLocation);
+          if (path.isDirectory()) {
+            return new Path(expandedLocation);
+          } else {
+            String msg = ExternalToolsModelMessages.format(
+                "DefaultRunnerContext.invalidDirectory", new Object[] { configuration.getName() }); //$NON-NLS-1$
+            abort(msg, null, 0);
+          }
+        }
+      } else {
+        throw new CoreException(status);
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Expands and returns the arguments attribute of the given launch configuration, based on the given variable context. Returns
+   * <code>null</code> if arguments are not specified.
+   * 
+   * @param configuration
+   *          launch configuration
+   * @param context
+   *          context used to expand variables
+   * @return an array of resolved arguments, or <code>null</code> if unspecified
+   * @throws CoreException
+   *           if unable to retrieve the associated launch configuration attribute, or if unable to resolve any variables
+   */
+  public static String[] getArguments(ILaunchConfiguration configuration, ExpandVariableContext context) throws CoreException {
+    String args = configuration.getAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, (String) null);
+    if (args != null) {
+      MultiStatus status = new MultiStatus(IExternalToolConstants.PLUGIN_ID, 0, ExternalToolsModelMessages
+          .getString("RunExternalToolAction.runProblem"), null); //$NON-NLS-1$;
+      String[] expandedArgs = ToolUtil.expandArguments(args, context, status);
+      if (status.isOK()) {
+        return expandedArgs;
+      } else {
+        throw new CoreException(status);
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Returns the refresh scope specified by the given launch configuration or <code>null</code> if none.
+   * 
+   * @param configuration
+   * @return refresh scope
+   * @throws CoreException
+   *           if unable to access the associated attribute
+   */
+  public static String getRefreshScope(ILaunchConfiguration configuration) throws CoreException {
+    return configuration.getAttribute(IExternalToolConstants.ATTR_REFRESH_SCOPE, (String) null);
+  }
+
+  /**
+   * Returns whether the refresh scope specified by the given launch configuration is recursive.
+   * 
+   * @param configuration
+   * @return whether the refresh scope is recursive
+   * @throws CoreException
+   *           if unable to access the associated attribute
+   */
+  public static boolean isRefreshRecursive(ILaunchConfiguration configuration) throws CoreException {
+    return configuration.getAttribute(IExternalToolConstants.ATTR_REFRESH_RECURSIVE, false);
+  }
+
+  /**
+   * Refreshes the resources as specified by the given launch configuration.
+   * 
+   * @param configuration
+   *          launch configuration
+   * @param context
+   *          context used to expand variables
+   * @param monitor
+   *          progress monitor
+   * @throws CoreException
+   *           if an exception occurrs while refreshing resources
+   */
+  public static void refreshResources(ILaunchConfiguration configuration, ExpandVariableContext context, IProgressMonitor monitor)
+      throws CoreException {
+    String scope = getRefreshScope(configuration);
+    if (scope == null)
+      return;
+
+    ToolUtil.VariableDefinition varDef = ToolUtil.extractVariableTag(scope, 0);
+    if (varDef.start == -1 || varDef.end == -1 || varDef.name == null) {
+      String msg = ExternalToolsModelMessages.format(
+          "DefaultRunnerContext.invalidRefreshVarFormat", new Object[] { configuration.getName() }); //$NON-NLS-1$
+      abort(msg, null, 0);
+    }
+
+    RefreshScopeVariableRegistry registry = ExternalToolsPlugin.getDefault().getRefreshVariableRegistry();
+    RefreshScopeVariable variable = registry.getRefreshVariable(varDef.name);
+    if (variable == null) {
+      String msg = ExternalToolsModelMessages.format(
+          "DefaultRunnerContext.noRefreshVarNamed", new Object[] { configuration.getName(), varDef.name }); //$NON-NLS-1$
+      abort(msg, null, 0);
+    }
+
+    int depth = IResource.DEPTH_ZERO;
+    if (isRefreshRecursive(configuration))
+      depth = IResource.DEPTH_INFINITE;
+
+    if (monitor.isCanceled())
+      return;
+
+    IResource[] resources = variable.getExpander().getResources(varDef.name, varDef.argument, context);
+    if (resources == null || resources.length == 0)
+      return;
+
+    monitor.beginTask(ExternalToolsModelMessages.getString("DefaultRunnerContext.refreshResources"), //$NON-NLS-1$
+        resources.length);
+
+    MultiStatus status = new MultiStatus(IExternalToolConstants.PLUGIN_ID, 0, ExternalToolsLaunchConfigurationMessages
+        .getString("ExternalToolsUtil.Exception(s)_occurred_during_refresh._2"), null); //$NON-NLS-1$
+    for (int i = 0; i < resources.length; i++) {
+      if (monitor.isCanceled())
+        break;
+      if (resources[i] != null && resources[i].isAccessible()) {
+        try {
+          resources[i].refreshLocal(depth, null);
+        } catch (CoreException e) {
+          status.merge(e.getStatus());
+        }
+      }
+      monitor.worked(1);
+    }
+
+    monitor.done();
+    if (!status.isOK()) {
+      throw new CoreException(status);
+    }
+  }
+
+  /**
+   * Returns whether this tool is to be run in the background..
+   * 
+   * @param configuration
+   * @return whether this tool is to be run in the background
+   * @throws CoreException
+   *           if unable to access the associated attribute
+   */
+  public static boolean isBackground(ILaunchConfiguration configuration) throws CoreException {
+    return configuration.getAttribute(IExternalToolConstants.ATTR_RUN_IN_BACKGROUND, false);
+  }
+
+  /**
+   * Returns a launch configuration from the given ICommand arguments. If the given arguments are from an old-style external tool,
+   * an unsaved working copy will be created from the arguments and returned.
+   * 
+   * @param commandArgs
+   *          the builder ICommand arguments
+   * @param newName
+   *          a new name for the config if the one in the command is invalid
+   * @return a launch configuration, a launch configuration working copy, or <code>null</code> if not possible.
+   */
+  public static ILaunchConfiguration configFromBuildCommandArgs(Map commandArgs) {
+    String configHandle = (String) commandArgs.get(LAUNCH_CONFIG_HANDLE);
+    if (configHandle == null) {
+      // Probably an old-style external tool. Try to migrate.
+      return ExternalToolMigration.configFromArgumentMap(commandArgs);
+    }
+    try {
+      return DebugPlugin.getDefault().getLaunchManager().getLaunchConfiguration(configHandle);
+    } catch (CoreException e) {
+      return null;
+    }
+  }
+
+  /**
+   * Executes an external progam and saves the LaunchConfiguration under external tools
+   * 
+   * @param command
+   *          external tools command name
+   * @param executable
+   *          executable path i.e.c:\apache\apache.exe
+   * @param arguments
+   *          arguments for this configuration
+   * @param background
+   *          run this configuration in background mode
+   */
+  public static void execute(String command, String executable, String arguments, boolean background) {
+    execute(command, executable, null, arguments, background);
+  }
+  
+  
+  public static void execute(String command, String executable, String workingDirectory, String arguments, boolean background) {
+    ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
+    ILaunchConfigurationType type = manager.getLaunchConfigurationType(IExternalToolConstants.ID_PROGRAM_LAUNCH_CONFIGURATION_TYPE);
+
+    ILaunchConfigurationWorkingCopy wc = null;
+    try {
+      wc = type.newInstance(null, command);
+    } catch (CoreException e) {
+      //some exception handling
+    }
+    wc.setAttribute(IExternalToolConstants.ATTR_LOCATION, executable);
+    if (workingDirectory != null) {
+      wc.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, workingDirectory);
+    }
+    if (arguments != null) {
+      wc.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, arguments);
+    }
+    wc.setAttribute(IExternalToolConstants.ATTR_RUN_IN_BACKGROUND, background);
+
+    //		saving will add the configuration to the external tools configurations
+    ILaunchConfiguration config;
+    try {
+      config = wc.doSave();
+      config.launch(ILaunchManager.RUN_MODE, null);
+    } catch (CoreException e) {
+    }
+
+  }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/IExternalToolConstants.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/IExternalToolConstants.java
new file mode 100644
index 0000000..3a00faa
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/IExternalToolConstants.java
@@ -0,0 +1,384 @@
+package net.sourceforge.phpdt.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 {
+	/**
+	 * Plugin identifier for external tools (value <code>org.eclipse.ui.externaltools</code>).
+	 */
+	public static final String PLUGIN_ID = "net.sourceforge.phpeclipse.externaltools"; //$NON-NLS-1$;
+
+	// ------- Extensions Points -------
+	/**
+	 * Extension point to declare the launch configuration type that should be
+	 * created when duplicating an existing configuration as a project builder.
+	 */
+	public static final String EXTENSION_POINT_CONFIGURATION_DUPLICATION_MAPS = "configurationDuplicationMaps"; //$NON-NLS-1$
+	/**
+	 * Extension point to declare argument variables
+	 * (value <code>argumentVariables</code>).
+	 */
+	public static final String EXTENSION_POINT_ARGUMENT_VARIABLES = "argumentVariables"; //$NON-NLS-1$
+
+	/**
+	 * Extension point to declare file variables
+	 * (value <code>fileVariables</code>).
+	 */
+	public static final String EXTENSION_POINT_FILE_VARIABLES = "fileVariables"; //$NON-NLS-1$
+
+	/**
+	 * Extension point to declare directory variables
+	 * (value <code>directoryVariables</code>).
+	 */
+	public static final String EXTENSION_POINT_DIRECTORY_VARIABLES = "directoryVariables"; //$NON-NLS-1$
+
+	/**
+	 * Extension point to declare refresh scope variables
+	 * (value <code>refreshVariables</code>).
+	 */
+	public static final String EXTENSION_POINT_REFRESH_VARIABLES = "refreshVariables"; //$NON-NLS-1$
+
+	// ------- Views -------
+
+	/**
+	 * Ant View identifier (value <code>org.eclipse.ui.externaltools.AntView</code>).
+	 */
+	//public static final String ANT_VIEW_ID = PLUGIN_ID + ".AntView"; //$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 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 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 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 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 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$
+
+	// ------- Refresh 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 project resource (value <code>project</code>).
+	 */
+	public static final String VAR_PROJECT = "project"; //$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 a resource (value <code>resource</code>).
+	 */
+	public static final String VAR_RESOURCE = "resource"; //$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$
+
+	// ------- 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$
+
+	// ------- Images -------
+	/**
+	 * External tools wizard banner image
+	 */
+	public static final String IMG_WIZBAN_EXTERNAL_TOOLS = PLUGIN_ID + ".IMG_WIZBAN_EXTERNAL_TOOLS"; //$NON-NLS-1$
+
+	/**
+	 * Refresh action image
+	 */
+	public static final String IMG_ACTION_REFRESH = PLUGIN_ID + ".IMG_ACTION_REFRESH"; //$NON-NLS-1$
+
+	/**
+	 * Main tab image.
+	 */
+	public static final String IMG_TAB_MAIN = PLUGIN_ID + ".IMG_TAB_MAIN"; //$NON-NLS-1$
+
+	/**
+	 * Options tab image.
+	 */
+	public static final String IMG_TAB_OPTIONS = PLUGIN_ID + ".IMG_TAB_OPTIONS"; //$NON-NLS-1$
+
+	/**
+	 * Ant Targets tab image.
+	 */
+	public static final String IMG_TAB_ANT_TARGETS = PLUGIN_ID + ".IMG_TAB_ANT_TARGETS"; //$NON-NLS-1$
+
+	// ------- Launch configuration types --------
+	/**
+	 * Ant launch configuration type identifier.
+	 */
+//	public static final String ID_ANT_LAUNCH_CONFIGURATION_TYPE = "org.eclipse.ant.AntLaunchConfigurationType"; //$NON-NLS-1$
+	
+	/**
+	 * Ant builder launch configuration type identifier. Ant project builders
+	 * are of this type.
+	 */
+//	public static final String ID_ANT_BUILDER_LAUNCH_CONFIGURATION_TYPE = "org.eclipse.ant.AntBuilderLaunchConfigurationType"; //$NON-NLS-1$
+
+	/**
+	 * Program launch configuration type identifier.
+	 */
+	public static final String ID_PROGRAM_LAUNCH_CONFIGURATION_TYPE = "net.sourceforge.phpdt.externaltools.ProgramLaunchConfigurationType"; //$NON-NLS-1$
+	
+	/**
+	 * Program builder launch configuration type identifier. Program project
+	 * builders are of this type.
+	 */
+	public static final String ID_PROGRAM_BUILDER_LAUNCH_CONFIGURATION_TYPE = "net.sourceforge.phpdt.externaltools.ProgramBuilderLaunchConfigurationType"; //$NON-NLS-1$	
+
+	// ------- Launch configuration category --------
+	/**
+	 * Identifier for external tools launch configuration category. Launch
+	 * configuration types for external tools that appear in the external tools
+	 * launch configuration dialog should belong to this category.
+	 */
+	public static final String ID_EXTERNAL_TOOLS_LAUNCH_CATEGORY = "net.sourceforge.phpdt.externaltools"; //$NON-NLS-1$
+	/**
+	 * Identifier for external tools launch configuration builders category.
+	 * Launch configuration types that can be added as project builders should
+	 * belong to this category.
+	 */
+	public static final String ID_EXTERNAL_TOOLS_BUILDER_LAUNCH_CATEGORY = "net.sourceforge.phpdt.externaltools.builder"; //$NON-NLS-1$
+
+	// ------- Launch configuration groups --------
+	/**
+	 * Identifier for external tools launch configuration group. The external
+	 * tools launch configuration group corresponds to the external tools
+	 * category in run mode.
+	 */
+	//public static final String ID_EXTERNAL_TOOLS_LAUNCH_GROUP = "net.sourceforge.phpdt.externaltools.launchGroup"; //$NON-NLS-1$
+	/**
+	 * Identifier for external tools launch configuration group
+	 */
+	//public static final String ID_EXTERNAL_TOOLS_BUILDER_LAUNCH_GROUP = "net.sourceforge.phpdt.externaltools.launchGroup.builder"; //$NON-NLS-1$
+
+	// ------- Common External Tool Launch Configuration Attributes -------
+
+	/**
+	 * Boolean attribute indicating if external tool output should be captured.
+	 * Default value is <code>false</code>.
+	 */
+	public static final String ATTR_CAPTURE_OUTPUT = PLUGIN_ID + ".ATTR_CAPTURE_OUTPUT"; //$NON-NLS-1$
+	/**
+	 * String attribute identifying the location of an external. Default value
+	 * is <code>null</code>. Encoding is tool specific.
+	 */
+	public static final String ATTR_LOCATION = PLUGIN_ID + ".ATTR_LOCATION"; //$NON-NLS-1$
+
+	/**
+	 * Boolean attribute indicating if the user should be prompted for
+	 * arguments before running a tool. Default value is <code>false</code>.
+	 */
+	public static final String ATTR_PROMPT_FOR_ARGUMENTS = PLUGIN_ID + ".ATTR_PROMPT_FOR_ARGUMENTS"; //$NON-NLS-1$
+
+	/**
+	 * Boolean attribute indicating if a refresh scope is recursive. Default
+	 * value is <code>false</code>.
+	 */
+	public static final String ATTR_REFRESH_RECURSIVE = PLUGIN_ID + ".ATTR_REFRESH_RECURSIVE"; //$NON-NLS-1$
+
+	/**
+	 * String attribute identifying the scope of resources that should be
+	 * refreshed after an external tool is run. Default value is
+	 * <code>null</code>, indicating no refresh. Format is ???
+	 */
+	public static final String ATTR_REFRESH_SCOPE = PLUGIN_ID + ".ATTR_REFRESH_SCOPE"; //$NON-NLS-1$
+	
+	/**
+	 * String attribute containing an array of build kinds for which an
+	 * external tool builder should be run.
+	 */
+	public static final String ATTR_RUN_BUILD_KINDS = PLUGIN_ID + ".ATTR_RUN_BUILD_KINDS"; //$NON-NLS-1$
+
+	/**
+	 * Boolean attribute indicating if an external tool should be run in the
+	 * background. Default value is <code>false</code>.
+	 */
+	public static final String ATTR_RUN_IN_BACKGROUND = PLUGIN_ID + ".ATTR_RUN_IN_BACKGROUND"; //$NON-NLS-1$
+	
+	/**
+	 * Boolean attribute indicating if the console should be shown on external
+	 * tool output. Default value is <code>false</code>.
+	 */
+	public static final String ATTR_SHOW_CONSOLE = PLUGIN_ID + ".ATTR_SHOW_CONSOLE"; //$NON-NLS-1$
+
+	/**
+	 * String attribute containing the arguments that should be passed to the
+	 * tool. Default value is <code>null</code>, and encoding is tool specific.
+	 */
+	public static final String ATTR_TOOL_ARGUMENTS = PLUGIN_ID + ".ATTR_TOOL_ARGUMENTS"; //$NON-NLS-1$
+
+	/**
+	 * String attribute identifying the working directory of an external tool.
+	 * Default value is <code>null</code>, which indicates a default working
+	 * directory, which is tool specific.
+	 */
+	public static final String ATTR_WORKING_DIRECTORY = PLUGIN_ID + ".ATTR_WORKING_DIRECTORY"; //$NON-NLS-1$
+
+	// ------- Common Ant Launch Configuration Attributes -------
+	/**
+	 * String attribute indicating the Ant targets to execute. Default value is
+	 * <code>null</code> which indicates that the default target is to be
+	 * executed. Format is a comma separated listing of targets.
+	 */
+	public static final String ATTR_ANT_TARGETS = PLUGIN_ID + ".ATTR_ANT_TARGETS"; //$NON-NLS-1$
+
+	/**
+	 * Map attribute indicating the Ant properties to be defined during the
+	 * build. Default value is <code>null</code> which indicates no additional
+	 * properties will be defined.
+	 */
+	public static final String ATTR_ANT_PROPERTIES = PLUGIN_ID + ".ATTR_ANT_PROPERTIES"; //$NON-NLS-1$					
+
+	/**
+	 * String attribute indicating the Ant targets to execute. Default value is
+	 * <code>null</code> which indicates that no additional property files
+	 * will be defined. Format is a comma separated listing of property files.
+	 */
+	//public static final String ATTR_ANT_PROPERTY_FILES = PLUGIN_ID + ".ATTR_ANT_PROPERTY_FILES"; //$NON-NLS-1$
+	
+	/**
+ 	* String attribute indicating the custom runtime classpath to use for an Ant
+ 	* build. Default value is <code>null</code> which indicates that the global
+ 	* classpath is to be used. Format is a comma separated listing of URLs.
+  	*/
+	//public static final String ATTR_ANT_CUSTOM_CLASSPATH = PLUGIN_ID + ".ATTR_ANT_CUSTOM_CLASSPATH"; //$NON-NLS-1$
+	
+	/**
+	 * String attribute indicating the custom Ant home to use for an Ant build.
+	 * Default value is <code>null</code> which indicates that no Ant homeis to
+	 * be set 
+	 */
+	//public static final String ATTR_ANT_HOME = PLUGIN_ID + ".ATTR_ANT_HOME"; //$NON-NLS-1$
+	
+	/**
+	 * Identifier for ant processes (value <code>ant</code>). This identifier is
+	 * set as the value for the <code>IProcess.ATTR_PROCESS_TYPE</code>
+	 * attribute in processes create by the ant launch delegate.
+	 */
+	//public static final String ID_ANT_PROCESS_TYPE = "ant"; //$NON-NLS-1$									
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/IRunnerLog.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/IRunnerLog.java
new file mode 100644
index 0000000..5172569
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/IRunnerLog.java
@@ -0,0 +1,43 @@
+package net.sourceforge.phpdt.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/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/StringMatcher.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/StringMatcher.java
new file mode 100644
index 0000000..e4c530b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/StringMatcher.java
@@ -0,0 +1,388 @@
+package net.sourceforge.phpdt.externaltools.model;
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp.  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
+**********************************************************************/
+
+import java.util.Vector;
+
+/**
+ * Copied from net.sourceforge.phpdt.internal.ui.util.StringMatcher
+ * 
+ *  A string pattern matcher, suppporting * and ? wildcards.
+ */
+public class StringMatcher {
+	protected String fPattern;
+	protected int fLength; // pattern length
+	protected boolean fIgnoreWildCards;
+	protected boolean fIgnoreCase;
+	protected boolean fHasLeadingStar;
+	protected boolean fHasTrailingStar;
+	protected String fSegments[]; //the given pattern is split into * separated segments
+
+	/* boundary value beyond which we don't need to search in the text */
+	protected int fBound= 0;
+
+
+	protected static final char fSingleWildCard= '\u0000';
+
+	public static class Position {
+		int start; //inclusive
+		int end; //exclusive
+		public Position(int start, int end) {
+			this.start= start;
+			this.end= end;
+		}
+		public int getStart() {
+			return start;
+		}
+		public int getEnd() {
+			return end;
+		}
+	}
+	/**
+	 * StringMatcher constructor takes in a String object that is a simple
+	 * pattern which may contain �*� for 0 and many characters and
+	 * �?� for exactly one character.
+	 *
+	 * Literal '*' and '?' characters must be escaped in the pattern
+	 * e.g., "\*" means literal "*", etc.
+	 *
+	 * Escaping any other character (including the escape character itself),
+	 * just results in that character in the pattern.
+	 * e.g., "\a" means "a" and "\\" means "\"
+	 *
+	 * If invoking the StringMatcher with string literals in Java, don't forget
+	 * escape characters are represented by "\\".
+	 *
+	 * @param pattern the pattern to match text against
+	 * @param ignoreCase if true, case is ignored
+	 * @param ignoreWildCards if true, wild cards and their escape sequences are ignored
+	 * 		  (everything is taken literally).
+	 */
+	public StringMatcher(String pattern, boolean ignoreCase, boolean ignoreWildCards) {
+		if (pattern == null)
+			throw new IllegalArgumentException();
+		fIgnoreCase= ignoreCase;
+		fIgnoreWildCards= ignoreWildCards;
+		fPattern= pattern;
+		fLength= pattern.length();
+
+		if (fIgnoreWildCards) {
+			parseNoWildCards();
+		} else {
+			parseWildCards();
+		}
+	}
+	/**
+	 * Find the first occurrence of the pattern between <code>start</code)(inclusive)
+	 * and <code>end</code>(exclusive).
+	 * @param <code>text</code>, the String object to search in
+	 * @param <code>start</code>, the starting index of the search range, inclusive
+	 * @param <code>end</code>, the ending index of the search range, exclusive
+	 * @return an <code>StringMatcher.Position</code> object that keeps the starting
+	 * (inclusive) and ending positions (exclusive) of the first occurrence of the
+	 * pattern in the specified range of the text; return null if not found or subtext
+	 * is empty (start==end). A pair of zeros is returned if pattern is empty string
+	 * Note that for pattern like "*abc*" with leading and trailing stars, position of "abc"
+	 * is returned. For a pattern like"*??*" in text "abcdf", (1,3) is returned
+	 */
+	public StringMatcher.Position find(String text, int start, int end) {
+		if (text == null)
+			throw new IllegalArgumentException();
+
+		int tlen= text.length();
+		if (start < 0)
+			start= 0;
+		if (end > tlen)
+			end= tlen;
+		if (end < 0 ||start >= end )
+			return null;
+		if (fLength == 0)
+			return new Position(start, start);
+		if (fIgnoreWildCards) {
+			int x= posIn(text, start, end);
+			if (x < 0)
+				return null;
+			return new Position(x, x+fLength);
+		}
+
+		int segCount= fSegments.length;
+		if (segCount == 0)//pattern contains only '*'(s)
+			return new Position (start, end);
+
+		int curPos= start;
+		int matchStart= -1;
+		int i;
+		for (i= 0; i < segCount && curPos < end; ++i) {
+			String current= fSegments[i];
+			int nextMatch= regExpPosIn(text, curPos, end, current);
+			if (nextMatch < 0 )
+				return null;
+			if(i == 0)
+				matchStart= nextMatch;
+			curPos= nextMatch + current.length();
+		}
+		if (i < segCount)
+			return null;
+		return new Position(matchStart, curPos);
+	}
+	/**
+	 * match the given <code>text</code> with the pattern
+	 * @return true if matched eitherwise false
+	 * @param <code>text</code>, a String object
+	 */
+	public boolean match(String text) {
+		return match(text, 0, text.length());
+	}
+	/**
+	 * Given the starting (inclusive) and the ending (exclusive) positions in the
+	 * <code>text</code>, determine if the given substring matches with aPattern
+	 * @return true if the specified portion of the text matches the pattern
+	 * @param String <code>text</code>, a String object that contains the substring to match
+	 * @param int <code>start<code> marks the starting position (inclusive) of the substring
+	 * @param int <code>end<code> marks the ending index (exclusive) of the substring
+	 */
+	public boolean match(String text, int start, int end) {
+		if (null == text)
+			throw new IllegalArgumentException();
+
+		if (start > end)
+			return false;
+
+		if (fIgnoreWildCards)
+			return (end - start == fLength) && fPattern.regionMatches(fIgnoreCase, 0, text, start, fLength);
+		int segCount= fSegments.length;
+		if (segCount == 0 && (fHasLeadingStar || fHasTrailingStar))  // pattern contains only '*'(s)
+			return true;
+		if (start == end)
+			return fLength == 0;
+		if (fLength == 0)
+			return start == end;
+
+		int tlen= text.length();
+		if (start < 0)
+			start= 0;
+		if (end > tlen)
+			end= tlen;
+
+		int tCurPos= start;
+		int bound= end - fBound;
+		if ( bound < 0)
+			return false;
+		int i=0;
+		String current= fSegments[i];
+		int segLength= current.length();
+
+		/* process first segment */
+		if (!fHasLeadingStar){
+			if(!regExpRegionMatches(text, start, current, 0, segLength)) {
+				return false;
+			} else {
+				++i;
+				tCurPos= tCurPos + segLength;
+			}
+		}
+
+		/* process middle segments */
+		while (i < segCount) {
+			current= fSegments[i];
+			int currentMatch;
+			int k= current.indexOf(fSingleWildCard);
+			if (k < 0) {
+				currentMatch= textPosIn(text, tCurPos, end, current);
+				if (currentMatch < 0)
+					return false;
+			} else {
+				currentMatch= regExpPosIn(text, tCurPos, end, current);
+				if (currentMatch < 0)
+					return false;
+			}
+			tCurPos= currentMatch + current.length();
+			i++;
+		}
+
+		/* process final segment */
+		if (!fHasTrailingStar && tCurPos != end) {
+			int clen= current.length();
+			return regExpRegionMatches(text, end - clen, current, 0, clen);
+		}
+		return i == segCount ;
+	}
+	/**
+	 * This method parses the given pattern into segments seperated by wildcard '*' characters.
+	 * Since wildcards are not being used in this case, the pattern consists of a single segment.
+	 */
+	private void parseNoWildCards() {
+		fSegments= new String[1];
+		fSegments[0]= fPattern;
+		fBound= fLength;
+	}
+	/**
+	 * Parses the given pattern into segments seperated by wildcard '*' characters.
+	 * @param p, a String object that is a simple regular expression with �*� and/or �?�
+	 */
+	private void parseWildCards() {
+		if(fPattern.startsWith("*"))//$NON-NLS-1$
+			fHasLeadingStar= true;
+		if(fPattern.endsWith("*")) {//$NON-NLS-1$
+			/* make sure it's not an escaped wildcard */
+			if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') {
+				fHasTrailingStar= true;
+			}
+		}
+
+		Vector temp= new Vector();
+
+		int pos= 0;
+		StringBuffer buf= new StringBuffer();
+		while (pos < fLength) {
+			char c= fPattern.charAt(pos++);
+			switch (c) {
+				case '\\':
+					if (pos >= fLength) {
+						buf.append(c);
+					} else {
+						char next= fPattern.charAt(pos++);
+						/* if it's an escape sequence */
+						if (next == '*' || next == '?' || next == '\\') {
+							buf.append(next);
+						} else {
+							/* not an escape sequence, just insert literally */
+							buf.append(c);
+							buf.append(next);
+						}
+					}
+				break;
+				case '*':
+					if (buf.length() > 0) {
+						/* new segment */
+						temp.addElement(buf.toString());
+						fBound += buf.length();
+						buf.setLength(0);
+					}
+				break;
+				case '?':
+					/* append special character representing single match wildcard */
+					buf.append(fSingleWildCard);
+				break;
+				default:
+					buf.append(c);
+			}
+		}
+
+		/* add last buffer to segment list */
+		if (buf.length() > 0) {
+			temp.addElement(buf.toString());
+			fBound += buf.length();
+		}
+
+		fSegments= new String[temp.size()];
+		temp.copyInto(fSegments);
+	}
+	/**
+	 * @param <code>text</code>, a string which contains no wildcard
+	 * @param <code>start</code>, the starting index in the text for search, inclusive
+	 * @param <code>end</code>, the stopping point of search, exclusive
+	 * @return the starting index in the text of the pattern , or -1 if not found
+	 */
+	protected int posIn(String text, int start, int end) {//no wild card in pattern
+		int max= end - fLength;
+
+		if (!fIgnoreCase) {
+			int i= text.indexOf(fPattern, start);
+			if (i == -1 || i > max)
+				return -1;
+			return i;
+		}
+
+		for (int i= start; i <= max; ++i) {
+			if (text.regionMatches(true, i, fPattern, 0, fLength))
+				return i;
+		}
+
+		return -1;
+	}
+	/**
+	 * @param <code>text</code>, a simple regular expression that may only contain '?'(s)
+	 * @param <code>start</code>, the starting index in the text for search, inclusive
+	 * @param <code>end</code>, the stopping point of search, exclusive
+	 * @param <code>p</code>, a simple regular expression that may contains '?'
+	 * @param <code>caseIgnored</code>, wether the pattern is not casesensitive
+	 * @return the starting index in the text of the pattern , or -1 if not found
+	 */
+	protected int regExpPosIn(String text, int start, int end, String p) {
+		int plen= p.length();
+
+		int max= end - plen;
+		for (int i= start; i <= max; ++i) {
+			if (regExpRegionMatches(text, i, p, 0, plen))
+				return i;
+		}
+		return -1;
+	}
+	/**
+	 *
+	 * @return boolean
+	 * @param <code>text</code>, a String to match
+	 * @param <code>start</code>, int that indicates the starting index of match, inclusive
+	 * @param <code>end</code> int that indicates the ending index of match, exclusive
+	 * @param <code>p</code>, String,  String, a simple regular expression that may contain '?'
+	 * @param <code>ignoreCase</code>, boolean indicating wether code>p</code> is case sensitive
+	 */
+	protected boolean regExpRegionMatches(String text, int tStart, String p, int pStart, int plen) {
+		while (plen-- > 0) {
+			char tchar= text.charAt(tStart++);
+			char pchar= p.charAt(pStart++);
+
+			/* process wild cards */
+			if (!fIgnoreWildCards) {
+				/* skip single wild cards */
+				if (pchar == fSingleWildCard) {
+					continue;
+				}
+			}
+			if (pchar == tchar)
+				continue;
+			if (fIgnoreCase) {
+				if (Character.toUpperCase(tchar) == Character.toUpperCase(pchar))
+					continue;
+				// comparing after converting to upper case doesn't handle all cases;
+				// also compare after converting to lower case
+				if (Character.toLowerCase(tchar) == Character.toLowerCase(pchar))
+					continue;
+			}
+			return false;
+		}
+		return true;
+	}
+	/**
+	 * @param <code>text</code>, the string to match
+	 * @param <code>start</code>, the starting index in the text for search, inclusive
+	 * @param <code>end</code>, the stopping point of search, exclusive
+	 * @param code>p</code>, a string that has no wildcard
+	 * @param <code>ignoreCase</code>, boolean indicating wether code>p</code> is case sensitive
+	 * @return the starting index in the text of the pattern , or -1 if not found
+	 */
+	protected int textPosIn(String text, int start, int end, String p) {
+
+		int plen= p.length();
+		int max= end - plen;
+
+		if (!fIgnoreCase) {
+			int i= text.indexOf(p, start);
+			if (i == -1 || i > max)
+				return -1;
+			return i;
+		}
+
+		for (int i= start; i <= max; ++i) {
+			if (text.regionMatches(true, i, p, 0, plen))
+				return i;
+		}
+
+		return -1;
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/ToolUtil.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/ToolUtil.java
new file mode 100644
index 0000000..13d90a6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/model/ToolUtil.java
@@ -0,0 +1,451 @@
+package net.sourceforge.phpdt.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 net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsModelMessages;
+import net.sourceforge.phpdt.externaltools.internal.registry.ArgumentVariable;
+import net.sourceforge.phpdt.externaltools.internal.registry.ArgumentVariableRegistry;
+import net.sourceforge.phpdt.externaltools.internal.registry.PathLocationVariable;
+import net.sourceforge.phpdt.externaltools.internal.registry.PathLocationVariableRegistry;
+import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
+import net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.MultiStatus;
+
+/**
+ * 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 = ExternalToolsModelMessages.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 = ExternalToolsModelMessages.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 = ExternalToolsModelMessages.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 = ExternalToolsModelMessages.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 = ExternalToolsModelMessages.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 = ExternalToolsModelMessages.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 = ExternalToolsModelMessages.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 = ExternalToolsModelMessages.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 = ExternalToolsModelMessages.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 = ExternalToolsModelMessages.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 = ExternalToolsModelMessages.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;
+		}
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/BuildTypeExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/BuildTypeExpander.java
new file mode 100644
index 0000000..306d459
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/BuildTypeExpander.java
@@ -0,0 +1,9 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+public class BuildTypeExpander implements IVariableTextExpander {
+
+	public String getText(String varTag, String varValue, ExpandVariableContext context) {
+		return context.getBuildType();
+	}
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ExpandVariableContext.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ExpandVariableContext.java
new file mode 100644
index 0000000..b5eeb46
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ExpandVariableContext.java
@@ -0,0 +1,102 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+
+/**
+ * Represents the context the external tool is running in
+ * that a variable uses to expand itself.
+ */
+public final class ExpandVariableContext {
+	public static final ExpandVariableContext EMPTY_CONTEXT = new ExpandVariableContext(null);
+	
+	private IProject project = null;
+	private IResource selectedResource = null;
+	private String buildType = IExternalToolConstants.BUILD_TYPE_NONE;
+	
+	/**
+	 * Create a context for an external tool running
+	 * as a builder on the given project.
+	 * 
+	 * @param project the <code>IProject</code> being built.
+	 * @param buildKind the kind of build being performed
+	 * 		(see <code>IncrementalProjectBuilder</code>).
+	 */
+	public ExpandVariableContext(IProject project, int buildKind) {
+		super();
+		this.project = project;
+		switch (buildKind) {
+			case IncrementalProjectBuilder.INCREMENTAL_BUILD :
+				this.buildType = IExternalToolConstants.BUILD_TYPE_INCREMENTAL;
+				break;
+			case IncrementalProjectBuilder.FULL_BUILD :
+				this.buildType = IExternalToolConstants.BUILD_TYPE_FULL;
+				break;
+			case IncrementalProjectBuilder.AUTO_BUILD :
+				this.buildType = IExternalToolConstants.BUILD_TYPE_AUTO;
+				break;
+			default :
+				this.buildType = IExternalToolConstants.BUILD_TYPE_NONE;
+				break;
+		}
+	}
+	
+	/**
+	 * Create a context for an external tool running
+	 * with the given resource selected.
+	 * 
+	 * @param selectedResource the <code>IResource</code> selected
+	 * 		or <code>null</code> if none.
+	 */
+	public ExpandVariableContext(IResource selectedResource) {
+		super();
+		if (selectedResource != null) {
+			this.selectedResource = selectedResource;
+			this.project = selectedResource.getProject();
+		}
+	}
+	
+	/**
+	 * Returns the build type being performed if the
+	 * external tool is being run as a project builder.
+	 * 
+	 * @return one of the <code>IExternalToolConstants.BUILD_TYPE_*</code> constants.
+	 */
+	public String getBuildType() {
+		return buildType;
+	}
+	
+	/**
+	 * Returns the project which the variable can use. This
+	 * will the the project being built if the tool is being
+	 * run as a builder. Otherwise, it is the project of the
+	 * selected resource, or <code>null</code> if none.
+	 * 
+	 * @return the <code>IProject</code> or <code>null</code> if none
+	 */
+	public IProject getProject() {
+		return project;
+	}
+	
+	/**
+	 * Returns the resource selected at the time the tool
+	 * is run, or <code>null</code> if none selected.
+	 * 
+	 * @return the <code>IResource</code> selected, or <code>null</code> if none
+	 */
+	public IResource getSelectedResource() {
+		return selectedResource;
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/FileExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/FileExpander.java
new file mode 100644
index 0000000..17779cb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/FileExpander.java
@@ -0,0 +1,34 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Expands a variable into the last opened PHP file 
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class FileExpander extends ResourceExpander { //implements IVariableTextExpander {
+
+  /**
+   * Create an instance
+   */
+  public FileExpander() {
+    super();
+  }
+
+  /**
+   * Returns a string representation of the path to a file or directory
+   * for the given variable tag and value or <code>null</code>.
+   * 
+   * @see IVariableTextExpander#getText(String, String, ExpandVariableContext)
+   */
+  public String getText(String varTag, String varValue, ExpandVariableContext context) {
+    IPath path = getPath(varTag, varValue, context);
+    if (path != null) {
+      return path.toString();
+    }
+    return "<no file selected>";
+  }
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableComponent.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableComponent.java
new file mode 100644
index 0000000..722ffb2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableComponent.java
@@ -0,0 +1,77 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.group.IGroupDialogPage;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Represents the API for a client extending one of the
+ * variable extension points to provide visual editing
+ * of the variable.
+ * <p>
+ * This interface is not to be extended by clients. Clients
+ * may implement this interface.
+ * </p>
+ */
+public interface IVariableComponent {
+	/**
+	 * Returns the control to edit the variable
+	 * value, otherwise <code>null</code> if no editing
+	 * supported or if <code>createContents</code> has
+	 * not been called yet
+	 * 
+	 * @return the main control for the variable component
+	 * 		or <code>null</code> if none
+	 */
+	public Control getControl();
+	
+	/**
+	 * Creates the control to edit the variable. Does nothing
+	 * if no editing supported.
+	 * 
+	 * @param parent the composite to parent all controls to
+	 * @param varTag the variable tag name to create the controls for
+	 * @param page the dialog page this visual component will be part of
+	 */
+	public void createContents(Composite parent, String varTag, IGroupDialogPage page);
+
+	/**
+	 * Returns the variable value as specified by
+	 * the user thru the visual component.
+	 * 
+	 * @return the variable value as indicated by the visual component
+	 */
+	public String getVariableValue();
+
+	/**
+	 * Returns whether the variable's visual component has an
+	 * acceptable value.
+	 * 
+	 * @return <code>true</code> if all value acceptable, or <code>false</code> otherwise
+	 */
+	public boolean isValid();
+
+	/**
+	 * Sets the visual component to represent the
+	 * given variable value.
+	 * 
+	 * @param varValue the variable value the visual component should indicate
+	 */
+	public void setVariableValue(String varValue);
+
+	/**
+	 * Validates visual component current values entered by the
+	 * user and updates it's valid state if needed
+	 */
+	public void validate();
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableLocationExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableLocationExpander.java
new file mode 100644
index 0000000..0a79960
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableLocationExpander.java
@@ -0,0 +1,39 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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.IPath;
+
+/**
+ * Responsible for expanding a variable into the location
+ * path of a file or directory.
+ * <p>
+ * Implementation of this interface will be treated like
+ * a singleton. That is, only one instance will be created
+ * per variable extension.
+ * </p><p>
+ * This interface is not to be extended by clients. Clients
+ * may implement this interface.
+ * </p>
+ */
+public interface IVariableLocationExpander {
+	/**
+	 * Returns the path location to a file or directory
+	 * for the given variable tag and value. The path does
+	 * not need to exist.
+	 * 
+	 * @param varTag the variable tag name
+	 * @param varValue the value for the variable
+	 * @param context the context the variable should use to expand itself
+	 * @return the <code>IPath</code> to a file/directory
+	 * 		or <code>null</code> if not possible
+	 */
+	public IPath getPath(String varTag, String varValue, ExpandVariableContext context);
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableResourceExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableResourceExpander.java
new file mode 100644
index 0000000..a1aac20
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableResourceExpander.java
@@ -0,0 +1,38 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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.resources.IResource;
+
+/**
+ * Responsible for expanding a variable into a list of
+ * <code>IResource</code>.
+ * <p>
+ * Implementation of this interface will be treated like
+ * a singleton. That is, only one instance will be created
+ * per variable extension.
+ * </p><p>
+ * This interface is not to be extended by clients. Clients
+ * may implement this interface.
+ * </p>
+ */
+public interface IVariableResourceExpander {
+	/**
+	 * Returns the <code>IResource</code> list
+	 * for the given variable tag and value.
+	 * 
+	 * @param varTag the variable tag name
+	 * @param varValue the value for the variable
+	 * @param context the context the variable should use to expand itself
+	 * @return the list of <code>IResource</code> or <code>null</code> if not
+	 * 		possible (note, elements of the list can be <code>null</code>)
+	 */
+	public IResource[] getResources(String varTag, String varValue, ExpandVariableContext context);
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableTextExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableTextExpander.java
new file mode 100644
index 0000000..16ee242
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/IVariableTextExpander.java
@@ -0,0 +1,35 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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:
+**********************************************************************/
+
+/**
+ * Responsible for expanding a variable into text format.
+ * <p>
+ * Implementation of this interface will be treated like
+ * a singleton. That is, only one instance will be created
+ * per variable extension.
+ * </p><p>
+ * This interface is not to be extended by clients. Clients
+ * may implement this interface.
+ * </p>
+ */
+public interface IVariableTextExpander {
+	/**
+	 * Returns the expanded text for the given variable
+	 * tag and value.
+	 * 
+	 * @param varTag the variable tag name
+	 * @param varValue the value for the variable
+	 * @param context the context the variable should use to expand itself
+	 * @return the text of the expanded variable
+	 * 		or <code>null</code> if not possible
+	 */
+	public String getText(String varTag, String varValue, ExpandVariableContext context);
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/LocalhostExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/LocalhostExpander.java
new file mode 100644
index 0000000..2966aaf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/LocalhostExpander.java
@@ -0,0 +1,21 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Expands a variable into the predefined localhost.
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class LocalhostExpander implements IVariableTextExpander {
+
+  public String getText(String varTag, String varValue, ExpandVariableContext context) {
+    IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore(); 
+    return store.getString(WebUI.PHP_LOCALHOST_PREF);
+  }
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ProjectNameExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ProjectNameExpander.java
new file mode 100644
index 0000000..11fe671
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ProjectNameExpander.java
@@ -0,0 +1,22 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+import org.eclipse.core.resources.IProject;
+
+/**
+ * Extracts the project name from a variable context
+ */
+public class ProjectNameExpander implements IVariableTextExpander {
+
+	/**
+	 * Returns the name of the project in the given context or
+	 * <code>null</code> if there is no project in the context.
+	 */
+	public String getText(String varTag, String varValue, ExpandVariableContext context) {
+		IProject project= context.getProject();
+		if (project != null) {
+			return project.getName();
+		}
+		return null;
+	}
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceComponent.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceComponent.java
new file mode 100644
index 0000000..143a6e6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceComponent.java
@@ -0,0 +1,265 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.group.IGroupDialogPage;
+import net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsModelMessages;
+import net.sourceforge.phpdt.externaltools.model.ToolUtil;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+/**
+ * Visual component to edit the resource type variable
+ * value.
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class ResourceComponent implements IVariableComponent {
+	private IGroupDialogPage page;
+	private boolean isValid = true;
+	
+	protected Group mainGroup;
+	protected Button selectedResourceButton;
+	protected Button specificResourceButton;
+	protected TreeViewer resourceList;
+	private IResource selectedResource;
+	
+	/**
+	 * Creates the component
+	 */
+	public ResourceComponent() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on IVariableComponent.
+	 */
+	public void createContents(Composite parent, String varTag, IGroupDialogPage page) {
+		this.page = page;
+		
+		// main composite
+		mainGroup = new Group(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 1;
+		GridData gridData = new GridData(GridData.FILL_BOTH);
+		mainGroup.setLayout(layout);
+		mainGroup.setLayoutData(gridData);
+		mainGroup.setFont(parent.getFont());
+		mainGroup.setText(ToolUtil.buildVariableTag(varTag, null));
+		
+		createSelectedResourceOption();
+		createSpecificResourceOption();
+		createResourceList();
+		
+		updateResourceListEnablement();
+	}
+
+	/**
+	 * Creates the list of resources.
+	 */
+	protected void createResourceList() {
+		Tree tree = new Tree(mainGroup, SWT.SINGLE | SWT.BORDER);
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.heightHint = tree.getItemHeight() * getInitialVisibleItemCount();
+		tree.setLayoutData(data);
+		tree.setFont(mainGroup.getFont());
+		
+		resourceList = new TreeViewer(tree);
+		resourceList.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				validateResourceListSelection();
+				selectedResource= (IResource) ((IStructuredSelection)event.getSelection()).getFirstElement();
+			}
+		});
+		resourceList.setContentProvider(new WorkbenchContentProvider());
+		resourceList.setLabelProvider(new WorkbenchLabelProvider());
+		resourceList.setInput(ResourcesPlugin.getWorkspace().getRoot());
+	}
+	
+	/**
+	 * Creates the option button for using the selected
+	 * resource.
+	 */
+	protected void createSelectedResourceOption() {
+		selectedResourceButton = new Button(mainGroup, SWT.RADIO);
+		selectedResourceButton.setText(ExternalToolsModelMessages.getString("ResourceComponent.selectedResLabel")); //$NON-NLS-1$
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		selectedResourceButton.setLayoutData(data);
+		selectedResourceButton.setFont(mainGroup.getFont());
+		selectedResourceButton.setSelection(true);
+	}
+	
+	/**
+	 * Creates the option button for using a specific
+	 * resource.
+	 */
+	protected void createSpecificResourceOption() {
+		specificResourceButton = new Button(mainGroup, SWT.RADIO);
+		specificResourceButton.setText(ExternalToolsModelMessages.getString("ResourceComponent.specificResLabel")); //$NON-NLS-1$
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		specificResourceButton.setLayoutData(data);
+		specificResourceButton.setFont(mainGroup.getFont());
+		specificResourceButton.setSelection(false);
+		
+		specificResourceButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				updateResourceListEnablement();
+			}
+		});
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on IVariableComponent.
+	 */
+	public Control getControl() {
+		return mainGroup;
+	}
+
+	/**
+	 * Returns the dialog page this component is part of
+	 */
+	protected final IGroupDialogPage getPage() {
+		return page;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on IVariableComponent.
+	 */
+	public String getVariableValue() {
+		if (selectedResourceButton != null && selectedResourceButton.getSelection())
+			return null;
+		
+		if (resourceList != null) {
+			if (selectedResource != null)
+				return selectedResource.getFullPath().toString();
+		}
+		
+		return null;
+	}
+
+	/**
+	 * Returns the number of items to be visible in the
+	 * resource list. This will determine the initial height.
+	 */
+	protected int getInitialVisibleItemCount() {
+		return 10;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on IVariableComponent.
+	 */
+	public boolean isValid() {
+		return isValid;
+	}
+
+	/**
+	 * Sets whether the component's values are all valid.
+	 * Updates the components's page valid state. No action
+	 * taken if new valid state same as current one.
+	 * 
+	 * @param isValid <code>true</code> if all values valid,
+	 * 		<code>false</code> otherwise
+	 */
+	protected final void setIsValid(boolean isValid) {
+		if (this.isValid != isValid) {
+			this.isValid = isValid;
+			this.page.updateValidState();
+		}
+	}
+	
+	/**
+	 * Updates the enablement of the resource list if needed
+	 */
+	protected void updateResourceListEnablement() {
+		if (specificResourceButton != null && resourceList != null)
+			resourceList.getTree().setEnabled(specificResourceButton.getSelection());
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on IVariableComponent.
+	 */
+	public void setVariableValue(String varValue) {
+		if (varValue == null || varValue.length() == 0) {
+			if (selectedResourceButton != null)
+				selectedResourceButton.setSelection(true);
+			if (specificResourceButton != null)
+				specificResourceButton.setSelection(false);
+			if (resourceList != null)
+				resourceList.getTree().setEnabled(false);
+		} else {
+			if (selectedResourceButton != null)
+				selectedResourceButton.setSelection(false);
+			if (specificResourceButton != null)
+				specificResourceButton.setSelection(true);
+			if (resourceList != null) {
+				resourceList.getTree().setEnabled(true);
+				IResource member = ResourcesPlugin.getWorkspace().getRoot().findMember(varValue);
+				if (member != null)
+					resourceList.setSelection(new StructuredSelection(member), true);
+				else
+					resourceList.setSelection(StructuredSelection.EMPTY);
+			}
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on IVariableComponent.
+	 */
+	public void validate() {
+		if (specificResourceButton != null && specificResourceButton.getSelection()) {
+			validateResourceListSelection();
+		}
+
+		getPage().setMessage(null, IMessageProvider.NONE);
+		setIsValid(true);
+	}
+
+	/**
+	 * Returns whether that the resource list selection is valid.
+	 * If the list was not created, returns <code>true</code>.
+	 * 
+	 * @return <code>true</code> to continue validating other
+	 * 	fields, <code>false</code> to stop.
+	 */
+	protected boolean validateResourceListSelection() {
+		if (resourceList == null)
+			return true;
+
+		if (resourceList.getSelection().isEmpty()) {
+			getPage().setMessage(ExternalToolsModelMessages.getString("ResourceComponent.selectionRequired"), IMessageProvider.WARNING); //$NON-NLS-1$
+			setIsValid(false);
+			return false;
+		}
+		
+		return true;
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceContainerExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceContainerExpander.java
new file mode 100644
index 0000000..5e8bf04
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceContainerExpander.java
@@ -0,0 +1,40 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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.resources.IResource;
+
+/**
+ * Expands a resource's container type variable into the desired
+ * result format.
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class ResourceContainerExpander extends ResourceExpander {
+
+	/**
+	 * Create an instance
+	 */
+	public ResourceContainerExpander() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on ResourceExpander.
+	 */
+	/*package*/ IResource expand(String varValue, ExpandVariableContext context) {
+		IResource resource = super.expand(varValue, context);
+		if (resource != null)
+			return resource.getParent();
+		else
+			return null;
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceExpander.java
new file mode 100644
index 0000000..fe5cfa8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceExpander.java
@@ -0,0 +1,124 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Expands a resource type variable into the desired
+ * result format.
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class ResourceExpander implements IVariableLocationExpander, IVariableResourceExpander, IVariableTextExpander {
+
+	/**
+	 * Create an instance
+	 */
+	public ResourceExpander() {
+		super();
+	}
+
+	/**
+	 * Expands the variable to a resource.
+	 */
+	/*package*/ IResource expand(String varValue, ExpandVariableContext context) {
+		if (varValue != null && varValue.length() > 0) {
+			return expandToMember(varValue);
+		} else {
+			return expandUsingContext(context);
+		}
+	}
+	
+	/**
+	 * Expands using the current context information.
+	 * By default, return the selected resource of the
+	 * context.
+	 */
+	/*package*/ IResource expandUsingContext(ExpandVariableContext context) {
+		return context.getSelectedResource();
+	}
+	
+	/**
+	 * Expands the variable value to a resource. The value
+	 * will not be <code>null</code> nor empty. By default,
+	 * lookup the member from the workspace root.
+	 */
+	/*package*/ IResource expandToMember(String varValue) {
+		return getWorkspaceRoot().findMember(varValue);
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on IVariableLocationExpander.
+	 */
+	public IPath getPath(String varTag, String varValue, ExpandVariableContext context) {
+		IResource resource = expand(varValue, context);
+		if (resource != null) {
+			if (isPathVariable(varTag)) {
+				return resource.getFullPath();
+			} else {
+				return resource.getLocation();
+			}
+		} else {
+			return null;
+		}
+	}
+	
+	/**
+	 * Returns whether the given variable tag is a known path
+	 * variable tag. Path variable tags represent variables that
+	 * expand to paths relative to the workspace root.
+	 */
+	private boolean isPathVariable(String varTag) {
+		return varTag.equals(IExternalToolConstants.VAR_CONTAINER_PATH) ||
+				varTag.equals(IExternalToolConstants.VAR_PROJECT_PATH) ||
+				varTag.equals(IExternalToolConstants.VAR_RESOURCE_PATH);
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on IVariableResourceExpander.
+	 */
+	public IResource[] getResources(String varTag, String varValue, ExpandVariableContext context) {
+		IResource resource = expand(varValue, context);
+		if (resource != null) {
+			return new IResource[] {resource};
+		} else {
+			return null;
+		}
+	}
+	
+	/**
+	 * Returns the workspace root resource.
+	 */
+	protected final IWorkspaceRoot getWorkspaceRoot() {
+		return ResourcesPlugin.getWorkspace().getRoot();
+	}
+	
+	/**
+	 * Returns a string representation of the path to a file or directory
+	 * for the given variable tag and value or <code>null</code>.
+	 * 
+	 * @see IVariableTextExpander#getText(String, String, ExpandVariableContext)
+	 */
+	public String getText(String varTag, String varValue, ExpandVariableContext context) {
+		IPath path= getPath(varTag, varValue, context);
+		if (path != null) {
+			return path.toString();
+		}
+		return null;
+	}
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceProjectExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceProjectExpander.java
new file mode 100644
index 0000000..9df7758
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/ResourceProjectExpander.java
@@ -0,0 +1,47 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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.resources.IResource;
+
+/**
+ * Expands a resource's project type variable into the desired
+ * result format.
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class ResourceProjectExpander extends ResourceExpander {
+
+	/**
+	 * Create an instance
+	 */
+	public ResourceProjectExpander() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on ResourceExpander.
+	 */
+	/*package*/ IResource expandUsingContext(ExpandVariableContext context) {
+		return context.getProject();
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on ResourceExpander.
+	 */
+	/*package*/ IResource expandToMember(String varValue) {
+		IResource member = super.expandToMember(varValue);
+		if (member != null)
+			return member.getProject();
+		else
+			return null;
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/SpecificFileResourceComponent.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/SpecificFileResourceComponent.java
new file mode 100644
index 0000000..cdeb292
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/SpecificFileResourceComponent.java
@@ -0,0 +1,73 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsModelMessages;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Visual component to edit the resource type variable
+ * value for the file location. Variable is limited to a specific
+ * <code>IFile</code> resource.
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class SpecificFileResourceComponent extends ResourceComponent {
+
+	/**
+	 * Creates an instance
+	 */
+	public SpecificFileResourceComponent() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on ResourceComponent.
+	 */
+	protected void createSelectedResourceOption() {
+		// Do not present this option...
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on ResourceComponent.
+	 */
+	protected void createSpecificResourceOption() {
+		Label label = new Label(mainGroup, SWT.NONE);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		label.setLayoutData(data);
+		label.setFont(mainGroup.getFont());
+		label.setText(ExternalToolsModelMessages.getString("ResourceComponent.specificResLabel")); //$NON-NLS-1$
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on ResourceComponent.
+	 */
+	protected boolean validateResourceListSelection() {
+		if (resourceList == null)
+			return true;
+			
+		IStructuredSelection sel = (IStructuredSelection) resourceList.getSelection();
+		IResource resource = (IResource) sel.getFirstElement();
+		if (resource == null || resource.getType() != IResource.FILE) {
+			getPage().setMessage(ExternalToolsModelMessages.getString("ResourceComponent.selectionRequired"), IMessageProvider.WARNING); //$NON-NLS-1$
+			setIsValid(false);
+			return false;
+		}
+		
+		return true;
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/SpecificFolderResourceComponent.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/SpecificFolderResourceComponent.java
new file mode 100644
index 0000000..e0b4aa7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/SpecificFolderResourceComponent.java
@@ -0,0 +1,111 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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 net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsModelMessages;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Visual component to edit the resource type variable
+ * value for the working directory. Variable is limited to a specific
+ * <code>IContainer</code> resource.
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class SpecificFolderResourceComponent extends ResourceComponent {
+
+	/**
+	 * Creates an instance
+	 */
+	public SpecificFolderResourceComponent() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on ResourceComponent.
+	 */
+	protected void createSelectedResourceOption() {
+		// Do not present this option...
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on ResourceComponent.
+	 */
+	protected void createResourceList() {
+		super.createResourceList();
+		if (resourceList != null)
+			resourceList.addFilter(new FileFilter());
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on ResourceComponent.
+	 */
+	protected void createSpecificResourceOption() {
+		Label label = new Label(mainGroup, SWT.NONE);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		label.setLayoutData(data);
+		label.setFont(mainGroup.getFont());
+		label.setText(ExternalToolsModelMessages.getString("ResourceComponent.specificResLabel")); //$NON-NLS-1$
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on ResourceComponent.
+	 */
+	protected boolean validateResourceListSelection() {
+		if (resourceList == null)
+			return true;
+			
+		IStructuredSelection sel = (IStructuredSelection) resourceList.getSelection();
+		IResource resource = (IResource) sel.getFirstElement();
+		if (resource == null || resource.getType() == IResource.FILE) {
+			getPage().setMessage(ExternalToolsModelMessages.getString("ResourceComponent.selectionRequired"), IMessageProvider.WARNING); //$NON-NLS-1$
+			setIsValid(false);
+			return false;
+		}
+		
+		return true;
+	}
+	
+	
+	/**
+	 * Filter to remove any IFile resources.
+	 */
+	private static final class FileFilter extends ViewerFilter {
+		/* (non-Javadoc)
+		 * Method declared on ViewerFilter.
+		 */
+		public boolean select(Viewer viewer, Object parentElement, Object element) {
+			IResource resource = null;
+			if (element instanceof IResource) {
+				resource = (IResource) element;
+			} else {
+				if (element instanceof IAdaptable) {
+					IAdaptable adaptable = (IAdaptable) element;
+					resource = (IResource) adaptable.getAdapter(IResource.class);
+				}
+			}
+			
+			if (resource != null)
+				return resource.getType() != IResource.FILE;
+			else
+				return false;
+		}
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/UrlExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/UrlExpander.java
new file mode 100644
index 0000000..17cbdf5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/UrlExpander.java
@@ -0,0 +1,49 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Expands a variable into a localhost/documentRoot URL string 
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class UrlExpander extends ResourceExpander { //implements IVariableTextExpander {
+
+  /**
+   * Create an instance
+   */
+  public UrlExpander() {
+    super();
+  }
+
+  /**
+   * Returns a string representation to a localhost/documentRoot URL 
+   * for the given variable tag and value or <code>null</code>.
+   * 
+   * @see IVariableTextExpander#getText(String, String, ExpandVariableContext)
+   */
+  public String getText(String varTag, String varValue, ExpandVariableContext context) {
+    IPath path = getPath(varTag, varValue, context);
+    if (path != null) {
+      IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
+      String localhostURL = path.toString();
+      String lowerCaseFileName = localhostURL.toLowerCase();
+      String documentRoot = store.getString(WebUI.PHP_DOCUMENTROOT_PREF);
+      documentRoot = documentRoot.replace('\\', '/');
+      documentRoot = documentRoot.toLowerCase();
+
+      if (lowerCaseFileName.startsWith(documentRoot)) {
+        localhostURL = localhostURL.substring(documentRoot.length());
+        localhostURL = store.getString(WebUI.PHP_LOCALHOST_PREF)+ localhostURL;
+      }
+      return localhostURL;
+    }
+    return "<no file selected>";
+  }
+
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/WorkingSetExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/WorkingSetExpander.java
new file mode 100644
index 0000000..73474d0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/WorkingSetExpander.java
@@ -0,0 +1,56 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ui.IWorkingSet;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Expands a working set type variable into the desired
+ * result format.
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class WorkingSetExpander implements IVariableResourceExpander {
+
+	/**
+	 * Create an instance
+	 */
+	public WorkingSetExpander() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on IVariableResourceExpander.
+	 */
+	public IResource[] getResources(String varTag, String varValue, ExpandVariableContext context) {
+		if (varValue == null || varValue.length() == 0)
+			return null;
+
+		IWorkingSet set = PlatformUI.getWorkbench().getWorkingSetManager().getWorkingSet(varValue);
+		if (set == null)
+			return null;
+			
+		IAdaptable[] elements = set.getElements();
+		IResource[] resources = new IResource[elements.length];
+		for (int i = 0; i < elements.length; i++) {
+			IAdaptable adaptable = elements[i];
+			if (adaptable instanceof IResource)
+				resources[i] = (IResource) adaptable;
+			else
+				resources[i] = (IResource) adaptable.getAdapter(IResource.class);
+		}
+		
+		return resources;
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/WorkspaceExpander.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/WorkspaceExpander.java
new file mode 100644
index 0000000..cf2ab3c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpdt/externaltools/variable/WorkspaceExpander.java
@@ -0,0 +1,36 @@
+package net.sourceforge.phpdt.externaltools.variable;
+
+/**********************************************************************
+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.resources.IResource;
+
+/**
+ * Expands a workspace variable into the desired
+ * result format.
+ * <p>
+ * This class is not intended to be extended by clients.
+ * </p>
+ */
+public class WorkspaceExpander extends ResourceExpander {
+
+	/**
+	 * Create an instance
+	 */
+	public WorkspaceExpander() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on ResourceExpander.
+	 */
+	/*package*/ IResource expandUsingContext(ExpandVariableContext context) {
+		return getWorkspaceRoot();
+	}
+}
diff --git a/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpeclipse/externaltools/ExternalToolsPlugin.java b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpeclipse/externaltools/ExternalToolsPlugin.java
new file mode 100644
index 0000000..811948e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.externaltools/src/net/sourceforge/phpeclipse/externaltools/ExternalToolsPlugin.java
@@ -0,0 +1,216 @@
+package net.sourceforge.phpeclipse.externaltools;
+
+/**********************************************************************
+ 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.net.MalformedURLException;
+import java.net.URL;
+
+import net.sourceforge.phpdt.externaltools.internal.model.ColorManager;
+import net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsImages;
+import net.sourceforge.phpdt.externaltools.internal.model.IPreferenceConstants;
+import net.sourceforge.phpdt.externaltools.internal.model.VariableContextManager;
+import net.sourceforge.phpdt.externaltools.internal.registry.ArgumentVariableRegistry;
+import net.sourceforge.phpdt.externaltools.internal.registry.PathLocationVariableRegistry;
+import net.sourceforge.phpdt.externaltools.internal.registry.RefreshScopeVariableRegistry;
+import net.sourceforge.phpdt.externaltools.model.IExternalToolConstants;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.Bundle;
+
+/**
+ * External tools plug-in class
+ */
+public final class ExternalToolsPlugin extends AbstractUIPlugin {
+  /**
+   * Status representing no problems encountered during operation.
+   */
+  public static final IStatus OK_STATUS = new Status(IStatus.OK, IExternalToolConstants.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
+
+  private static ExternalToolsPlugin plugin;
+
+  private RefreshScopeVariableRegistry refreshVarRegistry;
+
+  private PathLocationVariableRegistry fileLocVarRegistry;
+
+  private PathLocationVariableRegistry dirLocVarRegistry;
+
+  private ArgumentVariableRegistry argumentVarRegistry;
+
+  /**
+   * Create an instance of the External Tools plug-in.
+   */
+  public ExternalToolsPlugin() { // IPluginDescriptor descriptor) {
+    // super(descriptor);
+    plugin = this;
+  }
+
+  /**
+   * Returns the default instance of the receiver. This represents the runtime plugin.
+   */
+  public static ExternalToolsPlugin getDefault() {
+    return plugin;
+  }
+
+  /**
+   * Returns a new <code>IStatus</code> for this plug-in
+   */
+  public static IStatus newErrorStatus(String message, Throwable exception) {
+    return new Status(Status.ERROR, IExternalToolConstants.PLUGIN_ID, 0, message, exception);
+  }
+
+  /**
+   * Returns a new <code>CoreException</code> for this plug-in
+   */
+  public static CoreException newError(String message, Throwable exception) {
+    return new CoreException(new Status(Status.ERROR, IExternalToolConstants.PLUGIN_ID, 0, message, exception));
+  }
+
+  /**
+   * Returns the registry of refresh scope variables.
+   */
+  public ArgumentVariableRegistry getArgumentVariableRegistry() {
+    if (argumentVarRegistry == null)
+      argumentVarRegistry = new ArgumentVariableRegistry();
+    return argumentVarRegistry;
+  }
+
+  /**
+   * Returns the registry of directory location variables.
+   */
+  public PathLocationVariableRegistry getDirectoryLocationVariableRegistry() {
+    if (dirLocVarRegistry == null)
+      dirLocVarRegistry = new PathLocationVariableRegistry(IExternalToolConstants.EXTENSION_POINT_DIRECTORY_VARIABLES);
+    return dirLocVarRegistry;
+  }
+
+  /**
+   * Returns the registry of file location variables.
+   */
+  public PathLocationVariableRegistry getFileLocationVariableRegistry() {
+    if (fileLocVarRegistry == null)
+      fileLocVarRegistry = new PathLocationVariableRegistry(IExternalToolConstants.EXTENSION_POINT_FILE_VARIABLES);
+    return fileLocVarRegistry;
+  }
+
+  /**
+   * Returns the registry of refresh scope variables.
+   */
+  public RefreshScopeVariableRegistry getRefreshVariableRegistry() {
+    if (refreshVarRegistry == null)
+      refreshVarRegistry = new RefreshScopeVariableRegistry();
+    return refreshVarRegistry;
+  }
+
+  /**
+   * Writes the message to the plug-in's log
+   * 
+   * @param message
+   *          the text to write to the log
+   */
+  public void log(String message, Throwable exception) {
+    IStatus status = newErrorStatus(message, exception);
+    //	getLog().log(status);
+    PHPeclipsePlugin.log(status);
+  }
+
+  /**
+   * Returns the ImageDescriptor for the icon with the given path
+   * 
+   * @return the ImageDescriptor object
+   */
+  public ImageDescriptor getImageDescriptor(String path) {
+    try {
+      Bundle bundle = PHPeclipsePlugin.getDefault().getBundle();
+      URL installURL = bundle.getEntry("/"); //$NON-NLS-1$
+      URL url = new URL(installURL, path);
+      return ImageDescriptor.createFromURL(url);
+    } catch (MalformedURLException e) {
+      return null;
+    }
+  }
+
+  /*
+   * (non-Javadoc) Method declared in AbstractUIPlugin.
+   */
+  public void initializeDefaultPreferences(IPreferenceStore prefs) {
+    prefs.setDefault(IPreferenceConstants.PROMPT_FOR_MIGRATION, true);
+
+    PreferenceConverter.setDefault(prefs, IPreferenceConstants.CONSOLE_ERROR_RGB, new RGB(255, 0, 0)); // red - exactly the same as
+                                                                                                       // debug Consol
+    PreferenceConverter.setDefault(prefs, IPreferenceConstants.CONSOLE_WARNING_RGB, new RGB(255, 100, 0)); // orange
+    PreferenceConverter.setDefault(prefs, IPreferenceConstants.CONSOLE_INFO_RGB, new RGB(0, 0, 255)); // blue
+    PreferenceConverter.setDefault(prefs, IPreferenceConstants.CONSOLE_VERBOSE_RGB, new RGB(0, 200, 125)); // green
+    PreferenceConverter.setDefault(prefs, IPreferenceConstants.CONSOLE_DEBUG_RGB, new RGB(0, 0, 0)); // black
+  }
+
+  public static IWorkbenchWindow getActiveWorkbenchWindow() {
+    return PHPeclipsePlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+  }
+
+  /**
+   * Returns the standard display to be used. The method first checks, if the thread calling this method has an associated display.
+   * If so, this display is returned. Otherwise the method returns the default display.
+   */
+  public static Display getStandardDisplay() {
+    Display display = Display.getCurrent();
+    if (display == null) {
+      display = Display.getDefault();
+    }
+    return display;
+  }
+
+  /**
+   * @see org.eclipse.ui.plugin.AbstractUIPlugin#createImageRegistry()
+   */
+  protected ImageRegistry createImageRegistry() {
+    return ExternalToolsImages.initializeImageRegistry();
+  }
+
+  /**
+   * @see org.eclipse.core.runtime.Plugin#startup()
+   */
+  public void startup() throws CoreException {
+//    super.startup();
+    getStandardDisplay().asyncExec(new Runnable() {
+      public void run() {
+        //initialize the variable context manager
+        VariableContextManager.getDefault();
+      }
+    });
+  }
+
+  /**
+   * @see org.eclipse.core.runtime.Plugin#shutdown()
+   */
+  public void shutdown() throws CoreException {
+//    	super.shutdown();
+    ColorManager.getDefault().dispose();
+  }
+
+  /**
+   * Returns the preference color, identified by the given preference.
+   */
+  public static Color getPreferenceColor(String pref) {
+    return ColorManager.getDefault().getColor(
+        PreferenceConverter.getColor(PHPeclipsePlugin.getDefault().getPreferenceStore(), pref));
+  }
+}
\ No newline at end of file