[107722] Implement user settable runtime base location for the server. Updated server editor to support modification using a new section.  Moved deploy directory field to this new section. Refactored runtime base directory handling.
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatServer.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatServer.java
index 8de7627..eee5098 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatServer.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatServer.java
@@ -20,12 +20,18 @@
 	 * for testing environment.
 	 */
 	public static final String PROPERTY_TEST_ENVIRONMENT = "testEnvironment";
-
+	
+	/**
+	 * Property which specifies the directory where the server instance
+	 * exists.  If not specified, instance directory is derived
+	 * from the textEnvironment setting.
+	 */
+	public static final String PROPERTY_INSTANCE_DIR = "instanceDir";
 	/**
 	 * Property which specifies the directory where web applications
 	 * are published.
 	 */
-	public static final String PROPERTY_DEPLOYDIR = "deployDir";
+	public static final String PROPERTY_DEPLOY_DIR = "deployDir";
 
 	/**
 	 * Returns true if this is a test (publish and run code out of the
@@ -34,6 +40,15 @@
 	 * @return boolean
 	 */
 	public boolean isTestEnvironment();
+	
+	/**
+	 * Gets the directory where the server instance exists.  If not set,
+	 * the instance directory is derived from the testEnvironment setting.  
+	 * 
+	 * @return directory where the server instance exists. Returns null
+	 * if not set.
+	 */
+	public String getInstanceDirectory();
 
 	/**
 	 * Gets the directory to which web applications are to be deployed.
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatServerWorkingCopy.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatServerWorkingCopy.java
index 3459ada..75e169b 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatServerWorkingCopy.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatServerWorkingCopy.java
@@ -30,6 +30,15 @@
 	 * @param b boolean
 	 */
 	public void setTestEnvironment(boolean b);
+	
+	/**
+	 * Sets the instance directory for the server. If set to
+	 * null, the instance directory is derived from the
+	 * testEnvironment setting.'
+	 * 
+	 * @param instanceDir absolule path to the instance directory.
+	 */
+	public void setInstanceDirectory(String instanceDir);
 
 	/**
 	 * Set the deployment directory for the server.  May be absolute
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatVersionHandler.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatVersionHandler.java
index ce82ac7..13a2e5c 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatVersionHandler.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/ITomcatVersionHandler.java
@@ -19,10 +19,31 @@
  * 
  */
 public interface ITomcatVersionHandler {
+	/**
+	 * Verifies if the specified path points to a a Tomcat
+	 * installation of this version.
+	 * 
+	 * @param installPath an installation path 
+	 * @return OK status if a valid installation
+	 * exists at the location.  If not valid, the IStatus
+	 * contains an indication of why.
+	 */
 	public IStatus verifyInstallPath(IPath installPath);
 	
+	/**
+	 * Gets the startup class for the Tomcat server.
+	 * 
+	 * @return server startup class
+	 */
 	public String getRuntimeClass();
 	
+	/**
+	 * Gets the startup classpath for the Tomcat server.
+	 * 
+	 * @param installPath an installation path
+	 * @return list of classpath entries required to
+	 * start the Tomcat server.
+	 */
 	public List getRuntimeClasspath(IPath installPath);
 	
 	/**
@@ -45,8 +66,22 @@
 	 */
 	public String[] getExcludedRuntimeProgramArguments(boolean debug, boolean starting);
 	
+	/**
+	 * Gets the startup VM arguments for the Tomcat server.
+	 * 
+	 * @param installPath installation path for the server
+	 * @param configPath configuration path for the server
+	 * @param isTestEnv test environment flag
+	 * @return array of VM arguments for starting the server
+	 */
 	public String[] getRuntimeVMArguments(IPath installPath, IPath configPath, boolean isTestEnv);
 
+	/**
+	 * Gets the contents of the Java policy file for the Tomcat server.
+	 * 
+	 * @param configPath path to configuration
+	 * @return contents of Java policy file in the configuration
+	 */
 	public String getRuntimePolicyFile(IPath configPath);
 
 	/**
@@ -62,11 +97,11 @@
 	 * Returns the runtime base path for relative paths in the server
 	 * configuration.
 	 * 
-	 * @param serverBehaviour TomcatServerBehaviour instance from
-	 * which to determine the base path
-	 * @return the base path
+	 * @param server TomcatServer instance from which to determine
+	 * the base path.
+	 * @return the server base path
 	 */
-	public IPath getRuntimeBaseDirectory(TomcatServerBehaviour serverBehaviour);
+	public IPath getRuntimeBaseDirectory(TomcatServer server);
 
 	/**
 	 * Prepare server runtime directory. Create catalina instance set of
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.java
index 73c560c..d2155b8 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.java
@@ -83,30 +83,19 @@
 	public static String errorXMLContextNotFoundPath;
 	public static String errorXMLContextMangerNotFound;
 	public static String errorXMLContextNotFoundPath32;
-	public static String configurationEditorActionModifyPortDescription;
+
 	public static String configurationEditorActionModifyPort;
-	public static String configurationEditorActionModifyMimeMappingDescription;
 	public static String configurationEditorActionModifyMimeMapping;
-	public static String configurationEditorActionAddMimeMappingDescription;
 	public static String configurationEditorActionAddMimeMapping;
-	public static String configurationEditorActionAddWebModuleDescription;
 	public static String configurationEditorActionAddWebModule;
-	public static String configurationEditorActionModifyWebModuleDescription;
 	public static String configurationEditorActionModifyWebModule;
-	public static String configurationEditorActionRemoveMimeMappingDescription;
 	public static String configurationEditorActionRemoveMimeMapping;
-	public static String configurationEditorActionRemoveWebModuleDescription;
 	public static String configurationEditorActionRemoveWebModule;
-	public static String serverEditorActionSetDebugModeDescription;
-	public static String serverEditorActionSetDebugMode;
-	public static String serverEditorActionSetSecureDescription;
-	public static String serverEditorActionSetSecure;
-	public static String serverEditorActionSetTestEnvironmentDescription;
-	public static String serverEditorActionSetTestEnvironment;
-	public static String serverEditorActionSetDeployDirectory;
-	public static String serverEditorActionSetDeployDirectoryDescription;
-	public static String configurationEditorActionEditWebModuleDescription;
 	public static String configurationEditorActionEditWebModulePath;
+	public static String serverEditorActionSetDebugMode;
+	public static String serverEditorActionSetSecure;
+	public static String serverEditorActionSetServerDirectory;
+	public static String serverEditorActionSetDeployDirectory;
 	public static String fixModuleContextRootDescription;
 	public static String fixModuleContextRoot;
 
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.properties b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.properties
index 660efe4..305e01c 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.properties
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.properties
@@ -43,22 +43,14 @@
 errorPublish=Publishing failed with multiple errors
 
 # Editor commands (used in undo/redo menus)
-configurationEditorActionAddMimeMapping=add MIME mapping
-configurationEditorActionAddMimeMappingDescription=Add a MIME mapping
-configurationEditorActionModifyMimeMapping=modify MIME mapping
-configurationEditorActionModifyMimeMappingDescription=Modify the MIME mapping
-configurationEditorActionRemoveMimeMapping=remove MIME mapping
-configurationEditorActionRemoveMimeMappingDescription=Remove a MIME mapping
-configurationEditorActionAddWebModule=add Web module
-configurationEditorActionAddWebModuleDescription=Add a Web module
-configurationEditorActionModifyWebModule=modify Web module
-configurationEditorActionModifyWebModuleDescription=Modify the Web module
-configurationEditorActionRemoveWebModule=remove Web module
-configurationEditorActionRemoveWebModuleDescription=Remove Web module {0}
-configurationEditorActionModifyPort=set port number
-configurationEditorActionModifyPortDescription=Set the port number
-configurationEditorActionEditWebModulePath=edit Web module path
-configurationEditorActionEditWebModuleDescription=Change Web module path from {0} to {1}
+configurationEditorActionAddMimeMapping=MIME Mapping Addition
+configurationEditorActionModifyMimeMapping=MIME Mapping Change
+configurationEditorActionRemoveMimeMapping=MIME Mapping Removal
+configurationEditorActionAddWebModule=Web Module Addition
+configurationEditorActionModifyWebModule=Web Module Change
+configurationEditorActionRemoveWebModule=Web Module Removal
+configurationEditorActionModifyPort=Port Number Change
+configurationEditorActionEditWebModulePath=Web Module Path Change
 
 # --------------- General ---------------
 canAddModule=Web module can be added to the server.
@@ -113,11 +105,7 @@
 warningCantReadConfig=Cannot read the Tomcat configuration.
 
 # Actions (used in undo/redo menus)
-serverEditorActionSetSecure=set security
-serverEditorActionSetSecureDescription=Set the Tomcat security
-serverEditorActionSetDebugMode=set Tomcat debug mode
-serverEditorActionSetDebugModeDescription=Set Tomcat in debug mode
-serverEditorActionSetTestEnvironment=run modules from workspace
-serverEditorActionSetTestEnvironmentDescription=Run modules from the workspace
-serverEditorActionSetDeployDirectory=set deploy directory
-serverEditorActionSetDeployDirectoryDescription=Set the Tomcat deploy directory.
+serverEditorActionSetSecure=Tomcat Security Option Change
+serverEditorActionSetDebugMode=Tomcat Debug Option Change
+serverEditorActionSetServerDirectory=Tomcat Server Path Change
+serverEditorActionSetDeployDirectory=Tomcat Deploy Path Change
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat32Handler.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat32Handler.java
index 5f4f2f2..3497eff 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat32Handler.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat32Handler.java
@@ -111,12 +111,10 @@
 	}
 
 	/**
-	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServerBehaviour)
+	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServer)
 	 */
-	public IPath getRuntimeBaseDirectory(TomcatServerBehaviour serverBehaviour) {
-		if (serverBehaviour.getTomcatServer().isTestEnvironment())
-			return serverBehaviour.getTempDirectory();
-		return serverBehaviour.getServer().getRuntime().getLocation();
+	public IPath getRuntimeBaseDirectory(TomcatServer server) {
+		return TomcatVersionHelper.getStandardBaseDirectory(server);
 	}
 
 	/**
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat40Handler.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat40Handler.java
index bb9893b..6de5b3a 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat40Handler.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat40Handler.java
@@ -119,12 +119,10 @@
 	}
 
 	/**
-	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServerBehaviour)
+	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServer)
 	 */
-	public IPath getRuntimeBaseDirectory(TomcatServerBehaviour serverBehaviour) {
-		if (serverBehaviour.getTomcatServer().isTestEnvironment())
-			return serverBehaviour.getTempDirectory();
-		return serverBehaviour.getServer().getRuntime().getLocation();
+	public IPath getRuntimeBaseDirectory(TomcatServer server) {
+		return TomcatVersionHelper.getStandardBaseDirectory(server);
 	}
 
 	/**
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat41Handler.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat41Handler.java
index 7b4a9d7..248643b 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat41Handler.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat41Handler.java
@@ -117,12 +117,10 @@
 	}
 
 	/**
-	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServerBehaviour)
+	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServer)
 	 */
-	public IPath getRuntimeBaseDirectory(TomcatServerBehaviour serverBehaviour) {
-		if (serverBehaviour.getTomcatServer().isTestEnvironment())
-			return serverBehaviour.getTempDirectory();
-		return serverBehaviour.getServer().getRuntime().getLocation();
+	public IPath getRuntimeBaseDirectory(TomcatServer server) {
+		return TomcatVersionHelper.getStandardBaseDirectory(server);
 	}
 
 	/**
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat50Handler.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat50Handler.java
index e75de3b..ed069fd 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat50Handler.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat50Handler.java
@@ -117,12 +117,10 @@
 	}
 
 	/**
-	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServerBehaviour)
+	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServer)
 	 */
-	public IPath getRuntimeBaseDirectory(TomcatServerBehaviour serverBehaviour) {
-		if (serverBehaviour.getTomcatServer().isTestEnvironment())
-			return serverBehaviour.getTempDirectory();
-		return serverBehaviour.getServer().getRuntime().getLocation();
+	public IPath getRuntimeBaseDirectory(TomcatServer server) {
+		return TomcatVersionHelper.getStandardBaseDirectory(server);
 	}
 
 	/**
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat60Handler.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat60Handler.java
index 359aa22..3aa61cd 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat60Handler.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat60Handler.java
@@ -111,19 +111,16 @@
 	}
 
 	/**
-	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServerBehaviour)
+	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServer)
 	 */
-	public IPath getRuntimeBaseDirectory(TomcatServerBehaviour serverBehaviour) {
-		if (serverBehaviour.getTomcatServer().isTestEnvironment())
-			return serverBehaviour.getTempDirectory();
-		return serverBehaviour.getServer().getRuntime().getLocation();
+	public IPath getRuntimeBaseDirectory(TomcatServer server) {
+		return TomcatVersionHelper.getStandardBaseDirectory(server);
 	}
 
 	/**
 	 * @see ITomcatVersionHandler#prepareRuntimeDirectory(IPath)
 	 */
 	public IStatus prepareRuntimeDirectory(IPath baseDir) {
-		// TODO Update to Servlet 2.5 when supported
 		return TomcatVersionHelper.createCatalinaInstanceDirectory(baseDir);
 	}
 
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServer.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServer.java
index b84f70a..8bb1354 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServer.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServer.java
@@ -206,13 +206,35 @@
 	}
 	
 	/**
+	 * @see ITomcatServer#getInstanceDirectory()
+	 */
+	public String getInstanceDirectory() {
+		return getAttribute(PROPERTY_INSTANCE_DIR, (String)null);
+	}
+	
+	/**
 	 * @see ITomcatServer#getDeployDirectory()
 	 */
 	public String getDeployDirectory() {
 		// Default to value used by prior WTP versions
-		return getAttribute(PROPERTY_DEPLOYDIR, LEGACY_DEPLOYDIR);
+		return getAttribute(PROPERTY_DEPLOY_DIR, LEGACY_DEPLOYDIR);
 	}
 	
+	/**
+	 * Gets the base directory where the server instance runs.  This
+	 * path can vary depending on the configuration. Null may be returned
+	 * if a runtime hasn't been specified for the server.
+	 * 
+	 * @return path to base directory for the server or null if
+	 * runtime hasn't been specified.
+	 */
+	public IPath getRuntimeBaseDirectory() {
+		ITomcatVersionHandler tvh = getTomcatVersionHandler();
+		if (tvh != null)
+			return tvh.getRuntimeBaseDirectory(this);
+		return null;
+	}
+
 	protected static String renderCommandLine(String[] commandLine, String separator) {
 		if (commandLine == null || commandLine.length < 1)
 			return "";
@@ -342,18 +364,22 @@
 	}
 	
 	/**
-	 * Set the deployment directory for this server.  May be absolute
-	 * or relative to runtime base directory.
-	 * 
-	 * @param deployDir deployment directory for the server
+	 * @see ITomcatServerWorkingCopy#setInstanceDirectory(String)
+	 */
+	public void setInstanceDirectory(String instanceDir) {
+		setAttribute(PROPERTY_INSTANCE_DIR, instanceDir);
+	}
+	
+	/**
+	 * @see ITomcatServerWorkingCopy#setDeployDirectory(String)
 	 */
 	public void setDeployDirectory(String deployDir) {
 		// Remove attribute if setting to legacy value assumed in prior versions of WTP.
 		// Allowing values that differ only in case is asking for more trouble that it is worth.
 		if (LEGACY_DEPLOYDIR.equalsIgnoreCase(deployDir))
-			setAttribute(PROPERTY_DEPLOYDIR, (String)null);
+			setAttribute(PROPERTY_DEPLOY_DIR, (String)null);
 		else
-			setAttribute(PROPERTY_DEPLOYDIR, deployDir);
+			setAttribute(PROPERTY_DEPLOY_DIR, deployDir);
 	}
 
 	/**
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java
index 1eb0f48..68f148e 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java
@@ -97,7 +97,7 @@
 	 * @return the base path
 	 */
 	public IPath getRuntimeBaseDirectory() {
-		return getTomcatVersionHandler().getRuntimeBaseDirectory(this);
+		return getTomcatServer().getRuntimeBaseDirectory();
 	}
 
 	/**
@@ -109,7 +109,7 @@
 	protected String[] getRuntimeProgramArguments(boolean starting) {
 		IPath configPath = null;
 		if (getTomcatServer().isTestEnvironment())
-			configPath = getTempDirectory();
+			configPath = getRuntimeBaseDirectory();
 		return getTomcatVersionHandler().getRuntimeProgramArguments(configPath, getTomcatServer().isDebug(), starting);
 	}
 
@@ -124,21 +124,13 @@
 	 */
 	protected String[] getRuntimeVMArguments() {
 		IPath installPath = getServer().getRuntime().getLocation();
-		IPath configPath = null;
-		if (getTomcatServer().isTestEnvironment())
-			configPath = getTempDirectory();
-		else
-			configPath = installPath;
+		IPath configPath = getRuntimeBaseDirectory();
 		return getTomcatVersionHandler().getRuntimeVMArguments(installPath, configPath,
 				getTomcatServer().isTestEnvironment());
 	}
 	
 	protected String getRuntimePolicyFile() {
-		IPath configPath;
-		if (getTomcatServer().isTestEnvironment())
-			configPath = getTempDirectory();
-		else
-			configPath = getServer().getRuntime().getLocation();
+		IPath configPath = getRuntimeBaseDirectory();
 		return getTomcatVersionHandler().getRuntimePolicyFile(configPath);
 	}
 	
@@ -203,7 +195,7 @@
 		IPath installDir = getServer().getRuntime().getLocation();
 		IPath confDir = null;
 		if (getTomcatServer().isTestEnvironment()) {
-			confDir = getTempDirectory();
+			confDir = getRuntimeBaseDirectory();
 			IStatus status = getTomcatVersionHandler().prepareRuntimeDirectory(confDir);
 			if (status != null && !status.isOK())
 				throw new CoreException(status);
@@ -348,14 +340,9 @@
 	}
 
 	protected void publishFinish(IProgressMonitor monitor) throws CoreException {
-		IPath baseDir;
-		if (getTomcatServer().isTestEnvironment())
-			baseDir = getTempDirectory();
-		else
-			baseDir = getServer().getRuntime().getLocation();
-		
 		// Publish context configuration for servers that support META-INF/context.xml
-		IStatus status = getTomcatConfiguration().publishContextConfig(baseDir, getServerDeployDirectory(), monitor);
+		IStatus status = getTomcatConfiguration().publishContextConfig(
+				getRuntimeBaseDirectory(), getServerDeployDirectory(), monitor);
 		if (!status.isOK())
 			throw new CoreException(status);
 	}
@@ -540,6 +527,7 @@
 	 * 
 	 * @param originalArg String of original arguments.
 	 * @param vmArgs Arguments to merge into the original arguments string
+	 * @param excludeArgs Arguments to exclude from the original arguments string
 	 * @param keepActionLast If <b>true</b> the vmArguments are assumed to be Tomcat
 	 * program arguments, the last of which is the action to perform which must
 	 * remain the last argument.  This only has an impact if the last vmArg is
@@ -910,7 +898,7 @@
 	 */
 	public IStatus cleanServerWorkDir(IProgressMonitor monitor) throws CoreException {
 		IStatus result;
-		IPath basePath = getTomcatVersionHandler().getRuntimeBaseDirectory(this);
+		IPath basePath = getRuntimeBaseDirectory();
 		IPath workPath = getTomcatConfiguration().getServerWorkDirectory(basePath);
 		if (workPath != null) {
 			File workDir = workPath.toFile();
@@ -957,7 +945,7 @@
 	 */
 	public IStatus cleanContextWorkDir(ITomcatWebModule module, IProgressMonitor monitor) throws CoreException {
 		IStatus result;
-		IPath basePath = getTomcatVersionHandler().getRuntimeBaseDirectory(this);
+		IPath basePath = getRuntimeBaseDirectory();
 		IPath workPath = getTomcatConfiguration().getContextWorkDirectory(basePath, module);
 		if (workPath != null) {
 			IStatus [] results = PublishUtil.deleteDirectory(workPath.toFile(), monitor);
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatVersionHelper.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatVersionHelper.java
index c92ae90..7c4f305 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatVersionHelper.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatVersionHelper.java
@@ -25,10 +25,12 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.eclipse.core.resources.ResourcesPlugin;
 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.jst.server.core.PublishUtil;
 import org.eclipse.jst.server.tomcat.core.internal.xml.Factory;
@@ -108,6 +110,34 @@
 	}
 	
 	/**
+	 * Gets the base directory for this server. This directory
+	 * is used as the "base" property for the server.
+	 * 
+	 * @param ts TomcatServer from which to derive the base directory 
+	 * directory.  Only used to get the temp directory if needed.
+	 * @return path to base directory
+	 */
+	public static IPath getStandardBaseDirectory(TomcatServer ts) {
+		if (ts.isTestEnvironment()) {
+			String baseDir = ts.getInstanceDirectory();
+			// If test mode and no instance directory specified, use temporary directory
+			if (baseDir == null) {
+				TomcatServerBehaviour tsb = (TomcatServerBehaviour)ts.getServer().loadAdapter(TomcatServerBehaviour.class, null);
+				return tsb.getTempDirectory();
+			}
+			IPath path = new Path(baseDir);
+			if (!path.isAbsolute()) {
+				IPath rootPath = ResourcesPlugin.getWorkspace().getRoot().getLocation();
+				path = rootPath.append(path);
+			}
+			// Return specified instance directory
+			return path;
+		}
+		// Return runtime path
+		return ts.getServer().getRuntime().getLocation();
+	}
+	
+	/**
 	 * Gets a ServerInstance for the specified server.xml, Service name,
 	 * and Host name.  Returns null if server.xml does not exist
 	 * or an error occurs.
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/command/SetInstanceDirectoryCommand.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/command/SetInstanceDirectoryCommand.java
new file mode 100644
index 0000000..5ce4619
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/command/SetInstanceDirectoryCommand.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2007 SAS Institute, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Larry Isaacs - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.server.tomcat.core.internal.command;
+
+import org.eclipse.jst.server.tomcat.core.internal.ITomcatServerWorkingCopy;
+import org.eclipse.jst.server.tomcat.core.internal.Messages;
+
+/**
+ * Command to change the deploy directory
+ */
+public class SetInstanceDirectoryCommand extends ServerCommand {
+	protected String instanceDir;
+	protected String oldInstanceDir;
+	protected boolean oldTestEnvironment;
+
+	/**
+	 * Constructs command to set the instance directory. Setting
+	 * the instance directory also sets testEnvironment true;
+	 * 
+	 * @param server a Tomcat server
+	 * @param instanceDir instance directory to set
+	 */
+	public SetInstanceDirectoryCommand(ITomcatServerWorkingCopy server, String instanceDir) {
+		super(server, Messages.serverEditorActionSetServerDirectory);
+		this.instanceDir = instanceDir;
+	}
+
+	/**
+	 * Execute setting the deploy directory
+	 */
+	public void execute() {
+		oldTestEnvironment = server.isTestEnvironment();
+		oldInstanceDir = server.getInstanceDirectory();
+		if (!oldTestEnvironment)
+			server.setTestEnvironment(true);
+		server.setInstanceDirectory(instanceDir);
+	}
+
+	/**
+	 * Restore prior deploy directory
+	 */
+	public void undo() {
+		if (!oldTestEnvironment)
+			server.setTestEnvironment(false);
+		server.setInstanceDirectory(oldInstanceDir);
+	}
+}
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/command/SetTestEnvironmentCommand.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/command/SetTestEnvironmentCommand.java
index a2b48af..53eb6c3 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/command/SetTestEnvironmentCommand.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/command/SetTestEnvironmentCommand.java
@@ -13,11 +13,13 @@
 import org.eclipse.jst.server.tomcat.core.internal.ITomcatServerWorkingCopy;
 import org.eclipse.jst.server.tomcat.core.internal.Messages;
 /**
- * Command to change the server debug mode.
+ * Command to change the server test mode.  The server instance directory
+ * is cleared in conjunction with this command for legacy support.
  */
 public class SetTestEnvironmentCommand extends ServerCommand {
 	protected boolean te;
 	protected boolean oldTe;
+	protected String oldInstanceDir;
 
 	/**
 	 * SetTestEnvironmentCommand constructor comment.
@@ -26,7 +28,7 @@
 	 * @param te <code>true</code> for a test environment.
 	 */
 	public SetTestEnvironmentCommand(ITomcatServerWorkingCopy server, boolean te) {
-		super(server, Messages.serverEditorActionSetTestEnvironment);
+		super(server, Messages.serverEditorActionSetServerDirectory);
 		this.te = te;
 	}
 
@@ -35,7 +37,11 @@
 	 */
 	public void execute() {
 		oldTe = server.isTestEnvironment();
+		// save old instance directory
+		oldInstanceDir = server.getInstanceDirectory();
 		server.setTestEnvironment(te);
+		// ensure instance directory is cleared
+		server.setInstanceDirectory(null);
 	}
 
 	/**
@@ -43,5 +49,6 @@
 	 */
 	public void undo() {
 		server.setTestEnvironment(oldTe);
+		server.setInstanceDirectory(oldInstanceDir);
 	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.server.tomcat.ui/plugin.xml b/plugins/org.eclipse.jst.server.tomcat.ui/plugin.xml
index 1679129..5a738d3 100644
--- a/plugins/org.eclipse.jst.server.tomcat.ui/plugin.xml
+++ b/plugins/org.eclipse.jst.server.tomcat.ui/plugin.xml
@@ -79,10 +79,16 @@
 
    <extension point="org.eclipse.wst.server.ui.editorPageSections">
       <section
-         id="org.eclipse.jst.server.tomcat.server.editor.general"
+         id="org.eclipse.jst.server.tomcat.server.editor.instance"
          order="0"
          insertionId="org.eclipse.wst.server.editor.overview.left"
          typeIds="org.eclipse.jst.server.tomcat.*"
+         class="org.eclipse.jst.server.tomcat.ui.internal.editor.ServerLocationEditorSection"/>
+      <section
+         id="org.eclipse.jst.server.tomcat.server.editor.general"
+         order="5"
+         insertionId="org.eclipse.wst.server.editor.overview.left"
+         typeIds="org.eclipse.jst.server.tomcat.*"
          class="org.eclipse.jst.server.tomcat.ui.internal.editor.ServerGeneralEditorSection"/>
       <section
          id="org.eclipse.jst.server.tomcat.configuration.editor.port"
diff --git a/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/Messages.java b/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/Messages.java
index 4271bec..0dceefc 100644
--- a/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/Messages.java
+++ b/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/Messages.java
@@ -28,6 +28,7 @@
 	public static String editorAdd;
 	public static String editorEdit;
 	public static String editorRemove;
+	public static String editorBrowse;
 	public static String errorMissingWebModule;
 	public static String configurationEditorMimeMappingsSection;
 	public static String configurationEditorMimeMappingsDescription;
@@ -51,17 +52,27 @@
 	public static String configurationEditorMimeMapppingDialogTitleAdd;
 	public static String configurationEditorMimeMapppingDialogMimeType;
 	public static String configurationEditorMimeMapppingDialogMimeExtension;
-	public static String configurationEditorBrowseDeploy;
-	public static String configurationEditorBrowseDeployMessage;
+	public static String serverEditorLocationsSection;
+	public static String serverEditorLocationsDescription;
+	public static String serverEditorLocationsDescription2;
 	public static String serverEditorGeneralSection;
 	public static String serverEditorGeneralDescription;
+	public static String serverEditorSetInternalServerDirLink;
+	public static String serverEditorSetInternalServerDirLink2;
+	public static String serverEditorSetInstallServerDirLink;
+	public static String serverEditorSetInstallServerDirLink2;
+	public static String serverEditorSetDefaultDeployDirLink;
+	public static String serverEditorSetDefaultDeployDirLink2;
+	public static String serverEditorServerDir;
+	public static String serverEditorDeployDir;
 	public static String serverEditorTestEnvironment;
 	public static String serverEditorSecure;
 	public static String serverEditorDebugMode;
-	public static String serverEditorDeployDir;
-	public static String serverEditorBrowse;
-	public static String serverEditorSpecialFieldsLabel;
+	public static String errorServerDirIsRoot;
+	public static String errorServerDirUnderRoot;
 	public static String errorDeployDirNotSpecified;
+	public static String serverEditorBrowseServerMessage;
+	public static String serverEditorBrowseDeployMessage;
 	public static String configurationEditorWebModuleDialogTitleEdit;
 	public static String configurationEditorWebModuleDialogTitleAdd;
 	public static String configurationEditorWebModuleDialogProjects;
diff --git a/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/Messages.properties b/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/Messages.properties
index 65fe7b5..e6225a4 100644
--- a/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/Messages.properties
+++ b/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/Messages.properties
@@ -30,6 +30,7 @@
 editorRemove=Remove
 editorAdd=Add...
 editorEdit=Edit...
+editorBrowse=Browse...
 
 # --- Configuration Editor ---
 configurationEditorWebModulesPageTitle=Web Modules
@@ -69,21 +70,36 @@
 configurationEditorWebModuleDialogSelectDirectory=Select the Web module directory.
 errorMissingWebModule=The Web module at the following location cannot be found: {0}.
 
-# Browse for Deploy dialog
-configurationEditorBrowseDeploy=Browse
-configurationEditorBrowseDeployMessage=Select a deploy directory.
-
 # --- Server Editor ---
-serverEditorGeneralSection=Server
+serverEditorLocationsSection=Server Locations
+serverEditorLocationsDescription=Specify the server and deploy paths. Relative server paths are relative to the workspace. Relative deploy paths are relative to the server path. These settings can be changed only when the server is synchronized with no modules present, or has never been published. 
+serverEditorLocationsDescription2=Specify the server path (i.e. catalina.base) and deploy path. Relative server paths are relative to the workspace. Relative deploy paths are relative to the server path. These settings can be changed only when the server is synchronized with no modules present, or has never been published. 
+serverEditorGeneralSection=Server Options
 serverEditorGeneralDescription=Enter settings for the server.
 
+# Link Fields 
+serverEditorSetInternalServerDirLink=Set server path to internally supplied location
+serverEditorSetInternalServerDirLink2=Set server path to internally supplied location (currently set)
+serverEditorSetInstallServerDirLink=Set server path to the location of the Tomcat installation
+serverEditorSetInstallServerDirLink2=Set server path to the location of the Tomcat installation (currently set)
+serverEditorSetDefaultDeployDirLink=Set deploy path to the default value
+serverEditorSetDefaultDeployDirLink2=Set deploy path to the default value (currently set)
+
 # Fields
+serverEditorServerDir=Server path:
+serverEditorDeployDir=Deploy path:
 serverEditorSecure=Enable security
 serverEditorDebugMode=Enable Tomcat debug mode (v4.x and above only)
 serverEditorTestEnvironment=Run modules directly from the workspace (do not modify the Tomcat installation)
-serverEditorDeployDir=Deploy directory:
-serverEditorSpecialFieldsLabel=The field above may be changed only when the server is synchronized with no modules added.
-errorDeployDirNotSpecified=A Deploy directory must be specified.
+errorServerDirIsRoot=The server path may not be set to the the root of your workspace.
+errorServerDirUnderRoot=The server path may not be under the \"{0}\" folder of your workspace unless it is the internally supplied path.
+errorDeployDirNotSpecified=A deploy path must be specified.
+
+# Browse for Server dialog
+serverEditorBrowseServerMessage=Select a server directory.
+
+# Browse for Deploy dialog
+serverEditorBrowseDeployMessage=Select a deploy directory.
 
 # --- Clean Work Directory ---
 confirmCleanWorkDirTitle=Confirm Clean
diff --git a/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/editor/ServerGeneralEditorSection.java b/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/editor/ServerGeneralEditorSection.java
index 4b5a3e8..a063d0d 100644
--- a/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/editor/ServerGeneralEditorSection.java
+++ b/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/editor/ServerGeneralEditorSection.java
@@ -13,29 +13,18 @@
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.jst.server.tomcat.core.internal.ITomcatServer;
 import org.eclipse.jst.server.tomcat.core.internal.TomcatServer;
 import org.eclipse.jst.server.tomcat.core.internal.command.SetDebugModeCommand;
-import org.eclipse.jst.server.tomcat.core.internal.command.SetDeployDirectoryCommand;
 import org.eclipse.jst.server.tomcat.core.internal.command.SetSecureCommand;
-import org.eclipse.jst.server.tomcat.core.internal.command.SetTestEnvironmentCommand;
 import org.eclipse.jst.server.tomcat.ui.internal.ContextIds;
 import org.eclipse.jst.server.tomcat.ui.internal.Messages;
-import org.eclipse.jst.server.tomcat.ui.internal.TomcatUIPlugin;
 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.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.DirectoryDialog;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IEditorSite;
 import org.eclipse.ui.PlatformUI;
@@ -43,10 +32,8 @@
 import org.eclipse.ui.forms.widgets.FormToolkit;
 import org.eclipse.ui.forms.widgets.Section;
 import org.eclipse.ui.help.IWorkbenchHelpSystem;
-import org.eclipse.wst.server.core.IPublishListener;
-import org.eclipse.wst.server.core.IServer;
-import org.eclipse.wst.server.core.util.PublishAdapter;
-import org.eclipse.wst.server.ui.editor.ServerEditorSection;
+
+import org.eclipse.wst.server.ui.editor.*;
 /**
  * Tomcat server general editor page.
  */
@@ -55,15 +42,9 @@
 
 	protected Button secure;
 	protected Button debug;
-	protected Button testEnvironment;
-	protected Text deployDir;
-	protected Button deployDirBrowse;
 	protected boolean updating;
 
 	protected PropertyChangeListener listener;
-	protected IPublishListener publishListener;
-	
-	boolean allowRestrictedEditing;
 
 	/**
 	 * ServerGeneralEditorPart constructor comment.
@@ -75,7 +56,7 @@
 	/**
 	 * 
 	 */
-	protected void addChangeListeners() {
+	protected void addChangeListener() {
 		listener = new PropertyChangeListener() {
 			public void propertyChange(PropertyChangeEvent event) {
 				if (updating)
@@ -87,39 +68,11 @@
 				} else if (TomcatServer.PROPERTY_DEBUG.equals(event.getPropertyName())) {
 					Boolean b = (Boolean) event.getNewValue();
 					ServerGeneralEditorSection.this.debug.setSelection(b.booleanValue());
-				} else if (ITomcatServer.PROPERTY_TEST_ENVIRONMENT.equals(event.getPropertyName())) {
-					Boolean b = (Boolean) event.getNewValue();
-					ServerGeneralEditorSection.this.testEnvironment.setSelection(b.booleanValue());
-				} else if (ITomcatServer.PROPERTY_DEPLOYDIR.equals(event.getPropertyName())) {
-					String s = (String) event.getNewValue();
-					ServerGeneralEditorSection.this.deployDir.setText(s);
-					validate();
 				}
 				updating = false;
 			}
 		};
 		server.addPropertyChangeListener(listener);
-		
-		publishListener = new PublishAdapter() {
-			public void publishFinished(IServer server2, IStatus status) {
-				boolean flag = false;
-				if (status.isOK() && server2.getModules().length == 0)
-					flag = true;
-				if (flag != allowRestrictedEditing) {
-					allowRestrictedEditing = flag;
-					// Update the state of the fields
-					PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
-						public void run() {
-							if (!ServerGeneralEditorSection.this.deployDir.isDisposed())
-								ServerGeneralEditorSection.this.deployDir.setEnabled(allowRestrictedEditing);
-							if (!ServerGeneralEditorSection.this.deployDirBrowse.isDisposed())
-								ServerGeneralEditorSection.this.deployDirBrowse.setEnabled(allowRestrictedEditing);
-						}
-					});
-				}
-			}
-		};
-		server.getOriginal().addPublishListener(publishListener);
 	}
 	
 	/**
@@ -151,72 +104,9 @@
 		toolkit.paintBordersFor(composite);
 		section.setClient(composite);
 		
-		// deployment directory
-		Label label = toolkit.createLabel(composite, Messages.serverEditorDeployDir);
-		GridData data = new GridData(SWT.BEGINNING, SWT.CENTER, false, false);
-		label.setLayoutData(data);
-		
-		deployDir = toolkit.createText(composite, null);
-		data = new GridData(SWT.FILL, SWT.CENTER, true, false);
-		deployDir.setLayoutData(data);
-		deployDir.addModifyListener(new ModifyListener() {
-			public void modifyText(ModifyEvent e) {
-				if (updating)
-					return;
-				updating = true;
-				execute(new SetDeployDirectoryCommand(tomcatServer, deployDir.getText()));
-				updating = false;
-				validate();
-			}
-		});
-		
-		deployDirBrowse = toolkit.createButton(composite, Messages.configurationEditorBrowseDeploy, SWT.PUSH);
-		deployDirBrowse.addSelectionListener(new SelectionAdapter() {
-			public void widgetSelected(SelectionEvent se) {
-				DirectoryDialog dialog = new DirectoryDialog(deployDir.getShell());
-				dialog.setMessage(Messages.configurationEditorBrowseDeployMessage);
-				dialog.setFilterPath(deployDir.getText());
-				String selectedDirectory = dialog.open();
-				if (selectedDirectory != null && !selectedDirectory.equals(deployDir.getText())) {
-					updating = true;
-					execute(new SetDeployDirectoryCommand(tomcatServer, selectedDirectory));
-					deployDir.setText(selectedDirectory);
-					updating = false;
-					validate();
-				}
-			}
-		});
-		deployDirBrowse.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false));
-		
-		label = toolkit.createLabel(composite, Messages.serverEditorSpecialFieldsLabel);
-		data = new GridData(SWT.BEGINNING, SWT.CENTER, true, false);
-		data.horizontalSpan = 3;
-		label.setLayoutData(data);
-
-		Label separator = toolkit.createSeparator(composite, SWT.HORIZONTAL);
-		data = new GridData(SWT.FILL, SWT.CENTER, true, false);
-		data.horizontalSpan = 3;
-		separator.setLayoutData(data);
-		
-		// test environment
-		testEnvironment = toolkit.createButton(composite, Messages.serverEditorTestEnvironment, SWT.CHECK);
-		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
-		data.horizontalSpan = 3;
-		testEnvironment.setLayoutData(data);
-		testEnvironment.addSelectionListener(new SelectionAdapter() {
-			public void widgetSelected(SelectionEvent se) {
-				if (updating)
-					return;
-				updating = true;
-				execute(new SetTestEnvironmentCommand(tomcatServer, testEnvironment.getSelection()));
-				updating = false;
-			}
-		});
-		whs.setHelp(testEnvironment, ContextIds.SERVER_EDITOR_TEST_ENVIRONMENT);
-
 		// security
 		secure = toolkit.createButton(composite, Messages.serverEditorSecure, SWT.CHECK);
-		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
 		data.horizontalSpan = 3;
 		secure.setLayoutData(data);
 		secure.addSelectionListener(new SelectionAdapter() {
@@ -248,16 +138,13 @@
 	
 		initialize();
 	}
-	
+
 	/**
 	 * @see ServerEditorSection#dispose()
 	 */
 	public void dispose() {
-		if (server != null) {
+		if (server != null)
 			server.removePropertyChangeListener(listener);
-			if (server.getOriginal() != null)
-				server.getOriginal().removePublishListener(publishListener);
-		}
 	}
 
 	/**
@@ -268,7 +155,7 @@
 		
 		if (server != null) {
 			tomcatServer = (TomcatServer) server.loadAdapter(TomcatServer.class, null);
-			addChangeListeners();
+			addChangeListener();
 		}
 		initialize();
 	}
@@ -280,19 +167,7 @@
 		if (secure == null || tomcatServer == null)
 			return;
 		updating = true;
-		
-		allowRestrictedEditing = false;
-		if (server.getOriginal().getServerPublishState() == IServer.PUBLISH_STATE_NONE
-				&& server.getOriginal().getModules().length == 0) {
-			allowRestrictedEditing = true;
-		}
-		
-		deployDir.setText(tomcatServer.getDeployDirectory());
-		deployDir.setEnabled(allowRestrictedEditing);
-		
-		deployDirBrowse.setEnabled(allowRestrictedEditing);
 
-		testEnvironment.setSelection(tomcatServer.isTestEnvironment());
 		secure.setSelection(tomcatServer.isSecure());
 		if (server.getRuntime() != null && server.getRuntime().getRuntimeType().getId().indexOf("32") >= 0 || readOnly)
 			debug.setEnabled(false);
@@ -307,32 +182,5 @@
 			secure.setEnabled(true);
 		
 		updating = false;
-		validate();
-	}
-	
-	/**
-	 * @see ServerEditorSection#getSaveStatus()
-	 */
-	public IStatus[] getSaveStatus() {
-		if (tomcatServer != null) {
-			String dir = tomcatServer.getDeployDirectory();
-			if (dir == null || dir.length() == 0) {
-				return new IStatus [] {
-						new Status(IStatus.ERROR, TomcatUIPlugin.PLUGIN_ID, Messages.errorDeployDirNotSpecified)};
-			}
-		}
-		// use default implementation to return success
-		return super.getSaveStatus();
-	}
-	
-	protected void validate() {
-		if (tomcatServer != null) {
-			String dir = tomcatServer.getDeployDirectory();
-			if (dir == null || dir.length() == 0) {
-				setErrorMessage(Messages.errorDeployDirNotSpecified);
-				return;
-			}
-		}
-		setErrorMessage(null);
 	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/editor/ServerLocationEditorSection.java b/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/editor/ServerLocationEditorSection.java
new file mode 100644
index 0000000..3ea5539
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.tomcat.ui/tomcatui/org/eclipse/jst/server/tomcat/ui/internal/editor/ServerLocationEditorSection.java
@@ -0,0 +1,531 @@
+/**********************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jst.server.tomcat.ui.internal.editor;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jst.server.tomcat.core.internal.ITomcatServer;
+import org.eclipse.jst.server.tomcat.core.internal.ITomcatServerWorkingCopy;
+import org.eclipse.jst.server.tomcat.core.internal.TomcatServer;
+import org.eclipse.jst.server.tomcat.core.internal.command.SetDeployDirectoryCommand;
+import org.eclipse.jst.server.tomcat.core.internal.command.SetInstanceDirectoryCommand;
+import org.eclipse.jst.server.tomcat.core.internal.command.SetTestEnvironmentCommand;
+import org.eclipse.jst.server.tomcat.ui.internal.ContextIds;
+import org.eclipse.jst.server.tomcat.ui.internal.Messages;
+import org.eclipse.jst.server.tomcat.ui.internal.TomcatUIPlugin;
+import org.eclipse.osgi.util.NLS;
+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.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.DirectoryDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.FormColors;
+import org.eclipse.ui.forms.events.HyperlinkAdapter;
+import org.eclipse.ui.forms.events.HyperlinkEvent;
+import org.eclipse.ui.forms.widgets.ExpandableComposite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.Hyperlink;
+import org.eclipse.ui.forms.widgets.Section;
+import org.eclipse.ui.help.IWorkbenchHelpSystem;
+import org.eclipse.wst.server.core.IPublishListener;
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.util.PublishAdapter;
+import org.eclipse.wst.server.ui.editor.ServerEditorSection;
+/**
+ * Tomcat server general editor page.
+ */
+public class ServerLocationEditorSection extends ServerEditorSection {
+	protected Section section;
+	protected TomcatServer tomcatServer;
+
+	protected Hyperlink setInternalServerDir;
+	protected Hyperlink setRuntimeServerDir;
+	protected Hyperlink setDefaultDeployDir;
+	
+	protected boolean internalServerDirIsSet;
+	protected boolean installServerDirIsSet;
+	protected boolean defaultDeployDirIsSet;
+	
+	protected Text serverDir;
+	protected Button serverDirBrowse;
+	protected Text deployDir;
+	protected Button deployDirBrowse;
+	protected boolean updating;
+
+	protected PropertyChangeListener listener;
+	protected IPublishListener publishListener;
+	protected IPath workspacePath;
+	protected IPath defaultDeployPath;
+	
+	protected boolean allowRestrictedEditing;
+	protected IPath tempDirPath;
+
+	// Avoid hardcoding this at some point
+	private final static String METADATADIR = ".metadata";
+	/**
+	 * ServerGeneralEditorPart constructor comment.
+	 */
+	public ServerLocationEditorSection() {
+		// do nothing
+	}
+
+	/**
+	 * Add listeners to detect undo changes and publishing of the server.
+	 */
+	protected void addChangeListeners() {
+		listener = new PropertyChangeListener() {
+			public void propertyChange(PropertyChangeEvent event) {
+				if (updating)
+					return;
+				updating = true;
+				if (ITomcatServer.PROPERTY_INSTANCE_DIR.equals(event.getPropertyName())
+						|| ITomcatServer.PROPERTY_TEST_ENVIRONMENT.equals(event.getPropertyName())) {
+					updateServerDirFields();
+					validate();
+				}
+				else if (ITomcatServer.PROPERTY_DEPLOY_DIR.equals(event.getPropertyName())) {
+					String s = (String) event.getNewValue();
+					ServerLocationEditorSection.this.deployDir.setText(s);
+					updateDefaultDeployLink();					
+					validate();
+				}
+				updating = false;
+			}
+		};
+		server.addPropertyChangeListener(listener);
+		
+		publishListener = new PublishAdapter() {
+			public void publishFinished(IServer server2, IStatus status) {
+				boolean flag = false;
+				if (status.isOK() && server2.getModules().length == 0)
+					flag = true;
+				if (flag != allowRestrictedEditing) {
+					allowRestrictedEditing = flag;
+					// Update the state of the fields
+					PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+						public void run() {
+							if (!ServerLocationEditorSection.this.setInternalServerDir.isDisposed())
+								ServerLocationEditorSection.this.setInternalServerDir.setEnabled(allowRestrictedEditing);
+							if (!ServerLocationEditorSection.this.setRuntimeServerDir.isDisposed())
+								ServerLocationEditorSection.this.setRuntimeServerDir.setEnabled(allowRestrictedEditing);
+							if (!ServerLocationEditorSection.this.serverDir.isDisposed())
+								ServerLocationEditorSection.this.serverDir.setEnabled(allowRestrictedEditing);
+							if (!ServerLocationEditorSection.this.serverDirBrowse.isDisposed())
+								ServerLocationEditorSection.this.serverDirBrowse.setEnabled(allowRestrictedEditing);
+							if (!ServerLocationEditorSection.this.setDefaultDeployDir.isDisposed())
+								ServerLocationEditorSection.this.setDefaultDeployDir.setEnabled(allowRestrictedEditing);
+							if (!ServerLocationEditorSection.this.deployDir.isDisposed())
+								ServerLocationEditorSection.this.deployDir.setEnabled(allowRestrictedEditing);
+							if (!ServerLocationEditorSection.this.deployDirBrowse.isDisposed())
+								ServerLocationEditorSection.this.deployDirBrowse.setEnabled(allowRestrictedEditing);
+						}
+					});
+				}
+			}
+		};
+		server.getOriginal().addPublishListener(publishListener);
+	}
+	
+	/**
+	 * Creates the SWT controls for this workbench part.
+	 *
+	 * @param parent the parent control
+	 */
+	public void createSection(Composite parent) {
+		super.createSection(parent);
+		FormToolkit toolkit = getFormToolkit(parent.getDisplay());
+
+		section = toolkit.createSection(parent, ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED
+			| ExpandableComposite.TITLE_BAR | Section.DESCRIPTION | ExpandableComposite.FOCUS_TITLE);
+		section.setText(Messages.serverEditorLocationsSection);
+		section.setDescription(Messages.serverEditorLocationsDescription);
+		section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
+
+		Composite composite = toolkit.createComposite(section);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 3;
+		layout.marginHeight = 5;
+		layout.marginWidth = 10;
+		layout.verticalSpacing = 5;
+		layout.horizontalSpacing = 15;
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
+		IWorkbenchHelpSystem whs = PlatformUI.getWorkbench().getHelpSystem();
+		whs.setHelp(composite, ContextIds.SERVER_EDITOR);
+		whs.setHelp(section, ContextIds.SERVER_EDITOR);
+		toolkit.paintBordersFor(composite);
+		section.setClient(composite);
+
+		// server directory links
+		setInternalServerDir = toolkit.createHyperlink(composite,
+				NLS.bind(Messages.serverEditorSetInternalServerDirLink, ""), SWT.WRAP);
+		setInternalServerDir.addHyperlinkListener(new HyperlinkAdapter() {
+			public void linkActivated(HyperlinkEvent e) {
+				updating = true;
+				execute(new SetTestEnvironmentCommand(tomcatServer, true));
+				updateServerDirFields();
+				updating = false;
+				validate();
+			}
+		});
+		GridData data = new GridData(SWT.FILL, SWT.CENTER, true, false);
+		data.horizontalSpan = 3;
+		setInternalServerDir.setLayoutData(data);
+
+		setRuntimeServerDir = toolkit.createHyperlink(composite,
+				NLS.bind(Messages.serverEditorSetInstallServerDirLink, ""), SWT.WRAP);
+		setRuntimeServerDir.addHyperlinkListener(new HyperlinkAdapter() {
+			public void linkActivated(HyperlinkEvent e) {
+				updating = true;
+				execute(new SetTestEnvironmentCommand(tomcatServer, false));
+				updateServerDirFields();
+				updating = false;
+				validate();
+			}
+		});
+		data = new GridData(SWT.FILL, SWT.CENTER, true, false);
+		data.horizontalSpan = 3;
+		setRuntimeServerDir.setLayoutData(data);
+		
+		// server directory
+		Label label = createLabel(toolkit, composite, Messages.serverEditorServerDir);
+		data = new GridData(SWT.BEGINNING, SWT.CENTER, false, false);
+		label.setLayoutData(data);
+
+		serverDir = toolkit.createText(composite, null, SWT.SINGLE);
+		data = new GridData(SWT.FILL, SWT.CENTER, true, false);
+		serverDir.setLayoutData(data);
+		serverDir.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				if (updating)
+					return;
+				updating = true;
+				execute(new SetInstanceDirectoryCommand(tomcatServer, getServerDir()));
+				updating = false;
+				validate();
+			}
+		});
+
+		serverDirBrowse = toolkit.createButton(composite, Messages.editorBrowse, SWT.PUSH);
+		serverDirBrowse.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent se) {
+				DirectoryDialog dialog = new DirectoryDialog(serverDir.getShell());
+				dialog.setMessage(Messages.serverEditorBrowseDeployMessage);
+				dialog.setFilterPath(serverDir.getText());
+				String selectedDirectory = dialog.open();
+				if (selectedDirectory != null && !selectedDirectory.equals(serverDir.getText())) {
+					updating = true;
+					execute(new SetInstanceDirectoryCommand(tomcatServer, selectedDirectory));
+					serverDir.setText(selectedDirectory);
+					updating = false;
+					validate();
+				}
+			}
+		});
+		serverDirBrowse.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+
+		// deployment directory link
+		setDefaultDeployDir = toolkit.createHyperlink(composite,
+				NLS.bind(Messages.serverEditorSetDefaultDeployDirLink, ""), SWT.WRAP);
+		setDefaultDeployDir.addHyperlinkListener(new HyperlinkAdapter() {
+			public void linkActivated(HyperlinkEvent e) {
+				updating = true;
+				execute(new SetDeployDirectoryCommand(tomcatServer, ITomcatServerWorkingCopy.DEFAULT_DEPLOYDIR));
+				updating = false;
+				validate();
+			}
+		});
+		data = new GridData(SWT.FILL, SWT.CENTER, true, false);
+		data.horizontalSpan = 3;
+		setDefaultDeployDir.setLayoutData(data);
+
+		// deployment directory
+		label = createLabel(toolkit, composite, Messages.serverEditorDeployDir);
+		data = new GridData(SWT.BEGINNING, SWT.CENTER, false, false);
+		label.setLayoutData(data);
+
+		deployDir = toolkit.createText(composite, null);
+		data = new GridData(SWT.FILL, SWT.CENTER, true, false);
+		deployDir.setLayoutData(data);
+		deployDir.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				if (updating)
+					return;
+				updating = true;
+				execute(new SetDeployDirectoryCommand(tomcatServer, deployDir.getText().trim()));
+				updateDefaultDeployLink();
+				updating = false;
+				validate();
+			}
+		});
+
+		deployDirBrowse = toolkit.createButton(composite, Messages.editorBrowse, SWT.PUSH);
+		deployDirBrowse.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent se) {
+				DirectoryDialog dialog = new DirectoryDialog(deployDir.getShell());
+				dialog.setMessage(Messages.serverEditorBrowseDeployMessage);
+				dialog.setFilterPath(deployDir.getText());
+				String selectedDirectory = dialog.open();
+				if (selectedDirectory != null && !selectedDirectory.equals(deployDir.getText())) {
+					updating = true;
+					execute(new SetDeployDirectoryCommand(tomcatServer, selectedDirectory));
+					deployDir.setText(selectedDirectory);
+					updating = false;
+					validate();
+				}
+			}
+		});
+		deployDirBrowse.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+
+		initialize();
+	}
+
+	protected Label createLabel(FormToolkit toolkit, Composite parent, String text) {
+		Label label = toolkit.createLabel(parent, text);
+		label.setForeground(toolkit.getColors().getColor(FormColors.TITLE));
+		return label;
+	}
+
+	/**
+	 * @see ServerEditorSection#dispose()
+	 */
+	public void dispose() {
+		if (server != null) {
+			server.removePropertyChangeListener(listener);
+			if (server.getOriginal() != null)
+				server.getOriginal().removePublishListener(publishListener);
+		}
+	}
+
+	/**
+	 * @see ServerEditorSection#init(IEditorSite, IEditorInput)
+	 */
+	public void init(IEditorSite site, IEditorInput input) {
+		super.init(site, input);
+		
+		// Cache workspace and default deploy paths
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		workspacePath = root.getLocation();
+		defaultDeployPath = new Path(ITomcatServerWorkingCopy.DEFAULT_DEPLOYDIR);
+
+		if (server != null) {
+			tomcatServer = (TomcatServer) server.loadAdapter(TomcatServer.class, null);
+			addChangeListeners();
+		}
+		initialize();
+	}
+
+	/**
+	 * Initialize the fields in this editor.
+	 */
+	protected void initialize() {
+		if (serverDir== null || tomcatServer == null)
+			return;
+		updating = true;
+
+		IRuntime runtime = server.getRuntime();
+		// If not Tomcat 3.2, update description to mention catalina.base
+		if (runtime != null && runtime.getRuntimeType().getId().indexOf("32") < 0)
+			section.setDescription(Messages.serverEditorLocationsDescription2);
+		
+		// determine if editing of locations is allowed
+		allowRestrictedEditing = false;
+		IPath basePath = tomcatServer.getRuntimeBaseDirectory();
+		if (!readOnly) {
+			// If server has not been published, or server is published with no modules, allow editing
+			// TODO Find better way to determine if server hasn't been published
+			if ((basePath != null && !basePath.append("conf").toFile().exists())
+					|| (server.getOriginal().getServerPublishState() == IServer.PUBLISH_STATE_NONE
+							&& server.getOriginal().getModules().length == 0)) {
+				allowRestrictedEditing = true;
+			}
+		}
+
+		// Update server related fields
+		updateServerDirFields();
+
+		setInternalServerDir.setEnabled(allowRestrictedEditing);
+		setRuntimeServerDir.setEnabled(allowRestrictedEditing);
+		serverDir.setEnabled(allowRestrictedEditing);
+		serverDirBrowse.setEnabled(allowRestrictedEditing);
+
+		// Update deployment related fields
+		updateDefaultDeployLink();
+		
+		deployDir.setText(tomcatServer.getDeployDirectory());
+
+		setDefaultDeployDir.setEnabled(allowRestrictedEditing);
+		deployDir.setEnabled(allowRestrictedEditing);
+		deployDirBrowse.setEnabled(allowRestrictedEditing);
+
+		updating = false;
+		validate();
+	}
+	
+	protected String getServerDir() {
+		String dir = null;
+		if (serverDir != null) {
+			dir = serverDir.getText().trim();
+			IPath path = new Path(dir);
+			// Adjust if the temp dir is known and has been entered
+			if (tempDirPath != null && tempDirPath.equals(path))
+				dir = null;
+			// If under the workspace, make relative
+			else if (workspacePath.isPrefixOf(path)) {
+				int cnt = path.matchingFirstSegments(workspacePath);
+				path = path.removeFirstSegments(cnt);
+				dir = path.toOSString();
+			}
+		}
+		return dir;
+	}
+	
+	protected void updateServerDirFields() {
+		updateServerDir();
+		updateInternalServerDirLink();
+		updateInstallServerDirLink();
+	}
+	
+	protected void updateInternalServerDirLink() {
+		boolean newState = tomcatServer.isTestEnvironment() && tomcatServer.getInstanceDirectory() == null;
+		if (newState != internalServerDirIsSet) {
+			setInternalServerDir.setText(
+					newState ? Messages.serverEditorSetInternalServerDirLink2
+							: Messages.serverEditorSetInternalServerDirLink);
+			internalServerDirIsSet = newState;
+		}
+	}
+
+	protected void updateInstallServerDirLink() {
+		boolean newState = !tomcatServer.isTestEnvironment();
+		if (newState != installServerDirIsSet) {
+			setRuntimeServerDir.setText(
+					newState ? Messages.serverEditorSetInstallServerDirLink2
+							: Messages.serverEditorSetInstallServerDirLink);
+			installServerDirIsSet = newState;
+		}
+	}
+
+	protected void updateServerDir() {
+		IPath path = tomcatServer.getRuntimeBaseDirectory();
+		if (workspacePath.isPrefixOf(path)) {
+			int cnt = path.matchingFirstSegments(workspacePath);
+			path = path.removeFirstSegments(cnt);
+			serverDir.setText(path.toOSString());
+			// cache the relative temp dir path if that is what we have
+			if (tempDirPath == null) {
+				if (tomcatServer.isTestEnvironment() && tomcatServer.getInstanceDirectory() == null)
+					tempDirPath = path;
+			}
+		}
+		else
+			serverDir.setText(path.toOSString());
+	}
+	
+	protected void updateDefaultDeployLink() {
+		boolean newState = defaultDeployPath.equals(new Path(tomcatServer.getDeployDirectory()));
+		if (newState != defaultDeployDirIsSet) {
+			setDefaultDeployDir.setText(
+					newState ? Messages.serverEditorSetDefaultDeployDirLink2
+							: Messages.serverEditorSetDefaultDeployDirLink);
+			defaultDeployDirIsSet = newState;
+		}
+	}
+	
+	/**
+	 * @see ServerEditorSection#getSaveStatus()
+	 */
+	public IStatus[] getSaveStatus() {
+		if (tomcatServer != null) {
+			// Check the instance directory
+			String dir = tomcatServer.getInstanceDirectory();
+			if (dir != null) {
+				IPath path = new Path(dir);
+				// Must not be the same as the workspace location
+				if (dir.length() == 0 || workspacePath.equals(path)) {
+					return new IStatus [] {
+							new Status(IStatus.ERROR, TomcatUIPlugin.PLUGIN_ID, Messages.errorServerDirIsRoot)};
+				}
+				// User specified value may not be under the ".metadata" folder of the workspace 
+				else if (workspacePath.isPrefixOf(path)
+						|| (!path.isAbsolute() && METADATADIR.equals(path.segment(0)))) {
+					int cnt = path.matchingFirstSegments(workspacePath);
+					if (METADATADIR.equals(path.segment(cnt))) {
+						return new IStatus [] {
+								new Status(IStatus.ERROR, TomcatUIPlugin.PLUGIN_ID, NLS.bind(Messages.errorServerDirUnderRoot, METADATADIR))};
+					}
+				}
+			}
+
+			// Check the deployment directory
+			dir = tomcatServer.getDeployDirectory();
+			// Deploy directory must be set
+			if (dir == null || dir.length() == 0) {
+				return new IStatus [] {
+						new Status(IStatus.ERROR, TomcatUIPlugin.PLUGIN_ID, Messages.errorDeployDirNotSpecified)};
+			}
+		}
+		// use default implementation to return success
+		return super.getSaveStatus();
+	}
+	
+	protected void validate() {
+		if (tomcatServer != null) {
+			// Validate instance directory
+			String dir = tomcatServer.getInstanceDirectory();
+			if (dir != null) {
+				IPath path = new Path(dir);
+				// Must not be the same as the workspace location
+				if (dir.length() == 0 || workspacePath.equals(path)) {
+					setErrorMessage(Messages.errorServerDirIsRoot);
+					return;
+				}
+				// User specified value may not be under the ".metadata" folder of the workspace 
+				else if (workspacePath.isPrefixOf(path)
+						|| (!path.isAbsolute() && METADATADIR.equals(path.segment(0)))) {
+					int cnt = path.matchingFirstSegments(workspacePath);
+					if (METADATADIR.equals(path.segment(cnt))) {
+						setErrorMessage(NLS.bind(Messages.errorServerDirUnderRoot, METADATADIR));
+						return;
+					}
+				}
+			}
+
+			// Check the deployment directory
+			dir = tomcatServer.getDeployDirectory();
+			// Deploy directory must be set
+			if (dir == null || dir.length() == 0) {
+				setErrorMessage(Messages.errorDeployDirNotSpecified);
+				return;
+			}
+		}
+		// All is okay, clear any previous error
+		setErrorMessage(null);
+	}
+}
\ No newline at end of file