This commit was manufactured by cvs2svn to create tag 'R3_0_5'.
diff --git a/features/org.eclipse.jst.server_adapters.feature/feature.xml b/features/org.eclipse.jst.server_adapters.feature/feature.xml
index c24a357..9e1c376 100644
--- a/features/org.eclipse.jst.server_adapters.feature/feature.xml
+++ b/features/org.eclipse.jst.server_adapters.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jst.server_adapters.feature"
       label="%featureName"
-      version="3.0.0.qualifier"
+      version="3.0.4.qualifier"
       provider-name="%providerName">
 
    <description>
diff --git a/features/org.eclipse.jst.server_adapters.sdk.feature/feature.xml b/features/org.eclipse.jst.server_adapters.sdk.feature/feature.xml
index e39f7ab..29b36c9 100644
--- a/features/org.eclipse.jst.server_adapters.sdk.feature/feature.xml
+++ b/features/org.eclipse.jst.server_adapters.sdk.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jst.server_adapters.sdk.feature"
       label="%featureName"
-      version="3.0.0.qualifier"
+      version="3.0.4.qualifier"
       provider-name="%providerName">
 
    <description>
@@ -28,5 +28,5 @@
    <includes
          id="org.eclipse.jst.server_adapters.feature.source"
          version="0.0.0"/>
- 
+
 </feature>
diff --git a/features/org.eclipse.jst.server_core.feature/feature.xml b/features/org.eclipse.jst.server_core.feature/feature.xml
index e7323d6..19d34fb 100644
--- a/features/org.eclipse.jst.server_core.feature/feature.xml
+++ b/features/org.eclipse.jst.server_core.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jst.server_core.feature"
       label="%featureName"
-      version="3.0.0.qualifier"
+      version="3.0.4.qualifier"
       provider-name="%providerName">
 
    <description>
diff --git a/features/org.eclipse.jst.server_sdk.feature/feature.xml b/features/org.eclipse.jst.server_sdk.feature/feature.xml
index 7c4dce3..e387248 100644
--- a/features/org.eclipse.jst.server_sdk.feature/feature.xml
+++ b/features/org.eclipse.jst.server_sdk.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jst.server_sdk.feature"
       label="%featureName"
-      version="3.0.0.qualifier"
+      version="3.0.4.qualifier"
       provider-name="%providerName">
 
    <description>
@@ -28,5 +28,5 @@
    <includes
          id="org.eclipse.jst.server_ui.feature.source"
          version="0.0.0"/>
- 
+
 </feature>
diff --git a/features/org.eclipse.jst.server_tests.feature/feature.xml b/features/org.eclipse.jst.server_tests.feature/feature.xml
index fed2f65..81ab60a 100644
--- a/features/org.eclipse.jst.server_tests.feature/feature.xml
+++ b/features/org.eclipse.jst.server_tests.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jst.server_tests.feature"
       label="%featureName"
-      version="3.0.0.qualifier"
+      version="3.0.1.qualifier"
       provider-name="%providerName">
 
    <description>
diff --git a/features/org.eclipse.jst.server_ui.feature/feature.xml b/features/org.eclipse.jst.server_ui.feature/feature.xml
index af078a4..6bad139 100644
--- a/features/org.eclipse.jst.server_ui.feature/feature.xml
+++ b/features/org.eclipse.jst.server_ui.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jst.server_ui.feature"
       label="%featureName"
-      version="3.0.0.qualifier"
+      version="3.0.4.qualifier"
       provider-name="%providerName">
 
    <description>
diff --git a/features/org.eclipse.wst.server_core.feature/feature.xml b/features/org.eclipse.wst.server_core.feature/feature.xml
index c212fe4..94764ef 100644
--- a/features/org.eclipse.wst.server_core.feature/feature.xml
+++ b/features/org.eclipse.wst.server_core.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.wst.server_core.feature"
       label="%featureName"
-      version="3.0.1.qualifier"
+      version="3.0.5.qualifier"
       provider-name="%providerName">
 
    <description>
diff --git a/features/org.eclipse.wst.server_sdk.feature/feature.xml b/features/org.eclipse.wst.server_sdk.feature/feature.xml
index 90bc873..9e3fa73 100644
--- a/features/org.eclipse.wst.server_sdk.feature/feature.xml
+++ b/features/org.eclipse.wst.server_sdk.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.wst.server_sdk.feature"
       label="%featureName"
-      version="3.0.1.qualifier"
+      version="3.0.5.qualifier"
       provider-name="%providerName">
 
    <description>
@@ -29,4 +29,11 @@
          id="org.eclipse.wst.server_ui.feature.source"
          version="0.0.0"/>
 
+   <plugin
+         id="org.eclipse.servertools.doc.isv"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
diff --git a/features/org.eclipse.wst.server_ui.feature/feature.xml b/features/org.eclipse.wst.server_ui.feature/feature.xml
index ce2c6b6..e9adaef 100644
--- a/features/org.eclipse.wst.server_ui.feature/feature.xml
+++ b/features/org.eclipse.wst.server_ui.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.wst.server_ui.feature"
       label="%featureName"
-      version="3.0.1.qualifier"
+      version="3.0.5.qualifier"
       provider-name="%providerName">
 
    <description>
diff --git a/features/org.eclipse.wst.server_userdoc.feature/feature.xml b/features/org.eclipse.wst.server_userdoc.feature/feature.xml
index c9468fe..917ba21 100644
--- a/features/org.eclipse.wst.server_userdoc.feature/feature.xml
+++ b/features/org.eclipse.wst.server_userdoc.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.wst.server_userdoc.feature"
       label="%featureName"
-      version="3.0.0.qualifier"
+      version="3.0.150.qualifier"
       provider-name="%providerName">
 
    <description>
diff --git a/plugins/org.eclipse.jst.server.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.jst.server.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..bacd972
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.core/META-INF/MANIFEST.MF
@@ -0,0 +1,22 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.jst.server.core; singleton:=true
+Bundle-Version: 1.1.3.qualifier
+Bundle-Activator: org.eclipse.jst.server.core.internal.JavaServerPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.jst.server.core,
+ org.eclipse.jst.server.core.internal;x-friends:="org.eclipse.jst.server.ui",
+ org.eclipse.jst.server.core.internal.cactus;x-friends:="org.eclipse.jst.server.ui"
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.debug.core;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.jdt.core;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.jdt.launching;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.wst.server.core;bundle-version="[1.0.304,2.0.0)",
+ org.eclipse.wst.common.project.facet.core;bundle-version="[1.1.0,2.0.0)",
+ org.eclipse.jst.common.project.facet.core;bundle-version="[1.1.0,2.0.0)"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/RuntimeClasspathProviderDelegate.java b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/RuntimeClasspathProviderDelegate.java
index 36ea2c5..b1f40b0 100644
--- a/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/RuntimeClasspathProviderDelegate.java
+++ b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/RuntimeClasspathProviderDelegate.java
@@ -65,7 +65,7 @@
 
 	private Map<String, IPath> runtimePathMap = new HashMap<String, IPath>();
 
-	private Map<String, IClasspathEntry[]> previousClasspath = new HashMap<String, IClasspathEntry[]>();
+	private Map<String, Integer> previousClasspath = new HashMap<String, Integer>();
 
 	public RuntimeClasspathProviderDelegate() {
 		// default constructor
@@ -158,13 +158,13 @@
 		
 		String key = project.getName() + "/" + runtime.getId();
 		if (!previousClasspath.containsKey(key))
-			previousClasspath.put(key, entries);
+			previousClasspath.put(key, new Integer(entries.length));
 		else {
-			IClasspathEntry[] previousEntries = previousClasspath.get(key);
+			Integer previousEntries = previousClasspath.get(key);
 			
-			if ((previousEntries == null) || (previousEntries.length != entries.length)) {
+			if ((previousEntries == null) || (previousEntries.intValue() != entries.length)) {
 				Trace.trace(Trace.FINEST, "Classpath update: " + key + " " + entries);
-				previousClasspath.put(key, entries);
+				previousClasspath.put(key, new Integer(entries.length));
 				
 				IPath path = new Path(RuntimeClasspathContainer.SERVER_CONTAINER);
 				path = path.append(extensionId).append(runtime.getId());
diff --git a/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/RuntimeClasspathProviderWrapper.java b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/RuntimeClasspathProviderWrapper.java
index e7fcd65..fb858d6 100644
--- a/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/RuntimeClasspathProviderWrapper.java
+++ b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/RuntimeClasspathProviderWrapper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * Copyright (c) 2005, 2009 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
@@ -19,6 +19,7 @@
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jst.server.core.RuntimeClasspathProviderDelegate;
 import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.internal.ServerPlugin;
 /**
  * 
  */
@@ -129,7 +130,7 @@
 				delegate = (RuntimeClasspathProviderDelegate) element.createExecutableExtension("class");
 				delegate.initialize(getId());
 			} catch (Throwable t) {
-				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString(), t);
+				ServerPlugin.logExtensionFailure(toString(), t);
 			}
 		}
 		return delegate;
@@ -144,7 +145,7 @@
 		try {
 			return getDelegate().resolveClasspathContainerImpl(project, runtime);
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString(), e);
+			ServerPlugin.logExtensionFailure(toString(), e);
 		}
 		return null;
 	}
@@ -158,7 +159,7 @@
 		try {
 			getDelegate().requestClasspathContainerUpdate(runtime, entries);
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString(), e);
+			ServerPlugin.logExtensionFailure(toString(), e);
 		}
 	}
 
@@ -171,7 +172,7 @@
 		try {
 			return getDelegate().hasRuntimeClasspathChanged(runtime);
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString(), e);
+			ServerPlugin.logExtensionFailure(toString(), e);
 		}
 		return false;
 	}
diff --git a/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/RuntimeComponentProviderWrapper.java b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/RuntimeComponentProviderWrapper.java
index c6424d0..e47eaf1 100644
--- a/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/RuntimeComponentProviderWrapper.java
+++ b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/RuntimeComponentProviderWrapper.java
@@ -18,6 +18,7 @@
 import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeComponent;
 import org.eclipse.wst.server.core.IRuntime;
 import org.eclipse.wst.server.core.IRuntimeType;
+import org.eclipse.wst.server.core.internal.ServerPlugin;
 /**
  * 
  */
@@ -102,7 +103,7 @@
 			try {
 				delegate = (RuntimeComponentProviderDelegate) element.createExecutableExtension("class");
 			} catch (Throwable t) {
-				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString(), t);
+				ServerPlugin.logExtensionFailure(toString(), t);
 			}
 		}
 		return delegate;
@@ -117,7 +118,7 @@
 		try {
 			return getDelegate().getRuntimeComponents(runtime);
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString(), e);
+			ServerPlugin.logExtensionFailure(toString(), e);
 		}
 		return null;
 	}
diff --git a/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/Trace.java b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/Trace.java
new file mode 100644
index 0000000..fd470af
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/Trace.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.core.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+/**
+ * Helper class to route trace output.
+ */
+public class Trace {
+	/**
+	 * Config tracing
+	 */
+	public static final byte CONFIG = 0;
+	/**
+	 * Warning tracing
+	 */
+	public static final byte WARNING = 1;
+	/**
+	 * Severe tracing
+	 */
+	public static final byte SEVERE = 2;
+	/**
+	 * Finest tracing
+	 */
+	public static final byte FINEST = 3;
+
+	public static final byte PUBLISHING = 4;
+
+	private static Set<String> logged = new HashSet<String>();
+
+	/**
+	 * Trace constructor comment.
+	 */
+	private Trace() {
+		super();
+	}
+
+	/**
+	 * Trace the given text.
+	 *
+	 * @param level trace level
+	 * @param s String
+	 */
+	public static void trace(byte level, String s) {
+		Trace.trace(level, s, null);
+	}
+
+	/**
+	 * Trace the given message and exception.
+	 *
+	 * @param level trace level
+	 * @param s String
+	 * @param t Throwable
+	 */
+	public static void trace(byte level, String s, Throwable t) {
+		if (s == null)
+			return;
+		
+		if (level == SEVERE) {
+			if (!logged.contains(s)) {
+				JavaServerPlugin.getInstance().getLog().log(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, s, t));
+				logged.add(s);
+			}
+		}
+		
+		if (!JavaServerPlugin.getInstance().isDebugging())
+			return;
+		
+		System.out.println(JavaServerPlugin.PLUGIN_ID + " " + s);
+		if (t != null)
+			t.printStackTrace();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.server.generic.jboss/META-INF/MANIFEST.MF b/plugins/org.eclipse.jst.server.generic.jboss/META-INF/MANIFEST.MF
index 08761a1..1e811d8 100644
--- a/plugins/org.eclipse.jst.server.generic.jboss/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.jst.server.generic.jboss/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jst.server.generic.jboss;singleton:=true
-Bundle-Version: 1.5.205.qualifier
+Bundle-Version: 1.5.206.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Require-Bundle: org.eclipse.jst.server.core;bundle-version="[1.0.102,2.0.0)",
diff --git a/plugins/org.eclipse.jst.server.generic.jboss/servers/jboss5.serverdef b/plugins/org.eclipse.jst.server.generic.jboss/servers/jboss5.serverdef
index ba702b2..cdd7307 100644
--- a/plugins/org.eclipse.jst.server.generic.jboss/servers/jboss5.serverdef
+++ b/plugins/org.eclipse.jst.server.generic.jboss/servers/jboss5.serverdef
@@ -117,20 +117,21 @@
 	       <include name="client/*.jar" />
 	       <include name="server/default/lib/*.jar" />
 	       	       
-	       <include name="server/default/deployers/jbossweb.deployer/jsf-libs/*.jar" />	       
+		   <include name="server/default/deploy/jbossweb.sar/jsf-libs/*.jar" />
 
 	       <!-- This will be ignored if EJB3 is not there 5.0 -->
 	       <include name="lib/*.jar" />
 	       <include name="server/default/deployers/jbossweb.deployer/*.jar" />
 	       <include name="server/default/deployers/jboss-aop-jboss5.deployer/*.jar" />
-		   <include name="server/default/deployers/ejb3.deployer/jboss-annotations-ejb3.jar" />
+	       <include name="common/lib/*.jar" />
+	       <include name="server/default/deploy/jbossweb.sar/*.jar" />
 	       
 	       <!-- for validation to work this library is defined as an archive -->
-	       <exclude name="server/default/lib/mail.jar" />
+		   <exclude name="lib/jboss-kernel.jar" />
 	    </fileset>
 	    
 	    <!-- leave one generic jar as an archive so that validation works -->
-		<archive path="${serverRootDirectory}/server/default/lib/mail.jar" />
+		<archive path="${serverRootDirectory}/lib/jboss-kernel.jar" />
    
 	</classpath>
 	<jndiConnection>
diff --git a/plugins/org.eclipse.jst.server.preview.adapter/META-INF/MANIFEST.MF b/plugins/org.eclipse.jst.server.preview.adapter/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5eccac1
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.preview.adapter/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.jst.server.preview.adapter;singleton:=true
+Bundle-Version: 1.0.101.qualifier
+Bundle-Activator: org.eclipse.jst.server.preview.adapter.internal.PreviewPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.jst.server.preview.adapter.internal;x-friends:="org.eclipse.jst.server.ui"
+Require-Bundle: org.eclipse.jdt.core;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.jdt.launching;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.wst.server.core;bundle-version="[1.0.103,2.0.0)",
+ org.eclipse.jst.server.core;bundle-version="[1.0.204,2.0.0)",
+ org.eclipse.debug.ui;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.wst.server.ui;bundle-version="[1.0.103,2.0.0)",
+ org.eclipse.wst.common.project.facet.ui;bundle-version="[1.1.0,2.0.0)",
+ org.eclipse.jst.common.project.facet.core;bundle-version="[1.1.0,2.0.0)",
+ org.eclipse.jdt.debug.ui;bundle-version="[3.2.100,4.0.0)"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.jst.server.preview.adapter/src/org/eclipse/jst/server/preview/adapter/internal/core/PreviewServerBehaviour.java b/plugins/org.eclipse.jst.server.preview.adapter/src/org/eclipse/jst/server/preview/adapter/internal/core/PreviewServerBehaviour.java
new file mode 100644
index 0000000..5ef20cb
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.preview.adapter/src/org/eclipse/jst/server/preview/adapter/internal/core/PreviewServerBehaviour.java
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.preview.adapter.internal.core;
+
+import java.io.IOException;
+
+import org.eclipse.core.resources.IContainer;
+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.Status;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.jst.server.core.IWebModule;
+import org.eclipse.jst.server.preview.adapter.internal.IMemento;
+import org.eclipse.jst.server.preview.adapter.internal.Messages;
+import org.eclipse.jst.server.preview.adapter.internal.PreviewPlugin;
+import org.eclipse.jst.server.preview.adapter.internal.ProgressUtil;
+import org.eclipse.jst.server.preview.adapter.internal.Trace;
+import org.eclipse.jst.server.preview.adapter.internal.XMLMemento;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.server.core.IModule;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ServerPort;
+import org.eclipse.wst.server.core.model.IModuleResource;
+import org.eclipse.wst.server.core.model.IModuleResourceDelta;
+import org.eclipse.wst.server.core.model.ServerBehaviourDelegate;
+import org.eclipse.wst.server.core.util.IStaticWeb;
+import org.eclipse.wst.server.core.util.ProjectModule;
+import org.eclipse.wst.server.core.util.PublishUtil;
+import org.eclipse.wst.server.core.util.SocketUtil;
+/**
+ * Generic Http server.
+ */
+public class PreviewServerBehaviour extends ServerBehaviourDelegate {
+	// the thread used to ping the server to check for startup
+	protected transient PingThread ping = null;
+	protected transient IDebugEventSetListener processListener;
+
+	/**
+	 * PreviewServer.
+	 */
+	public PreviewServerBehaviour() {
+		super();
+	}
+
+	public void initialize(IProgressMonitor monitor) {
+		// do nothing
+	}
+
+	public PreviewRuntime getPreviewRuntime() {
+		if (getServer().getRuntime() == null)
+			return null;
+
+		return (PreviewRuntime) getServer().getRuntime().loadAdapter(PreviewRuntime.class, null);
+	}
+
+	public PreviewServer getPreviewServer() {
+		return (PreviewServer) getServer().getAdapter(PreviewServer.class);
+	}
+
+	/**
+	 * Returns the runtime base path for relative paths in the server
+	 * configuration.
+	 * 
+	 * @return the base path
+	 */
+	public IPath getRuntimeBaseDirectory() {
+		return getServer().getRuntime().getLocation();
+	}
+
+	/**
+	 * Setup for starting the server.
+	 * 
+	 * @param launch ILaunch
+	 * @param launchMode String
+	 * @param monitor IProgressMonitor
+	 * @throws CoreException if anything goes wrong
+	 */
+	protected void setupLaunch(ILaunch launch, String launchMode, IProgressMonitor monitor) throws CoreException {
+		// check that ports are free
+		ServerPort[] ports = getPreviewServer().getServerPorts();
+		int port = ports[0].getPort();
+		
+		if (SocketUtil.isPortInUse(port, 5))
+			throw new CoreException(new Status(IStatus.ERROR, PreviewPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorPortInUse, new String[] {port + "", getServer().getName()}), null));
+		
+		// generate preview config file
+		XMLMemento memento = XMLMemento.createWriteRoot("server");
+		memento.putInteger("port", port);
+		
+		IModule[] modules = getServer().getModules();
+		for (IModule module : modules) {
+			IMemento mod = memento.createChild("module");
+			mod.putString("name", module.getName());
+			String type = module.getModuleType().getId();
+			if ("wst.web".equals(type)) {
+				IStaticWeb staticWeb = (IStaticWeb) module.loadAdapter(IStaticWeb.class, null);
+				if (staticWeb != null)
+					mod.putString("context", staticWeb.getContextRoot());
+				mod.putString("type", "static");
+			} else if ("jst.web".equals(type)) {
+				IWebModule webModule = (IWebModule) module.loadAdapter(IWebModule.class, null);
+				if (webModule != null)
+					mod.putString("context", webModule.getContextRoot());
+				mod.putString("type", "j2ee");
+			}
+			mod.putString("path", getModulePublishDirectory(module).toPortableString());
+		}
+		try {
+			memento.saveToFile(getTempDirectory().append("preview.xml").toOSString());
+		} catch (IOException e) {
+			Trace.trace(Trace.SEVERE, "Could not write preview config", e);
+			throw new CoreException(new Status(IStatus.ERROR, PreviewPlugin.PLUGIN_ID, 0, "Could not write preview configuration", null));
+		}
+		
+		setServerRestartState(false);
+		setServerState(IServer.STATE_STARTING);
+		setMode(launchMode);
+		
+		// ping server to check for startup
+		try {
+			String url = "http://localhost";
+			if (port != 80)
+				url += ":" + port;
+			ping = new PingThread(getServer(), url, this);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Can't ping for Tomcat startup.");
+		}
+	}
+
+	protected void addProcessListener(final IProcess newProcess) {
+		if (processListener != null || newProcess == null)
+			return;
+		
+		processListener = new IDebugEventSetListener() {
+			public void handleDebugEvents(DebugEvent[] events) {
+				if (events != null) {
+					for (DebugEvent event : events) {
+						if (newProcess != null && newProcess.equals(event.getSource()) && event.getKind() == DebugEvent.TERMINATE) {
+							stop(true);
+						}
+					}
+				}
+			}
+		};
+		DebugPlugin.getDefault().addDebugEventListener(processListener);
+	}
+
+	protected void setServerStarted() {
+		setServerState(IServer.STATE_STARTED);
+	}
+
+	protected void publishServer(int kind, IProgressMonitor monitor) throws CoreException {
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		monitor.done();
+
+		setServerPublishState(IServer.PUBLISH_STATE_NONE);
+	}
+
+	/*
+	 * Publishes the given module to the server.
+	 */
+	protected void publishModule(int kind, int deltaKind, IModule[] moduleTree, IProgressMonitor monitor) throws CoreException {
+		IModule module = moduleTree[moduleTree.length - 1];
+		if (isSingleRootStructure(module))
+			return;
+		
+		IPath to = getModulePublishDirectory(module);
+		
+		if (kind == IServer.PUBLISH_CLEAN || deltaKind == ServerBehaviourDelegate.REMOVED) {
+			IStatus[] status = PublishUtil.deleteDirectory(to.toFile(), monitor);
+			throwException(status);
+		}
+		
+		IModuleResource[] res = getResources(moduleTree);
+		IStatus[] status = PublishUtil.publishSmart(res, to, monitor);
+		throwException(status);
+		
+		setModulePublishState(moduleTree, IServer.PUBLISH_STATE_NONE);
+	}
+
+	/**
+	 * Utility method to throw a CoreException based on the contents of a list of
+	 * error and warning status.
+	 * 
+	 * @param status a List containing error and warning IStatus
+	 * @throws CoreException
+	 */
+	private static void throwException(IStatus[] status) throws CoreException {
+		if (status == null || status.length == 0)
+			return;
+		
+		if (status.length == 1)
+			throw new CoreException(status[0]);
+		
+		String message = Messages.errorPublish;
+		MultiStatus status2 = new MultiStatus(PreviewPlugin.PLUGIN_ID, 0, status, message, null);
+		throw new CoreException(status2);
+	}
+
+	public void restart(String launchMode) throws CoreException {
+		setServerState(IServer.STATE_STOPPED);
+		setServerState(IServer.STATE_STARTED);
+	}
+
+	/**
+	 * Cleanly shuts down and terminates the server.
+	 * 
+	 * @param force <code>true</code> to kill the server
+	 */
+	public void stop(boolean force) {
+		int state = getServer().getServerState();
+		if (state == IServer.STATE_STOPPED)
+			return;
+		
+		setServerState(IServer.STATE_STOPPING);
+		
+		if (ping != null) {
+			ping.stop();
+			ping = null;
+		}
+		
+		if (processListener != null) {
+			DebugPlugin.getDefault().removeDebugEventListener(processListener);
+			processListener = null;
+		}
+		
+		try {
+			Trace.trace(Trace.FINEST, "Killing the process");
+			ILaunch launch = getServer().getLaunch();
+			if (launch != null)
+				launch.terminate();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error killing the process", e);
+		}
+		
+		setServerState(IServer.STATE_STOPPED);
+	}
+
+	protected IPath getTempDirectory() {
+		return super.getTempDirectory();
+	}
+
+	/**
+	 * Returns <code>true</code> if the module in the workspace has a single
+	 * root structure - i.e. matches the spec disk layout - and <code>false</code>
+	 * otherwise.
+	 * 
+	 * @return <code>true</code> if the module in the workspace has a single
+	 *    root structure - i.e. matches the spec disk layout - and
+	 *    <code>false</code> otherwise
+	 */
+	protected boolean isSingleRootStructure(IModule module) {
+		ProjectModule pm = (ProjectModule) module.loadAdapter(ProjectModule.class, null);
+		if (pm == null)
+			return false;
+		
+		return pm.isSingleRootStructure();
+	}
+
+	/**
+	 * Returns the module's publish path.
+	 * 
+	 * @param module a module
+	 * @return the publish directory for the module
+	 */
+	protected IPath getModulePublishDirectory(IModule module) {
+		if (isSingleRootStructure(module)) {
+			String type = module.getModuleType().getId();
+			if ("wst.web".equals(type)) {
+				IStaticWeb webModule = (IStaticWeb) module.loadAdapter(IStaticWeb.class, null);
+				if (webModule != null) {
+					//IContainer[] moduleFolder = webModule.getResourceFolders();
+					//if (moduleFolder != null && moduleFolder.length > 0)
+					//	return moduleFolder[0].getLocation();							
+				}
+			} else if ("jst.web".equals(type)) {
+				IWebModule webModule = (IWebModule) module.loadAdapter(IWebModule.class, null);
+				if (webModule != null) {
+					IContainer[] moduleFolder = webModule.getResourceFolders();
+					if (moduleFolder != null && moduleFolder.length > 0)
+						return moduleFolder[0].getLocation();							
+				}
+			}
+		}
+		
+		return getTempDirectory().append(module.getName());
+	}
+
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return a string
+	 */
+	public String toString() {
+		return "PreviewServer";
+	}
+
+	protected IModuleResourceDelta[] getPublishedResourceDelta(IModule[] module) {
+		return super.getPublishedResourceDelta(module);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.jst.server.tomcat.core/META-INF/MANIFEST.MF
index 05a23f6..579a244 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.jst.server.tomcat.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jst.server.tomcat.core; singleton:=true
-Bundle-Version: 1.1.102.qualifier
+Bundle-Version: 1.1.104.qualifier
 Bundle-Activator: org.eclipse.jst.server.tomcat.core.internal.TomcatPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/wst/ModuleTraverser.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/wst/ModuleTraverser.java
index fac45fd..c772703 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/wst/ModuleTraverser.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/wst/ModuleTraverser.java
@@ -79,6 +79,13 @@
 	 * via the virtual component API.
 	 */
 	public static final String CLASSPATH_COMPONENT_NON_DEPENDENCY = "org.eclipse.jst.component.nondependency"; //$NON-NLS-1
+	
+	/**
+	 * Argument values that are used to select component dependency attribute type. 
+	 */
+	private static final int DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY = 0;
+	private static final int DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_DEPENDENCY = 1;
+	private static final int DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_NONDEPENDENCY = 2;
 
 	/**
      * Scans the module using the specified visitor.
@@ -432,7 +439,8 @@
 			
 			final IPath pkgFragPath = root.getPath();
 			final IClasspathEntry resolvedEntry = (IClasspathEntry) pathToResolvedEntry.get(pkgFragPath);
-			final IClasspathAttribute resolvedAttrib = checkForComponentDependencyAttribute(resolvedEntry);
+			final IClasspathAttribute resolvedAttrib = checkForComponentDependencyAttribute(resolvedEntry,
+					DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY);
 			// attribute for the resolved entry must either be unspecified or it must be the
 			// dependency attribute for it to be included
 			if (resolvedAttrib == null || resolvedAttrib.getName().equals(CLASSPATH_COMPONENT_DEPENDENCY)) {
@@ -461,7 +469,8 @@
 		final IClasspathEntry[] entries = javaProject.getRawClasspath();
         for (int i = 0; i < entries.length; i++) {
             final IClasspathEntry entry = entries[i];
-            final IClasspathAttribute attrib = checkForComponentDependencyAttribute(entry);
+            final IClasspathAttribute attrib = checkForComponentDependencyAttribute(entry,
+            		DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_DEPENDENCY);
             if (attrib != null) {
             	referencedRawEntries.put(entry, attrib);
             }
@@ -472,7 +481,7 @@
 	/*
 	 * Derived from ClasspathDependencyUtil.checkForComponentDependencyAttribute()
 	 */
-	private static IClasspathAttribute checkForComponentDependencyAttribute(final IClasspathEntry entry) {
+	private static IClasspathAttribute checkForComponentDependencyAttribute(final IClasspathEntry entry, final int attributeType) {
 		if (entry == null) {
 			return null;
 		}
@@ -481,7 +490,15 @@
 	    	final IClasspathAttribute attribute = attributes[i];
 	    	final String name = attribute.getName();
 	    	if (name.equals(CLASSPATH_COMPONENT_DEPENDENCY)) {
-	    		return attribute;
+	    		if (attributeType == DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY
+	    				|| attributeType == DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_DEPENDENCY) {
+	    			return attribute;
+	    		}
+	    	} else if (name.equals(CLASSPATH_COMPONENT_NON_DEPENDENCY)) {
+	    		if (attributeType == DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY
+	    				|| attributeType == DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_NONDEPENDENCY) {
+	    			return attribute;
+	    		}
 	    	}
 	    }
 	    return null;
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.internet.monitor.core/META-INF/MANIFEST.MF
index 755e3b2..86cfb48 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.wst.internet.monitor.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.wst.internet.monitor.core; singleton:=true
-Bundle-Version: 1.0.303.qualifier
+Bundle-Version: 1.0.304.qualifier
 Bundle-Activator: org.eclipse.wst.internet.monitor.core.internal.MonitorPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPThread.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPThread.java
index f9d6b92..2acbbe1 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPThread.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPThread.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2003, 2008 IBM Corporation and others.
+ * Copyright (c) 2003, 2009 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
@@ -198,27 +198,37 @@
 		
 		if (isRequest) {
 			if (contentLength != -1) {
-				if (contentLength < 1024 * 1024) { // 1Mb
-					byte[] b = readBytes(contentLength);
-					out.write(b);
-					conn.addRequest(b, false);
-					setHTTPBody(b);
-				} else {
-					byte[] b = removeFromBuffer(Math.min(bufferIndex, contentLength));
-					int bytesLeft = contentLength - b.length;
-					out.write(b);
-					
-					int n = 0;
-					while (bytesLeft > 0) {
-						n = in.read(readBuffer);
-						bytesLeft -= n;
-						out.write(readBuffer, 0, n);
-					}
-					
-					b = Messages.errorContentSize.getBytes();
-					conn.addRequest(b, false);
-					setHTTPBody(b);
+				byte[] b2 = null;
+				int b2Index = 0;
+				if (contentLength < 1024 * 1024)
+					b2 = new byte[contentLength];
+				byte[] b = removeFromBuffer(Math.min(buffer.length, bufferIndex + contentLength));
+				if (b2 != null) {
+					System.arraycopy(b, 0, b2, 0, b.length);
+					b2Index += b.length;
 				}
+				int bytesLeft = contentLength - b.length;
+				Trace.trace(Trace.PARSING, "[Request] bytesLeft: "+ bytesLeft);
+				out.write(b);
+				
+				int n = 0;
+				while (bytesLeft > 0) {  
+					n = in.read(readBuffer, 0, Math.min(readBuffer.length, bytesLeft));
+					bytesLeft -= n;
+					if (b2 != null) {
+						System.arraycopy(readBuffer, 0, b2, b2Index, n);
+						b2Index += n;
+					}
+					out.write(readBuffer, 0, n);					
+					Trace.trace(Trace.PARSING,  "[Request] bytes read: "+ n + " bytesLeft: "+ bytesLeft);
+				}
+				
+				// restore the byte array for display
+				if (b2 == null)
+					b2 = Messages.errorContentSize.getBytes();
+				
+				conn.addRequest(b2, false);
+				setHTTPBody(b2);
 			} else if (transferEncoding != -1 && transferEncoding != ENCODING_IDENTITY) {
 				parseChunk();
 			}
@@ -275,33 +285,40 @@
 		
 		// spec 4.4.3
 		if (contentLength != -1) {
-			if (contentLength < 1024 * 1024) { // 1Mb
-				byte[] b = readBytes(contentLength);
-				out.write(b);
-				if (isRequest)
-					conn.addRequest(b, false);
-				else
-					conn.addResponse(b, false);
-				setHTTPBody(b);
-			} else {
-				byte[] b = removeFromBuffer(Math.min(bufferIndex, contentLength));
-				int bytesLeft = contentLength - b.length;
-				out.write(b);
-				
-				int n = 0;
-				while (bytesLeft > 0) {
-					n = in.read(readBuffer);
-					bytesLeft -= n;
-					out.write(readBuffer, 0, n);
-				}
-				
-				b = Messages.errorContentSize.getBytes();
-				if (isRequest)
-					conn.addRequest(b, false);
-				else
-					conn.addResponse(b, false);
-				setHTTPBody(b);
+			byte[] b2 = null;
+			int b2Index = 0;
+			if (contentLength < 1024 * 1024)
+				b2 = new byte[contentLength];
+			byte[] b = removeFromBuffer(Math.min(buffer.length, bufferIndex + contentLength));
+			if (b2 != null) {
+				System.arraycopy(b, 0, b2, 0, b.length);
+				b2Index += b.length;
 			}
+			int bytesLeft = contentLength - b.length;
+			Trace.trace(Trace.PARSING,"bytesLeft: "+ bytesLeft);
+			out.write(b);
+			
+			int n = 0;
+			while (bytesLeft > 0) {
+				n = in.read(readBuffer, 0, Math.min(readBuffer.length, bytesLeft));
+				bytesLeft -= n;
+				if (b2 != null) {
+					System.arraycopy(readBuffer, 0, b2, b2Index, n);
+					b2Index += n;
+				}
+				Trace.trace(Trace.PARSING,"bytes read: "+n + " bytesLeft: "+ bytesLeft);
+				out.write(readBuffer, 0, n);
+			}
+						
+			// restore the byte array for display
+			if (b2 == null)
+				b2 = Messages.errorContentSize.getBytes();
+			
+			if (isRequest)
+				conn.addRequest(b2, false);
+			else
+				conn.addResponse(b2, false);
+			setHTTPBody(b2);
 			return;
 		}
 		
@@ -310,6 +327,20 @@
 		Trace.trace(Trace.PARSING, "Unknown body for: " + this);
 	}
 
+	// Use this method to dump the content of a byte array
+	//
+	//	private void dumpBuffer(byte[] b) {
+	//		Trace.trace(Trace.PARSING, "Buffer dump to default.out:");
+	//		Trace.trace(Trace.PARSING, "Byte array: " + b.length);
+	//		for (int i = 0; i < b.length; i++) {
+	//			System.out.print(" [" + (char) b[i] + "]"); // +" ["+b[i+1]+"] "
+	//			if (i % 20 == 0) {
+	//				System.out.println();
+	//			}
+	//		}
+	//	}
+	
+	
 	/**
 	 * Parse an HTTP chunk.
 	 * 
diff --git a/plugins/org.eclipse.wst.server.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.server.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..13a0841
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/META-INF/MANIFEST.MF
@@ -0,0 +1,22 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.wst.server.core; singleton:=true
+Bundle-Version: 1.1.4.qualifier
+Bundle-Activator: org.eclipse.wst.server.core.internal.ServerPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.wst.server.core,
+ org.eclipse.wst.server.core.internal;x-friends:="org.eclipse.wst.server.ui",
+ org.eclipse.wst.server.core.internal.facets;x-friends:="org.eclipse.wst.server.ui",
+ org.eclipse.wst.server.core.internal.provisional;x-internal:=true,
+ org.eclipse.wst.server.core.model,
+ org.eclipse.wst.server.core.util
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.debug.core;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.update.core;bundle-version="[3.2.0,4.0.0)";resolution:=optional,
+ org.eclipse.wst.common.project.facet.core;bundle-version="[1.1.0,2.0.0)";resolution:=optional
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ResourceManager.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ResourceManager.java
index 1dd3d5a..1ca7d55 100644
--- a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ResourceManager.java
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ResourceManager.java
@@ -196,7 +196,7 @@
 				}
 				Trace.trace(Trace.EXTENSION_POINT, "  Loaded startup: " + cf[i].getAttribute("id"));
 			} catch (Throwable t) {
-				Trace.trace(Trace.SEVERE, "  Could not load startup: " + cf[i].getAttribute("id"), t);
+				ServerPlugin.logExtensionFailure(cf[i].getAttribute("id"), t);
 			}
 		}
 		
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Server.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Server.java
index e8b3eff..0c0396d 100644
--- a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Server.java
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Server.java
@@ -239,12 +239,6 @@
 			this.modules4 = modules4;
 			this.start = start;
 			this.info = info;
-			
-			// 102227 - lock entire workspace during publish
-			ISchedulingRule rule = MultiRule.combine(new ISchedulingRule[] {
-				ResourcesPlugin.getWorkspace().getRoot(), Server.this
-			});
-			setRule(rule);
 		}
 
 		public boolean belongsTo(Object family) {
@@ -253,12 +247,30 @@
 
 		protected IStatus run(IProgressMonitor monitor) {
 			if (start) {
-				IStatus status = startImpl(ILaunchManager.RUN_MODE, monitor);
-				if (status != null && status.getSeverity() == IStatus.ERROR)
-					return status;
+				try{
+					// 237222 - Apply the rules only when the job has started
+					Job.getJobManager().beginRule(Server.this, monitor);
+					IStatus status = startImpl(ILaunchManager.RUN_MODE, monitor);
+					if (status != null && status.getSeverity() == IStatus.ERROR)
+						return status;
+				}
+				finally{
+					Job.getJobManager().endRule(Server.this);
+				}
 			}
 			
-			return publishImpl(kind, modules4, info, monitor);
+			// 102227 - lock entire workspace during publish
+			ISchedulingRule publishRule = MultiRule.combine(new ISchedulingRule[] {
+				ResourcesPlugin.getWorkspace().getRoot(), Server.this
+			});
+			
+			try{
+				// 237222 - Apply the rules only when the job has started
+				Job.getJobManager().beginRule(publishRule, monitor);	
+				return publishImpl(kind, modules4, info, monitor);
+			} finally {
+				Job.getJobManager().endRule(publishRule);
+			}
 		}
 	}
 
@@ -268,24 +280,12 @@
 		protected static final byte PUBLISH_AFTER = 2;
 
 		protected String launchMode;
-		protected byte publish;
 
-		public StartJob(String launchMode, byte publish) {
+		public StartJob(String launchMode) {
 			super(NLS.bind(Messages.jobStartingServer, Server.this.getName()));
 			this.launchMode = launchMode;
-			this.publish = publish;
 			
-			if (publish != PUBLISH_NONE) {
-				IResourceRuleFactory ruleFactory = ResourcesPlugin.getWorkspace().getRuleFactory();
-				
-				// 102227 - lock entire workspace during publish		
-				ISchedulingRule[] rules = new ISchedulingRule[2];
-				rules[0] = ruleFactory.createRule(ResourcesPlugin.getWorkspace().getRoot());
-				rules[1] = Server.this;
-				
-				setRule(MultiRule.combine(rules));
-			} else
-				setRule(Server.this);
+			setRule(Server.this);
 		}
 
 		public boolean belongsTo(Object family) {
@@ -297,21 +297,7 @@
 		}
 
 		protected IStatus run(IProgressMonitor monitor) {
-			if (publish == PUBLISH_BEFORE) {
-				IStatus status = publishImpl(IServer.PUBLISH_INCREMENTAL, null, null, monitor);
-				if (status != null && status.getSeverity() == IStatus.ERROR)
-					return status;
-			}
-			
 			IStatus stat = startImpl(launchMode, monitor);
-			
-			if ( IStatus.ERROR != stat.getSeverity() ) {
-				if (publish == PUBLISH_AFTER) {
-					IStatus status = publishImpl(IServer.PUBLISH_INCREMENTAL, null, null, monitor);
-					if (status != null && status.getSeverity() == IStatus.ERROR)
-						return status;
-				}
-			}
 			return stat;
 		}
 	}
@@ -449,10 +435,11 @@
 				try {
 					long time = System.currentTimeMillis();
 					delegate = ((ServerType) serverType).createServerDelegate();
-					InternalInitializer.initializeServerDelegate(delegate, Server.this, monitor);
+					if (delegate != null)
+						InternalInitializer.initializeServerDelegate(delegate, Server.this, monitor);
 					Trace.trace(Trace.PERFORMANCE, "Server.getDelegate(): <" + (System.currentTimeMillis() - time) + "> " + getServerType().getId());
 				} catch (Throwable t) {
-					Trace.trace(Trace.SEVERE, "Could not create delegate " + toString(), t);
+					ServerPlugin.logExtensionFailure(toString(), t);
 				}
 			}
 		}
@@ -468,13 +455,14 @@
 				try {
 					long time = System.currentTimeMillis();
 					behaviourDelegate = ((ServerType) serverType).createServerBehaviourDelegate();
-					InternalInitializer.initializeServerBehaviourDelegate(behaviourDelegate, Server.this, monitor);
+					if (behaviourDelegate != null)
+						InternalInitializer.initializeServerBehaviourDelegate(behaviourDelegate, Server.this, monitor);
 					Trace.trace(Trace.PERFORMANCE, "Server.getBehaviourDelegate(): <" + (System.currentTimeMillis() - time) + "> " + getServerType().getId());
 					
 					if (getServerState() == IServer.STATE_STARTED)
 						autoPublish();
 				} catch (Throwable t) {
-					Trace.trace(Trace.SEVERE, "Could not create behaviour delegate " + toString(), t);
+					ServerPlugin.logExtensionFailure(toString(), t);
 				}
 			}
 		}
@@ -579,7 +567,11 @@
 	public void setServerState(int state) {
 		if (state == serverState)
 			return;
-
+		
+		// ensure that any server monitors are started
+		if (state == IServer.STATE_STARTED)
+			ServerMonitorManager.getInstance();
+		
 		this.serverState = state;
 		fireServerStateChangeEvent();
 	}
@@ -1099,7 +1091,6 @@
 
 	/*
 	 * Publish the given modules to the server.
-	 * TODO: Implementation!
 	 */
 	public void publish(final int kind, final List<IModule[]> modules2, final IAdaptable info, final IOperationListener opListener) {
 		if (getServerType() == null) {
@@ -1515,29 +1506,6 @@
 	}
 
 	/**
-	 * @see IServer#start(String, IProgressMonitor)
-	 */
-	public void start(String mode2, IProgressMonitor monitor) throws CoreException {
-		Trace.trace(Trace.FINEST, "Starting server: " + toString() + ", launchMode: " + mode2);
-		if (getServerType() == null)
-			return;
-		
-		// make sure that the delegate is loaded and the server state is correct
-		loadAdapter(ServerBehaviourDelegate.class, null);
-		
-		byte pub = StartJob.PUBLISH_NONE;
-		if (ServerCore.isAutoPublishing() && shouldPublish()) {
-			if (((ServerType)getServerType()).startBeforePublish())
-				pub = StartJob.PUBLISH_AFTER;
-			else
-				pub = StartJob.PUBLISH_BEFORE;
-		}
-		
-		StartJob startJob = new StartJob(mode2, pub);
-		startJob.schedule();
-	}
-
-	/**
 	 * Clean up any metadata associated with the server, typically in preparation for
 	 * deletion.
 	 */
@@ -1670,19 +1638,135 @@
 		job.schedule();
 	}
 
+	protected IStatus publishBeforeStart(IProgressMonitor monitor, boolean synchronous){
+
+		// check if we need to publish
+		byte pub = StartJob.PUBLISH_NONE;
+		if (ServerCore.isAutoPublishing() && shouldPublish()) {
+			if (((ServerType)getServerType()).startBeforePublish())
+				return Status.OK_STATUS;
+			pub = StartJob.PUBLISH_BEFORE;
+		}
+		
+		final IStatus [] pubStatus = new IStatus[]{Status.OK_STATUS};
+		
+		// publish before start
+		byte publish = pub;
+		if (publish == StartJob.PUBLISH_BEFORE) {
+			PublishJob pubJob = new PublishJob(IServer.PUBLISH_INCREMENTAL, null,false, null);
+			pubJob.addJobChangeListener(new JobChangeAdapter(){
+				public void done(IJobChangeEvent event) {
+					IStatus status = event.getResult();
+					if (status != null && status.getSeverity() == IStatus.ERROR)
+						pubStatus[0] = status; 
+				}
+				
+			});
+			
+			pubJob.schedule();
+			
+			try{
+				if (synchronous)
+					pubJob.join();
+					
+			}
+			catch (InterruptedException ie){
+				return Status.CANCEL_STATUS;
+			}
+		}
+		return pubStatus[0];
+	}
+	
+	protected IStatus publishAfterStart(IProgressMonitor monitor, boolean synchronous, final IOperationListener op){
+		
+		// check if we need to publish
+		byte pub = StartJob.PUBLISH_NONE;
+		if (ServerCore.isAutoPublishing() && shouldPublish()) {
+			if (((ServerType)getServerType()).startBeforePublish())
+				pub = StartJob.PUBLISH_AFTER;
+			else
+				return Status.OK_STATUS;
+		}
+		
+		final IStatus [] pubStatus = new IStatus[]{Status.OK_STATUS};
+		
+		// publish after start
+		byte publish = pub;
+		if (publish == StartJob.PUBLISH_AFTER) {
+			PublishJob pubJob = new PublishJob(IServer.PUBLISH_INCREMENTAL, null,false, null);
+			pubJob.addJobChangeListener(new JobChangeAdapter(){
+				public void done(IJobChangeEvent event) {
+					IStatus status = event.getResult();
+					if (status != null && status.getSeverity() == IStatus.ERROR)
+						pubStatus[0] = status; 
+					if (op != null){
+						op.done(status);
+					}
+				}
+				
+			});
+			
+			pubJob.schedule();
+			
+			try{
+				if (synchronous)
+					pubJob.join();
+			}
+			catch (InterruptedException ie){
+				return Status.CANCEL_STATUS;
+			}
+		}
+		return pubStatus[0];
+	}
+	
+	/**
+	 * @see IServer#start(String, IProgressMonitor)
+	 */
+	public void start(String mode2, IProgressMonitor monitor) throws CoreException {
+		Trace.trace(Trace.FINEST, "Starting server: " + toString() + ", launchMode: " + mode2);
+		
+		// make sure that the delegate is loaded and the server state is correct
+		loadAdapter(ServerBehaviourDelegate.class, null);
+		
+		if (getServerType() == null)
+			return;
+		
+		IStatus status = publishBeforeStart(monitor,false);
+		
+		if (status != null && status.getSeverity() == IStatus.ERROR){
+			Trace.trace(Trace.FINEST,"Failed publish job during start routine");
+			return;
+		}
+		
+		StartJob startJob = new StartJob(mode2);
+		startJob.schedule();
+		
+		publishAfterStart(monitor,false,null);
+
+	}
+	
 	/**
 	 * @see IServer#start(String, IOperationListener)
 	 */
 	public void start(String mode2, final IOperationListener opListener) {
+		
+		// make sure that the delegate is loaded and the server state is correct
+		loadAdapter(ServerBehaviourDelegate.class, null);
+		
 		if (getServerType() == null) {
 			if (opListener != null)
 				opListener.done(Status.OK_STATUS);
 			return;
 		}
 		
-		// make sure that the delegate is loaded and the server state is correct
-		loadAdapter(ServerBehaviourDelegate.class, null);
+		IStatus status = publishBeforeStart(null,false);
 		
+		if (status != null && status.getSeverity() == IStatus.ERROR){
+			Trace.trace(Trace.FINEST,"Failed publish job during start routine");
+			return;
+		}
+
+		// check the publish flag (again) to determine when to call opListener.done 
 		byte pub = StartJob.PUBLISH_NONE;
 		if (ServerCore.isAutoPublishing() && shouldPublish()) {
 			if (((ServerType)getServerType()).startBeforePublish())
@@ -1690,9 +1774,9 @@
 			else
 				pub = StartJob.PUBLISH_BEFORE;
 		}
-		
-		StartJob startJob = new StartJob(mode2, pub);
-		if (opListener != null) {
+
+		StartJob startJob = new StartJob(mode2);
+		if (opListener != null && pub != StartJob.PUBLISH_AFTER) {
 			startJob.addJobChangeListener(new JobChangeAdapter() {
 				public void done(IJobChangeEvent event) {
 					opListener.done(event.getResult());
@@ -1700,24 +1784,26 @@
 			});
 		}
 		startJob.schedule();
+		
+		publishAfterStart(null,false, opListener);
 	}
 
 	public void synchronousStart(String mode2, IProgressMonitor monitor) throws CoreException {
+		
+		// make sure that the delegate is loaded and the server state is correct
+		loadAdapter(ServerBehaviourDelegate.class, null);
+		
 		if (getServerType() == null)
 			return;
 		
-		// make sure that the delegate is loaded and the server state is correct
-		loadAdapter(ServerBehaviourDelegate.class, monitor);
+		IStatus status = publishBeforeStart(monitor,true);
 		
-		byte pub = StartJob.PUBLISH_NONE;
-		if (ServerCore.isAutoPublishing() && shouldPublish()) {
-			if (((ServerType)getServerType()).startBeforePublish())
-				pub = StartJob.PUBLISH_AFTER;
-			else
-				pub = StartJob.PUBLISH_BEFORE;
+		if (status != null && status.getSeverity() == IStatus.ERROR){
+			Trace.trace(Trace.FINEST,"Failed publish job during start routine");
+			return;
 		}
 		
-		StartJob startJob = new StartJob(mode2, pub);
+		StartJob startJob = new StartJob(mode2);
 		startJob.schedule();
 		
 		try {
@@ -1725,6 +1811,8 @@
 		} catch (InterruptedException e) {
 			Trace.trace(Trace.WARNING, "Error waiting for job", e);
 		}
+		
+		publishAfterStart(monitor,true,null);
 	}
 
 	/*
@@ -2024,7 +2112,7 @@
 		try {
 			return getDelegate(monitor).canModifyModules(add, remove);
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate canModifyModules() " + toString(), e);
+			ServerPlugin.logExtensionFailure(toString(), e);
 			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, e.getMessage(), e);
 		}
 	}
@@ -2138,7 +2226,7 @@
 				return null;
 			return children;
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate getChildModules() " + toString(), e);
+			ServerPlugin.logExtensionFailure(toString(), e);
 			return null;
 		}
 	}
@@ -2155,7 +2243,7 @@
 			//Trace.trace(Trace.FINER, "CoreException calling delegate getParentModules() " + toString(), se);
 			throw se;
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate getParentModules() " + toString(), e);
+			ServerPlugin.logExtensionFailure(toString(), e);
 			return null;
 		}
 	}
@@ -2179,7 +2267,7 @@
 			if (b)
 				return Status.OK_STATUS;
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate canRestartRuntime() " + toString(), e);
+			ServerPlugin.logExtensionFailure(toString(), e);
 		}
 		return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorRestartModule, null);
 	}
@@ -2214,7 +2302,7 @@
 		try {
 			getBehaviourDelegate(null).startModule(module, null);
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate restartModule() " + toString(), e);
+			Trace.trace(Trace.SEVERE, "Error calling delegate startModule() " + toString(), e);
 		}
 	}
 
@@ -2227,7 +2315,7 @@
 		try {
 			getBehaviourDelegate(null).stopModule(module, null);
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate restartModule() " + toString(), e);
+			Trace.trace(Trace.SEVERE, "Error calling delegate stopModule() " + toString(), e);
 		}
 	}
 
@@ -2254,7 +2342,7 @@
 		try {
 			return getDelegate(monitor).getServerPorts();
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error calling delegate getServerPorts() " + toString(), e);
+			ServerPlugin.logExtensionFailure(toString(), e);
 			return null;
 		}
 	}
@@ -2623,12 +2711,10 @@
 		
 		if (timer.timeout) {
 			stop(false);
-			// TODO this message should be changed to restart time out
 			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorRestartFailed, new String[] { getName(), (restartTimeout / 1000) + "" }), null);
 		}
 		
 		if (getServerState() == IServer.STATE_STOPPED)
-			// TODO this message should be changed to restart time out
 			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorRestartFailed, getName()), null);
 		
 		Trace.trace(Trace.FINEST, "synchronousRestart 4");
@@ -2679,7 +2765,7 @@
 					if (totalTimeout < 0)
 						totalTimeout = 1;
 					boolean userCancelled = false;
-					int retryPeriod = 2500;
+					int retryPeriod = 1000;
 					while (!notified[0] && totalTimeout > 0 && !userCancelled && !timer.alreadyDone) {
 						Thread.sleep(retryPeriod);
 						if (serverTimeout > 0)
@@ -2687,7 +2773,8 @@
 						if (!notified[0] && !timer.alreadyDone && monitor2.isCanceled()) {
 							// user canceled - set the server state to stopped
 							userCancelled = true;
-							setServerState(IServer.STATE_STOPPED);
+							if (launch != null && !launch.isTerminated())
+								launch.terminate();
 							// notify waiter
 							synchronized (notified) {
 								Trace.trace(Trace.FINEST, "synchronousStart user cancelled");
@@ -2751,7 +2838,7 @@
 			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorStartTimeout, new String[] { getName(), (serverTimeout / 1000) + "" }), null);
 		}
 		
-		if (getServerState() == IServer.STATE_STOPPED)
+		if (!monitor.isCanceled() && getServerState() == IServer.STATE_STOPPED)
 			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorStartFailed, getName()), null);
 		
 		Trace.trace(Trace.FINEST, "synchronousStart 4");
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPlugin.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPlugin.java
index 60e638b..3b92f41 100644
--- a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPlugin.java
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPlugin.java
@@ -331,6 +331,20 @@
 		context.removeBundleListener(bundleListener);
 	}
 
+	/**
+	 * Logs an error message caused by a missing or failed extension
+	 * (server adapters, runtime, class-path provider, etc.). A single
+	 * error is output to the .log (once per session) and the full
+	 * exception is output to tracing.
+	 * 
+	 * @param id the id of the missing/failed extension
+	 * @param t a throwable or exception
+	 */
+	public static void logExtensionFailure(String id, Throwable t) {
+		Trace.trace(Trace.SEVERE, "Missing or failed server extension: " + id + ". Enable tracing for more information");
+		Trace.trace(Trace.WARNING, "Exception in server delegate", t);
+	}
+
 	private static void addAll(List<Object> list, Object[] obj) {
 		if (obj == null)
 			return;
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Trace.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Trace.java
new file mode 100644
index 0000000..ea2fd7f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Trace.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.core.internal;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+/**
+ * Helper class to route trace output.
+ */
+public class Trace {
+	public static final byte CONFIG = 0;
+	public static final byte INFO = 1;
+	public static final byte WARNING = 2;
+	public static final byte SEVERE = 3;
+	public static final byte FINER = 4;
+	public static final byte FINEST = 5;
+	
+	public static final byte RESOURCES = 6;
+	public static final byte EXTENSION_POINT = 7;
+	public static final byte LISTENERS = 8;
+	public static final byte RUNTIME_TARGET = 9;
+	public static final byte PERFORMANCE = 10;
+	public static final byte PUBLISHING = 11;
+
+	private static final String[] levelNames = new String[] {
+		"CONFIG   ", "INFO     ", "WARNING  ", "SEVERE   ", "FINER    ", "FINEST   ",
+		"RESOURCES", "EXTENSION", "LISTENERS", "TARGET   ", "PERF     ", "PUBLISH  "};
+
+	private static final SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm.ss.SSS");
+
+	private static Set<String> logged = new HashSet<String>();
+
+	/**
+	 * Trace constructor comment.
+	 */
+	private Trace() {
+		super();
+	}
+
+	/**
+	 * Trace the given text.
+	 *
+	 * @param level a trace level
+	 * @param s a message
+	 */
+	public static void trace(int level, String s) {
+		trace(level, s, null);
+	}
+
+	/**
+	 * Trace the given message and exception.
+	 *
+	 * @param level a trace level
+	 * @param s a message
+	 * @param t a throwable
+	 */
+	public static void trace(int level, String s, Throwable t) {
+		if (s == null)
+			return;
+		
+		if (level == SEVERE) {
+			if (!logged.contains(s)) {
+				ServerPlugin.log(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, s, t));
+				logged.add(s);
+			}
+		}
+		
+		if (!ServerPlugin.getInstance().isDebugging())
+			return;
+		
+		StringBuffer sb = new StringBuffer(ServerPlugin.PLUGIN_ID);
+		sb.append(" ");
+		sb.append(levelNames[level]);
+		sb.append(" ");
+		sb.append(sdf.format(new Date()));
+		sb.append(" ");
+		sb.append(s);
+		//Platform.getDebugOption(ServerCore.PLUGIN_ID + "/" + "resources");
+
+		System.out.println(sb.toString());
+		if (t != null)
+			t.printStackTrace();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ServerBehaviourDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ServerBehaviourDelegate.java
index b0f48c0..1a822ee 100644
--- a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ServerBehaviourDelegate.java
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ServerBehaviourDelegate.java
@@ -853,7 +853,10 @@
 			if (taskStatus != null && !taskStatus.isOK())
 				tempMulti.addAll(taskStatus);
 			
-			executePublishers(kind, moduleList, monitor, info2);
+			// execute publishers
+			taskStatus = executePublishers(kind, moduleList, monitor, info2);
+			if (taskStatus != null && !taskStatus.isOK())
+				tempMulti.addAll(taskStatus);			
 			
 			if (monitor.isCanceled())
 				return Status.CANCEL_STATUS;
@@ -1063,13 +1066,15 @@
 	 *    org.eclipse.swt.widgets.Shell.class
 	 * @throws CoreException
 	 */
-	protected void executePublishers(int kind, List<IModule[]> modules, IProgressMonitor monitor, IAdaptable info) throws CoreException {
+	protected MultiStatus executePublishers(int kind, List<IModule[]> modules, IProgressMonitor monitor, IAdaptable info) throws CoreException {
 		Publisher[] publishers = ((Server)getServer()).getEnabledPublishers();
 		int size = publishers.length;
 		Trace.trace(Trace.FINEST, "Executing publishers: " + size);
 		
 		if (size == 0)
-			return;
+			return null;
+		
+		MultiStatus multi = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, Messages.taskPerforming, null);
 		
 		TaskModel taskModel = new TaskModel();
 		taskModel.putObject(TaskModel.TASK_SERVER, getServer());
@@ -1080,7 +1085,8 @@
 			monitor.subTask(NLS.bind(Messages.taskPerforming, pub.getName()));
 			try {
 				pub.setTaskModel(taskModel);
-				pub.execute(kind, ProgressUtil.getSubMonitorFor(monitor, 500), info);
+				IStatus pubStatus = pub.execute(kind, ProgressUtil.getSubMonitorFor(monitor, 500), info);
+				multi.add(pubStatus);
 			} catch (CoreException ce) {
 				Trace.trace(Trace.SEVERE, "Publisher failed", ce);
 				throw ce;
@@ -1088,8 +1094,9 @@
 			
 			// return early if the monitor has been canceled
 			if (monitor.isCanceled())
-				return;
+				return multi;
 		}
+		return multi;
 	}
 
 	/**
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/PublishHelper.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/PublishHelper.java
new file mode 100644
index 0000000..3b8d979
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/PublishHelper.java
@@ -0,0 +1,806 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.wst.server.core.util;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.*;
+import org.eclipse.wst.server.core.internal.Messages;
+import org.eclipse.wst.server.core.internal.ProgressUtil;
+import org.eclipse.wst.server.core.internal.ServerPlugin;
+import org.eclipse.wst.server.core.internal.Trace;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.server.core.model.IModuleFile;
+import org.eclipse.wst.server.core.model.IModuleFolder;
+import org.eclipse.wst.server.core.model.IModuleResource;
+import org.eclipse.wst.server.core.model.IModuleResourceDelta;
+/**
+ * Utility class with an assortment of useful publishing file methods.
+ *
+ * @since 3.0
+ */
+public final class PublishHelper {
+	// size of the buffer
+	private static final int BUFFER = 65536;
+
+	// the buffer
+	private static byte[] buf = new byte[BUFFER];
+
+	private static final IStatus[] EMPTY_STATUS = new IStatus[0];
+
+	private static final File defaultTempDir = ServerPlugin.getInstance().getStateLocation().toFile();
+
+	private static final String TEMPFILE_PREFIX = "tmp";
+
+	private File tempDir;
+
+	/**
+	 * Create a new PublishHelper.
+	 * 
+	 * @param tempDirectory a temporary directory to use during publishing, or <code>null</code>
+	 *    to use the default. If it does not exist, the folder will be created
+	 */
+	public PublishHelper(File tempDirectory) {
+		this.tempDir = tempDirectory;
+		if (tempDir == null)
+			tempDir = defaultTempDir;
+		else if (!tempDir.exists())
+			tempDir.mkdirs();
+	}
+
+	/**
+	 * Copy a file from a to b. Closes the input stream after use.
+	 * 
+	 * @param in an input stream
+	 * @param to a path to copy to. the directory must already exist
+	 * @param ts timestamp
+	 * @throws CoreException if anything goes wrong
+	 */
+	private void copyFile(InputStream in, IPath to, long ts, IModuleFile mf) throws CoreException {
+		OutputStream out = null;
+		
+		File tempFile = null;
+		try {
+			File file = to.toFile();
+			tempFile = File.createTempFile(TEMPFILE_PREFIX, "." + to.getFileExtension(), tempDir);
+			
+			out = new FileOutputStream(tempFile);
+			
+			int avail = in.read(buf);
+			while (avail > 0) {
+				out.write(buf, 0, avail);
+				avail = in.read(buf);
+			}
+			
+			out.close();
+			out = null;
+			
+			moveTempFile(tempFile, file);
+			
+			if (ts != IResource.NULL_STAMP && ts != 0)
+				file.setLastModified(ts);
+		} catch (CoreException e) {
+			throw e;
+		} catch (Exception e) {
+			IPath path = mf.getModuleRelativePath().append(mf.getName());
+			Trace.trace(Trace.SEVERE, "Error copying file: " + path.toOSString() + " to " + to.toOSString(), e);
+			throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCopyingFile, path.toOSString(), e.getLocalizedMessage()), null));
+		} finally {
+			if (tempFile != null && tempFile.exists())
+				tempFile.deleteOnExit();
+			try {
+				if (in != null)
+					in.close();
+			} catch (Exception ex) {
+				// ignore
+			}
+			try {
+				if (out != null)
+					out.close();
+			} catch (Exception ex) {
+				// ignore
+			}
+		}
+	}
+
+	/**
+	 * Utility method to recursively delete a directory.
+	 *
+	 * @param dir a directory
+	 * @param monitor a progress monitor, or <code>null</code> if progress
+	 *    reporting and cancellation are not desired
+	 * @return a possibly-empty array of error and warning status
+	 */
+	public static IStatus[] deleteDirectory(File dir, IProgressMonitor monitor) {
+		if (!dir.exists() || !dir.isDirectory())
+			return new IStatus[] { new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorNotADirectory, dir.getAbsolutePath()), null) };
+		
+		List<IStatus> status = new ArrayList<IStatus>(2);
+		
+		try {
+			File[] files = dir.listFiles();
+			int size = files.length;
+			monitor = ProgressUtil.getMonitorFor(monitor);
+			monitor.beginTask(NLS.bind(Messages.deletingTask, new String[] { dir.getAbsolutePath() }), size * 10);
+			
+			// cycle through files
+			boolean deleteCurrent = true;
+			for (int i = 0; i < size; i++) {
+				File current = files[i];
+				if (current.isFile()) {
+					if (!current.delete()) {
+						status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, files[i].getAbsolutePath()), null));
+						deleteCurrent = false;
+					}
+					monitor.worked(10);
+				} else if (current.isDirectory()) {
+					monitor.subTask(NLS.bind(Messages.deletingTask, new String[] {current.getAbsolutePath()}));
+					IStatus[] stat = deleteDirectory(current, ProgressUtil.getSubMonitorFor(monitor, 10));
+					if (stat != null && stat.length > 0) {
+						deleteCurrent = false;
+						addArrayToList(status, stat);
+					}
+				}
+			}
+			if (deleteCurrent && !dir.delete())
+				status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, dir.getAbsolutePath()), null));
+			monitor.done();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error deleting directory " + dir.getAbsolutePath(), e);
+			status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, e.getLocalizedMessage(), null));
+		}
+		
+		IStatus[] stat = new IStatus[status.size()];
+		status.toArray(stat);
+		return stat;
+	}
+
+	/**
+	 * Smart copy the given module resources to the given path.
+	 * 
+	 * @param resources an array of module resources
+	 * @param path an external path to copy to
+	 * @param monitor a progress monitor, or <code>null</code> if progress
+	 *    reporting and cancellation are not desired
+	 * @return a possibly-empty array of error and warning status 
+	 */
+	public IStatus[] publishSmart(IModuleResource[] resources, IPath path, IProgressMonitor monitor) {
+		return publishSmart(resources, path, null, monitor);
+	}
+
+	/**
+	 * Smart copy the given module resources to the given path.
+	 * 
+	 * @param resources an array of module resources
+	 * @param path an external path to copy to
+	 * @param ignore an array of paths relative to path to ignore, i.e. not delete or copy over
+	 * @param monitor a progress monitor, or <code>null</code> if progress
+	 *    reporting and cancellation are not desired
+	 * @return a possibly-empty array of error and warning status 
+	 */
+	public IStatus[] publishSmart(IModuleResource[] resources, IPath path, IPath[] ignore, IProgressMonitor monitor) {
+		if (resources == null)
+			return EMPTY_STATUS;
+		
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		
+		List<IStatus> status = new ArrayList<IStatus>(2);
+		File toDir = path.toFile();
+		int fromSize = resources.length;
+		String[] fromFileNames = new String[fromSize];
+		for (int i = 0; i < fromSize; i++)
+			fromFileNames[i] = resources[i].getName();
+		List<String> ignoreFileNames = new ArrayList<String>();
+		if (ignore != null) {
+			for (int i = 0; i < ignore.length; i++) {
+				if (ignore[i].segmentCount() == 1) {
+					ignoreFileNames.add(ignore[i].toOSString());
+				}
+			}
+		}
+		
+		//	cache files and file names for performance
+		File[] toFiles = null;
+		String[] toFileNames = null;
+		
+		boolean foundExistingDir = false;
+		if (toDir.exists()) {
+			if (toDir.isDirectory()) {
+				foundExistingDir = true;
+				toFiles = toDir.listFiles();
+				int toSize = toFiles.length;
+				toFileNames = new String[toSize];
+				
+				// check if this exact file exists in the new directory
+				for (int i = 0; i < toSize; i++) {
+					toFileNames[i] = toFiles[i].getName();
+					boolean isDir = toFiles[i].isDirectory();
+					boolean found = false;
+					for (int j = 0; j < fromSize; j++) {
+						if (toFileNames[i].equals(fromFileNames[j]) && isDir == resources[j] instanceof IModuleFolder) {
+							found = true;
+							break;
+						}
+					}
+					
+					// delete file if it can't be found or isn't the correct type
+					if (!found) {
+						boolean delete = true;
+						// if should be preserved, don't delete and don't try to copy
+						for (String preserveFileName : ignoreFileNames) {
+							if (toFileNames[i].equals(preserveFileName)) {
+								delete = false;
+								break;
+							}
+						}
+						if (delete) {
+							if (isDir) {
+								IStatus[] stat = deleteDirectory(toFiles[i], null);
+								addArrayToList(status, stat);
+							} else {
+								if (!toFiles[i].delete())
+									status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, toFiles[i].getAbsolutePath()), null));
+							}
+						}
+						toFiles[i] = null;
+						toFileNames[i] = null;
+					}
+				}
+			} else { //if (toDir.isFile())
+				if (!toDir.delete()) {
+					status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, toDir.getAbsolutePath()), null));
+					IStatus[] stat = new IStatus[status.size()];
+					status.toArray(stat);
+					return stat;
+				}
+			}
+		}
+		if (!foundExistingDir && !toDir.mkdirs()) {
+			status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorMkdir, toDir.getAbsolutePath()), null));
+			IStatus[] stat = new IStatus[status.size()];
+			status.toArray(stat);
+			return stat;
+		}
+		
+		if (monitor.isCanceled())
+			return new IStatus[] { Status.CANCEL_STATUS };
+		
+		monitor.worked(50);
+		
+		// cycle through files and only copy when it doesn't exist
+		// or is newer
+		if (toFiles == null) {
+			toFiles = toDir.listFiles();
+			if (toFiles == null)
+				toFiles = new File[0];
+		}
+		int toSize = toFiles.length;
+		
+		int dw = 0;
+		if (toSize > 0)
+			dw = 500 / toSize;
+		
+		// cache file names and last modified dates for performance
+		if (toFileNames == null)
+			toFileNames = new String[toSize];
+		long[] toFileMod = new long[toSize];
+		for (int i = 0; i < toSize; i++) {
+			if (toFiles[i] != null) {
+				if (toFileNames[i] != null)
+					toFileNames[i] = toFiles[i].getName();
+				toFileMod[i] = toFiles[i].lastModified();
+			}
+		}
+		
+		for (int i = 0; i < fromSize; i++) {
+			IModuleResource current = resources[i];
+			String name = fromFileNames[i];
+			boolean currentIsDir = current instanceof IModuleFolder;
+			
+			if (!currentIsDir) {
+				// check if this is a new or newer file
+				boolean copy = true;
+				IModuleFile mf = (IModuleFile) current;
+				
+				long mod = -1;
+				IFile file = (IFile) mf.getAdapter(IFile.class);
+				if (file != null) {
+					mod = file.getLocalTimeStamp();
+				} else {
+					File file2 = (File) mf.getAdapter(File.class);
+					mod = file2.lastModified();
+				}
+				
+				for (int j = 0; j < toSize; j++) {
+					if (name.equals(toFileNames[j]) && mod == toFileMod[j]) {
+						copy = false;
+						break;
+					}
+				}
+				
+				if (copy) {
+					try {
+						copyFile(mf, path.append(name));
+					} catch (CoreException ce) {
+						status.add(ce.getStatus());
+					}
+				}
+				monitor.worked(dw);
+			} else { //if (currentIsDir) {
+				IModuleFolder folder = (IModuleFolder) current;
+				IModuleResource[] children = folder.members();
+
+				// build array of ignored Paths that apply to this folder
+				IPath[] ignoreChildren = null;
+				if (ignore != null) {
+					List<IPath> ignoreChildPaths = new ArrayList<IPath>();
+					for (int j = 0; j < ignore.length; j++) {
+						IPath preservePath = ignore[j];
+						if (preservePath.segment(0).equals(name)) {
+							ignoreChildPaths.add(preservePath.removeFirstSegments(1));
+						}
+					}
+					if (ignoreChildPaths.size() > 0)
+						ignoreChildren = ignoreChildPaths.toArray(new Path[ignoreChildPaths.size()]);
+				}
+				monitor.subTask(NLS.bind(Messages.copyingTask, new String[] {name, name}));
+				IStatus[] stat = publishSmart(children, path.append(name), ignoreChildren, ProgressUtil.getSubMonitorFor(monitor, dw));
+				addArrayToList(status, stat);
+			}
+		}
+		if (monitor.isCanceled())
+			return new IStatus[] { Status.CANCEL_STATUS };
+		
+		monitor.worked(500 - dw * toSize);
+		monitor.done();
+		
+		IStatus[] stat = new IStatus[status.size()];
+		status.toArray(stat);
+		return stat;
+	}
+
+	/**
+	 * Handle a delta publish.
+	 * 
+	 * @param delta a module resource delta
+	 * @param path the path to publish to
+	 * @param monitor a progress monitor, or <code>null</code> if progress
+	 *    reporting and cancellation are not desired
+	 * @return a possibly-empty array of error and warning status
+	 */
+	public IStatus[] publishDelta(IModuleResourceDelta[] delta, IPath path, IProgressMonitor monitor) {
+		if (delta == null)
+			return EMPTY_STATUS;
+		
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		
+		List<IStatus> status = new ArrayList<IStatus>(2);
+		int size2 = delta.length;
+		for (int i = 0; i < size2; i++) {
+			IStatus[] stat = publishDelta(delta[i], path, monitor);
+			addArrayToList(status, stat);
+		}
+		
+		IStatus[] stat = new IStatus[status.size()];
+		status.toArray(stat);
+		return stat;
+	}
+
+	/**
+	 * Handle a delta publish.
+	 * 
+	 * @param delta a module resource delta
+	 * @param path the path to publish to
+	 * @param monitor a progress monitor, or <code>null</code> if progress
+	 *    reporting and cancellation are not desired
+	 * @return a possibly-empty array of error and warning status
+	 */
+	public IStatus[] publishDelta(IModuleResourceDelta delta, IPath path, IProgressMonitor monitor) {
+		List<IStatus> status = new ArrayList<IStatus>(2);
+		
+		IModuleResource resource = delta.getModuleResource();
+		int kind2 = delta.getKind();
+		
+		if (resource instanceof IModuleFile) {
+			IModuleFile file = (IModuleFile) resource;
+			try {
+				if (kind2 == IModuleResourceDelta.REMOVED)
+					deleteFile(path, file);
+				else {
+					IPath path2 = path.append(file.getModuleRelativePath()).append(file.getName());
+					File f = path2.toFile().getParentFile();
+					if (!f.exists())
+						f.mkdirs();
+					
+					copyFile(file, path2);
+				}
+			} catch (CoreException ce) {
+				status.add(ce.getStatus());
+			}
+			IStatus[] stat = new IStatus[status.size()];
+			status.toArray(stat);
+			return stat;
+		}
+		
+		if (kind2 == IModuleResourceDelta.ADDED) {
+			IPath path2 = path.append(resource.getModuleRelativePath()).append(resource.getName());
+			File file = path2.toFile();
+			if (!file.exists() && !file.mkdirs()) {
+				status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorMkdir, path2), null));
+				IStatus[] stat = new IStatus[status.size()];
+				status.toArray(stat);
+				return stat;
+			}
+		}
+		
+		IModuleResourceDelta[] childDeltas = delta.getAffectedChildren();
+		int size = childDeltas.length;
+		for (int i = 0; i < size; i++) {
+			IStatus[] stat = publishDelta(childDeltas[i], path, monitor);
+			addArrayToList(status, stat);
+		}
+		
+		if (kind2 == IModuleResourceDelta.REMOVED) {
+			IPath path2 = path.append(resource.getModuleRelativePath()).append(resource.getName());
+			File file = path2.toFile();
+			if (file.exists() && !file.delete()) {
+				status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, path2), null));
+			}
+		}
+		
+		IStatus[] stat = new IStatus[status.size()];
+		status.toArray(stat);
+		return stat;
+	}
+
+	private static void deleteFile(IPath path, IModuleFile file) throws CoreException {
+		Trace.trace(Trace.PUBLISHING, "Deleting: " + file.getName() + " from " + path.toString());
+		IPath path2 = path.append(file.getModuleRelativePath()).append(file.getName());
+		if (path2.toFile().exists() && !path2.toFile().delete())
+			throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, path2), null));
+	}
+
+	private void copyFile(IModuleFile mf, IPath path) throws CoreException {
+		Trace.trace(Trace.PUBLISHING, "Copying: " + mf.getName() + " to " + path.toString());
+		
+		IFile file = (IFile) mf.getAdapter(IFile.class);
+		if (file != null)
+			copyFile(file.getContents(), path, file.getLocalTimeStamp(), mf);
+		else {
+			File file2 = (File) mf.getAdapter(File.class);
+			InputStream in = null;
+			try {
+				in = new FileInputStream(file2);
+			} catch (IOException e) {
+				throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorReading, file2.getAbsolutePath()), e));
+			}
+			copyFile(in, path, file2.lastModified(), mf);
+		}
+	}
+
+	/**
+	 * Publish the given module resources to the given path.
+	 * 
+	 * @param resources an array of module resources
+	 * @param path a path to publish to
+	 * @param monitor a progress monitor, or <code>null</code> if progress
+	 *    reporting and cancellation are not desired
+	 * @return a possibly-empty array of error and warning status
+	 */
+	public IStatus[] publishFull(IModuleResource[] resources, IPath path, IProgressMonitor monitor) {
+		if (resources == null)
+			return EMPTY_STATUS;
+		
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		
+		List<IStatus> status = new ArrayList<IStatus>(2);
+		int size = resources.length;
+		for (int i = 0; i < size; i++) {
+			IStatus[] stat = copy(resources[i], path, monitor);
+			addArrayToList(status, stat);
+		}
+		
+		IStatus[] stat = new IStatus[status.size()];
+		status.toArray(stat);
+		return stat;
+	}
+
+	private IStatus[] copy(IModuleResource resource, IPath path, IProgressMonitor monitor) {
+		String name = resource.getName();
+		Trace.trace(Trace.PUBLISHING, "Copying: " + name + " to " + path.toString());
+		List<IStatus> status = new ArrayList<IStatus>(2);
+		if (resource instanceof IModuleFolder) {
+			IModuleFolder folder = (IModuleFolder) resource;
+			IStatus[] stat = publishFull(folder.members(), path, monitor);
+			addArrayToList(status, stat);
+		} else {
+			IModuleFile mf = (IModuleFile) resource;
+			path = path.append(mf.getModuleRelativePath()).append(name);
+			File f = path.toFile().getParentFile();
+			if (!f.exists())
+				f.mkdirs();
+			try {
+				copyFile(mf, path);
+			} catch (CoreException ce) {
+				status.add(ce.getStatus());
+			}
+		}
+		IStatus[] stat = new IStatus[status.size()];
+		status.toArray(stat);
+		return stat;
+	}
+
+	/**
+	 * Creates a new zip file containing the given module resources. Deletes the existing file
+	 * (and doesn't create a new one) if resources is null or empty.
+	 * 
+	 * @param resources an array of module resources
+	 * @param path the path where the zip file should be created 
+	 * @param monitor a progress monitor, or <code>null</code> if progress
+	 *    reporting and cancellation are not desired
+	 * @return a possibly-empty array of error and warning status
+	 */
+	public IStatus[] publishZip(IModuleResource[] resources, IPath path, IProgressMonitor monitor) {
+		if (resources == null || resources.length == 0) {
+			// should also check if resources consists of all empty directories
+			File file = path.toFile();
+			if (file.exists())
+				file.delete();
+			return EMPTY_STATUS;
+		}
+		
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		
+		File tempFile = null;
+		try {
+			File file = path.toFile();
+			tempFile = File.createTempFile(TEMPFILE_PREFIX, "." + path.getFileExtension(), tempDir);
+			
+			BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(tempFile));
+			ZipOutputStream zout = new ZipOutputStream(bout);
+			addZipEntries(zout, resources);
+			zout.close();
+			
+			moveTempFile(tempFile, file);
+		} catch (CoreException e) {
+			return new IStatus[] { e.getStatus() };
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error zipping", e);
+			return new Status[] { new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCreatingZipFile, path.lastSegment(), e.getLocalizedMessage()), e) };
+		} finally {
+			if (tempFile != null && tempFile.exists())
+				tempFile.deleteOnExit();
+		}
+		return EMPTY_STATUS;
+	}
+
+	private static void addZipEntries(ZipOutputStream zout, IModuleResource[] resources) throws Exception {
+		if (resources == null)
+			return;
+		
+		int size = resources.length;
+		for (int i = 0; i < size; i++) {
+			if (resources[i] instanceof IModuleFolder) {
+				IModuleFolder mf = (IModuleFolder) resources[i];
+				IModuleResource[] res = mf.members();
+				
+				IPath path = mf.getModuleRelativePath().append(mf.getName());
+				String entryPath = path.toPortableString();
+				if (!entryPath.endsWith("/"))
+					entryPath += '/';
+				
+				ZipEntry ze = new ZipEntry(entryPath);
+				
+				long ts = 0;
+				IContainer folder = (IContainer) mf.getAdapter(IContainer.class);
+				if (folder != null)
+					ts = folder.getLocalTimeStamp();
+				
+				if (ts != IResource.NULL_STAMP && ts != 0)
+					ze.setTime(ts);
+				
+				zout.putNextEntry(ze);
+				zout.closeEntry();
+				
+				addZipEntries(zout, res);
+				continue;
+			}
+			
+			IModuleFile mf = (IModuleFile) resources[i];
+			IPath path = mf.getModuleRelativePath().append(mf.getName());
+			
+			ZipEntry ze = new ZipEntry(path.toPortableString());
+			
+			InputStream in = null;
+			long ts = 0;
+			IFile file = (IFile) mf.getAdapter(IFile.class);
+			if (file != null) {
+				ts = file.getLocalTimeStamp();
+				in = file.getContents();
+			} else {
+				File file2 = (File) mf.getAdapter(File.class);
+				ts = file2.lastModified();
+				in = new FileInputStream(file2);
+			}
+			
+			if (ts != IResource.NULL_STAMP && ts != 0)
+				ze.setTime(ts);
+			
+			zout.putNextEntry(ze);
+			
+			try {
+				int n = 0;
+				while (n > -1) {
+					n = in.read(buf);
+					if (n > 0)
+						zout.write(buf, 0, n);
+				}
+			} finally {
+				in.close();
+			}
+			
+			zout.closeEntry();
+		}
+	}
+
+	/**
+	 * Utility method to move a temp file into position by deleting the original and
+	 * swapping in a new copy.
+	 *  
+	 * @param tempFile
+	 * @param file
+	 * @throws CoreException
+	 */
+	private void moveTempFile(File tempFile, File file) throws CoreException {
+		if (file.exists()) {
+			if (!safeDelete(file, 2)) {
+				// attempt to rewrite an existing file with the tempFile contents if
+				// the existing file can't be deleted to permit the move
+				try {
+					InputStream in = new FileInputStream(tempFile);
+					IStatus status = copyFile(in, file.getPath());
+					if (!status.isOK()) {
+						MultiStatus status2 = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, file.toString()), null);
+						status2.add(status);
+						throw new CoreException(status2);
+					}
+					return;
+				} catch (FileNotFoundException e) {
+					// shouldn't occur
+				} finally {
+					tempFile.delete();
+				}
+				/*if (!safeDelete(file, 8)) {
+					tempFile.delete();
+					throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, file.toString()), null));
+				}*/
+			}
+		}
+		if (!safeRename(tempFile, file, 10))
+			throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorRename, tempFile.toString()), null));
+	}
+
+	/**
+	 * Copy a file from a to b. Closes the input stream after use.
+	 *
+	 * @param in an InputStream
+	 * @param to the file to copy to
+	 * @return a status
+	 */
+	private IStatus copyFile(InputStream in, String to) {
+		OutputStream out = null;
+		
+		try {
+			out = new FileOutputStream(to);
+			
+			int avail = in.read(buf);
+			while (avail > 0) {
+				out.write(buf, 0, avail);
+				avail = in.read(buf);
+			}
+			return Status.OK_STATUS;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error copying file", e);
+			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCopyingFile, new String[] {to, e.getLocalizedMessage()}), e);
+		} finally {
+			try {
+				if (in != null)
+					in.close();
+			} catch (Exception ex) {
+				// ignore
+			}
+			try {
+				if (out != null)
+					out.close();
+			} catch (Exception ex) {
+				// ignore
+			}
+		}
+	}
+
+	/**
+	 * Safe delete. Tries to delete multiple times before giving up.
+	 * 
+	 * @param f
+	 * @return <code>true</code> if it succeeds, <code>false</code> otherwise
+	 */
+	private static boolean safeDelete(File f, int retrys) {
+		int count = 0;
+		while (count < retrys) {
+			if (!f.exists())
+				return true;
+			
+			f.delete();
+			
+			if (!f.exists())
+				return true;
+			
+			count++;
+			// delay if we are going to try again
+			if (count < retrys) {
+				try {
+					Thread.sleep(100);
+				} catch (Exception e) {
+					// ignore
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Safe rename. Will try multiple times before giving up.
+	 * 
+	 * @param from
+	 * @param to
+	 * @param retrys number of times to retry
+	 * @return <code>true</code> if it succeeds, <code>false</code> otherwise
+	 */
+	private static boolean safeRename(File from, File to, int retrys) {
+		// make sure parent dir exists
+		File dir = to.getParentFile();
+		if (dir != null && !dir.exists())
+			dir.mkdirs();
+		
+		int count = 0;
+		while (count < retrys) {
+			if (from.renameTo(to))
+				return true;
+			
+			count++;
+			// delay if we are going to try again
+			if (count < retrys) {
+				try {
+					Thread.sleep(100);
+				} catch (Exception e) {
+					// ignore
+				}
+			}
+		}
+		return false;
+	}
+
+	private static void addArrayToList(List<IStatus> list, IStatus[] a) {
+		if (list == null || a == null || a.length == 0)
+			return;
+		
+		int size = a.length;
+		for (int i = 0; i < size; i++)
+			list.add(a[i]);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/.classpath b/plugins/org.eclipse.wst.server.http.core/.classpath
deleted file mode 100644
index 196d49a..0000000
--- a/plugins/org.eclipse.wst.server.http.core/.classpath
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src/"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
-	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/plugins/org.eclipse.wst.server.http.core/.cvsignore b/plugins/org.eclipse.wst.server.http.core/.cvsignore
deleted file mode 100644
index 33dd7de..0000000
--- a/plugins/org.eclipse.wst.server.http.core/.cvsignore
+++ /dev/null
@@ -1,6 +0,0 @@
-bin
-temp.folder
-build.xml
-@dot
-src.zip
-javaCompiler...args
diff --git a/plugins/org.eclipse.wst.server.http.core/.project b/plugins/org.eclipse.wst.server.http.core/.project
deleted file mode 100644
index c94c165..0000000
--- a/plugins/org.eclipse.wst.server.http.core/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>org.eclipse.wst.server.http.core</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.jdt.core.javanature</nature>
-		<nature>org.eclipse.pde.PluginNature</nature>
-	</natures>
-</projectDescription>
diff --git a/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.core.resources.prefs b/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index c8be432..0000000
--- a/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,3 +0,0 @@
-#Fri Nov 10 17:11:35 HST 2006
-eclipse.preferences.version=1
-encoding/<project>=ISO-8859-1
diff --git a/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 2920850..0000000
--- a/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,77 +0,0 @@
-#Thu Sep 13 15:25:06 EDT 2007
-eclipse.preferences.version=1
-instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
-org.eclipse.jdt.core.builder.cleanOutputFolder=clean
-org.eclipse.jdt.core.builder.duplicateResourceTask=error
-org.eclipse.jdt.core.builder.invalidClasspath=ignore
-org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
-org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch,*.testsuite,*.deploy,*.location,*.execution,*.datapool,*.artifact,*.html,*.svg
-org.eclipse.jdt.core.circularClasspath=error
-org.eclipse.jdt.core.classpath.exclusionPatterns=disabled
-org.eclipse.jdt.core.classpath.multipleOutputLocations=disabled
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.5
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.maxProblemPerUnit=1000
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=error
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=error
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=error
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.nullReference=warning
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedImport=error
-org.eclipse.jdt.core.compiler.problem.unusedLabel=error
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.5
-org.eclipse.jdt.core.incompatibleJDKLevel=warning
-org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.jdt.ui.prefs b/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.jdt.ui.prefs
deleted file mode 100644
index a7cc1d0..0000000
--- a/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,3 +0,0 @@
-#Fri Feb 23 21:11:52 EST 2007
-eclipse.preferences.version=1
-org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?>\n<templates/>
diff --git a/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.pde.prefs b/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.pde.prefs
deleted file mode 100644
index 08a60e5..0000000
--- a/plugins/org.eclipse.wst.server.http.core/.settings/org.eclipse.pde.prefs
+++ /dev/null
@@ -1,14 +0,0 @@
-#Sat Apr 22 18:36:14 EDT 2006
-compilers.incompatible-environment=0
-compilers.p.build=0
-compilers.p.deprecated=1
-compilers.p.no-required-att=0
-compilers.p.not-externalized-att=2
-compilers.p.unknown-attribute=0
-compilers.p.unknown-class=0
-compilers.p.unknown-element=0
-compilers.p.unknown-resource=0
-compilers.p.unresolved-ex-points=0
-compilers.p.unresolved-import=0
-compilers.use-project=true
-eclipse.preferences.version=1
diff --git a/plugins/org.eclipse.wst.server.http.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.server.http.core/META-INF/MANIFEST.MF
deleted file mode 100644
index c5c0356..0000000
--- a/plugins/org.eclipse.wst.server.http.core/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,16 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: %pluginName
-Bundle-SymbolicName: org.eclipse.wst.server.http.core;singleton:=true
-Bundle-Version: 1.0.100.qualifier
-Bundle-Activator: org.eclipse.wst.server.http.core.internal.HttpCorePlugin
-Bundle-Vendor: %providerName
-Bundle-Localization: plugin
-Export-Package: org.eclipse.wst.server.http.core.internal;x-friends:="org.eclipse.wst.server.http.ui",
- org.eclipse.wst.server.http.core.internal.command;x-friends:="org.eclipse.wst.server.http.ui"
-Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
- org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)",
- org.eclipse.core.commands;bundle-version="[3.2.0,4.0.0)",
- org.eclipse.wst.server.core;bundle-version="[1.0.204,2.0.0)"
-Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.wst.server.http.core/about.html b/plugins/org.eclipse.wst.server.http.core/about.html
deleted file mode 100644
index 2199df3..0000000
--- a/plugins/org.eclipse.wst.server.http.core/about.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
-<HTML>
-
-<head>
-<title>About</title>
-<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
-</head>
-
-<BODY lang="EN-US">
-
-<H3>About This Content</H3>
-
-<P>June, 2008</P>
-
-<H3>License</H3>
-
-<P>The Eclipse Foundation makes available all content in this plug-in 
-("Content"). Unless otherwise indicated below, the Content is provided to you 
-under the terms and conditions of the Eclipse Public License Version 1.0 
-("EPL"). A copy of the EPL is available at
-<A href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</A>. 
-For purposes of the EPL, "Program" will mean the Content.</P>
-
-<P>If you did not receive this Content directly from the Eclipse Foundation, the 
-Content is being redistributed by another party ("Redistributor") and different 
-terms and conditions may apply to your use of any object code in the Content. 
-Check the RedistributorÂ’s license that was provided with the Content. If no such 
-license exists, contact the Redistributor. Unless otherwise indicated below, the 
-terms and conditions of the EPL still apply to any source code in the Content 
-and such source code may be obtained at
-<A href="http://www.eclipse.org/">http://www.eclipse.org/</A>.</P>
-
-</BODY>
-</HTML>
diff --git a/plugins/org.eclipse.wst.server.http.core/build.properties b/plugins/org.eclipse.wst.server.http.core/build.properties
deleted file mode 100644
index af949f3..0000000
--- a/plugins/org.eclipse.wst.server.http.core/build.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-###############################################################################
-# Copyright (c) 2007 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
-###############################################################################
-bin.includes = META-INF/,\
-               plugin.properties,\
-               .,\
-               plugin.xml,\
-               about.html
-bin.excludes = bin/**,\
-               @dot/**,\
-               temp.folder/**
-source.. = src/
diff --git a/plugins/org.eclipse.wst.server.http.core/plugin.properties b/plugins/org.eclipse.wst.server.http.core/plugin.properties
deleted file mode 100644
index 9ac1c1b..0000000
--- a/plugins/org.eclipse.wst.server.http.core/plugin.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-###############################################################################
-# Copyright (c) 2007, 2008 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
-###############################################################################
-pluginName=HTTP Server Support
-providerName=Eclipse.org
-
-runtimeTypeHttpLabel=HTTP Server
-runtimeTypeHttpDescription=Publishes and runs projects on an HTTP server.
-
-httpServerType=HTTP Server
-httpServerDescription=Publishes and runs projects on an HTTP server.
diff --git a/plugins/org.eclipse.wst.server.http.core/plugin.xml b/plugins/org.eclipse.wst.server.http.core/plugin.xml
deleted file mode 100644
index c6bcbfc..0000000
--- a/plugins/org.eclipse.wst.server.http.core/plugin.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
-   <extension point="org.eclipse.wst.server.core.runtimeTypes">
-	    <runtimeType
-	       id="org.eclipse.wst.server.http.runtime"
-	       name="%runtimeTypeHttpLabel"
-	       description="%runtimeTypeHttpDescription"
-	       facetRuntimeComponent="org.eclipse.wst.server.http.runtime"
-	       facetRuntimeVersion="1.0"
-	       class="org.eclipse.wst.server.http.core.internal.HttpRuntime">
-	       <moduleType
-	         types="PHP"
-	         versions="1.0"/>
-	       <moduleType
-	       	 types="wst.web"
-	       	 versions="1.0"/>
-	    </runtimeType>
-  	</extension>
-
- 	<extension point="org.eclipse.wst.server.core.serverTypes">
-     <serverType
-       id="org.eclipse.wst.server.http.server"
-       name="%httpServerType"
-       description="%httpServerDescription"
-       supportsRemoteHosts="true"
-       runtime="true"
-       initialState="started"
-       hasConfiguration="false"
-       runtimeTypeId="org.eclipse.wst.server.http.runtime"
-       class="org.eclipse.wst.server.http.core.internal.HttpServer"
-       behaviourClass="org.eclipse.wst.server.http.core.internal.HttpServerBehaviour"/>
-  	</extension>
-
-  <extension point="org.eclipse.wst.server.core.runtimeLocators">
-    <runtimeLocator
-       id="org.eclipse.wst.server.http.runtime.locator"
-       typeIds="org.eclipse.wst.server.http.runtime"
-       class="org.eclipse.wst.server.http.core.internal.HttpRuntimeLocator"/>
-  </extension>
-
-  <extension point="org.eclipse.wst.common.project.facet.core.runtimes">
-    <runtime-component-type
-       id="org.eclipse.wst.server.http.runtime"/>
-    <runtime-component-version
-       type="org.eclipse.wst.server.http.runtime"
-       version="1.0"/>
-    <supported>
-      <runtime-component
-         id="org.eclipse.wst.server.http.runtime"
-         version="1.0"/>
-      <facet
-         id="wst.web"
-         version="[1.0"/>
-    </supported>
-  </extension>
-
-  <extension point="org.eclipse.wst.common.project.facet.core.defaultFacets">
-    <default-facets>
-      <runtime-component id="org.eclipse.wst.server.http.runtime"/>
-      <facet id="wst.jsdt.web" version="1.0"/>
-    </default-facets>
-  </extension>
-
-   <extension point="org.eclipse.wst.server.core.launchableAdapters">
-      <launchableAdapter
-        id="org.eclipse.wst.server.http.web"
-        class="org.eclipse.wst.server.http.core.internal.HttpLaunchableAdapterDelegate"
-        typeIds="org.eclipse.wst.server.http.server"/>
-   </extension>
-</plugin>
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpCorePlugin.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpCorePlugin.java
deleted file mode 100644
index 1277685..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpCorePlugin.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal;
-
-import org.eclipse.core.runtime.Plugin;
-import org.osgi.framework.BundleContext;
-/**
- * The HTTP server core plugin.
- */
-public class HttpCorePlugin extends Plugin {
-	public static final String PLUGIN_ID = "org.eclipse.wst.server.http.core";
-
-	private static HttpCorePlugin plugin;
-
-	/**
-	 * The constructor
-	 */
-	public HttpCorePlugin() {
-		plugin = this;
-	}
-
-	/**
-	 * Returns the singleton instance of this plugin.
-	 * 
-	 * @return an instance
-	 */
-	public static HttpCorePlugin getInstance() {
-		return plugin;
-	}
-
-	/**
-	 * Return the install location preference.
-	 * 
-	 * @param id a runtime type id
-	 * @return the install location
-	 */
-	public static String getPreference(String id) {
-		return getInstance().getPluginPreferences().getString(id);
-	}
-
-	/**
-	 * Set the install location preference.
-	 * 
-	 * @param id the runtimt type id
-	 * @param value the location
-	 */
-	public static void setPreference(String id, String value) {
-		getInstance().getPluginPreferences().setValue(id, value);
-		getInstance().savePluginPreferences();
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
-	 */
-	public void stop(BundleContext context) throws Exception {
-		plugin = null;
-		super.stop(context);
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpLaunchableAdapterDelegate.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpLaunchableAdapterDelegate.java
deleted file mode 100644
index 6ab83f8..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpLaunchableAdapterDelegate.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal;
-
-import java.net.URL;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.wst.server.core.IModuleArtifact;
-import org.eclipse.wst.server.core.IServer;
-import org.eclipse.wst.server.core.model.LaunchableAdapterDelegate;
-import org.eclipse.wst.server.core.util.HttpLaunchable;
-import org.eclipse.wst.server.core.util.WebResource;
-
-public class HttpLaunchableAdapterDelegate extends LaunchableAdapterDelegate {
-	/*
-	 * @see LaunchableAdapterDelegate#getLaunchable(IServer, IModuleArtifact)
-	 */
-	public Object getLaunchable(IServer server, IModuleArtifact moduleArtifact) throws CoreException {
-		if (server == null || moduleArtifact == null)
-			return null;
-		
-		HttpServer server2 = (HttpServer) server.loadAdapter(HttpServer.class, null);
-		if (server2 == null)
-			return null;
-		
-		try {
-			URL url = server2.getModuleRootURL(moduleArtifact.getModule());
-			
-			if (moduleArtifact instanceof WebResource) {
-				WebResource resource = (WebResource) moduleArtifact;
-				String path = resource.getPath().toString();
-				
-				if (path.startsWith("/"))
-					path = path.substring(1);
-				url = new URL(url.toExternalForm() + "/" + path);
-			}
-			return new HttpLaunchable(url);
-		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error in launchable adapter", e);
-		}
-		
-		return null;
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpRuntime.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpRuntime.java
deleted file mode 100644
index 542bb1f..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpRuntime.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.wst.server.core.model.RuntimeDelegate;
-/**
- * 
- */
-public class HttpRuntime extends RuntimeDelegate {
-	public static final String ID = "org.eclipse.wst.server.http.runtime";
-
-	public HttpRuntime() {
-		// do nothing
-	}
-
-	public IStatus validate() {
-		return Status.OK_STATUS;
-	}
-
-	/*
-	 * @see RuntimeDelegate#setDefaults(IProgressMonitor)
-	 */
-	public void setDefaults(IProgressMonitor monitor) {
-		getRuntimeWorkingCopy().setLocation(new Path(""));
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpRuntimeLocator.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpRuntimeLocator.java
deleted file mode 100644
index c325456..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpRuntimeLocator.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 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.wst.server.http.core.internal;
-
-import java.io.File;
-import java.io.FileFilter;
-
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.wst.server.core.IRuntimeType;
-import org.eclipse.wst.server.core.IRuntimeWorkingCopy;
-import org.eclipse.wst.server.core.ServerCore;
-import org.eclipse.wst.server.core.model.RuntimeLocatorDelegate;
-/**
- * 
- */
-public class HttpRuntimeLocator extends RuntimeLocatorDelegate {
-	protected static final String[] runtimeTypes = new String[] { HttpRuntime.ID };
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.wst.server.core.model.IRuntimeFactoryDelegate#getKnownRuntimes()
-	 */
-	public void searchForRuntimes(IPath path, IRuntimeSearchListener listener,
-			IProgressMonitor monitor) {
-		searchForRuntimes2(path, listener, monitor);
-	}
-
-	protected static void searchForRuntimes2(IPath path, IRuntimeSearchListener listener,
-			IProgressMonitor monitor) {
-		File[] files = null;
-		if (path != null) {
-			File f = path.toFile();
-			if (f.exists())
-				files = f.listFiles();
-			else
-				return;
-		} else
-			files = File.listRoots();
-
-		if (files != null) {
-			int size = files.length;
-			int work = 100 / size;
-			int workLeft = 100 - (work * size);
-			for (File file : files) {
-				if (monitor.isCanceled())
-					return;
-				if (file != null && file.isDirectory())
-					searchDir(listener, file, 4, monitor);
-				monitor.worked(work);
-			}
-			monitor.worked(workLeft);
-		} else
-			monitor.worked(100);
-	}
-
-	protected static void searchDir(IRuntimeSearchListener listener, File dir, int depth, IProgressMonitor monitor) {
-		if ("htdocs".equals(dir.getName())) {
-			IRuntimeWorkingCopy runtime = getRuntimeFromDir(dir.getParentFile(), monitor);
-			if (runtime != null) {
-				listener.runtimeFound(runtime);
-				return;
-			}
-		}
-
-		if (depth == 0)
-			return;
-
-		File[] files = dir.listFiles(new FileFilter() {
-			public boolean accept(File file) {
-				return file.isDirectory();
-			}
-		});
-		if (files != null) {
-			for (File file : files) {
-				if (monitor.isCanceled())
-					return;
-				searchDir(listener, file, depth - 1, monitor);
-			}
-		}
-	}
-
-	protected static IRuntimeWorkingCopy getRuntimeFromDir(File dir, IProgressMonitor monitor) {
-		for (String rt : runtimeTypes) {
-			try {
-				IRuntimeType runtimeType = ServerCore.findRuntimeType(rt);
-				String absolutePath = dir.getAbsolutePath();
-				String id = absolutePath.replace(File.separatorChar, '_').replace(':', '-');
-				IRuntimeWorkingCopy runtime = runtimeType.createRuntime(id, monitor);
-				runtime.setName(dir.getName());
-				runtime.setLocation(new Path(absolutePath).append("htdocs"));
-				IStatus status = runtime.validate(monitor);
-				if (status == null || status.getSeverity() != IStatus.ERROR)
-					return runtime;
-				
-				Trace.trace(Trace.FINER, "False runtime found at " + dir.getAbsolutePath()
-						+ ": " + status.getMessage());
-			} catch (Exception e) {
-				Trace.trace(Trace.SEVERE, "Could not find runtime", e);
-			}
-		}
-		return null;
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpServer.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpServer.java
deleted file mode 100644
index 3a51982..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpServer.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 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.wst.server.http.core.internal;
-
-import java.net.URL;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.wst.server.core.IModule;
-import org.eclipse.wst.server.core.IRuntime;
-import org.eclipse.wst.server.core.IRuntimeType;
-import org.eclipse.wst.server.core.IRuntimeWorkingCopy;
-import org.eclipse.wst.server.core.IServer;
-import org.eclipse.wst.server.core.IServerType;
-import org.eclipse.wst.server.core.IServerWorkingCopy;
-import org.eclipse.wst.server.core.ServerCore;
-import org.eclipse.wst.server.core.ServerPort;
-import org.eclipse.wst.server.core.model.IURLProvider;
-import org.eclipse.wst.server.core.model.ServerDelegate;
-import org.eclipse.wst.server.core.util.IStaticWeb;
-/**
- * Generic HTTP server.
- */
-public class HttpServer extends ServerDelegate implements IURLProvider {
-	public static final String PROPERTY_URL_PREFIX = "urlPrefix";
-	public static final String PROPERTY_PORT = "port";
-	public static final String PROPERTY_IS_PUBLISHING = "isPublishing";
-
-	public static final String ID = "org.eclipse.wst.server.http.server";
-
-	/**
-	 * HttpServer.
-	 */
-	public HttpServer() {
-		super();
-	}
-
-	protected void initialize() {
-		// do nothing
-	}
-
-	/*
-	 * @see RuntimeDelegate#setDefaults(IProgressMonitor)
-	 */
-	public void setDefaults(IProgressMonitor monitor) {
-		setPort(80);
-		setURLPrefix("");
-		setPublishing(true);
-	}
-
-	public HttpRuntime getHttpRuntime() {
-		if (getServer().getRuntime() == null)
-			return null;
-
-		return (HttpRuntime) getServer().getRuntime().loadAdapter(HttpRuntime.class, null);
-	}
-
-	/*public void importRuntimeConfiguration(IRuntime arg0, IProgressMonitor arg1) throws CoreException {
-		if (getHttpRuntime() != null) {
-			if (!getHttpRuntime().publishToDirectory()) {
-				setAttribute("auto-publish-setting", 1);
-			} else {
-				setAttribute("auto-publish-setting", 2);
-				setAttribute("auto-publish-time", 1);
-			}
-			//setPublishDirectory(getHttpRuntime().getPublishLocation());
-		}
-	}*/
-
-	public boolean dontPublish() {
-		return getAttribute("auto-publish-setting", "2").equals("1");
-	}
-
-	// public void setDocumentRoot(String docRoot) {
-	// setAttribute(HttpServer.DOCUMENT_ROOT, docRoot);
-	// }
-
-	// public String getDocumentRoot() {
-	// return getAttribute(HttpServer.DOCUMENT_ROOT, "");
-	// }
-
-	// public boolean canPublish() {
-	// return getAttribute(HttpServer.PUBLISH, true);
-	// }
-
-	// public void setPublish(boolean publish) {
-	// setAttribute(HttpServer.PUBLISH, publish);
-	// }
-
-	/**
-	 * Processes the host to return IPv6 addresses in square brackets, e.g.
-	 * "[4ffe:ff2f:101:21:230:6eff:fe04:d9fe]". If the host is just a host name
-	 * or IPv4 address, then it is returned as is.
-	 * 
-	 * @param host the host, an IP address or host name
-	 */
-	protected static String getURLHost(String host) {
-		// use ":" to determine if this is an IPv6 address 
-		return (host != null && host.indexOf(":") >= 0) ? "[" + host + "]" : host;
-	}
-
-	/**
-	 * Return the root URL of this module.
-	 * 
-	 * @param module a module
-	 * @return the root URL
-	 */
-	public URL getModuleRootURL(IModule module) {
-		try {
-			String base = "http://" + getURLHost(getServer().getHost());
-			
-			if (base.equals(""))
-				base = "http://" + getURLHost(getServer().getHost());
-			
-			int port = getPort();
-			URL url = null;
-			if (port == 80)
-				url = new URL(base + "/");
-			else
-				url = new URL(base + ":" + port + "/");
-			
-			String prefix = getURLPrefix();
-			if (prefix != null && prefix.length() > 0)
-				url = new URL(url, prefix + "/");
-			
-			IStaticWeb staticWeb = (IStaticWeb) module.loadAdapter(IStaticWeb.class, null);
-			return new URL(url, staticWeb.getContextRoot());
-		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Could not get root URL", e);
-			return null;
-		}
-	}
-
-	/*
-	 * Returns the child module(s) of this module.
-	 */
-	public IModule[] getChildModules(IModule[] module) {
-		return new IModule[0];
-	}
-
-	/*
-	 * Returns the root module(s) of this module.
-	 */
-	public IModule[] getRootModules(IModule module) throws CoreException {
-		return new IModule[] { module };
-	}
-
-	/**
-	 * Returns true if the given project is supported by this server, and false
-	 * otherwise.
-	 * 
-	 * @param add modules
-	 * @param remove modules
-	 * @return the status
-	 */
-	public IStatus canModifyModules(IModule[] add, IModule[] remove) {
-		return new Status(IStatus.OK, HttpCorePlugin.PLUGIN_ID, 0, Messages.canModifyModules, null);
-	}
-
-	public ServerPort[] getServerPorts() {
-		int port = getPort();
-		ServerPort[] ports = { new ServerPort("http", Messages.httpPort, port, "http") };
-		return ports;
-	}
-
-	public int getPort() {
-		return getAttribute(HttpServer.PROPERTY_PORT, 80);
-	}
-
-	public void setPort(int port) {
-		setAttribute(HttpServer.PROPERTY_PORT, port);
-	}
-
-	public void setURLPrefix(String prefix) {
-		setAttribute(HttpServer.PROPERTY_URL_PREFIX, prefix);
-	}
-
-	public String getURLPrefix() {
-		return getAttribute(HttpServer.PROPERTY_URL_PREFIX, "");
-	}
-
-	public boolean isPublishing() {
-		return getAttribute(PROPERTY_IS_PUBLISHING, false);
-	}
-
-	public void setPublishing(boolean shouldPublish) {
-		setAttribute(PROPERTY_IS_PUBLISHING, shouldPublish);
-	}
-
-	public static IServer createHttpServer(String host, String serverName, IProgressMonitor monitor) {
-		try {
-			IRuntimeType runtimeType = ServerCore.findRuntimeType(HttpRuntime.ID);
-			IRuntimeWorkingCopy runtimeCopy = runtimeType.createRuntime(HttpRuntime.ID, monitor);
-			IRuntime runtime = runtimeCopy.save(true, monitor);
-			
-			IServerType serverType = ServerCore.findServerType(ID);
-			IServerWorkingCopy workingCopy = serverType.createServer(ID, null, runtime, monitor);
-			workingCopy.setName(serverName);
-			workingCopy.setHost(host);
-			
-			return workingCopy.save(true, monitor);
-		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error creating server", e);
-		}
-		
-		return null;
-	}
-
-	public static IServer findHttpServer(String id) {
-		IServer[] servers = ServerCore.getServers();
-		for (IServer server : servers) {
-			if (server.getId().equals(id))
-				return server;
-		}
-		return null;
-	}
-
-	/*public void setPublishDirectory(String pubDir) {
-		setAttribute(PROPERTY_PUB_DIR, pubDir);
-	}
-
-	public String getPublishDirectory() {
-		if (getHttpRuntime() != null)
-			return getAttribute(PROPERTY_PUB_DIR, getHttpRuntime().getPublishLocation());
-		return getAttribute(PROPERTY_PUB_DIR, "");
-	}*/
-
-	/*
-	 * public static void updateBaseURL(String id, String baseURL) {
-	 * updateBaseURL(checkForHttpServer(id), baseURL); }
-	 */
-
-	/*
-	 * public static void updateBaseURL(IServer server, String baseURL) { if
-	 * (server == null) return;
-	 * 
-	 * IServerWorkingCopy workingCopy = server.createWorkingCopy();
-	 * 
-	 * HttpServer as = (HttpServer) workingCopy.getAdapter(HttpServer.class); if
-	 * (as == null) as = (HttpServer) workingCopy.loadAdapter(HttpServer.class,
-	 * null);
-	 * 
-	 * String currentURL = as.getBaseURL();
-	 * 
-	 * if (currentURL.equals(baseURL)) return; as.setBaseURL(baseURL); try {
-	 * as.saveConfiguration(null); workingCopy.save(true, null); } catch
-	 * (CoreException e) { e.printStackTrace(); } }
-	 */
-
-	public void modifyModules(IModule[] add, IModule[] remove, IProgressMonitor monitor) throws CoreException {
-		// do nothing
-	}
-
-	/**
-	 * Return a string representation of this object.
-	 * 
-	 * @return java.lang.String
-	 */
-	public String toString() {
-		return "HttpServer";
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpServerBehaviour.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpServerBehaviour.java
deleted file mode 100644
index d8f7ce0..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/HttpServerBehaviour.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal;
-
-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.wst.server.core.IModule;
-import org.eclipse.wst.server.core.IServer;
-import org.eclipse.wst.server.core.model.IModuleResource;
-import org.eclipse.wst.server.core.model.ServerBehaviourDelegate;
-import org.eclipse.wst.server.core.util.IStaticWeb;
-import org.eclipse.wst.server.core.util.PublishUtil;
-/**
- * Generic Http server.
- */
-public class HttpServerBehaviour extends ServerBehaviourDelegate {
-	// the thread used to ping the server to check for startup
-	protected transient PingThread ping = null;
-
-	/**
-	 * HttpServer.
-	 */
-	public HttpServerBehaviour() {
-		super();
-	}
-
-	public void initialize(IProgressMonitor monitor) {
-		// do nothing
-	}
-
-	public HttpRuntime getHttpRuntime() {
-		if (getServer().getRuntime() == null)
-			return null;
-
-		return (HttpRuntime) getServer().getRuntime().loadAdapter(HttpRuntime.class, null);
-	}
-
-	public HttpServer getHttpServer() {
-		return (HttpServer) getServer().getAdapter(HttpServer.class);
-	}
-
-	protected void setServerStarted() {
-		setServerState(IServer.STATE_STARTED);
-	}
-
-	protected void publishServer(int kind, IProgressMonitor monitor) throws CoreException {
-		monitor = ProgressUtil.getMonitorFor(monitor);
-		monitor.done();
-
-		setServerPublishState(IServer.PUBLISH_STATE_NONE);
-	}
-
-	/*
-	 * Publishes the given module to the server.
-	 */
-	protected void publishModule(int kind, int deltaKind, IModule[] moduleTree, IProgressMonitor monitor) throws CoreException {
-		if (!getHttpServer().isPublishing())
-			return;
-		
-		String contextRoot = null;
-		IModule module = moduleTree[moduleTree.length - 1]; 
-		IStaticWeb sw = (IStaticWeb) module.loadAdapter(IStaticWeb.class, monitor);
-		if (sw != null)
-			contextRoot = sw.getContextRoot();
-		else
-			contextRoot = module.getName();
-		
-		IPath to = getServer().getRuntime().getLocation();
-		if (contextRoot != null && !contextRoot.equals(""))
-			to = to.append(contextRoot);
-		
-		IModuleResource[] res = getResources(moduleTree);
-		IStatus[] status = PublishUtil.publishSmart(res, to, monitor);
-		throwException(status);
-		
-		setModulePublishState(moduleTree, IServer.PUBLISH_STATE_NONE);
-	}
-
-	/**
-	 * Utility method to throw a CoreException based on the contents of a list of
-	 * error and warning status.
-	 * 
-	 * @param status a List containing error and warning IStatus
-	 * @throws CoreException
-	 */
-	private static void throwException(IStatus[] status) throws CoreException {
-		if (status == null || status.length == 0)
-			return;
-		
-		if (status.length == 1)
-			throw new CoreException(status[0]);
-		
-		String message = Messages.errorPublish;
-		MultiStatus status2 = new MultiStatus(HttpCorePlugin.PLUGIN_ID, 0, status, message, null);
-		throw new CoreException(status2);
-	}
-
-	public void restart(String launchMode) throws CoreException {
-		setServerState(IServer.STATE_STOPPED);
-		setServerState(IServer.STATE_STARTED);
-	}
-
-	/**
-	 * Cleanly shuts down and terminates the server.
-	 * 
-	 * @param force <code>true</code> to kill the server
-	 */
-	public void stop(boolean force) {
-		setServerState(IServer.STATE_STOPPED);
-	}
-
-	/**
-	 * Return a string representation of this object.
-	 * 
-	 * @return java.lang.String
-	 */
-	public String toString() {
-		return "HttpServer";
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/Messages.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/Messages.java
deleted file mode 100644
index 8dae1de..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/Messages.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal;
-
-import org.eclipse.osgi.util.NLS;
-/**
- * Translated messages.
- */
-public class Messages extends NLS {
-	public static String errorPublish;
-	public static String canModifyModules;
-	public static String httpPort;
-	public static String actionModifyPort;
-	public static String actionModifyPrefixURL;
-	public static String actionModifyPublishing;
-
-	public static String errorPortInUse;
-
-	static {
-		NLS.initializeMessages(HttpCorePlugin.PLUGIN_ID + ".internal.Messages", Messages.class);
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/Messages.properties b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/Messages.properties
deleted file mode 100644
index 520bbe8..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/Messages.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-###############################################################################
-# Copyright (c) 2007 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
-###############################################################################
-
-actionModifyPort=set port number
-actionModifyPrefixURL=set URL prefix
-actionModifyPublishing=set publishing enablement
-errorPublish=Error during publish
-
-httpPort=HTTP Port
-canModifyModules=Web modules can be modified.
-
-errorPortInUse=Port {0} required by {1} is already in use. The server may already be running in another process, or a system process may be using the port. \
-  To start this server you will need to stop the other process or change the port number(s).
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/PingThread.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/PingThread.java
deleted file mode 100644
index 39360c3..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/PingThread.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal;
-
-import java.io.FileNotFoundException;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.net.URLConnection;
-
-import org.eclipse.wst.server.core.IServer;
-
-/**
- * Thread used to ping server to test when it is started.
- */
-public class PingThread {
-	// delay before pinging starts
-	private static final int PING_DELAY = 2000;
-
-	// delay between pings
-	private static final int PING_INTERVAL = 250;
-
-	// maximum number of pings before giving up
-	private int maxPings = 56; // total: 16 seconds + connection time
-
-	private boolean stop = false;
-
-	private String url;
-
-	private IServer server;
-
-	private HttpServerBehaviour behaviour;
-
-	/**
-	 * Create a new PingThread.
-	 * 
-	 * @param server
-	 * @param url
-	 * @param maxPings
-	 * @param behaviour
-	 */
-	public PingThread(IServer server, String url, int maxPings,
-			HttpServerBehaviour behaviour) {
-		super();
-		this.server = server;
-		this.url = url;
-		this.maxPings = maxPings;
-		this.behaviour = behaviour;
-		Thread t = new Thread() {
-			public void run() {
-				ping();
-			}
-		};
-		t.setDaemon(true);
-		t.start();
-	}
-
-	/**
-	 * Ping the server until it is started. Then set the server state to
-	 * STATE_STARTED.
-	 */
-	protected void ping() {
-		int count = 0;
-		try {
-			Thread.sleep(PING_DELAY);
-		} catch (Exception e) {
-			// ignore
-		}
-		while (!stop) {
-			try {
-				if (count == maxPings) {
-					try {
-						server.stop(false);
-					} catch (Exception e) {
-						Trace.trace(Trace.FINEST, "Ping: could not stop server");
-					}
-					stop = true;
-					break;
-				}
-				count++;
-
-				Trace.trace(Trace.FINEST, "Ping: pinging");
-				URL pingUrl = new URL(url);
-				URLConnection conn = pingUrl.openConnection();
-				((HttpURLConnection) conn).getResponseCode();
-
-				// ping worked - server is up
-				if (!stop) {
-					Trace.trace(Trace.FINEST, "Ping: success");
-					Thread.sleep(200);
-					behaviour.setServerStarted();
-				}
-				stop = true;
-			} catch (FileNotFoundException fe) {
-				try {
-					Thread.sleep(200);
-				} catch (Exception e) {
-					// ignore
-				}
-				behaviour.setServerStarted();
-				stop = true;
-			} catch (Exception e) {
-				Trace.trace(Trace.FINEST, "Ping: failed");
-				// pinging failed
-				if (!stop) {
-					try {
-						Thread.sleep(PING_INTERVAL);
-					} catch (InterruptedException e2) {
-						// ignore
-					}
-				}
-			}
-		}
-	}
-
-	/**
-	 * Tell the pinging to stop.
-	 */
-	public void stop() {
-		Trace.trace(Trace.FINEST, "Ping: stopping");
-		stop = true;
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/ProgressUtil.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/ProgressUtil.java
deleted file mode 100644
index 788a656..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/ProgressUtil.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.SubProgressMonitor;
-/**
- * Progress Monitor utility.
- */
-public class ProgressUtil {
-	/**
-	 * ProgressUtil constructor comment.
-	 */
-	private ProgressUtil() {
-		super();
-	}
-
-	/**
-	 * Return a valid progress monitor.
-	 * 
-	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
-	 * @return org.eclipse.core.runtime.IProgressMonitor
-	 */
-	public static IProgressMonitor getMonitorFor(IProgressMonitor monitor) {
-		if (monitor == null)
-			return new NullProgressMonitor();
-		return monitor;
-	}
-
-	/**
-	 * Return a sub-progress monitor with the given amount on the current
-	 * progress monitor.
-	 * 
-	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
-	 * @param ticks int
-	 * @return org.eclipse.core.runtime.IProgressMonitor
-	 */
-	public static IProgressMonitor getSubMonitorFor(IProgressMonitor monitor, int ticks) {
-		if (monitor == null)
-			return new NullProgressMonitor();
-		if (monitor instanceof NullProgressMonitor)
-			return monitor;
-		return new SubProgressMonitor(monitor, ticks);
-	}
-
-	/**
-	 * Return a sub-progress monitor with the given amount on the current
-	 * progress monitor.
-	 * 
-	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
-	 * @param ticks a number of ticks
-	 * @param style a style
-	 * @return org.eclipse.core.runtime.IProgressMonitor
-	 */
-	public static IProgressMonitor getSubMonitorFor(IProgressMonitor monitor, int ticks,
-			int style) {
-		if (monitor == null)
-			return new NullProgressMonitor();
-		if (monitor instanceof NullProgressMonitor)
-			return monitor;
-		return new SubProgressMonitor(monitor, ticks, style);
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/Trace.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/Trace.java
deleted file mode 100644
index 5977cd0..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/Trace.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-/**
- * Helper class to route trace output.
- */
-public class Trace {
-	public static byte CONFIG = 0;
-	public static byte WARNING = 1;
-	public static byte SEVERE = 2;
-	public static byte FINEST = 3;
-	public static byte FINER = 4;
-	
-	private static final String[] levelNames = new String[] { "CONFIG   ", "WARNING  ",
-		"SEVERE   ", "FINER    ", "FINEST   " };
-
-	private static final SimpleDateFormat sdf = new SimpleDateFormat(
-			"dd/MM/yy HH:mm.ss.SSS");
-
-	/**
-	 * Trace constructor comment.
-	 */
-	private Trace() {
-		super();
-	}
-
-	/**
-	 * Trace the given text.
-	 * 
-	 * @param level the trace level
-	 * @param s a message
-	 */
-	public static void trace(byte level, String s) {
-		Trace.trace(level, s, null);
-	}
-
-	/**
-	 * Trace the given message and exception.
-	 * 
-	 * @param level the trace level
-	 * @param s a message
-	 * @param t a throwable
-	 */
-	public static void trace(byte level, String s, Throwable t) {
-		if (s == null)
-			return;
-		
-		if (level == SEVERE)
-			HttpCorePlugin.getInstance().getLog().log(new Status(IStatus.ERROR, HttpCorePlugin.PLUGIN_ID, s, t));
-		
-		if (!HttpCorePlugin.getInstance().isDebugging())
-			return;
-
-		StringBuffer sb = new StringBuffer(HttpCorePlugin.PLUGIN_ID);
-		sb.append(" ");
-		sb.append(levelNames[level]);
-		sb.append(" ");
-		sb.append(sdf.format(new Date()));
-		sb.append(" ");
-		sb.append(s);
-		// Platform.getDebugOption(ServerCore.PLUGIN_ID + "/" + "resources");
-
-		System.out.println(sb.toString());
-		if (t != null)
-			t.printStackTrace();
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ModifyPortCommand.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ModifyPortCommand.java
deleted file mode 100644
index 396021f..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ModifyPortCommand.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal.command;
-
-import org.eclipse.wst.server.core.ServerPort;
-import org.eclipse.wst.server.http.core.internal.HttpServer;
-import org.eclipse.wst.server.http.core.internal.Messages;
-/**
- * Command to change the port.
- */
-public class ModifyPortCommand extends ServerCommand {
-	protected int port;
-	protected int oldPort;
-
-	/**
-	 * ModifyPortCommand constructor.
-	 * 
-	 * @param server a server
-	 * @param port new port number
-	 */
-	public ModifyPortCommand(HttpServer server, int port) {
-		super(server, Messages.actionModifyPort);
-		this.port = port;
-	}
-
-	/**
-	 * Execute the command.
-	 */
-	public void execute() {
-		// find old port number
-		ServerPort temp = server.getServerPorts()[0];
-		oldPort = temp.getPort();
-		
-		// make the change
-		server.setPort(port);
-	}
-
-	/**
-	 * Undo the command.
-	 */
-	public void undo() {
-		server.setPort(oldPort);
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ModifyPublishingCommand.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ModifyPublishingCommand.java
deleted file mode 100644
index adb278f..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ModifyPublishingCommand.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal.command;
-
-import org.eclipse.wst.server.http.core.internal.HttpServer;
-import org.eclipse.wst.server.http.core.internal.Messages;
-/**
- * Command to change the publishing state.
- */
-public class ModifyPublishingCommand extends ServerCommand {
-	protected boolean shouldPublish;
-	protected boolean oldShouldPublish;
-
-	/**
-	 * ModifyPublishingCommand constructor.
-	 * 
-	 * @param server a server
-	 * @param shouldPublish 
-	 */
-	public ModifyPublishingCommand(HttpServer server, boolean shouldPublish) {
-		super(server, Messages.actionModifyPublishing);
-		this.shouldPublish = shouldPublish;
-	}
-
-	/**
-	 * Execute the command.
-	 */
-	public void execute() {
-		oldShouldPublish = server.isPublishing();
-		
-		// make the change
-		server.setPublishing(shouldPublish);
-	}
-
-	/**
-	 * Undo the command.
-	 */
-	public void undo() {
-		server.setPublishing(oldShouldPublish);
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ModifyURLPrefixCommand.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ModifyURLPrefixCommand.java
deleted file mode 100644
index e30759f..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ModifyURLPrefixCommand.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal.command;
-
-import org.eclipse.wst.server.http.core.internal.HttpServer;
-import org.eclipse.wst.server.http.core.internal.Messages;
-
-public class ModifyURLPrefixCommand extends ServerCommand {
-	protected String prefix;
-	protected String oldPrefix;
-
-	/**
-	 * ModifyURLPrefixCommand constructor.
-	 * 
-	 * @param server a HTTP configuration
-	 * @param prefix a new prefix
-	 */
-	public ModifyURLPrefixCommand(HttpServer server, String prefix) {
-		super(server, Messages.actionModifyPrefixURL);
-		this.prefix = prefix;
-	}
-
-	/**
-	 * Execute the command.
-	 */
-	public void execute() {
-		// find old prefix
-		oldPrefix = server.getURLPrefix();
-
-		// make the change
-		server.setURLPrefix(prefix);
-	}
-
-	/**
-	 * Undo the command.
-	 */
-	public void undo() {
-		server.setURLPrefix(oldPrefix);
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ServerCommand.java b/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ServerCommand.java
deleted file mode 100644
index 0ad3f60..0000000
--- a/plugins/org.eclipse.wst.server.http.core/src/org/eclipse/wst/server/http/core/internal/command/ServerCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 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.wst.server.http.core.internal.command;
-
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.commands.operations.AbstractOperation;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.wst.server.http.core.internal.HttpServer;
-/**
- * Server command.
- */
-public abstract class ServerCommand extends AbstractOperation {
-	protected HttpServer server;
-
-	/**
-	 * ServerCommand constructor comment.
-	 * 
-	 * @param server a server
-	 * @param label a label
-	 */
-	public ServerCommand(HttpServer server, String label) {
-		super(label);
-		this.server = server;
-	}
-
-	public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
-		return execute(monitor, info);
-	}
-
-	public abstract void execute();
-
-	public IStatus execute(IProgressMonitor monitor, IAdaptable info)
-			throws ExecutionException {
-		execute();
-		return null;
-	}
-
-	public abstract void undo();
-
-	public IStatus undo(IProgressMonitor monitor, IAdaptable info)
-			throws ExecutionException {
-		undo();
-		return null;
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.preview.adapter/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.server.preview.adapter/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..487f18a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.preview.adapter/META-INF/MANIFEST.MF
@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.wst.server.preview.adapter;singleton:=true
+Bundle-Version: 1.0.101.qualifier
+Bundle-Activator: org.eclipse.wst.server.preview.adapter.internal.core.PreviewPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.wst.server.core;bundle-version="[1.0.204,2.0.0)",
+ org.eclipse.wst.server.ui;bundle-version="[1.0.103,2.0.0)",
+ org.eclipse.debug.ui;bundle-version="[3.3.0,4.0.0)",
+ org.eclipse.wst.common.project.facet.ui;bundle-version="[1.2.0,2.0.0)"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.wst.server.preview.adapter/src/org/eclipse/wst/server/preview/adapter/internal/core/PreviewServerBehaviour.java b/plugins/org.eclipse.wst.server.preview.adapter/src/org/eclipse/wst/server/preview/adapter/internal/core/PreviewServerBehaviour.java
new file mode 100644
index 0000000..ea0f5ec
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.preview.adapter/src/org/eclipse/wst/server/preview/adapter/internal/core/PreviewServerBehaviour.java
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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.wst.server.preview.adapter.internal.core;
+
+import java.io.IOException;
+
+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.Status;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.server.core.IModule;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ServerPort;
+import org.eclipse.wst.server.core.model.IModuleResource;
+import org.eclipse.wst.server.core.model.IModuleResourceDelta;
+import org.eclipse.wst.server.core.model.ServerBehaviourDelegate;
+import org.eclipse.wst.server.core.util.IStaticWeb;
+import org.eclipse.wst.server.core.util.ProjectModule;
+import org.eclipse.wst.server.core.util.PublishUtil;
+import org.eclipse.wst.server.core.util.SocketUtil;
+/**
+ * Preview server.
+ */
+public class PreviewServerBehaviour extends ServerBehaviourDelegate {
+	// the thread used to ping the server to check for startup
+	protected transient PingThread ping = null;
+	protected transient IDebugEventSetListener processListener;
+
+	/**
+	 * PreviewServer.
+	 */
+	public PreviewServerBehaviour() {
+		super();
+	}
+
+	public void initialize(IProgressMonitor monitor) {
+		// do nothing
+	}
+
+	public PreviewRuntime getPreviewRuntime() {
+		if (getServer().getRuntime() == null)
+			return null;
+
+		return (PreviewRuntime) getServer().getRuntime().loadAdapter(PreviewRuntime.class, null);
+	}
+
+	public PreviewServer getPreviewServer() {
+		return (PreviewServer) getServer().getAdapter(PreviewServer.class);
+	}
+
+	/**
+	 * Returns the runtime base path for relative paths in the server
+	 * configuration.
+	 * 
+	 * @return the base path
+	 */
+	public IPath getRuntimeBaseDirectory() {
+		return getServer().getRuntime().getLocation();
+	}
+
+	/**
+	 * Setup for starting the server.
+	 * 
+	 * @param launch ILaunch
+	 * @param launchMode String
+	 * @param monitor IProgressMonitor
+	 * @throws CoreException if anything goes wrong
+	 */
+	protected void setupLaunch(ILaunch launch, String launchMode, IProgressMonitor monitor) throws CoreException {
+		// check that ports are free
+		ServerPort[] ports = getPreviewServer().getServerPorts();
+		int port = ports[0].getPort();
+		
+		if (SocketUtil.isPortInUse(port, 5))
+			throw new CoreException(new Status(IStatus.ERROR, PreviewPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorPortInUse, new String[] {port + "", getServer().getName()}), null));
+		
+		// generate preview config file
+		XMLMemento memento = XMLMemento.createWriteRoot("server");
+		memento.putInteger("port", port);
+		
+		IModule[] modules = getServer().getModules();
+		for (IModule module : modules) {
+			IMemento mod = memento.createChild("module");
+			mod.putString("name", module.getName());
+			String type = module.getModuleType().getId();
+			if ("wst.web".equals(type)) {
+				IStaticWeb staticWeb = (IStaticWeb) module.loadAdapter(IStaticWeb.class, null);
+				if (staticWeb != null)
+					mod.putString("context", staticWeb.getContextRoot());
+				mod.putString("type", "static");
+			}
+			mod.putString("path", getModulePublishDirectory(module).toPortableString());
+		}
+		try {
+			memento.saveToFile(getTempDirectory().append("preview.xml").toOSString());
+		} catch (IOException e) {
+			Trace.trace(Trace.SEVERE, "Could not write preview config", e);
+			throw new CoreException(new Status(IStatus.ERROR, PreviewPlugin.PLUGIN_ID, 0, "Could not write preview configuration", null));
+		}
+		
+		setServerRestartState(false);
+		setServerState(IServer.STATE_STARTING);
+		setMode(launchMode);
+		
+		// ping server to check for startup
+		try {
+			String url = "http://localhost";
+			if (port != 80)
+				url += ":" + port;
+			ping = new PingThread(getServer(), url, this);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Can't ping for Tomcat startup.");
+		}
+	}
+
+	protected void addProcessListener(final IProcess newProcess) {
+		if (processListener != null || newProcess == null)
+			return;
+		
+		processListener = new IDebugEventSetListener() {
+			public void handleDebugEvents(DebugEvent[] events) {
+				if (events != null) {
+					for (DebugEvent event : events) {
+						if (newProcess != null && newProcess.equals(event.getSource()) && event.getKind() == DebugEvent.TERMINATE) {
+							stop(true);
+						}
+					}
+				}
+			}
+		};
+		DebugPlugin.getDefault().addDebugEventListener(processListener);
+	}
+
+	protected void setServerStarted() {
+		setServerState(IServer.STATE_STARTED);
+	}
+
+	protected void publishServer(int kind, IProgressMonitor monitor) throws CoreException {
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		monitor.done();
+
+		setServerPublishState(IServer.PUBLISH_STATE_NONE);
+	}
+
+	/*
+	 * Publishes the given module to the server.
+	 */
+	protected void publishModule(int kind, int deltaKind, IModule[] moduleTree, IProgressMonitor monitor) throws CoreException {
+		IModule module = moduleTree[moduleTree.length - 1];
+		if (isSingleRootStructure(module))
+			return;
+		
+		IPath to = getModulePublishDirectory(module);
+		
+		if (kind == IServer.PUBLISH_CLEAN || deltaKind == ServerBehaviourDelegate.REMOVED) {
+			IStatus[] status = PublishUtil.deleteDirectory(to.toFile(), monitor);
+			throwException(status);
+		}
+		
+		IModuleResource[] res = getResources(moduleTree);
+		IStatus[] status = PublishUtil.publishSmart(res, to, monitor);
+		throwException(status);
+		
+		setModulePublishState(moduleTree, IServer.PUBLISH_STATE_NONE);
+	}
+
+	/**
+	 * Utility method to throw a CoreException based on the contents of a list of
+	 * error and warning status.
+	 * 
+	 * @param status a List containing error and warning IStatus
+	 * @throws CoreException
+	 */
+	private static void throwException(IStatus[] status) throws CoreException {
+		if (status == null || status.length == 0)
+			return;
+		
+		if (status.length == 1)
+			throw new CoreException(status[0]);
+		
+		String message = Messages.errorPublish;
+		MultiStatus status2 = new MultiStatus(PreviewPlugin.PLUGIN_ID, 0, status, message, null);
+		throw new CoreException(status2);
+	}
+
+	public void restart(String launchMode) throws CoreException {
+		setServerState(IServer.STATE_STOPPED);
+		setServerState(IServer.STATE_STARTED);
+	}
+
+	/**
+	 * Cleanly shuts down and terminates the server.
+	 * 
+	 * @param force <code>true</code> to kill the server
+	 */
+	public void stop(boolean force) {
+		int state = getServer().getServerState();
+		if (state == IServer.STATE_STOPPED)
+			return;
+		
+		setServerState(IServer.STATE_STOPPING);
+		
+		if (ping != null) {
+			ping.stop();
+			ping = null;
+		}
+		
+		if (processListener != null) {
+			DebugPlugin.getDefault().removeDebugEventListener(processListener);
+			processListener = null;
+		}
+		
+		try {
+			Trace.trace(Trace.FINEST, "Killing the process");
+			ILaunch launch = getServer().getLaunch();
+			if (launch != null)
+				launch.terminate();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error killing the process", e);
+		}
+		
+		setServerState(IServer.STATE_STOPPED);
+	}
+
+	protected IPath getTempDirectory() {
+		return super.getTempDirectory();
+	}
+
+	/**
+	 * Returns <code>true</code> if the module in the workspace has a single
+	 * root structure - i.e. matches the spec disk layout - and <code>false</code>
+	 * otherwise.
+	 * 
+	 * @return <code>true</code> if the module in the workspace has a single
+	 *    root structure - i.e. matches the spec disk layout - and
+	 *    <code>false</code> otherwise
+	 */
+	protected boolean isSingleRootStructure(IModule module) {
+		ProjectModule pm = (ProjectModule) module.loadAdapter(ProjectModule.class, null);
+		if (pm == null)
+			return false;
+		
+		return pm.isSingleRootStructure();
+	}
+
+	/**
+	 * Returns the module's publish path.
+	 * 
+	 * @param module a module
+	 * @return the publish directory for the module
+	 */
+	protected IPath getModulePublishDirectory(IModule module) {
+		if (isSingleRootStructure(module)) {
+			IStaticWeb webModule = (IStaticWeb) module.loadAdapter(IStaticWeb.class, null);
+			if (webModule != null) {
+				//IContainer[] moduleFolder = webModule.getResourceFolders();
+				//if (moduleFolder != null && moduleFolder.length > 0)
+				//	return moduleFolder[0].getLocation();							
+			}
+		}
+		
+		return getTempDirectory().append(module.getName());
+	}
+
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return "PreviewServer";
+	}
+
+	protected IModuleResourceDelta[] getPublishedResourceDelta(IModule[] module) {
+		return super.getPublishedResourceDelta(module);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.server.ui/META-INF/MANIFEST.MF
index 8815a61..08f5c3d 100644
--- a/plugins/org.eclipse.wst.server.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.wst.server.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.wst.server.ui; singleton:=true
-Bundle-Version: 1.1.1.qualifier
+Bundle-Version: 1.1.5.qualifier
 Bundle-Activator: org.eclipse.wst.server.ui.internal.ServerUIPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.wst.server.ui/serverAdapterSites.xml b/plugins/org.eclipse.wst.server.ui/serverAdapterSites.xml
new file mode 100644
index 0000000..54ec5e0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverAdapterSites.xml
@@ -0,0 +1,10 @@
+<extensions>
+    <site url="http://www.apache.org/dist/geronimo/eclipse/updates/"/>
+    <site url="http://download.boulder.ibm.com/ibmdl/pub/software/websphere/wasce/updates/"/>
+    <site url="http://www.pramati.com/downloads/eclipse/updates/"/>
+    <site url="http://update.eclipse.org/updates/3.3/"/>
+    <site url="http://download.oracle.com/otn_software/oepe/ganymede/wls-adapter/"/>
+    <site url="https://ajax.dev.java.net/eclipse"/>
+    <site url="https://www.sdn.sap.com/downloads/updates/netweaver/nwds/sapnwserver/"/>
+    <site url="http://www.webtide.com/eclipse"/>
+</extensions>
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DefaultMonitorDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DefaultMonitorDelegate.java
index 279ddbb..e8fca29 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DefaultMonitorDelegate.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DefaultMonitorDelegate.java
@@ -76,7 +76,7 @@
 		try {
 			IMonitor monitor = monitors.get(port);
 			int mport = -1;
-			if (monitor == null) {
+			if (monitor == null || monitor.getLocalPort() != monitorPort) {
 				mport = monitorPort;
 				if (mport == -1)
 					mport = SocketUtil.findUnusedPort(5000, 15000);
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.java
index 48a4403..79f2f7a 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.java
@@ -183,6 +183,7 @@
 	public static String wizModuleRemoveAll;
 	public static String wizModuleRequiredModule;
 	public static String wizModuleRequiredModules;
+	public static String wizModulePublishImmediately;
 	public static String wizTaskTitle;
 	public static String wizTaskDescription;
 	public static String wizErrorInvalidFolder;
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.properties b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.properties
index f768261..08b92ba 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.properties
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.properties
@@ -85,6 +85,7 @@
 wizModuleRemoveAll=<< Re&move All
 wizModuleRequiredModule={0} is required and cannot be removed from the server
 wizModuleRequiredModules=One of the required modules ({0}) must be added to the server
+wizModulePublishImmediately=If server is started, publish changes &immediately
 
 # Wizard info and error messages
 wizErrorInvalidFolder=The folder must be a server project or a folder within a server project
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerPropertyPage.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerPropertyPage.java
new file mode 100644
index 0000000..53a7147
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerPropertyPage.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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.wst.server.ui.internal;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.dialogs.Dialog;
+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.Label;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PropertyPage;
+import org.eclipse.ui.help.IWorkbenchHelpSystem;
+import org.eclipse.wst.server.core.IRuntimeType;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerType;
+import org.eclipse.wst.server.core.internal.Server;
+/**
+ * PropertyPage for servers.
+ */
+public class ServerPropertyPage extends PropertyPage {
+	protected IServer server;
+
+	protected IServer defaultServer;
+
+	/**
+	 * ServerPropertyPage constructor comment.
+	 */
+	public ServerPropertyPage() {
+		super();
+	}
+
+	/**
+	 * Create the body of the page.
+	 *
+	 * @param parent org.eclipse.swt.widgets.Composite
+	 * @return org.eclipse.swt.widgets.Control
+	 */
+	protected Control createContents(Composite parent) {
+		try {
+			IAdaptable element = getElement();
+			server = (IServer) element.getAdapter(IServer.class);
+			
+			Composite composite = new Composite(parent, SWT.NONE);
+			GridLayout layout = new GridLayout();
+			layout.marginHeight = 0;
+			layout.marginWidth = 0;
+			layout.numColumns = 3;
+			composite.setLayout(layout);
+			composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+			
+			IWorkbenchHelpSystem whs = PlatformUI.getWorkbench().getHelpSystem();
+			whs.setHelp(composite, ContextIds.SERVER_PROPERTY_PAGE);			
+			
+			// name
+			Label label = new Label(composite, SWT.NONE);
+			label.setText(Messages.propServerInfoName);
+			
+			label = new Label(composite, SWT.NONE);
+			label.setText(server.getName());
+			GridData data = new GridData(GridData.FILL_HORIZONTAL);
+			data.horizontalSpan = 2;
+			label.setLayoutData(data);
+			
+			// type
+			label = new Label(composite, SWT.NONE);
+			label.setText(Messages.propServerInfoType);
+			
+			IServerType serverType = server.getServerType();
+			label = new Label(composite, SWT.NONE);
+			if (serverType != null)
+				label.setText(serverType.getName());
+			else
+				label.setText(Messages.elementUnknownName);
+			data = new GridData(GridData.FILL_HORIZONTAL);
+			data.horizontalSpan = 2;
+			label.setLayoutData(data);
+			
+			// vendor
+			label = new Label(composite, SWT.NONE);
+			label.setText(Messages.propServerInfoVendor);
+			
+			IRuntimeType runtimeType = null;
+			if (serverType != null)
+				runtimeType = serverType.getRuntimeType();
+			label = new Label(composite, SWT.NONE);
+			if (runtimeType != null)
+				label.setText(runtimeType.getVendor());
+			else
+				label.setText(Messages.elementUnknownName);
+			data = new GridData(GridData.FILL_HORIZONTAL);
+			data.horizontalSpan = 2;
+			label.setLayoutData(data);
+			
+			// location
+			label = new Label(composite, SWT.NONE);
+			label.setText(Messages.switchServerLocation);
+			label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING));
+			
+			final Label serverLocation = new Label(composite, SWT.NONE);
+			final Server svr = (Server) server;
+			if (svr.getFile() != null)
+				serverLocation.setText(svr.getFile().getFullPath().toPortableString());
+			else
+				serverLocation.setText(Messages.switchServerLocationMetadata);
+			
+			serverLocation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING));
+			
+			Button switchLocation = new Button(composite, SWT.PUSH);
+			switchLocation.setText(Messages.actionSwitchServerLocation);
+			switchLocation.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
+			switchLocation.setEnabled(!server.isReadOnly());
+			switchLocation.addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					try {
+						Server.switchLocation(svr, null);
+					} catch (CoreException ce) {
+						Trace.trace(Trace.SEVERE, "Error switching server location", ce);
+					}
+					if (svr.getFile() != null)
+						serverLocation.setText(svr.getFile().getFullPath().toPortableString());
+					else
+						serverLocation.setText(Messages.switchServerLocationMetadata);
+				}
+			});
+			
+			Dialog.applyDialogFont(composite);
+			
+			return composite;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error creating property page", e);
+			return null;
+		}
+	}
+
+	protected void performDefaults() {
+		super.performDefaults();
+	}
+
+	/**
+	 * @see org.eclipse.jface.preference.PreferencePage#performOk()
+	 */
+	public boolean performOk() {
+		return super.performOk();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerToolTip.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerToolTip.java
new file mode 100644
index 0000000..ea16e5d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerToolTip.java
@@ -0,0 +1,299 @@
+/**********************************************************************
+ * Copyright (c) 2007, 2009 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.wst.server.ui.internal;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.internal.text.html.HTML2TextReader;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.window.ToolTip;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.internal.Trace;
+import org.eclipse.wst.server.ui.IServerModule;
+import org.eclipse.wst.server.ui.internal.provisional.IServerToolTip;
+
+public class ServerToolTip extends ToolTip {	
+	protected Hashtable<String,ArrayList<IServerToolTip>> toolTipProviders = new Hashtable<String,ArrayList<IServerToolTip>>();	
+	protected static Shell CURRENT_TOOLTIP;
+	protected Label hintLabel;
+	protected Tree tree;
+	protected int x;
+	protected int y;
+
+	public ServerToolTip(final Tree tree) {
+		super(tree);
+		
+		this.tree = tree;
+		
+		tree.addMouseMoveListener(new MouseMoveListener() {
+			public void mouseMove(MouseEvent e) {
+				x = e.x;
+				y = e.y;
+			}
+		});
+		
+		tree.addKeyListener(new KeyListener() {
+			public void keyPressed(KeyEvent  e) {
+				if (e == null)
+					return;
+				
+				if (e.keyCode == SWT.ESC) {
+					if (CURRENT_TOOLTIP != null) {
+						CURRENT_TOOLTIP.dispose();
+						CURRENT_TOOLTIP = null;
+					}
+					activate();
+				}
+				if (e.keyCode == SWT.F6) {
+					if (CURRENT_TOOLTIP == null) {
+						deactivate();
+						hide();
+						createFocusedTooltip(tree);
+					}
+				}
+			}
+			public void keyReleased(KeyEvent e){
+				// nothing to do 
+			}
+		});
+		
+		loadExtensions();
+	}
+	
+	public void createFocusedTooltip(final Control control) {
+		final Shell stickyTooltip = new Shell(control.getShell(), SWT.ON_TOP | SWT.TOOL
+				| SWT.NO_FOCUS);
+		stickyTooltip.setLayout(new FillLayout());
+		stickyTooltip.setBackground(stickyTooltip.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+		
+		control.getDisplay().asyncExec(new Runnable() {
+			public void run() {
+				Event event = new Event();
+				event.x = x;
+				event.y = y;
+				event.widget = tree;
+				
+				createToolTipContentArea(event, stickyTooltip);
+				stickyTooltip.pack();
+				
+				stickyTooltip.setLocation(stickyTooltip.getDisplay().getCursorLocation());				
+				hintLabel.setText(Messages.toolTipDisableFocus);
+				stickyTooltip.setVisible(true);
+//				Eventually we want to add a listener that checks if
+//              the mouseDown event is occurring outside of the bounds of the tooltip
+//              if it is, then hide the tooltip
+//				addListener(stickyTooltip);
+			}
+		});
+		CURRENT_TOOLTIP = stickyTooltip;
+	}
+
+//  read the createFocusedTooltip method for information on why this is commented out
+//
+//	private void addListener(Control control){
+//		control.addMouseListener(new StickyTipMouseListener());
+//		if (control instanceof Composite){
+//			Control[] childrens = ((Composite)control).getChildren();
+//			for (Control child :childrens){
+//				addListener(child);
+//			}
+//		}
+//		
+//	}
+	
+	
+	@Override
+	protected Object getToolTipArea(Event event) {
+		Object o = tree.getItem(new Point(event.x,event.y));
+		return o;
+	}
+
+	protected final boolean shouldCreateToolTip(Event event) {
+		if (tree.getItem(new Point(event.x, event.y)) == null)
+			return false;
+		return super.shouldCreateToolTip(event);
+	}
+
+	protected Composite createToolTipContentArea(Event event, Composite parent) {
+		Object o = tree.getItem(new Point(event.x, event.y));
+		if (o == null)
+			return null;
+		
+		IServer server = null;
+		IServerModule module = null;
+		if (o instanceof TreeItem) {
+			Object obj = ((TreeItem)o).getData();
+			if (obj instanceof IServer)
+				server = (IServer) obj;
+			if (obj instanceof IServerModule)
+				module = (IServerModule) obj;
+		}
+		
+		FillLayout layout = (FillLayout)parent.getLayout();
+		layout.type = SWT.VERTICAL;
+		parent.setLayout(layout);
+		
+		// set the default text for the tooltip
+		StyledText sText = new StyledText(parent, SWT.NONE);
+		sText.setEditable(false);
+		sText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+		
+		if (module != null) {
+			IModule[] modules = module.getModule();
+			IModule m = modules[modules.length - 1];
+			sText.setText("<b>" + m.getName() + "</b>");
+			//sText.setText("<b>" + m.getName() + "</b></p>" + m.getModuleType().getName());
+			
+			StyledText sText2 = new StyledText(parent, SWT.NONE);
+			sText2.setEditable(false);
+			sText2.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+			sText2.setText(m.getModuleType().getName());
+		}
+		
+		if (server != null) {
+			sText.setText("<b>" + server.getName() + "</b>");
+			
+			// add adopters content
+			if (server.getServerType() != null) {
+				ArrayList<IServerToolTip> listOfProviders = toolTipProviders.get(server.getServerType().getId());
+				
+				final Composite adoptersComposite = new Composite(parent,SWT.NONE);
+				adoptersComposite.setLayout(new FillLayout());
+				adoptersComposite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+				
+				if (listOfProviders != null) {
+					for (IServerToolTip tipProvider : listOfProviders) {
+						tipProvider.createContent(adoptersComposite,server);
+					}
+				}
+			}
+		}
+		
+		// add the F3 text
+		hintLabel = new Label(parent,SWT.BORDER);
+		hintLabel.setAlignment(SWT.RIGHT);
+		hintLabel.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+		hintLabel.setText(Messages.toolTipEnableFocus);
+		hintLabel.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
+		
+		final Font font;
+		Display display = parent.getDisplay();
+		FontData[] fd = parent.getFont().getFontData();
+		int size2 = fd.length;
+		for (int i = 0; i < size2; i++)
+			fd[i].setHeight(7);
+		font = new Font(display, fd);
+		parent.addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				font.dispose();
+			}
+		});
+		hintLabel.setFont(font);
+		
+		parseText(sText.getText(),sText);
+		
+		return parent;
+	}
+
+	protected void parseText(String htmlText,StyledText sText) {	
+		TextPresentation presentation = new TextPresentation();
+		HTML2TextReader reader = new HTML2TextReader(new StringReader(htmlText), presentation);
+		String text;
+		
+		try {
+			text = reader.getString();
+		} catch (IOException e) {
+			text= ""; //$NON-NLS-1$
+		}
+		
+		sText.setText(text);		
+		Iterator iter = presentation.getAllStyleRangeIterator();
+		while (iter.hasNext()) {
+			StyleRange sr = (StyleRange)iter.next();
+			sText.setStyleRange(sr);
+		}
+	}
+
+	private void loadExtensions() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading serverToolTip extension point ->-");
+		
+		// search for extension points 
+		IExtensionRegistry reg = Platform.getExtensionRegistry();
+		IConfigurationElement[] extensions = reg.getConfigurationElementsFor(ServerUIPlugin.PLUGIN_ID + ".serverToolTip");
+		
+		IServerType[] serverTypes = ServerCore.getServerTypes();
+		
+		for (int i=0; i < extensions.length; i++){			
+			IConfigurationElement exElement = extensions[i];
+			
+			// Sort the extensions based on serverType
+			String exServerType = exElement.getAttribute("serverTypes");
+			
+			for (IServerType serverType : serverTypes) {
+				if (exServerType.compareTo("*") == 0 || 
+						exServerType.startsWith(serverType.getId()) == true) {
+					try {
+						IServerToolTip exTooltip = (IServerToolTip) exElement.createExecutableExtension("class");
+						ArrayList<IServerToolTip> listOfProviders = new ArrayList<IServerToolTip>(); 
+						if (toolTipProviders.containsKey(serverType)) {
+							listOfProviders = toolTipProviders.get(serverType);
+						}
+						listOfProviders.add(exTooltip);
+						toolTipProviders.put(serverType.getId(), listOfProviders);
+					} catch (CoreException e) {
+						Trace.trace(Trace.SEVERE, "Tooltip failed to load" + extensions[i].toString(), e);
+					}
+					Trace.trace(Trace.EXTENSION_POINT, "  Loaded serverToolTip: " + extensions[i].getAttribute("id"));
+				}
+			}
+		}
+	}
+
+//  read the createFocusedTooltip method for information on why this is commented out
+//
+//	protected class StickyTipMouseListener implements MouseListener{
+//
+//		public void mouseDoubleClick(MouseEvent e) {
+//			// TODO Auto-generated method stub
+//			
+//		}
+//
+//		public void mouseDown(MouseEvent e) {
+//			//System.out.println("mouseDown");
+//			if (CURRENT_TOOLTIP.getBounds().contains(new Point(e.x,e.y)) == true){
+//				CURRENT_TOOLTIP.setVisible(false);
+//				CURRENT_TOOLTIP.dispose();
+//				activate();
+//				CURRENT_TOOLTIP.removeMouseListener(this);
+//			}
+//		}
+//
+//		public void mouseUp(MouseEvent e) {
+//			// TODO Auto-generated method stub
+//			
+//		}
+//		
+//	}	
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPreferences.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPreferences.java
index a66d68b..e9c6e3a 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPreferences.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPreferences.java
@@ -29,6 +29,7 @@
 	private static final String PREF_ENABLE_BREAKPOINTS = "enable-breakpoints";
 	private static final String PREF_RESTART = "restart";
 	private static final String PREF_CREATE_SERVER_WITH_RUNTIME = "create-server";
+	private static final String PREF_PUBLISH_ON_ADD_REMOVE = "publish-on-add-remove";
 
 	public static final byte SAVE_EDITORS_ALWAYS = 2;
 	public static final byte SAVE_EDITORS_NEVER = 0;
@@ -72,6 +73,7 @@
 		preferences.setDefault(PREF_HOST_NAMES, "localhost");
 		preferences.setDefault(PREF_SHOW_ON_ACTIVITY, true);
 		preferences.setDefault(PREF_CREATE_SERVER_WITH_RUNTIME, false);
+		preferences.setDefault(PREF_PUBLISH_ON_ADD_REMOVE, true);
 	}
 
 	/**
@@ -340,4 +342,23 @@
 		preferences.setValue(PREF_CREATE_SERVER_WITH_RUNTIME, b);
 		ServerUIPlugin.getInstance().savePluginPreferences();
 	}
+
+	/**
+	 * Returns the setting for publishing when modules are added or removed.
+	 * 
+	 * @return boolean
+	 */
+	public boolean getPublishOnAddRemoveModule() {
+		return preferences.getBoolean(PREF_PUBLISH_ON_ADD_REMOVE);
+	}
+
+	/**
+	 * Sets the value for publishing when modules are added or removed.
+	 * 
+	 * @param b
+	 */
+	public void setPublishOnAddRemoveModule(boolean b) {
+		preferences.setValue(PREF_PUBLISH_ON_ADD_REMOVE, b);
+		ServerUIPlugin.getInstance().savePluginPreferences();
+	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Trace.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Trace.java
new file mode 100644
index 0000000..c8513f7
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Trace.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.ui.internal;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+/**
+ * Helper class to route trace output.
+ */
+public class Trace {
+	public static final byte CONFIG = 0;
+	public static final byte INFO = 1;
+	public static final byte WARNING = 2;
+	public static final byte SEVERE = 3;
+	public static final byte FINEST = 4;
+	public static final byte FINER = 5;
+	public static final byte PERFORMANCE = 6;
+	public static final byte EXTENSION_POINT = 7;
+
+	private static final String[] levelNames = new String[] {
+		"CONFIG ", "INFO   ", "WARNING", "SEVERE ", "FINER  ", "FINEST ", "PERF   ", "EXTENSION"};
+
+	private static final SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm.ss.SSS");
+
+	private static Set<String> logged = new HashSet<String>();
+
+	/**
+	 * Trace constructor comment.
+	 */
+	private Trace() {
+		super();
+	}
+
+	/**
+	 * Trace the given text.
+	 *
+	 * @param level a trace level
+	 * @param s a message
+	 */
+	public static void trace(byte level, String s) {
+		trace(level, s, null);
+	}
+
+	/**
+	 * Trace the given message and exception.
+	 *
+	 * @param level a trace level
+	 * @param s a message
+	 * @param t a throwable
+	 */
+	public static void trace(byte level, String s, Throwable t) {
+		if (s == null)
+			return;
+		
+		if (level == SEVERE) {
+			if (!logged.contains(s)) {
+				ServerUIPlugin.getInstance().getLog().log(new Status(IStatus.ERROR, ServerUIPlugin.PLUGIN_ID, s, t));
+				logged.add(s);
+			}
+		}
+		
+		if (!ServerUIPlugin.getInstance().isDebugging())
+			return;
+		
+		StringBuffer sb = new StringBuffer(ServerUIPlugin.PLUGIN_ID);
+		sb.append(" ");
+		sb.append(levelNames[level]);
+		sb.append(" ");
+		sb.append(sdf.format(new Date()));
+		sb.append(" ");
+		sb.append(s);
+		System.out.println(sb.toString());
+		if (t != null)
+			t.printStackTrace();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RunOnServerActionDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RunOnServerActionDelegate.java
index 35b8265..6df0cf2 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RunOnServerActionDelegate.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RunOnServerActionDelegate.java
@@ -422,21 +422,31 @@
 						final IServer server3 = server;
 						server.restart(launchMode, new IServer.IOperationListener() {
 							public void done(IStatus result) {
-								server3.publish(IServer.PUBLISH_INCREMENTAL, null, info, new IServer.IOperationListener() {
-									public void done(IStatus result2) {
-										if (result2.isOK())
-											clientJob.schedule();
-									}
-								});
+								// Only publish if the server requires publish before launching the client.
+								if (server3.shouldPublish()) {
+									server3.publish(IServer.PUBLISH_INCREMENTAL, null, info, new IServer.IOperationListener() {
+										public void done(IStatus result2) {
+											if (result2.isOK())
+												clientJob.schedule();
+										}
+									});
+								} else {
+									clientJob.schedule();
+								}
 							}
 						});
 					} else {
-						server.publish(IServer.PUBLISH_INCREMENTAL, null, info, new IServer.IOperationListener() {
-							public void done(IStatus result) {
-								if (result.isOK())
-									clientJob.schedule();
-							}
-						});
+						// Only publish if the server requires publish before launching the client.
+						if (server.shouldPublish()) {
+							server.publish(IServer.PUBLISH_INCREMENTAL, null, info, new IServer.IOperationListener() {
+								public void done(IStatus result) {
+									if (result.isOK())
+										clientJob.schedule();
+								}
+							});
+						} else {
+							clientJob.schedule();
+						}
 					}
 				} else if (state != IServer.STATE_STOPPING) {
 					final LaunchClientJob clientJob = new LaunchClientJob(server, modules, launchMode, moduleArtifact, launchableAdapter, client);
@@ -751,7 +761,7 @@
 			// TODO - multiple module artifacts
 			IModuleArtifact[] moduleArtifacts = ServerPlugin.getModuleArtifacts(globalSelection);
 			IModuleArtifact moduleArtifact = null;
-			if (moduleArtifacts != null)
+			if (moduleArtifacts != null && moduleArtifacts.length > 0)
 				moduleArtifact = moduleArtifacts[0];
 			
 			IModule module = null;
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RunOnServerLaunchConfigurationDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RunOnServerLaunchConfigurationDelegate.java
index 1c01ae3..4a4303a 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RunOnServerLaunchConfigurationDelegate.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RunOnServerLaunchConfigurationDelegate.java
@@ -220,21 +220,31 @@
 				final IServer server2 = server;
 				server.restart(launchMode, new IServer.IOperationListener() {
 					public void done(IStatus result) {
-						server2.publish(IServer.PUBLISH_INCREMENTAL, null, info, new IServer.IOperationListener() {
-							public void done(IStatus result2) {
-								if (result2.isOK())
-									clientJob.schedule();
-							}
-						});
+						// Only publish if the server requires publish before launching the client.
+						if (server2.shouldPublish()) {
+							server2.publish(IServer.PUBLISH_INCREMENTAL, null, info, new IServer.IOperationListener() {
+								public void done(IStatus result2) {
+									if (result2.isOK())
+										clientJob.schedule();
+								}
+							});
+						} else {
+							clientJob.schedule();
+						}
 					}
 				});
 			} else {
-				server.publish(IServer.PUBLISH_INCREMENTAL, null, info, new IServer.IOperationListener() {
-					public void done(IStatus result) {
-						if (result.isOK())
-							clientJob.schedule();
-					}
-				});
+				// Only publish if the server requires publish before launching the client.
+				if (server.shouldPublish()) {
+					server.publish(IServer.PUBLISH_INCREMENTAL, null, info, new IServer.IOperationListener() {
+						public void done(IStatus result) {
+							if (result.isOK())
+								clientJob.schedule();
+						}
+					});
+				} else {
+					clientJob.schedule();
+				}
 			}
 		} else if (state != IServer.STATE_STOPPING) {
 			final LaunchClientJob clientJob = new LaunchClientJob(server, modules, launchMode, moduleArtifact, launchableAdapter, client);
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/OverviewEditorPart.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/OverviewEditorPart.java
index 29539cf..1e6dc84 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/OverviewEditorPart.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/OverviewEditorPart.java
@@ -741,7 +741,7 @@
 		toolkit.paintBordersFor(composite);
 		section.setClient(composite);
 		
-		//	 timeouts
+		//	timeouts
 		if (server != null) {
 			final Server svr = (Server) server;
 			
@@ -754,7 +754,7 @@
 			startTimeoutSpinner = new Spinner(composite, SWT.BORDER);
 			startTimeoutSpinner.setEnabled(true);
 			startTimeoutSpinner.setMinimum(1);
-			startTimeoutSpinner.setMaximum(60*30); // 30 minutes
+			startTimeoutSpinner.setMaximum(60*60*24); // 24 hours
 			startTimeoutSpinner.setIncrement(5);
 			startTimeoutSpinner.setSelection(svr.getStartTimeout());
 			SWTUtil.setSpinnerTooltip(startTimeoutSpinner);
@@ -772,7 +772,7 @@
 			stopTimeoutSpinner = new Spinner(composite, SWT.BORDER);
 			stopTimeoutSpinner.setEnabled(true);
 			stopTimeoutSpinner.setMinimum(1);
-			stopTimeoutSpinner.setMaximum(60*30); // 30 minutes
+			stopTimeoutSpinner.setMaximum(60*60*24); // 24 hours
 			stopTimeoutSpinner.setIncrement(5);
 			stopTimeoutSpinner.setSelection(svr.getStopTimeout());
 			SWTUtil.setSpinnerTooltip(stopTimeoutSpinner);
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/DeleteAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/DeleteAction.java
new file mode 100644
index 0000000..43bf11e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/DeleteAction.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.ui.internal.view.servers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.internal.DeleteServerDialog;
+import org.eclipse.wst.server.ui.internal.Messages;
+import org.eclipse.swt.widgets.Shell;
+/**
+ * Action for deleting server resources.
+ */
+public class DeleteAction extends AbstractServerAction {
+	protected IServer[] servers;
+	protected IFolder[] configs;
+
+	/**
+	 * DeleteAction constructor.
+	 * 
+	 * @param shell a shell
+	 * @param sp a selection provider
+	 */
+	public DeleteAction(Shell shell, ISelectionProvider sp) {
+		super(shell, sp, Messages.actionDelete);
+		ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
+		setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE));
+		setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE_DISABLED));
+		setActionDefinitionId(IWorkbenchActionDefinitionIds.DELETE);
+	}
+
+	public boolean accept(IServer server) {
+		servers = new IServer[] { server };
+		List<IFolder> list = new ArrayList<IFolder>();
+		
+		int size = servers.length;
+		for (int i = 0; i < size; i++) {
+			if (servers[i].isReadOnly())
+				return false;
+			
+			if (servers[i].getServerConfiguration() != null)
+				list.add(servers[i].getServerConfiguration());
+		}
+		
+		// remove configurations that are still referenced by other servers
+		IServer[] servers2 = ServerCore.getServers();
+		if (servers2 != null) {
+			int size2 = servers2.length;
+			for (int j = 0; j < size2; j++) {
+				boolean found = false;
+				for (int i = 0; i < size; i++) {
+					if (servers[i].equals(servers2[j]))
+						found = true;
+				}
+				if (!found) {
+					IFolder folder = servers2[j].getServerConfiguration();
+					if (folder != null && list.contains(folder))
+						list.remove(folder);
+				}
+			}
+		}
+		
+		configs = new IFolder[list.size()];
+		list.toArray(configs);
+		return true;
+	}
+
+	public void perform(IServer server) {
+		DeleteServerDialog dsd = new DeleteServerDialog(shell, servers, configs);
+		dsd.open();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RemoveModuleAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RemoveModuleAction.java
index b198af0..756ba36 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RemoveModuleAction.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RemoveModuleAction.java
@@ -16,8 +16,8 @@
 import org.eclipse.wst.server.core.IModule;
 import org.eclipse.wst.server.core.IServer;
 import org.eclipse.wst.server.core.IServerWorkingCopy;
-import org.eclipse.wst.server.core.internal.Server;
 import org.eclipse.wst.server.ui.internal.Messages;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
 import org.eclipse.wst.server.ui.internal.Trace;
 import org.eclipse.swt.widgets.Shell;
 /**
@@ -53,7 +53,8 @@
 				wc.modifyModules(null, new IModule[] { module }, null);
 				server = wc.save(true, null);
 				
-				if (server.getServerState() != IServer.STATE_STOPPED && ((Server)server).getAutoPublishSetting() != Server.AUTO_PUBLISH_DISABLE) {
+				if (server.getServerState() != IServer.STATE_STOPPED &&
+						ServerUIPlugin.getPreferences().getPublishOnAddRemoveModule()) {
 					final IAdaptable info = new IAdaptable() {
 						public Object getAdapter(Class adapter) {
 							if (Shell.class.equals(adapter))
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServerTableLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServerTableLabelProvider.java
index 4936576..34f7733 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServerTableLabelProvider.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServerTableLabelProvider.java
@@ -57,7 +57,8 @@
 	 * ServerTableLabelProvider constructor comment.
 	 */
 	public ServerTableLabelProvider() {
-		super();
+		// Ensure decorator is initialized.
+		super(null);
 	}
 
 	public void setDefaultServer(IServer ds) {
@@ -168,10 +169,9 @@
 				}
 				return name;
 			} else if (columnIndex == 1) {
-				//if (ms.server == null)
-				//	return "";
-				//return getStateLabel(ms.server.getServerType(), ms.server.getModuleState(ms.module), null);
-				return "";
+				if (ms.server == null)
+					return "";
+				return getStateLabel(ms.server.getServerType(), ms.server.getModuleState(ms.module), null);
 			} else if (columnIndex == 2) {
 				IStatus status = ((Server) ms.server).getModuleStatus(ms.module);
 				if (status != null)
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServerTableViewer.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServerTableViewer.java
index e3a5bb4..cc49345 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServerTableViewer.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServerTableViewer.java
@@ -58,6 +58,7 @@
 	protected static Set<String> starting = new HashSet<String>(4);
 
 	protected ServerTableLabelProvider labelProvider;
+	protected ILabelProviderListener labelProviderListener;
 	//protected ISelectionListener dsListener;
 
 	protected ServersView view;
@@ -452,6 +453,13 @@
 				((Server) servers[i]).addPublishListener(publishListener);
 			}
 		}
+		
+		labelProviderListener = new ILabelProviderListener() {
+			public void labelProviderChanged(LabelProviderChangedEvent event) {
+		    handleLabelProviderChanged(event);
+		  }
+		};
+		labelProvider.addListener(labelProviderListener);
 	}
 
 	protected void refreshServer(final IServer server) {
@@ -487,6 +495,11 @@
 			}
 		}
 		
+		// Remove the label provider listeners.
+		if (labelProvider != null && labelProviderListener != null) {
+			labelProvider.removeListener(labelProviderListener);
+		}
+		
 		clipboard.dispose();
 		
 		super.handleDispose(event);
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServersView.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServersView.java
new file mode 100644
index 0000000..5d754ad
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServersView.java
@@ -0,0 +1,460 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 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.wst.server.ui.internal.view.servers;
+
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.internal.Server;
+import org.eclipse.wst.server.core.internal.UpdateServerJob;
+import org.eclipse.wst.server.core.model.ServerDelegate;
+import org.eclipse.wst.server.ui.internal.*;
+import org.eclipse.wst.server.ui.internal.actions.NewServerWizardAction;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.*;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.contexts.IContextService;
+import org.eclipse.ui.keys.IBindingService;
+import org.eclipse.ui.part.ResourceTransfer;
+import org.eclipse.ui.part.ViewPart;
+import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
+/**
+ * A view of servers, their modules, and status.
+ */
+public class ServersView extends ViewPart {
+	private static final String TAG_COLUMN_WIDTH = "columnWidth";
+	private static final String SERVERS_VIEW_CONTEXT = "org.eclipse.ui.serverViewScope";
+
+	protected Action noneAction = new Action(Messages.dialogMonitorNone) {
+		// dummy action
+	};
+
+	protected int[] cols;
+
+	protected Tree treeTable;
+	protected ServerTableViewer tableViewer;
+
+	// actions on a server
+	protected Action[] actions;
+	protected Action actionModifyModules;
+	protected Action openAction, showInConsoleAction, showInDebugAction, propertiesAction, monitorPropertiesAction;
+	protected Action copyAction, pasteAction, deleteAction, renameAction;
+
+	/**
+	 * ServersView constructor comment.
+	 */
+	public ServersView() {
+		super();
+	}
+
+	protected SelectionListener getHeaderListener(final int col) {
+		return new SelectionAdapter() {
+			/**
+			 * Handles the case of user selecting the header area.
+			 */
+			public void widgetSelected(SelectionEvent e) {
+				if (tableViewer == null)
+					return;
+				TreeColumn column = (TreeColumn) e.widget;
+				tableViewer.resortTable(column, col);
+			}
+		};
+	}
+
+	/**
+	 * createPartControl method comment.
+	 * 
+	 * @param parent a parent composite
+	 */
+	public void createPartControl(Composite parent) {
+		treeTable = new Tree(parent, SWT.SINGLE | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL);
+		treeTable.setHeaderVisible(true);
+		treeTable.setLinesVisible(false);
+		treeTable.setLayoutData(new GridData(GridData.FILL_BOTH));
+		treeTable.setFont(parent.getFont());
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(treeTable, ContextIds.VIEW_SERVERS);
+		
+		// add columns
+		TreeColumn column = new TreeColumn(treeTable, SWT.SINGLE);
+		column.setText(Messages.viewServer);
+		column.setWidth(cols[0]);
+		column.addSelectionListener(getHeaderListener(0));
+		treeTable.setSortColumn(column);
+		treeTable.setSortDirection(SWT.UP);
+		
+		TreeColumn column2 = new TreeColumn(treeTable, SWT.SINGLE);
+		column2.setText(Messages.viewState);
+		column2.setWidth(cols[1]);
+		column2.addSelectionListener(getHeaderListener(1));
+		
+		TreeColumn column3 = new TreeColumn(treeTable, SWT.SINGLE);
+		column3.setText(Messages.viewStatus);
+		column3.setWidth(cols[2]);
+		column3.addSelectionListener(getHeaderListener(2));
+		
+		IContextService contextSupport = (IContextService)getSite().getService(IContextService.class);
+		contextSupport.activateContext(SERVERS_VIEW_CONTEXT);
+		
+		deferInitialization();
+	}
+
+	private void deferInitialization() {
+		TreeItem item = new TreeItem(treeTable, SWT.NONE);
+		item.setText(Messages.viewInitializing);
+		
+		tableViewer = new ServerTableViewer(this, treeTable);
+		initializeActions(tableViewer);
+		
+		Job job = new Job(Messages.jobInitializingServersView) {
+			public IStatus run(IProgressMonitor monitor) {
+				IServer[] servers = ServerCore.getServers();
+				int size = servers.length;
+				for (int i = 0; i < size; i++) {
+					((Server)servers[i]).getAllModules().iterator();
+					/*while (iterator.hasNext()) {
+						Module module = (Module) iterator.next();
+						module.g
+					}*/
+				}
+				
+				Display.getDefault().asyncExec(new Runnable() {
+					public void run() {
+						try {
+							deferredInitialize();
+						} catch (Exception e) {
+							// ignore - view has already been closed
+						}
+					}
+				});
+				return Status.OK_STATUS;
+			}
+		};
+		
+		job.setSystem(true);
+		job.setPriority(Job.SHORT);
+		job.schedule();
+	}
+
+	protected void deferredInitialize() {
+		tableViewer.initialize();
+		tableViewer.addOpenListener(new IOpenListener() {
+			public void open(OpenEvent event) {
+				try {
+					IStructuredSelection sel = (IStructuredSelection) event.getSelection();
+					Object data = sel.getFirstElement();
+					if (!(data instanceof IServer))
+						return;
+					IServer server = (IServer) data;
+					ServerUIPlugin.editServer(server);
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Could not open server", e);
+				}
+			}
+		});
+		
+		MenuManager menuManager = new MenuManager("#PopupMenu");
+		menuManager.setRemoveAllWhenShown(true);
+		final Shell shell = treeTable.getShell();
+		menuManager.addMenuListener(new IMenuListener() {
+			public void menuAboutToShow(IMenuManager mgr) {
+				fillContextMenu(shell, mgr);
+			}
+		});
+		Menu menu = menuManager.createContextMenu(treeTable);
+		treeTable.setMenu(menu);
+		getSite().registerContextMenu(menuManager, tableViewer);
+		getSite().setSelectionProvider(tableViewer);
+		
+		initDragAndDrop();
+		
+		// init the tooltip
+		ServerToolTip toolTip = new ServerToolTip(treeTable);
+		toolTip.setShift(new Point(10, 3));
+		toolTip.setPopupDelay(400); // in ms
+		toolTip.setHideOnMouseDown(true);
+		toolTip.activate();
+		
+		if (tableViewer.getTree().getItemCount() > 0) {
+			Object obj = tableViewer.getTree().getItem(0).getData();
+			tableViewer.setSelection(new StructuredSelection(obj));
+		}
+		
+		Thread thread = new Thread() {
+			public void run() {
+				try {
+					Thread.sleep(5000);
+				} catch (Exception e) {
+					// ignore
+				}
+				IServer[] servers = ServerCore.getServers();
+				int size = servers.length;
+				for (int i = 0; i < size; i++) {
+					IServer server = servers[i];
+					if (server.getServerType() != null && server.getServerState() == IServer.STATE_UNKNOWN) {
+						UpdateServerJob job = new UpdateServerJob(server);
+						job.schedule();
+					}
+				}
+			}
+		};
+		thread.setDaemon(true);
+		thread.setPriority(Thread.MIN_PRIORITY + 1);
+		thread.start();
+	}
+
+	public void init(IViewSite site, IMemento memento) throws PartInitException {
+		super.init(site, memento);
+		cols = new int[3];
+		for (int i = 0; i < 3; i++) {
+			cols[i] = 200;
+			if (memento != null) {
+				Integer in = memento.getInteger(TAG_COLUMN_WIDTH + i);
+				if (in != null && in.intValue() > 5)
+					cols[i] = in.intValue();
+			}
+		}
+	}
+
+	public void saveState(IMemento memento) {
+		TreeColumn[] tc = treeTable.getColumns();
+		for (int i = 0; i < 3; i++) {
+			int width = tc[i].getWidth();
+			if (width != 0)
+				memento.putInteger(TAG_COLUMN_WIDTH + i, width);
+		}
+	}
+
+	/**
+	 * Initialize actions
+	 * 
+	 * @param provider a selection provider
+	 */
+	public void initializeActions(ISelectionProvider provider) {
+		Shell shell = getSite().getShell();
+		IActionBars actionBars = getViewSite().getActionBars();
+		
+		actions = new Action[6];
+		// create the start actions
+		actions[0] = new StartAction(shell, provider, ILaunchManager.DEBUG_MODE);
+		actionBars.setGlobalActionHandler("org.eclipse.wst.server.debug", actions[0]);
+		actions[1] = new StartAction(shell, provider, ILaunchManager.RUN_MODE);
+		actionBars.setGlobalActionHandler("org.eclipse.wst.server.run", actions[1]);
+		actions[2] = new StartAction(shell, provider, ILaunchManager.PROFILE_MODE);
+		
+		// create the stop action
+		actions[3] = new StopAction(shell, provider);
+		actionBars.setGlobalActionHandler("org.eclipse.wst.server.stop", actions[3]);
+		
+		// create the publish actions
+		actions[4] = new PublishAction(shell, provider);
+		actionBars.setGlobalActionHandler("org.eclipse.wst.server.publish", actions[4]);
+		actions[5] = new PublishCleanAction(shell, provider);
+		
+		// create the open action
+		openAction = new OpenAction(provider);
+		actionBars.setGlobalActionHandler("org.eclipse.ui.navigator.Open", openAction);
+		
+		// create copy, paste, and delete actions
+		pasteAction = new PasteAction(shell, provider, tableViewer.clipboard);
+		copyAction = new CopyAction(provider, tableViewer.clipboard, pasteAction);
+		deleteAction = new DeleteAction(shell, provider);
+		renameAction = new RenameAction(shell, tableViewer, provider);
+		actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+		actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), pasteAction);
+		actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), deleteAction);
+		actionBars.setGlobalActionHandler(ActionFactory.RENAME.getId(), renameAction);
+		
+		// create the other actions
+		actionModifyModules = new ModuleSloshAction(shell, provider);
+		showInConsoleAction = new ShowInConsoleAction(provider);
+		showInDebugAction = new ShowInDebugAction(provider);
+		
+		// create the properties action
+		propertiesAction = new PropertiesAction(shell, provider);
+		actionBars.setGlobalActionHandler(ActionFactory.PROPERTIES.getId(), propertiesAction);
+		monitorPropertiesAction = new PropertiesAction(shell, "org.eclipse.wst.server.ui.properties.monitor", provider);
+		
+		// add toolbar buttons
+		IContributionManager cm = actionBars.getToolBarManager();
+		for (int i = 0; i < actions.length - 1; i++)
+			cm.add(actions[i]);
+		
+		cm.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+	}
+
+	private static void fillNewContextMenu(Shell shell, ISelection selection, IMenuManager menu) {
+		IAction newServerAction = new NewServerWizardAction();
+		newServerAction.setText(Messages.actionNewServer);
+		menu.add(newServerAction);
+	}
+
+	protected void fillContextMenu(Shell shell, IMenuManager menu) {
+		// get selection but avoid no selection or multiple selection
+		IServer server = null;
+		IModule[] module = null;
+		IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection();
+		if (!selection.isEmpty()) {
+			Iterator iterator = selection.iterator();
+			Object obj = iterator.next();
+			if (obj instanceof IServer)
+				server = (IServer) obj;
+			if (obj instanceof ModuleServer) {
+				ModuleServer ms = (ModuleServer) obj;
+				server = ms.server;
+				module = ms.module;
+			}
+			if (iterator.hasNext()) {
+				server = null;
+				module = null;
+			}
+		}
+		
+		// new action
+		MenuManager newMenu = new MenuManager(Messages.actionNew);
+		fillNewContextMenu(null, selection, newMenu);
+		menu.add(newMenu);
+		
+		// open action
+		if (server != null && module == null) {
+			menu.add(openAction);
+			
+			String text = Messages.actionShowIn;
+			final IWorkbench workbench = PlatformUI.getWorkbench();
+			final IBindingService bindingService = (IBindingService) workbench
+					.getAdapter(IBindingService.class);
+			final TriggerSequence[] activeBindings = bindingService
+					.getActiveBindingsFor("org.eclipse.ui.navigate.showInQuickMenu");
+			if (activeBindings.length > 0) {
+				text += "\t" + activeBindings[0].format();
+			}
+			
+			MenuManager showInMenu = new MenuManager(text);
+			showInMenu.add(showInConsoleAction);
+			showInMenu.add(showInDebugAction);
+			//IActionBars actionBars = getViewSite().getActionBars();
+			//actionBars.setGlobalActionHandler("group.show", showInMenu);
+			menu.add(showInMenu);
+			menu.add(new Separator());
+		} else
+			menu.add(new Separator());
+		
+		if (server != null) {
+			if (module == null) {
+				menu.add(copyAction);
+				menu.add(pasteAction);
+				menu.add(deleteAction);
+				menu.add(renameAction);
+			} else if (module.length == 1)
+				menu.add(new RemoveModuleAction(shell, server, module[0]));
+			menu.add(new Separator());
+		}
+		
+		if (server != null && module == null) {
+			// server actions
+			for (int i = 0; i < actions.length; i++)
+				menu.add(actions[i]);
+			
+			menu.add(new Separator());
+			menu.add(actionModifyModules);
+			
+			// monitor
+			if (server.getServerType() != null) {
+				final MenuManager menuManager = new MenuManager(Messages.actionMonitor);
+				
+				final IServer server2 = server;
+				final Shell shell2 = shell;
+				menuManager.addMenuListener(new IMenuListener() {
+					public void menuAboutToShow(IMenuManager manager) {
+						menuManager.removeAll();
+						if (server2.getAdapter(ServerDelegate.class) != null) {
+							ServerPort[] ports = server2.getServerPorts(null);
+							if (ports != null) {
+								int size = ports.length;
+								for (int i = 0; i < size; i++) {
+									if (!ports[i].isAdvanced())
+										menuManager.add(new MonitorServerPortAction(shell2, server2, ports[i]));
+								}
+							}
+						}
+						
+						if (menuManager.isEmpty())
+							menuManager.add(noneAction);
+						
+						menuManager.add(new Separator());
+						menuManager.add(monitorPropertiesAction);
+					}
+				});
+				
+				// add an initial menu item so that the menu appears correctly
+				noneAction.setEnabled(false);
+				menuManager.add(noneAction);
+				menu.add(menuManager);
+			}
+		}
+		
+		if (server != null && module != null) {
+			menu.add(new Separator());
+			menu.add(new StartModuleAction(server, module));
+			menu.add(new StopModuleAction(server, module));			
+			menu.add(new RestartModuleAction(server, module));
+		}
+		
+		menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+		menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS+"-end"));
+		
+		if (server != null) {
+			menu.add(new Separator());
+			menu.add(propertiesAction);
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public void setFocus() {
+		if (treeTable != null)
+			treeTable.setFocus();
+	}
+
+	/**
+    * Adds drag and drop support to the Servers view.
+    */
+   protected void initDragAndDrop() {
+		int ops = DND.DROP_COPY;
+		Transfer[] transfers = new Transfer[] { LocalSelectionTransfer.getInstance(),
+			ResourceTransfer.getInstance(), FileTransfer.getInstance() };
+		//tableViewer.addDragSupport(ops, transfers, new ServersViewDragAdapter(viewer));
+		tableViewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers, new ServersViewDropAdapter(tableViewer));
+   }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeContentProvider.java
new file mode 100644
index 0000000..3e5e096
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeContentProvider.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.ui.internal.viewers;
+
+import java.util.*;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * Runtime type content provider.
+ */
+public abstract class AbstractTreeContentProvider implements ITreeContentProvider {
+	public static final String ROOT = "root";
+
+	protected Object initialSelection;
+
+	public class TreeElement {
+		public String text;
+		public List<Object> contents;
+	}
+
+	protected Object[] elements;
+	protected Map<Object, TreeElement> elementToParentMap = new HashMap<Object, TreeElement>(2);
+	protected Map<String, TreeElement> textMap = new HashMap<String, TreeElement>(2);
+
+	/**
+	 * AbstractTreeContentProvider constructor comment.
+	 */
+	public AbstractTreeContentProvider() {
+		super();
+		
+		fillTree();
+	}
+
+	public AbstractTreeContentProvider(boolean init) {
+		super();
+	}
+
+	protected abstract void fillTree();
+
+	protected void clean() {
+		elements = null;
+		elementToParentMap = new HashMap<Object, TreeElement>(2);
+		textMap = new HashMap<String, TreeElement>(2);
+		
+		initialSelection = null;
+	}
+
+	protected TreeElement getOrCreate(List<TreeElement> list, String text) {
+		try {
+			Object obj = textMap.get(text);
+			if (obj != null)
+				return (TreeElement) obj;
+		} catch (Exception e) {
+			return null;
+		}
+		
+		TreeElement element = new TreeElement();
+		element.text = text;
+		element.contents = new ArrayList<Object>();
+		textMap.put(text, element);
+		list.add(element);
+		return element;
+	}
+	
+	protected TreeElement getOrCreate(List<TreeElement> list, String id, String text) {
+		try {
+			Object obj = textMap.get(id);
+			if (obj != null)
+				return (TreeElement) obj;
+		} catch (Exception e) {
+			return null;
+		}
+		
+		TreeElement element = new TreeElement();
+		element.text = text;
+		element.contents = new ArrayList<Object>();
+		textMap.put(id, element);
+		list.add(element);
+		return element;
+	}
+
+	protected TreeElement getByText(String text) {
+		try {
+			return textMap.get(text);
+		} catch (Exception e) {
+			return null;
+		}
+	}
+	
+	protected TreeElement getParentImpl(Object obj) {
+		try {
+			return elementToParentMap.get(obj);
+		} catch (Exception e) {
+			return null;
+		}
+	}
+
+	/**
+	 * Disposes of this content provider.  
+	 * This is called by the viewer when it is disposed.
+	 */
+	public void dispose() {
+		// do nothing
+	}
+
+	/**
+	 * Returns the elements to display in the viewer 
+	 * when its input is set to the given element. 
+	 * These elements can be presented as rows in a table, items in a list, etc.
+	 * The result is not modified by the viewer.
+	 *
+	 * @param element the input element
+	 * @return the array of elements to display in the viewer
+	 */
+	public Object[] getElements(Object element) {
+		return elements;
+	}
+
+	public Object[] getChildren(Object element) {
+		if (!(element instanceof TreeElement))
+			return null;
+		
+		TreeElement rte = (TreeElement) element;
+		return rte.contents.toArray();
+	}
+
+	public Object getParent(Object element) {
+		return getParentImpl(element);
+	}
+
+	public boolean hasChildren(Object element) {
+		Object[] children = getChildren(element);
+		return children != null && children.length > 0;
+	}
+
+	/**
+	 * Notifies this content provider that the given viewer's input
+	 * has been switched to a different element.
+	 * <p>
+	 * A typical use for this method is registering the content provider as a listener
+	 * to changes on the new input (using model-specific means), and deregistering the viewer 
+	 * from the old input. In response to these change notifications, the content provider
+	 * propagates the changes to the viewer.
+	 * </p>
+	 *
+	 * @param viewer the viewer
+	 * @param oldInput the old input element, or <code>null</code> if the viewer
+	 *   did not previously have an input
+	 * @param newInput the new input element, or <code>null</code> if the viewer
+	 *   does not have an input
+	 */
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		// do nothing
+	}
+
+	private Object[] getAllObjects() {
+		List<Object> list = new ArrayList<Object>();
+		Object[] obj = getElements(null);
+		if (obj != null) {
+			int size = obj.length;
+			for (int i = 0; i < size; i++) {
+				if (!(obj[i] instanceof AbstractTreeContentProvider.TreeElement))
+					list.add(obj[i]);
+				getAllChildren(list, obj[i]);
+			}
+		}
+		return list.toArray();
+	}
+
+	private void getAllChildren(List<Object> list, Object element) {
+		Object[] obj = getChildren(element);
+		if (obj != null) {
+			int size = obj.length;
+			for (int i = 0; i < size; i++) {
+				if (!(obj[i] instanceof AbstractTreeContentProvider.TreeElement))
+					list.add(obj[i]);
+				getAllChildren(list, obj[i]);
+			}
+		}
+	}
+
+	public Object getInitialSelection() {
+		if (initialSelection == null) {
+			InitialSelectionProvider isp = ServerUIPlugin.getInitialSelectionProvider();
+			initialSelection = isp.getInitialSelection(getAllObjects());
+		}
+		return initialSelection;
+	}
+	
+	public Object getInitialSelection(IProject project){
+		if (initialSelection == null) {
+			InitialSelectionProvider isp = ServerUIPlugin.getInitialSelectionProvider();
+			initialSelection = isp.getInitialSelection(getAllObjects(),project);
+		}
+		return initialSelection;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/BaseCellLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/BaseCellLabelProvider.java
index 64e5640..94ecc8c 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/BaseCellLabelProvider.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/BaseCellLabelProvider.java
@@ -10,9 +10,7 @@
  *******************************************************************************/
 package org.eclipse.wst.server.ui.internal.viewers;
 
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.ILabelDecorator;
-import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.jface.viewers.*;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.ui.PlatformUI;
@@ -21,6 +19,7 @@
  */
 public abstract class BaseCellLabelProvider extends ColumnLabelProvider {
 	public ILabelDecorator decorator;
+	protected ILabelProviderListener providerListener;
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.jface.viewers.ColumnLabelProvider#update(org.eclipse.jface.viewers.ViewerCell)
@@ -38,7 +37,7 @@
 	 * Create a BaseCellLabelProvider
 	 */
 	public BaseCellLabelProvider() {
-		super();
+		super();		
 	}
 
 	/**
@@ -47,9 +46,18 @@
 	 */
 	public BaseCellLabelProvider(ILabelDecorator decorator) {
 		super();
-		if (decorator == null)
+			
+		if (decorator == null){
 			decorator = PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator();
-		
+			providerListener = new ILabelProviderListener() {
+				@SuppressWarnings("synthetic-access")
+				public void labelProviderChanged(LabelProviderChangedEvent event) {
+					fireLabelProviderChanged(event);
+				}
+			};
+			decorator.addListener(providerListener);
+		}
+	
 		this.decorator = decorator;
 	} 
 
@@ -64,6 +72,13 @@
 	public int getToolTipTimeDisplayed(Object object) {	
 		return 5000;
 	}
+	
+	public void dispose() {
+		if (decorator != null && providerListener != null) {
+			decorator.removeListener(providerListener);
+		}
+		super.dispose();
+	}
 
 	/**
 	 * Extenders of this class would implement this method to provide an image to the column based on the element 
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/InitialSelectionProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/InitialSelectionProvider.java
new file mode 100644
index 0000000..248fad9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/InitialSelectionProvider.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 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.wst.server.ui.internal.viewers;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.wst.common.project.facet.core.IFacetedProject;
+import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.internal.ResourceManager;
+import org.eclipse.wst.server.core.internal.facets.FacetUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+/**
+ * Class used to sort categories, runtime types, and server types in the
+ * New wizards.
+ */
+public class InitialSelectionProvider extends ViewerSorter {
+
+	public Object getInitialSelection(Object[] obj) {
+		if (obj == null || obj.length == 0)
+			return null;
+		
+		if (obj[0] instanceof IRuntimeType) {
+			int size = obj.length;
+			IRuntimeType[] rt = new IRuntimeType[size];
+			for (int i = 0; i < size; i++)
+				rt[i] = (IRuntimeType) obj[i];
+			return getInitialSelection(rt);
+		}
+		
+		if (obj[0] instanceof IServerType) {
+			int size = obj.length;
+			IServerType[] st = new IServerType[size];
+			for (int i = 0; i < size; i++)
+				st[i] = (IServerType) obj[i];
+			return getInitialSelection(st);
+		}
+		
+		if (obj[0] instanceof IServer) {
+			int size = obj.length;
+			IServer[] st = new IServer[size];
+			for (int i = 0; i < size; i++)
+				st[i] = (IServer) obj[i];
+			return getInitialSelection(st);
+		}
+		
+		return null;
+	}
+
+	/**
+	 * 
+	 * @param serverTypes
+	 * @return the initial selection
+	 */
+	public IServerType getInitialSelection(IServerType[] serverTypes) {
+		if (serverTypes == null)
+			return null;
+		
+		int size = serverTypes.length;
+		for (int i = 0; i < size; i++) {
+			if (hasRuntime(serverTypes[i]))
+				return serverTypes[i];
+		}
+		return getDefaultServerType(serverTypes);
+	}
+
+	/**
+	 * 
+	 * @param servers
+	 * @return the initial selection
+	 */
+	public IServer getInitialSelection(IServer[] servers) {
+		return getInitialSelection(servers,null);
+	}
+	
+	/**
+	 * Allows adopters to provide an initial selection out of a list of items.
+	 * <p>
+	 * The <code>IProject</code> can be null, in cases where a project selection was not available (ie: New Server Wizard)
+	 * </p><p>
+	 * Returning <code>null</code> means no object is applicable to be selected. 
+	 * </p>
+	 * 
+	 * @param servers
+	 * @param project
+	 * @return
+	 */
+	public IServer getInitialSelection(IServer[] servers, IProject project){
+		if (servers == null)
+			return null;
+		
+		IServer rval = servers[0];
+		
+		if (project != null){
+			try{
+				// check for the targeted runtime of the project
+				IFacetedProject facetedProject = ProjectFacetsManager.create(project);
+				if (facetedProject != null){
+					org.eclipse.wst.common.project.facet.core.runtime.IRuntime facetedRuntime = facetedProject.getPrimaryRuntime();
+						if (facetedRuntime != null){
+							IRuntime runtime = FacetUtil.getRuntime(facetedRuntime);
+							IServer server = findServerFromRuntime(runtime.getId());
+							if (server != null){
+								rval = server;
+							}
+						}
+					}
+				}
+				catch (CoreException ce){
+					Trace.trace(Trace.WARNING,"Could not create a faceted project",ce);
+				}
+			}
+		return rval;
+	}
+
+	/**
+	 * 
+	 * @param runtimeTypes
+	 * @return the initial selection
+	 */
+	public IRuntimeType getInitialSelection(IRuntimeType[] runtimeTypes) {
+		if (runtimeTypes == null)
+			return null;
+		
+		int size = runtimeTypes.length;
+		for (int i = 0; i < size; i++) {
+			if (hasRuntime(runtimeTypes[i]))
+				return runtimeTypes[i];
+		}
+		return getDefaultRuntimeType(runtimeTypes);
+	}
+
+	protected boolean hasRuntime(IServerType serverType) {
+		return hasRuntime(serverType.getRuntimeType());
+	}
+
+	protected boolean hasRuntime(IRuntimeType runtimeType) {
+		if (runtimeType == null)
+			return false;
+		IRuntime[] runtimes = ServerUIPlugin.getRuntimes(runtimeType);
+		return runtimes != null && runtimes.length > 0;
+	}
+
+	/**
+	 * Returns a default server type, typically the 'first' one sorted
+	 * alphabetically by name.
+	 * 
+	 * @param serverTypes
+	 * @return the default server type
+	 */
+	protected IServerType getDefaultServerType(IServerType[] serverTypes) {
+		if (serverTypes == null)
+			return null;
+		
+		int size = serverTypes.length;
+		if (size == 1)
+			return serverTypes[0];
+		
+		IServerType first = serverTypes[0];
+		for (int i = 1; i < size; i++) {
+			if (DefaultViewerSorter.compareServerTypes(first, serverTypes[i]) > 0)
+				first = serverTypes[i];
+		}
+		return first;
+	}
+
+	/**
+	 * Returns a default runtime type, typically the 'first' one sorted
+	 * alphabetically by name.
+	 * 
+	 * @param runtimeTypes
+	 * @return the default runtime type
+	 */
+	protected IRuntimeType getDefaultRuntimeType(IRuntimeType[] runtimeTypes) {
+		if (runtimeTypes == null)
+			return null;
+		
+		int size = runtimeTypes.length;
+		if (size == 1)
+			return runtimeTypes[0];
+		
+		IRuntimeType first = runtimeTypes[0];
+		for (int i = 1; i < size; i++) {
+			if (DefaultViewerSorter.compareRuntimeTypes(first, runtimeTypes[i]) > 0)
+				first = runtimeTypes[i];
+		}
+		return first;
+	}
+	
+	/**
+	 * Allows adopters to provide an initial selection out of a list of items.
+	 * <p>
+	 * The <code>IProject</code> can be null, in cases where a project selection was not available (ie: New Server Wizard)
+	 * </p><p>
+	 * Returning <code>null</code> means no object is applicable to be selected. 
+	 * </p>
+	 * 
+	 * @param obj Contains an array of all the possible object to be selected. 
+	 * @param project
+	 * @return The object to be selected from the <code>obj[]</code> 
+	 */
+	public Object getInitialSelection(Object [] obj, IProject project){
+		if (obj == null || obj.length == 0)
+			return null;
+		
+		if (obj[0] instanceof IRuntimeType) {
+			int size = obj.length;
+			IRuntimeType[] rt = new IRuntimeType[size];
+			for (int i = 0; i < size; i++)
+				rt[i] = (IRuntimeType) obj[i];
+			return getInitialSelection(rt);
+		}
+		
+		if (obj[0] instanceof IServerType) {
+			int size = obj.length;
+			IServerType[] st = new IServerType[size];
+			for (int i = 0; i < size; i++)
+				st[i] = (IServerType) obj[i];
+			return getInitialSelection(st);
+		}
+		
+		if (obj[0] instanceof IServer) {
+			int size = obj.length;
+			IServer[] st = new IServer[size];
+			for (int i = 0; i < size; i++)
+				st[i] = (IServer) obj[i];
+			return getInitialSelection(st,project);
+		}
+		
+		return null;		
+	}
+	
+	/**
+	 * Returns the server with the given runtime id, or <code>null</code> 
+	 * if none. This convenience method searches the list of registered servers
+	 * for the matching runtime id. The id may not be null.
+	 * 
+	 * @param runtimeId
+	 * @return
+	 */
+	private static IServer findServerFromRuntime(String runtimeId){
+		if (runtimeId == null)
+			throw new IllegalArgumentException();
+			
+		IServer [] servers = ResourceManager.getInstance().getServers();
+		for (IServer server:servers){
+			if (runtimeId == server.getRuntime().getId()){
+				return server;
+			}
+		}
+		return null;
+	}
+	
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerComposite.java
new file mode 100644
index 0000000..2588b10
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerComposite.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.ui.internal.viewers;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.ui.dialogs.FilteredTree;
+
+import org.eclipse.wst.server.core.IModule;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.internal.Messages;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.view.servers.ServerTableLabelProvider;
+/**
+ * 
+ */
+public class ServerComposite extends AbstractTreeComposite {
+	protected IServer selection;
+	protected ServerSelectionListener listener;
+	protected ServerTreeContentProvider contentProvider;
+	protected boolean initialSelection = true;
+
+	protected IModule module;
+	protected String launchMode;
+	protected boolean includeIncompatibleVersions;
+
+	public interface ServerSelectionListener {
+		public void serverSelected(IServer server);
+	}
+
+	public ServerComposite(Composite parent, ServerSelectionListener listener2, IModule module, String launchMode) {
+		super(parent);
+		this.module = module;
+		this.launchMode = launchMode;
+		
+		this.listener = listener2;
+		
+		Tree tree2 = treeViewer.getTree();
+		TreeColumn column = new TreeColumn(tree2, SWT.SINGLE);
+		column.setText(Messages.viewServer);
+		column.setWidth(325);
+		
+		TreeColumn column2 = new TreeColumn(tree2, SWT.SINGLE);
+		column2.setText(Messages.viewState);
+		column2.setWidth(100);
+		
+		contentProvider = new ServerTreeContentProvider(module, launchMode);
+		treeViewer.setContentProvider(contentProvider);
+		
+		//ILabelProvider labelProvider = new ServerTreeLabelProvider();
+		ILabelProvider labelProvider = new ServerTableLabelProvider();
+		labelProvider.addListener(new ILabelProviderListener() {
+			public void labelProviderChanged(LabelProviderChangedEvent event) {
+				Object[] obj = event.getElements();
+				if (obj == null)
+					treeViewer.refresh(true);
+				else {
+					obj = ServerUIPlugin.adaptLabelChangeObjects(obj);
+					int size = obj.length;
+					for (int i = 0; i < size; i++)
+						treeViewer.refresh(obj[i], true);
+				}
+			}
+		});
+		treeViewer.setLabelProvider(labelProvider);
+		treeViewer.setInput(AbstractTreeContentProvider.ROOT);
+		treeViewer.expandToLevel(1);
+		
+		treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				Object obj = getSelection(event.getSelection());
+				if (obj instanceof IServer) {
+					selection = (IServer) obj;
+					setDescription(selection.getServerType().getRuntimeType().getDescription());
+				} else {
+					selection = null;
+					setDescription("");
+				}
+				listener.serverSelected(selection);
+			}
+		});
+	}
+
+	protected void createTree() {
+		tree = new FilteredTree(this, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION, new ServerPatternFilter());
+	}
+
+	public void setIncludeIncompatibleVersions(boolean b) {
+		includeIncompatibleVersions = b;
+		ISelection sel = treeViewer.getSelection();
+		contentProvider.setIncludeIncompatibleVersions(b);
+		treeViewer.refresh();
+		treeViewer.setSelection(sel, true);
+	}
+
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		if (visible && initialSelection) {
+			initialSelection = false;
+			deferInitialization();
+		}
+	}
+
+	public void refreshAll() {
+		ISelection sel = treeViewer.getSelection();
+		contentProvider = new ServerTreeContentProvider(module, launchMode);
+		contentProvider.setIncludeIncompatibleVersions(includeIncompatibleVersions);
+		treeViewer.setContentProvider(contentProvider);
+		treeViewer.setSelection(sel);
+	}
+
+	protected String getDescriptionLabel() {
+		return null;
+	}
+
+	protected String getTitleLabel() {
+		return Messages.wizNewServerSelectExisting;
+	}
+
+	public IServer getSelectedServer() {
+		return selection;
+	}
+
+	public void setSelection(IServer server) {
+		if (server != null)
+			treeViewer.setSelection(new StructuredSelection(server), true);
+		else
+			treeViewer.setSelection(null);
+	}
+
+	protected void deferInitialization() {
+		Job job = new Job(Messages.jobInitializingServersView) {
+			public IStatus run(IProgressMonitor monitor) {
+				Display.getDefault().asyncExec(new Runnable() {
+					public void run() {
+						try {
+							if (contentProvider.getInitialSelection(module.getProject()) != null)
+								treeViewer.setSelection(new StructuredSelection(contentProvider.getInitialSelection(module.getProject())), true);
+						} catch (Exception e) {
+							// ignore - wizard has already been closed
+						}
+					}
+				});
+				return Status.OK_STATUS;
+			}
+		};
+		
+		job.setSystem(true);
+		job.setPriority(Job.SHORT);
+		job.schedule();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ModifyModulesWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ModifyModulesWizard.java
index 1c6b776..9cdc191 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ModifyModulesWizard.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ModifyModulesWizard.java
@@ -16,8 +16,8 @@
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.wst.server.core.*;
-import org.eclipse.wst.server.core.internal.Server;
 import org.eclipse.wst.server.ui.internal.Messages;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
 import org.eclipse.wst.server.ui.internal.wizard.fragment.ModifyModulesWizardFragment;
 import org.eclipse.wst.server.ui.wizard.WizardFragment;
 /**
@@ -26,7 +26,7 @@
 public class ModifyModulesWizard extends TaskWizard {
 	static class ModifyModulesWizard2 extends WizardFragment {
 		protected void createChildFragments(List<WizardFragment> list) {
-			list.add(new ModifyModulesWizardFragment());
+			list.add(new ModifyModulesWizardFragment(true));
 			list.add(WizardTaskUtil.SaveServerFragment);
 			
 			list.add(new WizardFragment() {
@@ -34,7 +34,8 @@
 					IServerAttributes svr = (IServerAttributes) getTaskModel().getObject(TaskModel.TASK_SERVER);
 					if (svr instanceof IServer) {
 						IServer server = (IServer) svr;
-						if (server.getServerState() != IServer.STATE_STOPPED && ((Server)server).getAutoPublishSetting() != Server.AUTO_PUBLISH_DISABLE) {
+						if (server.getServerState() != IServer.STATE_STOPPED &&
+								ServerUIPlugin.getPreferences().getPublishOnAddRemoveModule()) {
 							IAdaptable info = null;
 							/*IAdaptable info = new IAdaptable() {
 								public Object getAdapter(Class adapter) {
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ModifyModulesWizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ModifyModulesWizardFragment.java
index 02b9e09..498555d 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ModifyModulesWizardFragment.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ModifyModulesWizardFragment.java
@@ -19,6 +19,7 @@
 import org.eclipse.wst.server.core.*;
 import org.eclipse.wst.server.core.internal.IModuleVisitor;
 import org.eclipse.wst.server.core.internal.Server;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
 import org.eclipse.wst.server.ui.internal.Trace;
 import org.eclipse.wst.server.ui.internal.wizard.WizardTaskUtil;
 import org.eclipse.wst.server.ui.internal.wizard.page.ModifyModulesComposite;
@@ -31,11 +32,16 @@
 	protected ModifyModulesComposite comp;
 
 	protected IModule module;
+	protected boolean showPublishOption;
 
 	public ModifyModulesWizardFragment() {
 		// do nothing
 	}
 
+	public ModifyModulesWizardFragment(boolean showPublishOption) {
+		this.showPublishOption = showPublishOption;
+	}
+
 	public ModifyModulesWizardFragment(IModule module) {
 		this.module = module;
 	}
@@ -48,7 +54,7 @@
 	 * @see org.eclipse.wst.server.ui.internal.task.WizardTask#getWizardPage()
 	 */
 	public Composite createComposite(Composite parent, IWizardHandle handle) {
-		comp = new ModifyModulesComposite(parent, handle, module);
+		comp = new ModifyModulesComposite(parent, handle, module, showPublishOption);
 		return comp;
 	}
 
@@ -120,7 +126,10 @@
 	}
 
 	public void performFinish(IProgressMonitor monitor) throws CoreException {
-		if (comp != null)
+		if (comp != null) {
 			WizardTaskUtil.modifyModules(comp.getModulesToAdd(), comp.getModulesToRemove(), getTaskModel(), monitor);
+			if (showPublishOption)
+				ServerUIPlugin.getPreferences().setPublishOnAddRemoveModule(comp.shouldPublishImmediately());
+		}
 	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/TasksWizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/TasksWizardFragment.java
new file mode 100644
index 0000000..5bc5f47
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/TasksWizardFragment.java
@@ -0,0 +1,305 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 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.wst.server.ui.internal.wizard.fragment;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.internal.*;
+import org.eclipse.wst.server.core.model.PublishOperation;
+import org.eclipse.wst.server.ui.internal.editor.IOrdered;
+import org.eclipse.wst.server.ui.internal.wizard.WizardTaskUtil;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+/**
+ * 
+ */
+public class TasksWizardFragment extends WizardFragment {
+	private static final int TASKS_PER_PAGE = 5;
+
+	public class TaskInfo implements IOrdered {
+		public int kind;
+		public String id;
+		public PublishOperation task2;
+		
+		private static final String DEFAULT = "default:";
+		
+		public boolean isSelected() {
+			if (id == null)
+				return false;
+			
+			if (selectedTaskMap.containsKey(id))
+				return (selectedTaskMap.get(id)).booleanValue();
+			
+			if (selectedTaskMap.containsKey(DEFAULT + id))
+				return (selectedTaskMap.get(DEFAULT + id)).booleanValue();
+
+			return false;
+		}
+		
+		public void setDefaultSelected(boolean sel) {
+			selectedTaskMap.put(DEFAULT + getId(), new Boolean(sel));
+		}
+
+		public boolean getDefaultSelected() {
+			return (selectedTaskMap.get(DEFAULT + id)).booleanValue();
+		}
+
+		public void setSelected(boolean sel) {
+			selectedTaskMap.put(getId(), new Boolean(sel));
+		}
+		
+		public int getOrder() {
+			return task2.getOrder();
+		}
+		
+		protected String getId() {
+			return id;
+		}
+		
+		public boolean equals(Object obj) {
+			if (!(obj instanceof TaskInfo))
+				return false;
+			
+			TaskInfo ti = (TaskInfo) obj;
+			if (kind != ti.kind)
+				return false;
+			
+			if (id == null || !id.equals(ti.id))
+				return false;
+			
+			if (task2 == null && ti.task2 != null)
+				return false;
+			
+			if (task2 != null && ti.task2 == null)
+				return false;
+			
+			try {
+				if (task2 != null && ti.task2 != null) {
+					if (task2.getKind() != ti.task2.getKind())
+						return false;
+					if (task2.getOrder() != ti.task2.getOrder())
+						return false;
+					if (!task2.getLabel().equals(ti.task2.getLabel()))
+						return false;
+					if (!task2.getDescription().equals(ti.task2.getDescription()))
+						return false;
+				}
+			} catch (Exception e) {
+				// ignore
+			}
+			return true;
+		}
+	}
+
+	protected List<TaskInfo> tasks;
+	protected boolean hasOptionalTasks;
+	protected boolean hasPreferredTasks;
+
+	protected Map<String, Boolean> selectedTaskMap = new HashMap<String, Boolean>();
+
+	public TasksWizardFragment() {
+		// do nothing
+	}
+
+	protected void createChildFragments(List<WizardFragment> list) {
+		if (tasks == null || tasks.isEmpty())
+			return;
+		
+		int size = tasks.size();
+		int pages = (size - 1) / TASKS_PER_PAGE + 1;
+		for (int i = 0; i < pages; i++) {
+			SubTasksWizardFragment fragment = new SubTasksWizardFragment();
+			List list2 = tasks.subList(TASKS_PER_PAGE * i, Math.min(size, TASKS_PER_PAGE * (i+1)));
+			fragment.updateTasks(list2);
+			list.add(fragment);
+		}
+	}
+
+	public void enter() {
+		updateTasks();
+	}
+
+	public List getChildFragments() {
+		updateTasks();
+		return super.getChildFragments();
+	}
+
+	public void setTaskModel(TaskModel taskModel) {
+		super.setTaskModel(taskModel);
+		updateTasks();
+	}
+
+	public void updateTasks() {
+		if (getTaskModel() == null) {
+			tasks = null;
+			return;
+		}
+		
+		IServerAttributes server = (IServerAttributes) getTaskModel().getObject(TaskModel.TASK_SERVER);
+		List modules = (List) getTaskModel().getObject(TaskModel.TASK_MODULES);
+		
+		if (server != null && modules == null) {
+			final List<IModule[]> moduleList = new ArrayList<IModule[]>();
+			((Server) server).visit(new IModuleVisitor() {
+				public boolean visit(IModule[] module2) {
+					moduleList.add(module2);
+					return true;
+				}
+			}, null);
+			
+			modules = moduleList;
+		}
+		
+		if (server != null && modules != null) {
+			hasOptionalTasks = false;
+			hasPreferredTasks = false;
+			List<TaskInfo> taskList = new ArrayList<TaskInfo>(5);
+			createTasks(taskList, server, modules);
+			
+			if (tasks == null || !tasks.equals(taskList)) {
+				tasks = taskList;
+				updateChildFragments();
+				
+				boolean b = hasOptionalTasks || hasPreferredTasks;
+				getTaskModel().putObject(WizardTaskUtil.TASK_HAS_TASKS, new Boolean(b));				
+			}
+		}
+	}
+
+	protected void createTasks(List<TaskInfo> taskList, IServerAttributes server, List modules) {
+		if (server == null)
+			return;
+		
+		List<String> enabledTasks = ((Server)server).getEnabledOptionalPublishOperationIds();
+		List<String> disabledTasks = ((Server)server).getDisabledPreferredPublishOperationIds();
+		PublishOperation[] tasks2 = ((Server)server).getAllTasks(modules);
+		for (int j = 0; j < tasks2.length; j++) {
+			int kind = tasks2[j].getKind();
+			String id = ((Server)server).getPublishOperationId(tasks2[j]);
+			if (kind == PublishOperation.OPTIONAL || kind == PublishOperation.PREFERRED)
+				hasOptionalTasks = true;
+			if (kind == PublishOperation.PREFERRED)
+				hasPreferredTasks = true;
+			tasks2[j].setTaskModel(getTaskModel());
+			
+			boolean selected = true;
+			if (kind == PublishOperation.OPTIONAL) {
+				if (!enabledTasks.contains(id))
+					selected = false;
+			} else if (kind == PublishOperation.PREFERRED) {
+				if (disabledTasks.contains(id))
+					selected = false;
+			}
+			taskList.add(getServerTask(server, tasks2[j], selected));
+		}
+	}
+
+	public TaskInfo getServerTask(IServerAttributes server, PublishOperation task2, boolean selected) {
+		TaskInfo sti = new TaskInfo();
+		sti.task2 = task2;
+		sti.kind = task2.getKind();
+		sti.id = ((Server)server).getPublishOperationId(task2);
+		sti.setDefaultSelected(selected);
+		
+		return sti;
+	}
+
+	/**
+	 * @see WizardFragment#performFinish(IProgressMonitor)
+	 */
+	public void performFinish(IProgressMonitor monitor) throws CoreException {
+		if (!hasOptionalTasks)
+			return;
+		
+		if (tasks == null || tasks.isEmpty())
+			return;
+		
+		TaskModel taskModel = getTaskModel();
+		IServer server = (IServer)taskModel.getObject(TaskModel.TASK_SERVER);
+		if (server == null)
+			return;
+		
+		boolean createdWC = false;
+		ServerWorkingCopy wc = null;
+		if (server instanceof ServerWorkingCopy)
+			wc = (ServerWorkingCopy)server;
+		else {
+			wc = (ServerWorkingCopy)server.createWorkingCopy();
+			createdWC = true;
+		}
+		
+		// compare lists
+		List<String> disabled = new ArrayList<String>();
+		List<String> enabled = new ArrayList<String>();
+		Iterator iterator = tasks.iterator();
+		while (iterator.hasNext()) {
+			TaskInfo task = (TaskInfo)iterator.next();
+			if (PublishOperation.REQUIRED == task.kind)
+				continue;
+			
+			String id = wc.getPublishOperationId(task.task2);
+			if (PublishOperation.PREFERRED == task.kind) {
+				if (!task.isSelected())
+					disabled.add(id);
+			} else if (PublishOperation.OPTIONAL == task.kind) {
+				if (task.isSelected())
+					enabled.add(id);
+			}
+		}
+		
+		List<String> curDisabled = wc.getDisabledPreferredPublishOperationIds();
+		List<String> curEnabled = wc.getEnabledOptionalPublishOperationIds();
+		
+		boolean different = false;
+		if (curEnabled.size() != enabled.size() || curDisabled.size() != disabled.size()) {
+			different = true;
+		} else {
+			for (String id : curDisabled) {
+				if (!disabled.contains(id))
+					different = true;
+			}
+			for (String id : curEnabled) {
+				if (!enabled.contains(id))
+					different = true;
+			}
+		}
+		
+		if (different) {
+			wc.resetPreferredPublishOperations();
+			wc.resetOptionalPublishOperations();
+			
+			Iterator<TaskInfo> iterator2 = tasks.iterator();
+			while (iterator2.hasNext()) {
+				TaskInfo task = iterator2.next();
+				if (PublishOperation.REQUIRED == task.kind)
+					continue;
+				
+				if (PublishOperation.PREFERRED == task.kind) {
+					if (!task.isSelected())
+						wc.disablePreferredPublishOperations(task.task2);
+				} else if (PublishOperation.OPTIONAL == task.kind) {
+					if (task.isSelected())
+						wc.enableOptionalPublishOperations(task.task2);
+				}
+			}
+		}
+		
+		if (createdWC && wc.isDirty())
+			wc.save(true, monitor);
+		monitor.done();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ModifyModulesComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ModifyModulesComposite.java
new file mode 100644
index 0000000..454ad8b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ModifyModulesComposite.java
@@ -0,0 +1,946 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.ui.internal.wizard.page;
+
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.*;
+import org.eclipse.wst.server.ui.internal.view.servers.ModuleServer;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+/**
+ * A wizard page used to add and remove modules.
+ */
+public class ModifyModulesComposite extends Composite {
+	public static final String TASK_REFRESH_MODULES = "refresh-modules";
+
+	private static final String ROOT = "root";
+	protected static Color color;
+	protected static Font font;
+
+	protected IWizardHandle wizard;
+
+	protected IServerAttributes server;
+	protected IRuntime runtime;
+	protected boolean runtimeDirty;
+	protected Object refreshModules;
+	protected boolean showPublishOption;
+	protected boolean publishImmediately;
+
+	protected Map<ChildModuleMapKey, IModule[]> childModuleMap = new HashMap<ChildModuleMapKey, IModule[]>();
+	protected Map<IModule, IModule[]> parentModuleMap = new HashMap<IModule, IModule[]>();
+
+	// original modules on the server
+	protected List<IModule> originalModules = new ArrayList<IModule>();
+
+	// modules available to be added to the server
+	protected List<IModule> modules = new ArrayList<IModule>();
+
+	// current modules on the server
+	protected List<IModule> deployed = new ArrayList<IModule>();
+
+	protected TreeViewer availableTreeViewer;
+	protected TreeViewer deployedTreeViewer;
+
+	protected Button add, addAll;
+	protected Button remove, removeAll;
+
+	protected TaskModel taskModel;
+
+	// a module that must be kept on the server
+	protected IModule requiredModule;
+	protected boolean isComplete = true;
+
+	// the parent modules of the above modules. at least one of these modules
+	// must be kept on the server
+	protected IModule[] requiredModules;
+
+	protected Map<IModule, IStatus> errorMap;
+
+	abstract class TreeContentProvider implements ITreeContentProvider {
+		public void dispose() {
+			// do nothing
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+			// do nothing
+		}
+		
+		public Object[] getChildren(Object parentElement) {
+			ModuleServer ms = (ModuleServer) parentElement;
+			IModule[] parent = ms.module;
+			IModule[] children = childModuleMap.get(new ChildModuleMapKey(parent));
+			
+			List<ModuleServer> list = new ArrayList<ModuleServer>();
+			if (children != null) {
+				int size = children.length;
+				for (int i = 0; i < size; i++) {
+					IModule child = children[i];
+					
+					parentModuleMap.put(child, parent);
+					
+					int size2 = parent.length;
+					IModule[] module2 = new IModule[size2 + 1];
+					System.arraycopy(parent, 0, module2, 0, size2);
+					module2[size2] = child;
+					list.add(new ModuleServer(null, module2));
+				}
+			}
+			return list.toArray();
+		}
+
+		public Object getParent(Object element) {
+			ModuleServer ms = (ModuleServer) element;
+			IModule[] child = ms.module;
+			IModule[] modules2 = parentModuleMap.get(child);
+			if (modules2 == null)
+				return null;
+			return new ModuleServer(null, modules2);
+		}
+
+		public boolean hasChildren(Object element) {
+			ModuleServer ms = (ModuleServer) element;
+			IModule[] parent = ms.module;
+			IModule[] children = childModuleMap.get(new ChildModuleMapKey(parent));
+			return (children != null && children.length > 0);
+		}
+	}
+
+	class AvailableContentProvider extends TreeContentProvider {
+		public Object[] getElements(Object inputElement) {
+			List<ModuleServer> list = new ArrayList<ModuleServer>();
+			Iterator iterator = modules.iterator();
+			while (iterator.hasNext()) {
+				IModule module = (IModule) iterator.next();
+				list.add(new ModuleServer(null, new IModule[] { module }));
+			}
+			return list.toArray();
+		}
+	}
+
+	class DeployedContentProvider extends TreeContentProvider {
+		public Object[] getElements(Object inputElement) {
+			List<ModuleServer> list = new ArrayList<ModuleServer>();
+			Iterator iterator = deployed.iterator();
+			while (iterator.hasNext()) {
+				IModule module = (IModule) iterator.next();
+				list.add(new ModuleServer(null, new IModule[] { module }));
+			}
+			return list.toArray();
+		}
+	}
+
+	/**
+	 * The key element for the child module map
+	 * ChildMapModuleKey
+	 */
+	protected class ChildModuleMapKey {
+		protected IModule[] moduleTree;
+		
+		protected ChildModuleMapKey(IModule curModule) {
+			if (curModule != null) {
+				moduleTree = new IModule[] { curModule };
+			}
+		}
+		
+		protected ChildModuleMapKey(IModule[] curModuleTree) {
+			moduleTree = curModuleTree;
+		}
+		
+		public boolean equals(Object obj) {
+			if (obj == this) // same object
+				return true;
+			
+			if (!(obj instanceof ChildModuleMapKey))
+				return false;
+				
+			IModule[] curCompareModule = ((ChildModuleMapKey) obj).moduleTree;
+			if (curCompareModule == moduleTree) {
+				// the module tree is the same
+				return true;
+			} else if (moduleTree == null || curCompareModule == null || moduleTree.length != curCompareModule.length){
+				return false;
+			} else {
+				// compare each module
+				for (int i = 0; i < curCompareModule.length; i++) {
+					if (!curCompareModule[i].equals(moduleTree[i]))
+						return false;
+				}
+				return true;
+			}
+		}
+
+		public int hashCode() {
+			// force the same hash code on all the instances to makes sure the
+			// equals(Object) method is being used for comparing the objects
+			return 12345;
+		}
+	}
+
+	/**
+	 * Create a new ModifyModulesComposite.
+	 * 
+	 * @param parent a parent composite
+	 * @param wizard a wizard
+	 * @param module the module that is being added
+	 */
+	public ModifyModulesComposite(Composite parent, IWizardHandle wizard, IModule module) {
+		super(parent, SWT.NONE);
+		this.wizard = wizard;
+		requiredModule = module;
+		
+		wizard.setTitle(Messages.wizModuleTitle);
+		wizard.setDescription(Messages.wizModuleDescription);
+		wizard.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_SELECT_SERVER));
+		
+		createControl();
+	}
+
+	/**
+	 * Create a new ModifyModulesComposite.
+	 * 
+	 * @param parent a parent composite
+	 * @param wizard a wizard
+	 * @param module the module that is being added
+	 * @param showPublishOption show the publishing options
+	 */
+	public ModifyModulesComposite(Composite parent, IWizardHandle wizard, IModule module, boolean showPublishOption) {
+		super(parent, SWT.NONE);
+		this.wizard = wizard;
+		requiredModule = module;
+		this.showPublishOption = showPublishOption;
+		
+		wizard.setTitle(Messages.wizModuleTitle);
+		wizard.setDescription(Messages.wizModuleDescription);
+		wizard.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_SELECT_SERVER));
+		
+		createControl();
+	}
+
+	public void setServer(IServerAttributes server) {
+		if (isVisible())
+			return;
+		
+		// see bug 185875, 205869
+		if (refreshModules == taskModel.getObject(TASK_REFRESH_MODULES) && server == this.server) {
+			if (server == null)
+				return;
+			if (runtime == server.getRuntime()) {
+				if (runtime == null)
+					return;
+				if (runtime instanceof IRuntimeWorkingCopy) {
+					IRuntimeWorkingCopy wc = (IRuntimeWorkingCopy) runtime;
+					if (wc.isDirty() == runtimeDirty)
+						return;
+				} else
+					return;
+			}
+		}
+		
+		refreshModules = taskModel.getObject(TASK_REFRESH_MODULES);
+		this.server = server;
+		if (server == null)
+			runtime = null;
+		else
+			runtime = server.getRuntime();
+		runtimeDirty = false;
+		if (runtime != null) {
+			if (runtime instanceof IRuntimeWorkingCopy) {
+				IRuntimeWorkingCopy wc = (IRuntimeWorkingCopy) runtime;
+				if (wc.isDirty())
+					runtimeDirty = true;
+			}
+		}
+		
+		originalModules = new ArrayList<IModule>();
+		deployed = new ArrayList<IModule>();
+		modules = new ArrayList<IModule>();
+		
+		childModuleMap = new HashMap<ChildModuleMapKey, IModule[]>();
+		
+		if (server == null)
+			return;
+		
+		System.setProperty("J2EEcache", "" + Math.random());
+		
+		// get currently deployed modules
+		IModule[] currentModules = server.getModules();
+		if (currentModules != null) {
+			int size = currentModules.length;
+			for (int i = 0; i < size; i++) {
+				originalModules.add(currentModules[i]);
+				deployed.add(currentModules[i]);
+			}
+		}
+		
+		// add new module
+		requiredModules = null;
+		errorMap = new HashMap<IModule, IStatus>();
+		if (requiredModule != null) {
+			try {
+				IModule[] parents = server.getRootModules(requiredModule, null);
+				if (parents != null && parents.length > 0)
+					requiredModules = parents;
+				else
+					requiredModules = new IModule[] { requiredModule };
+			} catch (CoreException ce) {
+				// ignore
+				//errorMap.put(newModule, ce.getStatus());
+				Trace.trace(Trace.INFO, "A possible server implementation error", ce);
+			} catch (Exception e) {
+				Trace.trace(Trace.WARNING, "Could not find root module", e);
+			}
+		}
+		if (requiredModules != null && !deployed.contains(requiredModules[0]))
+			deployed.add(requiredModules[0]);
+		
+		// get remaining modules
+		IModule[] modules2 = ServerUtil.getModules(server.getServerType().getRuntimeType().getModuleTypes());
+		if (modules2 != null) {
+			int size = modules2.length;
+			for (int i = 0; i < size; i++) {
+				IModule module = modules2[i];
+				if (!deployed.contains(module)) {
+					try {
+						IModule[] parents = server.getRootModules(module, null);
+						if (parents != null) {
+							int size2 = parents.length;
+							for (int j = 0; j < size2; j++) {
+								if (parents[j].equals(module)) {
+									IStatus status = server.canModifyModules(new IModule[] { module }, null, null);
+									if (status != null && !status.isOK())
+										errorMap.put(module, status);
+									modules.add(module);
+								}
+							}
+						}
+					} catch (CoreException ce) {
+						errorMap.put(module, ce.getStatus());
+						modules.add(module);
+					}
+				}
+			}
+		}
+		
+		// build child map
+		Iterator iterator = deployed.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			try {
+				IModule[] children = server.getChildModules(new IModule[] { module }, null);
+				if (children != null && children.length > 0)
+					childModuleMap.put(new ChildModuleMapKey(module), children);
+			} catch (Exception e) {
+				// ignore
+			}
+		}
+		
+		iterator = modules.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			try {
+				IModule[] children = server.getChildModules(new IModule[] { module }, null);
+				if (children != null && children.length > 0)
+					childModuleMap.put(new ChildModuleMapKey(module), children);
+			} catch (Exception e) {
+				// ignore
+			}
+		}
+		
+		// get children recursively one level
+		// put child elements into a different list to avoid concurrent modifications
+		Iterator<ChildModuleMapKey> iterator2 = childModuleMap.keySet().iterator();
+		List<ChildModuleMapKey> list = new ArrayList<ChildModuleMapKey>();
+		while (iterator2.hasNext()) {
+			list.add(iterator2.next());
+		}
+		
+		iterator = list.iterator();
+		while (iterator.hasNext()) {
+			ChildModuleMapKey key = (ChildModuleMapKey) iterator.next();
+			IModule[] children0 = childModuleMap.get(key);
+			if (children0 != null) {
+				int size = children0.length;
+				for (int i = 0; i < size; i++) {
+					int size2 = key.moduleTree.length;
+					IModule[] module2 = new IModule[size2 + 1];
+					System.arraycopy(key.moduleTree, 0, module2, 0, size2);
+					module2[size2] = children0[i];
+					
+					try {
+						IModule[] children = server.getChildModules(module2, null);
+						if (children != null && children.length > 0)
+							childModuleMap.put(new ChildModuleMapKey(module2), children);
+					} catch (Exception e) {
+						// ignore
+					}
+				}
+			}
+		}
+		
+		System.setProperty("J2EEcache", "");
+		
+		updateTaskModel();
+	}
+
+	public void setVisible(boolean b) {
+		if (b) {
+			Display.getDefault().syncExec(new Runnable() {
+				public void run() {
+					if (availableTreeViewer == null || availableTreeViewer.getControl().isDisposed())
+						return;
+					try { // update trees if we can
+						availableTreeViewer.refresh();
+						deployedTreeViewer.refresh();
+						setEnablement();
+					} catch (Exception e) {
+						// ignore
+					}
+				}
+			});
+		}
+		super.setVisible(b);
+	}
+
+	public void setTaskModel(TaskModel model) {
+		this.taskModel = model;
+	}
+
+	/**
+	 * Creates the UI of the page.
+	 */
+	protected void createControl() {
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.numColumns = 3;
+		setLayout(layout);
+		setFont(getParent().getFont());
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(this, ContextIds.MODIFY_MODULES_COMPOSITE);
+		
+		Display display = getDisplay();
+		color = display.getSystemColor(SWT.COLOR_DARK_GRAY);
+		FontData[] fd = getFont().getFontData();
+		int size2 = fd.length;
+		for (int i = 0; i < size2; i++)
+			fd[i].setStyle(SWT.ITALIC);
+		font = new Font(display, fd);
+		addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				font.dispose();
+			}
+		});
+		
+		Label label = new Label(this, SWT.NONE);
+		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING);
+		data.horizontalSpan = 3;
+		label.setLayoutData(data);
+		label.setText(Messages.wizModuleMessage);
+		
+		label = new Label(this, SWT.NONE);
+		label.setText(Messages.wizModuleAvailableList);
+		
+		label = new Label(this, SWT.NONE);
+		label.setText("");
+		
+		label = new Label(this, SWT.NONE);
+		label.setText(Messages.wizModuleDeployedList);
+		
+		Tree availableTree = new Tree(this, SWT.BORDER | SWT.MULTI);
+		data = new GridData(GridData.FILL_BOTH);
+		data.heightHint = 200;
+		data.widthHint = 150;
+		availableTree.setLayoutData(data);
+		
+		availableTreeViewer = new TreeViewer(availableTree);
+		ILabelProvider labelProvider = ServerUICore.getLabelProvider();
+		labelProvider.addListener(new ILabelProviderListener() {
+			public void labelProviderChanged(LabelProviderChangedEvent event) {
+				Object[] obj = event.getElements();
+				if (obj == null)
+					availableTreeViewer.refresh(true);
+				else {
+					obj = ServerUIPlugin.adaptLabelChangeObjects(obj);
+					int size = obj.length;
+					for (int i = 0; i < size; i++)
+						availableTreeViewer.refresh(obj[i], true);
+				}
+			}
+		});
+		availableTreeViewer.setLabelProvider(labelProvider);
+		availableTreeViewer.setContentProvider(new AvailableContentProvider());
+		availableTreeViewer.setComparator(new ViewerComparator() {
+			public int compare(Viewer viewer, Object e1, Object e2) {
+				if (e1 instanceof ModuleServer && e2 instanceof ModuleServer) {
+					ModuleServer s1 = (ModuleServer) e1;
+					ModuleServer s2 = (ModuleServer) e2;
+					return (s1.module[s1.module.length - 1].getName().compareToIgnoreCase(s2.module[s2.module.length - 1].getName()));
+				}
+				
+				return super.compare(viewer, e1, e2);
+			}
+		});
+		availableTreeViewer.setInput(ROOT);
+		
+		availableTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				setEnablement();
+			}
+		});
+		availableTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
+			public void doubleClick(DoubleClickEvent event) {
+				setEnablement();
+				if (add.isEnabled())
+					add(false);
+			}
+		});
+		
+		// slosh buttons
+		Composite comp = new Composite(this, SWT.NONE);
+		data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = 120;
+		comp.setLayoutData(data);
+		
+		layout = new GridLayout();
+		layout.marginWidth = 5;
+		layout.marginHeight = 25;
+		layout.verticalSpacing = 20;
+		comp.setLayout(layout);
+		
+		add = new Button(comp, SWT.PUSH);
+		add.setText(Messages.wizModuleAdd);
+		add.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		add.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				add(false);
+			}
+		});
+		
+		remove = new Button(comp, SWT.PUSH);
+		remove.setText(Messages.wizModuleRemove);
+		remove.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		remove.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				remove(false);
+			}
+		});
+		
+		label = new Label(comp, SWT.NONE);
+		label.setText("");
+		
+		addAll = new Button(comp, SWT.PUSH);
+		addAll.setText(Messages.wizModuleAddAll);
+		addAll.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		addAll.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				add(true);
+			}
+		});
+		
+		removeAll = new Button(comp, SWT.PUSH);
+		removeAll.setText(Messages.wizModuleRemoveAll);
+		removeAll.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		removeAll.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				remove(true);
+			}
+		});
+		
+		Tree deployedTree = new Tree(this, SWT.BORDER | SWT.MULTI);
+		data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = 150;
+		deployedTree.setLayoutData(data);
+		
+		deployedTreeViewer = new TreeViewer(deployedTree) {
+			public void doUpdateItem(Widget widget, Object element, boolean fullMap) {
+				if (widget instanceof TreeItem && color != null) {
+					TreeItem item = (TreeItem) widget;
+					if (element instanceof ModuleServer) {
+						ModuleServer ms = (ModuleServer) element;
+						IModule m = ms.module[ms.module.length-1];
+						if (m.isExternal())
+							item.setForeground(color);
+						else
+							item.setForeground(null);
+						if (!(server instanceof IServer) || ((IServer)server).getModulePublishState(ms.module) != IServer.PUBLISH_STATE_NONE)
+							item.setFont(font);
+						else
+							item.setFont(null);
+					}
+				}
+				super.doUpdateItem(widget, element, fullMap);
+			}
+		};
+		labelProvider = ServerUICore.getLabelProvider();
+		labelProvider.addListener(new ILabelProviderListener() {
+			public void labelProviderChanged(LabelProviderChangedEvent event) {
+				Object[] obj = event.getElements();
+				if (obj == null)
+					deployedTreeViewer.refresh(true);
+				else {
+					int size = obj.length;
+					for (int i = 0; i < size; i++)
+						deployedTreeViewer.refresh(obj[i], true);
+				}
+			}
+		});
+		deployedTreeViewer.setLabelProvider(labelProvider);
+		deployedTreeViewer.setContentProvider(new DeployedContentProvider());
+		deployedTreeViewer.setComparator(new ViewerComparator() {
+			public int compare(Viewer viewer, Object e1, Object e2) {
+				if (e1 instanceof ModuleServer && e2 instanceof ModuleServer) {
+					ModuleServer s1 = (ModuleServer) e1;
+					ModuleServer s2 = (ModuleServer) e2;
+					return (s1.module[s1.module.length - 1].getName().compareToIgnoreCase(s2.module[s2.module.length - 1].getName()));
+				}
+				
+				return super.compare(viewer, e1, e2);
+			}
+		});
+		deployedTreeViewer.setInput(ROOT);
+		
+		deployedTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				setEnablement();
+			}
+		});
+		deployedTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
+			public void doubleClick(DoubleClickEvent event) {
+				setEnablement();
+				if (remove.isEnabled())
+					remove(false);
+			}
+		});
+		
+		if (showPublishOption) {
+			final Button publish = new Button(this, SWT.CHECK);
+			publish.setText(Messages.wizModulePublishImmediately);
+			data = new GridData(GridData.FILL_HORIZONTAL);
+			data.horizontalSpan = 3;
+			publish.setLayoutData(data);
+			
+			publishImmediately = ServerUIPlugin.getPreferences().getPublishOnAddRemoveModule();
+			publish.setSelection(publishImmediately);
+			publish.addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent event) {
+					publishImmediately = publish.getSelection();
+				}
+			});
+		}
+		
+		setEnablement();
+		availableTree.setFocus();
+		
+		Dialog.applyDialogFont(this);
+	}
+
+	protected ModuleServer[] getAvailableSelection() {
+		IStructuredSelection sel = (IStructuredSelection) availableTreeViewer.getSelection();
+		if (sel.isEmpty())
+			return new ModuleServer[0];
+			
+		ModuleServer []  mss = new ModuleServer[sel.size()];
+		System.arraycopy(sel.toArray(), 0, mss, 0, sel.size());
+		return mss;
+	}
+
+	protected ModuleServer[] getDeployedSelection() {
+		IStructuredSelection sel = (IStructuredSelection) deployedTreeViewer.getSelection();
+		if (sel.isEmpty())
+			return new ModuleServer[0];
+		
+		ModuleServer []  mss = new ModuleServer[sel.size()];
+		System.arraycopy(sel.toArray(), 0, mss, 0, sel.size());
+		return mss;
+	}
+
+	protected static IModule getModule(ModuleServer ms) {
+		if (ms == null)
+			return null;
+		IModule[] modules2 = ms.module;
+		return modules2[modules2.length - 1];
+	}
+
+	protected static IModule[] getModules(ModuleServer[] ms) {
+		if (ms == null)
+			return null;
+		IModule[] modules2 = new IModule[ms.length];
+		for (int i = 0; i < ms.length; i++)
+			modules2[i] = getModule(ms[i]);
+		
+		return modules2;
+	}
+
+	protected void setEnablement() {
+		wizard.setMessage(null, IMessageProvider.NONE);
+		
+		int count = 0;
+		if (requiredModules != null) {
+			// count how many of requiredModules are deployed
+			int size = requiredModules.length;
+			for (int i = 0; i < size; i++) {
+				if (deployed.contains(requiredModules[i]))
+					count++;
+			}
+		}
+		
+		// give error if there are more than one possible required modules and none are
+		// added to the server
+		isComplete = true;
+		if (requiredModules != null && requiredModules.length > 1 && count == 0) {
+			String s = "";
+			int size = requiredModules.length;
+			for (int i = 0; i < size; i++) {
+				if (i > 0)
+					s += " | ";
+				s += requiredModules[i].getName();
+			}
+			wizard.setMessage(NLS.bind(Messages.wizModuleRequiredModules, s), IMessageProvider.ERROR);
+			isComplete = false;
+		}
+		
+		// selection specific messages
+		ModuleServer[] ms = getAvailableSelection();
+		if (ms == null ||  ms.length == 0) {
+			add.setEnabled(false);
+		} else {
+			boolean enabled = false;
+			// iterate through selection, if we find at least ONE module that can't be added, exit the loop
+			for (int i = 0; i < ms.length; i++) {
+				IModule module = getModule(ms[i]);
+				if (module != null) {
+					try {
+						IStatus status = errorMap.get(module);
+						if (modules.contains(module)) {
+							if (status == null )
+								enabled = true;
+							else if (status.getSeverity() == IStatus.ERROR) {
+								// this module can't be added because has errors, exit the loop
+								enabled = false;
+								wizard.setMessage(status.getMessage(), IMessageProvider.ERROR);
+								break;
+							} else if (status.getSeverity() == IStatus.WARNING){
+								enabled = true;
+								wizard.setMessage(status.getMessage(), IMessageProvider.WARNING);
+							}
+							else if (status.getSeverity() == IStatus.INFO){
+								enabled = true;
+								wizard.setMessage(status.getMessage(), IMessageProvider.INFORMATION);
+							}
+						}
+						else{
+							// at least ONE module from the selection can't be added, exit the loop   
+							enabled = false;
+							break;
+						}
+					} catch (Exception e) {
+						Trace.trace(Trace.INFO,"Unable to handle error map for module:" + module); 
+					}
+				}
+			}
+			add.setEnabled(enabled);
+		}
+		addAll.setEnabled(modules.size() > 0);
+		
+		ms = getDeployedSelection();
+		if (ms == null ||  ms.length == 0) {
+			remove.setEnabled(false);
+		} else {
+			boolean enabled = false;
+			// iterate through selection, if we find at least ONE module that can't be added, exit the loop
+			for (int i = 0; i < ms.length; i++) {
+				IModule module = getModule(ms[i]);
+				if (module != null && deployed.contains(module)) {
+					// provide error about removing required single module
+					// required modules can't be removed
+					if (requiredModules != null){
+						if (requiredModules.length == 1 && requiredModules[0].equals(module)) {
+							// this is a required module and can't be removed, exit the loop
+							wizard.setMessage(NLS.bind(Messages.wizModuleRequiredModule, module.getName()), IMessageProvider.ERROR);
+							enabled = false;
+							break;
+						}
+					}
+					else 
+						enabled = true;
+				}
+				else{
+					// this module is not found in the 'deployed' array, the module might be a child
+					// at least ONE module from the selection can't be removed, exit the loop
+					enabled = false;
+					break;
+				}
+			}
+			remove.setEnabled(enabled);
+		}
+	
+		if (requiredModules == null)
+			removeAll.setEnabled(deployed.size() > 0);
+		else
+			removeAll.setEnabled(deployed.size() > 1);
+	}
+
+	protected void add(boolean all) {
+		if (all) {
+			IModule[] modules2 = new IModule[modules.size()];
+			modules.toArray(modules2);
+			moveAll(modules2, true);
+		} else
+			moveAll(getModules(getAvailableSelection()), true);
+		updateTaskModel();
+	}
+
+	protected void remove(boolean all) {
+		if (all) {
+			// pick one of the required modules to keep
+			IModule keep = null;
+			if (requiredModules != null) {
+				int size2 = requiredModules.length;
+				for (int i = 0; i < size2; i++) {
+					if (keep == null && deployed.contains(requiredModules[i]))
+						keep = requiredModules[i];
+				}
+			}
+			
+			List<IModule> list = new ArrayList<IModule>();
+			list.addAll(deployed);
+			list.remove(keep);
+			
+			IModule[] modules2 = new IModule[list.size()];
+			list.toArray(modules2);
+			
+			moveAll(modules2, false);
+		} else
+			moveAll(getModules(getDeployedSelection()), false);
+		updateTaskModel();
+	}
+
+	protected void moveAll(IModule[] mods, boolean add2) {
+		int size = mods.length;
+		List<IModule> list = new ArrayList<IModule>();
+		for (int i = 0; i < size; i++) {
+			IStatus status = errorMap.get(mods[i]);
+			
+			if (status == null && !list.contains(mods[i]))
+				list.add(mods[i]);
+		}
+		
+		Iterator iterator = list.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			ModuleServer ms = new ModuleServer(null, new IModule[] { module });
+			if (add2) {
+				modules.remove(module);
+				deployed.add(module);
+				availableTreeViewer.remove(ms);
+				deployedTreeViewer.add(ROOT, ms);
+			} else {
+				modules.add(module);
+				deployed.remove(module);
+				availableTreeViewer.add(ROOT, ms);
+				deployedTreeViewer.remove(ms);
+			}
+		}
+
+		setEnablement();
+	}
+
+	protected void updateTaskModel() {
+		if (taskModel == null)
+			return;
+
+		taskModel.putObject(TaskModel.TASK_MODULES, getModuleMap());
+		wizard.update();
+	}
+
+	public List<IModule> getModulesToRemove() {
+		List<IModule> list = new ArrayList<IModule>();
+		Iterator iterator = originalModules.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			if (!deployed.contains(module))
+				list.add(module);
+		}
+		return list;
+	}
+
+	public List<IModule> getModulesToAdd() {
+		List<IModule> list = new ArrayList<IModule>();
+		Iterator iterator = deployed.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			if (!originalModules.contains(module))
+				list.add(module);
+		}
+		return list;
+	}
+	
+	private void addChildMap(List<IModule[]> map, IModule[] parents, IModule[] children) {
+		if (children == null)
+			return;
+		
+		int size = children.length;
+		for (int i = 0; i < size; i++) {
+			IModule module = children[i];
+			
+			int size2 = parents.length;
+			IModule[] modules2 = new IModule[size2 + 1];
+			System.arraycopy(parents, 0, modules2, 0, size2);
+			modules2[size2] = module;
+			map.add(modules2);
+			
+			IModule[] children2 = childModuleMap.get(new ChildModuleMapKey(module));
+			if (children2 != null)
+				addChildMap(map, modules2, children2);
+		}
+	}
+
+	public List getModuleMap() {
+		final List<IModule[]> map = new ArrayList<IModule[]>();
+	
+		Iterator iterator = deployed.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			IModule[] moduleTree = new IModule[] { module };
+			map.add(moduleTree);
+			IModule[] children = childModuleMap.get(new ChildModuleMapKey(module));
+			if (children != null)
+				addChildMap(map, moduleTree, children);
+		}
+		
+		return map;
+	}
+
+	public boolean isComplete() {
+		return isComplete;
+	}
+
+	public boolean shouldPublishImmediately() {
+		return publishImmediately;
+	}
+}
\ No newline at end of file