CVS structure renamed. org.eclipse.wtp.* has been moved to org.eclipse.*
diff --git a/plugins/org.eclipse.wst.server.core/.classpath b/plugins/org.eclipse.wst.server.core/.classpath
new file mode 100644
index 0000000..cf5d302
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="servercore/"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.wst.server.core/.cvsignore b/plugins/org.eclipse.wst.server.core/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/plugins/org.eclipse.wst.server.core/.options b/plugins/org.eclipse.wst.server.core/.options
new file mode 100644
index 0000000..3f8479c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/.options
@@ -0,0 +1,7 @@
+# Debugging options for the org.eclipse.wst.server.core plugin
+
+# Turn on general debugging
+org.eclipse.wst.server.core/debug=false
+
+# Prints out values
+org.eclipse.wst.server.core/resources=false
diff --git a/plugins/org.eclipse.wst.server.core/.project b/plugins/org.eclipse.wst.server.core/.project
new file mode 100644
index 0000000..bf1e7ef
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.server.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.core/build.properties b/plugins/org.eclipse.wst.server.core/build.properties
new file mode 100644
index 0000000..a0fb824
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/build.properties
@@ -0,0 +1,10 @@
+bin.includes = plugin.xml,\
+               *.jar,\
+               plugin.properties,\
+               servercore.jar,\
+               .options
+jars.compile.order = 
+src.includes = schema/,\
+               build.properties
+source.servercore.jar = servercore/
+output.servercore.jar = bin/
diff --git a/plugins/org.eclipse.wst.server.core/plugin.properties b/plugins/org.eclipse.wst.server.core/plugin.properties
new file mode 100644
index 0000000..3345e6f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/plugin.properties
@@ -0,0 +1,140 @@
+pluginName=Server Core
+providerName=IBM
+
+extensionPointServerStartup=Server Startup
+extensionPointModuleKinds=Module Types
+extensionPointRuntimeTypes=Runtime Types
+extensionPointRuntimeTargetHandler=Runtime Target Handler
+extensionPointRuntimeLocator=Runtime Locator
+extensionPointServerTypes=Server Types
+extensionPointServerConfigurationTypes=Server Configuration Types
+extensionPointServerLocator=Server Locator
+extensionPointPublishManager=Publish Manager
+extensionPointModuleFactories=Module Factories
+extensionPointModuleObjectAdapters=Module Object Adapters
+extensionPointLaunchableAdapters=Launchable Adapters
+extensionPointClients=Clients
+extensionPointServerTasks=Server Tasks
+extensionPointModuleTasks=Module Tasks
+extensionPointServerMonitors=Server Monitors
+
+# --------------- Tasks (progress monitors) ---------------
+
+# Creating default server and server configuration
+createServerProjectTask=Creating server project.
+createDefaultServerTask=Creating server.
+createDefaultServerConfigurationTask=Creating server configuration.
+
+# Modifying and searching for servers
+setServerConfigurationTask=Setting the configuration of {0} to {1}...
+removingServerConfigurationTask=Removing the configuration from {0}...
+getDefaultServerTask=Searching for a default server...
+getProjectServerInstanceTask=Locating a server...
+
+configurationUpdateOk=Server configuration updated successfully.
+serverUpdateOk=Server updated sucessfully.
+
+# General tasks
+copyingTask=Copying from {0} to {1}
+unZippingTask=Unzipping {0}
+expandingTask=Expanding {0}
+savingTask=Saving {0}
+deletingTask=Deleting {0}
+loadingTask=Loading {0}
+copyingTask=File copied successfully to {0}
+
+taskCancelled=Operation cancelled.
+taskPerforming=Performing Tasks
+taskPublishing=Publishing: {0}
+
+publishingTask=Publishing to {0}...
+publishingStatus=Publishing status
+publishingStart=Connecting to server
+publishingStop=Disconnecting from server
+
+publishingPublishFolder=Creating folder {0}
+publishingPublishFile=Publishing {0}
+publishingDeleteFolder=Removing folder {0}
+publishingDeleteFile=Deleting {0}
+publishingProject=Publishing: {0}
+publishingConfiguration=Publishing configuration: {0}
+
+publishingCancelled=Publishing cancelled
+
+# --------------- Misc UI ---------------
+
+# Server launch configuration
+serverLaunchConfigurationType=Server
+
+# Server builder
+builderName=Server Builder
+
+# Server project nature
+serverProjectNatureTitle=Server Project
+
+# Error Messages
+errorUnconfiguredServer=Unable to run the server because it does not have a valid configuration.
+errorCloseEditor=The action could not be completed because there is an open editor. Close the {0} editor and try again.
+errorNull=Could not perform the action on a null object.
+errorLaunch=Cannot start the server.
+errorInvalidServer=The server is not valid.
+errorServerAlreadyRunning=Cannot start the server because it is already running.
+errorServerStartFailed=The server named {0} did not start correctly. Check the Console for error messages.
+errorNoServer=No server can be found to run this project.
+errorPublishing=Could not publish to the server.
+errorNoConfiguration=The server has no configuration.
+errorPublishFailed=Errors occurred during publishing.
+errorRunOnServer=Running resource on server.
+errorRunOnServerFailed=Unable to run on server.
+errorLoading=Error loading from {0}.
+errorSaving=Could not save to {0}.
+errorMissingConfiguration=Server configuration is missing - See Task view
+errorMissingConfigurationTask=Server {0} is missing it's configuration.
+errorMissingProject=Project {0} is missing - See Task view
+errorMissingProjectTask=Server configuration {0} refers to a missing project {1}.
+errorCopyingFile=Error copying file to {0}: {1}
+errorModifyingConfiguration=Error modifying server configuration: {0}.
+errorModifyingServer=Error modifying server: {0}.
+errorCouldNotCreateServerProject=Could not create server project.
+errorCouldNotCreateServerProjectStatus=Could not create server project: {0}.
+errorNoDefaultServer=A default server could not be automatically created.
+errorNoDefaultServerParent=Could not find anything to deploy to the default server.
+errorDefaultServerInvalid=Could not deploy to the default server.
+errorModuleRestartFailed=Could not restart the module.
+
+errorConfigurationUpdate=Could not update the server configuration: {0}
+errorServerUpdate=Could not update the server: {0}
+
+# Info messages
+serverProjectCreated=Server project created successfully.
+infoNoPublishingNecessary=Publishing was not necessary.
+infoPublishSuccess=Published finished successfully.
+
+# Default server creation names
+# {0} will be replaced by a number if the given name is already being used
+defaultServerProjectName=Servers{0}
+defaultRuntimeName={0}
+defaultRuntimeName2={0} ({1})
+defaultServerName={0} @ {1}
+defaultServerName2={0} @ {1} ({2})
+defaultServerName3={0}
+defaultServerName4={0} ({1})
+defaultServerConfigurationName={0}
+defaultServerConfigurationName2={0} ({1})
+
+# Used when a name can't be found
+elementUnknownName=<unknown>
+defaultVendor=Basic
+defaultVersion=Basic
+defaultCategory=Basic
+moduleTypeUnknown=Unknown module
+
+# Publishers
+publisherFullName=Publish all
+publisherFullDescription=Publishes all resources to the server, regardless of whether they have changed. No resources are deleted from the server.
+publisherSmartName=Smart publish
+publisherSmartDescription=Intelligently publishes only modified resources to the server. Deletes all resources that no longer exist in the workspace.
+
+# null launchable
+nullLaunchableClient=Do nothing
+nullLaunchableClientDescription=Do not launch anything after starting the server.
diff --git a/plugins/org.eclipse.wst.server.core/plugin.xml b/plugins/org.eclipse.wst.server.core/plugin.xml
new file mode 100644
index 0000000..11e2dc3
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/plugin.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+
+<plugin id="org.eclipse.wst.server.core"
+  name="%pluginName"
+  version="3.0.0"
+  provider-name="%providerName"
+  class="org.eclipse.wst.server.core.internal.ServerPlugin">
+
+  <requires>
+    <import plugin="org.eclipse.core.runtime" version="3.0.0" match="equivalent"/>
+    <import plugin="org.eclipse.core.resources" version="3.0.0" match="equivalent"/>
+    <import plugin="org.eclipse.debug.core" version="3.0.0" match="equivalent"/>
+  </requires>
+
+  <runtime>
+    <library name="servercore.jar">
+      <export name="*"/>
+      <packages prefixes="org.eclipse.wst.server.core"/>
+    </library>
+  </runtime>
+
+  <extension-point id="startup" name="%extensionPointServerStartup" schema="schema/startup.exsd"/>
+  <extension-point id="moduleKinds" name="%extensionPointModuleKinds" schema="schema/moduleKinds.exsd"/>
+  <extension-point id="runtimeTypes" name="%extensionPointRuntimeTypes" schema="schema/runtimeTypes.exsd"/>
+  <extension-point id="runtimeTargetHandlers" name="%extensionPointRuntimeTargetHandlers" schema="schema/runtimeTargetHandlers.exsd"/>
+  <extension-point id="runtimeLocators" name="%extensionPointRuntimeLocators" schema="schema/runtimeLocators.exsd"/>
+  <extension-point id="serverTypes" name="%extensionPointServerTypes" schema="schema/serverTypes.exsd"/>
+  <extension-point id="serverLocators" name="%extensionPointServerLocators" schema="schema/serverLocators.exsd"/>
+  <extension-point id="serverConfigurationTypes" name="%extensionPointServerConfigurationTypes" schema="schema/serverConfigurationTypes.exsd"/>
+  <extension-point id="publish" name="%extensionPointPublishManager" schema="schema/publishManager.exsd"/>
+  <extension-point id="moduleFactories" name="%extensionPointModuleFactories" schema="schema/moduleFactories.exsd"/>
+  <extension-point id="moduleObjectAdapters" name="%extensionPointModuleObjectAdapters" schema="schema/moduleObjectAdapters.exsd"/>
+  <extension-point id="launchableAdapters" name="%extensionPointLaunchableAdapters" schema="schema/launchableAdapters.exsd"/>
+  <extension-point id="clients" name="%extensionPointClients" schema="schema/clients.exsd"/>
+  <extension-point id="serverTasks" name="%extensionPointServerTasks" schema="schema/serverTasks.exsd"/>
+  <extension-point id="moduleTasks" name="%extensionPointModuleTasks" schema="schema/moduleTasks.exsd"/>
+  <extension-point id="serverMonitors" name="%extensionPointServerMonitors" schema="schema/serverMonitors.exsd"/>
+
+  <extension point="org.eclipse.core.resources.natures"
+     id="nature"
+     name="%serverProjectNatureTitle">
+     <runtime>
+        <run class="org.eclipse.wst.server.core.internal.ServerProjectNature">
+        </run>
+     </runtime>
+  </extension>
+
+  <extension point="org.eclipse.core.resources.builders"
+     id="builder"
+     name="%builderName">
+     <builder>
+        <run class="org.eclipse.wst.server.core.internal.ServerBuilder">
+        </run>
+     </builder>
+  </extension>
+
+  <extension point="org.eclipse.wst.server.core.publish">
+     <publish
+           name="%publisherFullName"
+           description="%publisherFullDescription"
+           class="org.eclipse.wst.server.core.internal.FullPublisher"
+           id="org.eclipse.wst.server.core.publish.full">
+     </publish>
+     <publish
+           name="%publisherSmartName"
+           description="%publisherSmartDescription"
+           class="org.eclipse.wst.server.core.internal.SmartPublisher"
+           id="org.eclipse.wst.server.core.publish.smart">
+     </publish>
+  </extension>
+  
+  <extension point="org.eclipse.wst.server.core.moduleKinds">
+    <moduleKind
+       id="*"
+       name="%moduleTypeUnknown"/>
+  </extension>
+
+  <extension point="org.eclipse.wst.server.core.moduleFactories">
+     <moduleFactory
+           projects="false"
+           class="org.eclipse.wst.server.core.util.MissingModuleFactoryDelegate"
+           id="org.eclipse.wst.server.core.missingModuleFactory">
+     </moduleFactory>
+  </extension>
+
+   <extension point="org.eclipse.wst.server.core.clients">
+     <client
+           id="org.eclipse.wst.server.core.client.null"
+           name="%nullLaunchableClient"
+           description="%nullLaunchableClientDescription"
+           class="org.eclipse.wst.server.core.util.NullLaunchableClient">
+     </client>
+  </extension>
+</plugin>
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/schema/clients.exsd b/plugins/org.eclipse.wst.server.core/schema/clients.exsd
new file mode 100644
index 0000000..71277b1
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/clients.exsd
@@ -0,0 +1,129 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="clients" name="Clients"/>

+      </appInfo>

+      <documentation>

+         This extension point provides a way to launch a client for a specific type of resource that is being run on a server.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="client" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="client">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IClientDelegate&lt;/samp&gt;.
+Clieint instances of this type will delegate to instances of this class to launch.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  a translatable name used to identify the client

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="description" type="string">

+            <annotation>

+               <documentation>

+                  a translatable description of this client

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a client extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+&lt;extension point=&quot;org.eclipse.wst.server.core.clients&quot;&gt;
+  &lt;client
+    id=&quot;com.example.clients&quot;
+    name=&quot;%clientName&quot;
+    description=&quot;%clientDescription&quot;
+    class=&quot;com.example.ExampleClient&quot;/&gt;
+&lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IClientDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/launchableAdapters.exsd b/plugins/org.eclipse.wst.server.core/schema/launchableAdapters.exsd
new file mode 100644
index 0000000..3e3eae3
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/launchableAdapters.exsd
@@ -0,0 +1,113 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="launchableAdapters" name="Launchable Adapters"/>

+      </appInfo>

+      <documentation>

+         This extension point provides a way to invoke code during the server core plugin startup. Use sparingly.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="launchableAdapter" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="launchableAdapter">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;ILaunchableAdapterDelegate&lt;/samp&gt;.
+Launchable adapter instances of this type will delegate to instances of this class.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a launchable adapter extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+  &lt;extension point=&quot;org.eclipse.wst.server.core.launchableAdapters&quot;&gt;
+     &lt;launchableAdapter
+        id=&quot;com.example.launchableAdapter&quot;
+        class=&quot;com.example.ExampleLaunchableAdapterDelegate&quot;/&gt;
+  &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.ILaunchableAdapterDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/moduleFactories.exsd b/plugins/org.eclipse.wst.server.core/schema/moduleFactories.exsd
new file mode 100644
index 0000000..d345cff
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/moduleFactories.exsd
@@ -0,0 +1,143 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="moduleFactories" name="Module Factories"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to provide a factory for modules that can be used by servers.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="moduleFactory" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="moduleFactory">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+            <element ref="moduleType" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IModuleFactoryDelegate&lt;/samp&gt;.
+Module factory instances of this type will delegate to instances of this class.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="projects" type="boolean">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="index" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="moduleType">

+      <complexType>

+         <attribute name="types" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="versions" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a module factory extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IModuleFactoryDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/moduleKinds.exsd b/plugins/org.eclipse.wst.server.core/schema/moduleKinds.exsd
new file mode 100644
index 0000000..c21f43c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/moduleKinds.exsd
@@ -0,0 +1,110 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="moduleKinds" name="Module Kinds"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to provide a new module type.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="moduleKind" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="moduleKind">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable name used to identify the module type

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a module type extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+  &lt;extension point=&quot;org.eclipse.wst.server.core.moduleTypes&quot;&gt;
+    &lt;moduleType
+       id=&quot;com.example&quot;
+       name=&quot;%moduleTypeName&quot;
+       description=&quot;%moduleTypeDescription&quot;/&gt;
+  &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/moduleObjectAdapters.exsd b/plugins/org.eclipse.wst.server.core/schema/moduleObjectAdapters.exsd
new file mode 100644
index 0000000..c866b64
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/moduleObjectAdapters.exsd
@@ -0,0 +1,116 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="moduleObjectAdapters" name="Module Object Adapters"/>

+      </appInfo>

+      <documentation>

+         This extension point provides a way to invoke code during the server core plugin startup. Use sparingly.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="moduleObjectAdapter" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="moduleObjectAdapter">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IModuleObjectAdapterDelegate&lt;/samp&gt;.
+Module object adapter instances of this type will delegate to instances of this class.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="objectClass" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a module object adapter extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IModuleObjectAdapterDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/moduleTasks.exsd b/plugins/org.eclipse.wst.server.core/schema/moduleTasks.exsd
new file mode 100644
index 0000000..c7686cd
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/moduleTasks.exsd
@@ -0,0 +1,116 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="moduleTasks" name="Module Tasks"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to provide a task that can/should be run on modules before server publishing, startup, etc.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="moduleTask" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="moduleTask">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IModuleTaskDelegate&lt;/samp&gt;.
+Module task instances of this type will delegate to instances of this class.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="typeIds" type="string">

+            <annotation>

+               <documentation>

+                  a comma separated list of server type ids that this task may apply to. Used for memory &amp; performance reasons

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a module task extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IModuleTaskDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/publishManager.exsd b/plugins/org.eclipse.wst.server.core/schema/publishManager.exsd
new file mode 100644
index 0000000..aca4811
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/publishManager.exsd
@@ -0,0 +1,122 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="publish" name="Publish"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to provide new publish managers.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="publish" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="publish">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IPublisher&lt;/samp&gt;

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IPublishManagerDelegate"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  a translatable name used to identify the publisher

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="description" type="string">

+            <annotation>

+               <documentation>

+                  a translatable description of the publisher

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a publish extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IPublishManagerDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/runtimeLocator.exsd b/plugins/org.eclipse.wst.server.core/schema/runtimeLocator.exsd
new file mode 100644
index 0000000..aab223a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/runtimeLocator.exsd
@@ -0,0 +1,124 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="runtimeLocator" name="Runtime Locator"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to locate new runtimes on the local machine.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="runtimeLocator" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="runtimeLocator">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable name used to identify the locator

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="description" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable description of the locator

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IRuntimeLocatorDelegate&lt;/samp&gt;.
+Runtime locator instances of this type will delegate to instances of this class.

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a runtime locator extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+  &lt;extension point=&quot;org.eclipse.wst.server.core.runtimeLocators&quot;&gt;
+    &lt;runtimeLocator
+       id=&quot;com.example.locator&quot;
+       name=&quot;%runtimeLocatorName&quot;
+       description=&quot;%runtimeLocatorDescription&quot;
+       class=&quot;com.example.ExampleRuntimeLocator&quot;/&gt;
+  &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IRuntimeLocatorDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/runtimeTargetHandlers.exsd b/plugins/org.eclipse.wst.server.core/schema/runtimeTargetHandlers.exsd
new file mode 100644
index 0000000..b70a429
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/runtimeTargetHandlers.exsd
@@ -0,0 +1,128 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="runtimeTypes" name="Runtime Types"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to provide a new runtime target handler. Runtime target handlers are called whenever a runtime target is added or removed from a project. They can be used to switch Java classpaths, setup default resources, etc.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="runtimeTargetHandler" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="runtimeTargetHandler">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="runtimeTypeIds" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a comma separated list of runtime type ids that this handler may support. Used for memory &amp; performance reasons

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IRuntimeTargetHandlerDelegate&lt;/samp&gt;.
+Runtime target handler instances of this type will delegate to instances of this class.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="order" type="string">

+            <annotation>

+               <documentation>

+                  an integer order used to sort handlers relative to each other

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a runtime target handler extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+  &lt;extension point=&quot;org.eclipse.wst.server.core.runtimeTargetHandlers&quot;&gt;
+     &lt;runtimeTargetHandler
+        id=&quot;com.example.runtimeTargetHandler&quot;
+        runtimeTypeIds=&quot;com.example.runtime, com.example2.*&quot;
+        class=&quot;com.example.ExampleRuntimeTargetHandler&quot;/&gt;
+   &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IRuntimeTargetHandlerDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/runtimeTypes.exsd b/plugins/org.eclipse.wst.server.core/schema/runtimeTypes.exsd
new file mode 100644
index 0000000..3b13299
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/runtimeTypes.exsd
@@ -0,0 +1,189 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="runtimeTypes" name="Runtime Types"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to provide a new runtime type.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="runtimeType" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="runtimeType">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+            <element ref="moduleType" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable name used to identify the runtime type

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="description" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable description of the runtime type

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="vendor" type="string">

+            <annotation>

+               <documentation>

+                  a translatable vendor name

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="version" type="string">

+            <annotation>

+               <documentation>

+                  a translatable version number

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="vendorId" type="string">

+            <annotation>

+               <documentation>

+                  an id used to identify the vendor

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IRuntimeDelegate&lt;/samp&gt;.
+Runtime instances of this type will delegate to instances of this class.

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="workingCopyClass" type="string">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IRuntimeWorkingCopyDelegate&lt;/samp&gt;.
+Runtime instances of this type will delegate to instances of this class.

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="order" type="string">

+            <annotation>

+               <documentation>

+                  an integer order specifying the relative importance of this runtime

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="moduleType">

+      <complexType>

+         <attribute name="types" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a comma separated list of the module types that this runtime supports

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="versions" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a comma separated list of the module versions that this runtime supports

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a runtime type extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+  &lt;extension point=&quot;org.eclipse.wst.server.core.runtimeTypes&quot;&gt;
+    &lt;runtimeType
+       id=&quot;com.example.runtime&quot;
+       name=&quot;%runtimeTypeName&quot;
+       description=&quot;%runtimeTypeDescription&quot;
+       vendor=&quot;%runtimeTypeVendor&quot;
+       version=&quot;1.0&quot;
+       class=&quot;com.example.ExampleRuntimeDelegate&quot;
+       workingCopyClass=&quot;com.example.ExampleRuntimeWorkingCopyDelegate&quot;&gt;
+       &lt;moduleType
+         types=&quot;j2ee.web&quot;
+         versions=&quot;1.2, 1.3, 1.4&quot;/&gt;
+    &lt;/runtimeType&gt;
+  &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IRuntimeDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/serverConfigurationTypes.exsd b/plugins/org.eclipse.wst.server.core/schema/serverConfigurationTypes.exsd
new file mode 100644
index 0000000..5d014fc
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/serverConfigurationTypes.exsd
@@ -0,0 +1,151 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="serverConfigurationTypes" name="Server Configuration Types"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to provide a new server configuration type.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="serverConfigurationType"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="serverConfigurationType">

+      <complexType>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable name used to identify this server configuration

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="description" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable description of this server configuration type

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IServerConfigurationDelegate&lt;/samp&gt;.
+Server configuration instances of this type will delegate to instances of this class.

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="isFolder" type="string">

+            <annotation>

+               <documentation>

+                  true if the configuration requires it&apos;s own data in a folder

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="workingCopyClass" type="string">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IServerConfigurationWorkingCopyDelegate&lt;/samp&gt;.
+Server configuration instances of this type will delegate to instances of this class.

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="order" type="string">

+            <annotation>

+               <documentation>

+                  an integer order specifying the relative importance of this server configuration type

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="importExtensions" type="string">

+            <annotation>

+               <documentation>

+                  a comma separated list of import extensions (e.g. &quot;xml&quot;, &quot;cfg&quot;) that this server configuration could be imported using

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a server configuration type extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+  &lt;extension point=&quot;org.eclipse.wst.server.core.serverConfigurationTypes&quot;&gt;
+     &lt;serverConfigurationType
+       id=&quot;com.example.serverConfiguration&quot;
+       name=&quot;%serverConfigurationTypeName&quot;
+       description=&quot;%serverConfigurationTypeDescription&quot;
+       isFolder=&quot;true&quot;
+       class=&quot;com.example.ExampleServerConfigurationDelegate&quot;
+       workingCopyClass=&quot;com.example.ExampleServerConfigurationWorkingCopyDelegate&quot;&gt;
+     &lt;/serverConfigurationType&gt;
+   &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IServerConfigurationDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/serverLocator.exsd b/plugins/org.eclipse.wst.server.core/schema/serverLocator.exsd
new file mode 100644
index 0000000..c0b0a93
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/serverLocator.exsd
@@ -0,0 +1,131 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="serverLocator" name="Server Locator"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to locate new servers on the local or remote machines.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="serverLocator" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="serverLocator">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable name used to identify the locator

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="description" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable description of the locator

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IRuntimeLocatorDelegate&lt;/samp&gt;.
+Runtime locator instances of this type will delegate to instances of this class.

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="hosts" type="string">

+            <annotation>

+               <documentation>

+                  local and/or remote

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a server locator extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+  &lt;extension point=&quot;org.eclipse.wst.server.core.serverLocators&quot;&gt;
+    &lt;serverLocator
+       id=&quot;com.example.locator&quot;
+       name=&quot;%serverLocatorName&quot;
+       description=&quot;%serverLocatorDescription&quot;
+       class=&quot;com.example.ExampleServerLocator&quot;/&gt;
+  &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IServerLocatorDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/serverMonitors.exsd b/plugins/org.eclipse.wst.server.core/schema/serverMonitors.exsd
new file mode 100644
index 0000000..f766cd5
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/serverMonitors.exsd
@@ -0,0 +1,122 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="serverMonitor" name="Server Monitor"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to provide a new monitor for servers.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="monitor" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="monitor">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  a translatable name used to identify this monitor

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="description" type="string">

+            <annotation>

+               <documentation>

+                  a translatable description of this monitor

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IMonitor&lt;/samp&gt;

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a server monitor extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IServerMonitorDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/serverTasks.exsd b/plugins/org.eclipse.wst.server.core/schema/serverTasks.exsd
new file mode 100644
index 0000000..3a6009b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/serverTasks.exsd
@@ -0,0 +1,116 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="serverTasks" name="Server Tasks"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to provide a task that can/should be run before server publishing, startup, etc.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="serverTask" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="serverTask">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IServerTaskDelegate&lt;/samp&gt;.
+Server task instances of this type will delegate to instances of this class.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="typeIds" type="string">

+            <annotation>

+               <documentation>

+                  a comma separated list of server type ids that this task may apply to. Used for memory &amp; performance reasons

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a server task extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IServerTaskDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/serverTypes.exsd b/plugins/org.eclipse.wst.server.core/schema/serverTypes.exsd
new file mode 100644
index 0000000..057b0c8
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/serverTypes.exsd
@@ -0,0 +1,222 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="serverTypes" name="Server Types"/>

+      </appInfo>

+      <documentation>

+         This extension point is used to provide support for a new server type.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="serverType"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="serverType">

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="runtimeTypeId" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable name used to identify this server type

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="description" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a translatable description of this server type

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IServerDelegate&lt;/samp&gt;.
+Server instances of this type will delegate to instances of this class.

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="workingCopyClass" type="string">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IServerWorkingCopyDelegate&lt;/samp&gt;.
+Server instances of this type will delegate to instances of this class.

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="configurationTypeId" type="string">

+            <annotation>

+               <documentation>

+                  the id of the server configuration type that this server requires

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="startable" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="order" type="string">

+            <annotation>

+               <documentation>

+                  an integer order specifying the relative importance of this server type

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="launchConfigId" type="string">

+            <annotation>

+               <documentation>

+                  the launch configuration id for the launch configuration that is able to start this server

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="hosts" type="string">

+            <annotation>

+               <documentation>

+                  local and/or remote

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="runtime" type="string">

+            <annotation>

+               <documentation>

+                  &quot;true&quot; if this server requires a runtime, &quot;false&quot; otherwise

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="monitorable" type="boolean">

+            <annotation>

+               <documentation>

+                  &quot;true&quot; if the class implements IMonitorableServer, and &quot;false&quot; otherwise

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="launchModes" type="string">

+            <annotation>

+               <documentation>

+                  the launch modes that this server supports

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="testEnvironment" type="string">

+            <annotation>

+               <documentation>

+                  &quot;true&quot; if this server should not be creatable unless there is an existing runtime with the test environment flag set to true, &quot;false&quot; otherwise

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="initialState" type="string">

+            <annotation>

+               <documentation>

+                  the intial state of the server, either &quot;started&quot;, or &quot;stopped&quot;. if this attribute is not specified, the server state will be &quot;unknown&quot;

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="stateSet" type="string">

+            <annotation>

+               <documentation>

+                  the state set of the server (changes menu options and UI). values are &quot;managed&quot;, &quot;attach&quot;, and &quot;publish&quot;

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a server type extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+&lt;extension point=&quot;org.eclipse.wst.server.core.serverTypes&quot;&gt;
+     &lt;serverType
+       id=&quot;com.example.serverType&quot;
+       name=&quot;%serverTypeName&quot;
+       description=&quot;%serverTypeDescription&quot;
+       hosts=&quot;localhost, remote&quot;
+       runtime=&quot;true&quot;
+       monitorable=&quot;true&quot;
+       initialState=&quot;stopped&quot;
+       configurationTypeId=&quot;com.example.serverConfiguration&quot;
+       launchConfigId=&quot;com.example.launchConfigurationType&quot;
+       runtimeTypeId=&quot;com.example.runtime&quot;
+       class=&quot;com.example.ExampleServerDelegate&quot;
+       workingCopyClass=&quot;com.example.ExampleServerWorkingCopyDelegate&quot;&gt;
+     &lt;/serverType&gt;
+   &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IServerDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/schema/startup.exsd b/plugins/org.eclipse.wst.server.core/schema/startup.exsd
new file mode 100644
index 0000000..74c6f36
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/schema/startup.exsd
@@ -0,0 +1,112 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.core" id="startup" name="Startup"/>

+      </appInfo>

+      <documentation>

+         This extension point provides a way to invoke code during the server core plugin startup. Use sparingly.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="startup" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="startup">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;IStartup&lt;/samp&gt;

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a startup extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+ &lt;extension point=&quot;org.eclipse.wst.server.core.startup&quot;&gt;
+  &lt;startup
+   id=&quot;com.example.startup&quot;
+   class=&quot;com.example.ExampleStartup&quot;/&gt;
+ &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.core.model.IStartup&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IClient.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IClient.java
new file mode 100644
index 0000000..b4406cd
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IClient.java
@@ -0,0 +1,74 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunch;
+
+import org.eclipse.wst.server.core.model.IClientDelegate;
+import org.eclipse.wst.server.core.model.ILaunchable;
+/**
+ * A launchable client is a client side application or test
+ * harness that can be launched (run) against a resource
+ * running on a server.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IClient {
+	/**
+	 * Returns the id of the adapter.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId();
+
+	/**
+	 * Returns the label (name) of this client.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getName();
+
+	/**
+	 * Returns the description of this client.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getDescription();
+
+	/**
+	 * Returns the delegate for this launchable client
+	 * 
+	 * @return org.eclipse.wst.server.core.model.ILaunchableClientDelegate
+	 */
+	public IClientDelegate getDelegate();
+
+	/**
+	 * Returns true if this launchable can be run by this client.
+	 * 
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param launchable org.eclipse.wst.server.core.model.ILaunchable
+	 * @param launchMode String
+	 * @return boolean
+	 */
+	public boolean supports(IServer server, ILaunchable launchable, String launchMode);
+
+	/**
+	 * Launches the client.
+	 * 
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param launchable org.eclipse.wst.server.core.model.ILaunchable
+	 * @param launchMode String
+	 * @param launch org.eclipse.debug.core.ILaunch
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public IStatus launch(IServer server, ILaunchable launchable, String launchMode, ILaunch launch);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IElement.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IElement.java
new file mode 100644
index 0000000..9fd3184
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IElement.java
@@ -0,0 +1,100 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+/**
+ * An element.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IElement {
+	/**
+	 * Return the label (name) of this element.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getName();
+	
+	/**
+	 * Return the id of this element.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getId();
+
+	public void delete() throws CoreException;
+
+	/**
+	 * Returns true if this element is locked. (user cannot make changes).
+	 *
+	 * @return boolean
+	 */
+	public boolean isLocked();
+
+	/**
+	 * Returns true if this element is private (not shown in the UI).
+	 * 
+	 * @return boolean
+	 */
+	public boolean isPrivate();
+
+	/**
+	 * Returns true if this is a working copy.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isWorkingCopy();
+	
+	/**
+	 * Returns true if there are working copies that have not been saved or released.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isWorkingCopiesExist();
+	
+	/**
+	 * Returns true if there is a working copy that is dirty.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isAWorkingCopyDirty();
+
+	/**
+	 * Returns true if the plugin containing the delegate is loaded.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isDelegatePluginActivated();
+	
+	/**
+	 * Returns true if the delegate has been loaded.
+	 * 
+	 * @return
+	 */
+	public boolean isDelegateLoaded();
+
+	public int getAttribute(String attributeName, int defaultValue);
+
+	public boolean getAttribute(String attributeName, boolean defaultValue);
+	
+	public String getAttribute(String attributeName, String defaultValue);
+
+	public List getAttribute(String attributeName, List defaultValue);
+
+	public Map getAttribute(String attributeName, Map defaultValue);
+
+	public IStatus validateEdit(Object context);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IElementWorkingCopy.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IElementWorkingCopy.java
new file mode 100644
index 0000000..3131f10
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IElementWorkingCopy.java
@@ -0,0 +1,60 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.beans.PropertyChangeListener;
+import java.util.List;
+import java.util.Map;
+/**
+ * A server element.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IElementWorkingCopy extends IElement {
+	public void setAttribute(String attributeName, int value);
+
+	public void setAttribute(String attributeName, boolean value);
+
+	public void setAttribute(String attributeName, String value);
+
+	public void setAttribute(String attributeName, List value);
+
+	public void setAttribute(String attributeName, Map value);
+
+	public void setName(String name);
+	
+	public void setLocked(boolean b);
+	
+	public void setPrivate(boolean b);
+	
+	public boolean isDirty();
+	
+	public void release();
+
+	/**
+	 * Add a property change listener to this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void addPropertyChangeListener(PropertyChangeListener listener);
+
+	/**
+	 * Remove a property change listener from this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void removePropertyChangeListener(PropertyChangeListener listener);
+	
+	/**
+	 * Fire a property change event.
+	 */
+	public void firePropertyChangeEvent(String propertyName, Object oldValue, Object newValue);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ILaunchableAdapter.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ILaunchableAdapter.java
new file mode 100644
index 0000000..c1a25dd
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ILaunchableAdapter.java
@@ -0,0 +1,46 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * This interface, typically implemented by the server
+ * code, converts from an IModuleObject to an
+ * ILaunchable.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface ILaunchableAdapter {
+	/**
+	 * Returns the id of the adapter.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId();
+
+	/**
+	 * Returns the delegate for this launchable adapter.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.ILaunchableAdapterDelegate
+	 */
+	public ILaunchableAdapterDelegate getDelegate();
+
+	/**
+	 * Returns a launchable object from this module object.
+	 * 
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param moduleObject org.eclipse.wst.server.core.model.IModuleObject
+	 * @param org.eclipse.wst.server.core.model.ILaunchable
+	 * @exception org.eclipse.core.runtime.CoreException
+	 */
+	public ILaunchable getLaunchable(IServer server, IModuleObject moduleObject) throws CoreException;
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleFactory.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleFactory.java
new file mode 100644
index 0000000..97995d6
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleFactory.java
@@ -0,0 +1,84 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.List;
+
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IModuleFactoryDelegate;
+import org.eclipse.wst.server.core.model.IModuleFactoryListener;
+/**
+ * A module factory.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IModuleFactory extends IOrdered {
+	/**
+	 * Returns the id of the factory.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId();
+	
+	/**
+	 * Returns the type of module that the factory produces.
+	 * @return
+	 */
+	public List getModuleTypes();
+	
+	/**
+	 * Returns true if this module factory produces project modules.
+	 *
+	 * @return boolean
+	 */
+	public boolean isProjectModuleFactory();
+
+	/**
+	 * Returns the delegate for this factory.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.IModuleFactoryDelegate
+	 */
+	public IModuleFactoryDelegate getDelegate();
+
+	/**
+	 * Gets a module from the factory with the given memento.
+	 * 
+	 * @param memento java.lang.String
+	 * @return org.eclipse.wst.server.core.model.IModule
+	 */
+	public IModule getModule(String memento);
+
+	/**
+	 * Return all modules that are available to be added
+	 * to servers. This method might look through projects
+	 * to find modules or may return modules from
+	 * other sources.
+	 *
+	 * @return java.util.List
+	 */
+	public List getModules();
+
+	/**
+	 * Add a listener for modules that are added/removed from this
+	 * factory.
+	 * 
+	 * @param listener org.eclipse.wst.server.core.model.IModuleFactoryListener
+	 */
+	public void addModuleFactoryListener(IModuleFactoryListener listener);
+	
+	/**
+	 * Add a listener for modules that are added/removed from this
+	 * factory.
+	 * 
+	 * @param listener org.eclipse.wst.server.core.model.IModuleFactoryListener
+	 */
+	public void removeModuleFactoryListener(IModuleFactoryListener listener);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleKind.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleKind.java
new file mode 100644
index 0000000..a771da8
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleKind.java
@@ -0,0 +1,30 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IModuleKind {
+	/**
+	 * Returns the id, e.g. "j2ee.web".
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getId();
+
+	/**
+	 * Returns the name, e.g. "Web module".
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getName();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleObjectAdapter.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleObjectAdapter.java
new file mode 100644
index 0000000..732623a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleObjectAdapter.java
@@ -0,0 +1,58 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.wst.server.core.model.IModuleObject;
+import org.eclipse.wst.server.core.model.IModuleObjectAdapterDelegate;
+/**
+ * A module object adapter converts from some view's model
+ * object into a module object that is recognized by the
+ * server.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IModuleObjectAdapter {
+	/**
+	 * Returns the id of the adapter.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId();
+	
+	/**
+	 * Returns the (super) class name that this adapter can work with.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getObjectClassName();
+	
+	/**
+	 * Returns true if the plugin that loaded this class has been loaded.
+	 *
+	 * @return boolean
+	 */
+	public boolean isPluginActivated();	
+
+	/**
+	 * Returns the delegate for this module object adapter.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.IModuleObjectAdapterDelegate
+	 */
+	public IModuleObjectAdapterDelegate getDelegate();
+
+	/**
+	 * Converts from a model object to an IModuleObject.
+	 * 
+	 * @param obj java.lang.Object
+	 * @return org.eclipse.wst.server.core.model.IModuleObject
+	 */
+	public IModuleObject getModuleObject(Object obj);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleTask.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleTask.java
new file mode 100644
index 0000000..890210c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleTask.java
@@ -0,0 +1,62 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.List;
+
+import org.eclipse.wst.server.core.model.*;
+/**
+ * A task for a module.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IModuleTask extends ITask, IModuleTaskDelegate, IOrdered {
+	/**
+	 * Returns the id of the adapter.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId();
+	
+	/**
+	 * Return the type ids that may be supported.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	public String[] getTypeIds();
+	
+	/**
+	 * Returns true if the given type (given by the id) can use this task. This
+	 * result is based on the result of the getTypeIds() method.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsType(String id);
+
+	/**
+	 * Lets the task know that it is about to be used. This method should
+	 * be used to clean out any previously cached information, or start to
+	 * create a new cache.
+	 * 
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param configuration org.eclipse.wst.server.core.model.IServerConfiguration
+	 * @param parents java.util.List
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 */
+	public void init(IServer server, IServerConfiguration configuration, List parents, IModule module);
+
+	/**
+	 * Returns the status of this task.
+	 * 
+	 * @return byte
+	 */
+	public byte getTaskStatus();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleType.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleType.java
new file mode 100644
index 0000000..3d3cf27
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IModuleType.java
@@ -0,0 +1,28 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IModuleType {
+	/**
+	 * Returns the type, e.g. "j2ee.ejb".
+	 * @return
+	 */
+	public String getType();
+
+	/**
+	 * Returns the version (spec level), e.g. "1.0", "1.3.2"
+	 * @return
+	 */
+	public String getVersion();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IMonitoredServerPort.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IMonitoredServerPort.java
new file mode 100644
index 0000000..3409ffe
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IMonitoredServerPort.java
@@ -0,0 +1,54 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.wst.server.core.model.IServerPort;
+/**
+ * An monitored port on a server.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IMonitoredServerPort {
+	/**
+	 * Returns the server that it being monitored.
+	 * 
+	 * @return org.eclipse.wst.server.core.IServer
+	 */
+	public IServer getServer();
+
+	/**
+	 * Returns the server port.
+	 * 
+	 * @return org.eclipse.wst.server.model.IServerPort
+	 */
+	public IServerPort getServerPort();
+
+	/**
+	 * Return the port that is being used to monitor.
+	 * 
+	 * @return int
+	 */
+	public int getMonitorPort();
+
+	/**
+	 * Returns the content types that are being monitored, or null for all content.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	public String[] getContentTypes();
+
+	/**
+	 * Returns true if the monitor is currently running/active.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isStarted();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IOrdered.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IOrdered.java
new file mode 100644
index 0000000..fdf66e9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IOrdered.java
@@ -0,0 +1,24 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+/**
+ * An object that has an absolute ordering, and can be ordered against other objects.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IOrdered {
+	/**
+	 * Returns the order (index/priority).
+	 * 
+	 * @return int
+	 */
+	public int getOrder();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IProjectProperties.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IProjectProperties.java
new file mode 100644
index 0000000..94fc0ed
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IProjectProperties.java
@@ -0,0 +1,61 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.model.IProjectPropertiesListener;
+/**
+ * This interface holds information on the properties of a given project.
+ *
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IProjectProperties {
+	/**
+	 * Returns the preferred runtime server for the project. This method
+	 * returns null if the server was never chosen or does not currently exist. (if the
+	 * server is recreated or was in a closed project, etc. this method will return
+	 * the original value if it becomes available again)
+	 *
+	 * @return org.eclipse.wst.server.core.IServer
+	 */
+	public IServer getDefaultServer();
+
+	/**
+	 * Sets the preferred runtime server for the project. Set the server to
+	 * null to clear the setting. If there is a problem saving the file, a CoreException
+	 * will be thrown.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @throws org.eclipse.core.runtime.CoreException
+	 */
+	public void setDefaultServer(IServer server, IProgressMonitor monitor) throws CoreException;
+
+	/**
+	 * Returns the current runtime target for this project.
+	 * 
+	 * @return
+	 */
+	public IRuntime getRuntimeTarget();
+
+	/**
+	 * Sets the runtime target for the project.
+	 * 
+	 * @param target
+	 * @param monitor
+	 */
+	public void setRuntimeTarget(IRuntime runtime, IProgressMonitor monitor) throws CoreException;
+
+	public void addProjectPropertiesListener(IProjectPropertiesListener listener);
+
+	public void removeProjectPropertiesListener(IProjectPropertiesListener listener);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IPublishControl.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IPublishControl.java
new file mode 100644
index 0000000..13c1b72
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IPublishControl.java
@@ -0,0 +1,66 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.wst.server.core.resources.*;
+/**
+ * The publish controller that caches and provides information
+ * about the current publishing to the publisher.
+ *
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IPublishControl {
+	/**
+	 * Returns the mapping of this file on the remote system. Returns
+	 * null if this file should not be copied to the remote server.
+	 *
+	 * @param resource org.eclipse.wst.server.core.publish.IModuleResource
+	 * @return org.eclipse.core.resources.IPath
+	 */
+	public IPath getMappedLocation(IModuleResource resource);
+
+	/**
+	 * Returns the root level remote resources on the remote system.
+	 *
+	 * @param project org.eclipse.core.resources.IProject
+	 * @return java.util.List
+	 */
+	public IRemoteResource[] getRemoteResources();
+
+	/**
+	 * Returns true if there may be any files or folders within
+	 * this container that should be mapped to the remote system.
+	 * Returns false if files within this folder are never copied
+	 * to the remote system.
+	 *
+	 * @param folder org.eclipse.wst.server.core.publish.IModuleFolder
+	 * @return boolean
+	 */
+	public boolean shouldMapMembers(IModuleFolder folder);
+	
+	/**
+	 * Returns the timestamp of the remote resource on the remote
+	 * machine after it was last published.
+	 *
+	 * @param resource org.eclipse.wst.server.publish.IRemoteResource
+	 * @return long
+	 */
+	public long getPublishedTimestamp(IRemoteResource resource);
+
+	/**
+	 * Returns the timestamp that the resource was last published.
+	 *
+	 * @param resource org.eclipse.wst.server.publish.IModuleResource
+	 * @return long
+	 */
+	public long getPublishedTimestamp(IModuleResource resource);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IPublishManager.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IPublishManager.java
new file mode 100644
index 0000000..6cdc90f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IPublishManager.java
@@ -0,0 +1,83 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.List;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.model.*;
+/**
+ * Class that decides whether to publish or delete a given
+ * resource on the remote system.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IPublishManager {
+	/**
+	 * Returns the id of this default server.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId();
+
+	/**
+	 * Returns a description of this publisher.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getDescription();
+
+	/**
+	 * Returns the name of this publisher.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getName();
+
+	/**
+	 * Sets the publish control, used to obtain information about
+	 * the publishing.
+	 *
+	 * Sets the publish state, used to determine the timestamps
+	 * of the last publishing action.
+	 * 
+	 * Resolve which resources to publish or delete. To cancel publishing,
+	 * just cancel the progress monitor and return.
+	 *
+	 * @param control org.eclipse.wst.server.model.IPublishControl[]
+	 * @param module org.eclipse.wst.server.core.model.IModule[]
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 */
+	public void resolve(IPublishControl[] control, IModule[] module, IProgressMonitor monitor);
+
+	/**
+	 * Returns the list of remote resources to delete from the
+	 * remote system.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return java.util.List
+	 */
+	public List getResourcesToDelete(IModule module);
+
+	/**
+	 * Returns the list of resources to publish to the remote
+	 * system.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return java.util.List
+	 */
+	public List getResourcesToPublish(IModule module);
+	
+	/**
+	 * 
+	 */
+	public IPublishManagerDelegate getDelegate();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IPublishStatus.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IPublishStatus.java
new file mode 100644
index 0000000..321e1e9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IPublishStatus.java
@@ -0,0 +1,35 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * An IStatus that also contains a time and module. This
+ * status is returned from the publishing operations.
+ *
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IPublishStatus extends IStatus {
+	/**
+	 * Returns the time taken (in ms) for this publish action.
+	 * 
+	 * @return long
+	 */
+	public long getTime();
+
+	/**
+	 * Returns the module that was published.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IModule
+	 */
+	public IModule getModule();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IResourceManager.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IResourceManager.java
new file mode 100644
index 0000000..32c1a5a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IResourceManager.java
@@ -0,0 +1,170 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * IResourceManager handles the mappings between resources
+ * and servers or configurations, and creates notification
+ * of servers or configurations being added, removed, or modified.
+ *
+ * <p>Servers and configurations may be a single resource, or they may
+ * be a folder that contains a group of files.Folder-resources may not
+ * contain other servers or configurations. (i.e. they cannot be nested)</p>
+ *
+ * <p>Changes made to server element resources (e.g. an edit or deletion of a
+ * file) are processed as a reload or deletion of the element. Note that saving
+ * a folder-based server or configuration may result in a series of reload
+ * events.</p>
+ *
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IResourceManager {
+	/**
+	 * Adds a new server resource listener.
+	 *
+	 * @param listener org.eclipse.wst.server.model.IServerResourceListener
+	 */
+	public void addResourceListener(IServerResourceListener listener);
+
+	/**
+	 * Removes a server resource listener.
+	 *
+	 * @param listener org.eclipse.wst.server.model.IServerResourceListener
+	 */
+	public void removeResourceListener(IServerResourceListener listener);
+
+	/**
+	 * Returns a list of all runtimes.
+	 *
+	 * @return java.util.List
+	 */
+	public List getRuntimes();
+	
+	/**
+	 * Returns the default runtime. Test API - do not use.
+	 *
+	 * @return java.util.List
+	 */
+	public IRuntime getDefaultRuntime();
+	
+	/**
+	 * Sets the default runtime. Test API - do not use.
+	 *
+	 * @return java.util.List
+	 */
+	public void setDefaultRuntime(IRuntime runtime);
+	
+	/**
+	 * Returns the runtimes with the given runtime type.
+	 *
+	 * @return java.util.List
+	 */
+	public List getRuntimes(IRuntimeType runtimeType);
+	
+	/**
+	 * Returns the runtime with the given id.
+	 *
+	 * @return IRuntime
+	 */
+	public IRuntime getRuntime(String id);
+
+	/**
+	 * Returns a list of all servers.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServers();
+
+	/**
+	 * Returns the server with the given id.
+	 *
+	 * @return java.util.List
+	 */
+	public IServer getServer(String id);
+
+	/**
+	 * Returns the server that came from the given file.
+	 *
+	 * @param file org.eclipse.core.resources.IFile
+	 * @return org.eclipse.wst.server.model.IServer
+	 */
+	public IServer getServer(IFile file);
+	
+	/**
+	 * Returns a list of all servers.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServers(IServerType serverType);
+
+	/**
+	 * Returns a list of all currently active server configurations.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServerConfigurations();
+	
+	/**
+	 * Returns a list of all currently active server configurations.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServerConfigurations(IServerConfigurationType configType);
+
+	/**
+	 * Returns the servers with the given id.
+	 *
+	 * @return java.util.List
+	 */
+	public IServerConfiguration getServerConfiguration(String id);
+
+	/**
+	 * Returns the server configuration that came from the
+	 * given resource.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 * @return org.eclipse.wst.server.model.IServerConfiguration
+	 */
+	public IServerConfiguration getServerConfiguration(IFile file);
+
+	/**
+	 * Adds a new module events listener.
+	 *
+	 * @param listener org.eclipse.wst.server.model.IModuleEventsListener
+	 */
+	public void addModuleEventsListener(IModuleEventsListener listener);
+	
+	/**
+	 * Removes an existing module events listener.
+	 *
+	 * @param listener org.eclipse.wst.server.model.IModuleEventsListener
+	 */
+	public void removeModuleEventsListener(IModuleEventsListener listener);
+
+	/**
+	 * Adds a new server lifecycle event handler with the given index. Handlers with
+	 * lower indexes are always called first.
+	 *
+	 * @param handler org.eclipse.wst.server.model.IServerLifecycleEventHandler
+	 */
+	public void addServerLifecycleEventHandler(int index, IServerLifecycleEventHandler handler);
+
+	/**
+	 * Removes an existing server lifecycle event handler.
+	 *
+	 * @param handler org.eclipse.wst.server.model.IServerLifecycleEventHandler
+	 */
+	public void removeServerLifecycleEventHandler(IServerLifecycleEventHandler handler);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntime.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntime.java
new file mode 100644
index 0000000..007cf8f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntime.java
@@ -0,0 +1,38 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+
+import org.eclipse.wst.server.core.model.IRuntimeDelegate;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IRuntime extends IElement {
+	public IRuntimeType getRuntimeType();
+
+	public IRuntimeDelegate getDelegate();
+
+	public IRuntimeWorkingCopy getWorkingCopy();
+	
+	public IPath getLocation();
+	
+	public boolean isTestEnvironment();
+	
+	/**
+	 * Return the validation status of the runtime.
+	 * 
+	 * @return
+	 */
+	public IStatus validate();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeLocator.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeLocator.java
new file mode 100644
index 0000000..d9ea656
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeLocator.java
@@ -0,0 +1,40 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IRuntimeLocator {
+	/**
+	 * 
+	 * @return
+	 */
+	public String getId();
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getName();
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getDescription();
+
+	public void searchForRuntimes(IRuntimeLocatorListener listener, IProgressMonitor monitor) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeTargetHandler.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeTargetHandler.java
new file mode 100644
index 0000000..7083b72
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeTargetHandler.java
@@ -0,0 +1,35 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.model.IRuntimeTargetHandlerDelegate;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IRuntimeTargetHandler extends IOrdered {
+	/**
+	 * 
+	 * @return
+	 */
+	public String getId();
+
+	public boolean supportsRuntimeType(IRuntimeType runtimeType);
+
+	public IRuntimeTargetHandlerDelegate getDelegate();
+
+	public void setRuntimeTarget(IProject project, IRuntime runtime, IProgressMonitor monitor) throws CoreException;
+	
+	public void removeRuntimeTarget(IProject project, IRuntime runtime, IProgressMonitor monitor) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeType.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeType.java
new file mode 100644
index 0000000..fefce7e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeType.java
@@ -0,0 +1,52 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IRuntimeType extends IOrdered {
+	/**
+	 * 
+	 * @return
+	 */
+	public String getId();
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getName();
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getDescription();
+	
+	public String getVendor();
+	
+	public String getVersion();
+
+	/**
+	 * 
+	 * @return
+	 */
+	public List getModuleTypes();
+	
+	public boolean canCreate();
+
+	public IRuntimeWorkingCopy createRuntime(String id) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeWorkingCopy.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeWorkingCopy.java
new file mode 100644
index 0000000..b3e299b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IRuntimeWorkingCopy.java
@@ -0,0 +1,31 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.model.IRuntimeWorkingCopyDelegate;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IRuntimeWorkingCopy extends IRuntime, IElementWorkingCopy {	
+	public IRuntime getOriginal();
+	
+	public IRuntimeWorkingCopyDelegate getWorkingCopyDelegate();
+	
+	public void setLocation(IPath path);
+	
+	public IRuntime save(IProgressMonitor monitor) throws CoreException;
+	
+	public void setTestEnvironment(boolean b);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServer.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServer.java
new file mode 100644
index 0000000..28240f9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServer.java
@@ -0,0 +1,403 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+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.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServer extends IElement {
+	public static final String FILE_EXTENSION = "server";
+	
+	// attribute for launch configurations
+	public static final String ATTR_SERVER_ID = "server-id";
+
+	// --- Server State Constants ---
+	// (returned from getServerState() method)
+
+	// the server state is unknown
+	public static final byte SERVER_UNKNOWN = 0;
+
+	// the server is starting, but not yet ready to serve content
+	public static final byte SERVER_STARTING = 1;
+
+	// the server is ready to serve content
+	public static final byte SERVER_STARTED = 2;
+
+	// the server is started in debug mode and ready
+	// to serve content
+	public static final byte SERVER_STARTED_DEBUG = 3;
+	
+	// the server is started in profiling mode and ready
+	// to serve content
+	public static final byte SERVER_STARTED_PROFILE = 4;
+
+	// the server is shutting down
+	public static final byte SERVER_STOPPING = 5;
+
+	// the server is stopped
+	public static final byte SERVER_STOPPED = 6;
+
+	// getting the server state is unsupported
+	public static final byte SERVER_UNSUPPORTED = 7;
+
+
+	// --- Module State Constants ---
+	// (returned from getModuleState() method)
+
+	// the module state is unknown
+	public static final byte MODULE_STATE_UNKNOWN = 0;
+
+	// the module is starting up
+	public static final byte MODULE_STATE_STARTING = 1;
+
+	// the module is ready to serve content
+	public static final byte MODULE_STATE_STARTED = 2;
+
+	// the module is shutting down
+	public static final byte MODULE_STATE_STOPPING = 3;
+
+	// the module is stopped
+	public static final byte MODULE_STATE_STOPPED = 4;
+
+
+	// --- Sync State Constants ---
+	// (returned from the isXxxInSnyc() methods)
+
+	// the state of the server's contents are unknown
+	public static final byte SYNC_STATE_UNKNOWN = 0;
+
+	// the local contents exactly match the server's contents
+	public static final byte SYNC_STATE_IN_SYNC = 1;
+
+	// the local contents do not match the server's contents
+	public static final byte SYNC_STATE_DIRTY = 2;
+	
+	/**
+	 * Returns the current state of the server. (see SERVER_XXX
+	 * constants)
+	 *
+	 * @return byte
+	 */
+	public byte getServerState();
+	
+	public String getHostname();
+	
+	public IFile getFile();
+	
+	//public boolean hasRuntime();
+	
+	public IRuntime getRuntime();
+	
+	public IServerType getServerType();
+	
+	public IServerConfiguration getServerConfiguration();
+	
+	public IServerDelegate getDelegate();
+	
+	public IServerWorkingCopy getWorkingCopy();
+	
+	/**
+	 * Returns true if this is a configuration that is
+	 * applicable to (can be used with) this server.
+	 *
+	 * @param configuration org.eclipse.wst.server.core.model.IServerConfiguration
+	 * @return boolean
+	 */
+	public boolean isSupportedConfiguration(IServerConfiguration configuration);
+
+	/**
+	 * Returns the configuration's sync state.
+	 *
+	 * @return byte
+	 */
+	public byte getConfigurationSyncState();
+
+	/**
+	 * Returns a list of the projects that have not been published
+	 * since the last modification. (i.e. the projects that are
+	 * out of sync with the server.
+	 *
+	 * @return java.util.List
+	 */
+	public List getUnpublishedModules();
+
+	/**
+	 * Add a listener to this server.
+	 *
+	 * @param listener org.eclipse.wst.server.model.IServerListener
+	 */
+	public void addServerListener(IServerListener listener);
+	
+	/**
+	 * Remove a listener from this server.
+	 *
+	 * @param listener org.eclipse.wst.server.model.IServerListener
+	 */
+	public void removeServerListener(IServerListener listener);
+
+	/**
+	 * Adds a publish listener to this server.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IPublishListener
+	 */
+	public void addPublishListener(IPublishListener listener);
+	
+	/**
+	 * Removes a publish listener from this server.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IPublishListener
+	 */
+	public void removePublishListener(IPublishListener listener);
+	
+	/**
+	 * Returns true if the server is in a state that it can
+	 * be published to.
+	 *
+	 * @return boolean
+	 */
+	public boolean canPublish();
+	
+	/**
+	 * Returns true if the server may have any projects or it's
+	 * configuration out of sync.
+	 *
+	 * @return boolean
+	 */
+	public boolean shouldPublish();
+	
+	/**
+	 * Returns the publisher that can be used to publish the
+	 * given module. If the module should never
+	 * be published to the server, it may return null.
+	 *
+	 * @param parents java.util.List
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return org.eclipse.wst.server.core.model.IPublisher
+	 */
+	public IPublisher getPublisher(List parents, IModule module);
+
+	public IStatus publish(IProgressMonitor monitor);
+	
+	public IStatus publish(IPublishManager publishManager, IProgressMonitor monitor);
+	
+	/**
+	 * Returns true if the server is in a state that it can
+	 * be started, and supports the given mode.
+	 *
+	 * @param mode
+	 * @return boolean
+	 */
+	public boolean canStart(String mode);
+	
+	public ILaunch getExistingLaunch();
+	
+	/**
+	 * Return the launch configuration for this server. If one does not exist, it
+	 * will be created if "create" is true, and otherwise will return null.
+	 * 
+	 * @param create
+	 * @return
+	 * @throws CoreException
+	 */
+	public ILaunchConfiguration getLaunchConfiguration(boolean create) throws CoreException;
+
+	public void setLaunchDefaults(ILaunchConfigurationWorkingCopy workingCopy);
+
+	public ILaunch start(String mode, IProgressMonitor monitor) throws CoreException;
+	
+	/**
+	 * Start the server in the given start mode and waits until the server
+	 * has finished started.
+	 *
+	 * @param mode java.lang.String
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @exception CoreException - thrown if an error occurs while trying to start the server
+	 */
+	public void synchronousStart(String mode, IProgressMonitor monitor) throws CoreException;
+	
+	/**
+	 * Returns true if the server is in a state that it can
+	 * be restarted.
+	 *
+	 * @return boolean
+	 */
+	public boolean canRestart(String mode);
+	
+	/**
+	 * Returns true if the server is not in sync and needs to be
+	 * restarted. Returns false if the server should not be restarted.
+	 * (e.g. if the contents have not been modified and the server
+	 * process is still in sync)
+	 * Result is undefined if the server is not running.
+	 *
+	 * @return boolean
+	 */
+	public boolean isRestartNeeded();
+
+	/**
+	 * Restart the server with the given debug mode.
+	 * A server may only be restarted when it is currently running.
+	 * This method is asynchronous.
+	 */
+	public void restart(String mode);
+
+	/**
+	 * Returns true if the server is in a state that it can
+	 * be stopped.
+	 *
+	 * @return boolean
+	 */
+	public boolean canStop();
+
+	/**
+	 * Stop the server if it is running.
+	 */
+	public void stop();
+
+	/**
+	 * Stop the server and wait until the
+	 * server has completely stopped.
+	 */
+	public void synchronousStop();
+
+	/**
+	 * Terminate the server process(es). This method should only be
+	 * used as a last resort after the stop() method fails to work.
+	 * The server should return from this method quickly and
+	 * use the server listener to notify shutdown progress.
+	 * It MUST terminate the server completely and return it to
+	 * the stopped state.
+	 */
+	public void terminate();
+
+	/**
+	 * Trigger a restart of the given module and wait until it has finished restarting.
+	 *
+	 * @param module org.eclipse.wst.server.core.IModule
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @exception org.eclipse.core.runtime.CoreException - thrown if an error occurs while trying to restart the module
+	 */
+	public void synchronousModuleRestart(final IModule module, IProgressMonitor monitor) throws CoreException;
+
+	/**
+	 * Returns a temporary directory that the requestor can use
+	 * throughout it's lifecycle. This is primary to be used by
+	 * servers for working directories, server specific
+	 * files, etc.
+	 *
+	 * <p>As long as the same key is used to call this method on
+	 * each use of the workbench, this method directory will return
+	 * the same directory. If the directory is not requested over a
+	 * period of time, the directory may be deleted and a new one
+	 * will be assigned on the next request. For this reason, a
+	 * server should request the temp directory on startup
+	 * if it wants to store files there. In all cases, the server
+	 * should have a backup plan to refill the directory
+	 * in case it has been deleted since last use.</p>
+	 *
+	 * @param serverResource org.eclipse.wst.server.core.model.IServerResource
+	 * @return org.eclipse.core.runtime.IPath
+	 */
+	public IPath getTempDirectory();
+	
+	public void updateConfiguration();
+
+	/**
+	 * Returns true if this module can be added to this
+	 * configuration at the current time, and false otherwise.
+	 *
+	 * <p>This method may decide based on the type of module
+	 * or refuse simply due to reaching a maximum number of
+	 * modules or other criteria.</p>
+	 *
+	 * @param add org.eclipse.wst.server.core.model.IModule
+	 * @return boolean
+	 */
+	public IStatus canModifyModules(IModule[] add, IModule[] remove);
+
+	/**
+	 * Returns the modules that are in this configuration.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getModules();
+	
+	/**
+	 * Returns the current state of the given module. See
+	 * class header for MODULE_XXX constants.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return byte
+	 */
+	public byte getModuleState(IModule module);
+	
+	/**
+	 * Returns the child module(s) of this module. If this
+	 * module contains other modules, it should list those
+	 * modules. If not, it should return an empty list.
+	 *
+	 * <p>This method should only return the direct children.
+	 * To obtain the full module tree, this method may be
+	 * recursively called on the children.</p>
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return java.util.List
+	 */
+	public List getChildModules(IModule module);
+
+	/**
+	 * Returns the parent module(s) of this module. When
+	 * determining if a given project can run on a server
+	 * configuration, this method will be used to find the
+	 * actual module(s) that may be run on the server. For
+	 * instance, a Web module may return a list of Ear
+	 * modules that it is contained in if the server only
+	 * supports configuring Ear modules.
+	 *
+	 * <p>If the module type is not supported, this method
+	 * may return null. If the type is normally supported but there
+	 * is a configuration problem or missing parent, etc., this
+	 * method may fire a CoreException that may then be presented
+	 * to the user.</p>
+	 *
+	 * <p>If it does return valid parent(s), this method should
+	 * always return the topmost parent module(s), even if
+	 * there are a few levels (a heirarchy) of modules.</p>
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return java.util.List
+	 * @throws org.eclipse.core.runtime.CoreException
+	 */
+	public List getParentModules(IModule module) throws CoreException;
+
+	/**
+	 * Method called when changes to the module or module factories
+	 * within this configuration occur. Return any necessary commands to repair
+	 * or modify the server configuration in response to these changes.
+	 * 
+	 * @param org.eclipse.wst.server.core.model.IModuleFactoryEvent[]
+	 * @param org.eclipse.wst.server.core.model.IModuleEvent[]
+	 * @return org.eclipse.wst.server.core.model.ITask[]
+	 */
+	public ITask[] getRepairCommands(IModuleFactoryEvent[] factoryEvent, IModuleEvent[] moduleEvent);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerConfiguration.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerConfiguration.java
new file mode 100644
index 0000000..2beaacf
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerConfiguration.java
@@ -0,0 +1,38 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * A server configuration. Server configurations usually contain
+ * directories (the resources to be run on the server) and configuration
+ * information. (i.e. mime types, data sources, etc.)
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerConfiguration extends IElement {
+	public static final String FILE_EXTENSION = "config";
+
+	public IServerConfigurationType getServerConfigurationType();
+	
+	public IFile getFile();
+	
+	public IServerConfigurationDelegate getDelegate();
+	
+	public IServerConfigurationWorkingCopy getWorkingCopy();
+	
+	public IFolder getConfigurationDataFolder();
+	
+	public IPath getConfigurationDataPath();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerConfigurationType.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerConfigurationType.java
new file mode 100644
index 0000000..08cee7d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerConfigurationType.java
@@ -0,0 +1,60 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+/**
+ * A server configuration. Server configurations usually contain
+ * directories (the resources to be run on the server) and configuration
+ * information. (i.e. mime types, data sources, etc.)
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerConfigurationType extends IOrdered {
+	/**
+	 * 
+	 * @return
+	 */
+	public String getId();
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getName();
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getDescription();
+
+	/**
+	 * Returns the extensions to filter when importing the server
+	 * resource. If these extensions are given, the resource is
+	 * assumed to be a file. If null is returned, the import will
+	 * look for folders instead.
+	 *
+	 * @return java.lang.String[]
+	 */
+	public String[] getImportFilterExtensions();
+
+	public boolean isFolder();
+
+	public IServerConfigurationWorkingCopy createServerConfiguration(String id, IFile file, IProgressMonitor monitor) throws CoreException;
+	
+	public IServerConfigurationWorkingCopy importFromPath(String id, IFile file, IPath path, IProgressMonitor monitor) throws CoreException;
+	
+	public IServerConfigurationWorkingCopy importFromRuntime(String id, IFile file, IRuntime runtime, IProgressMonitor monitor) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerConfigurationWorkingCopy.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerConfigurationWorkingCopy.java
new file mode 100644
index 0000000..626942f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerConfigurationWorkingCopy.java
@@ -0,0 +1,26 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.model.IServerConfigurationWorkingCopyDelegate;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerConfigurationWorkingCopy extends IServerConfiguration, IElementWorkingCopy {
+	public IServerConfiguration getOriginal();
+	
+	public IServerConfigurationWorkingCopyDelegate getWorkingCopyDelegate();
+	
+	public IServerConfiguration save(IProgressMonitor monitor) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerLaunchConfig.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerLaunchConfig.java
new file mode 100644
index 0000000..58b63f4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerLaunchConfig.java
@@ -0,0 +1,21 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+/**
+ * 
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerLaunchConfig {
+	public void setDefaults(ILaunchConfigurationWorkingCopy workingCopy, IServer server);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerLifecycleEvent.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerLifecycleEvent.java
new file mode 100644
index 0000000..6fbe387
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerLifecycleEvent.java
@@ -0,0 +1,29 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.wst.server.core.model.IModuleEvent;
+import org.eclipse.wst.server.core.model.IModuleFactoryEvent;
+/**
+ * A server lifecycle event. This even is fired whenever changes to modules
+ * within the workspace require changes (fixes) to the given server.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerLifecycleEvent {
+	public IServer getServer();
+
+	public IModuleFactoryEvent[] getModuleFactoryEvents();
+
+	public IModuleEvent[] getModuleEvents();
+	
+	public ITask[] getTasks();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerMonitor.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerMonitor.java
new file mode 100644
index 0000000..2964afd
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerMonitor.java
@@ -0,0 +1,59 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.wst.server.core.model.IServerPort;
+/**
+ * An interface to a TCP/IP monitor.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerMonitor {
+	/**
+	 * Returns the id of the monitor.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId();
+
+	/**
+	 * Returns the label (name) of this monitor.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getName();
+
+	/**
+	 * Returns the description of this monitor.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getDescription();
+
+	/**
+	 * Start monitoring the given port, and return the port number to
+	 * tunnel requests through. The monitorPort is the new port to use, or
+	 * -1 to pick a random port.
+	 * 
+	 * @param port
+	 * @return
+	 */
+	public int startMonitoring(IServer server, IServerPort port, int monitorPort) throws CoreException;
+
+	/**
+	 * Stop monitoring the given port.
+	 * 
+	 * @param port
+	 */
+	public void stopMonitoring(IServer server, IServerPort port);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerMonitorManager.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerMonitorManager.java
new file mode 100644
index 0000000..f24cfed
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerMonitorManager.java
@@ -0,0 +1,92 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.wst.server.core.model.IServerPort;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerMonitorManager {
+	/**
+	 * Returns the monitor that is currently being used.
+	 *  
+	 * @return
+	 */
+	public IServerMonitor getCurrentServerMonitor();
+	
+	/**
+	 * Switch to use a different server monitor. All existing monitors will be
+	 * removed from the current monitor and added to the new monitor.
+	 * 
+	 * @param newMonitor
+	 * @throws CoreException
+	 */
+	public void setServerMonitor(IServerMonitor newMonitor) throws CoreException;
+
+	/**
+	 * Returns the list of ports that are currently being monitored. The elements in the
+	 * array are of type IMonitoredServerPorts.
+	 *
+	 * @return
+	 */
+	public List getMonitoredPorts(IServer server);
+
+	/**
+	 * Starts monitoring the given port, and returns the new port # to use that will
+	 * route to the monitored port.
+	 * 
+	 * @param server
+	 * @param port
+	 * @param monitorPort - the new port number to use for monitoring, or -1 to pick a new port
+	 * @param content
+	 * @return monitor port number
+	 */
+	public IMonitoredServerPort createMonitor(IServer server, IServerPort port, int monitorPort, String[] content);
+
+	/**
+	 * Stop monitoring the given port. Throws a CoreException if there was a problem
+	 * stopping the monitoring
+	 *
+	 * @param port
+	 */
+	public void removeMonitor(IMonitoredServerPort msp);
+
+	/**
+	 * Start the monitor. If the msp port is -1, it will be updated to the port that is actually in use.
+	 * 
+	 * @param port
+	 * @throws CoreException
+	 */
+	public void startMonitor(IMonitoredServerPort msp) throws CoreException;
+
+	/**
+	 * Stop monitoring.
+	 * 
+	 * @param port
+	 */
+	public void stopMonitor(IMonitoredServerPort port);
+
+	/**
+	 * Returns the monitored port to use when making requests to the given server, port number,
+	 * and content. Returns the existing port number if the port is not being monitored.
+	 * 
+	 * @param server
+	 * @param port
+	 * @param content
+	 * @return the monitored port number
+	 */
+	public int getMonitoredPort(IServer server, int port, String contentType);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerPreferences.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerPreferences.java
new file mode 100644
index 0000000..bfe1d1b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerPreferences.java
@@ -0,0 +1,137 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+/**
+ * Helper class that stores preference information for server core.
+ *
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerPreferences {
+	public static final byte REPAIR_NEVER = 0;
+	public static final byte REPAIR_PROMPT = 1;
+	public static final byte REPAIR_ALWAYS = 2;
+
+	/**
+	 * Returns whether servers will be automatically restarted when
+	 * required.
+	 *
+	 * @return boolean
+	 */
+	public boolean isAutoRestarting();
+
+	/**
+	 * Returns whether servers will be automatically restarted when
+	 * required.
+	 *
+	 * @return boolean
+	 */
+	public boolean isDefaultAutoRestarting();
+
+	/**
+	 * Set whether servers will be automatically restarted when
+	 * they need a restart.
+	 *
+	 * @param boolean
+	 */
+	public void setAutoRestarting(boolean b);
+
+	/**
+	 * Returns whether automatic publishing should occur before
+	 * starting a server.
+	 *
+	 * @return boolean
+	 */
+	public boolean isAutoPublishing();
+	
+	/**
+	 * Returns whether automatic publishing should occur before
+	 * starting a server.
+	 *
+	 * @return boolean
+	 */
+	public boolean isDefaultAutoPublishing();
+
+	/**
+	 * Set whether publishing should happen before the server starts.
+	 *
+	 * @param boolean
+	 */
+	public void setAutoPublishing(boolean b);
+
+	/**
+	 * Returns whether servers and configurations should be created in the
+	 * workspace (as opposed to in metadata).
+	 *
+	 * @return boolean
+	 */
+	public boolean isCreateResourcesInWorkspace();
+
+	/**
+	 * Returns whether servers and configurations should be created in the
+	 * workspace (as opposed to in metadata) by default.
+	 *
+	 * @return boolean
+	 */
+	public boolean isDefaultCreateResourcesInWorkspace();
+
+	/**
+	 * Set whether servers and configurations should be created in the
+	 * workspace (as opposed to in metadata).
+	 *
+	 * @param boolean
+	 */
+	public void setCreateResourcesInWorkspace(boolean b);
+
+	/**
+	 * Returns the default publish manager preference.
+	 *
+	 * @return String
+	 */
+	public String getDefaultPublishManager();
+
+	/**
+	 * Returns the publish manager preference.
+	 *
+	 * @return String
+	 */
+	public String getPublishManager();
+
+	/**
+	 * Sets the publish manager preference.
+	 *
+	 * @param String
+	 */
+	public void setPublishManager(String id);
+
+	/**
+	 * Returns whether changes to modules should be automatically fixed
+	 * in the server configurations. Returns one of the REPAIR_* constants.
+	 *
+	 * @return byte
+	 */
+	public byte getModuleRepairStatus();
+
+	/**
+	 * Returns the default module fix state. Returns one of the
+	 * REPAIR_* constants.
+	 *
+	 * @return byte
+	 */
+	public byte getDefaultModuleRepairStatus();
+
+	/**
+	 * Sets whether changes to modules should be automatically fixed
+	 * in the server configurations. Use one of the REPAIR_* constants.
+	 *
+	 * @return byte
+	 */
+	public void setModuleRepairStatus(byte b);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerProject.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerProject.java
new file mode 100644
index 0000000..2c61014
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerProject.java
@@ -0,0 +1,52 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.List;
+import org.eclipse.core.resources.IProject;
+/**
+ * A server project.
+ *
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerProject {
+	// server project nature id
+	public static final String NATURE_ID = ServerCore.PLUGIN_ID + ".nature";
+
+	/**
+	 * Returns a list of available folders within the server project. These are
+	 * all the folders within the project, except those that are already part of
+	 * a server configuration.
+	 */ 
+	public List getAvailableFolders();
+
+	/**
+	 * Returns the project that this nature is associated with.
+	 *
+	 * @return org.eclipse.core.resources.IProject
+	 */
+	public IProject getProject();
+
+	/**
+	 * Returns the server configurations that are located in
+	 * this project.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServerConfigurations();
+
+	/**
+	 * Returns the servers that are located in this project.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServers();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerState.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerState.java
new file mode 100644
index 0000000..3d901f9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerState.java
@@ -0,0 +1,47 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerState extends IServer {	
+	/**
+	 * Set the server state.
+	 * 
+	 * @param state
+	 */
+	public void setServerState(byte state);
+
+	/**
+	 * Sets the server restart state.
+	 *
+	 * @param state boolean
+	 */
+	public void setRestartNeeded(boolean state);
+
+	/**
+	 * Sets the configuration sync state.
+	 *
+	 * @param state byte
+	 */
+	public void setConfigurationSyncState(byte state);
+
+	/**
+	 * Hook to fire an event when a module state changes.
+	 * 
+	 * @param module
+	 * @param state
+	 */
+	public void updateModuleState(IModule module);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerTask.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerTask.java
new file mode 100644
index 0000000..f3ef9f4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerTask.java
@@ -0,0 +1,62 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.List;
+
+import org.eclipse.wst.server.core.model.*;
+/**
+ * A task for a server.
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerTask extends ITask, IServerTaskDelegate, IOrdered {
+	/**
+	 * Returns the id of the adapter.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId();
+	
+	/**
+	 * Return the type ids that may be supported.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	public String[] getTypeIds();
+	
+	/**
+	 * Returns true if the given type (given by the id) can use this task. This
+	 * result is based on the result of the getTypeIds() method.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsType(String id);
+
+	/**
+	 * Lets the task know that it is about to be used. This method should
+	 * be used to clean out any previously cached information, or start to
+	 * create a new cache.
+	 * 
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param configuration org.eclipse.wst.server.core.model.IServerConfiguration
+	 * @param parents java.util.List[]
+	 * @param modules org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public void init(IServer server, IServerConfiguration configuration, List[] parents, IModule[] modules);
+
+	/**
+	 * Returns the status of this task.
+	 * 
+	 * @return byte
+	 */
+	public byte getTaskStatus();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerType.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerType.java
new file mode 100644
index 0000000..c84a481
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerType.java
@@ -0,0 +1,126 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerType extends IOrdered {
+	//	--- State Set Constants ---
+	// (returned from the getServerStateSet() method)
+	
+	// a server that can be directly started/stopped, etc.
+	public static final byte SERVER_STATE_SET_MANAGED = 0;
+	
+	// a server that is attached to, typically for debugging
+	public static final byte SERVER_STATE_SET_ATTACHED = 1;
+	
+	// a server that is only used for publishing
+	public static final byte SERVER_STATE_SET_PUBLISHED = 2;
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getId();
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getName();
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getDescription();
+
+	/**
+	 * 
+	 * @return
+	 */
+	public IRuntimeType getRuntimeType();
+	
+	public boolean hasRuntime();
+	
+	/**
+	 * Returns true if this server can start or may already be started
+	 * in the given mode, and false if not. Uses the launchConfigId attribute
+	 * to find the server's launch configuration.
+	 * 
+	 * @param launchMode String
+	 * @return boolean
+	 */
+	public boolean supportsLaunchMode(String launchMode);
+
+	/**
+	 * Returns an IStatus message to verify if a server of this type will be able
+	 * to run the module immediately after being created, without any user
+	 * interaction. If OK, this server may be used as a default server. This
+	 * method should return ERROR if the user must supply any information to
+	 * configure the server correctly, or if the module is not supported.
+	 *
+	 * @return org.eclipse.core.resources.IStatus
+	 */
+	//public IStatus isDefaultAvailable(IModule module);
+
+	/**
+	 * Returns the server state set that should be used to represent
+	 * this server. If the state set is SERVER_STATE_SET_MANAGED, this is
+	 * a runnable server that may be directly started and stopped.
+	 * (i.e. it should be represented as starting, started in debug mode,
+	 * etc.) If the state set is SERVER_STATE_SET_ATTACHED, this is a
+	 * server that can be attached to, typically for debugging purposes.
+	 * (i.e. it should be represented as attaching, attached for
+	 * debugging, etc.)
+	 *
+	 * @return byte
+	 */
+	public byte getServerStateSet();
+
+	public IServerConfigurationType getServerConfigurationType();
+
+	public boolean hasServerConfiguration();
+
+	public boolean supportsLocalhost();
+
+	public boolean supportsRemoteHosts();
+
+	/**
+	 * Returns true if the "monitorable" attribute is set. If true, this
+	 * server's delegate should implement IMonitorableServer.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isMonitorable();
+
+	/**
+	 * Returns true if the "testEnvironment" attribute is set. If true, this
+	 * server can only be created when there is an existing runtime that has
+	 * the property "testEnvironment" set to true.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isTestEnvironment();
+
+	/**
+	 * Create a server. If file is null, it will be created in metadata. Otherwise,
+	 * it will be associated with the given file.
+	 */
+	public IServerWorkingCopy createServer(String id, IFile file, IRuntime runtime) throws CoreException;
+	
+	public IServerWorkingCopy createServer(String id, IFile file, IProgressMonitor monitor) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerWorkingCopy.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerWorkingCopy.java
new file mode 100644
index 0000000..2f2c0b8
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/IServerWorkingCopy.java
@@ -0,0 +1,43 @@
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IServerWorkingCopyDelegate;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerWorkingCopy extends IServer, IElementWorkingCopy {	
+	public void setServerConfiguration(IServerConfiguration configuration);
+	
+	public IServer getOriginal();
+	
+	public IServerWorkingCopyDelegate getWorkingCopyDelegate();
+
+	public IServer save(IProgressMonitor monitor) throws CoreException;
+
+	public IServer saveAll(IProgressMonitor monitor) throws CoreException;
+
+	public void setRuntime(IRuntime runtime);
+
+	public void setHostname(String host);
+
+	/**
+	 * Add the given module to this configuration. The
+	 * module must exist, should not already be deployed
+	 * within the configuration, and canModifyModules()
+	 * should have returned true. The configuration must assume
+	 * any default settings and add the module without any UI.
+	 * 
+	 * Removes the given module from this configuration.
+	 * The module must already exist in the configuration.
+	 * When this method is called, the module may no
+	 * longer exist in the workbench or filesystem.
+	 *
+	 * @param add org.eclipse.wst.server.core.model.IModule[]
+	 * @param remove org.eclipse.wst.server.core.model.Module[]
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 */
+	public void modifyModules(IModule[] add, IModule[] remove, IProgressMonitor monitor) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ITask.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ITask.java
new file mode 100644
index 0000000..d4e99d9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ITask.java
@@ -0,0 +1,35 @@
+package org.eclipse.wst.server.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface ITask {
+	/**
+	 * Returns the label for this command.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getName();
+
+	/**
+	 * Returns a description of this command.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getDescription();
+
+	public ITaskModel getTaskModel();
+
+	public void setTaskModel(ITaskModel taskModel);
+
+	public boolean canExecute();
+
+	public void execute(IProgressMonitor monitor) throws CoreException;
+
+	public boolean canUndo();
+	
+	public void undo();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ITaskModel.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ITaskModel.java
new file mode 100644
index 0000000..aa83843
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ITaskModel.java
@@ -0,0 +1,14 @@
+package org.eclipse.wst.server.core;
+/**
+ * 
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface ITaskModel {
+	public static final String TASK_RUNTIME = "runtime";
+	public static final String TASK_SERVER = "server";
+	public static final String TASK_SERVER_CONFIGURATION = "server-configuration";
+
+	public Object getObject(String id);
+	
+	public void putObject(String id, Object obj);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ServerCore.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ServerCore.java
new file mode 100644
index 0000000..64236bb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ServerCore.java
@@ -0,0 +1,921 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.*;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.wst.server.core.internal.*;
+import org.eclipse.wst.server.core.model.*;
+import org.eclipse.wst.server.core.util.ProgressUtil;
+/**
+ * Base class for obtaining references to server models.
+ * 
+ * Also provides references for servers and server configurations.
+ * These references can be saved as tool or server-data and can be
+ * used to return the original resource if it still exists. These
+ * references are not OS specific and can be used in a team environment.
+ */
+public class ServerCore {
+	// server core plugin id
+	public static final String PLUGIN_ID = "org.eclipse.wst.server.core";
+
+	// cached copy of all server startups
+	private static List startups;
+
+	// cached copy of all module factories
+	private static List moduleFactories;
+
+	// cached copy of all module object adapters
+	private static List moduleObjectAdapters;
+
+	// cached copy of all launchable adapters
+	private static List launchableAdapters;
+
+	// cached copy of all launchable clients
+	private static List launchableClients;
+	
+	// cached copy of all module tasks
+	private static List moduleTasks;
+	
+	// cached copy of all server tasks
+	private static List serverTasks;
+	
+	//	cached copy of all module kinds
+	private static List moduleKinds;
+	
+	//	cached copy of all runtime types
+	private static List runtimeTypes;
+	
+	//	cached copy of all runtime target handlers
+	private static List runtimeTargetHandlers;
+	
+	//	cached copy of all runtime locators
+	private static List runtimeLocators;
+
+	//	cached copy of all server and configuration types
+	private static List serverTypes;
+	private static List serverConfigurationTypes;
+	
+	//	cached copy of all monitors
+	private static List monitors;
+
+	// cached copy of the server publisher classes
+	// keyed from String id to IPublishManager
+	private static Map publishManagers;
+	
+	// preferences
+	private static IServerPreferences preferences;
+
+	/**
+	 * ServerCore constructor comment.
+	 */
+	private ServerCore() {
+		super();
+	}
+
+	/**
+	 * Returns a map of all publishManagers, keyed by String id.
+	 *
+	 * @return java.util.Map
+	 */
+	public static Map getPublishManagers() {
+		if (publishManagers == null)
+			loadPublishManagers();
+		return publishManagers;
+	}
+
+	/**
+	 * Returns the publish manager with the given id.
+	 *
+	 * @return org.eclipse.wst.server.core.IPublishManager
+	 */
+	public static IPublishManager getPublishManager(String id) {
+		if (publishManagers == null)
+			loadPublishManagers();
+			
+		try {
+			return (IPublishManager) publishManagers.get(id);
+		} catch (Exception e) {
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the resource manager.
+	 *
+	 * @return org.eclipse.wst.server.core.IResourceManager
+	 */
+	public static IResourceManager getResourceManager() {
+		return ResourceManager.getInstance();
+	}
+	
+	/**
+	 * Returns the server monitor manager.
+	 *
+	 * @return org.eclipse.wst.server.core.IServerMonitorManager
+	 */
+	public static IServerMonitorManager getServerMonitorManager() {
+		return ServerMonitorManager.getInstance();
+	}
+
+	/**
+	 * Returns the preference information for the server core plugin.
+	 *
+	 * @return org.eclipse.wst.server.core.IServerPreferences
+	 */
+	public static IServerPreferences getServerPreferences() {
+		if (preferences == null)
+			preferences = new ServerPreferences();
+		return preferences;
+	}
+	
+	/**
+	 * Returns the preference information for the project.
+	 *
+	 * @return org.eclipse.wst.server.core.IServerProjectPreferences
+	 */
+	public static IProjectProperties getProjectProperties(IProject project) {
+		return new ProjectProperties(project);
+	}
+	
+	/**
+	 * Returns a List of all startups.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getStartups() {
+		if (startups == null)
+			loadStartups();
+		return startups;
+	}
+	
+	/**
+	 * Returns a List of all module kinds.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getModuleKinds() {
+		if (moduleKinds == null)
+			loadModuleKinds();
+		return moduleKinds;
+	}
+	
+	/**
+	 * Returns the module kind with the given id.
+	 *
+	 * @return org.eclipse.wst.server.core.IModuleKind
+	 */
+	public static IModuleKind getModuleKind(String id) {
+		if (id == null)
+			return null;
+
+		if (moduleKinds == null)
+			loadModuleKinds();
+		
+		Iterator iterator = moduleKinds.iterator();
+		while (iterator.hasNext()) {
+			IModuleKind moduleType = (IModuleKind) iterator.next();
+			if (id.equals(moduleType.getId()))
+				return moduleType;
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns a List of all runtime types.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getRuntimeTypes() {
+		if (runtimeTypes == null)
+			loadRuntimeTypes();
+		return runtimeTypes;
+	}
+	
+	/**
+	 * Returns the runtime type with the given id.
+	 *
+	 * @return org.eclipse.wst.server.core.IRuntimeType
+	 */
+	public static IRuntimeType getRuntimeType(String id) {
+		if (id == null)
+			return null;
+
+		if (runtimeTypes == null)
+			loadRuntimeTypes();
+		
+		Iterator iterator = runtimeTypes.iterator();
+		while (iterator.hasNext()) {
+			IRuntimeType runtimeType = (IRuntimeType) iterator.next();
+			if (id.equals(runtimeType.getId()))
+				return runtimeType;
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns a List of all runtime locators.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getRuntimeLocators() {
+		if (runtimeLocators == null)
+			loadRuntimeLocators();
+		return runtimeLocators;
+	}
+	
+	/**
+	 * Returns a List of all runtime target handlers.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getRuntimeTargetHandlers() {
+		if (runtimeTargetHandlers == null)
+			loadRuntimeTargetHandlers();
+		return runtimeTargetHandlers;
+	}
+	
+	/**
+	 * Returns the runtime target handler with the given id.
+	 *
+	 * @return org.eclipse.wst.server.core.IRuntimeTargetHandler
+	 */
+	public static IRuntimeTargetHandler getRuntimeTargetHandler(String id) {
+		if (id == null)
+			return null;
+
+		if (runtimeTargetHandlers == null)
+			loadRuntimeTargetHandlers();
+		
+		Iterator iterator = runtimeTargetHandlers.iterator();
+		while (iterator.hasNext()) {
+			IRuntimeTargetHandler runtimeTargetListener = (IRuntimeTargetHandler) iterator.next();
+			if (id.equals(runtimeTargetListener.getId()))
+				return runtimeTargetListener;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns a List of all server types.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getServerTypes() {
+		if (serverTypes == null)
+			loadServerTypes();
+		return serverTypes;
+	}
+	
+	/**
+	 * Returns the server type with the given id.
+	 *
+	 * @return org.eclipse.wst.server.core.IServerType
+	 */
+	public static IServerType getServerType(String id) {
+		if (id == null)
+			return null;
+
+		if (serverTypes == null)
+			loadServerTypes();
+		
+		Iterator iterator = serverTypes.iterator();
+		while (iterator.hasNext()) {
+			IServerType serverType = (IServerType) iterator.next();
+			if (id.equals(serverType.getId()))
+				return serverType;
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns a List of all server configuration types.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getServerConfigurationTypes() {
+		if (serverConfigurationTypes == null)
+			loadServerConfigurationTypes();
+		return serverConfigurationTypes;
+	}
+	
+	/**
+	 * Returns the server configuration type with the given id.
+	 *
+	 * @return org.eclipse.wst.server.core.IServerConfigurationType
+	 */
+	public static IServerConfigurationType getServerConfigurationType(String id) {
+		if (id == null)
+			return null;
+
+		if (serverConfigurationTypes == null)
+			loadServerConfigurationTypes();
+		
+		Iterator iterator = serverConfigurationTypes.iterator();
+		while (iterator.hasNext()) {
+			IServerConfigurationType serverConfigurationType = (IServerConfigurationType) iterator.next();
+			if (id.equals(serverConfigurationType.getId()))
+				return serverConfigurationType;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns a List of all module factories.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getModuleFactories() {
+		if (moduleFactories == null)
+			loadModuleFactories();
+		return moduleFactories;
+	}
+	
+	/**
+	 * Returns the module factory.
+	 *
+	 * @return java.util.List
+	 */
+	public static IModuleFactory getModuleFactory(String id) {
+		if (id == null)
+			return null;
+
+		if (moduleFactories == null)
+			loadModuleFactories();
+		
+		Iterator iterator = moduleFactories.iterator();
+		while (iterator.hasNext()) {
+			IModuleFactory factory = (IModuleFactory) iterator.next();
+			if (id.equals(factory.getId()))
+				return factory;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns a List of all module object adapters.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getModuleObjectAdapters() {
+		if (moduleObjectAdapters == null)
+			loadModuleObjectAdapters();
+		return moduleObjectAdapters;
+	}
+	
+	/**
+	 * Returns a List of all launchable adapters.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getLaunchableAdapters() {
+		if (launchableAdapters == null)
+			loadLaunchableAdapters();
+		return launchableAdapters;
+	}
+	
+	/**
+	 * Returns a List of all launchable clients.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getLaunchableClients() {
+		if (launchableClients == null)
+			loadLaunchableClients();
+		return launchableClients;
+	}
+	
+	/**
+	 * Returns a List of all module tasks.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getModuleTasks() {
+		if (moduleTasks == null)
+			loadModuleTasks();
+		return moduleTasks;
+	}
+	
+	/**
+	 * Returns a List of all server tasks.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getServerTasks() {
+		if (serverTasks == null)
+			loadServerTasks();
+		return serverTasks;
+	}
+	
+	/**
+	 * Returns a List of all server monitors.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getServerMonitors() {
+		if (monitors == null)
+			loadServerMonitors();
+		return monitors;
+	}
+
+	/**
+	 * Returns a list of all open server projects (IServerProjects)
+	 * in the workbench.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getServerNatures() {
+		try {
+			IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+	
+			List list = new ArrayList();
+			int size = projects.length;
+			for (int i = 0; i < size; i++) {
+				try {
+					if (projects[i].isOpen() && projects[i].hasNature(IServerProject.NATURE_ID))
+						list.add(projects[i].getNature(IServerProject.NATURE_ID));
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Error adding server nature", e);
+				}
+			}
+	
+			return list;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error getting server natures", e);
+			return new ArrayList();
+		}
+	}
+
+	/**
+	 * Returns a list of all server projects (IProjects) in
+	 * the workbench.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getServerProjects() {
+		try {
+			IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+	
+			List list = new ArrayList();
+			int size = projects.length;
+			for (int i = 0; i < size; i++) {
+				try {
+					if (projects[i].hasNature(IServerProject.NATURE_ID))
+						list.add(projects[i]);
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Error adding server nature project", e);
+				}
+			}
+
+			return list;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error getting server nature projects", e);
+			return new ArrayList();
+		}
+	}
+	
+	/**
+	 * Add the given nature to the project.
+	 *
+	 * @param monitor
+	 * @param project org.eclipse.core.resources.IProject
+	 */
+	private static boolean addNature(IProject project, String natureId, IProgressMonitor monitor) {
+		if (project == null)
+			return false;
+
+		try {
+			monitor = ProgressUtil.getMonitorFor(monitor);
+
+			// make sure the project is open
+			if (!project.isOpen()) {
+				monitor.beginTask(ServerPlugin.getResource("%createServerProjectTask"), 2000);
+				project.open(ProgressUtil.getSubMonitorFor(monitor, 1000));
+			} else
+				monitor.beginTask(ServerPlugin.getResource("%createServerProjectTask"), 1000);
+		
+			// get the current natures
+			IProjectDescription desc = project.getDescription();
+			String[] natureIds = desc.getNatureIds();
+			if (natureIds == null)
+				natureIds = new String[0];
+	
+			// check that the nature isn't already there..
+			int size = natureIds.length;
+			for (int i = 0; i < size; i++) {
+				if (natureId.equals(natureIds[i]))
+					return true;
+			}
+	
+			// otherwise, add the new nature
+			String[] newNatureIds = new String[size + 1];
+			System.arraycopy(natureIds, 0, newNatureIds, 0, size);
+			newNatureIds[size] = natureId;
+			desc.setNatureIds(newNatureIds);
+	
+			project.setDescription(desc, ProgressUtil.getSubMonitorFor(monitor, 1000));
+			return true;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not add nature to " + project.getName(), e);
+			return false;
+		} finally {
+			monitor.done();
+		}
+	}
+
+	/**
+	 * Creates a new server project with the given name. If path is
+	 * null, it will be created in the default location.
+	 *
+	 * @param name java.lang.String
+	 * @param path org.eclipse.core.resource.IPath
+	 * @param monitor
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public static IStatus createServerProject(String name, IPath path, IProgressMonitor monitor) {
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		monitor.beginTask(ServerPlugin.getResource("%createServerProjectTask"), 3000);
+
+		try {
+			IWorkspace workspace = ResourcesPlugin.getWorkspace();
+			IProject project = workspace.getRoot().getProject(name);
+	
+			// get a project descriptor
+			IProjectDescription description = workspace.newProjectDescription(name);
+			description.setLocation(path);
+	
+			project.create(description, ProgressUtil.getSubMonitorFor(monitor, 1000));
+			if (monitor.isCanceled())
+				return null;
+			project.open(ProgressUtil.getSubMonitorFor(monitor, 1000));
+			if (monitor.isCanceled())
+				return null;
+
+			// add the server project nature
+			addNature(project, IServerProject.NATURE_ID, ProgressUtil.getSubMonitorFor(monitor, 1000));
+	
+			if (monitor.isCanceled())
+				return null;
+	
+			return new Status(IStatus.OK, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%serverProjectCreated"), null);
+		} catch (CoreException ce) {
+			Trace.trace(Trace.SEVERE, "Could not create server project named " + name, ce);
+			return new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorCouldNotCreateServerProjectStatus", ce.getMessage()), ce);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not create server project (2) named " + name, e);
+			return new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorCouldNotCreateServerProject"), e);
+		} finally {
+			monitor.done();
+		}
+	}
+
+	/**
+	 * Load the server startups.
+	 */
+	private static void loadStartups() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .startup extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "startup");
+
+		int size = cf.length;
+		startups = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				IStartup startup = (IStartup) cf[i].createExecutableExtension("class");
+				startups.add(startup);
+				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);
+			}
+		}
+		
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .startup extension point -<-");
+	}
+	
+	/**
+	 * Load the module kinds.
+	 */
+	private static void loadModuleKinds() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .moduleKinds extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "moduleKinds");
+
+		int size = cf.length;
+		moduleKinds = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				ModuleKind moduleKind = new ModuleKind(cf[i]);
+				moduleKinds.add(moduleKind);
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded moduleKind: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load moduleKind: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .moduleKinds extension point -<-");
+	}
+
+	/**
+	 * Load the runtime types.
+	 */
+	private static void loadRuntimeTypes() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .runtimeTypes extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "runtimeTypes");
+
+		int size = cf.length;
+		runtimeTypes = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				RuntimeType runtimeType = new RuntimeType(cf[i]);
+				runtimeTypes.add(runtimeType);
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded runtimeType: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load runtimeType: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		ServerUtil.sortOrderedList(runtimeTypes);
+		
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .runtimeTypes extension point -<-");
+	}
+	
+	/**
+	 * Load the runtime locators.
+	 */
+	private static void loadRuntimeLocators() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .runtimeLocators extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "runtimeLocators");
+
+		int size = cf.length;
+		runtimeLocators = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				RuntimeLocator runtimeLocator = new RuntimeLocator(cf[i]);
+				runtimeLocators.add(runtimeLocator);
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded runtimeLocator: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load runtimeLocator: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .runtimeLocators extension point -<-");
+	}
+	
+	/**
+	 * Load the runtime target listeners.
+	 */
+	private static void loadRuntimeTargetHandlers() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .runtimeTargetHandlers extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "runtimeTargetHandlers");
+
+		int size = cf.length;
+		runtimeTargetHandlers = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				RuntimeTargetHandler runtimeTargetListener = new RuntimeTargetHandler(cf[i]);
+				runtimeTargetHandlers.add(runtimeTargetListener);
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded runtimeTargetHandler: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load runtimeTargetHandler: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		ServerUtil.sortOrderedList(runtimeTargetHandlers);
+		
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .runtimeTargetHandlers extension point -<-");
+	}
+
+	/**
+	 * Load the server types.
+	 */
+	private static void loadServerTypes() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .serverTypes extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "serverTypes");
+
+		int size = cf.length;
+		serverTypes = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				ServerType serverType = new ServerType(cf[i]);
+				serverTypes.add(serverType);
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded serverType: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load serverType: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		ServerUtil.sortOrderedList(serverTypes);
+		
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .serverTypes extension point -<-");
+	}
+
+	/**
+	 * Load the server configuration types.
+	 */
+	private static void loadServerConfigurationTypes() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .serverConfigurationTypes extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "serverConfigurationTypes");
+
+		int size = cf.length;
+		serverConfigurationTypes = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				ServerConfigurationType serverConfigurationType = new ServerConfigurationType(cf[i]);
+				serverConfigurationTypes.add(serverConfigurationType);
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded serverConfigurationType: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load serverConfigurationType: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		ServerUtil.sortOrderedList(serverConfigurationTypes);
+		
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .serverConfigurationTypes extension point -<-");
+	}
+
+	/**
+	 * Load the publish manager extension point.
+	 */
+	private static void loadPublishManagers() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .publish extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "publish");
+
+		int size = cf.length;
+		publishManagers = new HashMap(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				String id = cf[i].getAttribute("id");
+				IPublishManager publisher = new PublishManager(cf[i]);
+				publishManagers.put(id, publisher);
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded publish manager: " + id);
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load publish manager: " + cf[i].getAttribute("class"), t);
+			}
+		}
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .publisher extension point -<-");
+	}
+
+	/**
+	 * Load the module factories extension point.
+	 */
+	private static void loadModuleFactories() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .moduleFactories extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "moduleFactories");
+
+		int size = cf.length;
+		moduleFactories = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				moduleFactories.add(new ModuleFactory(cf[i]));
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded moduleFactories: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load moduleFactories: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		ServerUtil.sortOrderedList(moduleFactories);
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .moduleFactories extension point -<-");
+	}
+
+	/**
+	 * Load the module object adapters extension point.
+	 */
+	private static void loadModuleObjectAdapters() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .moduleObjectAdapters extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "moduleObjectAdapters");
+
+		int size = cf.length;
+		moduleObjectAdapters = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				moduleObjectAdapters.add(new ModuleObjectAdapter(cf[i]));
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded moduleObjectAdapter: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load moduleObjectAdapter: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .moduleObjectAdapters extension point -<-");
+	}
+	
+	/**
+	 * Load the launchable adapters extension point.
+	 */
+	private static void loadLaunchableAdapters() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .launchableAdapters extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "launchableAdapters");
+
+		int size = cf.length;
+		launchableAdapters = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				launchableAdapters.add(new LaunchableAdapter(cf[i]));
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded launchableAdapter: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load launchableAdapter: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .launchableAdapters extension point -<-");
+	}
+
+	/**
+	 * Load the launchable client extension point.
+	 */
+	private static void loadLaunchableClients() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .clients extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "clients");
+
+		int size = cf.length;
+		launchableClients = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				launchableClients.add(new Client(cf[i]));
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded clients: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load clients: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .clients extension point -<-");
+	}
+	
+	/**
+	 * Load the module task extension point.
+	 */
+	private static void loadModuleTasks() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .moduleTasks extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "moduleTasks");
+
+		int size = cf.length;
+		moduleTasks = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				moduleTasks.add(new ModuleTask(cf[i]));
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded moduleTask: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load moduleTask: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		ServerUtil.sortOrderedList(moduleTasks);
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .moduleTasks extension point -<-");
+	}
+
+	/**
+	 * Load the server task extension point.
+	 */
+	private static void loadServerTasks() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .serverTasks extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "serverTasks");
+
+		int size = cf.length;
+		serverTasks = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				serverTasks.add(new ServerTask(cf[i]));
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded serverTask: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load serverTask: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		
+		ServerUtil.sortOrderedList(serverTasks);
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .serverTasks extension point -<-");
+	}
+
+	/**
+	 * Load the server monitor extension point.
+	 */
+	private static void loadServerMonitors() {
+		Trace.trace(Trace.EXTENSION_POINT, "->- Loading .serverMonitors extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerCore.PLUGIN_ID, "serverMonitors");
+
+		int size = cf.length;
+		monitors = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				monitors.add(new ServerMonitor(cf[i]));
+				Trace.trace(Trace.EXTENSION_POINT, "  Loaded serverMonitor: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load serverMonitor: " + cf[i].getAttribute("id"), t);
+			}
+		}
+	
+		Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .serverMonitors extension point -<-");
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ServerUtil.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ServerUtil.java
new file mode 100644
index 0000000..98c72a0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/ServerUtil.java
@@ -0,0 +1,1014 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core;
+
+import java.util.*;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunchManager;
+
+import org.eclipse.wst.server.core.internal.ServerPlugin;
+import org.eclipse.wst.server.core.internal.Trace;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * Server utility methods.
+ */
+public class ServerUtil {
+	/**
+	 * Static class - cannot create an instance.
+	 */
+	private ServerUtil() { }
+
+	/**
+	 * Returns true if the given configuration currently contains
+	 * the given object.
+	 *
+	 * @param configuration org.eclipse.wst.server.core.model.IServerConfiguration
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return boolean
+	 */
+	public static boolean containsModule(IServer server, IModule module) {
+		if (server == null)
+			return false;
+		Trace.trace(Trace.FINEST, "containsModule() " + server + " " + module);
+		try {
+			Iterator iterator = getAllContainedModules(server).iterator();
+			while (iterator.hasNext()) {
+				IModule module2 = (IModule) iterator.next();
+				Trace.trace(Trace.FINEST, "module: " + module2 + " " + module.equals(module2));
+				if (module.equals(module2))
+					return true;
+			}
+		} catch (Throwable t) { }
+		return false;
+	}
+
+	/**
+	 * Returns all projects contained by the server. This included the
+	 * projects that are in the configuration, as well as their
+	 * children, and their children...
+	 *
+	 * @param configuration org.eclipse.wst.server.core.model.IServerConfiguration
+	 * @return java.util.List
+	 */
+	public static List getAllContainedModules(IServer server) {
+		//Trace.trace("> getAllContainedModules: " + getName(configuration));
+		List modules = new ArrayList();
+		if (server == null)
+			return modules;
+
+		// get all of the directly contained projects
+		IModule[] deploys = server.getModules();
+		if (deploys == null || deploys.length == 0)
+			return modules;
+
+		int size = deploys.length;
+		for (int i = 0; i < size; i++) {
+			if (deploys[i] != null && !modules.contains(deploys[i]))
+				modules.add(deploys[i]);
+		}
+
+		//Trace.trace("  getAllContainedModules: root level done");
+
+		// get all of the module's children
+		int count = 0;
+		while (count < modules.size()) {
+			IModule module = (IModule) modules.get(count);
+			try {
+				List childProjects = server.getChildModules(module);
+				if (childProjects != null) {
+					Iterator iterator = childProjects.iterator();
+					while (iterator.hasNext()) {
+						IModule child = (IModule) iterator.next();
+						if (child != null && !modules.contains(child))
+							modules.add(child);
+					}
+				}
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error getting child modules for: " + module.getName(), e);
+			}
+			count ++;
+		}
+
+		//Trace.trace("< getAllContainedModules");
+
+		return modules;
+	}
+
+	/**
+	 * Returns a list of all servers that this module is configured on.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return java.util.List
+	 */
+	public static IServer[] getServersByModule(IModule module) {
+		if (module == null)
+			return new IServer[0];
+
+		// do it the slow way - go through all servers and
+		// see if this module is configured in it
+		List list = new ArrayList();
+		List servers = ServerCore.getResourceManager().getServers();
+		Iterator iterator = servers.iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (containsModule(server, module))
+				list.add(server);
+		}
+		
+		IServer[] allServers = new IServer[list.size()];
+		list.toArray(allServers);
+		return allServers;
+	}
+	
+	/**
+	 * Returns a list of all servers that this module is configured on.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return java.util.List
+	 */
+	public static IServer[] getServersBySupportedModule(IModule module) {
+		if (module == null)
+			return new IServer[0];
+
+		// do it the slow way - go through all servers and
+		// see if this module is configured in it
+		List list = new ArrayList();
+		List servers = ServerCore.getResourceManager().getServers();
+		Iterator iterator = servers.iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (isSupportedModule(server.getServerType(), module))
+				list.add(server);
+		}
+		
+		IServer[] allServers = new IServer[list.size()];
+		list.toArray(allServers);
+		return allServers;
+	}
+
+	/**
+	 * Returns a list of configurations that are supported by this
+	 * server.
+	 *
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @return java.util.List
+	 */
+	public static List getSupportedServerConfigurations(IServer server) {
+		if (server == null)
+			return new ArrayList();
+	
+		List list = new ArrayList();
+	
+		List configs = ServerCore.getResourceManager().getServerConfigurations();
+		Iterator iterator = configs.iterator();
+		while (iterator.hasNext()) {
+			IServerConfiguration configuration = (IServerConfiguration) iterator.next();
+			//Trace.trace("Is supported configuration: " + getName(server) + " " + getName(configuration) + " " + server.isSupportedConfiguration(configuration));
+			if (server.isSupportedConfiguration(configuration))
+				list.add(configuration);
+		}
+		return list;
+	}
+
+	/**
+	 * Returns true if the given project is a server project.
+	 *
+	 * @param project org.eclipse.core.resources.IProject
+	 * @return boolean
+	 */
+	public static boolean isServerProject(IProject project) {
+		try {
+			return project.hasNature(IServerProject.NATURE_ID);
+		} catch (Exception e) {
+			return false;
+		}
+	}
+
+	/**
+	 * Returns the project modules attached to a project.
+	 */
+	public static IProjectModule getModuleProject(IProject project) {
+		if (project == null)
+			return null;
+
+		Iterator iterator = getModules(null, null, true).iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			if (module != null && module instanceof IProjectModule) {
+				IProjectModule moduleProject = (IProjectModule) module;
+				if (project.equals(moduleProject.getProject()))
+					return moduleProject;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns a module from the given factoryId and memento.
+	 * 
+	 * @param java.lang.String factoryId
+	 * @param java.lang.String memento
+	 * @return org.eclipse.wst.server.core.model.IModule
+	 */
+	public static IModule getModule(String factoryId, String memento) {
+		Iterator iterator = ServerCore.getModuleFactories().iterator();
+		while (iterator.hasNext()) {
+			IModuleFactory factory = (IModuleFactory) iterator.next();
+			if (factory.getId().equals(factoryId)) {
+				IModule module = factory.getModule(memento);
+				if (module != null) {
+					return module;
+				}
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns true if the given class name s is a superclass or interface of
+	 * the class obj.
+	 * 
+	 * @param c java.lang.Class
+	 * @param s java.lang.String
+	 * @return boolean
+	 */
+	protected static boolean isEnabled(Class c, String s) {
+		if (s == null || s.length() == 0)
+			return true;
+
+		while (c != null && c != Object.class) {
+			if (s.equals(c.getName()))
+				return true;
+			Class[] inf = c.getInterfaces();
+			if (inf != null) {
+				int size = inf.length;
+				for (int i = 0; i < size; i++) {
+					if (s.equals(inf[i].getName()))
+						return true;
+				}
+			}
+			c = c.getSuperclass();
+		}
+		return false;
+	}
+	
+	/**
+	 * Returns a module for the given object that may be launchable on
+	 * a server using the Run on Server option. Throws an exception if it
+	 * can't determine the object without possible plugin loading.
+	 * 
+	 * @param obj java.lang.Object
+	 * @return IModule
+	 * @throws java.lang.Exception
+	 */
+	public static IModule getModule(Object obj, boolean initialized) throws Exception {
+		if (obj == null)
+			return null;
+		Trace.trace(Trace.FINEST, "ServerUtil.getModule()");
+		Iterator iterator = ServerCore.getModuleObjectAdapters().iterator();
+		while (iterator.hasNext()) {
+			IModuleObjectAdapter adapter = (IModuleObjectAdapter) iterator.next();
+			
+			if (isEnabled(obj.getClass(), adapter.getObjectClassName())) {
+				if (!initialized) {
+					Trace.trace(Trace.FINEST, "getModule(): " + obj.getClass() + " " + adapter.getObjectClassName());
+					throw new Exception();
+				}
+				IModuleObject moduleObject = adapter.getModuleObject(obj);
+				if (moduleObject != null)
+					return moduleObject.getModule();
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns a list of the launchable clients for the given object.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getModuleObjects(Object obj) {
+		List list = new ArrayList();
+		Trace.trace(Trace.FINEST, "ServerUtil.getModuleObjects()");
+		Iterator iterator = ServerCore.getModuleObjectAdapters().iterator();
+		while (iterator.hasNext()) {
+			IModuleObjectAdapter adapter = (IModuleObjectAdapter) iterator.next();
+			if (isEnabled(obj.getClass(), adapter.getObjectClassName())) {
+				IModuleObject moduleObject = adapter.getModuleObject(obj);
+				Trace.trace(Trace.FINEST, "moduleObject: " + moduleObject);
+				if (moduleObject != null)
+					list.add(moduleObject);
+			}
+		}
+		return list;
+	}
+	
+	/**
+	 * Returns the first launchable object for the given server and module
+	 * object.
+	 * 
+	 * @param server
+	 * @param moduleObject
+	 * @return ILaunchable
+	 */
+	public static ILaunchable getLaunchable(IServer server, IModuleObject moduleObject) {
+		Iterator iterator = ServerCore.getLaunchableAdapters().iterator();
+		while (iterator.hasNext()) {
+			ILaunchableAdapter adapter = (ILaunchableAdapter) iterator.next();
+			try {
+				ILaunchable launchable = adapter.getLaunchable(server, moduleObject);
+				Trace.trace(Trace.FINEST, "adapter= " + adapter + ", launchable= " + launchable);
+				if (launchable != null)
+					return launchable;
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error in launchable adapter", e);
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the launchable clients for the given server and launchable
+	 * object.
+	 *
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param moduleObject org.eclipse.wst.server.core.model.IModuleObject
+	 * @param launchMode String
+	 * @return java.util.List
+	 */
+	public static List getLaunchableClients(IServer server, ILaunchable launchable, String launchMode) {
+		ArrayList list = new ArrayList();
+		Iterator iterator = ServerCore.getLaunchableClients().iterator();
+		while (iterator.hasNext()) {
+			IClient client = (IClient) iterator.next();
+			Trace.trace(Trace.FINEST, "client= " + client);
+			if (client.supports(server, launchable, launchMode)) {
+				list.add(client);
+			}
+		}
+		return list;
+	}
+
+	/**
+	 * Returns the first launchable object for the given server and module
+	 * object.
+	 * 
+	 * @param server
+	 * @param moduleObject
+	 * @return ILaunchable
+	 */
+	public static ILaunchable getLaunchable(IServer server, List moduleObjects) {
+		Iterator iterator = moduleObjects.iterator();
+		while (iterator.hasNext()) {
+			IModuleObject moduleObject = (IModuleObject) iterator.next();
+			ILaunchable launchable = getLaunchable(server, moduleObject);
+			if (launchable != null)
+				return launchable;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the factory that created the given server resource.
+	 * 
+	 * @param org.eclipse.wst.server.core.model.IServerResource
+	 * @return org.eclipse.wst.server.core.IServerResourceFactory
+	 */
+/*	public static IServerResourceFactory getServerResourceFactory(IServerResource resource) {
+		if (resource == null)
+			return null;
+		String id = resource.getFactoryId();
+		return ServerCore.getCreationManager().getServerResourceFactory(id);
+	}*/
+	
+	/**
+	 * Returns the factory that created the given module.
+	 *
+	 * @param org.eclipse.wst.server.core.model.IModule
+	 * @return org.eclipse.wst.server.core.IModuleFactory
+	 */
+	public static IModuleFactory getModuleFactory(IModule module) {
+		String id = module.getFactoryId();
+		if (id == null)
+			return null;
+
+		Iterator iterator = ServerCore.getModuleFactories().iterator();
+		while (iterator.hasNext()) {
+			IModuleFactory factory = (IModuleFactory) iterator.next();
+			if (id.equals(factory.getId()))
+				return factory;
+		}
+		return null;
+	}
+
+	/**
+	 * Return all the available modules from all factories whose
+	 * type includes the given id.
+	 * 
+	 * @param type java.lang.String
+	 * @param onlyProjectModules boolean
+	 * @return java.util.List
+	 */
+	public static List getModules(String type, String version, boolean onlyProjectModules) {
+		List list = new ArrayList();
+
+		Iterator iterator = ServerCore.getModuleFactories().iterator();
+		while (iterator.hasNext()) {
+			IModuleFactory factory = (IModuleFactory) iterator.next();
+			//if (!(onlyProjectModules && factory.isProjectModuleFactory())) {
+			if (isSupportedModule(factory.getModuleTypes(), type, version)) {
+					List modules = factory.getModules();
+					if (modules != null && !modules.isEmpty()) {
+						list.addAll(modules);
+					}
+				}
+			//}
+		}
+		return list;
+	}
+	
+	public static boolean isSupportedModule(IServerType serverType, IModuleType moduleType) {
+		IRuntimeType runtimeType = serverType.getRuntimeType();
+		return isSupportedModule(runtimeType.getModuleTypes(), moduleType.getType(), moduleType.getVersion());
+	}
+	
+	public static boolean isSupportedModule(List moduleTypes, String type, String version) {
+		Iterator iterator = moduleTypes.iterator();
+		while (iterator.hasNext()) {
+			IModuleType mt = (IModuleType) iterator.next();
+			if (isSupportedModule(mt, type, version))
+				return true;
+		}
+		return false;
+	}
+	
+	public static boolean isSupportedModule(IModuleType moduleType, String type, String version) {
+		String type2 = moduleType.getType();
+		if (matches(type, type2)) {
+			String version2 = moduleType.getVersion();
+			if (matches(version, version2))
+				return true;
+		}
+		return false;
+	}
+
+	protected static boolean matches(String a, String b) {
+		if (a == null || b == null || "*".equals(a) || "*".equals(b) || a.startsWith(b) || b.startsWith(a))
+			return true;
+		else
+			return false;
+	}
+	
+	/**
+	 * Return all the available modules from all factories.
+	 * 
+	 * @return java.util.List
+	 */
+	public static List getModules() {
+		List list = new ArrayList();
+		
+		Iterator iterator = ServerCore.getModuleFactories().iterator();
+		while (iterator.hasNext()) {
+			IModuleFactory factory = (IModuleFactory) iterator.next();
+			List modules = factory.getModules();
+			if (modules != null) {
+				Iterator iterator2 = modules.iterator();
+				while (iterator2.hasNext()) {
+					IModule module = (IModule) iterator2.next();
+					if (!list.contains(module))
+						list.add(module);
+				}
+			}
+		}
+		return list;
+	}
+	
+	/**
+	 * Adds or removes modules from a server. Will search for the first parent module
+	 * of each module and add it to the server instead. This method will handle multiple
+	 * modules having the same parent (the parent will only be added once), but may not
+	 * handle the case where the same module or parent is being both added and removed.
+	 * 
+	 * @param server
+	 * @param add
+	 * @param remove
+	 * @param monitor
+	 * @throws CoreException
+	 */
+	public static void modifyModules(IServerWorkingCopy server, IModule[] add, IModule[] remove, IProgressMonitor monitor) throws CoreException {
+		if (add == null)
+			add = new IModule[0];
+		if (remove == null)
+			remove = new IModule[0];
+		
+		int size = add.length;
+		List addParentModules = new ArrayList();
+		for (int i = 0; i < size; i++) {
+			boolean found = false;
+			try {
+				List parents = server.getParentModules(add[i]);
+				if (parents != null) {
+					found = true;
+					if (parents.size() > 0) {				
+						Object parent = parents.get(0);
+						found = true;
+						if (!addParentModules.contains(parent))
+							addParentModules.add(parent);
+					}
+				} 
+			} catch (Exception e) {
+				Trace.trace(Trace.WARNING, "Could not find parent module", e);
+			}
+			
+			if (!found)
+				addParentModules.add(add[i]);
+		}
+		
+		size = remove.length;
+		List removeParentModules = new ArrayList();
+		for (int i = 0; i < size; i++) {
+			boolean found = false;
+			try {
+				List parents = server.getParentModules(remove[i]);
+				if (parents != null) {
+					found = true;
+					if (parents.size() > 0) {				
+						Object parent = parents.get(0);
+						found = true;
+						if (!removeParentModules.contains(parent))
+							removeParentModules.add(parent);
+					}
+				} 
+			} catch (Exception e) {
+				Trace.trace(Trace.WARNING, "Could not find parent module 2", e);
+			}
+			
+			if (!found)
+				removeParentModules.add(remove[i]);
+		}
+		
+		IModule[] add2 = new IModule[addParentModules.size()];
+		addParentModules.toArray(add2);
+		IModule[] remove2 = new IModule[removeParentModules.size()];
+		removeParentModules.toArray(remove2);
+		
+		server.modifyModules(add2, remove2, monitor);
+	}
+
+	/**
+	 * Returns true if the given server is already started in the given
+	 * mode, or could be (re)started in the start mode.
+	 * 
+	 * @param server org.eclipse.wst.server.core.IServer
+	 * @param launchMode java.lang.String
+	 * @return boolean
+	 */
+	public static boolean isCompatibleWithLaunchMode(IServer server, String launchMode) {
+		if (server == null)
+			return false;
+
+		byte state = server.getServerState();
+		if ((state == IServer.SERVER_STARTED && launchMode.equals(ILaunchManager.RUN_MODE)) ||
+			(state == IServer.SERVER_STARTED_DEBUG && launchMode.equals(ILaunchManager.DEBUG_MODE)) ||
+			(state == IServer.SERVER_STARTED_PROFILE && launchMode.equals(ILaunchManager.PROFILE_MODE)))
+			return true;
+		if (server.getServerType().supportsLaunchMode(launchMode))
+			return true;
+		return false;
+	}
+
+	/**
+	 * Filters the servers to those that are already started in the given launchMode
+	 * or can be (re)started in the given launchMode.
+	 * 
+	 * @param server org.eclipse.wst.server.core.IServer[]
+	 * @param launchMode java.lang.String
+	 * @return org.eclipse.wst.server.core.IServer[]
+	 */
+	public static IServer[] filterServersByLaunchMode(IServer[] servers, String launchMode) {
+		if (servers == null || servers.length == 0)
+			return servers;
+		
+		int size = servers.length;
+		List list = new ArrayList();
+		for (int i = 0; i < size; i++) {
+			if (isCompatibleWithLaunchMode(servers[i], launchMode))
+				list.add(servers[i]);
+		}
+		IServer[] temp = new IServer[list.size()];
+		list.toArray(temp);
+		return temp;
+	}
+	
+	/**
+	 * Visit all the modules in the server configuration.
+	 */
+	public static void visit(IServer server, IModuleVisitor visitor) {
+		if (server == null)
+			return;
+		
+		IModule[] modules = server.getModules();
+		if (modules != null) { 
+			int size = modules.length;
+			for (int i = 0; i < size; i++) {
+				if (!visitModule(server, new ArrayList(), modules[i], visitor))
+					return;
+			}
+		}
+	}
+
+	/**
+	 * Returns true to keep visiting, and false to stop.
+	 */
+	private static boolean visitModule(IServer server, List parents, IModule module, IModuleVisitor visitor) {
+		if (server == null || module == null || parents == null)
+			return true;
+		
+		if (!visitor.visit(parents, module))
+			return false;
+		
+		List children = server.getChildModules(module);
+		if (children != null) {
+			Iterator iterator = children.iterator();
+			while (iterator.hasNext()) {
+				IModule module2 = (IModule) iterator.next();
+				
+				List parents2 = new ArrayList(parents.size() + 1);
+				parents2.addAll(parents);
+				parents2.add(module);
+				
+				if (!visitModule(server, parents2, module2, visitor))
+					return false;
+			}
+		}
+			
+		return true;
+	}
+
+	public static boolean isNameInUse(IRuntime runtime) {
+		Iterator iterator = ServerCore.getResourceManager().getRuntimes().iterator();
+		while (iterator.hasNext()) {
+			IRuntime runtime2 = (IRuntime) iterator.next();
+			if (!runtime.equals(runtime2) && runtime.getName().equals(runtime2.getName()))
+				return true;
+		}
+		return false;
+	}
+
+	public static void setRuntimeDefaultName(IRuntimeWorkingCopy wc) {
+		String typeName = wc.getRuntimeType().getName();
+		
+		String name = ServerPlugin.getResource("%defaultRuntimeName", new String[] {typeName});
+		int i = 2;
+		while (isNameInUse(name)) {
+			name = ServerPlugin.getResource("%defaultRuntimeName2", new String[] {typeName, i + ""});
+			i++;
+		}
+		wc.setName(name);
+	}
+
+	public static void setServerDefaultName(IServerWorkingCopy wc) {
+		String typeName = wc.getServerType().getName();
+		String host = wc.getHostname();
+		
+		String name = ServerPlugin.getResource("%defaultServerName", new String[] {typeName, host});
+		int i = 2;
+		while (isNameInUse(name)) {
+			name = ServerPlugin.getResource("%defaultServerName2", new String[] {typeName, host, i + ""});
+			i++;
+		}
+		wc.setName(name);
+	}
+
+	public static void setServerConfigurationDefaultName(IServerConfigurationWorkingCopy wc) {
+		String typeName = wc.getServerConfigurationType().getName();
+		
+		String name = ServerPlugin.getResource("%defaultServerConfigurationName", new String[] {typeName});
+		int i = 2;
+		while (isNameInUse(name)) {
+			name = ServerPlugin.getResource("%defaultServerConfigurationName2", new String[] {typeName, i + ""});
+			i++;
+		}
+		wc.setName(name);
+	}
+	
+	public static IProject getDefaultServerProject() {
+		IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+		if (projects != null) {
+			int size = projects.length;
+			for (int i = 0; i < size; i++) {
+				if (ServerUtil.isServerProject(projects[i]))
+					return projects[i];
+			}
+		}
+		return ResourcesPlugin.getWorkspace().getRoot().getProject(findUnusedServerProjectName());
+	}
+
+	private static boolean isValidFilename(String name) {
+		IStatus status = ResourcesPlugin.getWorkspace().validateName(name, IResource.FILE);
+		if (status != null && !status.isOK())
+			return false;
+		
+		status = ResourcesPlugin.getWorkspace().validateName(name, IResource.FOLDER);
+		if (status != null && !status.isOK())
+			return false;
+		
+		return true;
+	}
+
+	private static String getValidFileName(String name) {
+		if (isValidFilename(name))
+			return name;
+	
+		// remove invalid characters
+		String[] s = new String[] {".", "\\", "/", "?", ":", "*", "\"", "|", "<", ">"};
+		int ind = 0;
+		while (ind < s.length) {
+			int index = name.indexOf(s[ind]);
+			while (index >= 0) {
+				name = name.substring(0, index) + name.substring(index+1);
+				index = name.indexOf(s[ind]);
+			}
+			ind++;
+		}
+		return name;
+	}
+
+	public static IFile getUnusedServerFile(IProject project, IServerType type) {
+		String typeName = getValidFileName(type.getName());
+		String name = ServerPlugin.getResource("%defaultServerName3", new String[] {typeName})+ "."  + IServer.FILE_EXTENSION;
+		int i = 2;
+		while (isFileNameInUse(project, name)) {
+			name = ServerPlugin.getResource("%defaultServerName4", new String[] {typeName, i + ""}) + "."  + IServer.FILE_EXTENSION;
+			i++;
+		}
+		return project.getFile(name);
+	}
+
+	public static IFile getUnusedServerConfigurationFile(IProject project, IServerConfigurationType type) {
+		String typeName = getValidFileName(type.getName());
+		String name = ServerPlugin.getResource("%defaultServerConfigurationName", new String[] {typeName}) + "."  + IServerConfiguration.FILE_EXTENSION;
+		int i = 2;
+		while (isFileNameInUse(project, name)) {
+			name = ServerPlugin.getResource("%defaultServerConfigurationName2", new String[] {typeName, i + ""}) + "."  + IServerConfiguration.FILE_EXTENSION;
+			i++;
+		}
+		return project.getFile(name);
+	}
+
+	/**
+	 * Returns true if an element exists with the given name.
+	 *
+	 * @param name java.lang.String
+	 * @return boolean
+	 */
+	private static boolean isNameInUse(String name) {
+		if (name == null)
+			return true;
+	
+		IResourceManager rm = ServerCore.getResourceManager();
+		List list = new ArrayList();
+		list.addAll(rm.getRuntimes());
+		list.addAll(rm.getServers());
+		list.addAll(rm.getServerConfigurations());
+
+		Iterator iterator = list.iterator();
+		while (iterator.hasNext()) {
+			IElement element = (IElement) iterator.next();
+			if (name.equalsIgnoreCase(element.getName()))
+				return true;
+		}
+
+		return false;
+	}
+	
+	/**
+	 * Returns true if an element exists with the given name.
+	 *
+	 * @param name java.lang.String
+	 * @return boolean
+	 */
+	private static boolean isFileNameInUse(IProject project, String name) {
+		if (name == null || project == null)
+			return false;
+		
+		if (project.getFile(name).exists())
+			return true;
+		if (project.getFolder(name).exists())
+			return true;
+	
+		return false;
+	}
+
+	/**
+	 * Finds an unused project name to use as a server project.
+	 * 
+	 * @return java.lang.String
+	 */
+	private static String findUnusedServerProjectName() {
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		String name = ServerPlugin.getResource("%defaultServerProjectName", "");
+		int count = 1;
+		while (root.getProject(name).exists()) {
+			name = ServerPlugin.getResource("%defaultServerProjectName", ++count + "");
+		}
+		return name;
+	}
+	
+	/**
+	 * Sort the given list of IOrdered items into indexed order. This method
+	 * modifies the original list, but returns the value for convenience.
+	 *
+	 * @param list java.util.List
+	 * @return java.util.List
+	 */
+	public static List sortOrderedList(List list) {
+		if (list == null)
+			return null;
+
+		int size = list.size();
+		for (int i = 0; i < size - 1; i++) {
+			for (int j = i + 1; j < size; j++) {
+				IOrdered a = (IOrdered) list.get(i);
+				IOrdered b = (IOrdered) list.get(j);
+				if (a.getOrder() > b.getOrder()) {
+					Object temp = a;
+					list.set(i, b);
+					list.set(j, temp);
+				}
+			}
+		}
+		return list;
+	}
+	
+	/**
+	 * Sort the given list of IOrdered items into reverse indexed order. This method
+	 * modifies the original list, but returns the value for convenience.
+	 *
+	 * @param list java.util.List
+	 * @return java.util.List
+	 */
+	public static List sortOrderedListReverse(List list) {
+		if (list == null)
+			return null;
+
+		int size = list.size();
+		for (int i = 0; i < size - 1; i++) {
+			for (int j = i + 1; j < size; j++) {
+				IOrdered a = (IOrdered) list.get(i);
+				IOrdered b = (IOrdered) list.get(j);
+				if (a.getOrder() < b.getOrder()) {
+					Object temp = a;
+					list.set(i, b);
+					list.set(j, temp);
+				}
+			}
+		}
+		return list;
+	}
+
+	/**
+	 * Return a list of all runtime targets that match the given type and version.
+	 * If type or version is null, it matches all of that type or version.
+	 * 
+	 * @param type
+	 * @param version
+	 * @return 
+	 */
+	public static List getRuntimes(String type, String version) {
+		List list = new ArrayList();
+		Iterator iterator = ServerCore.getResourceManager().getRuntimes().iterator();
+		while (iterator.hasNext()) {
+			IRuntime runtime = (IRuntime) iterator.next();
+			IRuntimeType runtimeType = runtime.getRuntimeType();
+			if (runtimeType != null && isSupportedModule(runtimeType.getModuleTypes(), type, version)) {
+				list.add(runtime);
+			}
+		}
+		return list;
+	}
+
+	/**
+	 * Return a list of all runtime types that match the given type and version.
+	 * If type or version is null, it matches all of that type or version.
+	 * 
+	 * @param type
+	 * @param version
+	 * @return 
+	 */
+	public static List getRuntimeTypes(String type, String version) {
+		List list = new ArrayList();
+		Iterator iterator = ServerCore.getRuntimeTypes().iterator();
+		while (iterator.hasNext()) {
+			IRuntimeType runtimeType = (IRuntimeType) iterator.next();
+			if (isSupportedModule(runtimeType.getModuleTypes(), type, version)) {
+				list.add(runtimeType);
+			}
+		}
+		return list;
+	}
+	
+	/**
+	 * Return a list of all runtime types that match the given type, version,
+	 * and partial runtime type id. If type, version, or runtimeTypeId is null,
+	 * it matches all of that type or version.
+	 * 
+	 * @param type
+	 * @param version
+	 * @return 
+	 */
+	public static List getRuntimeTypes(String type, String version, String runtimeTypeId) {
+		List list = new ArrayList();
+		Iterator iterator = ServerCore.getRuntimeTypes().iterator();
+		while (iterator.hasNext()) {
+			IRuntimeType runtimeType = (IRuntimeType) iterator.next();
+			if (isSupportedModule(runtimeType.getModuleTypes(), type, version)) {
+				if (runtimeTypeId == null || runtimeType.getId().startsWith(runtimeTypeId))
+					list.add(runtimeType);
+			}
+		}
+		return list;
+	}
+
+	/**
+	 * Returns a list of all servers that this deployable is not currently
+	 * configured on, but could be added to. If includeErrors is true, this
+	 * method return servers where the parent deployable may throw errors. For
+	 * instance, this deployable may be the wrong spec level.
+	 *
+	 * @param module com.ibm.etools.server.core.model.IModule
+	 * @return com.ibm.etools.server.core.model.IServer[]
+	 */
+	public static IServer[] getAvailableServersForModule(IModule module, boolean includeErrors) {
+		if (module == null)
+			return new IServer[0];
+
+		// do it the slow way - go through all servers and
+		// see if this deployable is not configured in it
+		// but could be added
+		List list = new ArrayList();
+		List servers = ServerCore.getResourceManager().getServers();
+		Iterator iterator = servers.iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (!containsModule(server, module)) {
+				try {
+					List parents = server.getParentModules(module);
+					if (parents != null && !parents.isEmpty()) {
+						Iterator iterator2 = parents.iterator();
+						boolean found = false;
+						while (!found && iterator2.hasNext()) {
+							IModule parent = (IModule) iterator2.next();
+							IStatus status = server.canModifyModules(new IModule[] { parent }, new IModule[0]);
+							if (status == null || status.isOK()){
+								list.add(server);
+								found = true;
+							}
+						}
+					}
+				} catch (Exception se) {
+					if (includeErrors)
+						list.add(server);
+				}
+			}
+		}
+		
+		// make sure that the preferred server is the first one
+		/*IServer server = ServerCore.getServerPreferences().getDeployableServerPreference(deployable);
+		if (server != null && list.contains(server) && list.indexOf(server) != 0) {
+			list.remove(server);
+			list.add(0, server);
+		}*/
+
+		IServer[] allServers = new IServer[list.size()];
+		list.toArray(allServers);
+		return allServers;
+	}
+	
+	public static boolean isDefaultAvailable(IServerType serverType, IModuleType moduleType) {
+		if (!isSupportedModule(serverType, moduleType))
+			return false;
+	
+		// remote servers won't automatically work (i.e. without hostname)
+		if (!serverType.supportsLocalhost())
+			return false;
+		
+		// if it needs a runtime, check if there is one
+		if (serverType.hasRuntime()) {
+			if (ServerCore.getResourceManager().getRuntimes(serverType.getRuntimeType()).isEmpty())
+				return false;
+		}
+		return true;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/AbstractPublisher.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/AbstractPublisher.java
new file mode 100644
index 0000000..cf741b7
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/AbstractPublisher.java
@@ -0,0 +1,334 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.*;
+import org.eclipse.wst.server.core.resources.*;
+/**
+ * Abstract class for publishing support.
+ */
+public abstract class AbstractPublisher implements IPublishManagerDelegate {
+	protected Map deleteMap;
+	protected Map publishMap;
+
+	protected List delete;
+	protected List publish;
+	protected IModule module;
+
+	protected Map resourceMap;
+
+	protected IPublishControl control;
+	
+	private static final List EMPTY_LIST = new ArrayList(0);
+
+	/**
+	 * AbstractPublisher constructor comment.
+	 */
+	public AbstractPublisher() {
+		super();
+	}
+	
+	/**
+	 * 
+	 */
+	protected void deleteResources(IRemoteResource remote, List delete2, List visited, IProgressMonitor monitor) {
+		if (remote == null)
+			return;
+	
+		/*if (!visited.contains(resource)) {
+			delete.add(resource);
+		}*/
+		IModuleResource resource = null;
+		try {
+			resource = (IModuleResource) resourceMap.get(remote.getPath());
+		} catch (Exception e) {
+			//Trace.trace("Error in abstract publisher", e);
+		}
+	
+		if (shouldDelete(resource, null, remote, IRemoteResource.TIMESTAMP_UNKNOWN, control.getPublishedTimestamp(remote))) {
+			delete2.add(remote);
+		}
+	
+		if (remote instanceof IRemoteFolder) {
+			IRemoteFolder folder = (IRemoteFolder) remote;
+			Iterator iterator = folder.getContents().iterator();
+			while (iterator.hasNext()) {
+				IRemoteResource sub = (IRemoteResource) iterator.next();
+				deleteResources(sub, delete2, visited, monitor);
+			}
+		}
+	}
+	
+	protected IRemoteResource findRemoteResource(IRemoteFolder folder, IPath path) {
+		Iterator iterator = folder.getContents().iterator();
+		while (iterator.hasNext()) {
+			IRemoteResource remote = (IRemoteResource) iterator.next();
+			if (path.equals(remote.getPath()))
+				return remote;
+			if (remote instanceof IRemoteFolder) {
+				IRemoteFolder folder2 = (IRemoteFolder) remote;
+				IPath folderPath = folder2.getPath();
+				if (folderPath.isPrefixOf(path)) {
+					IRemoteResource rem = findRemoteResource(folder2, path);
+					if (rem != null)
+						return rem;
+				}
+			}
+		}
+		return null;
+	}
+	
+	protected IRemoteResource findRemoteResource(IPath path) {
+		if (path == null)
+			return null;
+	
+		IRemoteResource[] resources = control.getRemoteResources();
+		int size = resources.length;
+		for (int i = 0; i < size; i++) {
+			IRemoteResource remote = resources[i];
+			
+			if (path.equals(remote.getPath()))
+				return remote;
+			if (remote instanceof IRemoteFolder) {
+				IRemoteFolder folder2 = (IRemoteFolder) remote;
+				IPath folderPath = folder2.getPath();
+				if (folderPath.isPrefixOf(path)) {
+					IRemoteResource rem = findRemoteResource(folder2, path);
+					if (rem != null)
+						return rem;
+				}
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns the list of remote resources to delete from the
+	 * remote machine.
+	 *
+	 * @return java.util.List
+	 */
+	public List getResourcesToDelete(IModule module2) {
+		try {
+			return (List) deleteMap.get(module2);
+		} catch (Exception e) {
+			return EMPTY_LIST;
+		}
+	}
+	
+	/**
+	 * Returns the list of resources to publish to the
+	 * remote machine.
+	 *
+	 * @return java.util.List
+	 */
+	public List getResourcesToPublish(IModule module2) {
+		try {
+			return (List) publishMap.get(module2);
+		} catch (Exception e) {
+			return EMPTY_LIST;
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	protected void publishResources(IModuleResource resource, List publish2, List visited, IProgressMonitor monitor) {
+		if (resource == null)
+			return;
+	
+		IPath path = control.getMappedLocation(resource);
+		resourceMap.put(path, resource);
+	
+		if (path != null) {
+			IRemoteResource remote = findRemoteResource(path);
+			if (!(resource instanceof IModuleFolder && remote != null)) { // don't republish directories that already exist
+				if (shouldPublish(resource, path, remote, control.getPublishedTimestamp(resource), control.getPublishedTimestamp(remote))) {
+					publish2.add(resource);
+				}
+			}
+		}
+	
+		if (resource instanceof IModuleFolder) {
+			IModuleFolder cont = (IModuleFolder) resource;
+			if (control.shouldMapMembers(cont)) {
+				try {
+					IModuleResource[] sub = cont.members();
+					if (sub != null) {
+						int size = sub.length;
+						for (int i = 0; i < size; i++)
+							publishResources(sub[i], publish2, visited, monitor);
+					}
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Error in abstract publisher", e);
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Sets the publish control, used to obtain information about
+	 * the publishing.
+	 *
+	 * Sets the publish state, used to determine the timestamps
+	 * of the last publishing action.
+	 * 
+	 * Resolve which resources to publish or delete.
+	 *
+	 * @param controls org.eclipse.wst.server.model.IPublishControl[]
+	 * @param modules org.eclipse.wst.server.core.model.IModule[]
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 */
+	public void resolve(IPublishControl[] controls, IModule[] modules, IProgressMonitor monitor) {
+		int size = controls.length;
+		Trace.trace(Trace.FINEST, "Abstract publisher starting " + size);
+		
+		deleteMap = new HashMap(size);
+		publishMap = new HashMap(size);
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.FINEST, "Resolving: " + modules[i]);
+			this.control = controls[i];
+			this.module = modules[i];
+			
+			delete = new ArrayList();
+			publish = new ArrayList();
+
+			resourceMap = new HashMap();
+
+			resolveModule(monitor);
+			
+			Trace.trace(Trace.FINEST, "Deleting " + delete.size() + " resources");
+			Trace.trace(Trace.FINEST, "Publishing " + publish.size() + " resources");
+			deleteMap.put(modules[i], delete);
+			publishMap.put(modules[i], publish);
+		}
+	}
+	
+	/**
+	 * Resolve which resources to publish or delete. Both setXxx()
+	 * methods will have been called before this method.
+	 */
+	protected void resolveModule(IProgressMonitor monitor) {
+		List visited = new ArrayList();
+	
+		// first, decide which files to publish
+		Trace.trace(Trace.FINEST, "Resolving publish for " + module);
+		try {
+			publish = new ArrayList();
+			IModuleResource[] resources = module.members();
+			if (resources != null) {
+				int size = resources.length;
+				for (int i = 0; i < size; i++)
+					publishResources(resources[i], publish, visited, monitor);
+			}
+			sortPublishList(publish);
+		} catch (Exception e) {
+		}
+	
+		// next, choose which files to delete
+		Trace.trace(Trace.FINEST, "Resolving delete for " + module);
+		delete = new ArrayList();
+		IRemoteResource[] resources = control.getRemoteResources();
+		if (resources != null) {
+			int size = resources.length;
+			for (int i = 0; i < size; i++) {
+				IRemoteResource remote = resources[i];
+				deleteResources(remote, delete, visited, monitor);
+			}
+		}
+		sortDeletionList(delete);
+	}
+
+	/**
+	 * Returns true if the remote resource should be deleted, and false
+	 * if it should be left on the server.
+	 *
+	 * @return boolean
+	 * @param option int
+	 */
+	public abstract boolean shouldDelete(IModuleResource resource, IPath path, IRemoteResource remote, long resourceTimestamp, long remoteTimestamp);
+
+	/**
+	 * Returns true if the resource should be published, and false
+	 * if it should be left on the server.
+	 *
+	 * @return boolean
+	 * @param option int
+	 */
+	public abstract boolean shouldPublish(IModuleResource resource, IPath path, IRemoteResource remote, long resourceTimestamp, long remoteTimestamp);
+
+	/**
+	 * Sorts the deletions so that directories are last and
+	 * appear in "reverse depth order".
+	 */
+	public static void sortDeletionList(List list) {
+		if (list == null)
+			return;
+	
+		int size = list.size();
+		for (int i = 0; i < size - 1; i++) {
+			for (int j = i + 1; j < size; j++) {
+				Object a = list.get(i);
+				Object b = list.get(j);
+	
+				boolean swap = false;
+				if (a instanceof IRemoteFolder && !(b instanceof IRemoteFolder))
+					swap = true;
+				else if (a instanceof IRemoteFolder && b instanceof IRemoteFolder) {
+					IRemoteFolder rfa = (IRemoteFolder) a;
+					IRemoteFolder rfb = (IRemoteFolder) b;
+					if (rfa.getPath().isPrefixOf(rfb.getPath()))
+						swap = true;
+				}
+	
+				if (swap) {
+					list.set(i, b);
+					list.set(j, a);
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Sorts the publishes so that directories are first and are
+	 * in "depth order". (subdirectories appear after their parents)
+	 */
+	public static void sortPublishList(List list) {
+		if (list == null)
+			return;
+	
+		int size = list.size();
+		for (int i = 0; i < size - 1; i++) {
+			for (int j = i + 1; j < size; j++) {
+				Object a = list.get(i);
+				Object b = list.get(j);
+	
+				boolean swap = false;
+				if (!(a instanceof IModuleFolder) && b instanceof IModuleFolder)
+					swap = true;
+				else if (a instanceof IModuleFolder && b instanceof IModuleFolder) {
+					IModuleFolder ca = (IModuleFolder) a;
+					IModuleFolder cb = (IModuleFolder) b;
+					if (cb.getPath().isPrefixOf(ca.getPath()))
+						swap = true;
+				}
+	
+				if (swap) {
+					list.set(i, b);
+					list.set(j, a);
+				}
+			}
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Base.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Base.java
new file mode 100644
index 0000000..a5fbed4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Base.java
@@ -0,0 +1,369 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.wst.server.core.IElementWorkingCopy;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.util.ProgressUtil;
+/**
+ * 
+ */
+public abstract class Base {
+	protected static final String PROP_LOCKED = "locked";
+	protected static final String PROP_PRIVATE = "private";
+	protected static final String PROP_NAME = "name";
+	protected static final String PROP_ID = "id";
+
+	protected Map map = new HashMap();
+	
+	protected List workingCopies;
+	
+	// file loaded from, or null if it is saved in metadata
+	protected IFile file;
+	
+	public Base(IFile file) {
+		this.file = file;
+	}
+
+	public Base(IFile file, String id) {
+		this.file = file;
+		//this.map = map;
+		map.put(PROP_ID, id);
+	}
+	
+	public IFile getFile() {
+		return file;
+	}
+
+	public String getAttribute(String attributeName, String defaultValue) {
+		try {
+			Object obj = map.get(attributeName);
+			if (obj == null)
+				return defaultValue;
+			return (String) obj;
+		} catch (Exception e) { }
+		return defaultValue;
+	}
+
+	public int getAttribute(String attributeName, int defaultValue) {
+		try {
+			Object obj = map.get(attributeName);
+			if (obj == null)
+				return defaultValue;
+			return Integer.parseInt((String) obj);
+		} catch (Exception e) { }
+		return defaultValue;
+	}
+
+	public boolean getAttribute(String attributeName, boolean defaultValue) {
+		try {
+			Object obj = map.get(attributeName);
+			if (obj == null)
+				return defaultValue;
+			return Boolean.valueOf((String) obj).booleanValue();
+		} catch (Exception e) { }
+		return defaultValue;
+	}
+	
+	public List getAttribute(String attributeName, List defaultValue) {
+		try {
+			Object obj = map.get(attributeName);
+			if (obj == null)
+				return defaultValue;
+			List list = (List) obj;
+			if (list != null)
+				return list;
+		} catch (Exception e) { }
+		return defaultValue;
+	}
+	
+	public Map getAttribute(String attributeName, Map defaultValue) {
+		try {
+			Object obj = map.get(attributeName);
+			if (obj == null)
+				return defaultValue;
+			Map map2 = (Map) obj;
+			if (map2 != null)
+				return map2;
+		} catch (Exception e) { }
+		return defaultValue;
+	}
+
+	public String getId() {
+		return getAttribute(PROP_ID, "");
+	}
+
+	public String getName() {
+		return getAttribute(PROP_NAME, "");
+	}
+
+	public boolean isLocked() {
+		return getAttribute(PROP_LOCKED, false);
+	}
+
+	public boolean isPrivate() {
+		return getAttribute(PROP_PRIVATE, false);
+	}
+	
+	public boolean isWorkingCopy() {
+		return false;
+	}
+	
+	protected abstract String getXMLRoot();
+	
+	protected void save(IMemento memento) {
+		//IMemento child = memento.createChild("properties");
+		IMemento child = memento;
+		Iterator iterator = map.keySet().iterator();
+		while (iterator.hasNext()) {
+			String key = (String) iterator.next();
+			Object obj = map.get(key);
+			if (obj instanceof String)
+				child.putString(key, (String) obj);
+			else if (obj instanceof Integer) {
+				Integer in = (Integer) obj;
+				child.putInteger(key, in.intValue());
+			} else if (obj instanceof Boolean) {
+				Boolean bool = (Boolean) obj;
+				child.putBoolean(key, bool.booleanValue());
+			} else if (obj instanceof List) {
+				List list = (List) obj;
+				saveList(child, key, list);
+			} else if (obj instanceof Map) {
+				Map vMap = (Map) obj;
+				//FIXME: ASSUMPTION MAP STORES STRINGS ONLY
+				saveMap(child,key,vMap);
+				
+			}
+		}
+		saveState(child);
+	}
+	protected void saveMap(IMemento memento, String key, Map map) {
+		IMemento child = memento.createChild("map");
+		child.putString("key", key);
+		int i = 1;
+		Iterator iterator = map.keySet().iterator();
+		while (iterator.hasNext()) {
+			String s = (String) iterator.next();
+			child.putString(s,(String)map.get(s));
+		}
+	}
+	
+	protected void saveList(IMemento memento, String key, List list) {
+		IMemento child = memento.createChild("list");
+		child.putString("key", key);
+		int i = 1;
+		Iterator iterator = list.iterator();
+		while (iterator.hasNext()) {
+			String s = (String) iterator.next();
+			child.putString(s + (i++), s);
+		}
+	}
+
+	protected void saveToFile(IProgressMonitor monitor) throws CoreException {
+		try {
+			XMLMemento memento = XMLMemento.createWriteRoot(getXMLRoot());
+			save(memento);
+
+			InputStream in = memento.getInputStream();
+			if (file.exists())
+				file.setContents(in, true, true, ProgressUtil.getSubMonitorFor(monitor, 1000));
+			else
+				file.create(in, true, ProgressUtil.getSubMonitorFor(monitor, 1000));
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save " + getXMLRoot(), e);
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorSaving", getFile().toString()), e));
+		}
+	}
+	
+	protected void doSave(IProgressMonitor monitor) throws CoreException {
+		if (file != null)
+			saveToFile(monitor);
+		else
+			saveToMetadata(monitor);
+		ResourceManager.getInstance().resolveServers();
+	}
+	
+	protected void saveToMetadata(IProgressMonitor monitor) {
+		// do nothing
+	}
+	
+	protected abstract void saveState(IMemento memento);
+
+	protected void load(IMemento memento) {
+		map = new HashMap();
+		
+		Iterator iterator = memento.getNames().iterator();
+		while (iterator.hasNext()) {
+			String key = (String) iterator.next();
+			map.put(key, memento.getString(key));
+		}
+		IMemento[] children = memento.getChildren("list");
+		if (children != null) {
+			int size = children.length;
+			for (int i = 0; i < size; i++) {
+				loadList(children[i]);
+			}
+		}
+		IMemento[] maps = memento.getChildren("map");
+		if (maps != null) {
+			for (int i = 0; i <maps.length ; i++) {
+				loadMap(maps[i]);
+			}
+		}
+		
+		loadState(memento);
+	}
+
+	
+	protected void loadMap(IMemento memento) {
+		String key = memento.getString("key");
+		Map vMap = new HashMap();
+		List keys = memento.getNames();
+		Iterator iterator = keys.iterator();
+		while(iterator.hasNext())
+		{
+			String s = (String)iterator.next();
+			String v = memento.getString(s);
+			vMap.put(s,v);
+		}
+		map.put(key, vMap);
+	}
+	
+	
+	protected void loadList(IMemento memento) {
+		String key = memento.getString("key");
+		List list = new ArrayList();
+		int i = 1;
+		String key2 = memento.getString("value" + (i++));
+		while (key2 != null) {
+			list.add(key2);
+			key2 = memento.getString("value" + (i++));
+		}
+		map.put(key, list);
+	}
+	
+	protected abstract void loadState(IMemento memento);
+	
+	protected void resolve() {
+		// do nothing
+	}
+	
+	public void delete() throws CoreException {
+		if (file != null)
+			file.delete(true, true, new NullProgressMonitor());
+		else
+			deleteFromMetadata();
+	}
+
+	protected void deleteFromMetadata() {
+		// do nothing
+	}
+
+	public boolean equals(Object obj) {
+		if (!(obj instanceof Base))
+			return false;
+		
+		Base base = (Base) obj;
+		if (getId() == null)
+			return false;
+		else
+			return getId().equals(base.getId());
+	}
+
+	/**
+	 * 
+	 */
+	protected void loadFromFile(IProgressMonitor monitor) throws CoreException {
+		InputStream in = null;
+		try {
+			in = file.getContents();
+			IMemento memento = XMLMemento.loadMemento(in);
+			load(memento);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not load from file" + e.getMessage(), e);
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorLoading", getFile().toString()), e));
+		} finally {
+			try {
+				in.close();
+			} catch (Exception e) { }
+		}
+	}
+	
+	protected void loadFromMemento(IMemento memento, IProgressMonitor monitor) {
+		load(memento);
+	}
+	
+	/**
+	 * 
+	 */
+	protected void loadFromPath(IPath path, IProgressMonitor monitor) throws CoreException {
+		FileInputStream fin = null;
+		try {
+			fin = new FileInputStream(path.toFile());
+			IMemento memento = XMLMemento.loadMemento(fin);
+			load(memento);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not load from path: " + e.getMessage(), e);
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorLoading", path.toString()), e));
+		} finally {
+			try {
+				fin.close();
+			} catch (Exception e) {}
+		}
+	}
+	
+	public boolean isWorkingCopiesExist() {
+		return (workingCopies == null || workingCopies.size() > 0);
+	}
+
+	public boolean isAWorkingCopyDirty() {
+		if (workingCopies == null)
+			return false;
+
+		Iterator iterator = workingCopies.iterator();
+		while (iterator.hasNext()) {
+			IElementWorkingCopy wc = (IElementWorkingCopy) iterator.next();
+			if (wc.isDirty())
+				return true;
+		}
+		return false;
+	}
+	
+	protected void addWorkingCopy(IElementWorkingCopy wc) {
+		if (workingCopies == null)
+			workingCopies = new ArrayList(2);
+		workingCopies.add(wc);
+	}
+
+	protected void release(IElementWorkingCopy wc) {
+		if (workingCopies != null)
+			workingCopies.remove(wc);
+	}
+	
+	public IStatus validateEdit(Object context) {
+		if (file == null)
+			return null;
+	
+		return file.getWorkspace().validateEdit(new IFile[] { file }, context);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Client.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Client.java
new file mode 100644
index 0000000..c9c2054
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Client.java
@@ -0,0 +1,109 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunch;
+
+import org.eclipse.wst.server.core.IClient;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.IClientDelegate;
+import org.eclipse.wst.server.core.model.ILaunchable;
+/**
+ * 
+ */
+public class Client implements IClient {
+	private IConfigurationElement element;
+	private IClientDelegate delegate;
+
+	/**
+	 * LaunchableClient constructor comment.
+	 */
+	public Client(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * Returns the id of this LaunchableClient.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+
+	/*
+	 * @see IPublishManager#getDescription()
+	 */
+	public String getDescription() {
+		return element.getAttribute("description");
+	}
+
+	/*
+	 * @see IPublishManager#getLabel()
+	 */
+	public String getName() {
+		String label = element.getAttribute("name");
+		if (label == null)
+			return "n/a";
+		else
+			return label;
+	}
+
+	/*
+	 * @see IPublishManager#getDelegate()
+	 */
+	public IClientDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IClientDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate" + toString() + ": " + e.getMessage());
+			}
+		}
+		return delegate;
+	}
+
+	/**
+	 * 
+	 */
+	public boolean supports(IServer server, ILaunchable launchable, String launchMode) {
+		try {
+			return getDelegate().supports(server, launchable, launchMode);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+			return false;
+		}
+	}
+
+	/**
+	 * Opens or executes on the launchable.
+	 */
+	public IStatus launch(IServer server, ILaunchable launchable, String launchMode, ILaunch launch) {
+		try {
+			return getDelegate().launch(server, launchable, launchMode, launch);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+		return null;
+	}
+	
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return "LaunchableClient[" + getId() + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/FullPublisher.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/FullPublisher.java
new file mode 100644
index 0000000..b4744ff
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/FullPublisher.java
@@ -0,0 +1,47 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.wst.server.core.resources.*;
+/**
+ * PublishManager that publishes everything and deletes nothing.
+ */
+public class FullPublisher extends AbstractPublisher {
+	/**
+	 * FullPublisher constructor comment.
+	 */
+	public FullPublisher() {
+		super();
+	}
+
+	/**
+	 * Returns true if the remote resource should be deleted, and false
+	 * if it should be left on the server.
+	 *
+	 * @return boolean
+	 * @param option int
+	 */
+	public boolean shouldDelete(IModuleResource resource, IPath path, IRemoteResource remote, long resourceTimestamp, long remoteTimestamp) {
+		return false;
+	}
+
+	/**
+	 * Returns true if the resource should be published, and false
+	 * if it should be left on the server.
+	 *
+	 * @return boolean
+	 * @param option int
+	 */
+	public boolean shouldPublish(IModuleResource resource, IPath path, IRemoteResource remote, long resourceTimestamp, long remoteTimestamp) {
+		return true;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/IMemento.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/IMemento.java
new file mode 100644
index 0000000..3d6f8fb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/IMemento.java
@@ -0,0 +1,192 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.List;
+/**
+ * Interface to a memento used for saving the important state of an object
+ * in a form that can be persisted in the file system.
+ * <p>
+ * Mementos were designed with the following requirements in mind:
+ * <ol>
+ *  <li>Certain objects need to be saved and restored across platform sessions.
+ *    </li>
+ *  <li>When an object is restored, an appropriate class for an object might not
+ *    be available. It must be possible to skip an object in this case.</li>
+ *  <li>When an object is restored, the appropriate class for the object may be
+ *    different from the one when the object was originally saved. If so, the
+ *    new class should still be able to read the old form of the data.</li>
+ * </ol>
+ * </p>
+ * <p>
+ * Mementos meet these requirements by providing support for storing a
+ * mapping of arbitrary string keys to primitive values, and by allowing
+ * mementos to have other mementos as children (arranged into a tree).
+ * A robust external storage format based on XML is used.
+ * </p><p>
+ * The key for an attribute may be any alpha numeric value.  However, the
+ * value of <code>TAG_ID</code> is reserved for internal use.
+ * </p><p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ *
+ * @see IPersistableElement
+ * @see IElementFactory
+ */
+public interface IMemento {
+	/**
+	 * Special reserved key used to store the memento id 
+	 * (value <code>"org.eclipse.ui.id"</code>).
+	 *
+	 * @see #getId
+	 */
+	public static final String TAG_ID = "IMemento.internal.id"; //$NON-NLS-1$
+
+	/**
+	 * Creates a new child of this memento with the given type.
+	 * <p>
+	 * The <code>getChild</code> and <code>getChildren</code> methods
+	 * are used to retrieve children of a given type.
+	 * </p>
+	 *
+	 * @param type the type
+	 * @return a new child memento
+	 * @see #getChild
+	 * @see #getChildren
+	 */
+	public IMemento createChild(String type);
+	
+	/**
+	 * Creates a new child of this memento with the given type and id.
+	 * The id is stored in the child memento (using a special reserved
+	 * key, <code>TAG_ID</code>) and can be retrieved using <code>getId</code>.
+	 * <p>
+	 * The <code>getChild</code> and <code>getChildren</code> methods
+	 * are used to retrieve children of a given type.
+	 * </p>
+	 *
+	 * @param type the type
+	 * @param id the child id
+	 * @return a new child memento with the given type and id
+	 * @see #getId
+	 */
+	public IMemento createChild(String type, String id);
+	
+	/**
+	 * Returns the first child with the given type id.
+	 *
+	 * @param type the type id
+	 * @return the first child with the given type
+	 */
+	public IMemento getChild(String type);
+	
+	/**
+	 * Returns all children with the given type id.
+	 *
+	 * @param type the type id
+	 * @return the list of children with the given type
+	 */
+	public IMemento[] getChildren(String type);
+	
+	/**
+	 * Returns the floating point value of the given key.
+	 *
+	 * @param key the key
+	 * @return the value, or <code>null</code> if the key was not found or was found
+	 *   but was not a floating point number
+	 */
+	public Float getFloat(String key);
+	
+	/**
+	 * Returns the id for this memento.
+	 *
+	 * @return the memento id, or <code>null</code> if none
+	 * @see #createChild(java.lang.String,java.lang.String)
+	 */
+	public String getId();
+	
+	/**
+	 * Returns the name for this memento.
+	 *
+	 * @return the memento name, or <code>null</code> if none
+	 * @see #createChild(java.lang.String,java.lang.String)
+	 */
+	public String getName();
+
+	/**
+	 * Returns the integer value of the given key.
+	 *
+	 * @param key the key
+	 * @return the value, or <code>null</code> if the key was not found or was found
+	 *   but was not an integer
+	 */
+	public Integer getInteger(String key);
+
+	/**
+	 * Returns the string value of the given key.
+	 *
+	 * @param key the key
+	 * @return the value, or <code>null</code> if the key was not found or was found
+	 *  but was not an integer
+	 */
+	public String getString(String key);
+
+	/**
+	 * Returns the boolean value of the given key.
+	 *
+	 * @param key the key
+	 * @return the value, or <code>null</code> if the key was not found or was found
+	 *  but was not a boolean
+	 */
+	public Boolean getBoolean(String key);
+	
+	public List getNames();
+	
+	/**
+	 * Sets the value of the given key to the given floating point number.
+	 *
+	 * @param key the key
+	 * @param value the value
+	 */
+	public void putFloat(String key, float value);
+	
+	/**
+	 * Sets the value of the given key to the given integer.
+	 *
+	 * @param key the key
+	 * @param value the value
+	 */
+	public void putInteger(String key, int value);
+	
+	/**
+	 * Sets the value of the given key to the given boolean value.
+	 *
+	 * @param key the key
+	 * @param value the value
+	 */
+	public void putBoolean(String key, boolean value);
+
+	/**
+	 * Copy the attributes and children from  <code>memento</code>
+	 * to the receiver.
+	 *
+	 * @param memento the IMemento to be copied.
+	 */
+	public void putMemento(IMemento memento);
+
+	/**
+	 * Sets the value of the given key to the given string.
+	 *
+	 * @param key the key
+	 * @param value the value
+	 */
+	public void putString(String key, String value);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/LaunchableAdapter.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/LaunchableAdapter.java
new file mode 100644
index 0000000..63e39c7
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/LaunchableAdapter.java
@@ -0,0 +1,76 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+
+import org.eclipse.wst.server.core.ILaunchableAdapter;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * 
+ */
+public class LaunchableAdapter implements ILaunchableAdapter {
+	private IConfigurationElement element;
+	private ILaunchableAdapterDelegate delegate;
+
+	/**
+	 * LaunchableAdapter constructor comment.
+	 */
+	public LaunchableAdapter(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * Returns the id of this LaunchableAdapter.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+
+	/*
+	 * @see IPublishManager#getDelegate()
+	 */
+	public ILaunchableAdapterDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (ILaunchableAdapterDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate" + toString() + ": " + e.getMessage());
+			}
+		}
+		return delegate;
+	}
+
+	/**
+	 * 
+	 */
+	public ILaunchable getLaunchable(IServer server, IModuleObject object) {
+		try {
+			return getDelegate().getLaunchable(server, object);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+			return null;
+		}
+	}
+
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return "LaunchableAdapter[" + getId() + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleFactory.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleFactory.java
new file mode 100644
index 0000000..468f767
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleFactory.java
@@ -0,0 +1,164 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+
+import org.eclipse.wst.server.core.IModuleFactory;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IModuleFactoryDelegate;
+import org.eclipse.wst.server.core.model.IModuleFactoryListener;
+/**
+ * 
+ */
+public class ModuleFactory implements IModuleFactory {
+	private IConfigurationElement element;
+	private IModuleFactoryDelegate delegate;
+	private List moduleTypes;
+
+	/**
+	 * ModuleFactory constructor comment.
+	 */
+	public ModuleFactory(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * Returns the id of this factory.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+	
+	/**
+	 * Returns the index (ordering) of this task.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			return Integer.parseInt(element.getAttribute("index"));
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public List getModuleTypes() {
+		if (moduleTypes == null)
+			moduleTypes = ServerPlugin.getModuleTypes(element.getChildren("moduleType"));
+
+		return moduleTypes;
+	}
+	
+	/**
+	 * Returns true if this modules factory produces project modules.
+	 *
+	 * @return boolean
+	 */
+	public boolean isProjectModuleFactory() {
+		return "true".equalsIgnoreCase(element.getAttribute("projects"));
+	}
+
+	/*
+	 * @see IPublishManager#getDelegate()
+	 */
+	public IModuleFactoryDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IModuleFactoryDelegate) element.createExecutableExtension("class");
+				ResourceManager rm = (ResourceManager) ServerCore.getResourceManager();
+				rm.addModuleFactoryListener(delegate);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString() + ": " + e.getMessage());
+			}
+		}
+		return delegate;
+	}
+
+	/**
+	 * Gets a module from a memento.
+	 * 
+	 * @param memento java.lang.String
+	 * @return org.eclipse.wst.server.core.model.IModule
+	 */
+	public IModule getModule(String memento) {
+		try {
+			return getDelegate().getModule(memento);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+			return null;
+		}
+	}
+	
+	/**
+	 * Return all modules that are available to be added
+	 * to servers. This method might look through projects
+	 * to find modules or may return modules from
+	 * other sources.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public List getModules() {
+		try {
+			return getDelegate().getModules();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+			return null;
+		}
+	}
+	
+	/**
+	 * Add a listener for modules that are added/removed from this
+	 * factory.
+	 * 
+	 * @param listener org.eclipse.wst.server.core.model.IModuleFactoryListener
+	 */
+	public void addModuleFactoryListener(IModuleFactoryListener listener) {
+		try {
+			getDelegate().addModuleFactoryListener(listener);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+	}
+	
+	/**
+	 * Add a listener for modules that are added/removed from this
+	 * factory.
+	 * 
+	 * @param listener org.eclipse.wst.server.core.model.IModuleFactoryListener
+	 */
+	public void removeModuleFactoryListener(IModuleFactoryListener listener) {
+		try {
+			getDelegate().removeModuleFactoryListener(listener);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+	}
+	
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return "ModuleFactory[" + getId() + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleKind.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleKind.java
new file mode 100644
index 0000000..344d58b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleKind.java
@@ -0,0 +1,46 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+
+import org.eclipse.wst.server.core.IModuleKind;
+/**
+ * 
+ */
+public class ModuleKind implements IModuleKind {
+	protected String id;
+	protected String name;
+	
+	public ModuleKind(IConfigurationElement ce) {
+		super();
+		this.id = ce.getAttribute("id");
+		this.name = ce.getAttribute("name");
+	}
+	
+	public ModuleKind(String id, String name) {
+		super();
+		this.id = id;
+		this.name = name;
+	}
+	
+	public String getId() {
+		return id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public String toString() {
+		return "ModuleType2[" + id + ", " + name + "]";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleObjectAdapter.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleObjectAdapter.java
new file mode 100644
index 0000000..0fb1798
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleObjectAdapter.java
@@ -0,0 +1,97 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+
+import org.eclipse.wst.server.core.IModuleObjectAdapter;
+import org.eclipse.wst.server.core.model.IModuleObject;
+import org.eclipse.wst.server.core.model.IModuleObjectAdapterDelegate;
+/**
+ * 
+ */
+public class ModuleObjectAdapter implements IModuleObjectAdapter {
+	private IConfigurationElement element;
+	private IModuleObjectAdapterDelegate delegate;
+
+	/**
+	 * ModuleObjectAdapter constructor comment.
+	 */
+	public ModuleObjectAdapter(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * Returns the id of this ModuleObjectAdapter.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+	
+	/**
+	 * Returns the (super) class name that this adapter can work with.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getObjectClassName() {
+		return element.getAttribute("objectClass");
+	}
+	
+	/**
+	 * Returns true if the plugin that loaded this class has been loaded.
+	 *
+	 * @return boolean
+	 */
+	public boolean isPluginActivated() {
+		String pluginId = element.getDeclaringExtension().getNamespace();
+		return Platform.getBundle(pluginId).getState() == Bundle.ACTIVE;
+	}
+
+	/*
+	 * @see IPublishManager#getDelegate()
+	 */
+	public IModuleObjectAdapterDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IModuleObjectAdapterDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString() + ": " + e.getMessage());
+			}
+		}
+		return delegate;
+	}
+
+	/**
+	 * Converts from a model object to an IModuleObject.
+	 */
+	public IModuleObject getModuleObject(Object obj) {
+		try {
+			return getDelegate().getModuleObject(obj);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate (" + obj + ") " + toString() + ": " + e.getMessage());
+			return null;
+		}
+	}
+	
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return "ModuleObjectAdapter[" + getId() + "]";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleTask.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleTask.java
new file mode 100644
index 0000000..753b900
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleTask.java
@@ -0,0 +1,199 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * 
+ */
+public class ModuleTask implements IModuleTask {
+	private IConfigurationElement element;
+	private IModuleTaskDelegate delegate;
+	protected ITaskModel model;
+
+	/**
+	 * ModuleTask constructor comment.
+	 */
+	public ModuleTask(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * Returns the id of this task.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+
+	/*
+	 * @see IPublishManager#getDescription()
+	 */
+	public String getDescription() {
+		return element.getAttribute("description");
+	}
+
+	/*
+	 * @see IPublishManager#getLabel()
+	 */
+	public String getName() {
+		String label = element.getAttribute("name");
+		if (label == null)
+			return "n/a";
+		else
+			return label;
+	}
+	
+	/**
+	 * Returns the index (ordering) of this task.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			return Integer.parseInt(element.getAttribute("index"));
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+	
+	public ITaskModel getTaskModel() {
+		return model;
+	}
+	
+	public void setTaskModel(ITaskModel taskModel) {
+		this.model = taskModel;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.ITask#canExecute()
+	 */
+	public boolean canExecute() {
+		return true;
+	}
+	
+	public boolean canUndo() {
+		return false;
+	}
+	
+	public void undo() { }
+	
+	/**
+	 * Return the type ids that may be supported.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	public String[] getTypeIds() {
+		try {
+			return ServerPlugin.tokenize(element.getAttribute("typeIds"), ",");
+		} catch (Exception e) {
+			return null;
+		}
+	}
+
+	/**
+	 * Returns true if the given type (given by the id) can use this task. This
+	 * result is based on the result of the getTypeIds() method.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsType(String id) {
+		if (id == null || id.length() == 0)
+			return false;
+
+		String[] s = getTypeIds();
+		if (s == null)
+			return true;
+		
+		int size = s.length;
+		for (int i = 0; i < size; i++) {
+			if (s[i].endsWith("*")) {
+				if (id.length() >= s[i].length() && id.startsWith(s[i].substring(0, s[i].length() - 1)))
+					return true;
+			} else if (id.equals(s[i]))
+				return true;
+		}
+		return false;
+	}
+
+	/*
+	 * @see IPublishManager#getDelegate()
+	 */
+	public IModuleTaskDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IModuleTaskDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate" + toString() + ": " + e.getMessage());
+			}
+		}
+		return delegate;
+	}
+	
+	/**
+	 * Lets the task know that it is about to be used. This method should
+	 * be used to clean out any previously cached information, or start to
+	 * create a new cache.
+	 */
+	public void init(IServer server, IServerConfiguration configuration, List parents, IModule module) {
+		try {
+			getDelegate().init(server, configuration, parents, module);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+	}
+	
+	/**
+	 * Returns the status of this task.
+	 * 
+	 * @return byte
+	 */
+	public byte getTaskStatus() {
+		try {
+			return getDelegate().getTaskStatus();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+			return 0;
+		}
+	}
+
+	/**
+	 * Perform the task.
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException {
+		try {
+			getDelegate().execute(monitor);
+		} catch (CoreException ce) {
+			Trace.trace(Trace.FINER, "Task error " + toString(), ce);
+			throw ce;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+	}
+	
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return "ModuleTask[" + getId() + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleType.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleType.java
new file mode 100644
index 0000000..ebc55df
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ModuleType.java
@@ -0,0 +1,38 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.wst.server.core.IModuleType;
+/**
+ * 
+ */
+public class ModuleType implements IModuleType {
+	protected String type;
+	protected String version;
+	
+	public ModuleType(String type, String version) {
+		super();
+		this.type = type;
+		this.version = version;
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public String getVersion() {
+		return version;
+	}
+
+	public String toString() {
+		return "ModuleType[" + type + ", " + version + "]";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ProjectProperties.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ProjectProperties.java
new file mode 100644
index 0000000..3cfcf01
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ProjectProperties.java
@@ -0,0 +1,266 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IProjectPropertiesListener;
+/**
+ * Helper class that stores preference information for
+ * the server tools.
+ */
+public class ProjectProperties implements IProjectProperties {
+	private static final String PROJECT_PREFERENCE_FILE = ".runtime";
+	
+	protected IProject project;
+	
+	protected String serverId;
+	protected String runtimeId;
+	
+	// project properties listeners
+	protected transient List listeners;
+
+	/**
+	 * ProjectProperties constructor comment.
+	 */
+	public ProjectProperties(IProject project) {
+		super();
+		this.project = project;
+	}
+
+	
+	/**
+	 * Load the preferences.
+	 */
+	private void loadPreferences() {
+		Trace.trace(Trace.FINEST, "Loading project preferences: " + project);
+		
+		try {
+			IMemento memento = null;
+			if (!project.exists() || !project.isOpen())
+				return;
+			IFile file = project.getFile(PROJECT_PREFERENCE_FILE);
+			if (file != null && file.exists())
+				memento = XMLMemento.loadMemento(file.getContents());
+			
+			if (memento == null)
+				return;
+			
+			serverId = memento.getString("server-id");
+			runtimeId = memento.getString("runtime-id");
+		} catch (Exception e) {
+			Trace.trace("Could not load preferences: " + e.getMessage());
+		}
+	}
+	
+	private void savePreferences(IProgressMonitor monitor) throws CoreException {
+		if (project.exists() && project.isOpen()) {
+			IFile file = project.getFile(PROJECT_PREFERENCE_FILE);
+			
+			if (file.exists() && file.isReadOnly()) {
+				IStatus status = ResourcesPlugin.getWorkspace().validateEdit(new IFile[] { file }, null);
+				if (status.getSeverity() == IStatus.ERROR)
+					// didn't work or not under source control
+					throw new CoreException(status);
+			}
+			
+			InputStream in = null;
+			try {
+				XMLMemento memento = XMLMemento.createWriteRoot("runtime");
+
+				if (runtimeId != null)
+					memento.putString("runtime-id", runtimeId);
+				if (serverId != null)
+					memento.putString("server-id", serverId);
+				in = memento.getInputStream();
+				
+				if (file.exists())
+					file.setContents(in, true, true, monitor);
+				else
+					file.create(in, true, monitor);
+			} catch (Exception e) {
+				throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, "", e));
+			} finally {
+				try {
+					in.close();
+				} catch (Exception e) { }
+			}
+			return;
+		}
+	}
+
+	/**
+	 * Returns the preferred runtime server for the project. This method
+	 * returns null if the server was never chosen or does not currently exist. (if the
+	 * server is recreated or was in a closed project, etc. this method will return
+	 * the original value if it becomes available again)
+	 *
+	 * @return server org.eclipse.wst.server.core.model.IServer
+	 */
+	public IServer getDefaultServer() {
+		loadPreferences();
+
+		IServer server = ServerCore.getResourceManager().getServer(serverId);
+		/*if (server != null && ServerUtil.containsModule(server, module))
+			return server;
+		else
+			return null;*/
+		return server;
+	}
+
+	/**
+	 * Sets the preferred runtime server for the project.
+	 *
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public void setDefaultServer(IServer server, IProgressMonitor monitor) throws CoreException {
+		loadPreferences();
+		if (server == null)
+			serverId = null;
+		else
+			serverId = server.getId();
+		savePreferences(monitor);
+		fireDefaultServerChanged(server);
+	}
+
+	/**
+	 * Returns the current runtime target type for the given project.
+	 * 
+	 * @return
+	 */
+	public IRuntime getRuntimeTarget() {
+		loadPreferences();
+		return ServerCore.getResourceManager().getRuntime(runtimeId);
+	}
+
+	/**
+	 * Sets the runtime target for the project.
+	 * 
+	 * @param target
+	 * @param monitor
+	 */
+	public void setRuntimeTarget(IRuntime runtime, IProgressMonitor monitor) throws CoreException {
+		if (runtime != null)
+			Trace.trace(Trace.RUNTIME_TARGET, "setRuntimeTarget : " + runtime + " " + runtime.getRuntimeType());
+		else
+			Trace.trace(Trace.RUNTIME_TARGET, "setRuntimeTarget : null");
+		// remove old target
+		loadPreferences();
+		IRuntime oldRuntime = ServerCore.getResourceManager().getRuntime(runtimeId);
+		if (oldRuntime != null) {
+			IRuntimeType runtimeType = oldRuntime.getRuntimeType();
+			Iterator iterator = ServerCore.getRuntimeTargetHandlers().iterator();
+			while (iterator.hasNext()) {
+				IRuntimeTargetHandler handler = (IRuntimeTargetHandler) iterator.next();
+				Trace.trace(Trace.RUNTIME_TARGET, "  < " + handler + " " + handler.supportsRuntimeType(runtimeType));
+				if (handler.supportsRuntimeType(runtimeType))
+					handler.removeRuntimeTarget(project, oldRuntime, monitor);
+			}
+		}
+		
+		// add new target
+		if (runtime != null) {
+			runtimeId = runtime.getId();
+			IRuntimeType runtimeType = runtime.getRuntimeType();
+			Iterator iterator = ServerCore.getRuntimeTargetHandlers().iterator();
+			while (iterator.hasNext()) {
+				IRuntimeTargetHandler handler = (IRuntimeTargetHandler) iterator.next();
+				Trace.trace(Trace.RUNTIME_TARGET, "  > " + handler + " " + handler.supportsRuntimeType(runtimeType));
+				if (handler.supportsRuntimeType(runtimeType))
+					handler.setRuntimeTarget(project, runtime, monitor);
+			}
+		} else
+			runtimeId = null;
+		savePreferences(monitor);
+		fireRuntimeTargetChanged(runtime);
+		Trace.trace(Trace.RUNTIME_TARGET, "setRuntimeTarget <");
+	}
+
+	public void addProjectPropertiesListener(IProjectPropertiesListener listener) {
+		Trace.trace(Trace.LISTENERS, "Adding project properties listener " + listener + " to " + this);
+		
+		if (listeners == null)
+			listeners = new ArrayList();
+		listeners.add(listener);
+	}
+
+	public void removeProjectPropertiesListener(IProjectPropertiesListener listener) {
+		Trace.trace(Trace.LISTENERS, "Removing project properties listener " + listener + " from " + this);
+		
+		if (listeners != null)
+			listeners.remove(listener);
+	}
+	
+	/**
+	 * Fire a event because the default server changed.
+	 *
+	 * @param server org.eclipse.wst.server.core.IServer
+	 */
+	private void fireDefaultServerChanged(IServer server) {
+		Trace.trace(Trace.LISTENERS, "->- Firing defaultServerChanged event: " + server + " ->-");
+	
+		if (listeners == null || listeners.isEmpty())
+			return;
+	
+		int size = listeners.size();
+		IProjectPropertiesListener[] ppl = new IProjectPropertiesListener[size];
+		listeners.toArray(ppl);
+	
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.LISTENERS, "  Firing defaultServerChanged event to " + ppl[i]);
+			try {
+				ppl[i].defaultServerChanged(project, server);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing defaultServerChanged event to " + ppl[i], e);
+			}
+		}
+	
+		Trace.trace(Trace.LISTENERS, "-<- Done firing defaultServerChanged event -<-");
+	}
+	
+	/**
+	 * Fire a event because the runtime target changed.
+	 *
+	 * @param server org.eclipse.wst.server.core.IRuntime
+	 */
+	private void fireRuntimeTargetChanged(IRuntime runtime) {
+		Trace.trace(Trace.LISTENERS, "->- Firing runtimeTargetChanged event: " + runtime + " ->-");
+	
+		if (listeners == null || listeners.isEmpty())
+			return;
+	
+		int size = listeners.size();
+		IProjectPropertiesListener[] ppl = new IProjectPropertiesListener[size];
+		listeners.toArray(ppl);
+	
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.LISTENERS, "  Firing runtimeTargetChanged event to " + ppl[i]);
+			try {
+				ppl[i].runtimeTargetChanged(project, runtime);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing runtimeTargetChanged event to " + ppl[i], e);
+			}
+		}
+	
+		Trace.trace(Trace.LISTENERS, "-<- Done firing runtimeTargetChanged event -<-");
+	}
+	
+	public String toString() {
+		return "ProjectProperties[" + project + ", " + serverId + ", " + runtimeId + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishControl.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishControl.java
new file mode 100644
index 0000000..7ba386c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishControl.java
@@ -0,0 +1,371 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IPublisher;
+import org.eclipse.wst.server.core.resources.*;
+import org.eclipse.wst.server.core.util.ProgressUtil;
+/**
+ * Publish controller.
+ */
+public class PublishControl implements IPublishControl {
+	public String memento;
+	public String parents;
+	public boolean isDirty = true;
+	public List resourceInfo = new ArrayList();
+
+	public class ResourcePublishInfo {
+		IPath localPath;
+		long localTimestamp;
+		IPath remotePath;
+		long remoteTimestamp;
+
+		public boolean equals(Object obj) {
+			if (!(obj instanceof ResourcePublishInfo))
+				return false;
+
+			// return true if local or remote paths are equal
+			ResourcePublishInfo rpi = (ResourcePublishInfo) obj;
+			if (localPath == null && rpi.localPath == null)
+				return true;
+			else if (localPath != null && localPath.equals(rpi.localPath))
+				return true;
+			else if (remotePath != null && rpi.remotePath == null)
+				return true;
+			else if (remotePath != null && remotePath.equals(rpi.remotePath))
+				return true;
+			else
+				return false;
+		}
+	}
+	
+	protected transient IPublisher publisher;
+	protected transient IRemoteResource[] remoteResources;
+
+	/**
+	 * PublishControl constructor comment.
+	 */
+	public PublishControl(String parents, String memento) {
+		super();
+
+		this.parents = parents;
+		this.memento = memento;
+	}
+	
+	/**
+	 * PublishControl constructor comment.
+	 */
+	public PublishControl(IMemento memento) {
+		super();
+		
+		load(memento);
+	}
+	
+	public void setPublisher(IPublisher publisher) {
+		this.publisher = publisher;
+	}
+	
+	public String getMemento() {
+		return memento;
+	}
+	
+	public String getParentsRef() {
+		return parents;
+	}
+
+	/**
+	 * 
+	 */
+	protected void fillRemoteResourceCache(IProgressMonitor monitor) throws CoreException {
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		monitor.beginTask(ServerPlugin.getResource("%caching"), 1000);
+		
+		if (publisher != null)
+			remoteResources = publisher.getRemoteResources(ProgressUtil.getSubMonitorFor(monitor, 1000));
+	
+		monitor.done();
+	}
+
+	/**
+	 * Returns the mapping of this file on the remote system. Returns
+	 * null if this file should not be copied to the remote server.
+	 *
+	 * @param resource org.eclipse.wst.server.core.publish.IModuleResource
+	 * @return org.eclipse.core.resources.IPath
+	 */
+	public IPath getMappedLocation(IModuleResource resource) {
+		if (publisher == null)
+			return null;
+		else
+			return publisher.getMappedLocation(resource);
+	}
+
+	/**
+	 * Returns the root level remote resources on the remote system.
+	 *
+	 * @param project org.eclipse.core.resources.IProject
+	 * @return java.util.List
+	 */
+	public IRemoteResource[] getRemoteResources() {
+		return remoteResources;
+	}
+
+	/**
+	 * Returns true if there may be any files or folders within
+	 * this container that should be mapped to the remote system.
+	 * Returns false if files within this folder are never copied
+	 * to the remote system.
+	 *
+	 * @param folder org.eclipse.wst.server.core.publish.IModuleFolder
+	 * @return boolean
+	 */
+	public boolean shouldMapMembers(IModuleFolder folder) {
+		if (publisher == null)
+			return false;
+		else
+			return publisher.shouldMapMembers(folder);
+	}
+	
+	/**
+	 * Returns the timestamp of the remote resource on the remote
+	 * machine after it was last published.
+	 *
+	 * @param resource org.eclipse.wst.server.publish.IRemoteResource
+	 * @return long
+	 */
+	public long getPublishedTimestamp(IRemoteResource resource) {
+		if (resource == null)
+			return IRemoteResource.TIMESTAMP_UNKNOWN;
+	
+		IPath remotePath = resource.getPath();
+		if (remotePath == null)
+			return IRemoteResource.TIMESTAMP_UNKNOWN;
+	
+		Iterator iterator = resourceInfo.iterator();
+		while (iterator.hasNext()) {
+			ResourcePublishInfo rpi = (ResourcePublishInfo) iterator.next();
+			if (remotePath.equals(rpi.remotePath))
+				return rpi.remoteTimestamp;
+		}
+	
+		return IRemoteResource.TIMESTAMP_UNKNOWN;
+	}
+
+	/**
+	 * Returns the timestamp that the resource was last published.
+	 *
+	 * @param resource org.eclipse.wst.server.publish.IModuleResource
+	 * @return long
+	 */
+	public long getPublishedTimestamp(IModuleResource resource) {
+		if (resource == null)
+			return IRemoteResource.TIMESTAMP_UNKNOWN;
+	
+		IPath resourcePath = resource.getPath();
+		if (resourcePath == null)
+			return IRemoteResource.TIMESTAMP_UNKNOWN;
+	
+		Iterator iterator = resourceInfo.iterator();
+		while (iterator.hasNext()) {
+			ResourcePublishInfo rpi = (ResourcePublishInfo) iterator.next();
+			if (resourcePath.equals(rpi.localPath))
+				return rpi.localTimestamp;
+		}
+	
+		return IRemoteResource.TIMESTAMP_UNKNOWN;
+	}
+	
+	/**
+	 * Returns true if the project is dirty.
+	 *
+	 * @return boolean
+	 */
+	public boolean isDirty() {
+		return isDirty;
+	}
+	
+	/**
+	 * Sets the dirty flag.
+	 *
+	 * @param boolean
+	 */
+	public void setDirty(boolean b) {
+		isDirty = b;
+	}
+	
+	/**
+	 * 
+	 */
+	protected void load(IMemento memento2) {
+		Trace.trace(Trace.FINEST, "Loading publish control for: " + memento2);
+	
+		try {
+			memento = memento2.getString("memento");
+			parents = memento2.getString("parents");
+			/*String temp = projectChild[i].getString("dirty");
+			if ("true".equals(temp))
+				ppi.isDirty = true;
+			else
+				ppi.isDirty = false;*/
+	
+			IMemento[] resourceChild = memento2.getChildren("resource");
+			int size2 = resourceChild.length;
+			resourceInfo = new ArrayList(size2 + 5);
+			for (int j = 0; j < size2; j++) {
+				ResourcePublishInfo rpi = new ResourcePublishInfo();
+				String temp = resourceChild[j].getString("localPath");
+				if (temp != null && temp.length() > 1)
+					rpi.localPath = new Path(temp);
+				temp = resourceChild[j].getString("remotePath");
+				if (temp != null && temp.length() > 1)
+					rpi.remotePath = new Path(temp);
+				temp = resourceChild[j].getString("localTimestamp");
+				if (temp != null && temp.length() > 1)
+					rpi.localTimestamp = Long.parseLong(temp);
+				temp = resourceChild[j].getString("remoteTimestamp");
+				if (temp != null && temp.length() > 1)
+					rpi.remoteTimestamp = Long.parseLong(temp);
+				resourceInfo.add(rpi);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not load publish control information: " + e.getMessage());
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	protected void save(IMemento memento2) {
+		try {
+			memento2.putString("memento", memento);
+			memento2.putString("parents", parents);
+			/*if (ppi.isDirty)
+				project.putString("dirty", "true");
+			else
+				project.putString("dirty", "false");*/
+	
+			Iterator ite = resourceInfo.iterator();
+			while (ite.hasNext()) {
+				ResourcePublishInfo rpi = (ResourcePublishInfo) ite.next();
+				IMemento resource = memento2.createChild("resource");
+	
+				if (rpi.localPath != null) {
+					resource.putString("localPath", rpi.localPath.toString());
+					resource.putString("localTimestamp", new Long(rpi.localTimestamp).toString());
+				}
+				if (rpi.remotePath != null) {
+					resource.putString("remotePath", rpi.remotePath.toString());
+					resource.putString("remoteTimestamp", new Long(rpi.remoteTimestamp).toString());
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save publish control info", e);
+		}
+	}
+	
+	protected IRemoteResource findRemoteResource(IRemoteFolder folder, IPath path) {
+		Iterator iterator = folder.getContents().iterator();
+		while (iterator.hasNext()) {
+			IRemoteResource remote = (IRemoteResource) iterator.next();
+			if (path.equals(remote.getPath()))
+				return remote;
+			if (remote instanceof IRemoteFolder) {
+				IRemoteFolder folder2 = (IRemoteFolder) remote;
+				IPath folderPath = folder2.getPath();
+				if (folderPath.isPrefixOf(path)) {
+					IRemoteResource rem = findRemoteResource(folder2, path);
+					if (rem != null)
+						return rem;
+				}
+			}
+		}
+		return null;
+	}
+	
+	protected IRemoteResource findRemoteResource(IRemoteResource[] resources, IPath path) {
+		if (resources == null || path == null)
+			return null;
+	
+		int size = resources.length;
+		for (int i = 0; i < size; i++) {
+			IRemoteResource remote = resources[i];
+			
+			if (path.equals(remote.getPath()))
+				return remote;
+			if (remote instanceof IRemoteFolder) {
+				IRemoteFolder folder2 = (IRemoteFolder) remote;
+				IPath folderPath = folder2.getPath();
+				if (folderPath.isPrefixOf(path)) {
+					IRemoteResource rem = findRemoteResource(folder2, path);
+					if (rem != null)
+						return rem;
+				}
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * Verify the files were published and update info.
+	 *
+	 * @param project org.eclipse.core.resources.IProject
+	 * @param publisher org.eclipse.wst.server.core.model.IDeployTargetPublisher
+	 * @param verifyList java.util.List
+	 */
+	protected void verify(List verifyList, List deleteList, IProgressMonitor monitor) {
+		Trace.trace(Trace.FINEST, "Verifying resource state info");
+		try {
+			IRemoteResource[] resources = publisher.getRemoteResources(monitor);
+	
+			Iterator iterator = verifyList.iterator();
+			while (iterator.hasNext()) {
+				IModuleResource resource = (IModuleResource) iterator.next();
+	
+				ResourcePublishInfo rpi = new ResourcePublishInfo();
+				rpi.localPath = resource.getPath();
+				rpi.localTimestamp = resource.getTimestamp();
+	
+				IPath path = publisher.getMappedLocation(resource);
+				IRemoteResource remote = findRemoteResource(resources, path);
+				Trace.trace(Trace.FINEST, "Verifying resource: " + resource + " " + remote);
+				if (remote != null) {
+					rpi.remotePath = remote.getPath();
+					rpi.remoteTimestamp = remote.getTimestamp();
+				}
+	
+				// remove any previous entry for this resource
+				if (resourceInfo.contains(rpi))
+					resourceInfo.remove(rpi);
+
+				// add new one
+				resourceInfo.add(rpi);
+			}
+	
+			iterator = deleteList.iterator();
+			while (iterator.hasNext()) {
+				IRemoteResource remote = (IRemoteResource) iterator.next();
+				ResourcePublishInfo rpi = new ResourcePublishInfo();
+				rpi.remotePath = remote.getPath();
+				resourceInfo.remove(rpi);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error verifying resource state info", e);
+		}
+	}
+	
+	public String toString() {
+		return "PublishControl [" + memento + " " + isDirty + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishInfo.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishInfo.java
new file mode 100644
index 0000000..84e8a54
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishInfo.java
@@ -0,0 +1,268 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.*;
+import java.io.File;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * Helper to obtain and store the global publish information.
+ * (what files were published and when) Delegates to PublishState
+ * for all server specific publishing information.
+ */
+public class PublishInfo {
+	protected static PublishInfo instance;
+
+	protected static final String PUBLISH_DIR = "publish";
+
+	// map of server refs to IPaths
+	protected Map servers;
+
+	// map of control ref to PublishControl
+	protected Map publishControls;
+
+	// list of serverRefs that have been loaded
+	protected List loadedServers;
+
+	/**
+	 * PublishInfo constructor comment.
+	 */
+	private PublishInfo() {
+		super();
+	
+		servers = new HashMap();
+		loadedServers = new ArrayList();
+		publishControls = new HashMap();
+		load();
+	}
+
+	/**
+	 * Return the publish info.
+	 * 
+	 * @return org.eclipse.wst.server.core.internal.PublishInfo
+	 */
+	public static PublishInfo getPublishInfo() {
+		if (instance == null)
+			instance = new PublishInfo();
+		return instance;
+	}
+
+	protected String getPublishControlRef(IServer server, List parents, IModule module) {
+		StringBuffer sb = new StringBuffer();
+		sb.append(server.getId());
+		
+		if (parents != null) {
+			Iterator iterator = parents.iterator();
+			while (iterator.hasNext()) {
+				IModule parent = (IModule) iterator.next();
+				sb.append("#");
+				sb.append(parent.getId());
+			}
+		}
+		
+		sb.append("#");
+		sb.append(module.getId());
+		return sb.toString();
+	}
+	
+	protected String getPublishControlRef(String serverId, String parentsRef, String memento) {
+		StringBuffer sb = new StringBuffer();
+		sb.append(serverId);
+		
+		if (parentsRef != null && parentsRef.length() > 0) {
+			sb.append("#");
+			sb.append(parentsRef);
+		}
+		
+		sb.append("#");
+		sb.append(memento);
+		return sb.toString();
+	}
+	
+	protected String getParentsMemento(List parents) {
+		StringBuffer sb = new StringBuffer();
+		boolean first = true;
+		
+		if (parents != null) {
+			Iterator iterator = parents.iterator();
+			while (iterator.hasNext()) {
+				IModule parent = (IModule) iterator.next();
+				if (!first)
+					sb.append("#");
+				else
+					first = false;
+				sb.append(parent.getId());
+			}
+		}
+		
+		return sb.toString();
+	}
+	
+	/**
+	 * Return the publish state.
+	 * 
+	 * @return org.eclipse.wst.server.core.internal.PublishState
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public PublishControl getPublishControl(IServer server, List parents, IModule module) {
+		String controlRef = getPublishControlRef(server, parents, module);
+		
+		// have we tried loading yet?
+		String serverId = server.getId();
+		if (servers.containsKey(serverId)) {
+			if (!loadedServers.contains(serverId)) {
+				loadServerPublishControls(serverId);
+				loadedServers.add(serverId);
+			} else {
+				// already loaded
+			}
+		} else {
+			// first time server is being used
+			IPath path = ServerPlugin.getInstance().getStateLocation().append(PUBLISH_DIR);
+			File file = new File(path.toOSString());
+			if (!file.exists())
+				file.mkdir();
+	
+			file = null;
+			int i = 0;
+			while (file == null || file.exists()) {
+				path = ServerPlugin.getInstance().getStateLocation().append(PUBLISH_DIR).append("data" + i + ".xml");
+				if (servers.get(path) == null)
+					file = new File(path.toOSString());
+				i++;
+			}
+			
+			servers.put(serverId, path);
+			loadedServers.add(serverId);
+			save();
+		}
+
+		// check if it now exists
+		if (publishControls.containsKey(controlRef)) {
+			PublishControl control = (PublishControl) publishControls.get(controlRef);
+			if (control != null)
+				return control;
+		}
+	
+		// have to create a new one
+		PublishControl control = new PublishControl(getParentsMemento(parents), module.getId());
+		publishControls.put(controlRef, control);
+		return control;
+	}
+
+	/**
+	 * 
+	 */
+	protected void load() {
+		Trace.trace(Trace.FINEST, "Loading publish info");
+		String filename = ServerPlugin.getInstance().getStateLocation().append("publish.xml").toOSString();
+	
+		try {
+			IMemento memento = XMLMemento.loadMemento(filename);
+	
+			IMemento[] serverChild = memento.getChildren("server");
+			int size = serverChild.length;
+			servers = new HashMap(size + 2);
+	
+			for (int i = 0; i < size; i++) {
+				String id = serverChild[i].getString("id");
+				String path = serverChild[i].getString("path");
+	
+				servers.put(id, new Path(path));
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not load global publish info: " + e.getMessage());
+		}
+	}
+
+	/**
+	 * 
+	 */
+	protected void save() {
+		String filename = ServerPlugin.getInstance().getStateLocation().append("publish.xml").toOSString();
+	
+		try {
+			XMLMemento memento = XMLMemento.createWriteRoot("publish-info");
+	
+			Iterator iterator = servers.keySet().iterator();
+			while (iterator.hasNext()) {
+				String serverId = (String) iterator.next();
+				IPath path = (IPath) servers.get(serverId);
+	
+				IMemento server = memento.createChild("server");
+				server.putString("id", serverId);
+				server.putString("path", path.toString());
+			}
+	
+			memento.saveToFile(filename);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save global publish info", e);
+		}
+	}
+	
+	public void save(IServer server) {
+		saveServerPublishControls(server.getId());
+	}
+
+	/**
+	 * 
+	 */
+	protected void loadServerPublishControls(String serverRef) {
+		IPath path = (IPath) servers.get(serverRef);
+		String filename = path.toOSString();
+		Trace.trace(Trace.FINEST, "Loading publish controls from " + filename);
+
+		try {
+			IMemento memento2 = XMLMemento.loadMemento(filename);
+			IMemento[] children = memento2.getChildren("module");
+	
+			int size = children.length;
+			for (int i = 0; i < size; i++) {
+				PublishControl control = new PublishControl(children[i]);
+				publishControls.put(getPublishControlRef(serverRef, control.getParentsRef(), control.getMemento()), control);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not load publish control information: " + e.getMessage());
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	protected void saveServerPublishControls(String serverRef) {
+		if (!servers.containsKey(serverRef))
+			return;
+
+		IPath path = (IPath) servers.get(serverRef);
+		String filename = path.toOSString();
+		Trace.trace(Trace.FINEST, "Saving publish controls to " + filename);
+	
+		try {
+			XMLMemento memento = XMLMemento.createWriteRoot("server");
+
+			Iterator iterator = publishControls.keySet().iterator();
+			while (iterator.hasNext()) {
+				String controlRef = (String) iterator.next();
+				if (controlRef.startsWith(serverRef + "#")) {
+					PublishControl control = (PublishControl) publishControls.get(controlRef);
+					IMemento child = memento.createChild("module");
+					control.save(child);
+				}
+			}
+			memento.saveToFile(filename);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save publish control information", e);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishManager.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishManager.java
new file mode 100644
index 0000000..c3a3df0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishManager.java
@@ -0,0 +1,102 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.IPublishControl;
+import org.eclipse.wst.server.core.IPublishManager;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IPublishManagerDelegate;
+/**
+ *
+ */
+public class PublishManager implements IPublishManager {
+	private IConfigurationElement element;
+	private IPublishManagerDelegate delegate;
+
+	/**
+	 * PublishManager constructor comment.
+	 */
+	public PublishManager(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * Returns the id of this publish manager.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+
+	/*
+	 * @see IPublishManager#getDescription()
+	 */
+	public String getDescription() {
+		String s = element.getAttribute("description");
+		if (s == null || s.length() == 0)
+			return "?";
+		else
+			return s;
+	}
+
+	/*
+	 * @see IPublishManager#getLabel()
+	 */
+	public String getName() {
+		String s = element.getAttribute("name");
+		if (s == null || s.length() == 0)
+			return "?";
+		else
+			return s;
+	}
+
+	/*
+	 * @see IPublishManager#getResourcesToDelete(IModule)
+	 */
+	public List getResourcesToDelete(IModule module) {
+		return getDelegate().getResourcesToDelete(module);
+	}
+
+	/*
+	 * @see IPublishManager#getResourcesToPublish(IModule)
+	 */
+	public List getResourcesToPublish(IModule module) {
+		return getDelegate().getResourcesToPublish(module);
+	}
+
+	/*
+	 * @see IPublishManager#resolve()
+	 */
+	public void resolve(IPublishControl[] control, IModule[] module, IProgressMonitor monitor) {
+		getDelegate().resolve(control, module, monitor);
+	}
+
+	/*
+	 * @see IPublishManager#getDelegate()
+	 */
+	public IPublishManagerDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IPublishManagerDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace("Could not create publisher", e);
+			}
+		}
+		return delegate;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishStatus.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishStatus.java
new file mode 100644
index 0000000..2fa1be4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishStatus.java
@@ -0,0 +1,235 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.*;
+import org.eclipse.core.runtime.IStatus;
+
+import org.eclipse.wst.server.core.IPublishStatus;
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * IStatus used during publishing. It contains the project
+ * or configuration that was published as extra information.
+ */
+public class PublishStatus implements IPublishStatus {
+	// Unique identifier of plug-in.
+	private String pluginId;
+
+	// Message, localized to the current locale.
+	private String message;
+
+	private List children;
+
+	private long time;
+	
+	private IModule module;
+	
+	private Throwable throwable;
+	
+	/**
+	 * PublishStatus constructor comment.
+	 */
+	public PublishStatus(String pluginId, String message, IModule module) {
+		super();
+		this.pluginId = pluginId;
+		this.message = message;
+		this.module = module;
+	}
+	
+	/**
+	 * PublishStatus constructor comment.
+	 */
+	public PublishStatus(String pluginId, String message, IModule module, Throwable throwable) {
+		this(pluginId, message, module);
+		this.throwable = throwable;
+	}
+
+	/**
+	 * 
+	 * @param status org.eclipse.core.runtime.IStatus
+	 */
+	public void addChild(IStatus status) {
+		getChildList().add(status);
+	}
+
+	/**
+	 * 
+	 * @return java.util.List
+	 */
+	protected List getChildList() {
+		if (children == null)
+			children = new ArrayList();
+		return children;
+	}
+
+	/**
+	 * Returns a list of status object immediately contained in this
+	 * multi-status, or an empty list if this is not a multi-status.
+	 *
+	 * @return an array of status objects
+	 * @see #isMultiStatus
+	 */
+	public IStatus[] getChildren() {
+		int size = getChildList().size();
+		IStatus[] status = new IStatus[size];
+		getChildList().toArray(status);
+		return status;
+	}
+
+	/**
+	 * Returns the plug-in-specific status code describing the outcome.
+	 *
+	 * @return plug-in-specific status code
+	 */
+	public int getCode() {
+		return 0;
+	}
+
+	/**
+	 * Returns the relevant low-level exception, or <code>null</code> if none. 
+	 * For example, when an operation fails because of a network communications
+	 * failure, this might return the <code>java.io.IOException</code>
+	 * describing the exact nature of that failure.
+	 *
+	 * @return the relevant low-level exception, or <code>null</code> if none
+	 */
+	public Throwable getException() {
+		return throwable;
+	}
+
+	/**
+	 * Returns the message describing the outcome.
+	 * The message is localized to the current locale.
+	 *
+	 * @return a localized message
+	 */
+	public String getMessage() {
+		return message;
+	}
+
+	/**
+	 * Returns the unique identifier of the plug-in associated with this status
+	 * (this is the plug-in that defines the meaning of the status code).
+	 *
+	 * @return the unique identifier of the relevant plug-in
+	 */
+	public String getPlugin() {
+		return pluginId;
+	}
+
+	/**
+	 * 
+	 * @return org.eclipse.core.resources.IProject
+	 */
+	public IModule getModule() {
+		return module;
+	}
+	
+	/**
+	 * Returns the severity. The severities are as follows (in
+	 * descending order):
+	 * <ul>
+	 * <li><code>ERROR</code> - a serious error (most severe)</li>
+	 * <li><code>WARNING</code> - a warning (less severe)</li>
+	 * <li><code>INFO</code> - an informational ("fyi") message (least severe)</li>
+	 * <li><code>OK</code> - everything is just fine</li>
+	 * </ul>
+	 * <p>
+	 * The severity of a multi-status is defined to be the maximum
+	 * severity of any of its children, or <code>OK</code> if it has
+	 * no children.
+	 * </p>
+	 *
+	 * @return the severity: one of <code>OK</code>,
+	 *   <code>ERROR</code>, <code>INFO</code>, or <code>WARNING</code>
+	 * @see #matches
+	 */
+	public int getSeverity() {
+		int sev = IStatus.OK;
+	
+		Iterator iterator = getChildList().iterator();
+		while (iterator.hasNext()) {
+			IStatus status = (IStatus) iterator.next();
+			sev = Math.max(sev, status.getSeverity());
+		}
+		return sev;
+	}
+
+	/**
+	 * 
+	 * @return long
+	 */
+	public long getTime() {
+		return time;
+	}
+
+	/**
+	 * Returns whether this status is a multi-status.
+	 * A multi-status describes the outcome of an operation
+	 * involving multiple operands.
+	 * <p>
+	 * The severity of a multi-status is derived from the severities
+	 * of its children; a multi-status with no children is
+	 * <code>OK</code> by definition.
+	 * A multi-status carries a plug-in identifier, a status code,
+	 * a message, and an optional exception. Clients may treat
+	 * multi-status objects in a multi-status unaware way.
+	 * </p>
+	 *
+	 * @return <code>true</code> for a multi-status, 
+	 *    <code>false</code> otherwise
+	 * @see #getChildren
+	 */
+	public boolean isMultiStatus() {
+		return true;
+	}
+
+	/**
+	 * Returns whether this status indicates everything is okay
+	 * (neither info, warning, nor error).
+	 *
+	 * @return <code>true</code> if this status has severity
+	 *    <code>OK</code>, and <code>false</code> otherwise
+	 */
+	public boolean isOK() {
+		return (getSeverity() == IStatus.OK);
+	}
+
+	/**
+	 * Returns whether the severity of this status matches the given
+	 * specification.
+	 *
+	 * @param severityMask a mask formed by bitwise or'ing severity mask
+	 *    constants (<code>ERROR</code>, <code>WARNING</code>,
+	 *    <code>INFO</code>)
+	 * @return <code>true</code> if there is at least one match, 
+	 *    <code>false</code> if there are no matches
+	 * @see #getSeverity
+	 * @see #ERROR
+	 * @see #WARNING
+	 * @see #INFO
+	 */
+	public boolean matches(int severityMask) {
+		return (getSeverity() & severityMask) != 0;
+	}
+
+	/**
+	 * 
+	 * @param time long
+	 */
+	public void setTime(long time) {
+		this.time = time;
+	}
+
+	public String toString() {
+		return "PublishStatus [" + getSeverity() + " " + getCode() + " " + getMessage() + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishStatusItem.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishStatusItem.java
new file mode 100644
index 0000000..ef2d4da
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/PublishStatusItem.java
@@ -0,0 +1,168 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.runtime.IStatus;
+/**
+ * IStatus used as child of a PublishStatus. It is just a
+ * wrapper around another IStatus, used to give information
+ * about the contained IStatus.
+ */
+public class PublishStatusItem implements IStatus {
+	// Unique identifier of plug-in.
+	private String pluginId;
+
+	// Message, localized to the current locale.
+	private String message;
+
+	private IStatus child;
+
+	/**
+	 * PublishStatus constructor comment.
+	 */
+	public PublishStatusItem(String pluginId, String message, IStatus child) {
+		super();
+		this.pluginId = pluginId;
+		this.message = message;
+		this.child = child;
+	}
+
+	/**
+	 * Returns a list of status object immediately contained in this
+	 * multi-status, or an empty list if this is not a multi-status.
+	 *
+	 * @return an array of status objects
+	 * @see #isMultiStatus
+	 */
+	public IStatus[] getChildren() {
+		if (child == null)
+			return new IStatus[0];
+		else
+			return new IStatus[] { child };
+	}
+
+	/**
+	 * Returns the plug-in-specific status code describing the outcome.
+	 *
+	 * @return plug-in-specific status code
+	 */
+	public int getCode() {
+		return 0;
+	}
+
+	/**
+	 * Returns the relevant low-level exception, or <code>null</code> if none. 
+	 * For example, when an operation fails because of a network communications
+	 * failure, this might return the <code>java.io.IOException</code>
+	 * describing the exact nature of that failure.
+	 *
+	 * @return the relevant low-level exception, or <code>null</code> if none
+	 */
+	public Throwable getException() {
+		return null;
+	}
+
+	/**
+	 * Returns the message describing the outcome.
+	 * The message is localized to the current locale.
+	 *
+	 * @return a localized message
+	 */
+	public String getMessage() {
+		return message;
+	}
+
+	/**
+	 * Returns the unique identifier of the plug-in associated with this status
+	 * (this is the plug-in that defines the meaning of the status code).
+	 *
+	 * @return the unique identifier of the relevant plug-in
+	 */
+	public String getPlugin() {
+		return pluginId;
+	}
+
+	/**
+	 * Returns the severity. The severities are as follows (in
+	 * descending order):
+	 * <ul>
+	 * <li><code>ERROR</code> - a serious error (most severe)</li>
+	 * <li><code>WARNING</code> - a warning (less severe)</li>
+	 * <li><code>INFO</code> - an informational ("fyi") message (least severe)</li>
+	 * <li><code>OK</code> - everything is just fine</li>
+	 * </ul>
+	 * <p>
+	 * The severity of a multi-status is defined to be the maximum
+	 * severity of any of its children, or <code>OK</code> if it has
+	 * no children.
+	 * </p>
+	 *
+	 * @return the severity: one of <code>OK</code>,
+	 *   <code>ERROR</code>, <code>INFO</code>, or <code>WARNING</code>
+	 * @see #matches
+	 */
+	public int getSeverity() {
+		if (child == null)
+			return IStatus.OK;
+		else
+			return child.getSeverity();
+	}
+
+	/**
+	 * Returns whether this status is a multi-status.
+	 * A multi-status describes the outcome of an operation
+	 * involving multiple operands.
+	 * <p>
+	 * The severity of a multi-status is derived from the severities
+	 * of its children; a multi-status with no children is
+	 * <code>OK</code> by definition.
+	 * A multi-status carries a plug-in identifier, a status code,
+	 * a message, and an optional exception. Clients may treat
+	 * multi-status objects in a multi-status unaware way.
+	 * </p>
+	 *
+	 * @return <code>true</code> for a multi-status, 
+	 *    <code>false</code> otherwise
+	 * @see #getChildren
+	 */
+	public boolean isMultiStatus() {
+		return true;
+	}
+
+	/**
+	 * Returns whether this status indicates everything is okay
+	 * (neither info, warning, nor error).
+	 *
+	 * @return <code>true</code> if this status has severity
+	 *    <code>OK</code>, and <code>false</code> otherwise
+	 */
+	public boolean isOK() {
+		return (getSeverity() == IStatus.OK);
+	}
+
+	/**
+	 * Returns whether the severity of this status matches the given
+	 * specification.
+	 *
+	 * @param severityMask a mask formed by bitwise or'ing severity mask
+	 *    constants (<code>ERROR</code>, <code>WARNING</code>,
+	 *    <code>INFO</code>)
+	 * @return <code>true</code> if there is at least one match, 
+	 *    <code>false</code> if there are no matches
+	 * @see #getSeverity
+	 * @see #ERROR
+	 * @see #WARNING
+	 * @see #INFO
+	 */
+	public boolean matches(int severityMask) {
+		return (getSeverity() & severityMask) != 0;
+	}
+}
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
new file mode 100644
index 0000000..0173684
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ResourceManager.java
@@ -0,0 +1,1451 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.io.ByteArrayInputStream;
+import java.util.*;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.*;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.*;
+import org.eclipse.wst.server.core.util.ProgressUtil;
+/**
+ * ResourceManager handles the mappings between resources
+ * and servers or server configurations, and creates
+ * notification of servers or server configurations
+ * being added and removed.
+ *
+ * <p>Servers and server configurations may be a single
+ * resource, or they may be a folder that contains a group
+ * of files. Folder-resource may not contain other servers
+ * or configurations.</p>
+ */
+public class ResourceManager implements IResourceManager {
+	private static final String SERVER_DATA_FILE = "servers.xml";
+	private static final String SERVER_CONFIGURATION_DATA_FILE = "configurations.xml";
+
+	private static ResourceManager instance;
+
+	// currently active runtimes, servers, and server configurations
+	protected List runtimes;
+	protected List servers;
+	protected List configurations;
+	protected IRuntime defaultRuntime;
+
+	// server resource change listeners
+	protected transient List listeners;
+
+	// resource change listeners
+	private IResourceChangeListener modelResourceChangeListener;
+	private IResourceChangeListener publishResourceChangeListener;
+	private Preferences.IPropertyChangeListener pcl;
+	protected boolean ignorePreferenceChanges = false;
+	
+	// module factory listener
+	private IModuleFactoryListener moduleFactoryListener;
+	protected List moduleFactoryEvents = new ArrayList(5);
+	
+	// module listener
+	protected IModuleListener moduleListener;
+	protected List moduleEvents = new ArrayList(5);
+	
+	// module events listeners
+	protected transient List moduleEventListeners;
+
+	/**
+	 * Resource listener - tracks changes on server resources so that
+	 * we can reload/drop server instances and configurations that
+	 * may change outside of our control.
+	 * Listens for two types of changes:
+	 * 1. Servers or configurations being added or removed
+	 *    from their respective folders. (in the future, including
+	 *    the addition or removal of a full server project, which
+	 *    we currently can't listen for because there is no nature
+	 *    attached to the project at this point - OTI defect)
+	 * 2. Projects being deleted.
+	 */
+	public class ServerModelResourceChangeListener implements IResourceChangeListener {
+		/**
+		 * Create a new ServerModelResourceChangeListener.
+		 */
+		public ServerModelResourceChangeListener() {
+			super();
+		}
+
+		/**
+		 * Listen for projects being added or removed and act accordingly.
+		 *
+		 * @param event org.eclipse.core.resources.IResourceChangeEvent
+		 */
+		public void resourceChanged(IResourceChangeEvent event) {
+			IResourceDelta delta = event.getDelta();
+			if (delta == null)
+				return;
+	
+			Trace.trace(Trace.RESOURCES, "->- ServerModelResourceManager responding to resource change: " + event.getType() + " ->-");
+			IResourceDelta[] children = delta.getAffectedChildren();
+			if (children != null) {
+				int size = children.length;
+				for (int i = 0; i < size; i++) {
+					IResource resource = children[i].getResource();
+					if (resource != null && resource instanceof IProject) {
+						projectChanged((IProject) resource, children[i]);
+					}
+				}
+			}
+	
+			Trace.trace(Trace.RESOURCES, "-<- Done ServerModelResourceManager responding to resource change -<-");
+		}
+	
+		/**
+		 * React to a change within a possible server project.
+		 *
+		 * @param delta org.eclipse.core.resources.IResourceDelta
+		 */
+		protected void projectChanged(IProject project, IResourceDelta delta) {
+			try {
+				if (project.exists() && !project.hasNature(IServerProject.NATURE_ID)) {
+					Trace.trace(Trace.RESOURCES, "Not a server project: " + project.getName());
+					return;
+				}
+			} catch (CoreException e) {
+				Trace.trace(Trace.SEVERE, "Could not verify project nature: " + project.getName() + " - " + e.getMessage());
+			}
+			
+			if (!project.exists()) {
+				Iterator iterator = ServerProjectNature.serverProjects.iterator();
+				boolean found = false;
+				while (iterator.hasNext()) {
+					IProject serverProject = (IProject) iterator.next();
+					if (serverProject.equals(project))
+						found = true;
+				}
+				if (!found)
+					return;
+			}
+
+			IResourceDelta[] children = delta.getAffectedChildren();
+	
+			int size = children.length;
+			for (int i = 0; i < size; i++) {
+				IResourceDelta child = children[i];
+
+				// look for servers and server configurations
+				try {
+					child.accept(new IResourceDeltaVisitor() {
+						public boolean visit(IResourceDelta delta2) {
+							return handleResourceDelta(delta2);
+						}
+					});
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Error responding to resource change", e);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Publish resource listener
+	 */
+	public class PublishResourceChangeListener implements IResourceChangeListener {
+		/**
+		 * Create a new PublishResourceChangeListener.
+		 */
+		public PublishResourceChangeListener() {
+			super();
+		}
+
+		/**
+		 * Listen for projects being added or removed and act accordingly.
+		 *
+		 * @param event org.eclipse.core.resources.IResourceChangeEvent
+		 */
+		public void resourceChanged(IResourceChangeEvent event) {
+			IResourceDelta delta = event.getDelta();
+			if (delta == null)
+				return;
+		
+			Trace.trace(Trace.FINEST, "->- PublishResourceManager responding to resource change: " + event.getType() + " ->-");
+			// search for changes to any project using a visitor
+			try {
+				delta.accept(new IResourceDeltaVisitor() {
+					public boolean visit(IResourceDelta visitorDelta) {
+						IResource resource = visitorDelta.getResource();
+
+						// only respond to project changes
+						if (resource != null && resource instanceof IProject) {
+							publishHandleProjectChange(visitorDelta);
+							return false;
+						}
+						return true;
+					}
+				});
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error responding to resource change", e);
+			}
+			Trace.trace(Trace.FINEST, "-<- Done PublishResourceManager responding to resource change -<-");
+		}
+	}
+	
+	public class ModuleFactoryListener implements IModuleFactoryListener {
+		public void moduleFactoryChanged(IModuleFactoryEvent event) {
+			Trace.trace(Trace.FINEST, "Module factory changed: " + event.getFactoryId());
+			moduleFactoryEvents.add(event);
+
+			// add new listeners
+			IModule[] modules = event.getAddedModules();
+			if (modules != null) {
+				int size = modules.length;
+				for (int i = 0; i < size; i++) {
+					Trace.trace(Trace.FINEST, "Adding module listener to: " + modules[i]);
+					modules[i].addModuleListener(moduleListener);
+				}
+			}
+			
+			// remove old listeners
+			modules = event.getRemovedModules();
+			if (modules != null) {
+				int size = modules.length;
+				for (int i = 0; i < size; i++) {
+					Trace.trace(Trace.FINEST, "Removing module listener from: " + modules[i]);
+					modules[i].removeModuleListener(moduleListener);
+				}
+			}
+		}
+	}
+
+	public class ModuleListener implements IModuleListener {
+		public void moduleChanged(IModuleEvent event) {
+			Trace.trace(Trace.FINEST, "Module changed: " + event);
+			if (!moduleEvents.contains(event))
+				moduleEvents.add(event);
+		}
+	}
+	
+	protected List moduleServerEventHandlers;
+	protected List moduleServerEventHandlerIndexes;
+	
+	class ModuleServerEvent implements IServerLifecycleEvent {
+		IServer server;
+		IModuleFactoryEvent[] factoryEvents;
+		IModuleEvent[] events;
+		ITask[] tasks;
+
+		public IServer getServer() {
+			return server;
+		}
+
+		public IModuleFactoryEvent[] getModuleFactoryEvents() {
+			return factoryEvents;
+		}
+
+		public IModuleEvent[] getModuleEvents() {
+			return events;
+		}
+
+		public ITask[] getTasks() {
+			return tasks;
+		}
+	}
+
+	/**
+	 * Cannot directly create a ResourceManager. Use
+	 * ServersCore.getResourceManager().
+	 */
+	private ResourceManager() {
+		super();
+		instance = this;
+		
+		init();
+	}
+
+	protected void init() {
+		servers = new ArrayList();
+		configurations = new ArrayList();
+		loadRuntimesList();
+		loadServersList();
+		loadServerConfigurationsList();
+		
+		pcl = new Preferences.IPropertyChangeListener() {
+			public void propertyChange(Preferences.PropertyChangeEvent event) {
+				if (ignorePreferenceChanges)
+					return;
+				String property = event.getProperty();
+				if (property.equals("runtimes")) {
+					loadRuntimesList();
+					saveRuntimesList();
+				}
+			}
+		};
+		
+		ServerPlugin.getInstance().getPluginPreferences().addPropertyChangeListener(pcl);
+		
+		resolveServers();
+
+		// keep track of future changes to the file system
+		modelResourceChangeListener = new ServerModelResourceChangeListener();
+		ResourcesPlugin.getWorkspace().addResourceChangeListener(modelResourceChangeListener, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE);
+	
+		// add listener for future changes
+		publishResourceChangeListener = new PublishResourceChangeListener();
+		ResourcesPlugin.getWorkspace().addResourceChangeListener(publishResourceChangeListener, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_DELETE);
+	
+		/*configurationListener = new IServerConfigurationListener() {
+			public void childProjectChange(IServerConfiguration configuration) {
+				handleConfigurationChildProjectsChange(configuration);
+			}
+		};*/
+		
+		Trace.trace(Trace.FINER, "Loading workspace servers and server configurations");
+		ServerCore.getServerNatures();
+		
+		moduleFactoryListener = new ModuleFactoryListener();
+		moduleListener = new ModuleListener();
+		
+		addResourceListener(ServerListener.getInstance());
+	}
+	
+	public static ResourceManager getInstance() {
+		if (instance == null)
+			new ResourceManager();
+
+		return instance;
+	}
+	
+	public static void shutdown() {
+		if (instance == null)
+			return;
+		
+		try {
+			instance.shutdownImpl();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error during shutdown", e);
+		}
+	}
+	
+	protected void shutdownImpl() {
+		// stop all running servers
+		Iterator iterator = getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			try {
+				if (server.getServerState() != IServer.SERVER_STOPPED) {
+					IServerDelegate delegate = server.getDelegate();
+					if (delegate instanceof IStartableServer && ((IStartableServer)delegate).isTerminateOnShutdown())
+						((IStartableServer) delegate).terminate();
+				}
+			} catch (Exception e) { }
+		}
+
+		IWorkspace workspace = ResourcesPlugin.getWorkspace();
+		if (workspace != null) {
+			workspace.removeResourceChangeListener(modelResourceChangeListener);
+			workspace.removeResourceChangeListener(publishResourceChangeListener);
+		}
+		
+		ServerPlugin.getInstance().getPluginPreferences().removePropertyChangeListener(pcl);
+		
+		removeResourceListener(ServerListener.getInstance());
+	}
+
+	/**
+	 * Adds a new server resource listener.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IServerResourceListener
+	 */
+	public void addResourceListener(IServerResourceListener listener) {
+		Trace.trace(Trace.LISTENERS, "Adding server resource listener " + listener + " to " + this);
+	
+		if (listeners == null)
+			listeners = new ArrayList();
+		listeners.add(listener);
+	}
+	
+	/**
+	 * Deregister an existing runtime.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 */
+	protected void deregisterRuntime(IRuntime runtime) {
+		if (runtime == null)
+			return;
+
+		Trace.trace(Trace.RESOURCES, "Deregistering runtime: " + runtime.getName());
+
+		((Runtime)runtime).dispose();
+		fireServerResourceRemoved(runtime);
+		runtimes.remove(runtime);
+	}
+
+	/**
+	 * Deregister an existing server resource.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 */
+	protected void deregisterServer(IServer server) {
+		if (server == null)
+			return;
+
+		Trace.trace(Trace.RESOURCES, "Deregistering server: " + server.getName());
+
+		// terminate server if it is being deleted!
+		byte state = server.getServerState();
+		if (state != IServer.SERVER_STOPPED && state != IServer.SERVER_STOPPING &&
+				state != IServer.SERVER_UNKNOWN) {
+			IServerDelegate delegate = server.getDelegate();
+			if (delegate instanceof IStartableServer) {
+				((IStartableServer) delegate).terminate();
+			}
+		}
+		
+		((Server) server).deleteLaunchConfigurations();
+		ServerPlugin.getInstance().removeTempDirectory(server.getId(), new NullProgressMonitor());
+
+		((Server)server).dispose();
+		fireServerResourceRemoved(server);
+		servers.remove(server);
+	}
+
+	/**
+	 * Deregister an existing server resource.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 */
+	protected void deregisterServerConfiguration(IServerConfiguration configuration) {
+		if (configuration == null)
+			return;
+	
+		Trace.trace(Trace.RESOURCES, "Deregistering server configuration: " + configuration.getName());
+
+		((ServerConfiguration)configuration).dispose();
+		resolveServers();
+		fireServerResourceRemoved(configuration);
+		configurations.remove(configuration);
+	}
+
+	/**
+	 * Fire a event because a new element has been added.
+	 *
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	private void fireServerResourceAdded(final IElement element) {
+		Trace.trace(Trace.LISTENERS, "->- Firing serverResourceAdded event: " + element.getName() + " ->-");
+		
+		if (listeners == null || listeners.isEmpty())
+			return;
+	
+		int size = listeners.size();
+		IServerResourceListener[] srl = new IServerResourceListener[size];
+		listeners.toArray(srl);
+	
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.LISTENERS, "  Firing serverResourceAdded event to " + srl[i]);
+			try {
+				if (element instanceof IRuntime)
+					srl[i].runtimeAdded((IRuntime) element);
+				else if (element instanceof IServer)
+					srl[i].serverAdded((IServer) element);
+				else
+					srl[i].serverConfigurationAdded((IServerConfiguration) element);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing serverResourceAdded event to " + srl[i], e);
+			}
+		}
+		Trace.trace(Trace.LISTENERS, "-<- Done firing serverResourceAdded event -<-");
+	}
+
+	/**
+	 * Fire a event because a resource has been changed.
+	 *
+	 * @param resource org.eclipse.wst.server.core.model.IServerResource
+	 */
+	private void fireServerResourceChanged(final IElement element) {
+		Trace.trace(Trace.LISTENERS, "->- Firing serverResourceChanged event: " + element.getName() + " ->-");
+	
+		if (listeners == null || listeners.isEmpty())
+			return;
+	
+		int size = listeners.size();
+		IServerResourceListener[] srl = new IServerResourceListener[size];
+		listeners.toArray(srl);
+	
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.LISTENERS, "  Firing serverResourceChanged event to " + srl[i]);
+			try {
+				if (element instanceof IRuntime)
+					srl[i].runtimeChanged((IRuntime) element);
+				else if (element instanceof IServer)
+					srl[i].serverChanged((IServer) element);
+				else
+					srl[i].serverConfigurationChanged((IServerConfiguration) element);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing serverResourceChanged event to " + srl[i], e);
+			}
+		}
+	
+		Trace.trace(Trace.LISTENERS, "-<- Done firing serverResourceChanged event -<-");
+	}
+
+	/**
+	 * Fire a event because a resource has been removed. Note
+	 * that although the physical resource no longer exists,
+	 * the element will remain in the resource manager until
+	 * after this event is fired.
+	 *
+	 * @param info org.eclipse.wst.server.core.model.IServerResource
+	 */
+	private void fireServerResourceRemoved(final IElement element) {
+		Trace.trace(Trace.LISTENERS, "->- Firing serverResourceRemoved event: " + element.getName() + " ->-");
+	
+		if (listeners == null || listeners.isEmpty())
+			return;
+	
+		int size = listeners.size();
+		IServerResourceListener[] srl = new IServerResourceListener[size];
+		listeners.toArray(srl);
+	
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.LISTENERS, "  Firing serverResourceRemoved event to " + srl[i]);
+			try {
+				if (element instanceof IRuntime)
+					srl[i].runtimeRemoved((IRuntime) element);
+				else if (element instanceof IServer)
+					srl[i].serverRemoved((IServer) element);
+				else
+					srl[i].serverConfigurationRemoved((IServerConfiguration) element);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing serverResourceRemoved event to " + srl[i], e);
+			}
+		}
+	
+		Trace.trace(Trace.LISTENERS, "-<- Done firing serverResourceRemoved event -<-");
+	}
+
+	/**
+	 * Returns the server configuration that came from the
+	 * given resource.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 * @return org.eclipse.wst.server.core.model.IServerConfiguration
+	 */
+	public IServerConfiguration getServerConfiguration(IFile file) {
+		if (file == null)
+			return null;
+		
+		Iterator iterator = configurations.iterator();
+		while (iterator.hasNext()) {
+			IServerConfiguration config = (IServerConfiguration) iterator.next();
+			if (file.equals(config.getFile()))
+				return config;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns a list of all currently active server configurations.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServerConfigurations() {
+		List list = new ArrayList(configurations);
+		return ServerPlugin.sortServerResourceList(list);
+	}
+	
+	/**
+	 * Returns a list of all servers configs.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServerConfigurations(IServerConfigurationType configType) {
+		List list = new ArrayList();
+		Iterator iterator = configurations.iterator();
+		while (iterator.hasNext()) {
+			IServerConfiguration config = (IServerConfiguration) iterator.next();
+			if (config.getServerConfigurationType().equals(configType))
+				list.add(config);
+		}
+		return list;
+	}
+	
+	/**
+	 * Returns a list of all servers.
+	 *
+	 * @return java.util.List
+	 */
+	public IServerConfiguration getServerConfiguration(String id) {
+		if (id == null)
+			return null;
+	
+		Iterator iterator = configurations.iterator();
+		while (iterator.hasNext()) {
+			IServerConfiguration config = (IServerConfiguration) iterator.next();
+			if (id.equals(config.getId()))
+				return config;
+		}
+		return null;
+	}
+	
+	protected void saveRuntimesList() {
+		try {
+			ignorePreferenceChanges = true;
+			XMLMemento memento = XMLMemento.createWriteRoot("runtimes");
+			
+			if (defaultRuntime != null) {
+				int ind = runtimes.indexOf(defaultRuntime);
+				if (ind >= 0)
+					memento.putString("default", ind + "");
+			}
+
+			Iterator iterator = runtimes.iterator();
+			while (iterator.hasNext()) {
+				Runtime runtime = (Runtime) iterator.next();
+
+				IMemento child = memento.createChild("runtime");
+				runtime.save(child);
+			}
+
+			String xmlString = memento.saveToString();
+			Preferences prefs = ServerPlugin.getInstance().getPluginPreferences();
+			prefs.setValue("runtimes", xmlString);
+			ServerPlugin.getInstance().savePluginPreferences();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save runtimes", e);
+		}
+		ignorePreferenceChanges = false;
+	}
+	
+	protected void saveServersList() {
+		String filename = ServerPlugin.getInstance().getStateLocation().append(SERVER_DATA_FILE).toOSString();
+		
+		try {
+			XMLMemento memento = XMLMemento.createWriteRoot("servers");
+
+			Iterator iterator = servers.iterator();
+			while (iterator.hasNext()) {
+				Server server = (Server) iterator.next();
+
+				IMemento child = memento.createChild("server");
+				server.save(child);
+			}
+
+			memento.saveToFile(filename);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save servers", e);
+		}
+	}
+	
+	protected void saveServerConfigurationsList() {
+		String filename = ServerPlugin.getInstance().getStateLocation().append(SERVER_CONFIGURATION_DATA_FILE).toOSString();
+		
+		try {
+			XMLMemento memento = XMLMemento.createWriteRoot("server-configurations");
+
+			Iterator iterator = configurations.iterator();
+			while (iterator.hasNext()) {
+				ServerConfiguration config = (ServerConfiguration) iterator.next();
+
+				IMemento child = memento.createChild("configuration");
+				config.save(child);
+			}
+
+			memento.saveToFile(filename);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save server configurations", e);
+		}
+	}
+	
+	protected void loadRuntimesList() {
+		Trace.trace(Trace.FINEST, "Loading runtime info");
+		Preferences prefs = ServerPlugin.getInstance().getPluginPreferences();
+		String xmlString = prefs.getString("runtimes");
+		
+		runtimes = new ArrayList();
+		if (xmlString != null && xmlString.length() > 0) {
+			try {
+				ByteArrayInputStream in = new ByteArrayInputStream(xmlString.getBytes());
+				IMemento memento = XMLMemento.loadMemento(in);
+		
+				IMemento[] children = memento.getChildren("runtime");
+				int size = children.length;
+				
+				for (int i = 0; i < size; i++) {
+					Runtime runtime = new Runtime(null);
+					runtime.loadFromMemento(children[i], new NullProgressMonitor());
+					runtimes.add(runtime);
+				}
+				
+				String s = memento.getString("default");
+				try {
+					int ind = Integer.parseInt(s);
+					defaultRuntime = (IRuntime) runtimes.get(ind);
+				} catch (Exception ex) { }
+			} catch (Exception e) {
+				Trace.trace(Trace.WARNING, "Could not load runtimes: " + e.getMessage());
+			}
+		}
+	}
+	
+	protected void loadServersList() {
+		Trace.trace(Trace.FINEST, "Loading server info");
+		String filename = ServerPlugin.getInstance().getStateLocation().append(SERVER_DATA_FILE).toOSString();
+		
+		try {
+			IMemento memento = XMLMemento.loadMemento(filename);
+			
+			IMemento[] children = memento.getChildren("server");
+			int size = children.length;
+			
+			for (int i = 0; i < size; i++) {
+				Server server = new Server(null);
+				server.loadFromMemento(children[i], new NullProgressMonitor());
+				servers.add(server);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not load servers: " + e.getMessage());
+		}
+	}
+	
+	protected void loadServerConfigurationsList() {
+		Trace.trace(Trace.FINEST, "Loading server configuration info");
+		String filename = ServerPlugin.getInstance().getStateLocation().append(SERVER_CONFIGURATION_DATA_FILE).toOSString();
+		
+		try {
+			IMemento memento = XMLMemento.loadMemento(filename);
+			
+			IMemento[] children = memento.getChildren("configuration");
+			int size = children.length;
+			
+			for (int i = 0; i < size; i++) {
+				ServerConfiguration config = new ServerConfiguration(null);
+				config.loadFromMemento(children[i], new NullProgressMonitor());
+				configurations.add(config);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not load server configurations: " + e.getMessage());
+		}
+	}
+	
+	protected void addRuntime(IRuntime runtime) {
+		if (!runtimes.contains(runtime))
+			registerRuntime(runtime);
+		else
+			fireServerResourceChanged(runtime);
+		saveRuntimesList();
+		resolveServers();
+	}
+
+	protected void removeRuntime(IRuntime runtime) {
+		if (runtimes.contains(runtime)) {
+			deregisterRuntime(runtime);
+			saveRuntimesList();
+			resolveServers();
+		}
+	}
+
+	protected void addServer(IServer server) {
+		if (!servers.contains(server))
+			registerServer(server);
+		else
+			fireServerResourceChanged(server);
+		saveServersList();
+		resolveServers();
+	}
+
+	protected void removeServer(IServer server) {
+		if (servers.contains(server)) {
+			deregisterServer(server);
+			saveServersList();
+			resolveServers();
+		}
+	}
+
+	protected void addServerConfiguration(IServerConfiguration config) {
+		if (!configurations.contains(config))
+			registerServerConfiguration(config);
+		else
+			fireServerResourceChanged(config);
+		saveServerConfigurationsList();
+		resolveServers();
+	}
+
+	protected void removeServerConfiguration(IServerConfiguration config) {
+		if (configurations.contains(config)) {
+			deregisterServerConfiguration(config);
+			saveServerConfigurationsList();
+			resolveServers();
+		}
+	}
+
+	/**
+	 * Returns a list of all runtimes.
+	 *
+	 * @return java.util.List
+	 */
+	public List getRuntimes() {
+		List list = new ArrayList(runtimes);
+		
+		int size = list.size();
+		for (int i = 0; i < size - 1; i++) {
+			for (int j = i + 1; j < size; j++) {
+				IRuntime a = (IRuntime) list.get(i);
+				IRuntime b = (IRuntime) list.get(j);
+				if (a.getRuntimeType().getOrder() < b.getRuntimeType().getOrder()) {
+					Object temp = a;
+					list.set(i, b);
+					list.set(j, temp);
+				}
+			}
+		}
+		
+		if (defaultRuntime != null) {
+			list.remove(defaultRuntime);
+			list.add(0, defaultRuntime);
+		}
+		
+		return list;
+	}
+	
+	/**
+	 * Returns the runtimes with the given runtime type.
+	 *
+	 * @return java.util.List
+	 */
+	public List getRuntimes(IRuntimeType runtimeType) {
+		List list = new ArrayList();
+		Iterator iterator = runtimes.iterator();
+		while (iterator.hasNext()) {
+			IRuntime runtime = (IRuntime) iterator.next();
+			if (runtime.getRuntimeType() != null && runtime.getRuntimeType().equals(runtimeType))
+				list.add(runtime);
+		}
+		return list;
+	}
+	
+	/**
+	 * Returns the runtime with the given id.
+	 *
+	 * @return IRuntime
+	 */
+	public IRuntime getRuntime(String id) {
+		Iterator iterator = runtimes.iterator();
+		while (iterator.hasNext()) {
+			IRuntime runtime = (IRuntime) iterator.next();
+			if (runtime.getId().equals(id))
+				return runtime;
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns the default runtime. Test API - do not use.
+	 *
+	 * @return java.util.List
+	 */
+	public IRuntime getDefaultRuntime() {
+		return defaultRuntime;
+	}
+	
+	/**
+	 * Sets the default runtime. Test API - do not use.
+	 *
+	 * @return java.util.List
+	 */
+	public void setDefaultRuntime(IRuntime runtime) {
+		defaultRuntime = runtime;
+		saveRuntimesList();
+	}
+
+	protected void resolveServers() {
+		Iterator iterator = servers.iterator();
+		while (iterator.hasNext()) {
+			Server server = (Server) iterator.next();
+			server.resolve();
+		}
+	}
+
+	/**
+	 * Returns the server that came from the
+	 * given resource.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 * @return org.eclipse.wst.server.core.model.IServer
+	 */
+	public IServer getServer(IFile file) {
+		if (file == null)
+			return null;
+		Iterator iterator = servers.iterator();
+		while (iterator.hasNext()) {
+			Server server = (Server) iterator.next();
+			if (file.equals(server.getFile()))
+				return server;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns a list of all servers.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServers() {
+		List list = new ArrayList(servers);
+		return ServerPlugin.sortServerResourceList(list);
+	}
+
+	/**
+	 * Returns a list of all servers.
+	 *
+	 * @return java.util.List
+	 */
+	public IServer getServer(String id) {
+		if (id == null)
+			return null;
+	
+		Iterator iterator = servers.iterator();
+		while (iterator.hasNext()) {
+			Server server = (Server) iterator.next();
+			if (id.equals(server.getId()))
+				return server;
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns a list of all servers.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServers(IServerType serverType) {
+		List list = new ArrayList();
+		Iterator iterator = servers.iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (server.getServerType().equals(serverType))
+				list.add(server);
+		}
+		return list;
+	}
+
+	/**
+	 * Handle a change to the child projects of this configuration.
+	 *
+	 * @param configuration org.eclipse.wst.server.core.model.IServerConfiguration
+	 */
+	protected void handleConfigurationChildProjectsChange(IServerConfiguration configuration) {
+		/*String configRef = ServerCore.getServerConfigurationRef(configuration);
+		if (configRef == null || configRef.length() == 0)
+			return;
+	
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer2 server = (IServer2) iterator.next();
+			if (server.getServerConfiguration().equals(configuration)) {
+				ServerControl control = (ServerControl) ServerCore.getServerControl(server);
+				control.handleConfigurationChildProjectChange(configuration);
+			}
+		}*/
+	}
+
+	/**
+	 * Returns true if the resource change was handled.
+	 *
+	 * @param delta org.eclipse.core.resources.IResourceDelta
+	 * @return boolean
+	 */
+	protected boolean handleResourceDelta(IResourceDelta delta) {
+		int kind = delta.getKind();
+		IResource resource2 = delta.getResource();
+	
+		// ignore markers
+		if (kind == IResourceDelta.CHANGED && (delta.getFlags() & IResourceDelta.MARKERS) != 0)
+			return false;
+	
+		Trace.trace(Trace.RESOURCES, "Resource changed: " + resource2 + " " + kind);
+		
+		if (resource2 instanceof IFile) {
+			IFile file = (IFile) resource2;
+			IProgressMonitor monitor = new NullProgressMonitor();
+			if (kind == IResourceDelta.ADDED) {
+				handleNewFile(file, monitor);
+			} else if (kind == IResourceDelta.REMOVED) {
+				handleRemovedFile(file);
+			} else
+				handleChangedFile(file, monitor);
+			monitor.done();
+			return false;
+		} else
+			return true;
+	
+		/*IProgressMonitor monitor = new NullProgressMonitor();
+		List list = getResourceParentList(resource2);
+		monitor.beginTask("", list.size() * 1000);
+	
+		Iterator iterator = list.iterator();
+		while (iterator.hasNext()) {
+			IResource resource = (IResource) iterator.next();
+			if (!visited.contains(resource.getFullPath())) {
+				visited.add(resource.getFullPath());
+				if (kind == IResourceDelta.REMOVED) {
+					boolean b = handleRemovedFile(resource);
+					if (b) {
+						if (resource instanceof IContainer)
+							removeServerResourcesBelow((IContainer) resource);
+						return false;
+					} else
+						return true;
+				} else if (kind == IResourceDelta.ADDED) {
+					return !handleNewServerResource(resource, monitor);
+				} else {
+					boolean b = handleChangedServerResource(resource, monitor);
+					if (!b) {
+						handleRemovedFile(resource);
+					}
+					return true;
+				}
+			}
+		}
+
+		monitor.done();
+		Trace.trace(Trace.RESOURCES, "Ignored resource change: " + resource2);
+		return true;*/
+	}
+	
+	protected IServer loadServer(IFile file, IProgressMonitor monitor) throws CoreException {
+		Server server = new Server(file);
+		server.loadFromFile(monitor);
+		return server;
+	}
+	
+	protected IServerConfiguration loadServerConfiguration(IFile file, IProgressMonitor monitor) throws CoreException {
+		ServerConfiguration config = new ServerConfiguration(file);
+		config.loadFromFile(monitor);
+		return config;
+	}
+	
+	/**
+	 * Tries to load a new server resource from the given resource.
+	 * Returns true if the load and register were successful.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 * @return boolean
+	 */
+	protected boolean handleNewFile(IFile file, IProgressMonitor monitor) {
+		Trace.trace(Trace.RESOURCES, "handleNewFile: " + file);
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		monitor.beginTask("", 2000);
+		
+		// try loading a server
+		if (file.getFileExtension().equals(IServer.FILE_EXTENSION)) {
+			try {
+				IServer server = loadServer(file, ProgressUtil.getSubMonitorFor(monitor, 1000));
+				if (server != null) {
+					registerServer(server);
+					monitor.done();
+					return true;
+				}
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error loading server", e);
+			}
+		} else if (file.getFileExtension().equals(IServerConfiguration.FILE_EXTENSION)) {
+	
+			// try loading a server configuration
+			try {
+				IServerConfiguration config = loadServerConfiguration(file, ProgressUtil.getSubMonitorFor(monitor, 1000));
+				if (config != null) {
+					registerServerConfiguration(config);
+					monitor.done();
+					return true;
+				}
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error loading configuration", e);
+			}
+		}
+	
+		monitor.done();
+		return false;
+	}
+
+	/**
+	 * Tries to handle a resource change. Returns true if the reload
+	 * was successful.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 * @return boolean
+	 */
+	protected boolean handleChangedFile(IFile file, IProgressMonitor monitor) {
+		Trace.trace(Trace.RESOURCES, "handleChangedFile: " + file);
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		monitor.beginTask("", 1000);
+		boolean found = false;
+	
+		IServer server = getServer(file);
+		if (server != null) {
+			found = true;
+			try {
+				Trace.trace(Trace.RESOURCES, "Reloading server: " + server);
+				((Server) server).loadFromFile(monitor);
+				fireServerResourceChanged(server);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error reloading server " + server.getName() + " from " + file + ": " + e.getMessage());
+				deregisterServer(server);
+			}
+		}
+		
+		IServerConfiguration configuration = getServerConfiguration(file);
+		if (configuration != null) {
+			found = true;
+			try {
+				Trace.trace(Trace.RESOURCES, "Reloading configuration: " + configuration);
+				((ServerConfiguration) configuration).loadFromFile(monitor);
+				fireServerResourceChanged(configuration);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error reloading configuration " + configuration.getName() + " from " + file + ": " + e.getMessage());
+				deregisterServerConfiguration(configuration);
+			}
+
+			// find any running servers that contain this configuration
+			// notify the servers with this configuration
+			Iterator iterator = getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server2 = (IServer) iterator.next();
+				if (server2.getServerConfiguration().equals(configuration))
+					server2.updateConfiguration();
+			}
+			fireServerResourceChanged(configuration);
+		}
+
+		Trace.trace(Trace.RESOURCES, "No server resource found at: " + file);
+	
+		monitor.done();
+		return found;
+	}
+
+	/**
+	 * Tries to remove a current resource. Returns true if the
+	 * deregistering was successful.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 * @return boolean
+	 */
+	protected boolean handleRemovedFile(IFile file) {
+		Trace.trace(Trace.RESOURCES, "handleRemovedServerResource: " + file);
+	
+		IServer server = getServer(file);
+		if (server != null) {
+			deregisterServer(server);
+			return true;
+		}
+		IServerConfiguration config = getServerConfiguration(file);
+		if (config != null) {
+			deregisterServerConfiguration(config);
+			return true;
+		}
+	
+		Trace.trace(Trace.RESOURCES, "No server resource found at: " + file);
+		return false;
+	}
+
+	/**
+	 * A project has changed. If this is an add or remove, check
+	 * to see if it is part of a current server configuration.
+	 *
+	 * @param delta org.eclipse.core.resources.IResourceDelta
+	 */
+	protected void publishHandleProjectChange(IResourceDelta delta) {
+		Trace.trace(Trace.FINEST, "> publishHandleProjectChange " + delta.getResource());
+		IProject project = (IProject) delta.getResource();
+		
+		if (project == null)
+			return;
+		
+		if (isDeltaOnlyMarkers(delta))
+			return;
+
+		final IProjectModule moduleProject = ServerUtil.getModuleProject(project);
+		if (moduleProject == null)
+			return;
+		
+		Trace.trace(Trace.FINEST, "- publishHandleProjectChange");
+
+		Iterator iterator = getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (server.isDelegateLoaded())
+				((Server) server).handleModuleProjectChange(delta, new IProjectModule[] { moduleProject });
+		}
+		Trace.trace(Trace.FINEST, "< publishHandleProjectChange");
+	}
+	
+	protected boolean isDeltaOnlyMarkers(IResourceDelta delta) {
+		class Temp {
+			boolean b = true;
+		}
+		final Temp t = new Temp();
+		try {
+			delta.accept(new IResourceDeltaVisitor() {
+				public boolean visit(IResourceDelta delta2) throws CoreException {
+					if (!t.b)
+						return false;
+					int flags = delta2.getFlags();
+					if (flags != 0 && flags != IResourceDelta.MARKERS) {
+						t.b = false;
+						return false;
+					}
+					return true;
+				}
+			});
+		} catch (Exception e) { }
+		return t.b;
+	}
+	
+	/**
+	 * Registers a new runtime.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void registerRuntime(IRuntime runtime) {
+		if (runtime == null)
+			return;
+	
+		Trace.trace(Trace.RESOURCES, "Registering runtime: " + runtime.getName());
+	
+		runtimes.add(runtime);
+		fireServerResourceAdded(runtime);
+	}
+	
+	/**
+	 * Registers a new server.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void registerServer(IServer server) {
+		if (server == null)
+			return;
+	
+		Trace.trace(Trace.RESOURCES, "Registering server: " + server.getName());
+	
+		servers.add(server);
+		fireServerResourceAdded(server);
+	}
+
+	/**
+	 * Registers a new server configuration resource.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void registerServerConfiguration(IServerConfiguration config) {
+		if (config == null)
+			return;
+	
+		Trace.trace(Trace.RESOURCES, "Registering server configuration: " + config.getName());
+	
+		configurations.add(config);
+		resolveServers();
+		fireServerResourceAdded(config);
+	}
+
+	/**
+	 * Removes an existing server resource listener.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IServerResourceListener
+	 */
+	public void removeResourceListener(IServerResourceListener listener) {
+		Trace.trace(Trace.LISTENERS, "Removing server resource listener " + listener + " from " + this);
+	
+		if (listeners != null)
+			listeners.remove(listener);
+	}
+
+	/**
+	 *
+	 */
+	protected void addModuleFactoryListener(IModuleFactoryDelegate delegate) {
+		if (delegate == null)
+			return;
+	
+		Trace.trace(Trace.LISTENERS, "Adding module factory listener to: " + delegate);
+		delegate.addModuleFactoryListener(moduleFactoryListener);
+		
+		List modules = delegate.getModules();
+		if (modules != null) {
+			Iterator iterator = modules.iterator();
+			while (iterator.hasNext()) {
+				IModule module = (IModule) iterator.next();
+				Trace.trace(Trace.LISTENERS, "Adding module listener to: " + module);
+				module.addModuleListener(moduleListener);
+			}
+		}
+	}
+	
+	/**
+	 * Adds a new module events listener.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IModuleEventsListener
+	 */
+	public void addModuleEventsListener(IModuleEventsListener listener) {
+		Trace.trace(Trace.LISTENERS, "Adding moduleEvents listener " + listener + " to " + this);
+	
+		if (moduleEventListeners == null)
+			moduleEventListeners = new ArrayList();
+		moduleEventListeners.add(listener);
+	}
+	
+	/**
+	 * Removes an existing module events listener.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IModuleEventsListener
+	 */
+	public void removeModuleEventsListener(IModuleEventsListener listener) {
+		Trace.trace(Trace.LISTENERS, "Removing moduleEvents listener " + listener + " to " + this);
+	
+		if (moduleEventListeners != null)
+			moduleEventListeners.remove(listener);
+	}
+	
+	/**
+	 * Module events have momentarily stopped firing and should be
+	 * handled appropriately.
+	 */
+	public void syncModuleEvents() {
+		if (moduleEvents.isEmpty() && moduleFactoryEvents.isEmpty())
+			return;
+
+		Trace.trace(Trace.LISTENERS, "->- Firing moduleEvents " + moduleEvents.size() + " " + moduleFactoryEvents.size());
+		Iterator iterator = moduleEvents.iterator();
+		while (iterator.hasNext()) {
+			IModuleEvent event = (IModuleEvent) iterator.next();
+			Trace.trace(Trace.LISTENERS, "  1> " + event);
+		}
+		iterator = moduleFactoryEvents.iterator();
+		while (iterator.hasNext()) {
+			IModuleFactoryEvent event = (IModuleFactoryEvent) iterator.next();
+			Trace.trace(Trace.LISTENERS, "  2> " + event);
+		}
+
+		IModuleEvent[] events = new IModuleEvent[moduleEvents.size()];
+		moduleEvents.toArray(events);
+		
+		IModuleFactoryEvent[] factoryEvents = new IModuleFactoryEvent[moduleFactoryEvents.size()];
+		moduleFactoryEvents.toArray(factoryEvents);
+		
+		if (moduleEventListeners != null) {
+			iterator = moduleEventListeners.iterator();
+			while (iterator.hasNext()) {
+				IModuleEventsListener listener = (IModuleEventsListener) iterator.next();
+				try {
+					Trace.trace(Trace.LISTENERS, "  Firing moduleEvents to " + listener);
+					listener.moduleEvents(factoryEvents, events);
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "  Error firing moduleEvents to " + listener);
+				}
+			}
+		}
+		
+		// fire module server events
+		fireModuleServerEvent(factoryEvents, events);
+		
+		// clear cache
+		moduleEvents = new ArrayList(5);
+		moduleFactoryEvents = new ArrayList(5);
+		
+		Trace.trace(Trace.LISTENERS, "-<- Firing moduleEvents " + moduleEvents.size() + " " + moduleFactoryEvents.size());
+	}
+
+	protected void fireModuleServerEvent(IModuleFactoryEvent[] factoryEvents, IModuleEvent[] events) {
+		if (moduleServerEventHandlers == null)
+			return;
+		
+		List list = new ArrayList();
+
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			
+			if (server.isDelegateLoaded()) {
+				// make sure it is reloaded
+				try {
+					if (server.getFile() != null)
+						server.getFile().refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor());
+				} catch (Exception e) { }
+	
+				ITask[] tasks = server.getRepairCommands(factoryEvents, events);
+				if (tasks != null && tasks.length > 0) {
+					ModuleServerEvent mse = new ModuleServerEvent();
+					mse.server = server;
+					mse.tasks = tasks;
+					mse.factoryEvents = factoryEvents; 
+					mse.events = events;
+					list.add(mse);
+				}
+			}
+		}
+		
+		if (list.isEmpty())
+			return;
+		
+		ModuleServerEvent[] msEvents = new ModuleServerEvent[list.size()];
+		list.toArray(msEvents);
+	
+		iterator = moduleServerEventHandlers.iterator();
+		while (iterator.hasNext()) {
+			IServerLifecycleEventHandler handler = (IServerLifecycleEventHandler) iterator.next();
+			try {
+				boolean[] result = null;
+				Trace.trace(Trace.LISTENERS, "  Firing moduleServerEvents to " + handler);
+				result = handler.handleModuleServerEvents(msEvents);
+				if (result != null && result.length == msEvents.length) {
+					List list2 = new ArrayList();
+					int size = result.length;
+					for (int i = 0; i < size; i++) {
+						if (!result[i])
+							list2.add(msEvents[i]);
+					}
+					msEvents = new ModuleServerEvent[list2.size()];
+					list2.toArray(msEvents);
+				}
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing moduleServerEvents to " + handler);
+			}
+		}
+	}
+	
+	public void addServerLifecycleEventHandler(int index, IServerLifecycleEventHandler handler) {
+		if (moduleServerEventHandlers == null) {
+			moduleServerEventHandlers = new ArrayList();
+			moduleServerEventHandlerIndexes = new ArrayList();
+		}
+		
+		int ind = 0;
+		int size = moduleServerEventHandlers.size();
+		while (ind < size && ((Integer) moduleServerEventHandlerIndexes.get(ind)).intValue() < index) {
+			ind++;
+		}
+		
+		moduleServerEventHandlers.add(ind, handler);
+		moduleServerEventHandlerIndexes.add(ind, new Integer(index));
+	}
+
+	public void removeServerLifecycleEventHandler(IServerLifecycleEventHandler handler) {
+		if (moduleServerEventHandlers == null)
+			return;
+		
+		int ind = moduleServerEventHandlers.indexOf(handler);
+		if (ind >= 0) {
+			moduleServerEventHandlers.remove(ind);
+			moduleServerEventHandlerIndexes.remove(ind);
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Runtime.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Runtime.java
new file mode 100644
index 0000000..41f08ce
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Runtime.java
@@ -0,0 +1,166 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IConfigurationElement;
+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.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IRuntimeDelegate;
+/**
+ * 
+ */
+public class Runtime extends Base implements IRuntime {
+	protected static final String PROP_RUNTIME_TYPE_ID = "runtime-type-id";
+	protected static final String PROP_LOCATION = "location";
+	protected static final String PROP_TEST_ENVIRONMENT = "test-environment";
+
+	protected IRuntimeType runtimeType;
+	protected IRuntimeDelegate delegate;
+
+	public Runtime(IFile file) {
+		super(file);
+	}
+
+	public Runtime(IFile file, String id, IRuntimeType runtimeType) {
+		super(file, id);
+		this.runtimeType = runtimeType;
+		map.put(PROP_NAME, runtimeType.getName());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.model.IRuntime#getRuntimeType()
+	 */
+	public IRuntimeType getRuntimeType() {
+		return runtimeType;
+	}
+
+	/**
+	 * Return the validation status of the runtime.
+	 * 
+	 * @return
+	 */
+	public IStatus validate() {
+		try {
+			return getDelegate().validate();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate validate() " + toString(), e);
+			return null;
+		}
+	}
+
+	public IRuntimeDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				RuntimeType runtimeType2 = (RuntimeType) runtimeType;
+				delegate = (IRuntimeDelegate) runtimeType2.getElement().createExecutableExtension("class");
+				delegate.initialize(this);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString(), e);
+			}
+		}
+		return delegate;
+	}
+	
+	/**
+	 * Returns true if the delegate has been loaded.
+	 * 
+	 * @return
+	 */
+	public boolean isDelegateLoaded() {
+		return delegate != null;
+	}
+	
+	public void dispose() {
+		if (delegate != null)
+			delegate.dispose();
+	}
+	
+	public IRuntimeWorkingCopy getWorkingCopy() {
+		IRuntimeWorkingCopy wc = new RuntimeWorkingCopy(this); 
+		addWorkingCopy(wc);
+		return wc;
+	}
+	
+	public boolean isWorkingCopy() {
+		return false;
+	}
+	
+	public boolean isDelegatePluginActivated() {
+		IConfigurationElement element = ((RuntimeType) runtimeType).getElement();
+		String pluginId = element.getDeclaringExtension().getNamespace();
+		return Platform.getBundle(pluginId).getState() == Bundle.ACTIVE;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.model.IRuntime#getLocation()
+	 */
+	public IPath getLocation() {
+		String temp = getAttribute(PROP_LOCATION, (String)null);
+		if (temp == null)
+			return null;
+		else
+			return new Path(temp);
+	}
+	
+	protected void deleteFromMetadata() {
+		ResourceManager rm = (ResourceManager) ServerCore.getResourceManager();
+		rm.removeRuntime(this);
+	}
+
+	protected void saveToMetadata(IProgressMonitor monitor) {
+		ResourceManager rm = (ResourceManager) ServerCore.getResourceManager();
+		rm.addRuntime(this);
+	}
+
+	protected String getXMLRoot() {
+		return "runtime";
+	}
+	
+	public boolean isTestEnvironment() {
+		return getAttribute(PROP_TEST_ENVIRONMENT, false);
+	}
+
+	protected void setInternal(RuntimeWorkingCopy wc) {
+		map = wc.map;
+		runtimeType = wc.runtimeType;
+		file = wc.file;
+		delegate = wc.delegate;
+	}
+
+	protected void loadState(IMemento memento) {
+		String runtimeTypeId = memento.getString(PROP_RUNTIME_TYPE_ID);
+		runtimeType = ServerCore.getRuntimeType(runtimeTypeId);
+	}
+
+	protected void saveState(IMemento memento) {
+		if (runtimeType != null)
+			memento.putString(PROP_RUNTIME_TYPE_ID, runtimeType.getId());
+	}
+
+	public boolean equals(Object obj) {
+		if (!(obj instanceof Runtime))
+			return false;
+		
+		Runtime runtime = (Runtime) obj;
+		return runtime.getId().equals(getId());
+	}
+	
+	public String toString() {
+		return "Runtime[" + getId() + ", " + getName() + ", " + getLocation() + ", " + getRuntimeType() + "]";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeLocator.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeLocator.java
new file mode 100644
index 0000000..31fba8d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeLocator.java
@@ -0,0 +1,86 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IRuntimeLocator;
+import org.eclipse.wst.server.core.model.IRuntimeLocatorDelegate;
+import org.eclipse.wst.server.core.model.IRuntimeLocatorListener;
+/**
+ * 
+ */
+public class RuntimeLocator implements IRuntimeLocator {
+	private IConfigurationElement element;
+	private IRuntimeLocatorDelegate delegate;
+
+	public RuntimeLocator(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+	
+	protected IConfigurationElement getElement() {
+		return element;
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getName() {
+		return element.getAttribute("name");
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getDescription() {
+		return element.getAttribute("description");
+	}
+	
+	/*
+	 * @see IPublishManager#getDelegate()
+	 */
+	protected IRuntimeLocatorDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IRuntimeLocatorDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString() + ": " + e.getMessage());
+			}
+		}
+		return delegate;
+	}
+
+	/**
+	 * 
+	 */
+	public void searchForRuntimes(IRuntimeLocatorListener found, IProgressMonitor monitor) {
+		try {
+			getDelegate().searchForRuntimes(found, monitor);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+	}
+
+	public String toString() {
+		return "RuntimeLocator[" + getId() + ", " + getName() + "]";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeTargetHandler.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeTargetHandler.java
new file mode 100644
index 0000000..8809d2d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeTargetHandler.java
@@ -0,0 +1,146 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IRuntimeTargetHandlerDelegate;
+/**
+ * 
+ */
+public class RuntimeTargetHandler implements IRuntimeTargetHandler {
+	private IConfigurationElement element;
+	private IRuntimeTargetHandlerDelegate delegate;
+
+	public RuntimeTargetHandler(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+	
+	protected IConfigurationElement getElement() {
+		return element;
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+
+	/**
+	 * Returns the order.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			String o = element.getAttribute("order");
+			return Integer.parseInt(o);
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+
+	public String[] getRuntimeTypeIds() {
+		try {
+			List list = new ArrayList();
+			StringTokenizer st = new StringTokenizer(element.getAttribute("runtimeTypeIds"), ",");
+			while (st.hasMoreTokens()) {
+				String str = st.nextToken();
+				if (str != null && str.length() > 0)
+					list.add(str.trim());
+			}
+			String[] s = new String[list.size()];
+			list.toArray(s);
+			return s;
+		} catch (Exception e) {
+			Trace.trace("Could not parse runtime type ids: " + element);
+			return null;
+		}
+	}
+
+	/**
+	 * Returns true if the given server resource type (given by the
+	 * id) can be opened with this editor. This result is based on
+	 * the result of the getServerResources() method.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsRuntimeType(IRuntimeType runtimeType) {
+		if (runtimeType == null)
+			return false;
+		String id = runtimeType.getId();
+		if (id == null || id.length() == 0)
+			return false;
+
+		String[] s = getRuntimeTypeIds();
+		if (s == null)
+			return false;
+		
+		int size = s.length;
+		for (int i = 0; i < size; i++) {
+			if (s[i].endsWith("*")) {
+				if (id.length() >= s[i].length() && id.startsWith(s[i].substring(0, s[i].length() - 1)))
+					return true;
+			} else if (id.equals(s[i]))
+				return true;
+		}
+		return false;
+	}
+
+	/*
+	 * @see IPublishManager#getDelegate()
+	 */
+	public IRuntimeTargetHandlerDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IRuntimeTargetHandlerDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString() + ": " + e.getMessage());
+			}
+		}
+		return delegate;
+	}
+
+	/**
+	 * 
+	 */
+	public void setRuntimeTarget(IProject project, IRuntime runtime, IProgressMonitor monitor) {
+		try {
+			getDelegate().setRuntimeTarget(project, runtime, monitor);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	public void removeRuntimeTarget(IProject project, IRuntime runtime, IProgressMonitor monitor) {
+		try {
+			getDelegate().removeRuntimeTarget(project, runtime, monitor);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+	}
+
+	public String toString() {
+		return "RuntimeTargetListener[" + getId() + "]";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeType.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeType.java
new file mode 100644
index 0000000..d9a2b80
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeType.java
@@ -0,0 +1,115 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.wst.server.core.*;
+/**
+ * 
+ */
+public class RuntimeType implements IRuntimeType {
+	private IConfigurationElement element;
+	private List moduleTypes;
+
+	public RuntimeType(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+	
+	protected IConfigurationElement getElement() {
+		return element;
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getName() {
+		return element.getAttribute("name");
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public String getDescription() {
+		return element.getAttribute("description");
+	}
+	
+	/**
+	 * Returns the order.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			String o = element.getAttribute("order");
+			return Integer.parseInt(o);
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+	
+	public String getVendor() {
+		String vendor = element.getAttribute("vendor");
+		if (vendor == null)
+			return ServerPlugin.getResource("%defaultVendor");
+		else
+			return vendor;
+	}
+	
+	public String getVersion() {
+		String version = element.getAttribute("version");
+		if (version == null)
+			return ServerPlugin.getResource("%defaultVersion");
+		else
+			return version;
+	}
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public List getModuleTypes() {
+		if (moduleTypes == null)
+			moduleTypes = ServerPlugin.getModuleTypes(element.getChildren("moduleType"));
+
+		return moduleTypes;
+	}
+	
+	public boolean canCreate() {
+		String a = element.getAttribute("class");
+		String b = element.getAttribute("workingCopyClass");
+		return a != null && b != null && a.length() > 0 && b.length() > 0;
+	}
+
+	public IRuntimeWorkingCopy createRuntime(String id) {
+		if (id == null || id.length() == 0)
+			id = ServerPlugin.generateId();
+		RuntimeWorkingCopy rwc = new RuntimeWorkingCopy(null, id, this);
+		rwc.setDefaults();
+		return rwc;
+	}
+
+	public String toString() {
+		return "RuntimeType[" + getId() + ", " + getName() + "]";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeWorkingCopy.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeWorkingCopy.java
new file mode 100644
index 0000000..b1d59f9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/RuntimeWorkingCopy.java
@@ -0,0 +1,190 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.beans.PropertyChangeListener;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+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.model.IRuntimeDelegate;
+import org.eclipse.wst.server.core.model.IRuntimeWorkingCopyDelegate;
+/**
+ * 
+ */
+public class RuntimeWorkingCopy extends Runtime implements IRuntimeWorkingCopy {
+	protected Runtime runtime;
+	protected WorkingCopyHelper wch;
+	
+	protected IRuntimeWorkingCopyDelegate workingCopyDelegate;
+	
+	// from existing runtime
+	public RuntimeWorkingCopy(Runtime runtime) {
+		super(runtime.getFile());
+		this.runtime = runtime;
+		
+		runtimeType = runtime.getRuntimeType();
+		
+		map = new HashMap(runtime.map);
+		wch = new WorkingCopyHelper(this);
+	}
+	
+	// new runtime
+	public RuntimeWorkingCopy(IFile file, String id, IRuntimeType runtimeType) {
+		super(file, id, runtimeType);
+		//runtime = this;
+		wch = new WorkingCopyHelper(this);
+		// throw CoreException if the id already exists
+	}
+	
+	public boolean isWorkingCopy() {
+		return true;
+	}
+	
+	public IRuntimeWorkingCopy getWorkingCopy() {
+		return this;
+	}
+	
+	public void setAttribute(String attributeName, int value) {
+		wch.setAttribute(attributeName, value);
+	}
+	
+	public void setAttribute(String attributeName, boolean value) {
+		wch.setAttribute(attributeName, value);
+	}
+	
+	public void setAttribute(String attributeName, String value) {
+		wch.setAttribute(attributeName, value);
+	}
+	
+	public void setAttribute(String attributeName, List value) {
+		wch.setAttribute(attributeName, value);
+	}
+	
+	public void setAttribute(String attributeName, Map value) {
+		wch.setAttribute(attributeName, value);
+	}
+	
+	public void setName(String name) {
+		wch.setName(name);
+	}
+	
+	public void setTestEnvironment(boolean b) {
+		setAttribute(PROP_TEST_ENVIRONMENT, b);
+	}
+
+	public boolean isDirty() {
+		return wch.isDirty();
+	}
+
+	public void release() {
+		wch.release();
+		dispose();
+		if (runtime != null)
+			runtime.release(this);
+	}
+	
+	public IRuntime getOriginal() {
+		return runtime;
+	}
+
+	public void setLocked(boolean b) {
+		wch.setLocked(b);
+	}
+
+	public void setPrivate(boolean b) {
+		wch.setPrivate(b);
+	}
+	
+	public void setLocation(IPath path) {
+		if (path == null)
+			setAttribute(PROP_LOCATION, (String)null);
+		else
+			setAttribute(PROP_LOCATION, path.toString());
+	}
+
+	public IRuntime save(IProgressMonitor monitor) {
+		if (wch.isReleased())
+			return null;
+		if (runtime == null)
+			runtime = new Runtime(file);
+		getWorkingCopyDelegate().handleSave(IRuntimeWorkingCopyDelegate.PRE_SAVE, monitor);
+		runtime.setInternal(this);
+		runtime.saveToMetadata(monitor);
+		wch.setDirty(false);
+		release();
+		getWorkingCopyDelegate().handleSave(IRuntimeWorkingCopyDelegate.POST_SAVE, monitor);
+		return runtime;
+	}
+	
+	public IRuntimeDelegate getDelegate() {
+		return getWorkingCopyDelegate();
+	}
+	
+	public IRuntimeWorkingCopyDelegate getWorkingCopyDelegate() {
+		if (workingCopyDelegate == null) {
+			try {
+				RuntimeType runtimeType2 = (RuntimeType) runtimeType;
+				workingCopyDelegate = (IRuntimeWorkingCopyDelegate) runtimeType2.getElement().createExecutableExtension("workingCopyClass");
+				workingCopyDelegate.initialize((IRuntime) this);
+				workingCopyDelegate.initialize(this);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString(), e);
+			}
+		}
+		return workingCopyDelegate;
+	}
+	
+	public void dispose() {
+		super.dispose();
+		if (workingCopyDelegate != null)
+			workingCopyDelegate.dispose();
+	}
+
+	/**
+	 * Add a property change listener to this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void addPropertyChangeListener(PropertyChangeListener listener) {
+		wch.addPropertyChangeListener(listener);
+	}
+	
+	/**
+	 * Remove a property change listener from this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void removePropertyChangeListener(PropertyChangeListener listener) {
+		wch.removePropertyChangeListener(listener);
+	}
+	
+	/**
+	 * Fire a property change event.
+	 */
+	public void firePropertyChangeEvent(String propertyName, Object oldValue, Object newValue) {
+		wch.firePropertyChangeEvent(propertyName, oldValue, newValue);
+	}
+	
+	public void setDefaults() {
+		try {
+			getWorkingCopyDelegate().setDefaults();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate setDefaults() " + toString(), e);
+		}
+	}
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..c159365
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Server.java
@@ -0,0 +1,1783 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.*;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.runtime.*;
+import org.eclipse.debug.core.*;
+import org.osgi.framework.Bundle;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.*;
+import org.eclipse.wst.server.core.resources.*;
+import org.eclipse.wst.server.core.util.ProgressUtil;
+import org.eclipse.wst.server.core.util.ServerAdapter;
+/**
+ * 
+ */
+public class Server extends Base implements IServer, IServerState {
+	protected static final List EMPTY_LIST = new ArrayList(0);
+	
+	protected static final String PROP_HOSTNAME = "hostname";
+	protected static final String SERVER_ID = "server-id";
+	protected static final String RUNTIME_ID = "runtime-id";
+	protected static final String CONFIGURATION_ID = "configuration-id";
+
+	protected IServerType serverType;
+	protected IServerDelegate delegate;
+
+	protected IRuntime runtime;
+	protected IServerConfiguration configuration;
+	protected byte serverState = SERVER_UNKNOWN;
+
+	// the configuration sync state
+	protected byte configurationSyncState;
+
+/*	private static final String[] stateStrings = new String[] {
+		"unknown", "starting", "started", "started_debug",
+		"stopping", "stopped", "started_unsupported", "started_profile"
+	};*/
+	
+	// the current restart value
+	protected boolean restartNeeded;
+	
+	//protected String lastMode = ILaunchManager.DEBUG_MODE;
+
+	// publish listeners
+	protected transient List publishListeners;
+	
+	// server listeners
+	private transient List serverListeners;
+	
+	class ServerTaskInfo implements IOrdered {
+		IServerTask task;
+		List[] parents;
+		IModule[] modules;
+		
+		public int getOrder() {
+			return task.getOrder();
+		}
+		
+		public String toString() {
+			return task.getName();
+		}
+	}
+
+	class ModuleTaskInfo implements IOrdered {
+		IModuleTask task;
+		List parents;
+		IModule module;
+	
+		public int getOrder() {
+			return task.getOrder();
+		}
+		
+		public String toString() {
+			return task.getName();
+		}
+	}
+
+	// working copy, loaded resource
+	public Server(IFile file) {
+		super(file);
+		map.put(PROP_HOSTNAME, "localhost");
+	}
+
+	// creation (working copy)
+	public Server(String id, IFile file, IRuntime runtime, IServerType serverType) {
+		super(file, id);
+		this.runtime = runtime;
+		this.serverType = serverType;
+		map.put("server-type-id", serverType.getId());
+		map.put(PROP_HOSTNAME, "localhost");
+		if (runtime != null && runtime.getRuntimeType() != null) {
+			String name = runtime.getRuntimeType().getName();
+			map.put(PROP_NAME, name);
+		}
+		serverState = ((ServerType)serverType).getInitialState();
+	}
+	
+	public IServerType getServerType() {
+		return serverType;
+	}
+	
+	public IServerWorkingCopy getWorkingCopy() {
+		IServerWorkingCopy wc = new ServerWorkingCopy(this); 
+		addWorkingCopy(wc);
+		return wc;
+	}
+
+	public boolean isWorkingCopy() {
+		return false;
+	}
+	
+	protected void deleteFromMetadata() {
+		ResourceManager rm = (ResourceManager) ServerCore.getResourceManager();
+		rm.removeServer(this);
+	}
+	
+	protected void saveToMetadata(IProgressMonitor monitor) {
+		ResourceManager rm = (ResourceManager) ServerCore.getResourceManager();
+		rm.addServer(this);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServer2#getRuntime()
+	 */
+	public IRuntime getRuntime() {
+		return runtime;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServer2#getServerConfiguration()
+	 */
+	public IServerConfiguration getServerConfiguration() {
+		return configuration;
+	}
+
+	public IServerDelegate getDelegate() {
+		if (delegate == null && serverType != null) {
+			try {
+				IConfigurationElement element = ((ServerType) serverType).getElement();
+				delegate = (IServerDelegate) element.createExecutableExtension("class");
+				delegate.initialize(this);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString(), e);
+			}
+		}
+		return delegate;
+	}
+	
+	/**
+	 * Returns true if the delegate has been loaded.
+	 * 
+	 * @return
+	 */
+	public boolean isDelegateLoaded() {
+		return delegate != null;
+	}
+	
+	public void dispose() {
+		if (delegate != null)
+			delegate.dispose();
+	}
+	
+	public boolean isDelegatePluginActivated() {
+		IConfigurationElement element = ((ServerType) serverType).getElement();
+		String pluginId = element.getDeclaringExtension().getNamespace();
+		return Platform.getBundle(pluginId).getState() == Bundle.ACTIVE;
+	}
+	
+	/**
+	 * Returns true if this is a configuration that is
+	 * applicable to (can be used with) this server.
+	 *
+	 * @param configuration org.eclipse.wst.server.core.model.IServerConfiguration
+	 * @return boolean
+	 */
+	public boolean isSupportedConfiguration(IServerConfiguration configuration2) {
+		if (!getServerType().hasServerConfiguration() || configuration2 == null)
+			return false;
+		else
+			return getServerType().getServerConfigurationType().equals(configuration2.getServerConfigurationType());
+	}
+
+	public String getHostname() {
+		return getAttribute(PROP_HOSTNAME, "localhost");
+	}
+
+	/**
+	 * Returns the current state of the server. (see SERVER_XXX constants)
+	 *
+	 * @return byte
+	 */
+	public byte getServerState() {
+		return serverState;
+	}
+
+	public void setServerState(byte state) {
+		if (state == serverState)
+			return;
+
+		this.serverState = state;
+		fireServerStateChangeEvent();
+	}
+	
+	/**
+	 * Add a listener to this server.
+	 *
+	 * @param listener org.eclipse.wst.server.model.IServerListener
+	 */
+	public void addServerListener(IServerListener listener) {
+		Trace.trace(Trace.LISTENERS, "Adding server listener " + listener + " to " + this);
+	
+		if (serverListeners == null)
+			serverListeners = new ArrayList();
+		serverListeners.add(listener);
+	}
+	
+	/**
+	 * Remove a listener from this server.
+	 *
+	 * @param listener org.eclipse.wst.server.model.IServerListener
+	 */
+	public void removeServerListener(IServerListener listener) {
+		Trace.trace(Trace.LISTENERS, "Removing server listener " + listener + " from " + this);
+	
+		if (serverListeners != null)
+			serverListeners.remove(listener);
+	}
+	
+	/**
+	 * Fire a server listener configuration sync state change event.
+	 */
+	protected void fireConfigurationSyncStateChangeEvent() {
+		Trace.trace(Trace.LISTENERS, "->- Firing server configuration change event: " + getName() + " ->-");
+	
+		if (serverListeners == null || serverListeners.isEmpty())
+			return;
+	
+		int size = serverListeners.size();
+		IServerListener[] sil = new IServerListener[size];
+		serverListeners.toArray(sil);
+	
+		for (int i = 0; i < size; i++) {
+			try {
+				Trace.trace(Trace.LISTENERS, "  Firing server configuration change event to: " + sil[i]);
+				sil[i].configurationSyncStateChange(this);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing server configuration change event", e);
+			}
+		}
+		Trace.trace(Trace.LISTENERS, "-<- Done firing server configuration change event -<-");
+	}
+	
+	/**
+	 * Fire a server listener restart state change event.
+	 */
+	protected void fireRestartStateChangeEvent() {
+		Trace.trace(Trace.LISTENERS, "->- Firing server restart change event: " + getName() + " ->-");
+	
+		if (serverListeners == null || serverListeners.isEmpty())
+			return;
+	
+		int size = serverListeners.size();
+		IServerListener[] sil = new IServerListener[size];
+		serverListeners.toArray(sil);
+	
+		for (int i = 0; i < size; i++) {
+			try {
+				Trace.trace(Trace.LISTENERS, "  Firing server restart change event to: " + sil[i]);
+				sil[i].restartStateChange(this);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing server restart change event", e);
+			}
+		}
+		Trace.trace(Trace.LISTENERS, "-<- Done firing server restart change event -<-");
+	}
+	
+	/**
+	 * Fire a server listener state change event.
+	 */
+	protected void fireServerStateChangeEvent() {
+		Trace.trace(Trace.LISTENERS, "->- Firing server state change event: " + getName() + ", " + getServerState() + " ->-");
+	
+		if (serverListeners == null || serverListeners.isEmpty())
+			return;
+	
+		int size = serverListeners.size();
+		IServerListener[] sil = new IServerListener[size];
+		serverListeners.toArray(sil);
+	
+		for (int i = 0; i < size; i++) {
+			try {
+				Trace.trace(Trace.LISTENERS, "  Firing server state change event to: " + sil[i]);
+				sil[i].serverStateChange(this);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing server state change event", e);
+			}
+		}
+		Trace.trace(Trace.LISTENERS, "-<- Done firing server state change event -<-");
+	}
+	
+	/**
+	 * Fire a server listener module change event.
+	 */
+	protected void fireServerModuleChangeEvent() {
+		Trace.trace(Trace.LISTENERS, "->- Firing server module change event: " + getName() + ", " + getServerState() + " ->-");
+		
+		if (serverListeners == null || serverListeners.isEmpty())
+			return;
+		
+		int size = serverListeners.size();
+		IServerListener[] sil = new IServerListener[size];
+		serverListeners.toArray(sil);
+		
+		for (int i = 0; i < size; i++) {
+			try {
+				Trace.trace(Trace.LISTENERS, "  Firing server module change event to: " + sil[i]);
+				sil[i].modulesChanged(this);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing server module change event", e);
+			}
+		}
+		Trace.trace(Trace.LISTENERS, "-<- Done firing server module change event -<-");
+	}
+	
+	/**
+	 * Fire a server listener module state change event.
+	 */
+	protected void fireServerModuleStateChangeEvent(IModule module) {
+		Trace.trace(Trace.LISTENERS, "->- Firing server module state change event: " + getName() + ", " + getServerState() + " ->-");
+		
+		if (serverListeners == null || serverListeners.isEmpty())
+			return;
+		
+		int size = serverListeners.size();
+		IServerListener[] sil = new IServerListener[size];
+		serverListeners.toArray(sil);
+		
+		for (int i = 0; i < size; i++) {
+			try {
+				Trace.trace(Trace.LISTENERS, "  Firing server module state change event to: " + sil[i]);
+				sil[i].moduleStateChange(this, module);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing server module state change event", e);
+			}
+		}
+		Trace.trace(Trace.LISTENERS, "-<- Done firing server module state change event -<-");
+	}
+
+	public void updateModuleState(IModule module) {
+		fireServerModuleStateChangeEvent(module);
+	}
+	
+	protected void handleModuleProjectChange(final IResourceDelta delta, final IProjectModule[] moduleProjects) {
+		//Trace.trace(Trace.FINEST, "> handleDeployableProjectChange() " + server + " " + delta + " " + moduleProjects);
+		final int size = moduleProjects.length;
+		final IModuleResourceDelta[] deployableDelta = new IModuleResourceDelta[size];
+		
+		if (configuration != null) {
+			IModuleVisitor visitor = new IModuleVisitor() {
+				public boolean visit(List parents, IModule module) {
+					if (!(module instanceof IProjectModule))
+						return true;
+					
+					IPublisher publisher = getPublisher(parents, module);
+					if (publisher == null)
+						return true;
+
+					for (int i = 0; i < size; i++) {
+						if (moduleProjects[i].equals(module)) {
+							if (deployableDelta[i] == null)
+								deployableDelta[i] = moduleProjects[i].getModuleResourceDelta(delta);
+							
+							if (deployableDelta[i] != null) {
+								// TODO updateDeployable(module, deployableDelta[i]);
+
+								PublishControl control = PublishInfo.getPublishInfo().getPublishControl(Server.this, parents, module);
+								if (control.isDirty())
+									return true;
+			
+								control.setDirty(true);
+								firePublishStateChange(parents, module);
+							}
+							return true;
+						}
+					}
+					return true;
+				}
+			};
+	
+			ServerUtil.visit(this, visitor);
+			//Trace.trace(Trace.FINEST, "< handleDeployableProjectChange()");
+		}
+	}
+	
+	/**
+	 * Returns the configuration's sync state.
+	 *
+	 * @return byte
+	 */
+	public byte getConfigurationSyncState() {
+		return configurationSyncState;
+	}
+	
+	/**
+	 * Sets the configuration sync state.
+	 *
+	 * @param state byte
+	 */
+	public void setConfigurationSyncState(byte state) {
+		if (state == configurationSyncState)
+			return;
+		configurationSyncState = state;
+		fireConfigurationSyncStateChangeEvent();
+	}
+	
+	/**
+	 * Adds a publish listener to this server.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IPublishListener
+	 */
+	public void addPublishListener(IPublishListener listener) {
+		Trace.trace(Trace.LISTENERS, "Adding publish listener " + listener + " to " + this);
+
+		if (publishListeners == null)
+			publishListeners = new ArrayList();
+		publishListeners.add(listener);
+	}
+	
+	/**
+	 * Removes a publish listener from this server.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IPublishListener
+	 */
+	public void removePublishListener(IPublishListener listener) {
+		Trace.trace(Trace.LISTENERS, "Removing publish listener " + listener + " from " + this);
+
+		if (publishListeners != null)
+			publishListeners.remove(listener);
+	}
+
+	/**
+	 * Fire a publish start event.
+	 *
+	 * @param 
+	 */
+	private void firePublishStarting(List[] parents, IModule[] targets) {
+		Trace.trace(Trace.FINEST, "->- Firing publish starting event: " + targets + " ->-");
+	
+		if (publishListeners == null || publishListeners.isEmpty())
+			return;
+
+		int size = publishListeners.size();
+		IPublishListener[] srl = new IPublishListener[size];
+		publishListeners.toArray(srl);
+
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.FINEST, "  Firing publish starting event to " + srl[i]);
+			try {
+				srl[i].publishStarting(this, parents, targets);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing publish starting event to " + srl[i], e);
+			}
+		}
+
+		Trace.trace(Trace.FINEST, "-<- Done firing publish starting event -<-");
+	}
+	
+	/**
+	 * Fire a publish start event.
+	 *
+	 * @param 
+	 */
+	private void firePublishStarted(IPublishStatus status) {
+		Trace.trace(Trace.FINEST, "->- Firing publish started event: " + status + " ->-");
+	
+		if (publishListeners == null || publishListeners.isEmpty())
+			return;
+
+		int size = publishListeners.size();
+		IPublishListener[] srl = new IPublishListener[size];
+		publishListeners.toArray(srl);
+
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.FINEST, "  Firing publish started event to " + srl[i]);
+			try {
+				srl[i].publishStarted(this, status);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing publish started event to " + srl[i], e);
+			}
+		}
+
+		Trace.trace(Trace.FINEST, "-<- Done firing publish started event -<-");
+	}
+	
+	/**
+	 * Fire a publish target event.
+	 *
+	 * @param 
+	 */
+	private void fireModulePublishStarting(List parents, IModule module) {
+		Trace.trace(Trace.FINEST, "->- Firing module starting event: " + module + " ->-");
+	
+		if (publishListeners == null || publishListeners.isEmpty())
+			return;
+
+		int size = publishListeners.size();
+		IPublishListener[] srl = new IPublishListener[size];
+		publishListeners.toArray(srl);
+
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.FINEST, "  Firing module starting event to " + srl[i]);
+			try {
+				srl[i].moduleStarting(this, parents, module);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing module starting event to " + srl[i], e);
+			}
+		}
+
+		Trace.trace(Trace.FINEST, "-<- Done firing module starting event -<-");
+	}
+	
+	/**
+	 * Fire a publish target event.
+	 *
+	 * @param 
+	 */
+	private void fireModulePublishFinished(List parents, IModule module, IPublishStatus status) {
+		Trace.trace(Trace.FINEST, "->- Firing module finished event: " + module + " " + status + " ->-");
+	
+		if (publishListeners == null || publishListeners.isEmpty())
+			return;
+
+		int size = publishListeners.size();
+		IPublishListener[] srl = new IPublishListener[size];
+		publishListeners.toArray(srl);
+
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.FINEST, "  Firing module finished event to " + srl[i]);
+			try {
+				srl[i].moduleFinished(this, parents, module, status);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing module finished event to " + srl[i], e);
+			}
+		}
+
+		Trace.trace(Trace.FINEST, "-<- Done firing module finished event -<-");
+	}
+	
+	/**
+	 * Fire a publish stop event.
+	 *
+	 * @param 
+	 */
+	private void firePublishFinished(IPublishStatus status) {
+		Trace.trace(Trace.FINEST, "->- Firing publishing finished event: " + status + " ->-");
+	
+		if (publishListeners == null || publishListeners.isEmpty())
+			return;
+
+		int size = publishListeners.size();
+		IPublishListener[] srl = new IPublishListener[size];
+		publishListeners.toArray(srl);
+
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.FINEST, "  Firing publishing finished event to " + srl[i]);
+			try {
+				srl[i].publishFinished(this, status);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing publishing finished event to " + srl[i], e);
+			}
+		}
+
+		Trace.trace(Trace.FINEST, "-<- Done firing publishing finished event -<-");
+	}
+
+	/**
+	 * Fire a publish state change event.
+	 *
+	 * @param 
+	 */
+	protected void firePublishStateChange(List parents, IModule module) {
+		Trace.trace(Trace.FINEST, "->- Firing publish state change event: " + module + " ->-");
+	
+		if (publishListeners == null || publishListeners.isEmpty())
+			return;
+
+		int size = publishListeners.size();
+		IPublishListener[] srl = new IPublishListener[size];
+		publishListeners.toArray(srl);
+
+		for (int i = 0; i < size; i++) {
+			Trace.trace(Trace.FINEST, "  Firing publish state change event to " + srl[i]);
+			try {
+				srl[i].moduleStateChange(this, parents, module);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing publish state change event to " + srl[i], e);
+			}
+		}
+
+		Trace.trace(Trace.FINEST, "-<- Done firing publish state change event -<-");
+	}
+
+	/**
+	 * Returns true if the server is in a state that it can
+	 * be published to.
+	 *
+	 * @return boolean
+	 */
+	public boolean canPublish() {
+		// can't publish if the server is starting or stopping
+		byte state = getServerState();
+		if (state == SERVER_STARTING ||
+			state == SERVER_STOPPING)
+			return false;
+	
+		// can't publish if there is no configuration
+		if (getServerType() == null || getServerType().hasServerConfiguration() && configuration == null)
+			return false;
+	
+		// return true if the configuration can be published
+		if (getConfigurationSyncState() != SYNC_STATE_IN_SYNC)
+			return true;
+
+		// return true if any modules can be published
+		class Temp {
+			boolean found = false;
+		}
+		final Temp temp = new Temp();
+	
+		IModuleVisitor visitor = new IModuleVisitor() {
+			public boolean visit(List parents, IModule module) {
+				if (getPublisher(parents, module) != null) {
+					temp.found = true;
+					return false;
+				} else
+					return true;
+			}
+		};
+		ServerUtil.visit(this, visitor);
+		
+		return temp.found;
+	}
+	
+	/**
+	 * Returns true if the server is in a state that it can
+	 * be published to.
+	 *
+	 * @return boolean
+	 */
+	public boolean shouldPublish() {
+		if (!canPublish())
+			return false;
+	
+		if (getConfigurationSyncState() != SYNC_STATE_IN_SYNC)
+			return true;
+	
+		if (!getUnpublishedModules().isEmpty())
+			return true;
+	
+		return false;
+	}
+	
+
+	/**
+	 * Returns a list of the projects that have not been published
+	 * since the last modification. (i.e. the projects that are
+	 * out of sync with the server.
+	 *
+	 * @return java.util.List
+	 */
+	public List getUnpublishedModules() {
+		final List modules = new ArrayList();
+		
+		if (configuration == null)
+			return modules;
+		
+		IModuleVisitor visitor = new IModuleVisitor() {
+			public boolean visit(List parents, IModule module) {
+				IPublisher publisher = getPublisher(parents, module);
+				if (publisher != null && !modules.contains(module)) {
+					PublishControl control = PublishInfo.getPublishInfo().getPublishControl(Server.this, parents, module);
+					if (control.isDirty)
+						modules.add(module);
+				}
+				return true;
+			}
+		};
+		ServerUtil.visit(this, visitor);
+		
+		Trace.trace(Trace.FINEST, "Unpublished modules: " + modules);
+		
+		return modules;
+	}
+	
+	public IPublisher getPublisher(List parents, IModule module) {
+		try {
+			return getDelegate().getPublisher(parents, module);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate getPublisher() " + toString(), e);
+		}
+		return null;
+	}
+	
+	/**
+	 * Publish to the server using the given progress monitor.
+	 * This method will use the smart publisher which has no UI.
+	 *
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @return org.eclispe.core.runtime.IStatus
+	 */
+	public IStatus publish(IProgressMonitor monitor) {
+		return publish(ServerCore.getPublishManager(ServerPreferences.DEFAULT_PUBLISH_MANAGER), monitor);
+	}
+
+	/**
+	 * Publish to the server using the given publisher and progress
+	 * monitor. The result of the publish operation is returned as
+	 * an IStatus.
+	 *
+	 * <p>This method will not present any UI unless 1) The publisher
+	 * requires UI, or 2) There is already a publish listener on this
+	 * server control which will respond to publish events by updating
+	 * a UI.</p>
+	 *
+	 * @param publisher org.eclipse.wst.server.core.model.IPublishManager
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @return org.eclispe.core.runtime.IStatus
+	 */
+	public IStatus publish(IPublishManager publishManager, IProgressMonitor monitor) {
+		if (getServerType() == null)
+			return new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorPublishing"), null);
+
+		// check what is out of sync and publish
+		if (getServerType().hasServerConfiguration() && configuration == null)
+			return new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorNoConfiguration"), null);
+	
+		Trace.trace(Trace.FINEST, "-->-- Publishing to server: " + toString() + " -->--");
+
+		final List parentList = new ArrayList();
+		final List moduleList = new ArrayList();
+		final List taskParentList = new ArrayList();
+		final List taskModuleList = new ArrayList();
+		
+		IModuleVisitor visitor = new IModuleVisitor() {
+			public boolean visit(List parents, IModule module) {
+				taskParentList.add(parents);
+				taskModuleList.add(module);
+				IPublisher publisher = getPublisher(parents, module);
+				if (publisher != null) {
+					if (parents != null)
+						parentList.add(parents);
+					else
+						parentList.add(EMPTY_LIST);
+					moduleList.add(module);
+				}
+				return true;
+			}
+		};
+
+		ServerUtil.visit(this, visitor);
+		
+		// get arrays without the server configuration
+		List[] taskParents = new List[taskParentList.size()];
+		taskParentList.toArray(taskParents);
+		IModule[] taskModules = new IModule[taskModuleList.size()];
+		taskModuleList.toArray(taskModules);
+
+		// get arrays with the server configuration
+		List[] parents = new List[parentList.size()];
+		parentList.toArray(parents);
+		IModule[] modules = new IModule[moduleList.size()];
+		moduleList.toArray(modules);
+
+		int size = 2000 + 3500 * parentList.size();
+		
+		// find tasks
+		List tasks = getTasks(taskParents, taskModules);
+		size += tasks.size() * 500;
+		
+		monitor = ProgressUtil.getMonitorFor(monitor);
+		monitor.beginTask(ServerPlugin.getResource("%publishingTask", toString()), size);
+
+		MultiStatus multi = new MultiStatus(ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%publishingStatus"), null);
+		
+		// perform tasks
+		IStatus taskStatus = performTasks(tasks, monitor);
+		if (taskStatus != null)
+			multi.add(taskStatus);
+
+		// start publishing
+		Trace.trace(Trace.FINEST, "Opening connection to the remote server");
+		boolean connectionOpen = false;
+		try {
+			if (!monitor.isCanceled()) {
+				firePublishStarting(parents, modules);
+				long time = System.currentTimeMillis();
+				PublishStatus ps = new PublishStatus(ServerCore.PLUGIN_ID, ServerPlugin.getResource("%publishingStart"), null);
+				IStatus status = getDelegate().publishStart(ProgressUtil.getSubMonitorFor(monitor, 1000));
+				ps.setTime(System.currentTimeMillis() - time);
+				ps.addChild(status);
+				firePublishStarted(ps);
+				multi.add(ps);
+				if (status.getSeverity() != IStatus.ERROR)
+					connectionOpen = true;
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error starting publish to " + toString(), e);
+			connectionOpen = true; // possibly open
+		}
+		
+		// publish the configuration
+		try {
+			if (connectionOpen && !monitor.isCanceled() && serverType.hasServerConfiguration()) {
+				delegate.publishConfiguration(ProgressUtil.getSubMonitorFor(monitor, 1000));
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error publishing configuration to " + toString(), e);
+		}
+		
+		// remove old modules
+	
+		// publish modules
+		if (connectionOpen && !monitor.isCanceled()) {
+			publishModules(publishManager, parents, modules, multi, monitor);
+		}
+		
+		// end the publishing
+		if (connectionOpen) {
+			Trace.trace(Trace.FINEST, "Closing connection with the remote server");
+			try {
+				PublishStatus ps = new PublishStatus(ServerCore.PLUGIN_ID, ServerPlugin.getResource("%publishingStop"), null);
+				IStatus status = delegate.publishStop(ProgressUtil.getSubMonitorFor(monitor, 500));
+				ps.addChild(status);
+				multi.add(ps);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error stopping publish to " + toString(), e);
+			}
+		}
+	
+		if (monitor.isCanceled()) {
+			IStatus status = new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%publishingCancelled"), null);
+			multi.add(status);
+		}
+
+		PublishStatus ps = new PublishStatus(ServerCore.PLUGIN_ID, ServerPlugin.getResource("%publishingStop"), null);
+		ps.addChild(multi);
+		firePublishFinished(ps);
+		
+		PublishInfo.getPublishInfo().save(this);
+
+		monitor.done();
+
+		Trace.trace(Trace.FINEST, "--<-- Done publishing --<--");
+		return multi;
+	}
+
+	/**
+	 * Publish a single module.
+	 */
+	protected IStatus publishModule(List parents, IModule module, IPublisher publisher, IPublishManager publishManager, PublishControl control, IProgressMonitor monitor) {
+		Trace.trace(Trace.FINEST, "Publishing module: " + module + " " + publisher);
+		
+		monitor.beginTask(ServerPlugin.getResource("%publishingProject", module.getName()), 1000);
+		
+		fireModulePublishStarting(parents, module);
+		long time = System.currentTimeMillis();
+	
+		PublishStatus multi = new PublishStatus(ServerCore.PLUGIN_ID, ServerPlugin.getResource("%publishingProject", module.getName()), module);
+	
+		// delete
+		List verifyDeleteList = new ArrayList();
+		try {
+			List deleteList = publishManager.getResourcesToDelete(module);
+			Trace.trace(Trace.FINEST, "Deleting: " + module + " " + deleteList);
+			if (deleteList != null) {
+				Trace.trace(Trace.FINEST, "Deleting remote resources:");
+				IRemoteResource[] remote = new IRemoteResource[deleteList.size()];
+				deleteList.toArray(remote);
+				IStatus[] status = publisher.delete(remote, ProgressUtil.getSubMonitorFor(monitor, 300));
+				int size = remote.length;
+				if (status.length < size) {
+					Trace.trace(Trace.WARNING, "Publish results missing: " + status.length + "/" + size);
+					size = status.length;
+				} 
+				for (int i = 0; i < size; i++) {
+					Trace.trace(Trace.FINEST, "  " + remote[i]);
+					PublishStatusItem publishStatusItem = null;
+					if (remote[i] instanceof IRemoteFolder)
+						publishStatusItem = new PublishStatusItem(ServerCore.PLUGIN_ID, ServerPlugin.getResource("%publishingDeleteFolder", remote[i].getPath().toString()), status[i]);
+					else
+						publishStatusItem = new PublishStatusItem(ServerCore.PLUGIN_ID, ServerPlugin.getResource("%publishingDeleteFile", remote[i].getPath().toString()), status[i]);
+					multi.addChild(publishStatusItem);
+					if (status[i] == null || status[i].getSeverity() != IStatus.ERROR)
+						verifyDeleteList.add(remote[i]);
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not delete from server", e);
+		}
+		
+		// publish
+		List verifyList = new ArrayList();
+		try {
+			List publishList = publishManager.getResourcesToPublish(module);
+			Trace.trace(Trace.FINEST, "Publishing: " + module + " " + publishList);
+			if (publishList != null) {
+				Trace.trace(Trace.FINEST, "Publishing resources:");
+				IModuleResource[] resource = new IModuleResource[publishList.size()];
+				publishList.toArray(resource);
+				IStatus[] status = publisher.publish(resource, ProgressUtil.getSubMonitorFor(monitor, 600));
+				int size = resource.length;
+				if (status == null)
+					size = 0;
+				else if (status.length < size)
+					size = status.length;
+				for (int i = 0; i < size; i++) {
+					Trace.trace(Trace.FINEST, "  " + resource[i]);
+					PublishStatusItem publishStatusItem = null;
+					if (resource[i] instanceof IModuleFolder)
+						publishStatusItem = new PublishStatusItem(ServerCore.PLUGIN_ID, ServerPlugin.getResource("%publishingPublishFolder", resource[i].getPath().toString()), status[i]);
+					else
+						publishStatusItem = new PublishStatusItem(ServerCore.PLUGIN_ID, ServerPlugin.getResource("%publishingPublishFile", resource[i].getPath().toString()), status[i]);
+					multi.addChild(publishStatusItem);
+					if (status[i] == null || status[i].getSeverity() != IStatus.ERROR)
+						verifyList.add(resource[i]);
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not publish to server", e);
+		}
+		
+		// update state info
+		control.verify(verifyList, verifyDeleteList, ProgressUtil.getSubMonitorFor(monitor, 100));
+		control.setDirty(false);
+
+		multi.setTime(System.currentTimeMillis() - time);
+		fireModulePublishFinished(parents, module, multi);
+		
+		monitor.done();
+		
+		Trace.trace(Trace.FINEST, "Done publishing: " + module);
+		return multi;
+	}
+	
+	/**
+	 * Publishes the given modules. Returns true if the publishing
+	 * should continue, or false if publishing has failed or is cancelled.
+	 * 
+	 * Uses 500 ticks plus 3500 ticks per module
+	 */
+	protected void publishModules(final IPublishManager publishManager, List[] parents, IModule[] modules, MultiStatus multi, IProgressMonitor monitor) {
+		if (parents == null)
+			return;
+
+		int size = parents.length;
+		if (size == 0)
+			return;
+
+		PublishControl[] controls = new PublishControl[size];
+		IPublisher[] publishers = new IPublisher[size];
+
+		// fill publish control cache
+		Trace.trace(Trace.FINEST, "Filling remote resource cache");
+		for (int i = 0; i < size; i++) {
+			publishers[i] = delegate.getPublisher(parents[i], modules[i]);
+			controls[i] = PublishInfo.getPublishInfo().getPublishControl(this, parents[i], modules[i]);
+			controls[i].setPublisher(publishers[i]);
+			try {
+				controls[i].fillRemoteResourceCache(ProgressUtil.getSubMonitorFor(monitor, 500));
+			} catch (Exception e) { }
+		}
+	
+		if (modules != null && modules.length > 0) {
+			Trace.trace(Trace.FINEST, "Using publish manager: " + publishManager.getName());
+	
+			publishManager.resolve(controls, modules, ProgressUtil.getSubMonitorFor(monitor, 500));
+			Trace.trace(Trace.FINEST, "Done resolving");
+		}
+		
+		if (monitor.isCanceled())
+			return;
+
+		// publish modules
+		for (int i = 0; i < size; i++) {
+			IStatus status = publishModule(parents[i], modules[i], publishers[i], publishManager, controls[i], ProgressUtil.getSubMonitorFor(monitor, 3000));
+			multi.add(status);
+		}
+	}
+
+	protected List getTasks(List[] parents, IModule[] modules) {
+		List tasks = new ArrayList();
+		
+		Iterator iterator = ServerCore.getServerTasks().iterator();
+		while (iterator.hasNext()) {
+			IServerTask task = (IServerTask) iterator.next();
+			task.init(this, configuration, parents, modules);
+			byte status = task.getTaskStatus();
+			if (status == IServerTaskDelegate.TASK_MANDATORY) {
+				ServerTaskInfo info = new ServerTaskInfo();
+				info.task = task;
+				info.parents = parents;
+				info.modules = modules;
+				tasks.add(info);
+			}
+		}
+		
+		int size = parents.length;
+		for (int i = 0; i < size; i++) {
+			iterator = ServerCore.getModuleTasks().iterator();
+			while (iterator.hasNext()) {
+				IModuleTask task = (IModuleTask) iterator.next();
+				task.init(this, configuration, parents[i], modules[i]);
+				byte status = task.getTaskStatus();
+				if (status == IModuleTaskDelegate.TASK_MANDATORY) {
+					ModuleTaskInfo info = new ModuleTaskInfo();
+					info.task = task;
+					info.parents = parents[i];
+					info.module = modules[i];
+					tasks.add(info);
+				}
+			}
+		}
+
+		ServerUtil.sortOrderedList(tasks);
+		
+		return tasks;
+	}
+
+	protected IStatus performTasks(List tasks, IProgressMonitor monitor) {
+		Trace.trace(Trace.FINEST, "Performing tasks: " + tasks.size());
+		
+		if (tasks.isEmpty())
+			return null;
+		
+		long time = System.currentTimeMillis();
+		PublishStatus multi = new PublishStatus(ServerCore.PLUGIN_ID, ServerPlugin.getResource("%taskPerforming"), null);
+
+		/*Iterator iterator = tasks.iterator();
+		while (iterator.hasNext()) {
+			IOrdered task = (IOrdered) iterator.next();
+			monitor.subTask(ServerPlugin.getResource("%taskPerforming", task.toString()));
+			IStatus status = null;
+			if (task instanceof ServerTaskInfo) {
+				ServerTaskInfo info = (ServerTaskInfo) task;
+				status = info.task.performTask(server, configuration, info.parents, info.modules, ProgressUtil.getSubMonitorFor(monitor, 500));
+			} else {
+				ModuleTaskInfo info = (ModuleTaskInfo) task;
+				status = info.task.performTask(server, configuration, info.parents, info.module, ProgressUtil.getSubMonitorFor(monitor, 500));
+			}
+			multi.addChild(status);
+			if (monitor.isCanceled())
+				return multi;
+		}
+		
+		// save server and configuration
+		try {
+			ServerUtil.save(server, ProgressUtil.getSubMonitorFor(monitor, 1000));
+			ServerUtil.save(configuration, ProgressUtil.getSubMonitorFor(monitor, 1000));
+		} catch (CoreException se) {
+			Trace.trace(Trace.SEVERE, "Error saving server and/or configuration", se);
+			multi.addChild(se.getStatus());
+		}*/
+
+		multi.setTime(System.currentTimeMillis() - time);
+		return multi;
+	}
+
+	public String toString() {
+		return getName();
+	}
+
+	/**
+	 * Returns true if the server is in a state that it can
+	 * be started, and supports the given mode.
+	 *
+	 * @param mode
+	 * @return boolean
+	 */
+	public boolean canStart(String mode) {
+		byte state = getServerState();
+		if (state != SERVER_STOPPED && state != SERVER_UNKNOWN)
+			return false;
+		
+		if (getServerType() == null || !getServerType().supportsLaunchMode(mode))
+			return false;
+
+		return true;
+	}
+	
+	public ILaunch getExistingLaunch() {
+		ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
+		
+		ILaunch[] launches = launchManager.getLaunches();
+		int size = launches.length;
+		for (int i = 0; i < size; i++) {
+			ILaunchConfiguration launchConfig = launches[i].getLaunchConfiguration();
+			try {
+				if (launchConfig != null) {
+					String serverId = launchConfig.getAttribute(SERVER_ID, (String) null);
+					if (getId().equals(serverId)) {
+						if (!launches[i].isTerminated())
+							return launches[i];
+					}
+				}
+			} catch (CoreException e) { }
+		}
+		
+		return null;
+	}
+
+	public void setLaunchDefaults(ILaunchConfigurationWorkingCopy workingCopy) {
+		try {
+			getDelegate().setLaunchDefaults(workingCopy);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate setLaunchDefaults() " + toString(), e);
+		}
+	}
+	
+	public ILaunchConfiguration getLaunchConfiguration(boolean create) throws CoreException {
+		ILaunchConfigurationType launchConfigType = ((ServerType) getServerType()).getLaunchConfigurationType();
+		
+		ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
+		ILaunchConfiguration[] launchConfigs = null;
+		try {
+			launchConfigs = launchManager.getLaunchConfigurations(launchConfigType);
+		} catch (CoreException e) { }
+		
+		if (launchConfigs != null) {
+			int size = launchConfigs.length;
+			for (int i = 0; i < size; i++) {
+				try {
+					String serverId = launchConfigs[i].getAttribute(SERVER_ID, (String) null);
+					if (getId().equals(serverId))
+						return launchConfigs[i];
+				} catch (CoreException e) { }
+			}
+		}
+		
+		if (!create)
+			return null;
+		
+		// create a new launch configuration
+		String name = launchManager.generateUniqueLaunchConfigurationNameFrom(getName()); 
+		ILaunchConfigurationWorkingCopy wc = launchConfigType.newInstance(null, name);
+		wc.setAttribute(SERVER_ID, getId());
+		setLaunchDefaults(wc);
+		return wc.doSave();
+	}
+
+	/**
+	 * Start the server in the given mode.
+	 *
+	 * @param launchMode String
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @return org.eclispe.core.runtime.IStatus
+	 */
+	public ILaunch start(String mode, IProgressMonitor monitor) throws CoreException {
+		Trace.trace(Trace.FINEST, "Starting server: " + toString() + ", launchMode: " + mode);
+	
+		try {
+			ILaunchConfiguration launchConfig = getLaunchConfiguration(true);
+			ILaunch launch = launchConfig.launch(mode, monitor);
+			Trace.trace(Trace.FINEST, "Launch: " + launch);
+			return launch;
+		} catch (CoreException e) {
+			Trace.trace(Trace.SEVERE, "Error starting server " + toString(), e);
+			throw e;
+		}
+	}
+
+	/**
+	 * Clean up any launch configurations with the given server ref.
+	 * 
+	 * @param serverRef java.lang.String
+	 */
+	protected void deleteLaunchConfigurations() {
+		if (getServerType() == null)
+			return;
+		ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
+		ILaunchConfigurationType launchConfigType = ((ServerType) getServerType()).getLaunchConfigurationType();
+		
+		ILaunchConfiguration[] configs = null;
+		try {
+			configs = launchManager.getLaunchConfigurations(launchConfigType);
+			int size = configs.length;
+			for (int i = 0; i < size; i++) {
+				try {
+					if (getId().equals(configs[i].getAttribute(SERVER_ID, (String) null)))
+						configs[i].delete();
+				} catch (Exception e) { }
+			}
+		} catch (Exception e) { }
+	}
+
+	/**
+	 * Returns true if the server is in a state that it can
+	 * be restarted.
+	 *
+	 * @return boolean
+	 */
+	public boolean canRestart(String mode) {
+		/*IServerDelegate delegate2 = getDelegate();
+		if (!(delegate2 instanceof IStartableServer))
+			return false;*/
+		if (!getServerType().supportsLaunchMode(mode))
+			return false;
+
+		byte state = getServerState();
+		return (state == SERVER_STARTED || state == SERVER_STARTED_DEBUG || state == SERVER_STARTED_PROFILE);
+	}
+
+	/**
+	 * Returns the current restart state of the server. This
+	 * implementation will always return false when the server
+	 * is stopped.
+	 *
+	 * @return boolean
+	 */
+	public boolean isRestartNeeded() {
+		if (getServerState() == SERVER_STOPPED)
+			return false;
+		else
+			return restartNeeded;
+	}
+	
+	/**
+	 * Sets the server restart state.
+	 *
+	 * @param state boolean
+	 */
+	public synchronized void setRestartNeeded(boolean state) {
+		if (state == restartNeeded)
+			return;
+		restartNeeded = state;
+		fireRestartStateChangeEvent();
+	}
+
+	/**
+	 * Restart the server with the given debug mode.
+	 * A server may only be restarted when it is currently running.
+	 * This method is asynchronous.
+	 */
+	public void restart(final String mode) {
+		if (getServerState() == SERVER_STOPPED)
+			return;
+	
+		Trace.trace(Trace.FINEST, "Restarting server: " + getName());
+	
+		try {
+			IServerDelegate delegate2 = getDelegate();
+			if (delegate2 instanceof IRestartableServer) {
+				((IRestartableServer) delegate2).restart(mode);
+			} else {
+				// add listener to start it as soon as it is stopped
+				addServerListener(new ServerAdapter() {
+					public void serverStateChange(IServer server) {
+						if (server.getServerState() == SERVER_STOPPED) {
+							server.removeServerListener(this);
+	
+							// restart in a quarter second (give other listeners a chance
+							// to hear the stopped message)
+							Thread t = new Thread() {
+								public void run() {
+									try {
+										Thread.sleep(250);
+									} catch (Exception e) { }
+									try {
+										Server.this.start(mode, new NullProgressMonitor());
+									} catch (Exception e) {
+										Trace.trace(Trace.SEVERE, "Error while restarting server", e);
+									}
+								}
+							};
+							t.setDaemon(true);
+							t.setPriority(Thread.NORM_PRIORITY - 2);
+							t.start();
+						}
+					}
+				});
+	
+				// stop the server
+				stop();
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error restarting server", e);
+		}
+	}
+
+
+	/**
+	 * Returns true if the server is in a state that it can
+	 * be stopped.
+	 *
+	 * @return boolean
+	 */
+	public boolean canStop() {
+		if (getServerState() == SERVER_STOPPED)
+			return false;
+		
+		if (!(getDelegate() instanceof IStartableServer))
+			return false;
+
+		return true;
+	}
+
+	/**
+	 * Stop the server if it is running.
+	 */
+	public void stop() {
+		if (getServerState() == SERVER_STOPPED)
+			return;
+
+		// check if this is still a valid server
+		if (!(getDelegate() instanceof IStartableServer))
+			return;
+
+		Trace.trace(Trace.FINEST, "Stopping server: " + toString());
+
+		try {
+			((IStartableServer) getDelegate()).stop();
+		} catch (Throwable t) {
+			Trace.trace(Trace.SEVERE, "Error stopping server " + toString(), t);
+		}
+	}
+	
+	/**
+	 * Terminate the server process(es). This method should only be
+	 * used as a last resort after the stop() method fails to work.
+	 * The server should return from this method quickly and
+	 * use the server listener to notify shutdown progress.
+	 * It MUST terminate the server completely and return it to
+	 * the stopped state.
+	 */
+	public void terminate() {
+		try {
+			IStartableServer startableServer = (IStartableServer) getDelegate();
+			startableServer.terminate();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate terminate() " + toString(), e);
+		}
+	}
+	
+	/**
+	 * Start the server in the given start mode and waits until the server
+	 * has finished started.
+	 *
+	 * @param mode java.lang.String
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @exception org.eclipse.core.runtime.CoreException - thrown if an error occurs while trying to start the server
+	 */
+	public void synchronousStart(String mode, IProgressMonitor monitor) throws CoreException {
+		Trace.trace(Trace.FINEST, "synchronousStart 1");
+		final Object mutex = new Object();
+	
+		// add listener to the server
+		IServerListener listener = new ServerAdapter() {
+			public void serverStateChange(IServer server) {
+				byte state = server.getServerState();
+				if (state == IServer.SERVER_STARTED || state == IServer.SERVER_STARTED_DEBUG
+					|| state == IServer.SERVER_STARTED_PROFILE || state == IServer.SERVER_STOPPED) {
+					// notify waiter
+					synchronized (mutex) {
+						try {
+							Trace.trace(Trace.FINEST, "synchronousStart notify");
+							mutex.notifyAll();
+						} catch (Exception e) {
+							Trace.trace(Trace.SEVERE, "Error notifying server start", e);
+						}
+					}
+				}
+			}
+		};
+		addServerListener(listener);
+		
+		class Timer {
+			boolean timeout;
+			boolean alreadyDone;
+		}
+		final Timer timer = new Timer();
+		
+		Thread thread = new Thread() {
+			public void run() {
+				try {
+					Thread.sleep(120000);
+					if (!timer.alreadyDone) {
+						timer.timeout = true;
+						// notify waiter
+						synchronized (mutex) {
+							Trace.trace(Trace.FINEST, "synchronousStart notify timeout");
+							mutex.notifyAll();
+						}
+					}
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Error notifying server start timeout", e);
+				}
+			}
+		};
+		thread.setDaemon(true);
+		thread.start();
+	
+		Trace.trace(Trace.FINEST, "synchronousStart 2");
+	
+		// start the server
+		try {
+			start(mode, monitor);
+		} catch (CoreException e) {
+			removeServerListener(listener);
+			throw e;
+		}
+	
+		Trace.trace(Trace.FINEST, "synchronousStart 3");
+	
+		// wait for it! wait for it! ...
+		synchronized (mutex) {
+			try {
+				while (!timer.timeout && !(getServerState() == IServer.SERVER_STARTED ||
+					getServerState() == IServer.SERVER_STARTED_DEBUG ||
+					getServerState() == IServer.SERVER_STARTED_PROFILE ||
+					getServerState() == IServer.SERVER_STOPPED))
+					mutex.wait();
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error waiting for server start", e);
+			}
+		}
+		removeServerListener(listener);
+		
+		if (timer.timeout)
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorInstanceStartFailed", getName()), null));
+		else
+			timer.alreadyDone = true;
+		
+		if (getServerState() == IServer.SERVER_STOPPED)
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorInstanceStartFailed", getName()), null));
+	
+		Trace.trace(Trace.FINEST, "synchronousStart 4");
+	}
+
+	/**
+	 * Stop the server and wait until the
+	 * server has completely stopped.
+	 */
+	public void synchronousStop() {
+		if (getServerState() == IServer.SERVER_STOPPED)
+			return;
+		
+		final Object mutex = new Object();
+	
+		// add listener to the server
+		IServerListener listener = new ServerAdapter() {
+			public void serverStateChange(IServer server) {
+				byte state = server.getServerState();
+				if (Server.this == server && state == IServer.SERVER_STOPPED) {
+					// notify waiter
+					synchronized (mutex) {
+						try {
+							mutex.notifyAll();
+						} catch (Exception e) {
+							Trace.trace(Trace.SEVERE, "Error notifying server stop", e);
+						}
+					}
+				}
+			}
+		};
+		addServerListener(listener);
+		
+		class Timer {
+			boolean timeout;
+			boolean alreadyDone;
+		}
+		final Timer timer = new Timer();
+		
+		Thread thread = new Thread() {
+			public void run() {
+				try {
+					Thread.sleep(120000);
+					if (!timer.alreadyDone) {
+						timer.timeout = true;
+						// notify waiter
+						synchronized (mutex) {
+							Trace.trace(Trace.FINEST, "stop notify timeout");
+							mutex.notifyAll();
+						}
+					}
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Error notifying server stop timeout", e);
+				}
+			}
+		};
+		thread.setDaemon(true);
+		thread.start();
+	
+		// stop the server
+		stop();
+	
+		// wait for it! wait for it!
+		synchronized (mutex) {
+			try {
+				while (!timer.timeout && getServerState() != IServer.SERVER_STOPPED)
+					mutex.wait();
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error waiting for server stop", e);
+			}
+		}
+		removeServerListener(listener);
+		
+		/*
+		//can't throw exceptions
+		if (timer.timeout)
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorInstanceStartFailed", getName()), null));
+		else
+			timer.alreadyDone = true;
+		
+		if (getServerState() == IServer.SERVER_STOPPED)
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorInstanceStartFailed", getName()), null));*/
+	}
+	
+	/**
+	 * Trigger a restart of the given module and wait until it has finished restarting.
+	 *
+	 * @param module org.eclipse.wst.server.core.IModule
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @exception org.eclipse.core.runtime.CoreException - thrown if an error occurs while trying to restart the module
+	 */
+	public void synchronousModuleRestart(final IModule module, IProgressMonitor monitor) throws CoreException {
+		IRestartableModule rm = null;
+		try {
+			rm = (IRestartableModule) getDelegate();
+		} catch (Exception e) {
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, "Server does not support restarting modules", e));
+		}
+		Trace.trace(Trace.FINEST, "synchronousModuleRestart 1");
+
+		final Object mutex = new Object();
+	
+		// add listener to the module
+		IServerListener listener = new ServerAdapter() {
+			public void moduleStateChange(IServer server) {
+				byte state = server.getModuleState(module);
+				if (state == IServer.MODULE_STATE_STARTED || state == IServer.MODULE_STATE_STOPPED) {
+					// notify waiter
+					synchronized (mutex) {
+						try {
+							Trace.trace(Trace.FINEST, "synchronousModuleRestart notify");
+							mutex.notifyAll();
+						} catch (Exception e) {
+							Trace.trace(Trace.SEVERE, "Error notifying module restart", e);
+						}
+					}
+				}
+			}
+		};
+		addServerListener(listener);
+		
+		// make sure it times out after 30s
+		class Timer {
+			boolean timeout;
+			boolean alreadyDone;
+		}
+		final Timer timer = new Timer();
+		
+		Thread thread = new Thread() {
+			public void run() {
+				try {
+					Thread.sleep(30000);
+					if (!timer.alreadyDone) {
+						timer.timeout = true;
+						// notify waiter
+						synchronized (mutex) {
+							Trace.trace(Trace.FINEST, "synchronousModuleRestart notify timeout");
+							mutex.notifyAll();
+						}
+					}
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Error notifying module restart timeout", e);
+				}
+			}
+		};
+		thread.setDaemon(true);
+		thread.start();
+	
+		Trace.trace(Trace.FINEST, "synchronousModuleRestart 2");
+	
+		// restart the module
+		try {
+			rm.restartModule(module, monitor);
+		} catch (CoreException e) {
+			removeServerListener(listener);
+			throw e;
+		}
+	
+		Trace.trace(Trace.FINEST, "synchronousModuleRestart 3");
+	
+		// wait for it! wait for it! ...
+		synchronized (mutex) {
+			try {
+				while (!timer.timeout && !(getModuleState(module) == IServer.MODULE_STATE_STARTED || getModuleState(module) == IServer.MODULE_STATE_STOPPED))
+					mutex.wait();
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error waiting for server start", e);
+			}
+		}
+		removeServerListener(listener);
+		if (timer.timeout)
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorModuleRestartFailed", getName()), null));
+		else
+			timer.alreadyDone = true;
+		
+		if (getModuleState(module) == IServer.SERVER_STOPPED)
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorModuleRestartFailed", getName()), null));
+	
+		Trace.trace(Trace.FINEST, "synchronousModuleRestart 4");
+	}
+
+	public IPath getTempDirectory() {
+		return ServerPlugin.getInstance().getTempDirectory(getId());
+	}
+
+	protected String getXMLRoot() {
+		return "server";
+	}
+	
+	protected void loadState(IMemento memento) {
+		/*String serverTypeId = memento.getString("server-type-id");
+		serverType = ServerCore.getServerType(serverTypeId);
+		
+		String runtimeId = memento.getString("runtime-id");
+		runtime = ServerCore.getResourceManager().getRuntime(runtimeId);
+		
+		String configurationId = memento.getString("configuration-id");
+		configuration = ServerCore.getResourceManager().getServerConfiguration(configurationId);*/
+		resolve();
+	}
+	
+	protected void resolve() {
+		IServerType oldServerType = serverType;
+		String serverTypeId = getAttribute("server-type-id", (String)null);
+		serverType = ServerCore.getServerType(serverTypeId);
+		if (serverType != null && !serverType.equals(oldServerType))
+			serverState = ((ServerType)serverType).getInitialState();
+		
+		String runtimeId = getAttribute(RUNTIME_ID, (String)null);
+		runtime = ServerCore.getResourceManager().getRuntime(runtimeId);
+		
+		String configurationId = getAttribute(CONFIGURATION_ID, (String)null);
+		configuration = ServerCore.getResourceManager().getServerConfiguration(configurationId);
+	}
+	
+	protected void setInternal(ServerWorkingCopy wc) {
+		map = wc.map;
+		configuration = wc.configuration;
+		runtime = wc.runtime;
+		configurationSyncState = wc.configurationSyncState;
+		restartNeeded = wc.restartNeeded;
+		serverType = wc.serverType;
+
+		// can never modify the following properties via the working copy
+		//serverState = wc.serverState;
+		delegate = wc.delegate;
+	}
+	
+	protected void saveState(IMemento memento) {
+		if (serverType != null)
+			memento.putString("server-type", serverType.getId());
+
+		if (configuration != null)
+			memento.putString(CONFIGURATION_ID, configuration.getId());
+		else
+			memento.putString(CONFIGURATION_ID, null);
+		
+		if (runtime != null)
+			memento.putString(RUNTIME_ID, runtime.getId());
+		else
+			memento.putString(RUNTIME_ID, null);
+	}
+	
+	public void updateConfiguration() {
+		try {
+			getDelegate().updateConfiguration();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate updateConfiguration() " + toString(), e);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServerConfiguration#canModifyModule(org.eclipse.wst.server.core.model.IModule)
+	 */
+	public IStatus canModifyModules(IModule[] add, IModule[] remove) {
+		try {
+			return getDelegate().canModifyModules(add, remove);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate canModifyModules() " + toString(), e);
+			return null;
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServer#getModules()
+	 */
+	public IModule[] getModules() {
+		try {
+			return getDelegate().getModules();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate getModules() " + toString(), e);
+			return new IModule[0];
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServer#getModuleState()
+	 */
+	public byte getModuleState(IModule module) {
+		try {
+			return getDelegate().getModuleState(module);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate getModuleState() " + toString(), e);
+			return MODULE_STATE_UNKNOWN;
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServerConfiguration#getRepairCommands(org.eclipse.wst.server.core.model.IModuleFactoryEvent[], org.eclipse.wst.server.core.model.IModuleEvent[])
+	 */
+	public ITask[] getRepairCommands(IModuleFactoryEvent[] factoryEvent, IModuleEvent[] moduleEvent) {
+		try {
+			return getDelegate().getRepairCommands(factoryEvent, moduleEvent);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate getRepairCommands() " + toString(), e);
+			return new ITask[0];
+		}
+	}
+
+	/*
+	 * @see IServerConfigurationFactory#getChildModule(IModule)
+	 */
+	public List getChildModules(IModule module) {
+		try {
+			return getDelegate().getChildModules(module);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate getChildModules() " + toString(), e);
+			return null;
+		}
+	}
+
+	/*
+	 * @see IServerConfigurationFactory#getParentModules(IModule)
+	 */
+	public List getParentModules(IModule module) throws CoreException {
+		try {
+			return getDelegate().getParentModules(module);
+		} catch (CoreException se) {
+			//Trace.trace(Trace.FINER, "CoreException calling delegate getParentModules() " + toString() + ": " + se.getMessage());
+			throw se;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate getParentModules() " + toString(), e);
+			return null;
+		}
+	}
+	
+	/*
+	 * 
+	 */
+	/*public boolean hasRuntime() {
+		try {
+			return getDelegate().requiresRuntime();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate requiresRuntime() " + toString(), e);
+			return false;
+		}
+	}*/
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerBuilder.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerBuilder.java
new file mode 100644
index 0000000..19b9b1c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerBuilder.java
@@ -0,0 +1,192 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.*;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.*;
+/**
+ * Links builder.
+ */
+public class ServerBuilder extends IncrementalProjectBuilder {
+	// attribute to tag the server core broken link markers
+	private static final String SERVER_CORE_MARKER = "server-core-marker";
+
+	/**
+	 * @see IncrementalProjectBuilder#build
+	 */
+	protected IProject[] build(int kind, Map args, IProgressMonitor monitor) {
+		Trace.trace(Trace.FINEST, "->- Link builder running on: " + getProject().getName() + " " + kind + " " + args + " ->-");
+		try {
+			IServerProject nature = (IServerProject) getProject().getNature(IServerProject.NATURE_ID);
+			Iterator iterator = nature.getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server = (IServer) iterator.next();
+				updateServerMarkers(server);
+			}
+			iterator = nature.getServerConfigurations().iterator();
+			while (iterator.hasNext()) {
+				IServerConfiguration configuration = (IServerConfiguration) iterator.next();
+				updateConfigurationMarkers(configuration);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error in link builder", e);
+		}
+		Trace.trace(Trace.FINEST, "-<- Done link builder running -<-");
+		return null;
+	}
+
+	/**
+	 * startupOnInitialize method comment.
+	 */
+	protected void startupOnInitialize() {
+	}
+
+	/**
+	 * Update the "broken link" markers on a specific configuration.
+	 */
+	protected void updateConfigurationMarkers(IServerConfiguration configuration) {
+		/*IResource resource = ServerCore.getResourceManager().getServerResourceLocation(configuration);
+	
+		List missingProjects = new ArrayList();
+	
+	//FIX-ME
+		// just do immediate projects for now
+		String[] projectRefs = configuration.getProjectRefs();
+		if (projectRefs != null) {
+			int size = projectRefs.length;
+			for (int i = 0; i < size; i++) {
+				IProject project = Reference.getProjectByRef(projectRefs[i]);
+				if (project == null) {
+					missingProjects.add(projectRefs[i]);
+				}
+			}
+		}
+	
+		if (Trace.isTracing())
+			Trace.trace("Updating markers on " + configuration + " " + resource.getLocation().toString() + " " + missingProjects);
+	
+		try {
+			boolean found = false;
+			IMarker[] marker = resource.findMarkers(IMarker.PROBLEM, false, IResource.DEPTH_ZERO);
+			if (marker != null) {
+				int size = marker.length;
+				for (int i = 0; i < size; i++) {
+					if (marker[i].getAttribute(SERVER_CORE_MARKER, false)) {
+						Trace.trace("marker found");
+						try {
+							String projectRef = marker[i].getAttribute("projectRef", null);
+							if (projectRef != null && missingProjects.contains(projectRef)) {
+								// update marker
+								Trace.trace("Updating marker: " + marker[i].getId());
+								marker[i].setAttribute(IMarker.MESSAGE, ServerPlugin.getResource("%errorMissingProjectTask", new String[] {ServerUtil.getName(configuration), Reference.getProjectNameFromRef(projectRef)}));
+								marker[i].setAttribute(IMarker.LOCATION, resource.getLocation().toString());
+								marker[i].setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);
+							} else {
+								// remove
+								Trace.trace("Removing marker: " + marker[i].getId());
+								marker[i].delete();
+							}
+							missingProjects.remove(projectRef);
+						} catch (Exception e) {
+							Trace.trace("Error updating markers 1", e);
+						}
+					}
+				}
+			}
+	
+			if (!missingProjects.isEmpty()) {
+				Iterator iterator = missingProjects.iterator();
+				while (iterator.hasNext()) {
+					String projectRef = (String) iterator.next();		
+					try {
+						// add new marker
+						Trace.trace("Adding new marker");
+						IMarker newMarker = resource.createMarker(IMarker.PROBLEM);
+						newMarker.setAttribute(SERVER_CORE_MARKER, true);
+						newMarker.setAttribute(IMarker.MESSAGE, ServerPlugin.getResource("%errorMissingProjectTask", new String[] {ServerUtil.getName(configuration), Reference.getProjectNameFromRef(projectRef)} ));
+						newMarker.setAttribute(IMarker.LOCATION, resource.getLocation().toString());
+						newMarker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);
+					} catch (Exception e) {
+						Trace.trace("Error updating markers 2", e);
+					}
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace("Error updating markers", e);
+		}
+		Trace.trace("Done updating markers");
+		*/
+	}
+
+	/**
+	 * Update the "broken link" markers on a specific server.
+	 */
+	protected void updateServerMarkers(IServer server) {
+		IFile file = server.getFile();
+		if (file == null || !file.exists())
+			return;
+		
+		if (!server.getServerType().hasServerConfiguration())
+			return;
+	
+		IServerConfiguration configuration = server.getServerConfiguration();
+		boolean isProblem = (configuration == null);
+	
+		Trace.trace(Trace.FINEST, "Updating markers on " + server + " " + file.getLocation().toString() + " " + isProblem);
+	
+		try {
+			boolean found = false;
+			IMarker[] marker = file.findMarkers(IMarker.PROBLEM, false, IResource.DEPTH_ZERO);
+			if (marker != null) {
+				int size = marker.length;
+				for (int i = 0; i < size; i++) {
+					if (marker[i].getAttribute(SERVER_CORE_MARKER, false)) {
+						try {
+							if (isProblem && !found) {
+								// update marker
+								Trace.trace(Trace.FINEST, "Updating marker: " + marker[i].getId());
+								marker[i].setAttribute(IMarker.MESSAGE, ServerPlugin.getResource("%errorMissingConfigurationTask", new String[] {server.getName()}));
+								marker[i].setAttribute(IMarker.LOCATION, file.getLocation().toString());
+								marker[i].setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+							} else {
+								// remove
+								Trace.trace(Trace.FINEST, "Removing marker: " + marker[i].getId());
+								marker[i].delete();
+							}
+						} catch (Exception e) {
+							Trace.trace(Trace.SEVERE, "Error updating markers 1", e);
+						}
+						found = true;
+					}
+				}
+			}
+	
+			if (!found && isProblem) {
+				try {
+					// add new marker
+					Trace.trace(Trace.FINEST, "Adding new marker");
+					IMarker newMarker = file.createMarker(IMarker.PROBLEM);
+					newMarker.setAttribute(SERVER_CORE_MARKER, true);
+					newMarker.setAttribute(IMarker.MESSAGE, ServerPlugin.getResource("%errorMissingConfigurationTask", new String[] {server.getName()}));
+					newMarker.setAttribute(IMarker.LOCATION, file.getLocation().toString());
+					newMarker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Error updating markers 2", e);
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error updating markers", e);
+		}
+		Trace.trace(Trace.FINEST, "Done updating markers");
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerConfiguration.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerConfiguration.java
new file mode 100644
index 0000000..95fe123
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerConfiguration.java
@@ -0,0 +1,241 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.runtime.*;
+import org.osgi.framework.Bundle;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.*;
+import org.eclipse.wst.server.core.util.FileUtil;
+/**
+ * 
+ */
+public class ServerConfiguration extends Base implements IServerConfiguration {
+	protected IServerConfigurationType configurationType;
+	protected IServerConfigurationDelegate delegate;
+	protected boolean isDataLoaded = false;
+	
+	// working copy, loaded resource
+	public ServerConfiguration(IFile file) {
+		super(file);
+	}
+
+	// creation (working copy)
+	public ServerConfiguration(String id, IFile file, IServerConfigurationType type) {
+		super(file, id);
+		this.configurationType = type;
+	}
+
+	public IServerConfigurationDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				ServerConfigurationType configType = (ServerConfigurationType) configurationType;
+				delegate = (IServerConfigurationDelegate) configType.getElement().createExecutableExtension("class");
+				delegate.initialize(this);
+				loadData();
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString(), e);
+			}
+		}
+		return delegate;
+	}
+	
+	/**
+	 * Returns true if the delegate has been loaded.
+	 * 
+	 * @return
+	 */
+	public boolean isDelegateLoaded() {
+		return delegate != null;
+	}
+	
+	public void dispose() {
+		if (delegate != null)
+			delegate.dispose();
+	}
+	
+	public boolean isDelegatePluginActivated() {
+		IConfigurationElement element = ((ServerConfigurationType) configurationType).getElement();
+		String pluginId = element.getDeclaringExtension().getNamespace();
+		return Platform.getBundle(pluginId).getState() == Bundle.ACTIVE;
+	}
+	
+	public IServerConfigurationWorkingCopy getWorkingCopy() {
+		IServerConfigurationWorkingCopy wc = new ServerConfigurationWorkingCopy(this); 
+		addWorkingCopy(wc);
+		return wc;
+	}
+	
+	public void delete() throws CoreException {
+		if (file != null) {
+			file.delete(true, true, new NullProgressMonitor());
+			if (getServerConfigurationType().isFolder()) {
+				IFolder folder = getFolder(false);
+				if (folder.exists())
+					folder.delete(true, true, new NullProgressMonitor());
+			}
+		} else
+			deleteFromMetadata();
+	}
+	
+	public IServerConfigurationType getServerConfigurationType() {
+		return configurationType;
+	}
+
+	public IFolder getConfigurationDataFolder() {
+		if (file == null)
+			return null;
+		try {
+			return getFolder(false);
+		} catch (Exception e) {
+			return null;
+		}
+	}
+	
+	public IPath getConfigurationDataPath() {
+		if (file != null)
+			return null;
+		else
+			return getPath(false);
+	}
+
+	protected IFolder getFolder(boolean create) throws CoreException {
+		IPath path = file.getProjectRelativePath();
+		path = path.removeLastSegments(1).append(file.getName() + "-data");
+		IFolder folder = file.getProject().getFolder(path);
+		if (!folder.exists() && create)
+			folder.create(true, true, new NullProgressMonitor());
+		return folder;
+	}
+	
+	protected IPath getPath(boolean create) {
+		IPath path = ServerPlugin.getInstance().getStateLocation().append("configs");
+		path = path.append(getId() + "-data");
+		if (create) {
+			File file2 = path.toFile();
+			if (!file2.exists())
+				file2.mkdirs();
+		}
+		return path;
+	}
+	
+	protected void loadData() {
+		if (isDataLoaded)
+			return;
+		isDataLoaded = true;
+		if (!getServerConfigurationType().isFolder())
+			return;
+
+		try {
+			if (file != null) {
+				IFolder folder = getFolder(false);
+				getDelegate().load(folder, new NullProgressMonitor());
+			} else {
+				IPath path = getPath(false);
+				getDelegate().load(path, new NullProgressMonitor());
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not load server configuration data", e);
+		}
+	}
+	
+	protected void saveData(boolean create) {
+		if (!isDataLoaded || !getServerConfigurationType().isFolder())
+			return;
+		
+		try {
+			if (file != null) {
+				IFolder folder = getFolder(create);
+				getDelegate().save(folder, new NullProgressMonitor());
+			} else {
+				IPath path = getPath(create);
+				getDelegate().save(path, new NullProgressMonitor());
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save server configuration data", e);
+		}
+	}
+
+	protected void saveToFile(IProgressMonitor monitor) throws CoreException {
+		super.saveToFile(monitor);
+		
+		saveData(true);
+	}
+
+	protected void loadFromFile(IProgressMonitor monitor) throws CoreException {
+		super.loadFromFile(monitor);
+		
+		//loadData();
+	}
+	
+	protected void deleteFromMetadata() {
+		ResourceManager rm = (ResourceManager) ServerCore.getResourceManager();
+		rm.removeServerConfiguration(this);
+		
+		if (getServerConfigurationType().isFolder()) {
+			try {
+				IPath path = getPath(false);
+				File file2 = path.toFile();
+				if (file2.exists())
+					FileUtil.deleteDirectory(file2, new NullProgressMonitor());
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not save server configuration", e);
+			}
+		}
+	}
+
+	protected void saveToMetadata(IProgressMonitor monitor) {
+		ResourceManager rm = (ResourceManager) ServerCore.getResourceManager();
+		rm.addServerConfiguration(this);
+		
+		saveData(true);
+	}
+	
+	protected String getXMLRoot() {
+		return "server-configuration";
+	}
+	
+	protected void setInternal(ServerConfigurationWorkingCopy wc) {
+		map = wc.map;
+		configurationType = wc.configurationType;
+		isDataLoaded = false; //wc.isDataLoaded; let the wc save it
+		delegate = wc.delegate;
+	}
+	
+	protected void loadFromMemento(IMemento memento, IProgressMonitor monitor) {
+		super.loadFromMemento(memento, monitor);
+		
+		//loadData();
+	}
+	
+	protected void loadState(IMemento memento) {
+		String serverTypeId = memento.getString("server-configuration-type-id");
+		configurationType = ServerCore.getServerConfigurationType(serverTypeId);
+	}
+	
+	protected void saveState(IMemento memento) {
+		if (configurationType != null)
+			memento.putString("server-configuration-type-id", configurationType.getId());
+	}
+	
+	public IStatus validateEdit(Object context) {
+		if (file == null)
+			return null;
+		
+		// TODO
+		return file.getWorkspace().validateEdit(new IFile[] { file }, context);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerConfigurationType.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerConfigurationType.java
new file mode 100644
index 0000000..c81f638
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerConfigurationType.java
@@ -0,0 +1,116 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.*;
+/**
+ * 
+ */
+public class ServerConfigurationType implements IServerConfigurationType {
+	protected IConfigurationElement element;
+
+	/**
+	 * ServerConfigurationType constructor comment.
+	 */
+	public ServerConfigurationType(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+	
+	protected IConfigurationElement getElement() {
+		return element;
+	}
+
+	/**
+	 * Returns the id of this factory.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+	
+	public String getName() {
+		return element.getAttribute("name");
+	}
+
+	public String getDescription() {
+		return element.getAttribute("description");
+	}
+	
+	/**
+	 * Returns the order.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			String o = element.getAttribute("order");
+			return Integer.parseInt(o);
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+	
+	public boolean isFolder() {
+		return "true".equalsIgnoreCase(element.getAttribute("isFolder"));
+	}
+	
+	/**
+	 * Return the label of this factory.
+	 *
+	 * @return java.lang.String
+	 */
+	public String[] getImportFilterExtensions() {
+		return ServerPlugin.tokenize(element.getAttribute("importExtensions"), ",");
+	}
+	
+	public IServerConfigurationWorkingCopy createServerConfiguration(String id, IFile file, IProgressMonitor monitor) {
+		if (id == null || id.length() == 0)
+			id = ServerPlugin.generateId();
+		ServerConfigurationWorkingCopy scwc = new ServerConfigurationWorkingCopy(id, file, this);
+		scwc.setDefaults();
+		return scwc;
+	}
+	
+	public IServerConfigurationWorkingCopy importFromRuntime(String id, IFile file, IRuntime runtime, IProgressMonitor monitor) throws CoreException {
+		if (id == null || id.length() == 0)
+			id = ServerPlugin.generateId();
+		ServerConfigurationWorkingCopy scwc = new ServerConfigurationWorkingCopy(id, file, this);
+		scwc.setDefaults();
+		scwc.importFromRuntime(runtime, monitor);
+		return scwc;
+	}
+	
+	public IServerConfigurationWorkingCopy importFromPath(String id, IFile file, IPath path, IProgressMonitor monitor) throws CoreException {
+		if (id == null || id.length() == 0)
+			id = ServerPlugin.generateId();
+		ServerConfigurationWorkingCopy scwc = new ServerConfigurationWorkingCopy(id, file, this);
+		scwc.setDefaults();
+		scwc.importFromPath(path, monitor);
+		return scwc;
+	}
+
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return "ServerConfigurationType[" + getId() + "]";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerConfigurationWorkingCopy.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerConfigurationWorkingCopy.java
new file mode 100644
index 0000000..d10ddba
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerConfigurationWorkingCopy.java
@@ -0,0 +1,228 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.beans.PropertyChangeListener;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IServerConfigurationDelegate;
+import org.eclipse.wst.server.core.model.IServerConfigurationWorkingCopyDelegate;
+/**
+ * 
+ */
+public class ServerConfigurationWorkingCopy extends ServerConfiguration implements IServerConfigurationWorkingCopy {
+	protected ServerConfiguration config;
+	protected WorkingCopyHelper wch;
+	
+	protected IServerConfigurationWorkingCopyDelegate workingCopyDelegate;
+	
+	// working copy
+	public ServerConfigurationWorkingCopy(ServerConfiguration config) {
+		super(config.getFile());
+		this.config = config;
+		this.configurationType = config.configurationType;
+		
+		map = new HashMap(config.map);
+		wch = new WorkingCopyHelper(this);
+	}
+
+	// creation
+	public ServerConfigurationWorkingCopy(String id, IFile file, IServerConfigurationType configType) {
+		super(id, file, configType);
+		//this.config = this;
+		wch = new WorkingCopyHelper(this);
+	}
+
+	public boolean isWorkingCopy() {
+		return true;
+	}
+	
+	public IServerConfiguration getOriginal() {
+		return config;
+	}
+	
+	public IServerConfigurationWorkingCopy getWorkingCopy() {
+		return this;
+	}
+
+	public void setAttribute(String attributeName, int value) {
+		wch.setAttribute(attributeName, value);
+	}
+
+	public void setAttribute(String attributeName, boolean value) {
+		wch.setAttribute(attributeName, value);
+	}
+	
+	public void setAttribute(String attributeName, String value) {
+		wch.setAttribute(attributeName, value);
+	}
+	
+	public void setAttribute(String attributeName, List value) {
+		wch.setAttribute(attributeName, value);
+	}
+	
+	public void setAttribute(String attributeName, Map value) {
+		wch.setAttribute(attributeName, value);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServerWorkingCopy#setName(java.lang.String)
+	 */
+	public void setName(String name) {
+		wch.setName(name);
+	}
+	
+	public void setLocked(boolean b) {
+		wch.setLocked(b);
+	}
+
+	public void setPrivate(boolean b) {
+		wch.setPrivate(b);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServerWorkingCopy#isDirty()
+	 */
+	public boolean isDirty() {
+		return wch.isDirty();
+	}
+	
+	public void release() {
+		wch.release();
+		dispose();
+		if (config != null)
+			config.release(this);
+	}
+	
+	public IServerConfiguration save(IProgressMonitor monitor) throws CoreException {
+		if (wch.isReleased())
+			return null;
+		if (config == null)
+			config = new ServerConfiguration(file);
+		config.setInternal(this);
+		config.doSave(monitor);
+		saveData(true);
+		wch.setDirty(false);
+		release();
+		return config;
+	}
+	
+	public IServerConfiguration save(IProgressMonitor monitor, boolean release) throws CoreException {
+		if (wch.isReleased())
+			return null;
+		if (config == null)
+			config = new ServerConfiguration(file);
+		config.setInternal(this);
+		config.doSave(monitor);
+		saveData(true);
+		wch.setDirty(false);
+		if (release)
+			release();
+		return config;
+	}
+	
+	public IServerConfigurationDelegate getDelegate() {
+		return getWorkingCopyDelegate();
+	}
+	
+	public IServerConfigurationWorkingCopyDelegate getWorkingCopyDelegate() {
+		return getWorkingCopyDelegate(true);
+	}
+
+	public IServerConfigurationWorkingCopyDelegate getWorkingCopyDelegate(boolean load) {
+		if (workingCopyDelegate == null) {
+			try {
+				ServerConfigurationType configType = (ServerConfigurationType) configurationType;
+				workingCopyDelegate = (IServerConfigurationWorkingCopyDelegate) configType.getElement().createExecutableExtension("workingCopyClass");
+				workingCopyDelegate.initialize((IServerConfiguration) this);
+				workingCopyDelegate.initialize(this);
+				if (load)
+					loadData();
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString(), e);
+			}
+		}
+		return workingCopyDelegate;
+	}
+	
+	public void dispose() {
+		super.dispose();
+		if (workingCopyDelegate != null)
+			workingCopyDelegate.dispose();
+	}
+	
+	/**
+	 * Add a property change listener to this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void addPropertyChangeListener(PropertyChangeListener listener) {
+		wch.addPropertyChangeListener(listener);
+	}
+	
+	/**
+	 * Remove a property change listener from this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void removePropertyChangeListener(PropertyChangeListener listener) {
+		wch.removePropertyChangeListener(listener);
+	}
+	
+	/**
+	 * Fire a property change event.
+	 */
+	public void firePropertyChangeEvent(String propertyName, Object oldValue, Object newValue) {
+		wch.firePropertyChangeEvent(propertyName, oldValue, newValue);
+	}
+	
+	public void setDefaults() {
+		try {
+			getWorkingCopyDelegate(false).setDefaults();
+			isDataLoaded = true;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate setDefaults() " + toString(), e);
+		}
+	}
+	
+	public void importFromPath(IPath path, IProgressMonitor monitor) throws CoreException {
+		try {
+			getWorkingCopyDelegate(false).importFromPath(path, monitor);
+			isDataLoaded = true;
+		} catch (CoreException ce) {
+			throw ce;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate importFromPath() " + toString(), e);
+		}
+	}
+	
+	public void importFromRuntime(IRuntime runtime, IProgressMonitor monitor) throws CoreException {
+		try {
+			getWorkingCopyDelegate(false).importFromRuntime(runtime, monitor);
+			isDataLoaded = true;
+		} catch (CoreException ce) {
+			throw ce;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate importFromRuntime() " + toString(), e);
+		}
+	}
+	
+	public String toString() {
+		return "ServerConfigurationWorkingCopy " + getId();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerListener.java
new file mode 100644
index 0000000..a08c22f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerListener.java
@@ -0,0 +1,110 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.*;
+import org.eclipse.wst.server.core.util.ServerResourceAdapter;
+/**
+ * Listens for messages from the servers. This class keeps
+ * track of server instances current state and any clients
+ * that are waiting to run on the server. 
+ */
+public class ServerListener extends ServerResourceAdapter implements IServerListener {
+	// static instance
+	protected static ServerListener listener;
+
+	/**
+	 * ServerListener constructor comment.
+	 */
+	private ServerListener() {
+		super();
+	}
+	
+	/**
+	 * Get the static instance.
+	 *
+	 * @return org.eclipse.wst.server.core.internal.plugin.ServerListener
+	 */
+	public static ServerListener getInstance() {
+		if (listener == null)
+			listener = new ServerListener();
+		return listener;
+	}
+	
+	/**
+	 * Called when the server configuration's sync state changes.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void configurationSyncStateChange(IServer server) { }
+
+	/**
+	 * Notification when the server state has changed.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void serverStateChange(IServer server) { }
+
+	/**
+	 * Notification when the server state has changed.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void modulesChanged(IServer server) { }
+
+	/**
+	 * Notification when the state of a module has changed.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void moduleStateChange(IServer server, IModule module) { }
+
+	/**
+	 * Called when the server isRestartNeeded() property changes.
+	 *
+	 * @param instance org.eclipse.wst.server.core.model.IServer
+	 */
+	public void restartStateChange(IServer server) {
+		/*if (server.isRestartNeeded() == false)
+			return;
+		
+		byte state = server.getServerState();
+		if (state != IServer2.SERVER_STARTED && state != IServer2.SERVER_STARTED_DEBUG && state != IServer.SERVER_STARTED_PROFILE)
+			return;
+	
+		if (ServerCore.getServerPreferences().isAutoRestarting()) {
+			try {
+				server.restart();
+			} catch (CoreException e) {
+				Trace.trace(Trace.SEVERE, "Error restarting server", e);
+			}
+		}*/
+	}
+
+	/**
+	 * A new resource has been added.
+	 *
+	 * @param event org.eclipse.wst.server.core.model.IServerResource
+	 */
+	public void serverAdded(IServer server) {
+		server.addServerListener(this);
+	}
+
+	/**
+	 * A existing resource has been removed.
+	 *
+	 * @param event org.eclipse.wst.server.core.model.IServerResource
+	 */
+	public void serverRemoved(IServer server) {
+		server.removeServerListener(this);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerMonitor.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerMonitor.java
new file mode 100644
index 0000000..5a344c9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerMonitor.java
@@ -0,0 +1,113 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerMonitor;
+import org.eclipse.wst.server.core.model.IServerMonitorDelegate;
+import org.eclipse.wst.server.core.model.IServerPort;
+/**
+ * 
+ */
+public class ServerMonitor implements IServerMonitor {
+	private IConfigurationElement element;
+	private IServerMonitorDelegate delegate;
+
+	/**
+	 * Monitor constructor comment.
+	 */
+	public ServerMonitor(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * Returns the id of this default server.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+
+	/*
+	 * @see IMonitor#getDescription()
+	 */
+	public String getDescription() {
+		return element.getAttribute("description");
+	}
+
+	/*
+	 * @see IMonitor#getLabel()
+	 */
+	public String getName() {
+		String label = element.getAttribute("name");
+		if (label == null)
+			return "n/a";
+		else
+			return label;
+	}
+
+	/*
+	 * @see IMonitor#getDelegate()
+	 */
+	public IServerMonitorDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IServerMonitorDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate" + toString() + ": " + e.getMessage());
+			}
+		}
+		return delegate;
+	}
+
+	/**
+	 * Start monitoring the given port, and return the port number to
+	 * tunnel requests through.
+	 * @param port
+	 * @return
+	 */
+	public int startMonitoring(IServer server, IServerPort port, int monitorPort) throws CoreException {
+		try {
+			return getDelegate().startMonitoring(server, port, monitorPort);
+		} catch (CoreException ce) {
+			throw ce;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+			return -1;
+		}
+	}
+
+	/**
+	 * Stop monitoring the given port.
+	 * @param port
+	 */
+	public void stopMonitoring(IServer server, IServerPort port) {
+		try {
+			getDelegate().stopMonitoring(server, port);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+	}
+
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return "Monitor[" + getId() + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerMonitorManager.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerMonitorManager.java
new file mode 100644
index 0000000..d39b383
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerMonitorManager.java
@@ -0,0 +1,362 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.*;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IMonitorableServer;
+import org.eclipse.wst.server.core.model.IServerPort;
+/**
+ * 
+ */
+public class ServerMonitorManager implements IServerMonitorManager {
+	private static final String MONITOR_DATA_FILE = "monitors.xml";
+	
+	protected static ServerMonitorManager instance;
+
+	protected List ports = new ArrayList(); 
+	protected IServerMonitor monitor;
+	
+	class MonitoredPort implements IMonitoredServerPort {
+		protected IServer server;
+		protected IServerPort port;
+		protected int newPort = -1;
+		protected String[] content;
+		public boolean started;
+		
+		public MonitoredPort(IServer server, IServerPort port, int newPort, String[] content) {
+			this.server = server;
+			this.port = port;
+			this.newPort = newPort;
+			this.content = content;
+		}
+		
+		public MonitoredPort(IMemento memento) {
+			load(memento);
+		}
+		
+		public IServer getServer() {
+			return server;
+		}
+		
+		public IServerPort getServerPort() {
+			return port;
+		}
+		
+		public int getMonitorPort() {
+			return newPort;
+		}
+		
+		public void setMonitorPort(int p) {
+			newPort = p;
+		}
+		
+		public String[] getContentTypes() {
+			return content;
+		}
+		
+		public boolean isStarted() {
+			return started;
+		}
+		
+		protected void setStarted(boolean s) {
+			started = s;
+		}
+		
+		public boolean equals(Object obj) {
+			if (!(obj instanceof MonitoredPort))
+				return false;
+			MonitoredPort mp = (MonitoredPort) obj;
+			if (!mp.server.equals(server))
+				return false;
+			if (!mp.port.equals(port))
+				return false;
+			if (newPort != mp.newPort)
+				return false;
+			if (content == null && mp.content != null)
+				return false;
+			if (content != null && mp.content == null)
+				return false;
+			if (content != null) {
+				int size = content.length;
+				if (size != mp.content.length)
+					return false;
+				for (int i = 0; i < size; i++)
+					if (!content[i].equals(mp.content[i]))
+						return false;
+			}
+			return true;
+		}
+		
+		protected boolean canSave() {
+			return (port.getId() != null);
+		}
+		
+		protected void save(IMemento memento) {
+			memento.putString("serverId", server.getId());
+			if (newPort != -1)
+				memento.putString("port", newPort + "");
+			memento.putString("portId", port.getId());
+			memento.putBoolean("started", started);
+			
+			if (content != null) {
+				StringBuffer sb = new StringBuffer();
+				int size = content.length;
+				for (int i = 0; i < size; i++) {
+					if (i > 0)
+						sb.append(",");
+					sb.append(content[i]);
+				}
+				memento.putString("contentTypes", sb.toString());
+			}
+		}
+		
+		protected void load(IMemento memento) {
+			String serverId = memento.getString("serverId");
+			server = ServerCore.getResourceManager().getServer(serverId);
+			if (server == null)
+				throw new RuntimeException("Server could not be found: " + serverId + " " + server);
+			String newPortStr = memento.getString("port");
+			if (newPortStr != null && newPortStr.length() > 0)
+				newPort = Integer.parseInt(newPortStr);
+			String portId = memento.getString("portId");
+			
+			IMonitorableServer ms = (IMonitorableServer) server.getDelegate();
+			Iterator iterator = ms.getServerPorts().iterator();
+			while (port == null && iterator.hasNext()) {
+				IServerPort sp = (IServerPort) iterator.next();
+				if (sp.getId() != null && sp.getId().equals(portId))
+					port = sp;
+			}
+			if (port == null)
+				throw new RuntimeException("Could not relocate port: " + serverId + " " + server + " " + portId);
+			
+			String s = memento.getString("contentTypes");
+			if (s != null)
+				content = ServerPlugin.tokenize(s, ",");
+			
+			Boolean b = memento.getBoolean("started");
+			if (b != null && b.booleanValue()) {
+				try {
+					newPort = monitor.startMonitoring(server, port, newPort);
+					started = true;
+				} catch (CoreException e) {
+					Trace.trace(Trace.WARNING, "Could not restart server monitor", e);
+				}
+			}
+		}
+	}
+
+	public ServerMonitorManager() {
+		List monitors = ServerCore.getServerMonitors();
+		if (!monitors.isEmpty())
+			monitor = (IServerMonitor) monitors.get(0);
+		
+		instance = this;
+		loadMonitors();
+	}
+	
+	public static ServerMonitorManager getInstance() {
+		if (instance == null)
+			new ServerMonitorManager();
+		return instance;
+	}
+	
+	public static void shutdown() {
+		if (instance == null)
+			return;
+		instance.saveMonitors();
+	}
+
+	/**
+	 * Returns the monitor that is currently being used.
+	 *  
+	 * @return
+	 */
+	public IServerMonitor getCurrentServerMonitor() {
+		return monitor;
+	}
+
+	/**
+	 * Switch to use a different server monitor. All existing monitors will be
+	 * removed from the current monitor and added to the new monitor.
+	 * 
+	 * @param newMonitor
+	 * @throws org.eclipse.core.runtime.CoreException
+	 */
+	public void setServerMonitor(IServerMonitor newMonitor) throws CoreException {
+		throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, "Not implemented yet", null));
+	}
+
+	/**
+	 * Returns the list of ports that are currently being monitored.
+	 *
+	 * @return
+	 */
+	public List getMonitoredPorts(IServer server) {
+		List list = new ArrayList();
+		Iterator iterator = ports.iterator();
+		while (iterator.hasNext()) {
+			MonitoredPort mp = (MonitoredPort) iterator.next();
+			if (mp.server.equals(server))
+				list.add(mp);
+		}
+		return list;
+	}
+
+	/**
+	 * Starts monitoring the given port, and returns the new port # to use that will
+	 * route to the monitored port.
+	 * 
+	 * @param port
+	 * @return
+	 * @throws org.eclipse.core.runtime.CoreException
+	 */
+	public IMonitoredServerPort createMonitor(IServer server, IServerPort port, int monitorPort, String[] content) {
+		if (port == null || monitor == null)
+			return null;
+		
+		//int mport = monitor.startMonitoring(server, port, monitorPort);
+		MonitoredPort mp = new MonitoredPort(server, port, monitorPort, content);
+		ports.add(mp);
+		return mp;
+		/*} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not monitor", e);
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, "Error creating monitor", null));
+		}*/
+	}
+
+	/**
+	 * Stop monitoring the given port. Throws a CoreException if there was a problem
+	 * stopping the monitoring
+	 *
+	 * @param port
+	 * @throws org.eclipse.core.runtime.CoreException
+	 */
+	public void removeMonitor(IMonitoredServerPort port) {
+		if (port == null)
+			return;
+
+		try {
+			ports.remove(port);
+			if (port.isStarted())
+				monitor.stopMonitoring(port.getServer(), port.getServerPort());
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not remove monitor", e);
+		}
+	}
+
+	/**
+	 * Start the monitor. If the msp port is -1, it will be updated to the port that is actually in use.
+	 * 
+	 * @param port
+	 * @throws CoreException
+	 */
+	public void startMonitor(IMonitoredServerPort msp) throws CoreException {
+		if (msp == null || msp.isStarted())
+			return;
+		
+		MonitoredPort port = (MonitoredPort) msp;
+		port.setMonitorPort(monitor.startMonitoring(msp.getServer(), msp.getServerPort(), msp.getMonitorPort()));
+		port.setStarted(true);
+	}
+
+	/**
+	 * Stop monitoring.
+	 * 
+	 * @param port
+	 */
+	public void stopMonitor(IMonitoredServerPort msp) {
+		if (msp == null || !msp.isStarted())
+			return;
+		MonitoredPort port = (MonitoredPort) msp;
+		monitor.stopMonitoring(msp.getServer(), msp.getServerPort());
+		port.setStarted(false);
+	}
+
+	/**
+	 * Returns the mapped port to use when making requests to the given server
+	 * and port number. Returns the existing port number if the port is not being
+	 * monitored.
+	 * 
+	 * @param port
+	 * @return
+	 */
+	public int getMonitoredPort(IServer server, int port, String content) {
+		try {
+			Iterator iterator = ports.iterator();
+			while (iterator.hasNext()) {
+				MonitoredPort mp = (MonitoredPort) iterator.next();
+				if (mp.isStarted() && mp.server.equals(server) && mp.port.getPort() == port) {
+					String[] contentTypes = mp.getContentTypes();
+					boolean found = false;
+					if (content == null || contentTypes != null) {
+						int size = contentTypes.length;
+						for (int i = 0; i < size; i++)
+							if (content.equals(contentTypes[i]))
+								found = true;
+					} else
+						found = true;
+					if (found && mp.newPort != -1)
+						return mp.newPort;
+				}
+			}
+		} catch (Exception e) { }
+		return port;
+	}
+	
+	protected void saveMonitors() {
+		String filename = ServerPlugin.getInstance().getStateLocation().append(MONITOR_DATA_FILE).toOSString();
+		try {
+			XMLMemento memento = XMLMemento.createWriteRoot("monitors");
+
+			Iterator iterator = ports.iterator();
+			while (iterator.hasNext()) {
+				MonitoredPort mp = (MonitoredPort) iterator.next();
+				if (mp.canSave()) {
+					IMemento child = memento.createChild("monitor");
+					mp.save(child);
+				}
+			}
+			
+			memento.saveToFile(filename);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error saving monitor info", e);
+		}
+	}
+	
+	protected void loadMonitors() {
+		Trace.trace(Trace.FINEST, "Loading monitor info");
+		String filename = ServerPlugin.getInstance().getStateLocation().append(MONITOR_DATA_FILE).toOSString();
+		
+		try {
+			IMemento memento = XMLMemento.loadMemento(filename);
+			
+			IMemento[] children = memento.getChildren("monitor");
+			int size = children.length;
+			
+			for (int i = 0; i < size; i++) {
+				try {
+					MonitoredPort mp = new MonitoredPort(children[i]);
+					ports.add(mp);
+				} catch (Exception e) {
+					Trace.trace(Trace.WARNING, "Could not load monitor: " + e);
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not load monitor info: " + e.getMessage());
+		}
+	}
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..5f40d1e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPlugin.java
@@ -0,0 +1,367 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.io.*;
+import java.util.*;
+import java.text.Collator;
+import java.text.DateFormat;
+import java.text.MessageFormat;
+
+import org.eclipse.core.runtime.*;
+import org.osgi.framework.BundleContext;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.*;
+import org.eclipse.wst.server.core.util.*;
+/**
+ * The main server plugin class.
+ */
+public class ServerPlugin extends Plugin {
+	public static final String PROJECT_PREF_FILE = ".serverPreference";
+	
+	protected static final DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
+	protected static int num = 0;
+
+	// singleton instance of this class
+	private static ServerPlugin singleton;
+
+	private static final String TEMP_DATA_FILE = "tmp-data.xml";
+
+	class TempDir {
+		String path;
+		int age;
+	}
+
+	// temp directories - String key to TempDir
+	protected Map tempDirHash;
+
+	/**
+	 * Create the ServerPlugin.
+	 */
+	public ServerPlugin() {
+		super();
+		singleton = this;
+	}
+
+	/**
+	 * Returns the singleton instance of this plugin.
+	 *
+	 * @return org.eclipse.wst.server.core.internal.plugin.ServerPlugin
+	 */
+	public static ServerPlugin getInstance() {
+		return singleton;
+	}
+
+	/**
+	 * Returns the translated String found with the given key.
+	 *
+	 * @param key java.lang.String
+	 * @return java.lang.String
+	 */
+	public static String getResource(String key) {
+		try {
+			return Platform.getResourceString(getInstance().getBundle(), key);
+		} catch (Exception e) {
+			return key;
+		}
+	}
+
+	/**
+	 * Returns the translated String found with the given key,
+	 * and formatted with the given arguments using java.text.MessageFormat.
+	 *
+	 * @param key java.lang.String
+	 * @param arguments java.lang.Object[]
+	 * @return java.lang.String
+	 */
+	public static String getResource(String key, Object[] arguments) {
+		try {
+			String text = getResource(key);
+			return MessageFormat.format(text, arguments);
+		} catch (Exception e) {
+			return key;
+		}
+	}
+	
+	/**
+	 * Returns the translated String found with the given key,
+	 * and formatted with the given arguments using java.text.MessageFormat.
+	 *
+	 * @param key java.lang.String
+	 * @param arguments java.lang.Object[]
+	 * @return java.lang.String
+	 */
+	public static String getResource(String key, String arg) {
+		return getResource(key, new String[] { arg });
+	}
+
+	/**
+	 * Returns a temporary directory that the requestor can use
+	 * throughout it's lifecycle. This is primary to be used by
+	 * server instances for working directories, instance specific
+	 * files, etc.
+	 *
+	 * <p>As long as the same key is used to call this method on
+	 * each use of the workbench, this method directory will return
+	 * the same directory. If the directory is not requested over a
+	 * period of time, the directory may be deleted and a new one
+	 * will be assigned on the next request. For this reason, a
+	 * server instance should request the temp directory on startup
+	 * if it wants to store files there. In all cases, the instance
+	 * should have a backup plan anyway, as this directory may be
+	 * deleted accidentally.</p>
+	 *
+	 * @param key
+	 * @return java.io.File
+	 */
+	public IPath getTempDirectory(String key) {
+		if (key == null)
+			return null;
+	
+		// first, look through hash of current directories
+		IPath statePath = ServerPlugin.getInstance().getStateLocation();
+		try {
+			TempDir dir = (TempDir) tempDirHash.get(key);
+			if (dir != null) {
+				dir.age = 0;
+				return statePath.append(dir.path);
+			}
+		} catch (Exception e) { }
+	
+		// otherwise, create a new directory
+	
+		// find first free directory
+		String path = null;
+		File dir = null;
+		int count = 0;
+		while (dir == null || dir.exists()) {
+			path = "tmp" + count;
+			dir = statePath.append(path).toFile();
+			count ++;
+		}
+	
+		dir.mkdirs();
+	
+		TempDir d = new TempDir();
+		d.path = path;
+		tempDirHash.put(key, d);
+		saveTempDirInfo();
+		return statePath.append(path);
+	}
+	
+	/**
+	 * Remove a temp directory.
+	 * @param key
+	 */
+	public void removeTempDirectory(String key, IProgressMonitor monitor) {
+		if (key == null)
+			return;
+		
+		IPath statePath = ServerPlugin.getInstance().getStateLocation();
+		try {
+			TempDir dir = (TempDir) tempDirHash.get(key);
+			if (dir != null) {
+				tempDirHash.remove(key);
+				saveTempDirInfo();
+				FileUtil.deleteDirectory(statePath.append(dir.path).toFile(), monitor);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not remove temp directory", e);
+		}
+	}
+	
+	/**
+	 * Load the temporary directory information.
+	 */
+	private void loadTempDirInfo() {
+		Trace.trace(Trace.FINEST, "Loading temporary directory information");
+		IPath statePath = ServerPlugin.getInstance().getStateLocation();
+		String filename = statePath.append(TEMP_DATA_FILE).toOSString();
+	
+		tempDirHash = new HashMap();
+		try {
+			IMemento memento = XMLMemento.loadMemento(filename);
+	
+			IMemento[] children = memento.getChildren("temp-directory");
+			int size = children.length;
+			for (int i = 0; i < size; i++) {
+				String key = children[i].getString("key");
+	
+				TempDir d = new TempDir();
+				d.path = children[i].getString("path");
+				d.age = children[i].getInteger("age").intValue();
+				d.age++;
+	
+				tempDirHash.put(key, d);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not load temporary directory information: " + e.getMessage());
+		}
+	}
+
+	/**
+	 * Convenience method for logging.
+	 *
+	 * @param status org.eclipse.core.runtime.IStatus
+	 */
+	public static void log(IStatus status) {
+		getInstance().getLog().log(status);
+	}
+
+	/**
+	 * Save the temporary directory information.
+	 */
+	private void saveTempDirInfo() {
+		// save remaining directories
+		IPath statePath = ServerPlugin.getInstance().getStateLocation();
+		String filename = statePath.append(TEMP_DATA_FILE).toOSString();
+	
+		try {
+			XMLMemento memento = XMLMemento.createWriteRoot("temp-directories");
+	
+			Iterator iterator = tempDirHash.keySet().iterator();
+			while (iterator.hasNext()) {
+				String key = (String) iterator.next();
+				TempDir d = (TempDir) tempDirHash.get(key);
+	
+				if (d.age < 5) {
+					IMemento child = memento.createChild("temp-directory");
+					child.putString("key", key);
+					child.putString("path", d.path);
+					child.putInteger("age", d.age);
+				} else {
+					FileUtil.deleteDirectory(statePath.append(d.path).toFile(), new NullProgressMonitor());
+				}
+			}
+	
+			memento.saveToFile(filename);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save temporary directory information", e);
+		}
+	}
+	
+	protected void initializeDefaultPluginPreferences() {
+		IServerPreferences prefs = ServerCore.getServerPreferences();
+		((ServerPreferences) prefs).setDefaults();
+	}
+
+	/**
+	 * Start up this plug-in.
+	 */
+	public void start(BundleContext context) throws Exception {
+		Trace.trace(Trace.CONFIG, "----->----- Server Core plugin startup ----->-----");
+		super.start(context);
+		
+		initializeDefaultPluginPreferences();
+
+		// load temp directory information
+		loadTempDirInfo();
+		
+		try {
+			Iterator iterator = ServerCore.getStartups().iterator();
+			while (iterator.hasNext()) {
+				IStartup startup = (IStartup) iterator.next();
+				try {
+					startup.startup();
+				} catch (Exception ex) {
+					Trace.trace(Trace.SEVERE, "Startup failed" + startup.toString(), ex);
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error with startup", e);
+		}
+	}
+
+	/**
+	 * Shuts down this plug-in and saves all plug-in state.
+	 */
+	public void stop(BundleContext context) throws Exception {
+		Trace.trace(Trace.CONFIG, "-----<----- Server Core plugin shutdown -----<-----");
+		super.stop(context);
+		
+		ResourceManager.shutdown();
+		ServerMonitorManager.shutdown();
+	}
+
+	/**
+	 * Sort the given elements into alphabetical order. This
+	 * method modifies the original list, but returns the value
+	 * for convenience.
+	 *
+	 * @param list java.util.List
+	 * @return java.util.List
+	 */
+	public static List sortServerResourceList(List list) {
+		if (list == null)
+			return null;
+	
+		Collator collator = Collator.getInstance();
+	
+		int size = list.size();
+		for (int i = 0; i < size - 1; i++) {
+			for (int j = i + 1; j < size; j++) {
+				IElement a = (IElement) list.get(i);
+				IElement b = (IElement) list.get(j);
+				if (collator.compare(a.getName(), b.getName()) > 0) {
+					Object temp = a;
+					list.set(i, b);
+					list.set(j, temp);
+				}
+			}
+		}
+		return list;
+	}
+	
+	public static String[] tokenize(String param, String delim) {
+		List list = new ArrayList();
+		
+		StringTokenizer st = new StringTokenizer(param, delim);
+		while (st.hasMoreTokens()) {
+			String str = st.nextToken();
+			if (str != null && str.length() > 0)
+				list.add(str.trim());
+		}
+
+		String[] s = new String[list.size()];
+		list.toArray(s);
+		return s;
+	}
+
+	protected static List getModuleTypes(IConfigurationElement[] elements) {
+		List list = new ArrayList();
+		if (elements == null)
+			return list;
+	
+		int size = elements.length;
+		for (int i = 0; i < size; i++) {
+			String[] types = tokenize(elements[i].getAttribute("types"), ",");
+			String[] versions = tokenize(elements[i].getAttribute("versions"), ",");
+			int sizeT = types.length;
+			int sizeV = versions.length;
+			for (int j = 0; j < sizeT; j++) {
+				for (int k = 0; k < sizeV; k++) {
+					ModuleType module = new ModuleType(types[j], versions[k]);
+					list.add(module);
+				}
+			}
+		}
+		return list;
+	}
+	
+	public static String generateId() {
+		String s = df.format(new Date()).toString() + num++;
+		s = s.replace(' ', '_');
+		s = s.replace(':', '_');
+		s = s.replace('/', '_');
+		s = s.replace('\\', '_');
+		return s;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPreferences.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPreferences.java
new file mode 100644
index 0000000..b7289fd
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPreferences.java
@@ -0,0 +1,194 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.wst.server.core.*;
+/**
+ * Helper class that stores preference information for server tools.
+ */
+public class ServerPreferences implements IServerPreferences {
+	private static final String PREF_AUTO_RESTART = "auto-restart";
+	private static final String PREF_AUTO_PUBLISH = "auto-publish";
+	private static final String PREF_AUTO_REPAIR_MODULES = "auto-repair-modules";
+	private static final String PREF_PUBLISHER = "publisher";
+	private static final String PREF_CREATE_IN_WORKSPACE = "create-workspace";
+
+	public static final String DEFAULT_PUBLISH_MANAGER = "org.eclipse.wst.server.core.publish.smart";
+	
+	private Preferences preferences;
+
+	/**
+	 * ServerPreference constructor comment.
+	 */
+	public ServerPreferences() {
+		super();
+		preferences = ServerPlugin.getInstance().getPluginPreferences();
+	}
+
+	/**
+	 * Returns whether servers will be automatically restarted when
+	 * required.
+	 *
+	 * @return boolean
+	 */
+	public boolean isAutoRestarting() {
+		return preferences.getBoolean(PREF_AUTO_RESTART);
+	}
+
+	/**
+	 * Returns whether servers will be automatically restarted when
+	 * required.
+	 *
+	 * @return boolean
+	 */
+	public boolean isDefaultAutoRestarting() {
+		return false;
+	}
+
+	/**
+	 * Returns whether publishing should occur before starting the
+	 * server.
+	 *
+	 * @return boolean
+	 */
+	public boolean isAutoPublishing() {
+		return preferences.getBoolean(PREF_AUTO_PUBLISH);
+	}
+	
+	/**
+	 * Returns whether publishing should occur before starting the
+	 * server.
+	 *
+	 * @return boolean
+	 */
+	public boolean isDefaultAutoPublishing() {
+		return true;
+	}
+	
+	/**
+	 * Returns whether servers and configurations should be created in the
+	 * workspace (as opposed to in metadata).
+	 *
+	 * @return boolean
+	 */
+	public boolean isCreateResourcesInWorkspace() {
+		return preferences.getBoolean(PREF_CREATE_IN_WORKSPACE);
+	}
+
+	/**
+	 * Returns whether servers and configurations should be created in the
+	 * workspace (as opposed to in metadata) by default.
+	 *
+	 * @return boolean
+	 */
+	public boolean isDefaultCreateResourcesInWorkspace() {
+		return false;
+	}
+
+	/**
+	 * Set whether servers and configurations should be created in the
+	 * workspace (as opposed to in metadata).
+	 *
+	 * @param boolean
+	 */
+	public void setCreateResourcesInWorkspace(boolean b) {
+		preferences.setValue(PREF_CREATE_IN_WORKSPACE, b);
+		ServerPlugin.getInstance().savePluginPreferences();
+	}
+
+	/**
+	 * Returns the publisher preference.
+	 *
+	 * @return String
+	 */
+	public String getPublishManager() {
+		return preferences.getString(PREF_PUBLISHER);
+	}
+
+	/**
+	 * Returns the publisher preference.
+	 *
+	 * @return String
+	 */
+	public String getDefaultPublishManager() {
+		return DEFAULT_PUBLISH_MANAGER;
+	}
+
+	/**
+	 * Set whether servers will be automatically restarted when
+	 * they need a restart.
+	 *
+	 * @param boolean
+	 */
+	public void setAutoRestarting(boolean value) {
+		preferences.setValue(PREF_AUTO_RESTART, value);
+		ServerPlugin.getInstance().savePluginPreferences();
+	}
+
+	/**
+	 * Set whether publishing should happen before the server starts.
+	 *
+	 * @param boolean
+	 */
+	public void setAutoPublishing(boolean value) {
+		preferences.setValue(PREF_AUTO_PUBLISH, value);
+		ServerPlugin.getInstance().savePluginPreferences();
+	}
+
+	/**
+	 * Sets the publisher to use.
+	 *
+	 * @param String id
+	 */
+	public void setPublishManager(String id) {
+		preferences.setValue(PREF_PUBLISHER, id);
+		ServerPlugin.getInstance().savePluginPreferences();
+	}
+	
+	/**
+	 * Returns whether changes to modules should be automatically fixed
+	 * in the server configurations.
+	 *
+	 * @return byte
+	 */
+	public byte getModuleRepairStatus() {
+		return (byte) preferences.getInt(PREF_AUTO_REPAIR_MODULES);
+	}
+
+	/**
+	 * Returns the default auto module fix state.
+	 *
+	 * @return byte
+	 */
+	public byte getDefaultModuleRepairStatus() {
+		return REPAIR_PROMPT;
+	}
+
+	/**
+	 * Sets whether changes to modules should be automatically fixed
+	 * in the server configurations.
+	 *
+	 * @return byte
+	 */
+	public void setModuleRepairStatus(byte b) {
+		preferences.setValue(PREF_AUTO_REPAIR_MODULES, b);
+		ServerPlugin.getInstance().savePluginPreferences();
+	}
+
+	public void setDefaults() {
+		preferences.setDefault(PREF_AUTO_PUBLISH, isDefaultAutoPublishing());
+		preferences.setDefault(PREF_AUTO_RESTART, isDefaultAutoRestarting());
+		preferences.setDefault(PREF_PUBLISHER, getDefaultPublishManager());
+		preferences.setDefault(PREF_AUTO_REPAIR_MODULES, getDefaultModuleRepairStatus());
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerProjectNature.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerProjectNature.java
new file mode 100644
index 0000000..d1ef989
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerProjectNature.java
@@ -0,0 +1,188 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.*;
+import org.eclipse.wst.server.core.*;
+/**
+ * A nature for projects that contain servers and server configurations.
+ */
+public class ServerProjectNature implements IServerProject, IProjectNature {
+	public static final String BUILDER_ID = ServerCore.PLUGIN_ID + ".builder";
+
+	// the project that contains this nature
+	protected IProject project;
+	
+	protected static List serverProjects = new ArrayList();
+
+	/**
+	 * ServerProjectNature constructor.
+	 */
+	public ServerProjectNature() {
+		super();
+	}
+	
+	/**
+	 * Adds a builder to the build spec for the given project.
+	 */
+	private void addToBuildSpec(String builderID) throws CoreException {
+		if (builderID == null)
+			return;
+
+		IProjectDescription description = getProject().getDescription();
+		ICommand[] commands = description.getBuildSpec();
+	
+		for (int i = 0; i < commands.length; ++i) {
+			if (commands[i].getBuilderName().equals(builderID))
+				return;
+		}
+		// add builder to project
+		ICommand command = description.newCommand();
+		command.setBuilderName(builderID);
+
+		ICommand[] newCommands = new ICommand[commands.length + 1];
+		System.arraycopy(commands, 0, newCommands, 0, commands.length);
+		newCommands[newCommands.length - 1] = command;
+
+		description.setBuildSpec(newCommands);
+		getProject().setDescription(description, new NullProgressMonitor());
+	}
+
+	/**
+	 * Nothing to configure in this nature.
+	 */
+	public void configure() throws CoreException {
+		Trace.trace(Trace.FINEST, "Server project configured");
+
+		// add link builder
+		addToBuildSpec(BUILDER_ID);
+	}
+
+	/**
+	 * Nothing to deconfigure in this nature.
+	 */
+	public void deconfigure() {	}
+
+	/**
+	 * Returns a list of the available folders.
+	 * @return java.util.List
+	 */
+	public List getAvailableFolders() {
+		List list = new ArrayList();
+		list.add(getProject());
+	
+		int t = 0;
+		while (t < list.size()) {
+			try {
+				IContainer container = (IContainer) list.get(t);
+				IResource[] members = container.members();
+				if (members != null) {
+					for (int j = 0; j < members.length; j++) {
+						if (members[j] instanceof IFolder)
+							list.add(members[j]);
+					}
+				}
+			} catch (Exception e) { }
+			t++;
+		}
+		return list;
+	}
+
+	/**
+	 * Returns the project that this nature is associated with.
+	 *
+	 * @return org.eclipse.core.resources.IProject
+	 */
+	public IProject getProject() {
+		return project;
+	}
+
+	/**
+	 * Returns the server configurations that are located in
+	 * this project.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServerConfigurations() {
+		List list = new ArrayList();
+		IResourceManager rm = ServerCore.getResourceManager();
+		Iterator iterator = rm.getServerConfigurations().iterator();
+		while (iterator.hasNext()) {
+			IServerConfiguration config = (IServerConfiguration) iterator.next();
+			IFile file = config.getFile();
+			if (file != null && file.getProject().equals(project))
+				list.add(config);
+		}
+		return list;
+	}
+
+	/**
+	 * Returns the servers that are located in
+	 * this project.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServers() {
+		List list = new ArrayList();
+		IResourceManager rm = ServerCore.getResourceManager();
+		Iterator iterator = rm.getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			IFile file = server.getFile();
+			if (file != null && file.getProject().equals(project))
+				list.add(server);
+		}
+		return list;
+	}
+
+	/**
+	 * Load all of the servers and server configurations.
+	 */
+	public void loadFiles() {
+		Trace.trace(Trace.FINER, "Initial server resource load for " + project.getName(), null);
+		final ResourceManager rm = (ResourceManager) ServerCore.getResourceManager();
+	
+		try {
+			getProject().accept(new IResourceVisitor() {
+				public boolean visit(IResource resource) {
+					try {
+						if (resource instanceof IFile) {
+							IFile file = (IFile) resource;
+							rm.handleNewFile(file, new NullProgressMonitor());
+							return false;
+						} else
+							return true;
+						//return !rm.handleNewServerResource(resource, new NullProgressMonitor());
+					} catch (Exception e) {
+						Trace.trace(Trace.SEVERE, "Error during initial server resource load", e);
+					}
+					return true;
+				}
+			});
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not load server project " + project.getName(), e);
+		}
+	}
+
+	/**
+	 * Sets the project that this nature belongs to.
+	 *
+	 * @param project org.eclipse.core.resources.IProject
+	 */
+	public void setProject(IProject project) {
+		Trace.trace(Trace.FINER, "Server project: " + project);
+		this.project = project;
+		loadFiles();
+		serverProjects.add(project);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerTask.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerTask.java
new file mode 100644
index 0000000..af62a7d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerTask.java
@@ -0,0 +1,201 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * 
+ */
+public class ServerTask implements IServerTask {
+	private IConfigurationElement element;
+	private IServerTaskDelegate delegate;
+	protected ITaskModel model;
+
+	/**
+	 * ServerTask constructor comment.
+	 */
+	public ServerTask(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * Returns the id of this default server.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+
+	/*
+	 * @see IPublishManager#getDescription()
+	 */
+	public String getDescription() {
+		return element.getAttribute("description");
+	}
+
+	/*
+	 * @see IPublishManager#getLabel()
+	 */
+	public String getName() {
+		String label = element.getAttribute("name");
+		if (label == null)
+			return "n/a";
+		else
+			return label;
+	}
+	
+	/**
+	 * Returns the index (ordering) of this task.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			return Integer.parseInt(element.getAttribute("index"));
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+	
+	public ITaskModel getTaskModel() {
+		return model;
+	}
+	
+	public void setTaskModel(ITaskModel taskModel) {
+		this.model = taskModel;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.ITask#canExecute()
+	 */
+	public boolean canExecute() {
+		return true;
+	}
+	
+	/**
+	 * Return the type ids that may be supported.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	public String[] getTypeIds() {
+		try {
+			return ServerPlugin.tokenize(element.getAttribute("typeIds"), ",");
+		} catch (Exception e) {
+			return null;
+		}
+	}
+	
+	/**
+	 * Returns true if the given type (given by the id) can use this task. This
+	 * result is based on the result of the getTypeIds() method.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsType(String id) {
+		if (id == null || id.length() == 0)
+			return false;
+
+		String[] s = getTypeIds();
+		if (s == null)
+			return true;
+		
+		int size = s.length;
+		for (int i = 0; i < size; i++) {
+			if (s[i].endsWith("*")) {
+				if (id.length() >= s[i].length() && id.startsWith(s[i].substring(0, s[i].length() - 1)))
+					return true;
+			} else if (id.equals(s[i]))
+				return true;
+		}
+		return false;
+	}
+
+	/*
+	 * @see IPublishManager#getDelegate()
+	 */
+	public IServerTaskDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IServerTaskDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate" + toString() + ": " + e.getMessage());
+			}
+		}
+		return delegate;
+	}
+	
+	/**
+	 * Lets the task know that it is about to be used. This method should
+	 * be used to clean out any previously cached information, or start to
+	 * create a new cache.
+	 */
+	public void init(IServer server, IServerConfiguration configuration, List[] parents, IModule[] modules) {
+		try {
+			getDelegate().init(server, configuration, parents, modules);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+	}
+	
+	/**
+	 * Returns the status of this task.
+	 * 
+	 * @return byte
+	 */
+	public byte getTaskStatus() {
+		try {
+			return getDelegate().getTaskStatus();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+			return 0;
+		}
+	}
+
+	/**
+	 * Perform the task.
+	 *
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException {
+		try {
+			getDelegate().execute(monitor);
+		} catch (CoreException ce) {
+			Trace.trace(Trace.FINER, "Task error " + toString(), ce);
+			throw ce;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate " + toString() + ": " + e.getMessage());
+		}
+	}
+	
+	public boolean canUndo() {
+		return false;
+	}
+	
+	public void undo() { }
+	
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return "ServerTask[" + getId() + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerType.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerType.java
new file mode 100644
index 0000000..c165baa
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerType.java
@@ -0,0 +1,234 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchManager;
+
+import org.eclipse.wst.server.core.*;
+/**
+ * 
+ */
+public class ServerType implements IServerType {
+	protected IConfigurationElement element;
+
+	/**
+	 * ServerType constructor comment.
+	 */
+	public ServerType(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+	
+	protected IConfigurationElement getElement() {
+		return element;
+	}
+
+	/**
+	 * Returns the id of this factory.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+	
+	public String getName() {
+		return element.getAttribute("name");
+	}
+
+	public String getDescription() {
+		return element.getAttribute("description");
+	}
+	
+	public IRuntimeType getRuntimeType() {
+		return ServerCore.getRuntimeType(element.getAttribute("runtimeTypeId"));
+	}
+	
+	public boolean hasRuntime() {
+		String s = element.getAttribute("runtime");
+		return "true".equals(s);
+	}
+	
+	/**
+	 * Returns the order.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			String o = element.getAttribute("order");
+			return Integer.parseInt(o);
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+	
+	protected ILaunchConfigurationType getLaunchConfigurationType() {
+		String launchConfigId = element.getAttribute("launchConfigId");
+		if (launchConfigId == null)
+			return null;
+		ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
+		return launchManager.getLaunchConfigurationType(launchConfigId);
+	}
+	
+	/**
+	 * Returns true if this server can start or may already be started
+	 * in the given mode, and false if not. Uses the launchMode attribute,
+	 * which may contain the strings "run", "debug", and/or "profile".
+	 * 
+	 * @param launchMode String
+	 * @return boolean
+	 */
+	public boolean supportsLaunchMode(String launchMode) {
+		ILaunchConfigurationType configType = getLaunchConfigurationType();
+		if (configType == null) {
+			String mode = element.getAttribute("launchModes");
+			if (mode == null)
+				return false;
+			else
+				return mode.indexOf(launchMode) >= 0;
+		} else
+			return configType.supportsMode(launchMode);
+	}
+
+	public IServerConfigurationType getServerConfigurationType() {
+		String configurationTypeId = element.getAttribute("configurationTypeId");
+		return ServerCore.getServerConfigurationType(configurationTypeId);
+	}
+	
+	public boolean supportsLocalhost() {
+		String hosts = element.getAttribute("hosts");
+		return (hosts == null || hosts.toLowerCase().indexOf("localhost") >= 0 
+				|| hosts.indexOf("127.0.0.1") >= 0);
+	}
+	
+	public boolean supportsRemoteHosts() {
+		String hosts = element.getAttribute("hosts");
+		return (hosts == null || hosts.toLowerCase().indexOf("remote") >= 0);
+	}
+	
+	public byte getInitialState() {
+		byte state = IServer.SERVER_UNKNOWN;
+		String stateString = element.getAttribute("initialState");
+		if ("stopped".equals(stateString))
+			state = IServer.SERVER_STOPPED;
+		else if ("started".equals(stateString))
+			state = IServer.SERVER_STARTED;
+		return state;
+	}
+
+	/**
+	 * Returns an IStatus message to verify if a server of this type will be able
+	 * to run the module immediately after being created, without any user
+	 * interaction. If OK, this server may be used as a default server. This
+	 * method should return ERROR if the user must supply any information to
+	 * configure the server correctly, or if the module is not supported.
+	 *
+	 * @return org.eclipse.core.resources.IStatus
+	 */
+	/*public IStatus isDefaultAvailable(IModule module) {
+		return null;
+	}*/
+	
+	public byte getServerStateSet() {
+		String stateSet = element.getAttribute("stateSet");
+		if (stateSet == null)
+			return SERVER_STATE_SET_MANAGED;
+		else if (stateSet.toLowerCase().indexOf("attach") >= 0)
+			return SERVER_STATE_SET_ATTACHED;
+		else if (stateSet.toLowerCase().indexOf("publish") >= 0)
+			return SERVER_STATE_SET_PUBLISHED;
+		else
+			return SERVER_STATE_SET_MANAGED;
+	}
+
+	public boolean hasServerConfiguration() {
+		String configurationTypeId = element.getAttribute("configurationTypeId");
+		return configurationTypeId != null && configurationTypeId.length() > 0;
+	}
+	
+	public boolean isMonitorable() {
+		return "true".equalsIgnoreCase(element.getAttribute("monitorable"));
+	}
+	
+	public boolean isTestEnvironment() {
+		return "true".equalsIgnoreCase(element.getAttribute("testEnvironment"));
+	}
+	
+	public IServerWorkingCopy createServer(String id, IFile file, IRuntime runtime) {
+		if (id == null || id.length() == 0)
+			id = ServerPlugin.generateId();
+		ServerWorkingCopy swc = new ServerWorkingCopy(id, file, runtime, this);
+		swc.setDefaults();
+		return swc;
+	}
+
+	public IServerWorkingCopy createServer(String id, IFile file, IProgressMonitor monitor) throws CoreException {
+		if (id == null || id.length() == 0)
+			id = ServerPlugin.generateId();
+		
+		IRuntime runtime = null;
+		if (hasRuntime()) {
+			// look for existing runtime
+			IRuntimeType runtimeType = getRuntimeType();
+			List list = ServerCore.getResourceManager().getRuntimes(runtimeType);
+			if (!list.isEmpty()) {
+				runtime = (IRuntime) list.get(0);
+			} else {
+				// create runtime
+				try {
+					IRuntimeWorkingCopy runtimeWC = runtimeType.createRuntime(id + "-runtime");
+					ServerUtil.setRuntimeDefaultName(runtimeWC);
+					runtime = runtimeWC;
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Couldn't create runtime", e);
+				}
+			}
+		}
+
+		ServerWorkingCopy swc = new ServerWorkingCopy(id, file, runtime, this);
+		ServerUtil.setServerDefaultName(swc);
+		if (runtime != null)
+			swc.setRuntime(runtime);
+		
+		IServerConfigurationWorkingCopy config = null;
+		if (hasServerConfiguration()) {
+			if (runtime != null)
+				config = getServerConfigurationType().importFromRuntime(id + "-config", file, runtime, monitor);
+			if (config == null)
+				config = getServerConfigurationType().createServerConfiguration(id + "-config", file, monitor);
+			ServerUtil.setServerConfigurationDefaultName(config);
+			if (config != null)
+				swc.setServerConfiguration(config);
+		}
+		
+		swc.setDefaults();
+		
+		return swc;
+	}
+
+	/**
+	 * Return a string representation of this object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return "ServerType[" + getId() + "]";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerWorkingCopy.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerWorkingCopy.java
new file mode 100644
index 0000000..0d883a5
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerWorkingCopy.java
@@ -0,0 +1,249 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.beans.PropertyChangeListener;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IServerDelegate;
+import org.eclipse.wst.server.core.model.IServerWorkingCopyDelegate;
+/**
+ * 
+ */
+public class ServerWorkingCopy extends Server implements IServerWorkingCopy {
+	protected Server server;
+	protected WorkingCopyHelper wch;
+	
+	protected IServerWorkingCopyDelegate workingCopyDelegate;
+	
+	// working copy
+	public ServerWorkingCopy(Server server) {
+		super(server.getFile());
+		this.server = server;
+		
+		map = new HashMap(server.map);
+		wch = new WorkingCopyHelper(this);
+		resolve();
+	}
+	
+	// creation
+	public ServerWorkingCopy(String id, IFile file, IRuntime runtime, IServerType serverType) {
+		super(id, file, runtime, serverType);
+		//server = this;
+		wch = new WorkingCopyHelper(this);
+	}
+
+	public boolean isWorkingCopy() {
+		return true;
+	}
+	
+	public IServer getOriginal() {
+		return server;
+	}
+	
+	public IServerWorkingCopy getWorkingCopy() {
+		return this;
+	}
+
+	public void setAttribute(String attributeName, int value) {
+		wch.setAttribute(attributeName, value);
+	}
+
+	public void setAttribute(String attributeName, boolean value) {
+		wch.setAttribute(attributeName, value);
+	}
+
+	public void setAttribute(String attributeName, String value) {
+		wch.setAttribute(attributeName, value);
+	}
+
+	public void setAttribute(String attributeName, List value) {
+		wch.setAttribute(attributeName, value);
+	}
+
+	public void setAttribute(String attributeName, Map value) {
+		wch.setAttribute(attributeName, value);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServerWorkingCopy#setName(java.lang.String)
+	 */
+	public void setName(String name) {
+		setAttribute(PROP_NAME, name);
+	}
+	
+	public void setLocked(boolean b) {
+		setAttribute(PROP_LOCKED, b);
+	}
+
+	public void setPrivate(boolean b) {
+		setAttribute(PROP_PRIVATE, b);
+	}
+
+	public void setHostname(String host) {
+		setAttribute(PROP_HOSTNAME, host);
+	}
+	
+	public void setServerConfiguration(IServerConfiguration config) {
+		this.configuration = config;
+		if (configuration == null)
+			setAttribute(CONFIGURATION_ID, (String)null);
+		else
+			setAttribute(CONFIGURATION_ID, configuration.getId());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServerWorkingCopy#isDirty()
+	 */
+	public boolean isDirty() {
+		return wch.isDirty();
+	}
+
+	public void release() {
+		wch.release();
+		dispose();
+		if (server != null)
+			server.release(this);
+	}
+	
+	public IServerDelegate getDelegate() {
+		return getWorkingCopyDelegate();
+	}
+	
+	public IServerWorkingCopyDelegate getWorkingCopyDelegate() {
+		if (workingCopyDelegate == null && serverType != null) {
+			try {
+				IConfigurationElement element = ((ServerType) serverType).getElement();
+				workingCopyDelegate = (IServerWorkingCopyDelegate) element.createExecutableExtension("workingCopyClass");
+				workingCopyDelegate.initialize((IServerState) this);
+				workingCopyDelegate.initialize((IServerWorkingCopy) this);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create delegate " + toString(), e);
+			}
+		}
+		return workingCopyDelegate;
+	}
+	
+	public void dispose() {
+		super.dispose();
+		if (workingCopyDelegate != null)
+			workingCopyDelegate.dispose();
+	}
+	
+	public IServer save(IProgressMonitor monitor) throws CoreException {
+		if (wch.isReleased())
+			return null;
+		if (server == null) {
+			server = new Server(file);
+			server.setServerState(((ServerType)serverType).getInitialState());
+		}
+		server.setInternal(this);
+		server.doSave(monitor);
+		wch.setDirty(false);
+		release();
+		return server;
+	}
+	
+	public IServer save(IProgressMonitor monitor, boolean release) throws CoreException {
+		if (wch.isReleased())
+			return null;
+		if (server == null) {
+			server = new Server(file);
+			server.setServerState(((ServerType)serverType).getInitialState());
+		}
+		server.setInternal(this);
+		server.doSave(monitor);
+		wch.setDirty(false);
+		if (release)
+			release();
+		return server;
+	}
+	
+	public IServer saveAll(IProgressMonitor monitor) throws CoreException {
+		if (runtime != null && runtime.isWorkingCopy()) {
+			IRuntimeWorkingCopy wc = (IRuntimeWorkingCopy) runtime;
+			wc.save(monitor);
+		}
+		
+		if (configuration != null && configuration.isWorkingCopy()) {
+			IServerConfigurationWorkingCopy wc = (IServerConfigurationWorkingCopy) configuration;
+			wc.save(monitor);
+		}
+		
+		return save(monitor);
+	}
+
+	/**
+	 * Add a property change listener to this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void addPropertyChangeListener(PropertyChangeListener listener) {
+		wch.addPropertyChangeListener(listener);
+	}
+	
+	/**
+	 * Remove a property change listener from this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void removePropertyChangeListener(PropertyChangeListener listener) {
+		wch.removePropertyChangeListener(listener);
+	}
+	
+	/**
+	 * Fire a property change event.
+	 */
+	public void firePropertyChangeEvent(String propertyName, Object oldValue, Object newValue) {
+		wch.firePropertyChangeEvent(propertyName, oldValue, newValue);
+	}
+	
+	public void setRuntime(IRuntime runtime) {
+		this.runtime = runtime;
+		if (runtime != null)
+			setAttribute(RUNTIME_ID, runtime.getId());
+		else
+			setAttribute(RUNTIME_ID, (String)null);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServer#modifyModule(org.eclipse.wst.server.core.model.IModule)
+	 */
+	public void modifyModules(IModule[] add, IModule[] remove,IProgressMonitor monitor) throws CoreException {
+		try {
+			getWorkingCopyDelegate().modifyModules(add, remove, monitor);
+		} catch (CoreException ce) {
+			throw ce;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate modifyModule() " + toString(), e);
+		}
+	}
+
+	public void setDefaults() {
+		try {
+			getWorkingCopyDelegate().setDefaults();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error calling delegate setDefaults() " + toString(), e);
+		}
+	}
+	
+	public String toString() {
+		return "ServerWorkingCopy " + getId();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/SmartPublisher.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/SmartPublisher.java
new file mode 100644
index 0000000..22bf246
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/SmartPublisher.java
@@ -0,0 +1,79 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.wst.server.core.resources.*;
+/**
+ * "Smart" publisher that only publishes files that have been
+ * modified or changed on the server. Deletes files that are no
+ * longer in the workbench.
+ */
+public class SmartPublisher extends AbstractPublisher {
+	/**
+	 * SmartPublisher constructor comment.
+	 */
+	public SmartPublisher() {
+		super();
+	}
+
+	/**
+	 * Returns true if the remote resource should be deleted, and false
+	 * if it should be left on the server.
+	 *
+	 * @return boolean
+	 * @param option int
+	 */
+	public boolean shouldDelete(IModuleResource resource, IPath path, IRemoteResource remote, long resourceTimestamp, long remoteTimestamp) {
+		Trace.trace(Trace.FINEST, "shouldDelete: " + resource + " " + path + " " + remote);
+		Trace.trace(Trace.FINEST, "  " + (resource instanceof IModuleFolder) + " " + (remote instanceof IRemoteFolder));
+		if (resource == null)
+			return true;
+		
+		if (resource instanceof IModuleFolder && !(remote instanceof IRemoteFolder))
+			return true;
+		else if (!(resource instanceof IModuleFolder) && remote instanceof IRemoteFolder)
+			return true;
+		
+		return false;
+	}
+
+	/**
+	 * Returns true if the resource should be published, and false
+	 * if it should be left on the server.
+	 *
+	 * @return boolean
+	 * @param option int
+	 */
+	public boolean shouldPublish(IModuleResource resource, IPath path, IRemoteResource remote, long resourceTimestamp, long remoteTimestamp) {
+		Trace.trace(Trace.FINEST, "shouldPublish: " + resource + " " + path + " " + remote);
+		Trace.trace(Trace.FINEST, "  " + (resource instanceof IModuleFolder) + " " + (remote instanceof IRemoteFolder));
+		Trace.trace(Trace.FINEST, "  " + resourceTimestamp + " " + remoteTimestamp);
+		// publish if the file doesn't exist on the remote side
+		if (remote == null)
+			return true;
+		
+		// publish if the file has changed in the IDE
+		if (resourceTimestamp == IRemoteResource.TIMESTAMP_UNKNOWN || resource.getTimestamp() != resourceTimestamp)
+			return true;
+		
+		// publish if the file has changed on the server
+		if (remoteTimestamp == IRemoteResource.TIMESTAMP_UNKNOWN || remote.getTimestamp() != remoteTimestamp)
+			return true;
+		
+		if (resource instanceof IModuleFolder && !(remote instanceof IRemoteFolder))
+			return true;
+		else if (!(resource instanceof IModuleFolder) && remote instanceof IRemoteFolder)
+			return true;
+		
+		return false;
+	}
+}
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..0c561f2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Trace.java
@@ -0,0 +1,117 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import org.eclipse.wst.server.core.ServerCore;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+/**
+ * Helper class to route trace output.
+ */
+public class Trace {
+	public static int CONFIG = 0;
+	public static int INFO = 1;
+	public static int WARNING = 2;
+	public static int SEVERE = 3;
+	public static int FINER = 4;
+	public static int FINEST = 5;
+	
+	public static int RESOURCES = 6;
+	public static int EXTENSION_POINT = 7;
+	public static int LISTENERS = 8;
+	public static int RUNTIME_TARGET = 9;
+
+	private static final String[] levelNames = new String[] {
+		"CONFIG   ", "INFO     ", "WARNING  ", "SEVERE   ", "FINER    ", "FINEST   ",
+		"RESOURCES", "EXTENSION", "LISTENERS", "TARGET   "};
+	private static final String spacer = "                                   ";
+
+	private static final SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm.ss.SSS");
+
+	protected static int pluginLength = -1;
+
+	/**
+	 * Trace constructor comment.
+	 */
+	private Trace() {
+		super();
+	}
+
+	/**
+	 * Trace the given text.
+	 *
+	 * @param s java.lang.String
+	 */
+	public static void trace(int level, String s) {
+		trace(level, s, null);
+	}
+
+	/**
+	 * Trace the given message and exception.
+	 *
+	 * @param s java.lang.String
+	 * @param t java.lang.Throwable
+	 */
+	public static void trace(int level, String s, Throwable t) {
+		trace(ServerCore.PLUGIN_ID, level, s, t);
+	}
+
+	/**
+	 * Trace the given message and exception.
+	 *
+	 * @param s java.lang.String
+	 * @param t java.lang.Throwable
+	 */
+	public static void trace(String pluginId, int level, String s, Throwable t) {
+		if (pluginId == null || s == null)
+			return;
+
+		if (!ServerPlugin.getInstance().isDebugging())
+			return;
+		
+		StringBuffer sb = new StringBuffer(pluginId);
+		if (pluginId.length() > pluginLength)
+			pluginLength = pluginId.length();
+		else if (pluginId.length() < pluginLength)
+			sb.append(spacer.substring(0, pluginLength - pluginId.length()));
+		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();
+	}
+
+	/**
+	 * Trace the given text.
+	 *
+	 * @param s java.lang.String
+	 */
+	public static void trace(String s) {
+		trace(s, null);
+	}
+
+	/**
+	 * Trace the given message and exception.
+	 *
+	 * @param s java.lang.String
+	 * @param t java.lang.Throwable
+	 */
+	public static void trace(String s, Throwable t) {
+		trace(FINER, s, t);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/WorkingCopyHelper.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/WorkingCopyHelper.java
new file mode 100644
index 0000000..0dac711
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/WorkingCopyHelper.java
@@ -0,0 +1,178 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+/**
+ * 
+ */
+public class WorkingCopyHelper {
+	protected Base base;
+	protected boolean isDirty;
+	protected boolean isReleased;
+	
+	// property change listeners
+	private transient List propertyListeners;
+
+	public WorkingCopyHelper(Base base) {
+		this.base = base;
+	}
+
+	public void setAttribute(String attributeName, int value) {
+		if (isReleased)
+			throw new RuntimeException("Model has already been saved or released");
+		int current = base.getAttribute(attributeName, 0);
+		if (current != 0 && current == value)
+			return;
+
+		isDirty = true;
+		base.map.put(attributeName, Integer.toString(value));
+		firePropertyChangeEvent(attributeName, new Integer(current), new Integer(value));
+	}
+
+	public void setAttribute(String attributeName, boolean value) {
+		if (isReleased)
+			throw new RuntimeException("Model has already been saved or released");
+		boolean current = base.getAttribute(attributeName, false);
+
+		isDirty = true;
+		base.map.put(attributeName, Boolean.toString(value));
+		firePropertyChangeEvent(attributeName, new Boolean(current), new Boolean(value));
+	}
+	
+	public void setAttribute(String attributeName, String value) {
+		if (isReleased)
+			throw new RuntimeException("Model has already been saved or released");
+		String current = base.getAttribute(attributeName, (String)null);
+		if (current != null && current.equals(value))
+			return;
+
+		isDirty = true;
+		if (value == null)
+			base.map.remove(attributeName);
+		else
+			base.map.put(attributeName, value);
+		firePropertyChangeEvent(attributeName, current, value);
+	}
+	
+	public void setAttribute(String attributeName, List value) {
+		if (isReleased)
+			throw new RuntimeException("Model has already been saved or released");
+		List current = base.getAttribute(attributeName, (List)null);
+		if (current != null && current.equals(value))
+			return;
+
+		isDirty = true;
+		if (value == null)
+			base.map.remove(attributeName);
+		else
+			base.map.put(attributeName, value);
+		firePropertyChangeEvent(attributeName, current, value);
+	}
+
+	public void setAttribute(String attributeName, Map value) {
+		if (isReleased)
+			throw new RuntimeException("Model has already been saved or released");
+		Map current = base.getAttribute(attributeName, (Map)null);
+		if (current != null && current.equals(value))
+			return;
+
+		isDirty = true;
+		if (value == null)
+			base.map.remove(attributeName);
+		else
+			base.map.put(attributeName, value);
+		firePropertyChangeEvent(attributeName, current, value);
+	}
+	
+	public void setName(String name) {
+		setAttribute(Base.PROP_NAME, name);
+	}
+	
+	public void setLocked(boolean b) {
+		setAttribute(Base.PROP_LOCKED, b);
+	}
+
+	public void setPrivate(boolean b) {
+		setAttribute(Base.PROP_PRIVATE, b);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.IServerWorkingCopy#isDirty()
+	 */
+	public boolean isDirty() {
+		return isDirty;
+	}
+	
+	public boolean isReleased() {
+		return isReleased;
+	}
+
+	public void release() {
+		if (isReleased)
+			return;
+		isReleased = true;
+		isDirty = false;
+	}
+
+	/**
+	 * Add a property change listener to this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void addPropertyChangeListener(PropertyChangeListener listener) {
+		if (propertyListeners == null)
+			propertyListeners = new ArrayList();
+		propertyListeners.add(listener);
+	}
+	
+	/**
+	 * Remove a property change listener from this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void removePropertyChangeListener(PropertyChangeListener listener) {
+		if (propertyListeners != null)
+			propertyListeners.remove(listener);
+	}
+	
+	/**
+	 * Fire a property change event.
+	 */
+	public void firePropertyChangeEvent(String propertyName, Object oldValue, Object newValue) {
+		if (propertyListeners == null)
+			return;
+	
+		PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
+		try {
+			Iterator iterator = propertyListeners.iterator();
+			while (iterator.hasNext()) {
+				try {
+					PropertyChangeListener listener = (PropertyChangeListener) iterator.next();
+					listener.propertyChange(event);
+				} catch (Exception e) {
+					Trace.trace("Error firing property change event", e);
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace("Error in property event", e);
+		}
+	}
+	
+	protected void setDirty(boolean dirty) {
+		isDirty = dirty;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/XMLMemento.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/XMLMemento.java
new file mode 100644
index 0000000..a412930
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/XMLMemento.java
@@ -0,0 +1,450 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.internal;
+
+import java.io.*;
+import java.util.*;
+import java.net.URL;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+import javax.xml.parsers.*;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+/**
+ * A Memento is a class independent container for persistence
+ * info.  It is a reflection of 3 storage requirements.
+ *
+ * 1)   We need the ability to persist an object and restore it.  
+ * 2)   The class for an object may be absent.  If so we would 
+ *      like to skip the object and keep reading. 
+ * 3)   The class for an object may change.  If so the new class 
+ *      should be able to read the old persistence info.
+ *
+ * We could ask the objects to serialize themselves into an 
+ * ObjectOutputStream, DataOutputStream, or Hashtable.  However 
+ * all of these approaches fail to meet the second requirement.
+ *
+ * Memento supports binary persistance with a version ID.
+ */
+public final class XMLMemento implements IMemento {
+	private Document factory;
+	private Element element;
+
+	/**
+	 * Answer a memento for the document and element.  For simplicity
+	 * you should use createReadRoot and createWriteRoot to create the initial
+	 * mementos on a document.
+	 */
+	public XMLMemento(Document doc, Element el) {
+		factory = doc;
+		element = el;
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public IMemento createChild(String type) {
+		Element child = factory.createElement(type);
+		element.appendChild(child);
+		return new XMLMemento(factory, child);
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public IMemento createChild(String type, String id) {
+		Element child = factory.createElement(type);
+		child.setAttribute(TAG_ID, id);
+		element.appendChild(child);
+		return new XMLMemento(factory, child);
+	}
+
+	/**
+	 * Create a Document from a Reader and answer a root memento for reading 
+	 * a document.
+	 */
+	protected static XMLMemento createReadRoot(Reader reader) {
+		Document document = null;
+		try {
+			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+			DocumentBuilder parser = factory.newDocumentBuilder();
+			document = parser.parse(new InputSource(reader));
+			Node node = document.getFirstChild();
+			if (node instanceof Element)
+				return new XMLMemento(document, (Element) node);
+		} catch (ParserConfigurationException e) {
+		} catch (IOException e) {
+		} catch (SAXException e) {
+		} finally {
+			try {
+				reader.close();
+			} catch (Exception e) { }
+		}
+		return null;
+	}
+	
+	/**
+	 * Answer a root memento for writing a document.
+	 */
+	public static XMLMemento createWriteRoot(String type) {
+		Document document;
+		try {
+			document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+			Element element = document.createElement(type);
+			document.appendChild(element);
+			return new XMLMemento(document, element);            
+		} catch (ParserConfigurationException e) {
+			throw new Error(e);
+		}
+	}
+	
+	/**
+	 * @see IMemento.
+	 */
+	public IMemento getChild(String type) {
+		// Get the nodes.
+		NodeList nodes = element.getChildNodes();
+		int size = nodes.getLength();
+		if (size == 0)
+			return null;
+	
+		// Find the first node which is a child of this node.
+		for (int nX = 0; nX < size; nX ++) {
+			Node node = nodes.item(nX);
+			if (node instanceof Element) {
+				Element element2 = (Element)node;
+				if (element2.getNodeName().equals(type))
+					return new XMLMemento(factory, element2);
+			}
+		}
+	
+		// A child was not found.
+		return null;
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public IMemento [] getChildren(String type) {
+		// Get the nodes.
+		NodeList nodes = element.getChildNodes();
+		int size = nodes.getLength();
+		if (size == 0)
+			return new IMemento[0];
+	
+		// Extract each node with given type.
+		ArrayList list = new ArrayList(size);
+		for (int nX = 0; nX < size; nX ++) {
+			Node node = nodes.item(nX);
+			if (node instanceof Element) {
+				Element element2 = (Element)node;
+				if (element2.getNodeName().equals(type))
+					list.add(element2);
+			}
+		}
+	
+		// Create a memento for each node.
+		size = list.size();
+		IMemento [] results = new IMemento[size];
+		for (int x = 0; x < size; x ++) {
+			results[x] = new XMLMemento(factory, (Element)list.get(x));
+		}
+		return results;
+	}
+
+	/**
+	 * Return the contents of this memento as a byte array.
+	 *
+	 * @return byte[]
+	 */
+	public byte[] getContents() throws IOException {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		save(out);
+		return out.toByteArray();
+	}
+
+	/**
+	 * Returns an input stream for writing to the disk with a local locale.
+	 *
+	 * @return java.io.InputStream
+	 */
+	public InputStream getInputStream() throws IOException {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		save(out);
+		return new ByteArrayInputStream(out.toByteArray());
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public Float getFloat(String key) {
+		Attr attr = element.getAttributeNode(key);
+		if (attr == null)
+			return null; 
+		String strValue = attr.getValue();
+		try {
+			return new Float(strValue);
+		} catch (NumberFormatException e) {
+			return null;
+		}
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public String getId() {
+		return element.getAttribute(TAG_ID);
+	}
+	
+	/**
+	 * @see IMemento.
+	 */
+	public String getName() {
+		return element.getNodeName();
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public Integer getInteger(String key) {
+		Attr attr = element.getAttributeNode(key);
+		if (attr == null)
+			return null; 
+		String strValue = attr.getValue();
+		try {
+			return new Integer(strValue);
+		} catch (NumberFormatException e) {
+			return null;
+		}
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public String getString(String key) {
+		Attr attr = element.getAttributeNode(key);
+		if (attr == null)
+			return null; 
+		return attr.getValue();
+	}
+	
+	public List getNames() {
+		NamedNodeMap map = element.getAttributes();
+		int size = map.getLength();
+		List list = new ArrayList();
+		for (int i = 0; i < size; i++) {
+			Node node = map.item(i);
+			String name = node.getNodeName();
+			list.add(name);
+		}
+		return list;
+	}
+
+	/**
+	 * Loads a memento from the given filename.
+	 *
+	 * @param in java.io.InputStream
+	 * @return org.eclipse.ui.IMemento
+	 * @exception java.io.IOException
+	 */
+	public static IMemento loadMemento(InputStream in) {
+		return createReadRoot(new InputStreamReader(in));
+	}
+	
+	/**
+	 * Loads a memento from the given filename.
+	 *
+	 * @param in java.io.InputStream
+	 * @return org.eclipse.ui.IMemento
+	 * @exception java.io.IOException
+	 */
+	public static IMemento loadCorruptMemento(InputStream in) {
+		Document document = null;
+		try {
+			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+			DocumentBuilder parser = factory.newDocumentBuilder();
+			document = parser.parse(in);
+			Node node = document.getFirstChild();
+			if (node instanceof Element)
+				return new XMLMemento(document, (Element) node);
+		} catch (ParserConfigurationException e) {
+		} catch (IOException e) {
+		} catch (SAXException e) {
+		} finally {
+			try {
+				in.close();
+			} catch (Exception e) { }
+		}
+		return null;
+	}
+
+	/**
+	 * Loads a memento from the given filename.
+	 *
+	 * @param filename java.lang.String
+	 * @return org.eclipse.ui.IMemento
+	 * @exception java.io.IOException
+	 */
+	public static IMemento loadMemento(String filename) throws IOException {
+		return XMLMemento.createReadRoot(new FileReader(filename));
+	}
+
+	/**
+	 * Loads a memento from the given filename.
+	 *
+	 * @param url java.net.URL
+	 * @return org.eclipse.ui.IMemento
+	 * @exception java.io.IOException
+	 */
+	public static IMemento loadMemento(URL url) throws IOException {
+		return XMLMemento.createReadRoot(new InputStreamReader(url.openStream()));
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	private void putElement(Element element2) {
+		NamedNodeMap nodeMap = element2.getAttributes();
+		int size = nodeMap.getLength();
+		for (int i = 0; i < size; i++){
+			Attr attr = (Attr)nodeMap.item(i);
+			putString(attr.getName(),attr.getValue());
+		}
+		
+		NodeList nodes = element2.getChildNodes();
+		size = nodes.getLength();
+		for (int i = 0; i < size; i ++) {
+			Node node = nodes.item(i);
+			if (node instanceof Element) {
+				XMLMemento child = (XMLMemento)createChild(node.getNodeName());
+				child.putElement((Element)node);
+			}
+		}
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public void putFloat(String key, float f) {
+		element.setAttribute(key, String.valueOf(f));
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public void putInteger(String key, int n) {
+		element.setAttribute(key, String.valueOf(n));
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public void putMemento(IMemento memento) {
+		XMLMemento xmlMemento = (XMLMemento) memento;
+		putElement(xmlMemento.element);
+	}
+
+	/**
+	 * @see IMemento.
+	 */
+	public void putString(String key, String value) {
+		if (value == null)
+			return;
+		element.setAttribute(key, value);
+	}
+
+	/**
+	 * Save this Memento to a Writer.
+	 */
+	public void save(Writer writer) throws IOException {
+		Result result = new StreamResult(writer);
+		Source source = new DOMSource(factory);
+		try {
+			Transformer transformer = TransformerFactory.newInstance().newTransformer();
+			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+			transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2");
+			transformer.transform(source, result);
+		} catch (Exception e) {
+			throw (IOException) (new IOException().initCause(e));
+		}
+	}
+	
+	/**
+	 * Save this Memento to a Writer.
+	 */
+	public void save(OutputStream os) throws IOException {
+		Result result = new StreamResult(os);
+		Source source = new DOMSource(factory);
+		try {
+			Transformer transformer = TransformerFactory.newInstance().newTransformer();
+			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+			transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2");
+			transformer.transform(source, result);
+		} catch (Exception e) {
+			throw (IOException) (new IOException().initCause(e));
+		}
+	}
+
+	/**
+	 * Saves the memento to the given file.
+	 *
+	 * @param filename java.lang.String
+	 * @exception java.io.IOException
+	 */
+	public void saveToFile(String filename) throws IOException {
+		Writer w = null;
+		try {
+			w = new FileWriter(filename);
+			save(w);
+		} catch (IOException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new IOException(e.getLocalizedMessage());
+		} finally {
+			if (w != null) {
+				try {
+					w.close();
+				} catch (Exception e) { }
+			}
+		}
+	}
+	
+	public String saveToString() throws IOException {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		save(out);
+		return out.toString("UTF-8");
+	}
+	
+	/*
+	 * @see IMemento#getBoolean(String)
+	 */
+	public Boolean getBoolean(String key) {
+		Attr attr = element.getAttributeNode(key);
+		if (attr == null)
+			return null;
+		String strValue = attr.getValue();
+		if ("true".equalsIgnoreCase(strValue))
+			return new Boolean(true);
+		else
+			return new Boolean(false);
+	}
+
+	/*
+	 * @see IMemento#putBoolean(String, boolean)
+	 */
+	public void putBoolean(String key, boolean value) {
+		element.setAttribute(key, value ? "true" : "false");
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IClientDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IClientDelegate.java
new file mode 100644
index 0000000..00b6d39
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IClientDelegate.java
@@ -0,0 +1,45 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.wst.server.core.IServer;
+/**
+ * A launchable client is a client side application or test
+ * harness that can be launched (run) against a resource
+ * running on a server.
+ * 
+ * <p>This is the implementation of a launchableClient
+ * extension point.</p>
+ */
+public interface IClientDelegate {
+	/**
+	 * Returns true if this launchable can be run by this client.
+	 * 
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param launchable org.eclipse.wst.server.core.model.ILaunchable
+	 * @param launchMode String
+	 * @return boolean
+	 */
+	public boolean supports(IServer server, ILaunchable launchable, String launchMode);
+
+	/**
+	 * Opens or executes on the launchable.
+	 * 
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param launchable org.eclipse.wst.server.core.model.ILaunchable
+	 * @param launchMode String
+	 * @param launch org.eclipse.debug.core.ILaunch
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public IStatus launch(IServer server, ILaunchable launchable, String launchMode, ILaunch launch);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ILaunchable.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ILaunchable.java
new file mode 100644
index 0000000..d5a940d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ILaunchable.java
@@ -0,0 +1,25 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * A launchable is a "reference" to a module object. The
+ * module object is the actual resource on the server; the
+ * launchable is the information necessary to access that
+ * resource. Examples may include HTTP requests and JNDI names.
+ */
+public interface ILaunchable {
+	/**
+	 * Returns the id of this launchable.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getId();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ILaunchableAdapterDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ILaunchableAdapterDelegate.java
new file mode 100644
index 0000000..600a508
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ILaunchableAdapterDelegate.java
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.server.core.IServer;
+/**
+ * This interface, typically implemented by the server
+ * code, converts from an IModuleObject to an
+ * ILaunchable.
+ * 
+ * <p>This is the implementation of a launchableAdapter
+ * extension point.</p>
+ */
+public interface ILaunchableAdapterDelegate {
+	/**
+	 * Returns a launchable object from this module object.
+	 * 
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param moduleObject org.eclipse.wst.server.core.model.IModuleObject
+	 * @param org.eclipse.wst.server.core.model.ILaunchable
+	 * @exception org.eclipse.core.runtime.CoreException
+	 */
+	public ILaunchable getLaunchable(IServer server, IModuleObject moduleObject) throws CoreException;
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModule.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModule.java
new file mode 100644
index 0000000..66710eb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModule.java
@@ -0,0 +1,103 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.wst.server.core.IModuleType;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+/**
+ * A resource (typically a project or folder) that can be deployed to a server.
+ * This interface will be subclassed to provide further information about the
+ * content.
+ */
+public interface IModule extends IModuleType {
+	/**
+	 * Returns a unique memento to distinguish this module
+	 * from all other module instances on a server.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId();
+
+	/**
+	 * Returns an IStatus that validates the contents of this module.
+	 * If there is an error that should block the server from starting,
+	 * (e.g. major errors) it should be returned from this method. This
+	 * method can also be used to return warning for such things as an
+	 * open (and dirty) editor.
+	 *
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public IStatus validate();
+
+	/**
+	 * Returns an IStatus that is used to determine if this object can
+	 * be published to the server. Should return an error if there is a
+	 * major problem with the resources, or can be used to return warnings
+	 * on unsaved files, etc.
+	 *
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public IStatus canPublish();
+
+	/**
+	 * Returns the base level resources for this module.
+	 *
+	 * @return IModuleResource[]
+	 */
+	public IModuleResource[] members() throws CoreException;
+
+	/**
+	 * Returns the name of this module.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getName();
+
+	/**
+	 * Returns the id of the factory that created this module.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getFactoryId();
+
+	/**
+	 * Returns true if this module currently exists, and false if it has
+	 * been deleted or moved and is no longer represented by this module.
+	 *
+	 * @return boolean
+	 */
+	public boolean exists();
+
+	/**
+	 * Add a listener for child module that are added/removed from this
+	 * module.
+	 * 
+	 * @param listener org.eclipse.wst.server.core.model.IModuleListener
+	 */
+	public void addModuleListener(IModuleListener listener);
+
+	/**
+	 * Add a listener for child modules that are added/removed from this
+	 * module.
+	 * 
+	 * @param listener org.eclipse.wst.server.core.model.IModuleListener
+	 */
+	public void removeModuleListener(IModuleListener listener);
+
+	/**
+	 * Returns the child modules of this module.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getChildModules();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleEvent.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleEvent.java
new file mode 100644
index 0000000..9ab6cb0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleEvent.java
@@ -0,0 +1,50 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * An event fired when a module changes.
+ */
+public interface IModuleEvent {
+	/**
+	 * Returns the module that has been changed.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IModule
+	 */
+	public IModule getModule();
+
+	/**
+	 * Returns true if this module's settings have changed.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isChanged();
+
+	/**
+	 * Returns any child modules that have been added.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getAddedChildModules();
+
+	/**
+	 * Returns any child modules that have been changed.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getChangedChildModules();
+
+	/**
+	 * Returns any child modules that have been removed.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getRemovedChildModules();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleEventsListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleEventsListener.java
new file mode 100644
index 0000000..6e8a7fb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleEventsListener.java
@@ -0,0 +1,23 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * 
+ */
+public interface IModuleEventsListener {
+	/**
+	 * A module or factory has been changed as specified in the event.
+	 *
+	 * @param factoryEvent org.eclipse.wst.server.core.model.IModuleFactoryEvent[]
+	 * @param event org.eclipse.wst.server.core.model.IModuleEvent[]
+	 */
+	public void moduleEvents(IModuleFactoryEvent[] factoryEvent, IModuleEvent[] event);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleFactoryDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleFactoryDelegate.java
new file mode 100644
index 0000000..8876317
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleFactoryDelegate.java
@@ -0,0 +1,51 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import java.util.List;
+/**
+ * 
+ */
+public interface IModuleFactoryDelegate {
+	/**
+	 * Gets a module from a memento.
+	 * 
+	 * @param memento java.lang.String
+	 * @return org.eclipse.wst.server.core.model.IModule
+	 */
+	public IModule getModule(String memento);
+
+	/**
+	 * Return all modules that are available to be added
+	 * to servers. This method might look through projects
+	 * to find modules or may return modules from
+	 * other sources.
+	 *
+	 * @return java.util.List
+	 */
+	public List getModules();
+	
+	/**
+	 * Add a listener for modules that are added/removed from this
+	 * factory.
+	 * 
+	 * @param listener org.eclipse.wst.server.core.model.IModuleFactoryListener
+	 */
+	public void addModuleFactoryListener(IModuleFactoryListener listener);
+
+	/**
+	 * Add a listener for modules that are added/removed from this
+	 * factory.
+	 * 
+	 * @param listener org.eclipse.wst.server.core.model.IModuleFactoryListener
+	 */
+	public void removeModuleFactoryListener(IModuleFactoryListener listener);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleFactoryEvent.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleFactoryEvent.java
new file mode 100644
index 0000000..6ba835c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleFactoryEvent.java
@@ -0,0 +1,36 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * An event fired when a module factory changes.
+ */
+public interface IModuleFactoryEvent {
+	/**
+	 * Returns the id of this factory.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getFactoryId();
+
+	/**
+	 * Returns any modules that have been added.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getAddedModules();
+
+	/**
+	 * Returns any modules that have been removed.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getRemovedModules();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleFactoryListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleFactoryListener.java
new file mode 100644
index 0000000..daa24be
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleFactoryListener.java
@@ -0,0 +1,22 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * 
+ */
+public interface IModuleFactoryListener {
+	/**
+	 * Fired when modules have been added or removed from this factory.
+	 *
+	 * @param event org.eclipse.wst.server.core.model.IModuleFactoryEvent
+	 */
+	public void moduleFactoryChanged(IModuleFactoryEvent event);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleListener.java
new file mode 100644
index 0000000..f7d3400
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleListener.java
@@ -0,0 +1,22 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * 
+ */
+public interface IModuleListener {
+	/**
+	 * A module has been changed as specified in the event.
+	 *
+	 * @param event org.eclipse.wst.server.core.model.IModuleEvent
+	 */
+	public void moduleChanged(IModuleEvent event);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleObject.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleObject.java
new file mode 100644
index 0000000..d26f366
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleObject.java
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * A module object is a resource within a module,
+ * which can be launched on the server. Examples of module
+ * objects could include servlets, HTML pages, or EJB beans.
+ */
+public interface IModuleObject {
+	/**
+	 * Returns the id of this module object.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getId();
+
+	/**
+	 * Returns the module that this object is a part of.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.IModule
+	 */
+	public IModule getModule();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleObjectAdapterDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleObjectAdapterDelegate.java
new file mode 100644
index 0000000..63d3cf7
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleObjectAdapterDelegate.java
@@ -0,0 +1,28 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * A module object adapter converts from some view's model
+ * object into a module object that is recognized by the
+ * server.
+ * 
+ * <p>This is the implementation of a moduleObjectAdapter
+ * extension point.</p>
+ */
+public interface IModuleObjectAdapterDelegate {
+	/**
+	 * Converts from a model object to an IModuleObject.
+	 *
+	 * @param obj java.lang.Object
+	 * @return org.eclipse.wst.server.core.model.IModuleObject
+	 */
+	public IModuleObject getModuleObject(Object obj);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleRestartListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleRestartListener.java
new file mode 100644
index 0000000..4235f14
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleRestartListener.java
@@ -0,0 +1,37 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.wst.server.core.IServer;
+/**
+ * This interface is used by a server implementing the IDeployTargetRestartable
+ * interface to broadcast a change of restart state for a project.
+ */
+public interface IModuleRestartListener {
+	/**
+	 * Called when a project's restart state has changed. This state
+	 * lets the user know whether a project should be restarted or
+	 * does not need to be.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param project org.eclipse.core.resources.IProject
+	 */
+	public void moduleRestartStateChange(IServer server, IModule module);
+
+	/**
+	 * Called when a project's state has changed. This means that the
+	 * project has switched it's available/unavailable state.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param project org.eclipse.core.resources.IProject
+	 */
+	public void moduleStateChange(IServer server, IModule module);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleTaskDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleTaskDelegate.java
new file mode 100644
index 0000000..d5547bb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleTaskDelegate.java
@@ -0,0 +1,56 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/**
+ * A module task.
+ * 
+ * <p>This is the implementation of a moduleTask extension point.</p>
+ */
+public interface IModuleTaskDelegate {
+	public static final byte TASK_UNNECESSARY = 0;
+	public static final byte TASK_COMPLETED = 1;
+	public static final byte TASK_READY = 2;
+	public static final byte TASK_PREFERRED = 3;
+	public static final byte TASK_MANDATORY = 4;
+	
+	/**
+	 * Lets the task know that it is about to be used. This method should
+	 * be used to clean out any previously cached information, or start to
+	 * create a new cache.
+	 * 
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param configuration org.eclipse.wst.server.core.model.IServerConfiguration
+	 * @param parents java.util.List
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 */
+	public void init(IServer server, IServerConfiguration configuration, List parents, IModule module);
+
+	/**
+	 * Returns the status of this task.
+	 * 
+	 * @return byte
+	 */
+	public byte getTaskStatus();
+
+	/**
+	 * Perform the task.
+	 *
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException;
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleVisitor.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleVisitor.java
new file mode 100644
index 0000000..eaa7ccd
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IModuleVisitor.java
@@ -0,0 +1,27 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import java.util.List;
+/**
+ * A visitor on a server's modules.
+ */
+public interface IModuleVisitor {
+	/**
+	 * Visit a single module. Returns true to keep visiting, and
+	 * false if it should stop visiting the module. 
+	 * 
+	 * @param parents java.util.List
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return boolean
+	 */
+	public boolean visit(List parents, IModule module);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IMonitorableServer.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IMonitorableServer.java
new file mode 100644
index 0000000..90f4a28
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IMonitorableServer.java
@@ -0,0 +1,24 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import java.util.List;
+/**
+ * 
+ */
+public interface IMonitorableServer {
+	/**
+	 * Returns a list of IServerPorts that this server has.
+	 *
+	 * @return java.util.List
+	 */
+	public abstract List getServerPorts();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IProjectModule.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IProjectModule.java
new file mode 100644
index 0000000..38d61da
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IProjectModule.java
@@ -0,0 +1,39 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.resources.IModuleResourceDelta;
+/**
+ * A module project is a connection between a module and a project in the
+ * workspace. Typically, this is used to listen for resource changes (meaning that
+ * the module may need to be republished) and associate the module with the
+ * project in the UI.
+ */
+public interface IProjectModule extends IModule {
+	/**
+	 * Returns the workbench project that this module is contained in.
+	 * 
+	 * @return org.eclipse.core.resources.IProject
+	 */
+	public IProject getProject();
+
+	/**
+	 * Returns the mapped module resource delta from a
+	 * workbench resource delta. This should convert from the 
+	 * 
+	 * @param delta org.eclipse.core.resources.IResourceDelta
+	 * @return org.eclipse.wst.server.core.IModuleResourceDelta
+	 */
+	public IModuleResourceDelta getModuleResourceDelta(IResourceDelta delta);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IProjectPropertiesListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IProjectPropertiesListener.java
new file mode 100644
index 0000000..41aeda3
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IProjectPropertiesListener.java
@@ -0,0 +1,42 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IServer;
+/**
+ * A project properties listener. Fires events when the default server or
+ * runtime target changes. Note that this interface should be used for
+ * informational purposes only. If (e.g.) you have code that needs to respond
+ * to a specific runtime target, you should use the runtimeTargetHandler
+ * extension point. The extension point will allow your code to be automatically
+ * loaded when necessary (instead of having to preload and add a listener),
+ * will not cause unnecessary plugin loading, and will allow ordering of
+ * setting/unsetting the runtime target. 
+ */
+public interface IProjectPropertiesListener {
+	/**
+	 * Fired when the default server for the project changes.
+	 *
+	 * @param project org.eclipse.core.resources.IProject
+	 * @param server org.eclipse.wst.server.core.IServer
+	 */
+	public void defaultServerChanged(IProject project, IServer server);
+
+	/**
+	 * Fired when the runtime target for the project changes.
+	 *
+	 * @param project org.eclipse.core.resources.IProject
+	 * @param server org.eclipse.wst.server.core.IRuntime
+	 */
+	public void runtimeTargetChanged(IProject project, IRuntime runtime);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IPublishListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IPublishListener.java
new file mode 100644
index 0000000..48eed56
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IPublishListener.java
@@ -0,0 +1,116 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import java.util.List;
+
+import org.eclipse.wst.server.core.IPublishStatus;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+import org.eclipse.wst.server.core.resources.IRemoteResource;
+/**
+ * A publish listener. Can listen to publishing events from a
+ * server control. The usual
+ * 
+ * moduleStateChange() - Fired whenever resources change locally
+ *     that cause the publishing state of anything to change
+ * 
+ * publishStarting() - The overall publish operation is starting
+ *   publishStarted() - The initial connection to the remote machine
+ *   moduleStarting() - This section is fired for each module
+ *                           in the server
+ *     moduleResourcesPublished() - Some resources have been published
+ *     moduleResourcesDeleted() - Some resources have been deleted
+ *   moduleFinished() - This module is done
+ * publishFinished() - The publish operation is over
+ */
+public interface IPublishListener {
+	/**
+	 * Fired when a module on this server needs to be published
+	 * or no longer needs to be published.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param parents java.util.List
+	 * @param module org.eclipse.wst.server.model.IModule
+	 */
+	public void moduleStateChange(IServer server, List parents, IModule module);
+
+	/**
+	 * Global event fired when publishing is about to begin and the modules
+	 * that will be pushed to the remote machine.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param parents java.util.List[]
+	 * @param module org.eclipse.wst.server.model.IModule[]
+	 */
+	public void publishStarting(IServer server, List[] parents, IModule[] module);
+	
+	/**
+	 * Fired to notify the result of opening a connection to the remove machine.
+	 * If the status is an error, the publishing will finish immediately. If not,
+	 * events will be fired for each module in the array.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param status org.eclipse.wst.server.core.IPublishStatus
+	 */
+	public void publishStarted(IServer server, IPublishStatus status);
+
+	/**
+	 * Fired with the module to notify that publishing of this module
+	 * is starting.
+	 * 
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param parents java.util.List
+	 * @param module org.eclipse.wst.server.model.IModule
+	 */
+	public void moduleStarting(IServer server, List parents, IModule module);
+
+	/**
+	 * Fired when module resources are published.
+	 * 
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param parents java.util.List
+	 * @param module org.eclipse.wst.server.model.IModule
+	 * @param published org.eclipse.wst.server.resourcedel.IModuleResource[]
+	 * @param status org.eclipse.wst.server.core.IPublishStatus[]
+	 */
+	public void moduleResourcesPublished(IServer server, List parents, IModule module, IModuleResource[] published, IPublishStatus[] status);
+
+	/**
+	 * Fired when module resources are deleted.
+	 * 
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param parents java.util.List
+	 * @param module org.eclipse.wst.server.model.IModule
+	 * @param deleted org.eclipse.wst.server.resourcedel.IRemoteResource[]
+	 * @param status org.eclipse.wst.server.core.IPublishStatus[]
+	 */
+	public void moduleResourcesDeleted(IServer server, List parents, IModule module, IRemoteResource[] deleted, IPublishStatus[] status);
+
+	/**
+	 * The event is fired when the module has finished publishing,
+	 * and includes the status.
+	 * 
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param parents java.util.List
+	 * @param module org.eclipse.wst.server.model.IModule
+	 * @param status org.eclipse.wst.server.core.IPublishStatus
+	 */
+	public void moduleFinished(IServer server, List parents, IModule module, IPublishStatus status);
+
+	/**
+	 * Publishing has finished. Returns the overall status.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 * @param status org.eclipse.wst.server.core.IPublishStatus
+	 */
+	public void publishFinished(IServer server, IPublishStatus status);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IPublishManagerDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IPublishManagerDelegate.java
new file mode 100644
index 0000000..513ead4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IPublishManagerDelegate.java
@@ -0,0 +1,53 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import java.util.List;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IPublishControl;
+/**
+ * Class that decides whether to publish or delete a given
+ * resource on the remote system.
+ */
+public interface IPublishManagerDelegate {
+	/**
+	 * Sets the publish control, used to obtain information about
+	 * the publishing.
+	 *
+	 * Sets the publish state, used to determine the timestamps
+	 * of the last publishing action.
+	 * 
+	 * Resolve which resources to publish or delete.
+	 *
+	 * @param control org.eclipse.wst.server.model.IPublishControl[]
+	 * @param modules org.eclipse.wst.server.core.model.IModule[]
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 */
+	public void resolve(IPublishControl[] control, IModule[] modules, IProgressMonitor monitor);
+
+	/**
+	 * Returns the list of remote resources to delete from the
+	 * remote system.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return java.util.List
+	 */
+	public List getResourcesToDelete(IModule module);
+
+	/**
+	 * Returns the list of resources to publish to the remote
+	 * system.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return java.util.List
+	 */
+	public List getResourcesToPublish(IModule module);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IPublisher.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IPublisher.java
new file mode 100644
index 0000000..beaf444
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IPublisher.java
@@ -0,0 +1,101 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.wst.server.core.resources.*;
+/**
+ * A publisher for a project within the workbench. This class
+ * knows which resources within the workbench should be published
+ * to the server, and where they go. In addition, it has the
+ * ability to publish files and folders to the server, and delete
+ * them as well.
+ *
+ * <p>The class can assume that the delete(), publish(), and
+ * getRemoteResources() methods will only be called between calls
+ * to publishStart() and publishStop() on the server.
+ * (in other words, they can make use of a shared connection
+ * with the server) Any other methods are valid to be
+ * called at any time.</p>
+ */
+public interface IPublisher {
+	/**
+	 * Returns the mapping of this file on the remote
+	 * system. Return null if this file should not be
+	 * copied to the remote server.
+	 *
+	 * @param resource org.eclipse.wst.server.core.resources.IModuleResource
+	 * @return org.eclipse.core.resources.IPath
+	 */
+	public IPath getMappedLocation(IModuleResource resource);
+
+	/**
+	 * Returns true if there may be any files or folders within
+	 * this container that should be mapped to the remote system.
+	 * Returns false if files within this folder are never copied
+	 * to the remote system.
+	 *
+	 * @param folder org.eclipse.wst.server.core.resources.IModuleFolder
+	 * @return boolean
+	 */
+	public boolean shouldMapMembers(IModuleFolder folder);
+
+	/**
+	 * Returns a list of the remote resources at the root level
+	 * of the remote location. When this method is called, the
+	 * full remote resource tree should be built, which can be
+	 * found from these root resources.
+	 *
+	 * <p>The resources returned may be folders or files. This method
+	 * should not cache data between calls. (in other words, each
+	 * call to this method must result in obtaining the data from
+	 * the server)</p>
+	 *
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @return org.eclipse.wst.server.core.resources.IRemoteResource[]
+	 */
+	public IRemoteResource[] getRemoteResources(IProgressMonitor monitor) throws CoreException;
+
+	/**
+	 * Delete the following resources from the remote machine. The
+	 * remote resource may be a file or folder. This method should
+	 * return an array of simple IStatus (should not be MultiStatus)
+	 * with the result of every deletion attempt.
+	 *
+	 * @param resource org.eclipse.wst.server.resources.IRemoteResource[]
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @return org.eclipse.core.runtime.IStatus[]
+	 */
+	public IStatus[] delete(IRemoteResource[] resource, IProgressMonitor monitor) throws CoreException;
+
+	/**
+	 * Publish the given resources to the remote location. If the
+	 * resource is a folder (IFolder), the folder should be
+	 * recreated on the remote machine. If the resource is just a
+	 * file, it should be copied to the remote machine.  This
+	 * method should return an array of simple IStatus (should
+	 * not be MultiStatus) with the result of every publish
+	 * attempt.
+	 *
+	 * @param resource org.eclipse.wst.server.resources.IModuleResource[]
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @return org.eclipse.core.runtime.IStatus[]
+	 */
+	public IStatus[] publish(IModuleResource[] resource, IProgressMonitor monitor) throws CoreException;
+
+	/**
+	 * Delete the entire module from the remote location.
+	 *
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public IStatus deleteAll(IProgressMonitor monitor) throws CoreException;
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRestartableModule.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRestartableModule.java
new file mode 100644
index 0000000..16ae76b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRestartableModule.java
@@ -0,0 +1,50 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+/**
+ * An interface for a server that allows individual modules
+ * to be restarted while the server is running. This interface
+ * can be implemented by a server to allow it's
+ * individual modules to be restarted one at a time.
+ */
+public interface IRestartableModule extends IServerDelegate {
+	/**
+	 * Returns true if the given module can be restarted.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return boolean
+	 */
+	public boolean canRestartModule(IModule module);
+
+	/**
+	 * Check if the given module is in sync on the server. It should
+	 * return true if the module should be restarted (is out of
+	 * sync) or false if the module does not need to be restarted.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return boolean
+	 */
+	public boolean isModuleRestartNeeded(IModule module);
+
+	/**
+	 * Restart the user module on the server. This method should
+	 * update the module sync state and fire an event for the
+	 * module.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 */
+	public IStatus restartModule(IModule module, IProgressMonitor monitor) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRestartableServer.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRestartableServer.java
new file mode 100644
index 0000000..f69665b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRestartableServer.java
@@ -0,0 +1,26 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * A server may implement this interface if it can
+ * be restarted within the same process. If this interface is
+ * implemented, the restartInProcess() method will be called
+ * when the server is restarted, instead of calling stop(),
+ * waiting, and then starting the server again.
+ */
+public interface IRestartableServer extends IStartableServer {
+	/**
+	 * Restart this server. The server should use the server
+	 * listener to notify progress. It must use the same debug
+	 * flags as was originally passed into the start() method.
+	 */
+	public void restart(String launchMode);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeDelegate.java
new file mode 100644
index 0000000..0e229c0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeDelegate.java
@@ -0,0 +1,29 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.wst.server.core.IRuntime;
+/**
+ * An interface for defining server runtimes.
+ */
+public interface IRuntimeDelegate {
+	public void initialize(IRuntime runtime);
+
+	/**
+	 * Return the validation status of the runtime.
+	 * 
+	 * @return
+	 */
+	public IStatus validate();
+
+	public void dispose();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeLocatorDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeLocatorDelegate.java
new file mode 100644
index 0000000..60b8742
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeLocatorDelegate.java
@@ -0,0 +1,19 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+/**
+ * An interface to allow searching for runtimes.
+ */
+public interface IRuntimeLocatorDelegate {
+	public void searchForRuntimes(IRuntimeLocatorListener listener, IProgressMonitor monitor);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeLocatorListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeLocatorListener.java
new file mode 100644
index 0000000..9f90d0c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeLocatorListener.java
@@ -0,0 +1,17 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.wst.server.core.IRuntime;
+
+public interface IRuntimeLocatorListener {
+	public void runtimeFound(IRuntime runtime);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeTargetHandlerDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeTargetHandlerDelegate.java
new file mode 100644
index 0000000..31b3e65
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeTargetHandlerDelegate.java
@@ -0,0 +1,24 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IRuntime;
+/**
+ * 
+ */
+public interface IRuntimeTargetHandlerDelegate {
+	public void setRuntimeTarget(IProject project, IRuntime runtime, IProgressMonitor monitor) throws CoreException;
+	
+	public void removeRuntimeTarget(IProject project, IRuntime runtime, IProgressMonitor monitor) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeWorkingCopyDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeWorkingCopyDelegate.java
new file mode 100644
index 0000000..c10da3e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IRuntimeWorkingCopyDelegate.java
@@ -0,0 +1,37 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.IRuntimeWorkingCopy;
+/**
+ * An interface for defining server runtimes.
+ */
+public interface IRuntimeWorkingCopyDelegate extends IRuntimeDelegate {
+	public static final byte PRE_SAVE = 0;
+	public static final byte POST_SAVE = 1;
+
+	public void initialize(IRuntimeWorkingCopy runtime);
+	
+	public void setDefaults();
+	
+	/**
+	 * Handle a save of this runtime. This method is called when the runtime
+	 * working copy save() method is invoked and can be used to resolve
+	 * calculated fields or perform other operations related to the changes
+	 * that are being made.
+	 * 
+	 * @param id
+	 * @param monitor
+	 */
+	public void handleSave(byte id, IProgressMonitor monitor);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerConfigurationDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerConfigurationDelegate.java
new file mode 100644
index 0000000..cbd9b8c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerConfigurationDelegate.java
@@ -0,0 +1,43 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/*
+ * A server configuration. Server configurations usually contain
+ * directories (the resources to be run on the server) and configuration
+ * information. (i.e. mime types, data sources, etc.)
+ */
+public interface IServerConfigurationDelegate {
+	/**
+	 * Called when the server is loaded as a model object.
+	 */
+	public void initialize(IServerConfiguration configuration);
+
+	/**
+	 * Called when this server resource has become invalid or no longer
+	 * required and is being deregistered or dicarded. This method can
+	 * be used to remove listeners, etc.
+	 */
+	public void dispose();
+	
+	public void load(IPath path, IProgressMonitor monitor) throws CoreException;
+
+	public void load(IFolder folder, IProgressMonitor monitor) throws CoreException;
+	
+	public void save(IPath path, IProgressMonitor monitor) throws CoreException;
+	
+	public void save(IFolder folder, IProgressMonitor monitor) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerConfigurationWorkingCopyDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerConfigurationWorkingCopyDelegate.java
new file mode 100644
index 0000000..5850796
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerConfigurationWorkingCopyDelegate.java
@@ -0,0 +1,46 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+/**
+ * 
+ */
+public interface IServerConfigurationWorkingCopyDelegate extends IServerConfigurationDelegate {
+	public static final byte PRE_SAVE = 0;
+	public static final byte POST_SAVE = 1;
+
+	/**
+	 * Called when the server is loaded as a model object.
+	 */
+	public void initialize(IServerConfigurationWorkingCopy configuration);
+	
+	public void setDefaults();
+	
+	public void importFromPath(IPath path, IProgressMonitor monitor) throws CoreException;
+
+	public void importFromRuntime(IRuntime runtime, IProgressMonitor monitor) throws CoreException;
+	
+	/**
+	 * Handle a save of this server configuration. This method is called when the server
+	 * configuration working copy save() method is invoked and can be used to resolve
+	 * calculated fields or perform other operations related to the changes
+	 * that are being made.
+	 * 
+	 * @param id
+	 * @param monitor
+	 */
+	public void handleSave(byte id, IProgressMonitor monitor);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerDelegate.java
new file mode 100644
index 0000000..1fb2ce6
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerDelegate.java
@@ -0,0 +1,184 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.IServerState;
+import org.eclipse.wst.server.core.ITask;
+import org.eclipse.wst.server.core.resources.IModuleResourceDelta;
+/**
+ * 
+ */
+public interface IServerDelegate {
+	/**
+	 * Called when the server is loaded as a model object.
+	 */
+	public void initialize(IServerState liveServer);
+
+	/**
+	 * Called when this server resource has become invalid or no longer
+	 * required and is being deregistered or dicarded. This method can
+	 * be used to remove listeners, etc.
+	 */
+	public void dispose();
+	
+	/**
+	 * Returns the publisher that can be used to publish the
+	 * given module. If the module should never
+	 * be published to the server, it may return null.
+	 *
+	 * @param parents java.util.List
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return org.eclipse.wst.server.core.model.IPublisher
+	 */
+	public IPublisher getPublisher(List parents, IModule module);
+
+	/**
+	 * The server configuration has changed. This method should return
+	 * quickly. If any republishing must occur, the relevant in-sync
+	 * methods should return a new value. If the server must be restarted,
+	 * the isRestartNeeded() method should return true.
+	 */
+	public void updateConfiguration();
+
+	/**
+	 * A module resource has changed. This method should return
+	 * quickly. If the server must be restarted to handle the
+	 * change of this file, the isRestartNeeded() method should
+	 * return true and the event should be fired.
+	 *
+	 * @param module org.eclipse.wst.server.core.IModule
+	 * @param delta org.eclipse.wst.server.core.IModuleResourceDelta
+	 */
+	public void updateModule(IModule module, IModuleResourceDelta delta);
+
+	/**
+	 * Methods called to notify that publishing is about to begin.
+	 * This allows the server to open a connection to the server
+	 * or get any global information ready.
+	 *
+	 * <p>This method should not be called directly! Use the
+	 * IServerControl to correctly publish to the server.</p>
+	 *
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public IStatus publishStart(IProgressMonitor monitor);
+
+	/**
+	 * Publish the configuration.
+	 * 
+	 * @param monitor
+	 * @return
+	 */
+	public IStatus publishConfiguration(IProgressMonitor monitor);
+
+	/**
+	 * Methods called to notify that publishing has finished.
+	 * The server can close any open connections to the server
+	 * and do any cleanup operations.
+	 *
+	 * <p>This method should not be called directly! Use the
+	 * IServerControl to correctly publish to the
+	 * server.</p>
+	 *
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public IStatus publishStop(IProgressMonitor monitor);
+	
+	/**
+	 * Returns true if this module can be added to this
+	 * configuration at the current time, and false otherwise.
+	 *
+	 * <p>This method may decide based on the type of module
+	 * or refuse simply due to reaching a maximum number of
+	 * modules or other criteria.</p>
+	 *
+	 * @param add org.eclipse.wst.server.core.model.IModule[]
+	 * @param remove org.eclipse.wst.server.core.model.Module[]
+	 * @return boolean
+	 */
+	public IStatus canModifyModules(IModule[] add, IModule[] remove);
+
+	/**
+	 * Returns the modules that are in this configuration.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getModules();
+	
+	/**
+	 * Returns the current state of the given module. See
+	 * class header for MODULE_XXX constants.
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return byte
+	 */
+	public byte getModuleState(IModule module);
+
+	/**
+	 * Method called when changes to the modules or module factories
+	 * within this configuration occur. Return any necessary commands to repair
+	 * or modify the server configuration in response to these changes.
+	 * 
+	 * @param org.eclipse.wst.server.core.model.IModuleFactoryEvent[]
+	 * @param org.eclipse.wst.server.core.model.IModuleEvent[]
+	 * @return org.eclipse.wst.server.core.model.ITask[]
+	 */
+	public ITask[] getRepairCommands(IModuleFactoryEvent[] factoryEvent, IModuleEvent[] moduleEvent);
+	
+	/**
+	 * Returns the child module(s) of this module. If this
+	 * module contains other modules, it should list those
+	 * modules. If not, it should return an empty list.
+	 *
+	 * <p>This method should only return the direct children.
+	 * To obtain the full module tree, this method may be
+	 * recursively called on the children.</p>
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return java.util.List
+	 */
+	public List getChildModules(IModule module);
+
+	/**
+	 * Returns the parent module(s) of this module. When
+	 * determining if a given project can run on a server
+	 * configuration, this method will be used to find the
+	 * actual module(s) that may be run on the server. For
+	 * instance, a Web module may return a list of Ear
+	 * modules that it is contained in if the server only
+	 * supports configuring Ear modules.
+	 *
+	 * <p>If the module type is not supported, this method
+	 * may return null. If the type is normally supported but there
+	 * is a configuration problem or missing parent, etc., this
+	 * method may fire a CoreException that may then be presented
+	 * to the user.</p>
+	 *
+	 * <p>If it does return valid parent(s), this method should
+	 * always return the topmost parent module(s), even if
+	 * there are a few levels (a heirarchy) of modules.</p>
+	 *
+	 * @param module org.eclipse.wst.server.core.model.IModule
+	 * @return java.util.List
+	 * @throws org.eclipse.core.runtime.CoreException
+	 */
+	public List getParentModules(IModule module) throws CoreException;
+	
+	public void setLaunchDefaults(ILaunchConfigurationWorkingCopy workingCopy);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerLifecycleEventHandler.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerLifecycleEventHandler.java
new file mode 100644
index 0000000..d4aefe8
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerLifecycleEventHandler.java
@@ -0,0 +1,29 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.wst.server.core.IServerLifecycleEvent;
+
+/**
+ * An 
+ */
+public interface IServerLifecycleEventHandler {
+	/**
+	 * Handle module server events.
+	 * 
+	 * true - change has been handled (typically by calling execute() on the task)
+	 *    or task should not be run.
+	 * false - was not handled - let another handler deal with the change.
+	 * 
+	 * @return boolean[]
+	 */
+	public boolean[] handleModuleServerEvents(IServerLifecycleEvent[] events);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerListener.java
new file mode 100644
index 0000000..f0f6866
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerListener.java
@@ -0,0 +1,62 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.wst.server.core.IServer;
+/**
+ * This interface is used by the server to broadcast a change of state.
+ * Usually, the change of state will be caused by some user action,
+ * (e.g. requesting to start a server) however, it is equally fine for
+ * a server to broadcast a change of state through no direct user action.
+ * (e.g. stopping because the server crashed) This information can be
+ * used to inform the user of the change or update the UI.
+ *
+ * <p>Note: The server listener event MUST NOT directly be used to modify
+ * the server's state via one of the server's method. For example, a server
+ * stopped event cannot directly trigger a start(). Doing this may cause
+ * the thread to hang.</p>
+ */
+public interface IServerListener {
+	/**
+	 * Called when the server configuration's sync state changes.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void configurationSyncStateChange(IServer server);
+
+	/**
+	 * Called when the server isRestartNeeded() property changes.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void restartStateChange(IServer server);
+
+	/**
+	 * Notification when the server state has changed.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void serverStateChange(IServer server);
+	
+	/**
+	 * Notification when the state of a module has changed.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void moduleStateChange(IServer server, IModule module);
+	
+	/**
+	 * Called when the modules tree of this server has changed.
+	 *
+	 * @param server org.eclipse.wst.server.IServer
+	 */
+	public void modulesChanged(IServer server);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerLocatorDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerLocatorDelegate.java
new file mode 100644
index 0000000..705e919
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerLocatorDelegate.java
@@ -0,0 +1,19 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+/**
+ * An interface to allow searching for servers.
+ */
+public interface IServerLocatorDelegate {
+	public void searchForServers(IServerLocatorListener listener, IProgressMonitor monitor);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerLocatorListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerLocatorListener.java
new file mode 100644
index 0000000..1b8b2fe
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerLocatorListener.java
@@ -0,0 +1,17 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.wst.server.core.IServer;
+
+public interface IServerLocatorListener {
+	public void serverFound(IServer server);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerMonitorDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerMonitorDelegate.java
new file mode 100644
index 0000000..cc8f913
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerMonitorDelegate.java
@@ -0,0 +1,35 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.wst.server.core.IServer;
+/**
+ * An interface to a TCP/IP monitor.
+ */
+public interface IServerMonitorDelegate {
+	/**
+	 * Start monitoring the given port, and return the port number to
+	 * tunnel requests through. The monitorPort is the new port to use, or
+	 * -1 to pick a random port.
+	 * 
+	 * @param port
+	 * @return
+	 */
+	public int startMonitoring(IServer server, IServerPort port, int monitorPort) throws CoreException;
+
+	/**
+	 * Stop monitoring the given port.
+	 * @param port
+	 */
+	public void stopMonitoring(IServer server, IServerPort port);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerPort.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerPort.java
new file mode 100644
index 0000000..80d9663
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerPort.java
@@ -0,0 +1,58 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * An abstract port on a server.
+ */
+public interface IServerPort {
+	/**
+	 * Return an optional internal id used to identify this port.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getId();
+
+	/**
+	 * Return the name of the port.
+	 * @return java.lang.String
+	 */
+	public String getName();
+
+	/**
+	 * Return the actual port number.
+	 * @return int
+	 */
+	public int getPort();
+
+	/**
+	 * Returns the protocol, e.g. HTTP of this port. Returns null
+	 * if the protocol is unknown.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getProtocol();
+
+	/**
+	 * Returns the content types that this port would normally serve, or null
+	 * if the content is unknown.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	public String[] getContentTypes();
+	
+	/**
+	 * Returns true if this port is an "advanced" port and should not be shown
+	 * to novice users.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isAdvanced();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerResourceListener.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerResourceListener.java
new file mode 100644
index 0000000..76b8777
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerResourceListener.java
@@ -0,0 +1,82 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/**
+ * Listener interface for server and server configuration changes.
+ */
+public interface IServerResourceListener {
+	/**
+	 * A new runtime has been created.
+	 *
+	 * @param runtime org.eclipse.wst.server.core.IRuntime
+	 */
+	public void runtimeAdded(IRuntime runtime);
+
+	/**
+	 * An existing runtime has been updated or modified.
+	 *
+	 * @param runtime org.eclipse.wst.server.core.IRuntime
+	 */
+	public void runtimeChanged(IRuntime runtime);
+
+	/**
+	 * A existing runtime has been removed.
+	 *
+	 * @param runtime org.eclipse.wst.server.core.IRuntime
+	 */
+	public void runtimeRemoved(IRuntime runtime);
+
+	/**
+	 * A new server has been created.
+	 *
+	 * @param server org.eclipse.wst.server.core.IServer
+	 */
+	public void serverAdded(IServer server);
+
+	/**
+	 * An existing server has been updated or modified.
+	 *
+	 * @param server org.eclipse.wst.server.core.IServer
+	 */
+	public void serverChanged(IServer server);
+
+	/**
+	 * A existing server has been removed.
+	 *
+	 * @param server org.eclipse.wst.server.core.IServer
+	 */
+	public void serverRemoved(IServer server);
+	
+	/**
+	 * A new server configuration has been created.
+	 *
+	 * @param serverConfiguration org.eclipse.wst.server.core.IServerConfiguration
+	 */
+	public void serverConfigurationAdded(IServerConfiguration serverConfiguration);
+
+	/**
+	 * An existing server configuration has been updated or modified.
+	 *
+	 * @param serverConfiguration org.eclipse.wst.server.core.IServerConfiguration
+	 */
+	public void serverConfigurationChanged(IServerConfiguration serverConfiguration);
+
+	/**
+	 * A existing configuration has been removed.
+	 *
+	 * @param serverConfiguration org.eclipse.wst.server.core.IServerConfiguration
+	 */
+	public void serverConfigurationRemoved(IServerConfiguration serverConfiguration);
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerTaskDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerTaskDelegate.java
new file mode 100644
index 0000000..5c75ba9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerTaskDelegate.java
@@ -0,0 +1,54 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/**
+ * A server task.
+ * 
+ * <p>This is the implementation of a serverTask extension point.</p>
+ */
+public interface IServerTaskDelegate {
+	public static final byte TASK_UNNECESSARY = 0;
+	public static final byte TASK_COMPLETED = 1;
+	public static final byte TASK_READY = 2;
+	public static final byte TASK_PREFERRED = 3;
+	public static final byte TASK_MANDATORY = 4;
+	
+	/**
+	 * Lets the task know that it is about to be used. This method should
+	 * be used to clean out any previously cached information, or start to
+	 * create a new cache.
+	 * 
+	 * @param server org.eclipse.wst.server.core.IServer
+	 * @param configuration org.eclipse.wst.server.core.IServerConfiguration
+	 * @param parents java.util.List[]
+	 * @param modules org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public void init(IServer server, IServerConfiguration configuration, List[] parents, IModule[] modules);
+
+	/**
+	 * Returns the status of this task.
+	 * 
+	 * @return byte
+	 */
+	public byte getTaskStatus();
+
+	/**
+	 * Perform the task.
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException;
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerWorkingCopyDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerWorkingCopyDelegate.java
new file mode 100644
index 0000000..e4b5783
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IServerWorkingCopyDelegate.java
@@ -0,0 +1,54 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+/**
+ *
+ */
+public interface IServerWorkingCopyDelegate extends IServerDelegate {
+	public static final byte PRE_SAVE = 0;
+	public static final byte POST_SAVE = 1;
+
+	/**
+	 * Called when the server is loaded as a model object.
+	 */
+	public void initialize(IServerWorkingCopy workingCopy);
+
+	public void setDefaults();
+
+	/**
+	 * Add the given module to this configuration. The
+	 * module must exist, should not already be deployed
+	 * within the configuration, and canAddProject()
+	 * should have returned true. The configuration must assume
+	 * any default settings and add the module without any UI.
+	 *
+	 * @param add org.eclipse.wst.server.core.model.IModule[]
+	 * @param remove org.eclipse.wst.server.core.model.IModule[] 
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 */
+	public void modifyModules(IModule[] add, IModule[] remove, IProgressMonitor monitor) throws CoreException;
+
+	/**
+	 * Handle a save of this server. This method is called when the server
+	 * working copy save() method is invoked and can be used to resolve
+	 * calculated fields or perform other operations related to the changes
+	 * that are being made.
+	 * 
+	 * @param id
+	 * @param monitor
+	 */
+	public void handleSave(byte id, IProgressMonitor monitor);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IStartableServer.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IStartableServer.java
new file mode 100644
index 0000000..065b352
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IStartableServer.java
@@ -0,0 +1,62 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * A startable server. This interface just provides the extra methods for starting,
+ * stopping, and terminating the server.
+ */
+public interface IStartableServer extends IServerDelegate {
+	/**
+	 * Return true if the server should be terminated before the workbench
+	 * shutdown and false if not. If the server is not terminated when
+	 * workbench shutdown, then the server should get reconnected
+	 * in the server load when the workbench startsup.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isTerminateOnShutdown();
+
+	/**
+	 * Cleanly shuts down and stops this server. The
+	 * server should return from this method quickly and
+	 * use the server listener to notify shutdown progress.
+	 *
+	 * <p>This method should not be called directly! Use the
+	 * IServerControl to correctly start and register
+	 * the server.</p>
+	 */
+	public void stop();
+	
+	/**
+	 * Terminate the server process(es). This method should only be
+	 * used as a last resort after the stop() method fails to work.
+	 * The server should return from this method quickly and
+	 * use the server listener to notify shutdown progress.
+	 * It MUST terminate the server completely and return it to
+	 * the stopped state.
+	 */
+	public void terminate();
+	
+	/**
+	 * Return the timeout (in ms) that should be used to wa
+	 * 
+	 * @return
+	 */
+	public int getStartTimeout();
+
+	/**
+	 * Return the timeout (in ms) to wait before assuming that the server
+	 * has failed to stop.
+	 *  
+	 * @return
+	 */
+	public int getStopTimeout();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IStartup.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IStartup.java
new file mode 100644
index 0000000..d0abdd0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IStartup.java
@@ -0,0 +1,20 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+/**
+ * An interface for the startup extension point.
+ */
+public interface IStartup {
+	/**
+	 * Called on server core startup.
+	 */
+	public void startup();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IURLProvider.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IURLProvider.java
new file mode 100644
index 0000000..216d3f2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/IURLProvider.java
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.model;
+
+import java.net.URL;
+
+/**
+ * 
+ */
+public interface IURLProvider {
+	/**
+	 * Return the base URL of this module on the server. This method may return
+	 * null if this server does not have a valid configuration or does not contain
+	 * this module. Otherwise, it should return the base URL (e.g. 
+	 * "http://localhost:8080/myProject") regardless of whether the server is
+	 * running or not. The returned URL should not end in a trailing slash.
+	 * 
+	 * <p>If the module is null, the returned URL will just be to the root of
+	 * the server (e.g. "http://localhost:8080")</p>
+	 *
+	 * @param module com.ibm.etools.server.core.model.IModule
+	 * @return java.net.URL
+	 */
+	public URL getModuleRootURL(IModule module);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleFile.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleFile.java
new file mode 100644
index 0000000..defba72
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleFile.java
@@ -0,0 +1,24 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import java.io.InputStream;
+
+import org.eclipse.core.runtime.CoreException;
+/**
+ *
+ */
+public interface IModuleFile extends IModuleResource {
+	/**
+	 * Gets the contents of the file as a stream.
+	 */
+	public InputStream getContents() throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleFolder.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleFolder.java
new file mode 100644
index 0000000..82b26a8
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleFolder.java
@@ -0,0 +1,25 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import org.eclipse.core.runtime.CoreException;
+/**
+ * A remote folder is a remote resource that can have children.
+ */
+public interface IModuleFolder extends IModuleResource {
+	/**
+	 * Returns a list of IModuleResources directly contained
+	 * within this folder.
+	 *
+	 * @return java.util.List
+	 */
+	public IModuleResource[] members() throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleResource.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleResource.java
new file mode 100644
index 0000000..f09a9e1
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleResource.java
@@ -0,0 +1,56 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * A remote resource that has a name, parent, path, and timestamp.
+ */
+public interface IModuleResource {
+	public static final long TIMESTAMP_UNKNOWN = -1;
+
+	/**
+	 * Returns the name of the remote resource.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getName();
+
+	/**
+	 * Returns the module that contains this resource.
+	 */
+	public IModule getModule();
+
+	/**
+	 * Returns the parent folder, or null if we're at the root.
+	 *
+	 * @return org.eclipse.wst.server.model.IRemoteFolder
+	 */
+	public IModuleFolder getParent();
+
+	/**
+	 * Return the path to this resource.
+	 *
+	 * @return org.eclipse.core.runtime.IPath
+	 */
+	public IPath getPath();
+
+	/**
+	 * Returns the timestamp of the remote resource. This timestamp
+	 * does not need to match the local machine's time, but it
+	 * must be constantly increasing with time. (i.e. files with a
+	 * larger timestamp were created later)
+	 *
+	 * @return long
+	 */
+	public long getTimestamp();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleResourceDelta.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleResourceDelta.java
new file mode 100644
index 0000000..3e52516
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IModuleResourceDelta.java
@@ -0,0 +1,51 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import org.eclipse.core.runtime.IPath;
+/**
+ * 
+ */
+public interface IModuleResourceDelta {
+	public static final int NO_CHANGE = 0;
+	public static final int ADDED = 0x1;
+	public static final int REMOVED = 0x2;
+	public static final int CHANGED = 0x4;
+
+	/**
+	 * Returns the path to this resource.
+	 */
+	public IPath getFullPath();
+	
+	/**
+	 * Returns the resource at this location.
+	 */
+	public IModuleResource getResource();
+	
+	/**
+	 * Returns the flags for this change, as defined
+	 * in the class header.
+	 */
+	public int getKind();
+	
+	/**
+	 * 
+	 * 
+	 */
+	public IModuleResourceDelta[] getAffectedChildren();
+	
+	/**
+	 * 
+	 */
+	public IModuleResourceDelta findMember(IPath path);
+	
+	//public void accept(IResourceDeltaVisitor visitor) throws CoreException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IRemoteFolder.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IRemoteFolder.java
new file mode 100644
index 0000000..e790671
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IRemoteFolder.java
@@ -0,0 +1,25 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import java.util.List;
+/**
+ * A remote folder is a remote resource that can have children.
+ */
+public interface IRemoteFolder extends IRemoteResource {
+	/**
+	 * Returns a list of IRemoteResources directly contained
+	 * within this folder.
+	 *
+	 * @return java.util.List
+	 */
+	public List getContents();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IRemoteResource.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IRemoteResource.java
new file mode 100644
index 0000000..c55212d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/IRemoteResource.java
@@ -0,0 +1,50 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import org.eclipse.core.runtime.IPath;
+/**
+ * A remote resource that has a name, parent, path, and timestamp.
+ */
+public interface IRemoteResource {
+	public static final long TIMESTAMP_UNKNOWN = -1;
+
+	/**
+	 * Returns the name of the remote resource.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getName();
+
+	/**
+	 * Returns the parent folder, or null if we're at the root.
+	 *
+	 * @return org.eclipse.wst.server.model.IRemoteFolder
+	 */
+	public IRemoteFolder getParent();
+
+	/**
+	 * Return the path to this resource.
+	 *
+	 * @return org.eclipse.core.runtime.IPath
+	 */
+	public IPath getPath();
+
+	/**
+	 * Returns the timestamp of the remote resource. This timestamp
+	 * does not need to match the local machine's time, but it
+	 * must be constantly increasing with time. (i.e. files with a
+	 * larger timestamp were created later)
+	 *
+	 * @return long
+	 */
+	public long getTimestamp();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ModuleResourceDelta.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ModuleResourceDelta.java
new file mode 100644
index 0000000..7216cc9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ModuleResourceDelta.java
@@ -0,0 +1,82 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+/**
+ * 
+ */
+public class ModuleResourceDelta implements IModuleResourceDelta {
+	protected IModuleResource resource;
+	protected int flags;
+	
+	protected List children;
+	
+	private static final IModuleResourceDelta[] NO_CHILDREN = new ModuleResourceDelta[0];
+	
+	public ModuleResourceDelta(IModuleResource resource, int flags) {
+		this.resource = resource;
+		this.flags = flags;
+	}
+
+	/**
+	 * @see IModuleResourceDelta#getPath()
+	 */
+	public IPath getFullPath() {
+		return resource.getPath();
+	}
+
+	/**
+	 * @see IModuleResourceDelta#getResource()
+	 */
+	public IModuleResource getResource() {
+		return resource;
+	}
+
+	/**
+	 * @see IModuleResourceDelta#getFlags()
+	 */
+	public int getKind() {
+		return flags;
+	}
+	
+	/**
+	 * 
+	 */
+	public void addChild(IModuleResourceDelta delta) {
+		if (children == null)
+			children = new ArrayList(4);
+		children.add(delta);
+	}
+
+	/**
+	 * 
+	 * 
+	 */
+	public IModuleResourceDelta[] getAffectedChildren() {
+		if (children == null || children.size() == 0)
+			return NO_CHILDREN;
+		
+		ModuleResourceDelta[] delta = new ModuleResourceDelta[children.size()];
+		children.toArray(delta);
+		return delta;
+	}
+	
+	/**
+	 * 
+	 */
+	public IModuleResourceDelta findMember(IPath path) {
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ProjectModuleFile.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ProjectModuleFile.java
new file mode 100644
index 0000000..a682ae9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ProjectModuleFile.java
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import java.io.InputStream;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * 
+ */
+public class ProjectModuleFile extends ProjectModuleResource implements IModuleFile {
+	public ProjectModuleFile(IModule module, IModuleFolder parent, IFile file) {
+		super(module, parent, file);
+	}
+
+	/*
+	 * @see IModuleFile#getContents()
+	 */
+	public InputStream getContents() throws CoreException {
+		IFile file = (IFile) getResource();
+		return file.getContents();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ProjectModuleFolder.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ProjectModuleFolder.java
new file mode 100644
index 0000000..49cfbec
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ProjectModuleFolder.java
@@ -0,0 +1,56 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * 
+ */
+public class ProjectModuleFolder extends ProjectModuleResource implements IModuleFolder {
+	public ProjectModuleFolder(IModule module, IModuleFolder parent, IContainer container) {
+		super(module, parent, container);
+	}
+
+	/**
+	 * Returns a list of IModuleResources directly contained
+	 * within this folder.
+	 *
+	 * @return java.util.List
+	 */
+	public IModuleResource[] members() throws CoreException {
+		IContainer container = (IContainer) getResource();
+		IResource[] resources = container.members();
+		if (resources != null) {
+			List list = new ArrayList();
+			
+			int size = resources.length;
+			for (int i = 0; i < size; i++) {
+				IResource res = resources[i];
+				if (res instanceof IContainer) {
+					ProjectModuleFolder pdf = new ProjectModuleFolder(getModule(), this, (IContainer) res);	
+					list.add(pdf);
+				} else if (res instanceof IFile) {
+					ProjectModuleFile pdf = new ProjectModuleFile(getModule(), this, (IFile) res);
+					list.add(pdf);
+				}
+			}
+			
+			IModuleResource[] moduleResources = new IModuleResource[list.size()];
+			list.toArray(moduleResources);
+			return moduleResources;
+		}
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ProjectModuleResource.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ProjectModuleResource.java
new file mode 100644
index 0000000..0e0f827
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/ProjectModuleResource.java
@@ -0,0 +1,97 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * 
+ */
+public class ProjectModuleResource implements IModuleResource {
+	protected IModule module;
+	protected IModuleFolder parent;
+	protected IResource resource;
+
+	public ProjectModuleResource(IModule module, IModuleFolder parent, IResource resource) {
+		this.module = module;
+		this.parent = parent;
+		this.resource = resource;
+	}
+
+	/*
+	 * @see IModuleResource#getName()
+	 */
+	public String getName() {
+		return resource.getName();
+	}
+
+	/*
+	 * @see IModuleResource#getModule()
+	 */
+	public IModule getModule() {
+		return module;
+	}
+
+	/*
+	 * @see IModuleResource#getParent()
+	 */
+	public IModuleFolder getParent() {
+		return parent;
+	}
+
+	/*
+	 * @see IModuleResource#getPath()
+	 */
+	public IPath getPath() {
+		if (parent == null)
+			return new Path(getName());
+		else {
+			IPath path = parent.getPath();
+			return path.append(getName());
+		}
+	}
+
+	public IResource getResource() {
+		return resource;
+	}
+
+	/*
+	 * @see IModuleResource#getTimestamp()
+	 */
+	public long getTimestamp() {
+		return resource.getModificationStamp();
+	}
+
+	/**
+	 * 
+	 */
+	public boolean equals(Object obj) {
+		if (!(obj instanceof ProjectModuleResource))
+			return false;
+		
+		ProjectModuleResource ppr = (ProjectModuleResource) obj;
+		if (ppr.getModule() != module)
+			return false;
+		if (parent == null && ppr.getParent() != null)
+			return false;
+		if (parent != null && !parent.equals(ppr.getParent()))
+			return false;
+		if (resource != null && !resource.equals(ppr.getResource()))
+			return false;
+		return true;
+	}
+	
+	public String toString() {
+		return getPath() + "(" + getTimestamp() + ")";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/RemoteFolder.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/RemoteFolder.java
new file mode 100644
index 0000000..dfdf8af
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/RemoteFolder.java
@@ -0,0 +1,89 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import java.util.*;
+
+import org.eclipse.wst.server.core.internal.Trace;
+/**
+ * An implementation of a remote folder.
+ */
+public class RemoteFolder extends RemoteResource implements IRemoteFolder {
+	protected List children;
+
+	/**
+	 * RemoteFolder constructor comment.
+	 */
+	public RemoteFolder(IRemoteFolder parent, String name, long timestamp) {
+		super(parent, name, timestamp);
+	}
+
+	/**
+	 * 
+	 * @param resource org.eclipse.wst.server.core.model.IRemoteResource
+	 */
+	public void addChild(IRemoteResource resource) {
+		List children2 = getContents();
+		if (!children2.contains(resource))
+			children2.add(resource);
+	}
+
+	/**
+	 * Returns a list of IRemoteResources directly contained
+	 * within this folder.
+	 *
+	 * @return java.util.List
+	 */
+	public List getContents() {
+		if (children == null)
+			children = new ArrayList();
+		return children;
+	}
+	
+	/**
+	 * Output the remote folder to a string
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append(getPath().toString());
+		sb.append("[");
+	
+		boolean first = true;
+		Iterator iterator = getContents().iterator();
+		while (iterator.hasNext()) {
+			IRemoteResource remote = (IRemoteResource) iterator.next();
+			if (!first)
+				sb.append(", ");
+			first = false;
+			sb.append(remote.toString());
+		}
+		sb.append("]");
+		return sb.toString();
+	}
+	
+	/**
+	 * Trace the remote folder's output.
+	 */
+	public void trace(String indent) {
+		Trace.trace(indent + getPath().toString() + " (" + getTimestamp() + ") [");
+	
+		Iterator iterator = getContents().iterator();
+		while (iterator.hasNext()) {
+			IRemoteResource remote = (IRemoteResource) iterator.next();
+			if (remote instanceof RemoteFolder) {
+				((RemoteFolder) remote).trace(indent + "  ");
+			} else
+				Trace.trace(indent + "  " + remote.toString());
+		}
+		Trace.trace(indent + "]");
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/RemoteResource.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/RemoteResource.java
new file mode 100644
index 0000000..23db1bc
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/resources/RemoteResource.java
@@ -0,0 +1,111 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.resources;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+/**
+ * An implementation of a remote resource. The path is the
+ * path of the parent with the resource name appended.
+ */
+public class RemoteResource implements IRemoteResource {
+	protected IRemoteFolder parent;
+	protected String name;
+	protected long timestamp = TIMESTAMP_UNKNOWN;
+
+	/**
+	 * RemoteResource constructor comment.
+	 */
+	public RemoteResource(IRemoteFolder parent, String name, long timestamp) {
+		super();
+		this.parent = parent;
+		this.name = name;
+		this.timestamp = timestamp;
+	}
+
+	/**
+	 * 
+	 * @return boolean
+	 * @param obj java.lang.Object
+	 */
+	public boolean equals(Object obj) {
+		if (!(obj instanceof RemoteResource))
+			return false;
+
+		RemoteResource remote = (RemoteResource) obj;
+		if (name != null && !name.equals(remote.getName()))
+			return false;
+
+		if (parent == null && remote.getParent() != null)
+			return false;
+
+		if (parent != null && !parent.equals(remote.getParent()))
+			return false;
+
+		if (timestamp != remote.getTimestamp())
+			return false;
+
+		return true;
+	}
+
+	/**
+	 * Returns the name of the remote resource.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Returns the parent folder, or null if we're at the root.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IRemoteFolder
+	 */
+	public IRemoteFolder getParent() {
+		return parent;
+	}
+
+	/**
+	 * Return the path to this resource.
+	 *
+	 * @return org.eclipse.core.runtime.IPath
+	 */
+	public IPath getPath() {
+		if (parent == null)
+			return new Path(getName());
+		else {
+			IPath path = parent.getPath();
+			return path.append(getName());
+		}
+	}
+
+	/**
+	 * Returns the timestamp of the remote resource. This timestamp
+	 * does not need to match the local machine's time, but it
+	 * must be constantly increasing with time. (i.e. files with a
+	 * larger timestamp were created later)
+	 *
+	 * @return long
+	 */
+	public long getTimestamp() {
+		return timestamp;
+	}
+
+	/**
+	 * Returns this remote resource as a string.
+	 *
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return getPath().toString() + " (" + getTimestamp() + ")";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/FileUtil.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/FileUtil.java
new file mode 100644
index 0000000..094160b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/FileUtil.java
@@ -0,0 +1,339 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import java.io.*;
+import java.util.zip.*;
+import java.net.URL;
+import org.eclipse.core.runtime.*;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.internal.ServerPlugin;
+import org.eclipse.wst.server.core.internal.Trace;
+/**
+ * Utility class with an assortment of useful file methods.
+ */
+public class FileUtil {
+	// size of the buffer
+	private static final int BUFFER = 10240;
+
+	// the buffer
+	private static byte[] buf = new byte[BUFFER];
+
+	/**
+	 * FileUtil cannot be created. Use static methods.
+	 */
+	private FileUtil() {
+		super();
+	}
+
+	/**
+	 * Copys a directory from a to b.
+	 *
+	 * @param from java.lang.String
+	 * @param to java.lang.String
+	 */
+	public static void copyDirectory(String from, String to, IProgressMonitor monitor) {
+		try {
+			File fromDir = new File(from);
+			File toDir = new File(to);
+	
+			File[] files = fromDir.listFiles();
+	
+			toDir.mkdir();
+	
+			// cycle through files
+			int size = files.length;
+			monitor = ProgressUtil.getMonitorFor(monitor);
+			monitor.beginTask(ServerPlugin.getResource("%copyingTask", new String[] {from, to}), size * 50);
+	
+			for (int i = 0; i < size; i++) {
+				File current = files[i];
+				String fromFile = current.getAbsolutePath();
+				String toFile = to;
+				if (!toFile.endsWith(File.separator))
+					toFile += File.separator;
+				toFile += current.getName();
+				if (current.isFile()) {
+					copyFile(fromFile, toFile);
+					monitor.worked(50);
+				} else if (current.isDirectory()) {
+					monitor.subTask(ServerPlugin.getResource("%copyingTask", new String[] {fromFile, toFile}));
+					copyDirectory(fromFile, toFile, ProgressUtil.getSubMonitorFor(monitor, 50));
+				}
+				if (monitor.isCanceled())
+					return;
+			}
+			monitor.done();
+		} catch (Exception e) {
+			Trace.trace("Error copying directory", e);
+		}
+	}
+
+	/**
+	 * Copy a file from a to b. Closes the input stream after use.
+	 *
+	 * @param in java.io.InputStream
+	 * @param to java.lang.String
+	 */
+	public static 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 new Status(IStatus.OK, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%copyingTask", new String[] {to}), null);
+		} catch (Exception e) {
+			Trace.trace("Error copying file", e);
+			return new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorCopyingFile", new String[] {to, e.getLocalizedMessage()}), e);
+		} finally {
+			try {
+				if (in != null)
+					in.close();
+			} catch (Exception ex) { }
+			try {
+				if (out != null)
+					out.close();
+			} catch (Exception ex) { }
+		}
+	}
+
+	/**
+	 * Copy a file from a to b.
+	 *
+	 * @param from java.lang.String
+	 * @param to java.lang.String
+	 */
+	public static IStatus copyFile(String from, String to) {
+		try {
+			return copyFile(new FileInputStream(from), to);
+		} catch (Exception e) {
+			Trace.trace("Error copying file", e);
+			return new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorCopyingFile", new String[] {to, e.getLocalizedMessage()}), e);
+		}
+	}
+
+	/**
+	 * Copy a file from a to b.
+	 *
+	 * @param from java.net.URL
+	 * @param to java.lang.String
+	 */
+	public static IStatus copyFile(URL from, String to) {
+		try {
+			return copyFile(from.openStream(), to);
+		} catch (Exception e) {
+			Trace.trace("Error copying file", e);
+			return new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorCopyingFile", new String[] {to, e.getLocalizedMessage()}), e);
+		}
+	}
+	/**
+	 * Recursively deletes a directory.
+	 *
+	 * @param dir java.io.File
+	 */
+	public static void deleteDirectory(File dir, IProgressMonitor monitor) {
+		try {
+			if (!dir.exists() || !dir.isDirectory())
+				return;
+	
+			File[] files = dir.listFiles();
+			int size = files.length;
+			monitor = ProgressUtil.getMonitorFor(monitor);
+			monitor.beginTask(ServerPlugin.getResource("%deletingTask", new String[] {dir.getAbsolutePath()}), size * 10);
+	
+			// cycle through files
+			for (int i = 0; i < size; i++) {
+				File current = files[i];
+				if (current.isFile()) {
+					current.delete();
+					monitor.worked(10);
+				} else if (current.isDirectory()) {
+					monitor.subTask(ServerPlugin.getResource("%deletingTask", new String[] {current.getAbsolutePath()}));
+					deleteDirectory(current, ProgressUtil.getSubMonitorFor(monitor, 10));
+				}
+			}
+			dir.delete();
+			monitor.done();
+		} catch (Exception e) {
+			Trace.trace("Error deleting directory " + dir.getAbsolutePath(), e);
+		}
+	}
+
+	/**
+	 * Expand a zip file to a given directory.
+	 *
+	 * @param zipFile java.io.File
+	 * @param dir java.io.File
+	 */
+	public static void expandZip(File zipFile, File dir, IProgressMonitor monitor) {
+		ZipInputStream zis = null;
+	
+		try {
+			// first, count number of items in zip file
+			zis = new ZipInputStream(new FileInputStream(zipFile));
+			int count = 0;
+			while (zis.getNextEntry() != null)
+				count++;
+	
+			monitor = ProgressUtil.getMonitorFor(monitor);
+			monitor.beginTask(ServerPlugin.getResource("%unZippingTask", new String[] {zipFile.getName()}), count);
+			
+			zis = new ZipInputStream(new FileInputStream(zipFile));
+			ZipEntry ze = zis.getNextEntry();
+	
+			FileOutputStream out = null;
+	
+			while (ze != null) {
+				try {
+					monitor.subTask(ServerPlugin.getResource("%expandingTask", new String[] {ze.getName()}));
+					File f = new File(dir, ze.getName());
+	
+					if (ze.isDirectory()) {
+						out = null;
+						f.mkdirs();
+					} else {
+						out = new FileOutputStream(f);
+	
+						int avail = zis.read(buf);
+						while (avail > 0) {
+							out.write(buf, 0, avail);
+							avail = zis.read(buf);
+						}
+					}
+				} catch (FileNotFoundException ex) {
+					Trace.trace("Error extracting " + ze.getName() + " from zip " + zipFile.getAbsolutePath(), ex);
+				} finally {
+					try {
+						if (out != null)
+							out.close();
+					} catch (Exception e) { }
+				}
+				ze = zis.getNextEntry();
+				monitor.worked(1);
+				if (monitor.isCanceled())
+					return;
+			}
+			monitor.done();
+		} catch (Exception e) {
+			Trace.trace("Error expanding zip file " + zipFile.getAbsolutePath(), e);
+		} finally {
+			try {
+				if (zis != null)
+					zis.close();
+			} catch (Exception ex) {
+			}
+		}
+	}
+
+	/**
+	 * Copys a directory from a to b, only modifying as needed
+	 * and deleting old files and directories.
+	 *
+	 * @param from java.lang.String
+	 * @param to java.lang.String
+	 * @param IProgressMonitor
+	 */
+	public static void smartCopyDirectory(String from, String to, IProgressMonitor monitor) {
+		try {
+			File fromDir = new File(from);
+			File toDir = new File(to);
+	
+			File[] fromFiles = fromDir.listFiles();
+			int fromSize = fromFiles.length;
+	
+			monitor = ProgressUtil.getMonitorFor(monitor);
+			monitor.beginTask(ServerPlugin.getResource("%copyingTask", new String[] {from, to}), 550);
+	
+			File[] toFiles = null;
+	
+			// delete old files and directories from this directory
+			if (toDir.exists() && toDir.isDirectory()) {
+				toFiles = toDir.listFiles();
+				int toSize = toFiles.length;
+	
+				// check if this exact file exists in the new directory
+				for (int i = 0; i < toSize; i++) {
+					String name = toFiles[i].getName();
+					boolean isDir = toFiles[i].isDirectory();
+					boolean found = false;
+					for (int j = 0; j < fromSize; j++) {
+						if (name.equals(fromFiles[j].getName()) && isDir == fromFiles[j].isDirectory())
+							found = true;
+					}
+	
+					// delete file if it can't be found or isn't the correct type
+					if (!found) {
+						if (isDir)
+							deleteDirectory(toFiles[i], new NullProgressMonitor());
+						else
+							toFiles[i].delete();
+					}
+					if (monitor.isCanceled())
+						return;
+				}
+			} else {
+				if (toDir.isFile())
+					toDir.delete();
+				toDir.mkdir();
+			}
+			monitor.worked(50);
+	
+			// cycle through files and only copy when it doesn't exist
+			// or is newer
+			toFiles = toDir.listFiles();
+			int toSize = toFiles.length;
+			int dw = 0;
+			if (toSize > 0)
+				dw = 500 / toSize;
+	
+			for (int i = 0; i < fromSize; i++) {
+				File current = fromFiles[i];
+	
+				// check if this is a new or newer file
+				boolean copy = true;
+				if (!current.isDirectory()) {
+					String name = current.getName();
+					long mod = current.lastModified();
+					for (int j = 0; j < toSize; j++) {
+						if (name.equals(toFiles[j].getName()) && mod <= toFiles[j].lastModified())
+							copy = false;
+					}
+				}
+	
+				if (copy) {
+					String fromFile = current.getAbsolutePath();
+					String toFile = to;
+					if (!toFile.endsWith(File.separator))
+						toFile += File.separator;
+					toFile += current.getName();
+					if (current.isFile()) {
+						copyFile(fromFile, toFile);
+						monitor.worked(dw);
+					} else if (current.isDirectory()) {
+						monitor.subTask(ServerPlugin.getResource("%copyingTask", new String[] {fromFile, toFile}));
+						smartCopyDirectory(fromFile, toFile, ProgressUtil.getSubMonitorFor(monitor, dw));
+					}
+				}
+				if (monitor.isCanceled())
+					return;
+			}
+			monitor.worked(500 - dw * toSize);
+			monitor.done();
+		} catch (Exception e) {
+			Trace.trace("Error smart copying directory " + from + " - " + to, e);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/HttpLaunchable.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/HttpLaunchable.java
new file mode 100644
index 0000000..85cf1e7
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/HttpLaunchable.java
@@ -0,0 +1,39 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import java.net.URL;
+
+import org.eclipse.wst.server.core.model.ILaunchable;
+/**
+ *
+ */
+public class HttpLaunchable implements ILaunchable {
+	public static final String ID = "http.launchable";
+
+	private URL url;
+
+	public HttpLaunchable(URL url) {
+		this.url = url;
+	}
+
+	public String getId() {
+		return ID;
+	}
+
+	public URL getURL() {
+		return url;
+	}
+
+	public String toString() {
+		return "HttpLaunchable[id=" + getId() + ", url=" + url.toString() + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/MissingModule.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/MissingModule.java
new file mode 100644
index 0000000..ff6b7c9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/MissingModule.java
@@ -0,0 +1,133 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IModuleListener;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+import org.eclipse.wst.server.core.resources.IModuleResourceDelta;
+/**
+ * A simple IModule that represents a missing or unavailable
+ * module.
+ */
+public class MissingModule implements IModule {
+	protected String name;
+	protected String id;
+
+	public MissingModule(String id, String name) {
+		this.id = id;
+		this.name = name;
+	}
+
+	/*
+	 * @see IModuleProject#getModuleResourceDelta(IResourceDelta)
+	 */
+	public IModuleResourceDelta getModuleResourceDelta(IResourceDelta delta) {
+		return null;
+	}
+
+	/*
+	 * @see IModule#getFactoryId()
+	 */
+	public String getFactoryId() {
+		return "org.eclipse.wst.server.core.missingModuleFactory";
+	}
+
+	/*
+	 * @see IModule#getMemento()
+	 */
+	public String getMemento() {
+		return id + "/" + name;
+	}
+	
+	public String getType() {
+		return "";
+	}
+	
+	public String getVersion() {
+		return "";
+	}
+	
+	/*
+	 * @see IModule#getPublishStatus()
+	 */
+	public IStatus validate() {
+		return null;
+	}
+
+	/*
+	 * @see IModule#getPublishStatus()
+	 */
+	public IStatus canPublish() {
+		return null;
+	}
+
+	/*
+	 * @see IModule#members()
+	 */
+	public IModuleResource[] members() {
+		return new IModuleResource[0];
+	}
+
+	/*
+	 * @see IModule#getName()
+	 */
+	public String getName() {
+		return name;
+	}
+	
+	public String getId() {
+		return id;
+	}
+	
+	/**
+	 * Returns true if this module currently exists, and false if it has
+	 * been deleted or moved and is no longer represented by this module.
+	 *
+	 * @return boolean
+	 */
+	public boolean exists() {
+		return false;
+	}
+	
+	/**
+	 * 
+	 */
+	public boolean equals(Object obj) {
+		if (!(obj instanceof MissingModule))
+			return false;
+
+		MissingModule md = (MissingModule) obj;
+		return (md.getId().equals(id));
+	}
+	
+	/**
+	 * Add a listener for the module.
+	 * 
+	 * @param listener org.eclipse.wst.server.core.model.IModuleListener
+	 */
+	public void addModuleListener(IModuleListener listener) {
+	}
+	
+	/**
+	 * Remove a listener from the module.
+	 * 
+	 * @param listener org.eclipse.wst.server.core.model.IModuleListener
+	 */
+	public void removeModuleListener(IModuleListener listener) {
+	}
+	
+	public IModule[] getChildModules() {
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/MissingModuleFactoryDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/MissingModuleFactoryDelegate.java
new file mode 100644
index 0000000..b98f168
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/MissingModuleFactoryDelegate.java
@@ -0,0 +1,61 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.server.core.internal.Trace;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * 
+ */
+public class MissingModuleFactoryDelegate implements IModuleFactoryDelegate {
+	/*
+	 * @see IModuleFactoryDelegate#getModule(String)
+	 */
+	public IModule getModule(String memento) {
+		if (memento == null)
+			return null;
+		try {
+			int index = memento.indexOf("/");
+			if (index < 0)
+				return null;
+			String id = memento.substring(0, index);
+			String name = memento.substring(index + 1);
+			return new MissingModule(id, name);
+		} catch (Exception e) {
+			Trace.trace("Could not create module: " + e.getMessage());
+		}
+		return null;
+	}
+
+	/*
+	 * @see IModuleFactoryDelegate#getModules()
+	 */
+	public List getModules() {
+		return new ArrayList(0);
+	}
+	
+	/**
+	 * Add a listener to the module factory.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IModuleFactoryListener
+	 */
+	public void addModuleFactoryListener(IModuleFactoryListener listener) { }
+	
+	/**
+	 * Remove a listener from the module factory.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IModuleFactoryListener
+	 */
+	public void removeModuleFactoryListener(IModuleFactoryListener listener) { }
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ModuleEvent.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ModuleEvent.java
new file mode 100644
index 0000000..fec6613
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ModuleEvent.java
@@ -0,0 +1,67 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IModuleEvent;
+/**
+ * 
+ */
+public class ModuleEvent implements IModuleEvent {
+	protected IModule module;
+	protected boolean isChanged;
+	protected IModule[] added;
+	protected IModule[] changed;
+	protected IModule[] removed;
+
+	public ModuleEvent(IModule module, boolean isChanged, IModule[] added, IModule[] changed, IModule[] removed) {
+		this.module = module;
+		this.isChanged = isChanged;
+		this.added = added;
+		this.changed = changed;
+		this.removed = removed;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.server.core.model.IModuleEvent#getModule()
+	 */
+	public IModule getModule() {
+		return module;
+	}
+
+	/**
+	 * @see org.eclipse.wst.server.core.model.IModuleEvent#isChanged()
+	 */
+	public boolean isChanged() {
+		return isChanged;
+	}
+
+	/**
+	 * @see org.eclipse.wst.server.core.model.IModuleEvent#getAddedChildModules()
+	 */
+	public IModule[] getAddedChildModules() {
+		return added;
+	}
+
+	/**
+	 * @see org.eclipse.wst.server.core.model.IModuleEvent#getModifiedChildModules()
+	 */
+	public IModule[] getChangedChildModules() {
+		return changed;
+	}
+
+	/**
+	 * @see org.eclipse.wst.server.core.model.IModuleEvent#getRemovedChildModules()
+	 */
+	public IModule[] getRemovedChildModules() {
+		return removed;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ModuleFactoryDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ModuleFactoryDelegate.java
new file mode 100644
index 0000000..bc16676
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ModuleFactoryDelegate.java
@@ -0,0 +1,126 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import java.util.*;
+
+import org.eclipse.wst.server.core.internal.Trace;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * 
+ */
+public abstract class ModuleFactoryDelegate implements IModuleFactoryDelegate {
+	// modules - map from memento (String) to IModule
+	protected Map modules;
+	protected boolean cached = false;
+
+	// change listeners
+	private transient List listeners;
+
+	/**
+	 * Construct a new ModuleFactoryDelegate.
+	 */
+	public ModuleFactoryDelegate() {
+		modules = new HashMap();
+	}
+
+	/**
+	 * Cache any existing modules into the modules Map.
+	 */
+	protected abstract void cacheModules();
+
+	/**
+	 * @see org.eclipse.wst.server.core.model.IModuleFactoryDelegate#getModule(String)
+	 */
+	public IModule getModule(String memento) {
+		if (!cached) {
+			cached = true;
+			cacheModules();
+		}
+
+		try {
+			return (IModule) modules.get(memento);
+		} catch (Exception e) { }
+		return null;
+	}
+
+	/**
+	 * @see org.eclipse.wst.server.core.model.IModuleFactoryDelegate#getModules()
+	 */
+	public List getModules() {
+		if (!cached) {
+			cached = true;
+			cacheModules();
+		}
+
+		return new ArrayList(modules.values());
+	}
+
+	/**
+	 * Add a listener to the module factory.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IModuleFactoryListener
+	 */
+	public void addModuleFactoryListener(IModuleFactoryListener listener) {
+		Trace.trace(Trace.FINEST, "Adding module factory listener " + listener + " to " + this);
+	
+		if (listeners == null)
+			listeners = new ArrayList();
+		else if (listeners.contains(listener))
+			return;
+		listeners.add(listener);
+	}
+
+	/**
+	 * Remove a listener from the module factory.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IModuleFactoryListener
+	 */
+	public void removeModuleFactoryListener(IModuleFactoryListener listener) {
+		Trace.trace(Trace.FINEST, "Removing module factory listener " + listener + " from " + this);
+	
+		if (listeners != null)
+			listeners.remove(listener);
+	}
+
+	/**
+	 * Fire a module factory event.
+	 */
+	protected void fireModuleFactoryEvent(IModule[] added, IModule[] removed) {
+		Trace.trace(Trace.FINEST, "->- Firing module factory event: " + toString() + " ->-");
+
+		if (listeners == null || listeners.isEmpty())
+			return;
+
+		int size = listeners.size();
+		IModuleFactoryListener[] dfl = new IModuleFactoryListener[size];
+		listeners.toArray(dfl);
+		
+		IModuleFactoryEvent event = new ModuleFactoryEvent(getFactoryId(), added, removed);
+		
+		for (int i = 0; i < size; i++) {
+			try {
+				Trace.trace(Trace.FINEST, "  Firing module factory event to: " + dfl[i]);
+				dfl[i].moduleFactoryChanged(event);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing module factory event", e);
+			}
+		}
+		Trace.trace(Trace.FINEST, "-<- Done firing module factory event -<-");
+	}
+
+	/**
+	 * Return the factory ID for this module factory.
+	 *
+	 * @return java.lang.String
+	 */
+	public abstract String getFactoryId();
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ModuleFactoryEvent.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ModuleFactoryEvent.java
new file mode 100644
index 0000000..731894b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ModuleFactoryEvent.java
@@ -0,0 +1,55 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IModuleFactoryEvent;
+/**
+ * 
+ */
+public class ModuleFactoryEvent implements IModuleFactoryEvent {
+	protected String factoryId;
+	protected IModule[] added;
+	protected IModule[] removed;
+
+	public ModuleFactoryEvent(String factoryId, IModule[] added, IModule[] removed) {
+		this.factoryId = factoryId;
+		this.added = added;
+		this.removed = removed;
+	}
+
+	/**
+	 * Returns the id of this factory.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getFactoryId() {
+		return factoryId;
+	}
+
+	/**
+	 * Returns any modules that have been added.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getAddedModules() {
+		return added;
+	}
+
+	/**
+	 * Returns any modules that have been removed.
+	 * 
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getRemovedModules() {
+		return removed;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/NullLaunchable.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/NullLaunchable.java
new file mode 100644
index 0000000..b7673f3
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/NullLaunchable.java
@@ -0,0 +1,29 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.wst.server.core.model.ILaunchable;
+/**
+ * 
+ */
+public class NullLaunchable implements ILaunchable {
+	public static final String ID = "null.launchable";
+
+	public NullLaunchable() { }
+
+	public String getId() {
+		return ID;
+	}
+
+	public String toString() {
+		return "NullLaunchable[id=" + getId() + "]";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/NullLaunchableClient.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/NullLaunchableClient.java
new file mode 100644
index 0000000..59f5c74
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/NullLaunchableClient.java
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.IClientDelegate;
+import org.eclipse.wst.server.core.model.ILaunchable;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunch;
+/**
+ * 
+ */
+public class NullLaunchableClient implements IClientDelegate {
+	/*
+	 * @see ILaunchableClient#supports(ILaunchable)
+	 */
+	public boolean supports(IServer server, ILaunchable launchable, String launchMode) {
+		return (launchable instanceof NullLaunchable);
+	}
+	
+	public IStatus launch(IServer server, ILaunchable launchable, String launchMode, ILaunch launch) {
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/NullModuleObject.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/NullModuleObject.java
new file mode 100644
index 0000000..4a1dc94
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/NullModuleObject.java
@@ -0,0 +1,38 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IModuleObject;
+/**
+ * 
+ */
+public class NullModuleObject implements IModuleObject {
+	public static final String ID = "org.eclipse.wst.server.core.null";
+
+	private IModule module;
+
+	public NullModuleObject(IModule module) {
+		this.module = module;
+	}
+
+	public String getId() {
+		return ID;
+	}
+
+	public IModule getModule() {
+		return module;
+	}
+
+	public String toString() {
+		return "NullModuleObject [module=" + module + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ProgressUtil.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ProgressUtil.java
new file mode 100644
index 0000000..9132b02
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ProgressUtil.java
@@ -0,0 +1,68 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.core.runtime.*;
+/**
+ * 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 int
+	 * @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.core/servercore/org/eclipse/wst/server/core/util/ProjectModule.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ProjectModule.java
new file mode 100644
index 0000000..9bfd14c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ProjectModule.java
@@ -0,0 +1,323 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+
+import org.eclipse.wst.server.core.internal.Trace;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IModuleListener;
+import org.eclipse.wst.server.core.model.IProjectModule;
+import org.eclipse.wst.server.core.resources.*;
+/**
+ * A simple IModuleProject that maps a folder within a project
+ * (or the root of the project itself) to the module.
+ */
+public abstract class ProjectModule implements IProjectModule {
+	protected IProject project;
+	protected IPath root;
+	
+	// change listeners
+	private transient List listeners;
+
+	public ProjectModule() {
+	}
+
+	public ProjectModule(IProject project) {
+		this.project = project;
+	}
+
+	/*
+	 * @see IModuleProject#getProject()
+	 */
+	public IProject getProject() {
+		return project;
+	}
+
+	/**
+	 * Returns the root folder.
+	 */
+	public IPath getRootFolder() {
+		return root;
+	}
+
+	/*
+	 * @see IModuleProject#getModuleResourceDelta(IResourceDelta)
+	 */
+	public IModuleResourceDelta getModuleResourceDelta(IResourceDelta delta) {
+		Trace.trace(Trace.FINEST, "> getModuleResourceDelta");
+		IPath root2 = null;
+		try {
+			root2 = getRootFolder();
+		} catch (Exception e) {
+			Trace.trace(Trace.FINEST, "Error getting root2");
+		}
+		if (root2 == null) {
+			return convertChildren(delta, null);
+		} else {
+			class Helper {
+				boolean found = false;
+				IModuleResourceDelta delta2;
+			}
+			final Helper helper = new Helper();
+			final IPath root3 = root2;
+			try {
+				delta.accept(new IResourceDeltaVisitor() {
+					public boolean visit(IResourceDelta visitDelta) {
+						if (!helper.found && root3.equals(visitDelta.getProjectRelativePath())) {
+							helper.delta2 = convertChildren(visitDelta, null);
+							helper.found = true;
+							return false;
+						} else
+							return true;
+					}
+				});
+				Trace.trace(Trace.FINEST, "< getModuleResourceDelta");
+				return helper.delta2;
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not get module resource delta");
+			}
+		}
+		Trace.trace(Trace.FINEST, "< getModuleResourceDelta null");
+		return null;
+	}
+	
+	/**
+	 * 
+	 */
+	protected IModuleResourceDelta convertChildren(IResourceDelta delta, IModuleFolder parent) {
+		int flags = delta.getKind();
+		int kind = IModuleResourceDelta.NO_CHANGE;
+		if (flags == IResourceDelta.ADDED)
+			kind = IModuleResourceDelta.ADDED;
+		else if (flags == IResourceDelta.REMOVED)
+			kind = IModuleResourceDelta.REMOVED;
+		else if (flags == IResourceDelta.CHANGED)
+			kind = IModuleResourceDelta.CHANGED;
+		
+		IResource resource = delta.getResource();
+		
+		IModuleResource pubResource = null;
+		if (resource instanceof IContainer)
+			pubResource = new ProjectModuleFolder(this, parent, (IContainer) resource);	
+		else if (resource instanceof IFile) {
+			if (delta.getFlags() == IResourceDelta.MARKERS)
+				return null;
+			else
+				pubResource = new ProjectModuleFile(this, parent, (IFile) resource);
+		}
+		
+		ModuleResourceDelta deployDelta = new ModuleResourceDelta(pubResource, kind);
+		
+		IResourceDelta[] children = delta.getAffectedChildren();
+		if (children != null && pubResource instanceof IModuleFolder) {
+			int size = children.length;
+			for (int i = 0; i < size; i++) {
+				IModuleResourceDelta childDelta = convertChildren(children[i], (IModuleFolder) pubResource);
+				if (childDelta != null)
+					deployDelta.addChild(childDelta);
+			}
+		}
+		return deployDelta;
+	}
+
+	/*
+	 * @see IModule#getMemento()
+	 */
+	public String getId() {
+		return getProject().getName();
+	}
+	
+	/*
+	 * @see IModule#getPublishStatus()
+	 */
+	public IStatus validate() {
+		return null;
+	}
+
+	/*
+	 * @see IModule#getPublishStatus()
+	 */
+	public IStatus canPublish() {
+		return null;
+	}
+
+	/*
+	 * @see IModule#members()
+	 */
+	public IModuleResource[] members() throws CoreException {
+		IPath root2 = null;
+		try {
+			root2 = getRootFolder();
+		} catch (Exception e) { }
+		try {
+			if (root2 == null || root2.isRoot() || root2.equals(new Path("")) || root2.equals(new Path("/")))
+				return getModuleResources(getProject(), null);
+			else {
+				IFolder folder = project.getFolder(root2);
+				return getModuleResources(folder, null);
+			}
+		} catch (CoreException e) {
+			throw e;
+		}
+	}
+	
+	protected IModuleResource getModuleResources(IFile file) {
+		return new ProjectModuleFile(this, null, file);
+	}
+
+	protected IModuleResource[] getModuleResources(IContainer container, IModuleFolder parent) throws CoreException {
+		List list = new ArrayList();
+
+ 		IResource[] resources = container.members();
+	 	if (resources != null) {
+	 		int size = resources.length;
+	 		for (int i = 0; i < size; i++) {
+				IResource resource = resources[i];
+				if (resource instanceof IContainer) {
+					ProjectModuleFolder pdf = new ProjectModuleFolder(this, parent, (IContainer) resource);	
+					list.add(pdf);
+				} else if (resource instanceof IFile) {
+					ProjectModuleFile pdf = new ProjectModuleFile(this, parent, (IFile) resource);
+					list.add(pdf);
+				}
+			}
+	 	}
+	 	
+	 	IModuleResource[] moduleResources = new IModuleResource[list.size()];
+	 	list.toArray(moduleResources);
+	 	return moduleResources;
+	}
+
+	/*
+	 * @see IModule#getName()
+	 */
+	public String getName() {
+		return getProject().getName();
+	}
+	
+	/**
+	 * Returns true if this module currently exists, and false if it has
+	 * been deleted or moved and is no longer represented by this module.
+	 *
+	 * @return boolean
+	 */
+	public boolean exists() {
+		return (getProject() != null && getProject().exists());
+	}
+	
+	/**
+	 * 
+	 */
+	public boolean equals(Object obj) {
+		if (obj == null || !(obj instanceof ProjectModule))
+			return false;
+
+		ProjectModule dp = (ProjectModule) obj;
+		if (getFactoryId() != null && !getFactoryId().equals(dp.getFactoryId()))
+			return false;
+			
+		IPath root2 = null;
+		try {
+			root2 = getRootFolder();
+		} catch (Exception e) { }
+		
+		IPath root3 = null;
+		try {
+			root3 = dp.getRootFolder();
+		} catch (Exception e) { }
+		
+		if (project != null && project.exists() && !project.equals(dp.getProject()))
+			return false;
+
+		if (root2 == null && root3 != null)
+			return false;
+		if (root2 != null && !root2.equals(root3))
+			return false;
+
+		return true;
+	}
+
+	/**
+	 * Add a listener for the module.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IModuleListener
+	 */
+	public void addModuleListener(IModuleListener listener) {
+		Trace.trace(Trace.FINEST, "Adding module listener " + listener + " to " + this);
+	
+		if (listeners == null)
+			listeners = new ArrayList();
+		else if (listeners.contains(listener))
+			return;
+		listeners.add(listener);
+	}
+	
+	/**
+	 * Add a listener for the module.
+	 *
+	 * @param listener org.eclipse.wst.server.core.model.IModuleListener
+	 */
+	public void removeModuleListener(IModuleListener listener) {
+		Trace.trace(Trace.FINEST, "Removing module listener " + listener + " from " + this);
+	
+		if (listeners != null)
+			listeners.remove(listener);
+	}
+	
+	/**
+	 * Fire a module change event.
+	 */
+	protected void fireModuleChangeEvent(boolean isChange, IModule[] added, IModule[] changed, IModule[] removed) {
+		Trace.trace(Trace.FINEST, "->- Firing module change event: " + getName() + " (" + isChange + ") ->-");
+	
+		if (listeners == null || listeners.isEmpty())
+			return;
+	
+		int size = listeners.size();
+		IModuleListener[] dcl = new IModuleListener[size];
+		listeners.toArray(dcl);
+		
+		ModuleEvent event = new ModuleEvent(this, isChange, added, changed, removed);
+	
+		for (int i = 0; i < size; i++) {
+			try {
+				Trace.trace(Trace.FINEST, "  Firing module change event to: " + dcl[i]);
+				dcl[i].moduleChanged(event);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "  Error firing module change event", e);
+			}
+		}
+		Trace.trace(Trace.FINEST, "-<- Done firing module change event -<-");
+	}
+	
+	/**
+	 * Called when the listener paths from the module factory change.
+	 * Use this method to recache information about the module.
+	 */
+	protected void update() {
+	}
+
+	/**
+	 * Returns the child modules of this module.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IModule[]
+	 */
+	public IModule[] getChildModules() {
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ProjectModuleFactoryDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ProjectModuleFactoryDelegate.java
new file mode 100644
index 0000000..a5998fe
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ProjectModuleFactoryDelegate.java
@@ -0,0 +1,354 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import java.util.*;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.IPath;
+
+import org.eclipse.wst.server.core.IResourceManager;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.internal.ResourceManager;
+import org.eclipse.wst.server.core.internal.Trace;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * 
+ */
+public abstract class ProjectModuleFactoryDelegate extends ModuleFactoryDelegate {
+	protected static IResourceChangeListener listener;
+	
+	protected static List factories = new ArrayList();
+
+	protected List added;
+	protected List removed;
+
+	// map from IProject to IModuleProject
+	protected Map projects;
+
+	/**
+	 * Construct a new ProjectModuleFactoryDelegate.
+	 */
+	public ProjectModuleFactoryDelegate() {
+		super();
+		
+		factories.add(this);
+		
+		addListener();
+	}
+
+	/**
+	 * Cache any preexisting module.
+	 */
+	protected void cacheModules() {
+		projects = new HashMap();
+		try {
+			IProject[] projects2 = getWorkspaceRoot().getProjects();
+			int size = projects2.length;
+			for (int i = 0; i < size; i++) {
+				//Trace.trace("caching: " + this + " " + projects[i] + " " + isValidModule(projects[i]));
+				if (isValidModule(projects2[i])) {
+					addModuleProject(projects2[i]);
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace("Error caching modules", e);
+		}
+		fireEvents();
+	}
+
+	/**
+	 * Return the workspace root.
+	 * 
+	 * @return org.eclipse.core.resources.IWorkspaceRoot
+	 */
+	protected static IWorkspaceRoot getWorkspaceRoot() {
+		return ResourcesPlugin.getWorkspace().getRoot();
+	}
+
+	/**
+	 * Returns the module project for the given project, or null
+	 * if this factory does not have a module for the given project.
+	 * 
+	 * @param project org.eclipse.core.resources.IProject
+	 * @return org.eclipse.wst.server.core.model.IModuleProject
+	 */
+	public IProjectModule getModuleProject(IProject project) {
+		try {
+			return (IProjectModule) projects.get(project);
+		} catch (Exception e) { }
+		return null;
+	}
+
+	/**
+	 * Add a resource listener to the workspace.
+	 */
+	protected static void addListener() {
+		if (listener != null)
+			return;
+
+		listener = new IResourceChangeListener() {
+			public void resourceChanged(IResourceChangeEvent event) {
+				Trace.trace(Trace.FINEST, "->- ProjectModuleFactoryDelegate listener responding to resource change: " + event.getType() + " ->-");
+				try {
+					IResourceDelta delta = event.getDelta();
+					
+					//if (delta.getFlags() == IResourceDelta.MARKERS || delta.getFlags() == IResourceDelta.NO_CHANGE)
+					//	return; // TODO
+				
+					delta.accept(new IResourceDeltaVisitor() {
+						public boolean visit(IResourceDelta visitorDelta) {
+							IResource resource = visitorDelta.getResource();
+							//Trace.trace(Trace.FINEST, "resource: " + resource);
+	
+							// only respond changes within projects
+							if (resource != null && resource instanceof IProject) {
+								IProject project = (IProject) resource;
+								handleGlobalProjectChange(project, visitorDelta);
+								return true;
+							} else if (resource != null && resource.getProject() != null) {
+								return false;
+							} else
+								return true;
+						}
+					});
+				} catch (Exception e) {
+					//Trace.trace(Trace.SEVERE, "Error responding to resource change", e);
+				}
+				fireGlobalEvents();
+				Trace.trace(Trace.FINEST, "-<- Done ProjectModuleFactoryDelegate responding to resource change -<-");
+			}
+		};
+		
+		ResourcesPlugin.getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.POST_CHANGE);
+	}
+	
+	/**
+	 * Handle changes to a project.
+	 * 
+	 * @param project org.eclipse.core.resources.IProject
+	 * @param delta org.eclipse.core.resources.IResourceDelta
+	 */
+	protected static void handleGlobalProjectChange(final IProject project, IResourceDelta delta) {
+		// handle project level changes
+		Iterator iterator = factories.iterator();
+		while (iterator.hasNext()) {
+			ProjectModuleFactoryDelegate factory = (ProjectModuleFactoryDelegate) iterator.next();
+			//Trace.trace("Firing to: " + factory);
+			factory.handleProjectChange(project, delta);
+		}
+		
+		// handle internal updates
+		iterator = factories.iterator();
+		while (iterator.hasNext()) {
+			ProjectModuleFactoryDelegate factory = (ProjectModuleFactoryDelegate) iterator.next();
+			//Trace.trace("Firing to: " + factory);
+			factory.handleProjectInternalChange(project, delta);
+		}
+	}
+	
+	/**
+	 * Fire the accumulated module factory events.
+	 */
+	protected static void fireGlobalEvents() {
+		Trace.trace(Trace.FINEST, "Firing global module event");
+		Iterator iterator = factories.iterator();
+		while (iterator.hasNext()) {
+			ProjectModuleFactoryDelegate factory = (ProjectModuleFactoryDelegate) iterator.next();
+			factory.updateProjects();
+		}
+		
+		iterator = factories.iterator();
+		while (iterator.hasNext()) {
+			ProjectModuleFactoryDelegate factory = (ProjectModuleFactoryDelegate) iterator.next();
+			factory.fireEvents();
+		}
+		
+		IResourceManager rm = ServerCore.getResourceManager();
+		((ResourceManager) rm).syncModuleEvents();
+	}
+	
+	/**
+	 * Temporary to make sure that all project modules are updated.
+	 */
+	private void updateProjects() {
+		List modules2 = getModules();
+		if (modules2 != null) {
+			Iterator iterator = modules2.iterator();
+			while (iterator.hasNext()) {
+				IModule module = (IModule) iterator.next();
+				if (module instanceof ProjectModule)
+					((ProjectModule) module).update();
+			}
+		}
+	}
+
+	/**
+	 * Handle changes to a project.
+	 * 
+	 * @param project org.eclipse.core.resources.IProject
+	 * @param delta org.eclipse.core.resources.IResourceDelta
+	 */
+	protected void handleProjectChange(final IProject project, IResourceDelta delta) {
+		if (projects.containsKey(project)) {
+			// already a module
+			if (((delta.getKind() &  IResourceDelta.REMOVED) != 0) || !isValidModule(project)) {
+				removeModuleProject(project);
+			}
+		} else {
+			// not a module
+			if (isValidModule(project)) {
+				addModuleProject(project);
+			}
+		}
+	}
+	
+	/**
+	 * Handle changes to a project.
+	 * 
+	 * @param project org.eclipse.core.resources.IProject
+	 * @param delta org.eclipse.core.resources.IResourceDelta
+	 */
+	protected void handleProjectInternalChange(final IProject project, IResourceDelta delta) {
+		final IPath[] paths = getListenerPaths();
+		if (paths != null) {
+			final IModule module = getModuleProject(project);
+			if (module != null && module instanceof ProjectModule) {
+				final int size = paths.length;
+				class Temp {
+					boolean found = false;
+				}
+				final Temp temp = new Temp();
+				try {
+					delta.accept(new IResourceDeltaVisitor() {
+						public boolean visit(IResourceDelta visitorDelta) {
+							if (temp.found)
+								return false;
+							IPath path = visitorDelta.getProjectRelativePath();
+							
+							boolean prefix = false;
+							for (int i = 0; i < size && !temp.found; i++) {
+								if (paths[i].equals(path))
+									temp.found = true;
+								else if (path.isPrefixOf(paths[i]))
+									prefix = true;
+							}
+							if (temp.found) {
+								((ProjectModule) module).update();
+								return false;
+							} else if (prefix)
+								return true;
+							else
+								return false;
+						}
+					});
+				} catch (Exception e) {
+					Trace.trace("Error searching for listening paths", e);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Add a module for the given project.
+	 * 
+	 * @param project org.eclipse.core.resources.IProject
+	 */
+	protected void addModuleProject(IProject project) {
+		if (!cached) {
+			cached = true;
+			cacheModules();
+		}
+
+		IProjectModule module = createModule(project);
+		if (module == null)
+			return;
+		projects.put(project, module);
+		modules.put(module.getId(), module);
+		if (added == null)
+			added = new ArrayList(2);
+		added.add(module);
+	}
+
+	/**
+	 * Remove the module that represents the given project.
+	 * 
+	 * @param project org.eclipse.core.resources.IProject
+	 */
+	protected void removeModuleProject(IProject project) {
+		if (!cached) {
+			cached = true;
+			cacheModules();
+		}
+
+		try {
+			IProjectModule module = (IProjectModule) projects.get(project);
+			projects.remove(project);
+			modules.remove(module.getId());
+			if (removed == null)
+				removed = new ArrayList(2);
+			removed.add(module);
+		} catch (Exception e) {
+			Trace.trace("Error removing module project", e);
+		}
+	}
+
+	/**
+	 * Fire the accumulated module factory events.
+	 */
+	protected void fireEvents() {
+		if ((added == null || added.isEmpty()) && (removed == null || removed.isEmpty()))
+			return;
+
+		IModule[] add = null;
+		if (added != null) {
+			add = new IModule[added.size()];
+			added.toArray(add);
+		}
+		IModule[] remove = null;
+		if (removed != null) {
+			remove = new IModule[removed.size()];
+			removed.toArray(remove);
+		}
+		
+		fireModuleFactoryEvent(add, remove);
+		added = new ArrayList(2);
+		removed = new ArrayList(2);
+	}
+
+	/**
+	 * Returns true if the project represents a module project
+	 * of this type.
+	 * 
+	 * @param project org.eclipse.core.resources.IProject
+	 * @return boolean
+	 */
+	protected abstract boolean isValidModule(IProject project);
+
+	/**
+	 * Creates the module project for the given project.
+	 * 
+	 * @param project org.eclipse.core.resources.IProject
+	 * @return org.eclipse.wst.server.core.model.IModuleProject
+	 */
+	protected abstract IProjectModule createModule(IProject project);
+
+	/**
+	 * Returns the list of resources that the module should listen to
+	 * for state changes. The paths should be project relative paths.
+	 * Subclasses can override this method to provide the paths.
+	 *
+	 * @return org.eclipse.core.runtime.IPath[]
+	 */
+	protected IPath[] getListenerPaths() {
+		return null;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/PublishAdapter.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/PublishAdapter.java
new file mode 100644
index 0000000..4e445cd
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/PublishAdapter.java
@@ -0,0 +1,72 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import java.util.List;
+
+import org.eclipse.wst.server.core.IPublishStatus;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IPublishListener;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+import org.eclipse.wst.server.core.resources.IRemoteResource;
+/**
+ *
+ */
+public class PublishAdapter implements IPublishListener {
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.model.IPublishListener#moduleStateChange(org.eclipse.wst.server.core.IServer2, java.util.List, org.eclipse.wst.server.core.model.IModule)
+	 */
+	public void moduleStateChange(IServer server, List parents, IModule module) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.model.IPublishListener#publishStarting(org.eclipse.wst.server.core.IServer2, java.util.List[], org.eclipse.wst.server.core.model.IModule[])
+	 */
+	public void publishStarting(IServer server, List[] parents, IModule[] module) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.model.IPublishListener#publishStarted(org.eclipse.wst.server.core.IServer2, org.eclipse.wst.server.core.IPublishStatus)
+	 */
+	public void publishStarted(IServer server, IPublishStatus status) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.model.IPublishListener#moduleStarting(org.eclipse.wst.server.core.IServer2, java.util.List, org.eclipse.wst.server.core.model.IModule)
+	 */
+	public void moduleStarting(IServer server, List parents, IModule module) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.model.IPublishListener#moduleResourcesPublished(org.eclipse.wst.server.core.IServer2, java.util.List, org.eclipse.wst.server.core.model.IModule, org.eclipse.wst.server.core.resources.IModuleResource[], org.eclipse.wst.server.core.IPublishStatus[])
+	 */
+	public void moduleResourcesPublished(IServer server, List parents, IModule module, IModuleResource[] published, IPublishStatus[] status) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.model.IPublishListener#moduleResourcesDeleted(org.eclipse.wst.server.core.IServer2, java.util.List, org.eclipse.wst.server.core.model.IModule, org.eclipse.wst.server.core.resources.IRemoteResource[], org.eclipse.wst.server.core.IPublishStatus[])
+	 */
+	public void moduleResourcesDeleted(IServer server, List parents, IModule module, IRemoteResource[] deleted, IPublishStatus[] status) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.model.IPublishListener#moduleFinished(org.eclipse.wst.server.core.IServer2, java.util.List, org.eclipse.wst.server.core.model.IModule, org.eclipse.wst.server.core.IPublishStatus)
+	 */
+	public void moduleFinished(IServer server, List parents, IModule module, IPublishStatus status) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.core.model.IPublishListener#publishFinished(org.eclipse.wst.server.core.IServer, org.eclipse.wst.server.core.IPublishStatus)
+	 */
+	public void publishFinished(IServer server, IPublishStatus status) {
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerAdapter.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerAdapter.java
new file mode 100644
index 0000000..66aef26
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerAdapter.java
@@ -0,0 +1,57 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IServerListener;
+/**
+ * Helper class which implements all of the IServerListener
+ * interface with empty methods.
+ */
+public class ServerAdapter implements IServerListener {
+	/**
+	 * ServerAdapter constructor comment.
+	 */
+	public ServerAdapter() {
+		super();
+	}
+
+	/**
+	 * Called when the server configuration's sync state changes.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void configurationSyncStateChange(IServer server) { }
+
+	/**
+	 * Called when the server isRestartNeeded() property changes.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void restartStateChange(IServer server) { }
+
+	/**
+	 * Notification when the server state has changed.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void serverStateChange(IServer server) { }
+
+	/**
+	 * Notification when the state of a module has changed.
+	 *
+	 * @param server org.eclipse.wst.server.model.IServer
+	 */
+	public void moduleStateChange(IServer server, IModule module) { }
+
+	public void modulesChanged(IServer server) { }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerConfigurationDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerConfigurationDelegate.java
new file mode 100644
index 0000000..4bac948
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerConfigurationDelegate.java
@@ -0,0 +1,53 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.model.*;
+/**
+ * Abstract implementation of IServerConfiguration to implement
+ * methods that are not required often.
+ */
+public abstract class ServerConfigurationDelegate implements IServerConfigurationDelegate {
+	protected IServerConfiguration configuration;
+
+	/**
+	 * Called when the server is loaded as a model object.
+	 */
+	public void initialize(IServerConfiguration configuration2) {
+		this.configuration = configuration2;
+	}
+	
+	public IServerConfiguration getServerConfiguration() {
+		return configuration;
+	}
+	
+	/**
+	 * Called when this server resource has become invalid or no longer
+	 * required and is being deregistered or dicarded. This method can
+	 * be used to remove listeners, etc.
+	 */
+	public void dispose() {
+		configuration = null;
+	}
+	
+	public void load(IPath path, IProgressMonitor monitor) throws CoreException {
+		throw new CoreException(null);
+	}
+
+	public void load(IFolder folder, IProgressMonitor monitor) throws CoreException {
+		throw new CoreException(null);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerPort.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerPort.java
new file mode 100644
index 0000000..cd3e066
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerPort.java
@@ -0,0 +1,119 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.wst.server.core.model.IServerPort;
+/**
+ * A port on a server configuration.
+ */
+public class ServerPort implements IServerPort {
+	private String id;
+	private String name;
+	private int port;
+	private String protocol;
+	private String[] contentTypes;
+	private boolean advanced;
+	
+	/**
+	 * ServerPort constructor comment.
+	 */
+	public ServerPort(String id, String name, int port, String protocol) {
+		this(id, name, port, protocol, null, true);
+	}
+	
+	public ServerPort(String id, String name, int port, String protocol, boolean advanced) {
+		this(id, name, port, protocol, null, advanced);
+	}
+
+	public ServerPort(String id, String name, int port, String protocol, String[] contentTypes, boolean advanced) {
+		super();
+		this.id = id;
+		this.name = name;
+		this.port = port;
+		this.protocol = protocol;
+		this.contentTypes = contentTypes;
+		this.advanced = advanced;
+	}
+	
+	/**
+	 * ServerPort constructor comment.
+	 */
+	public ServerPort(String name, int port, String protocol) {
+		this(null, name, port, protocol);
+	}
+	
+	/**
+	 * Return an optional internal id used to identify this port.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return id;
+	}
+
+	/**
+	 * Return the name of the port.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Return the actual port number.
+	 * @return int
+	 */
+	public int getPort() {
+		return port;
+	}
+
+	/**
+	 * Returns the protocol, e.g. HTTP of this port. Returns null
+	 * if the protocol is unknown.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getProtocol() {
+		return protocol;
+	}
+
+	/**
+	 * Returns the content that this port would normally serve, or null
+	 * if the content is unknown.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	public String[] getContentTypes() {
+		return contentTypes;
+	}
+
+	/**
+	 * Returns true if this port is an "advanced" port and should not be shown
+	 * to novice users.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isAdvanced() {
+		return advanced;
+	}
+
+	public boolean equals(Object obj) {
+		if (!(obj instanceof ServerPort))
+			return false;
+		ServerPort sp = (ServerPort) obj;
+		return (sp.port == port);
+	}
+	
+	public int hashCode() {
+		return port;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerResourceAdapter.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerResourceAdapter.java
new file mode 100644
index 0000000..faf3479
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/ServerResourceAdapter.java
@@ -0,0 +1,38 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.model.IServerResourceListener;
+/**
+ * 
+ */
+public class ServerResourceAdapter implements IServerResourceListener {
+	public void runtimeAdded(IRuntime runtime) { }
+
+	public void runtimeChanged(IRuntime runtime) { }
+
+	public void runtimeRemoved(IRuntime runtime) { }
+
+	public void serverAdded(IServer server) { }
+
+	public void serverChanged(IServer server) { }
+
+	public void serverRemoved(IServer server) { }
+
+	public void serverConfigurationAdded(IServerConfiguration serverConfiguration) { }
+
+	public void serverConfigurationChanged(IServerConfiguration serverConfiguration) { }
+
+	public void serverConfigurationRemoved(IServerConfiguration serverConfiguration) { }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/SocketUtil.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/SocketUtil.java
new file mode 100644
index 0000000..9d50444
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/SocketUtil.java
@@ -0,0 +1,108 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.core.util;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.SocketException;
+import java.util.Random;
+
+import org.eclipse.wst.server.core.internal.Trace;
+/**
+ * 
+ */
+public class SocketUtil {
+	private static final Random fgRandom = new Random(System.currentTimeMillis());
+
+	/**
+	 * Finds an unused port between the given from and to values.
+	 * 
+	 * @param host
+	 * @param searchFrom
+	 * @param searchTo
+	 * @return
+	 */
+	public static int findUnusedPort(int searchFrom, int searchTo) {
+		for (int i = 0; i < 10; i++) {
+			int port = getRandomPort(searchFrom, searchTo);
+			if (!isPortInUse(port))
+				return port;
+		}
+		return -1;
+	}
+
+	private static int getRandomPort(int low, int high) {
+		return (int)(fgRandom.nextFloat()*(high-low))+low;
+	}
+
+	/**
+	 * Returns true if this port is in use. Retries every 500ms for "count" tries.
+	 *
+	 * @return boolean
+	 * @param port int
+	 * @param count int
+	 */
+	public static boolean isPortInUse(int port, int count) {
+		boolean inUse = isPortInUse(port);
+		while (inUse && count > 0) {
+			try {
+				Thread.sleep(500);
+			} catch (Exception e) { }
+			inUse = isPortInUse(port);
+			count --;
+		}
+	
+		return inUse;
+	}
+
+	/**
+	 * Returns true if this port is in use.
+	 *
+	 * @return boolean
+	 * @param port int
+	 */
+	public static boolean isPortInUse(int port) {
+		ServerSocket s = null;
+		try {
+			s = new ServerSocket(port);
+		} catch (SocketException e) {
+			return true;
+		} catch (IOException e) {
+			return true;
+		} catch (Exception e) {
+			return true;
+		} finally {
+			if (s != null) {
+				try {
+					s.close();
+				} catch (Exception e) { }
+			}
+		}
+
+		return false;
+	}
+
+	public static boolean isLocalhost(String host) {
+		if (host == null)
+			return false;
+		try {
+			if ("localhost".equals(host) || "127.0.0.1".equals(host))
+				return true;
+			InetAddress localHostaddr = InetAddress.getLocalHost();
+			if (localHostaddr.getHostName().equals(host))
+				return true;
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Error checking for localhost", e);
+		}
+		return false;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/Task.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/Task.java
new file mode 100644
index 0000000..729bda2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/Task.java
@@ -0,0 +1,48 @@
+package org.eclipse.wst.server.core.util;
+
+import org.eclipse.wst.server.core.*;
+
+/**
+ * 
+ */
+public abstract class Task implements ITask {
+	protected ITaskModel model;
+	protected String label;
+	protected String description;
+	
+	public Task() { }
+	
+	public Task(String label, String description) {
+		this.label = label;
+		this.description = description;
+	}
+	
+	public String getName() {
+		return label;
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public ITaskModel getTaskModel() {
+		return model;
+	}
+	
+	public void setTaskModel(ITaskModel taskModel) {
+		this.model = taskModel;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.ITask#canExecute()
+	 */
+	public boolean canExecute() {
+		return true;
+	}
+	
+	public boolean canUndo() {
+		return false;
+	}
+	
+	public void undo() { }
+}
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/TaskModel.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/TaskModel.java
new file mode 100644
index 0000000..f994bf1
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/TaskModel.java
@@ -0,0 +1,24 @@
+package org.eclipse.wst.server.core.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.wst.server.core.*;
+/**
+ * 
+ */
+public class TaskModel implements ITaskModel {
+	protected Map map = new HashMap();
+
+	public Object getObject(String id) {
+		try {
+			return map.get(id);
+		} catch (Exception e) {
+			return null;
+		}
+	}
+	
+	public void putObject(String id, Object obj) {
+		map.put(id, obj);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/.classpath b/plugins/org.eclipse.wst.server.ui/.classpath
new file mode 100644
index 0000000..4cb0786
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="serverui/"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.wst.server.ui/.cvsignore b/plugins/org.eclipse.wst.server.ui/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/plugins/org.eclipse.wst.server.ui/.options b/plugins/org.eclipse.wst.server.ui/.options
new file mode 100644
index 0000000..94000df
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/.options
@@ -0,0 +1,7 @@
+# Debugging options for the org.eclipse.wst.server.ui plugin
+
+# Turn on general debugging
+org.eclipse.wst.server.ui/debug=false
+
+# Prints out values
+org.eclipse.wst.server.ui/editor=false
diff --git a/plugins/org.eclipse.wst.server.ui/.project b/plugins/org.eclipse.wst.server.ui/.project
new file mode 100644
index 0000000..2fd3ed9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.server.ui</name>
+	<comment></comment>
+	<projects>
+		<project>org.eclipse.wst.server.core</project>
+		<project>org.eclipse.jst.server.core</project>
+	</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.ui/build.properties b/plugins/org.eclipse.wst.server.ui/build.properties
new file mode 100644
index 0000000..ebf73d8
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/build.properties
@@ -0,0 +1,11 @@
+bin.includes = plugin.xml,\
+               *.jar,\
+               plugin.properties,\
+               serverui.jar,\
+               icons/,\
+               .options
+jars.compile.order = 
+source.serverui.jar = serverui/
+src.includes = schema/,\
+               build.properties
+output.serverui.jar = bin/
diff --git a/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_debug.gif b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_debug.gif
new file mode 100644
index 0000000..5714d7a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_debug.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_disconnect.gif b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_disconnect.gif
new file mode 100644
index 0000000..6e0d383
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_disconnect.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_profile.gif b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_profile.gif
new file mode 100644
index 0000000..89c3340
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_profile.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_publish.gif b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_publish.gif
new file mode 100644
index 0000000..87827af
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_publish.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_restart.gif b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_restart.gif
new file mode 100644
index 0000000..bc0ac6e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_restart.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_run.gif b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_run.gif
new file mode 100644
index 0000000..57f4102
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_run.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_stop.gif b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_stop.gif
new file mode 100644
index 0000000..c4c7c80
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/clcl16/launch_stop.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/ctool16/debug_on_server.gif b/plugins/org.eclipse.wst.server.ui/icons/ctool16/debug_on_server.gif
new file mode 100644
index 0000000..d4650bb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/ctool16/debug_on_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/ctool16/profile_on_server.gif b/plugins/org.eclipse.wst.server.ui/icons/ctool16/profile_on_server.gif
new file mode 100644
index 0000000..aca9522
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/ctool16/profile_on_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/ctool16/run_on_server.gif b/plugins/org.eclipse.wst.server.ui/icons/ctool16/run_on_server.gif
new file mode 100644
index 0000000..5ed7d98
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/ctool16/run_on_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_import_configuration.gif b/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_import_configuration.gif
new file mode 100644
index 0000000..a4f6b31
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_import_configuration.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_modify_modules.gif b/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_modify_modules.gif
new file mode 100644
index 0000000..d507012
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_modify_modules.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_new_server.gif b/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_new_server.gif
new file mode 100644
index 0000000..55bacb2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_new_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_new_server_project.gif b/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_new_server_project.gif
new file mode 100644
index 0000000..1cfd11a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/ctool16/wiz_new_server_project.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/cview16/server_perspective.gif b/plugins/org.eclipse.wst.server.ui/icons/cview16/server_perspective.gif
new file mode 100644
index 0000000..88b648c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/cview16/server_perspective.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/cview16/servers_view.gif b/plugins/org.eclipse.wst.server.ui/icons/cview16/servers_view.gif
new file mode 100644
index 0000000..fbabfbb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/cview16/servers_view.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_debug.gif b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_debug.gif
new file mode 100644
index 0000000..02f9c3a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_debug.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_disconnect.gif b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_disconnect.gif
new file mode 100644
index 0000000..0956095
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_disconnect.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_profile.gif b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_profile.gif
new file mode 100644
index 0000000..8309b0d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_profile.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_publish.gif b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_publish.gif
new file mode 100644
index 0000000..78ba7cb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_publish.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_restart.gif b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_restart.gif
new file mode 100644
index 0000000..49d908e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_restart.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_run.gif b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_run.gif
new file mode 100644
index 0000000..9362e67
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_run.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_stop.gif b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_stop.gif
new file mode 100644
index 0000000..1dc8c69
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dlcl16/launch_stop.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dtool16/debug_on_server.gif b/plugins/org.eclipse.wst.server.ui/icons/dtool16/debug_on_server.gif
new file mode 100644
index 0000000..3b4cf27
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dtool16/debug_on_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dtool16/profile_on_server.gif b/plugins/org.eclipse.wst.server.ui/icons/dtool16/profile_on_server.gif
new file mode 100644
index 0000000..d14c89d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dtool16/profile_on_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dtool16/run_on_server.gif b/plugins/org.eclipse.wst.server.ui/icons/dtool16/run_on_server.gif
new file mode 100644
index 0000000..b422a86
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dtool16/run_on_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_import_configuration.gif b/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_import_configuration.gif
new file mode 100644
index 0000000..45f57b3
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_import_configuration.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_modify_modules.gif b/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_modify_modules.gif
new file mode 100644
index 0000000..314fed1
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_modify_modules.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_new_server.gif b/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_new_server.gif
new file mode 100644
index 0000000..116fcb0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_new_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_new_server_project.gif b/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_new_server_project.gif
new file mode 100644
index 0000000..fc52314
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/dtool16/wiz_new_server_project.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_debug.gif b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_debug.gif
new file mode 100644
index 0000000..5714d7a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_debug.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_disconnect.gif b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_disconnect.gif
new file mode 100644
index 0000000..6e0d383
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_disconnect.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_profile.gif b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_profile.gif
new file mode 100644
index 0000000..89c3340
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_profile.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_publish.gif b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_publish.gif
new file mode 100644
index 0000000..87827af
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_publish.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_restart.gif b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_restart.gif
new file mode 100644
index 0000000..bc0ac6e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_restart.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_run.gif b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_run.gif
new file mode 100644
index 0000000..57f4102
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_run.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_stop.gif b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_stop.gif
new file mode 100644
index 0000000..c4c7c80
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/elcl16/launch_stop.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/etool16/debug_on_server.gif b/plugins/org.eclipse.wst.server.ui/icons/etool16/debug_on_server.gif
new file mode 100644
index 0000000..d4650bb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/etool16/debug_on_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/etool16/profile_on_server.gif b/plugins/org.eclipse.wst.server.ui/icons/etool16/profile_on_server.gif
new file mode 100644
index 0000000..aca9522
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/etool16/profile_on_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/etool16/run_on_server.gif b/plugins/org.eclipse.wst.server.ui/icons/etool16/run_on_server.gif
new file mode 100644
index 0000000..5ed7d98
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/etool16/run_on_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_import_configuration.gif b/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_import_configuration.gif
new file mode 100644
index 0000000..a4f6b31
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_import_configuration.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_modify_modules.gif b/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_modify_modules.gif
new file mode 100644
index 0000000..d507012
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_modify_modules.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_new_server.gif b/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_new_server.gif
new file mode 100644
index 0000000..55bacb2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_new_server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_new_server_project.gif b/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_new_server_project.gif
new file mode 100644
index 0000000..1cfd11a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/etool16/wiz_new_server_project.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/eview16/server_perspective.gif b/plugins/org.eclipse.wst.server.ui/icons/eview16/server_perspective.gif
new file mode 100644
index 0000000..88b648c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/eview16/server_perspective.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/eview16/servers_view.gif b/plugins/org.eclipse.wst.server.ui/icons/eview16/servers_view.gif
new file mode 100644
index 0000000..fbabfbb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/eview16/servers_view.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/configuration.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/configuration.gif
new file mode 100644
index 0000000..fe296f6
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/configuration.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/configuration_missing.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/configuration_missing.gif
new file mode 100644
index 0000000..f0ef4c9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/configuration_missing.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/configuration_none.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/configuration_none.gif
new file mode 100644
index 0000000..cbd2756
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/configuration_none.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/edit_server_config.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/edit_server_config.gif
new file mode 100644
index 0000000..3a8f106
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/edit_server_config.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/monitorOff.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/monitorOff.gif
new file mode 100644
index 0000000..42e5f31
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/monitorOff.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/monitorOn.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/monitorOn.gif
new file mode 100644
index 0000000..2ff3974
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/monitorOn.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/project_missing.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/project_missing.gif
new file mode 100644
index 0000000..0cb4c16
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/project_missing.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/publish_disabled.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/publish_disabled.gif
new file mode 100644
index 0000000..519b846
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/publish_disabled.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/publish_enabled.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/publish_enabled.gif
new file mode 100644
index 0000000..bb900ed
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/publish_enabled.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/repair_config.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/repair_config.gif
new file mode 100644
index 0000000..e5690ec
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/repair_config.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server.gif
new file mode 100644
index 0000000..b51ae39
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_project.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_project.gif
new file mode 100644
index 0000000..3d35a02
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_project.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_started.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_started.gif
new file mode 100644
index 0000000..d370054
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_started.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_started_debug.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_started_debug.gif
new file mode 100644
index 0000000..f1e1778
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_started_debug.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_started_profile.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_started_profile.gif
new file mode 100644
index 0000000..47e2584
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_started_profile.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_starting1.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_starting1.gif
new file mode 100644
index 0000000..66263aa
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_starting1.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_starting2.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_starting2.gif
new file mode 100644
index 0000000..703bbfe
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_starting2.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_starting3.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_starting3.gif
new file mode 100644
index 0000000..5151e54
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_starting3.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopped.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopped.gif
new file mode 100644
index 0000000..d6c3b65
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopped.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopping1.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopping1.gif
new file mode 100644
index 0000000..306c57d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopping1.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopping2.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopping2.gif
new file mode 100644
index 0000000..d6c3b65
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopping2.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopping3.gif b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopping3.gif
new file mode 100644
index 0000000..306c57d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/obj16/server_stopping3.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/ovr16/default_server_ovr.gif b/plugins/org.eclipse.wst.server.ui/icons/ovr16/default_server_ovr.gif
new file mode 100644
index 0000000..dbfcbc0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/ovr16/default_server_ovr.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/ovr16/server_ovr.gif b/plugins/org.eclipse.wst.server.ui/icons/ovr16/server_ovr.gif
new file mode 100644
index 0000000..aa8d52e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/ovr16/server_ovr.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/wizban/import_configuration_wiz.gif b/plugins/org.eclipse.wst.server.ui/icons/wizban/import_configuration_wiz.gif
new file mode 100644
index 0000000..f46e4e0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/wizban/import_configuration_wiz.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/wizban/new_server_project_wiz.gif b/plugins/org.eclipse.wst.server.ui/icons/wizban/new_server_project_wiz.gif
new file mode 100644
index 0000000..39458ba
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/wizban/new_server_project_wiz.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/wizban/new_server_wiz.gif b/plugins/org.eclipse.wst.server.ui/icons/wizban/new_server_wiz.gif
new file mode 100644
index 0000000..30de91f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/wizban/new_server_wiz.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/wizban/pub_resource_server_wiz.gif b/plugins/org.eclipse.wst.server.ui/icons/wizban/pub_resource_server_wiz.gif
new file mode 100644
index 0000000..c74d61a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/wizban/pub_resource_server_wiz.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/wizban/select_client_wiz.gif b/plugins/org.eclipse.wst.server.ui/icons/wizban/select_client_wiz.gif
new file mode 100644
index 0000000..5b13db2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/wizban/select_client_wiz.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/icons/wizban/select_server_wiz.gif b/plugins/org.eclipse.wst.server.ui/icons/wizban/select_server_wiz.gif
new file mode 100644
index 0000000..3a9dadb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/icons/wizban/select_server_wiz.gif
Binary files differ
diff --git a/plugins/org.eclipse.wst.server.ui/plugin.properties b/plugins/org.eclipse.wst.server.ui/plugin.properties
new file mode 100644
index 0000000..256a028
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/plugin.properties
@@ -0,0 +1,586 @@
+pluginName=Server UI
+providerName=IBM
+
+extensionPointEditorPages=Editor Pages
+extensionPointEditorPageSections=Editor Page Sections
+extensionPointEditorActions=Editor Actions
+extensionPointServerActions=Server Actions
+extensionPointServerImages=Server Images
+extensionPointWizardFragments=Wizard Fragments
+
+# --------------- Wizards ---------------
+# (If the first two lines in a group do not start with "wiz", it is because
+# those lines are displayed in the workbench "New" wizard. The rest of the
+# text is displayed in each actual wizard)
+
+wizardCategoryTitle=Server
+
+# New Server Project wizard
+newServerProject=Server Project
+newServerProjectDescription=Create a new server project
+wizNewServerProjectWizardTitle=Create a New Server Project
+wizNewServerProjectTitle=Create a project to hold server information
+wizNewServerProjectDescription=Choose a name for the new Server project.
+
+# New Server (and Configuration) Wizard
+newServer=Server
+newServerDescription=Define a new server
+wizNewServerWizardTitle=New Server
+wizNewServerTitle=Define a New Server
+wizNewServerDescription=Choose the type of server to create.
+wizNewServerName=Server n&ame:
+wizNewServerType=&Server type:
+wizNewServerConfigurationType=Server &configuration type:
+
+# Import Server Configuration wizard
+importServerConfiguration=Server Configuration
+importServerConfigurationDescription=Import an existing server configuration from the file system.
+wizImportConfigurationWizardTitle=Import a Server Configuration
+wizImportConfigurationTitle=Import a server configuration
+wizImportConfigurationDescription=Fill out the fields below to import the configuration.
+wizImportConfigurationType=Configuration type:
+wizImportConfigurationLocation=&Location:
+wizImportConfigurationFile=Choose the server configuration file
+wizImportConfigurationDirectory=Choose the directory containing the server configuration
+
+# Select Server wizard
+wizSelectServerWizardTitle=Server Selection
+wizSelectServerTitle=Server selection
+wizSelectServerDescription=Select which server to launch.
+wizSelectServerExisting=Use an e&xisting server
+wizSelectServerPreconfigured=The server is already configured for this project
+wizSelectServerUnconfigured=The server will be automatically configured for this project
+wizSelectServerUnconfigurable=The server cannot be used with this project
+wizSelectServerStatusPreconfigured=Configured
+wizSelectServerStatusUnconfigured=Not configured
+wizSelectServerStatusUnconfigurable=Incompatible
+wizSelectServerAutogenerate=&Create a new server
+wizSelectServerPreferred=Set server as project &default (do not prompt)
+wizSelectServerIncompatibleRuntime=The project is targeted to a runtime that may be incompatible.
+
+# Select Server Client Wizard
+wizSelectClientWizardTitle=Select a Server Client
+wizSelectClientTitle=Select a server client
+wizSelectClientDescription=Select a client to use with this server.
+wizSelectClientMessage=Multiple clients can run on the current selection. Select a client from the list below:
+
+# Task Wizard
+wizTaskWizardTitle=Select Tasks
+wizTaskTitle=Select Tasks
+wizTaskDescription=Select the tasks to complete before launching the server.
+wizTaskDetail=Tasks for:
+
+# Publisher Wizard
+wizPublishWizardTitle=Publish Wizard
+wizPublishTitle=Resource Publish Selection
+wizPublishDescription=Select the resources that you want to publish or delete from the server.
+
+wizPublishColumnLocal=Workspace Resource
+wizPublishColumnRemote=Server Resource
+wizPublishColumnStatus=Status
+wizPublishColumnAction=Action
+wizPublishDeletedFolder=<deleted resources>
+wizPublishDeletedResource=<unknown>
+
+wizPublishStateNew=Added to workspace
+wizPublishStateUnmodified=Unmodified
+wizPublishStateModifiedLocal=Modified in workspace
+wizPublishStateModifiedRemote=Modified on server
+wizPublishStateModifiedBoth=Modified
+wizPublishStateDeleted=Deleted from workspace
+
+wizPublishStateNewDescription=The selected resource has been added to the workspace or deleted from the server since the last publish.
+wizPublishStateUnmodifiedDescription=The selected resource has not been modified in the workspace or on the server since the last publish.
+wizPublishStateModifiedLocalDescription=The selected resource has been modified in the workspace since the last publish.
+wizPublishStateModifiedRemoteDescription=The selected resource has been modified on the server since the last publish.
+wizPublishStateModifiedBothDescription=The selected resource has been modified in the workspace and on the server since the last publish.
+wizPublishStateDeletedDescription=The selected resource has been deleted from the workspace or added to the server since the last publish.
+
+wizPublishActionPublish=Publish to server
+wizPublishActionDelete=Delete from server
+
+wizPublishFilter=Resource Filter...
+wizPublishFilterTitle=Resource Filters
+wizPublishFilterMessage=Select the type of resources to filter:
+
+wizPublishFilterUnpublished=Unpublished resources
+wizPublishFilterNew=Added resources
+wizPublishFilterUnmodified=Unmodified resources
+wizPublishFilterModified=Modified resources
+wizPublishFilterDeleted=Deleted resources
+
+wizPublishFilterUnpublishedDescription=Filters resources that are never published to the server.
+wizPublishFilterNewDescription=Filters resources that have been added to the workspace.
+wizPublishFilterUnmodifiedDescription=Filters resources that have not been modified.
+wizPublishFilterModifiedDescription=Filters resources that have been modified.
+wizPublishFilterDeletedDescription=Filters resources that have been deleted from the workspace.
+
+# Server Capability
+wizServerCapabilityReady=Server project capability ready.
+wizServerCapabilityDetails=Create a server project to hold servers and server configurations
+wizServerCapabilityDescription=Server projects can be used to hold server resources such as servers and server configurations.
+
+# New Runtime Wizard
+wizNewRuntimeWizardTitle=New Server Runtime
+wizNewRuntimeTitle=New Server Runtime
+wizNewRuntimeDescription=Define a new installed server runtime environment
+wizEditRuntimeWizardTitle=Edit Server Runtime
+
+# Add/Remove Modules
+wizModuleWizardTitle=Add and Remove Projects
+wizModuleTitle=Add and Remove Projects
+wizModuleDescription=Modify the projects that are configured on the server
+wizModuleMessage=Move projects to the right to configure them on the server
+wizModuleAvailableList=&Available projects:
+wizModuleDeployedList=&Configured projects:
+wizModuleAdd=A&dd >
+wizModuleAddAll=Add A&ll >>
+wizModuleRemove=< &Remove
+wizModuleRemoveAll=<< Re&move All
+
+# General text used in multiple wizards
+wizFolder=F&older:
+wizCreate=Create...
+wizBrowse=B&rowse...
+wizChooseFolder=Select a server project folder
+wizDescription=Description:
+wizNone=None
+wizOther=Other
+
+# Wizard info and error messages
+wizErrorInvalidFolder=The folder must be a server project or a folder within a server project
+wizErrorClosedProject=The folder must not be in a closed project
+wizErrorInvalidElement=Select an existing server resource
+wizErrorResourceAlreadyExists=The specified resource already exists
+wizErrorUnknown=Unknown Error
+wizErrorServerCreationError=Cannot create a server using the selected type
+wizErrorConfigurationCreationError=Cannot create a server configuration using the selected type
+wizErrorLaunch=The resource you have selected cannot run with the server launcher
+wizErrorSelectServerType=Select a server type
+wizErrorSelectConfigurationType=Select a server configuration type
+wizErrorImport=Could not find a valid server configuration at the specified location
+
+
+# --------------- Views ---------------
+
+viewCategoryTitle=Server
+
+# --- Server Configuration view ---
+viewServers=Servers
+
+viewNoConfiguration=No configuration
+viewNoModules=Nothing deployed
+
+# Actions
+actionDelete=Delete
+actionDeleteConfiguration=Delete associated server configuration also
+actionOpen=Open
+actionBookmark=Add Bookmark
+actionSwitchConfiguration=Switch Configuration
+actionMonitor=Monitoring
+actionMonitorPort=Monitor port {0} ({1})
+actionMonitorProperties=Properties...
+actionNew=New
+actionNewServer=Server and Server Configuration
+actionNewServer=Server
+actionNewServerConfiguration=Server Configuration
+actionControl=Control
+
+# --- Servers view ---
+viewServersTitle=Servers
+
+# Column titles
+viewServer=Server
+viewHost=Host name
+viewStatus=Status
+viewSync=State
+
+actionRestartProject=Restart Project
+actionRuntimeTarget=Target Runtime...
+
+# Actions
+actionStart=Start
+actionStartToolTip=Start the server
+actionDebug=Debug
+actionDebugToolTip=Start the server in debug mode
+actionProfile=Profile
+actionProfileToolTip=Start the server in profiling mode
+actionStop=Stop
+actionStopToolTip=Stop the server
+actionRestart=Restart
+actionRestartToolTip=Restart the server
+actionPublish=Publish
+actionPublishToolTip=Publish to the server
+actionModifyModules=Add and remove projects...
+actionModifyModulesToolTip=Add and remove projects
+
+# Status column text
+viewStatusStarting=Starting
+viewStatusStarted=Started
+viewStatusStartedDebug=Debugging
+viewStatusStartedProfile=Profiling
+viewStatusStopping=Stopping
+viewStatusStopped=Stopped
+viewStatusUnsupported=Unsupported
+
+viewStatusStarting1=Starting.
+viewStatusStarting2=Starting..
+viewStatusStarting3=Starting...
+
+viewStatusStopping1=Stopping.
+viewStatusStopping2=Stopping..
+viewStatusStopping3=Stopping...
+
+# Server State text
+viewSyncOkay=Synchronized
+viewSyncRestart=Restart
+viewSyncPublish=Republish
+viewSyncRestartPublish=Restart & republish
+viewSyncPublishing=Publishing...
+
+# --- set 2 ---
+# Actions
+actionStart2=Connect
+actionStartToolTip2=Connect the server
+actionDebug2=Debug
+actionDebugToolTip2=Connect to the server in debug mode
+actionProfile2=Profile
+actionProfileToolTip2=Connect to the server in profiling mode
+actionStop2=Disconnect
+actionStopToolTip2=Disconnect from the server
+actionRestart2=Reconnect
+actionRestartToolTip2=Reconnect to the server
+actionPublish2=Publish
+actionPublishToolTip2=Publish to the server
+
+# Status column text
+viewStatusStarting4=Connecting
+viewStatusStarted2=Connected
+viewStatusStartedDebug2=Debugging
+viewStatusStopping4=Disconnecting
+viewStatusStopped2=Disconnected
+viewStatusUnsupported2=Unsupported
+viewStatusStartedProfile2=Profiling
+
+# Server State text
+viewSyncOkay2=Synchronized
+viewSyncRestart2=Reconnect
+viewSyncPublish2=Republish
+viewSyncRestartPublish2=Reconnect and republish
+viewSyncPublishing2=Publishing...
+
+
+# --------------- Action Sets (toolbar icon groups) ---------------
+
+# Servers action set
+actionSetTitle=Server
+actionSetNewServer=Create Server and Server Configuration
+actionSetNewServer=Create Server
+actionSetNewServerConfiguration=Create Server Configuration
+actionSetNewServerProject=Create Server Project
+
+# Run on Server actions
+actionRunOnServer=Run on Server...
+actionDebugOnServer=Debug on Server...
+actionProfileOnServer=Profile on Server...
+
+
+# --------------- Preferences ---------------
+
+# Names of the preference pages
+preferenceServersTitle=Server
+preferenceRuntimesTitle=Installed Runtimes
+preferenceRuntimesTitleLong=Installed Server Runtime Environments
+preferenceMonitorTitle=Monitoring
+
+# Server preferences
+prefShowPublishingDetails=Keep publishing dialog &open after publishing
+prefPublishBeforeStarting=Automatically p&ublish before starting servers
+prefAutoRestart=Automatically &restart servers when necessary
+prefPromptIrreversible=Prompt before making &irreversible changes within an editor
+prefPromptTerminate=Prompt to terminate a stoppin&g server after:
+prefPromptTerminateSeconds=s
+prefCreateInWorkspace=Create server resources in workspace
+
+prefRepairModuleGroup=Repair invalid servers
+prefRepairModuleNever=Ne&ver
+prefRepairModulePrompt=Promp&t
+prefRepairModuleAutomatic=Automati&cally
+
+prefPublisher=&Publishing method:
+prefPromptDelete=Confirm deletion of unused server configurations
+promptDelete=Always delete without prompt
+
+prefSaveEditorsGroup=Save dirty editors before starting server
+prefSaveEditorsNever=&Never
+prefSaveEditorsPrompt=Pro&mpt
+prefSaveEditorsAutosave=Auto-sav&e
+
+# Project properties preferences
+propertiesServer=Server
+prefProjectDescription=Set the runtime target and the default server for the project. To edit a runtime or it's location, go to the Window > Preferences > Servers > Installed Runtimes preference page.
+prefProject=Project:
+prefProjectDefaultServer=Default server:
+prefProjectNotModule=This project cannot be deployed to a server.
+prefProjectNotConfigured=Not currently deployed to any servers
+prefProjectNoServer=<None>
+
+# Installed runtimes
+preferenceRuntimesDescription=Add, remove, or edit installed server runtime definitions.\nInstalled server runtimes:
+
+
+# --------------- Tasks (progress monitors) ---------------
+
+# Creating default server and server configuration
+createServerProjectTask=Creating server project.
+createDefaultServerTask=Creating server.
+createDefaultServerConfigurationTask=Creating server configuration.
+
+# Modifying and searching for servers
+addProjectToConfigurationTask=Adding project {0} to {1}.
+removeProjectFromConfiguration=Removing project {0} from {1}.
+setInstanceConfigurationTask=Setting the configuration of {0} to {1}.
+removingInstanceConfigurationTask=Removing the configuration from {0}.
+getDefaultServerTask=Searching for a default server.
+getProjectServerTask=Locating a server.
+
+# General tasks
+copyingTask=Copying from {0} to {1}.
+unZippingTask=Unzipping {0}.
+expandingTask=Expanding {0}.
+savingTask=Saving {0}.
+deletingTask=Deleting {0}.
+loadingTask=Loading {0}.
+copyingTask=File copied successfully to {0}
+performingTasks=Performing tasks.
+
+publishingTask=Publishing to {0}.
+publishingStatus=Publishing status
+publishingStart=Connecting to server
+publishingStop=Disconnecting from server
+
+publishingPublishFolder=Creating folder {0}.
+publishingPublishFile=Publishing {0}.
+publishingDeleteFolder=Removing folder {0}.
+publishingDeleteFile=Deleting {0}.
+publishingProject=Publishing project: {0}
+publishingConfiguration=Publishing configuration: {0}
+
+# --------------- Dialogs ---------------
+
+# Delete Server Resource dialog
+deleteServerResourceDialogTitle=Delete Server Resource
+deleteServerResourceDialogMessage=Are you sure you want to delete {0}?
+deleteServerResourceDialogMessageMany=Are you sure you want to delete the {0} server resources?
+deleteServerResourceDialogLooseConfigurations=Also delete unused server configuration {0}.
+deleteServerResourceDialogLooseConfigurationsMany=Also delete {0} unused server configurations.
+
+# Create Server Project dialog
+createServerProjectDialogTitle=Create Server Project
+createServerProjectDialogMessage=Do you want to create a new server project with the name {0}?
+
+# Terminate Server dialog
+terminateServerDialogTitle=Terminate Server
+terminateServerDialogMessage=Server {0} is not responding. Do you want to terminate this server? Click OK to terminate the server or click Cancel to continue waiting.
+
+# Server resource dirty dialog
+resourceDirtyDialogTitle=Server Resource Dirty
+resourceDirtyDialogMessage=The server resource {0} has unsaved changes. Do you want to continue?
+resourceDirtyDialogContinue=Continue
+
+runtimeTargetDialogTitle=Modify Target Runtime
+runtimeTargetMessage=Select a target runtime for the {0} project.
+runtimeTargetCombo=Target runtime:
+runtimeTargetInformation=dddddddddddddddddd
+runtimeTargetNone=<None>
+runtimeTargetScope=Update {0} to have the same target runtime
+runtimeTargetNewRuntime=New...
+runtimeTargetChildren=Include child projects
+
+# Publishing dialog text and status
+publishingTitle=Publishing
+publishingBusy=Publishing...
+publishingOK=Publishing was successful
+publishingInfo=Publishing completed with information
+publishingWarning=Publishing completed with warning(s)
+publishingError=Publishing failed
+publishingCancelled=Publishing cancelled
+publishingTime={0}s
+
+# General dialogs
+defaultDialogTitle=Server
+dialogStoppingServer=Stopping server {0}.
+dialogRestartingProject=Restarting project {0}.
+
+# Configuration repair dialog
+dialogRepairConfigurationTitle=Repair Server Configuration
+dialogRepairConfigurationMessage=The following server configurations were affected by the changes and will be modified:
+dialogRepairConfigurationSaveMessage=Select the server configurations to save so that they can be repaired.
+
+# restart warning dialog
+dialogModeWarningDebug=The server is not running in debug mode. You may restart the server in debug mode, continue without debugging, or cancel the operation.
+dialogModeWarningProfile=The server is not running in profiling mode. You may restart the server in profiling mode, continue without profiling, or cancel the operation.
+dialogModeWarningRestart=Restart
+dialogModeWarningContinue=Continue
+
+# Monitor dialog
+dialogMonitorTitle=Monitoring Ports
+dialogMonitorDescription=The following ports are being monitored on server {0}:
+dialogMonitorAddDescription=The server {0} has the following ports that can be monitored:
+dialogMonitorColumnPort=Server Port
+dialogMonitorColumnType=Type
+dialogMonitorColumnMonitorPort=Monitor Port
+dialogMonitorColumnContentType=Content Type
+dialogMonitorColumnStatus=Status
+dialogMonitorMonitorPort=Monitor port:
+dialogMonitorContentType=Content type:
+dialogMonitorContentTypeAll=All
+dialogMonitorContentTypeWeb=Web
+dialogMonitorContentTypeWebServices=WebServices
+
+start=Start
+stop=Stop
+started=Started
+stopped=Stopped
+
+# Confirm runtime removal
+dialogRuntimeInUse=The runtime is currently being used and deleting it will cause compilation or runtime problems. Delete the runtime anyway?
+
+# Can't add remove
+dialogAddRemoveModulesNone=There are no projects that can be added or removed from the server.
+
+# --------------- Misc UI ---------------
+
+serverLaunchShortcut=Run on Server
+
+serverEditor=Server Editor
+
+# runtime composite
+runtimeTypeCompDescription=Runtimes are used at build time to compile projects.
+runtimeTypeCompTree=Select the type of &runtime that you want to define:
+serverTypeCompDescription=Select the &server type:
+name=Name
+vendor=Vendor
+version=Version
+host=Host name
+moduleSupport=Module Support
+viewBy=&View By:
+
+# misc composites
+hostnameTitle=Specify the host where you want to publish
+hostname=&Host name:
+
+# Server launch configuration tab
+serverLaunchConfigurationTab=Server
+serverLaunchStartMode=Start mode:
+serverLaunchServer=Server:
+serverLaunchServerType=Server type:
+serverLaunchReady=Server is ready to launch
+
+# Error Messages
+errorDialogTitle=Server Error
+errorUnconfiguredServer=Unable to run the server because it does not have a valid configuration.
+errorCloseEditor=Close the open editor on {0} before performing this action.
+errorLaunch=Cannot start the server.
+errorServerAlreadyRunning=Server already running
+errorServerStartFailed=The server named {0} did not start correctly. Check the Console for error messages.
+errorPublishing=Could not publish to the server.
+errorNoConfiguration=The server does not have a configuration.
+errorPublishFailed=Errors occurred during publishing.
+errorRunOnServer=Running resource on server.
+errorRunOnServerFailed=Unable to run on server.
+errorLoadingConfiguration=Error loading server configuration from {0}.
+errorSavingResource=Could not save server resource.
+errorMissingConfiguration=Server configuration is missing - See Task view
+errorMissingConfigurationTask=Server {0} cannot find the server configuration located at {1}. Replace the server configuration or use the Server Configuration view to set a new configuration.
+errorMissingProject=Project {0} is missing - See Task view
+errorMissingProjectTask=Server configuration {0} refers to a missing project {1}
+errorCopyingFile=Error copying file to {0}: {1}
+errorModifyingConfiguration=Error modifying server configuration: {0}
+errorModifyingInstance=Error modifying server: {0}
+errorCouldNotCreateServerProject=Could not create server project
+errorCouldNotCreateServerProjectStatus=Could not create server project: {0}
+errorNoModules=Did not find anything to deploy to a server
+errorNoServer=Could not find a server to run the selection
+errorNoClient=Could not find a client that is able to launch the selection
+errorCouldNotSavePreference=Could not save server preference information.
+errorEditorCantSave=Can't save the server resource for the following reason(s):
+errorSelectServer=A server must be selected.
+
+# Info messages
+infoNoPublishingNecessary=Publishing was not necessary
+infoPublishSuccess=Published finished successfully
+
+# Default server creation names
+# {0} will be replaced by a number if the given name is already being used
+defaultServerProjectName=Servers{0}
+defaultServerInstanceName=defaultServer{0}
+defaultServerConfigurationName=defaultConfiguration{0}
+
+serverStartError=Error received while starting the server
+
+# Used when a name can't be found
+elementUnknownName=<unknown>
+
+# Publish manager
+publisherVisualName=Prompt user
+publisherVisualDescription=Prompts the user to choose which resources to publish to or delete from the server.
+
+columnName=Name
+columnType=Type
+
+add=Add...
+edit=Edit...
+remove=Remove
+search=Search...
+
+
+# --------------- Editor support ---------------
+
+serverEditorOverviewPage=Overview
+serverEditorOverviewPageTitle=Server Overview
+serverEditorOverviewSection=General
+serverEditorOverviewDescription=Specify the host name and other settings.
+serverEditorOverviewServerName=Server name:
+serverEditorOverviewServerNameCommand=set server name
+serverEditorOverviewServerNameDescription=Set the server name
+serverEditorOverviewServerConfigurationName=Server configuration name:
+serverEditorOverviewServerConfigurationNameCommand=set server configuration name
+serverEditorOverviewServerConfigurationNameDescription=Set the server configuration name
+serverEditorOverviewServerHostname=Host name:
+serverEditorOverviewServerHostnameCommand=set host name
+serverEditorOverviewServerHostnameDescription=Set the host name
+
+# Menu items. {0} will be replaced by one of the xxxEditorActionXxx fields
+# from below. @Ctrl+Z is the menu mnemonic
+editorUndoEnabled=Undo {0}@Ctrl+Z
+editorUndoDisabled=Undo@Ctrl+Z
+editorRedoEnabled=Redo {0}@Ctrl+Y
+editorRedoDisabled=Redo@Ctrl+Y
+
+editorSaveErrorDialog=Save Problems
+editorSaveErrorMessage=Error while saving. {0}
+
+editorReadOnly=Read Only
+editorWritable=Writable
+editorReadOnlyFiles=Read Only files: {0}
+
+editorServerEditor=Server Editor
+editorPromptIrreversible=This operation cannot be undone. Do you want to proceed?
+
+# message if a dirty resource is deleted
+editorResourceDeleteTitle=Server Resource Deleted
+editorResourceDeleteBothMessage=The server {0} and the server configuration {1} have been deleted from the file system. Do you want to save your changes or close the editor without saving?
+editorResourceDeleteServerMessage=The server {0} has been deleted from the file system. Do you want to save your changes or close the editor without saving?
+editorResourceDeleteServerConfigurationMessage=The server configuration {0} has been deleted from the file system. Do you want to save your changes or close the editor without saving?
+editorResourceDeleteSave=Save
+
+editorResourceModifiedTitle=File Changed
+editorServerModifiedMessage=The server has been changed on the file system. Do you want to load the changes?
+editorServerConfigurationModifiedMessage=The server configuration has been changed on the file system. Do you want to load the changes?
+
+editorValidateEditFailureMessage=The server resource cannot be edited.
+editorReadOnlyMessage=File(s) being edited have become read-only. The editor will become read-only and changes will be lost.
+
+editorResourceWarnTitle=Server Modification Warning
+editorResourceWarnMessage=The resource you are modifying is read-only. All changes will be lost because the resource cannot be saved. 
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/plugin.xml b/plugins/org.eclipse.wst.server.ui/plugin.xml
new file mode 100644
index 0000000..09993e5
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/plugin.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+
+<plugin id="org.eclipse.wst.server.ui"
+  name="%pluginName"
+  version="3.0.0"
+  provider-name="%providerName"
+  class="org.eclipse.wst.server.ui.internal.ServerUIPlugin">
+
+<requires>
+  <import plugin="org.eclipse.core.runtime" version="3.0.0" match="equivalent"/>
+  <import plugin="org.eclipse.core.resources" version="3.0.0" match="equivalent"/>
+  <import plugin="org.eclipse.ui" version="3.0.0" match="equivalent"/>
+  <import plugin="org.eclipse.ui.ide" version="3.0.0" match="equivalent"/>
+  <import plugin="org.eclipse.ui.views" version="3.0.0" match="equivalent"/>
+  <import plugin="org.eclipse.ui.editors" version="3.0.0" match="equivalent"/>
+  <import plugin="org.eclipse.ui.forms" version="3.0.0" match="equivalent"/>
+  <import plugin="org.eclipse.ui.workbench.texteditor" version="3.0.0" match="equivalent"/>
+  <import plugin="org.eclipse.debug.core" version="3.0.0" match="equivalent"/>
+  <import plugin="org.eclipse.debug.ui" version="3.0.0" match="equivalent"/>
+  <import plugin="org.eclipse.wst.server.core" version="3.0.0" match="equivalent"/>
+</requires>
+
+<runtime>
+  <library name="serverui.jar">
+    <export name="*"/>
+    <packages prefixes="org.eclipse.wst.server.ui"/>
+  </library>
+</runtime>
+
+  <extension-point id="editorPages" name="%extensionPointEditorPages" schema="schema/editorPages.exsd"/>
+  <extension-point id="editorPageSections" name="%extensionPointEditorPageSections" schema="schema/editorPageSections.exsd"/>
+  <extension-point id="editorActions" name="%extensionPointEditorActions" schema="schema/editorActions.exsd"/>
+  <extension-point id="serverActions" name="%extensionPointServerActions" schema="schema/serverActions.exsd"/>
+  <extension-point id="serverImages" name="%extensionPointServerImages" schema="schema/serverImages.exsd"/>
+  <extension-point id="wizardFragments" name="%extensionPointWizardFragments" schema="schema/wizardFragments.exsd"/>
+
+<extension point="org.eclipse.ui.ide.projectNatureImages">
+  <image
+    id="org.eclipse.wst.server.ui.projectNatureImage"
+    natureId="org.eclipse.wst.server.core.nature"
+    icon="icons/ovr16/server_ovr.gif"/>
+</extension>
+
+<extension point="org.eclipse.ui.newWizards">
+  <category
+    id="org.eclipse.wst.server.ui"
+    name="%wizardCategoryTitle"/>
+  <wizard
+      id="org.eclipse.wst.server.ui.new.server.project"
+      name="%newServerProject"
+      project="true"
+      finalPerspective="org.eclipse.wst.server.ui.perspective"
+      class="org.eclipse.wst.server.ui.internal.wizard.NewServerProjectWizard"
+      category="org.eclipse.wst.server.ui"
+      icon="icons/ctool16/wiz_new_server_project.gif">
+    <description>%newServerProjectDescription</description>
+  </wizard>
+
+  <wizard
+      id="org.eclipse.wst.server.ui.new.server"
+      name="%newServer"
+      class="org.eclipse.wst.server.ui.internal.wizard.NewServerWizard"
+      category="org.eclipse.wst.server.ui"
+      icon="icons/ctool16/wiz_new_server.gif">
+    <description>%newServerDescription</description>
+  </wizard>
+</extension>
+
+<extension point="org.eclipse.ui.importWizards">
+  <wizard
+      id="org.eclipse.wst.server.ui.import.configuration"
+      name="%importServerConfiguration"
+      class="org.eclipse.wst.server.ui.internal.wizard.ImportServerConfigurationWizard"
+      icon="icons/ctool16/wiz_import_configuration.gif">
+    <description>%importServerConfigurationDescription</description>
+  </wizard>
+</extension>
+
+<extension point="org.eclipse.ui.views"> 
+  <category
+    id="org.eclipse.wst.server.ui"
+    name="%viewCategoryTitle"/>
+
+  <view
+    id="org.eclipse.wst.server.ui.ServersView"
+    name="%viewServersTitle"
+    category="org.eclipse.wst.server.ui"
+    class="org.eclipse.wst.server.ui.internal.view.servers.ServersView"
+    icon="icons/cview16/servers_view.gif"/>
+</extension>
+
+<extension point="org.eclipse.ui.perspectiveExtensions">
+  <perspectiveExtension
+    targetID="org.eclipse.debug.ui.DebugPerspective">
+    <view
+      relative="org.eclipse.debug.ui.DebugView"
+      relationship="stack"
+      id="org.eclipse.wst.server.ui.ServersView">
+    </view>
+  </perspectiveExtension>
+</extension>
+
+<extension point="org.eclipse.ui.preferencePages">
+  <page
+    id="org.eclipse.wst.server.ui.preferencePage"
+    name="%preferenceServersTitle"
+    class="org.eclipse.wst.server.ui.internal.ServerPreferencePage"/>
+  <page
+    id="org.eclipse.wst.server.ui.runtime.preferencePage"
+    name="%preferenceRuntimesTitle"
+    category="org.eclipse.wst.server.ui.preferencePage"
+    class="org.eclipse.wst.server.ui.internal.RuntimePreferencePage"/>
+</extension>
+
+<extension point="org.eclipse.ui.editors">
+  <editor id="org.eclipse.wst.server.ui.editor"
+    name="%serverEditor"
+    icon="icons/obj16/server.gif"
+    extensions="server, config"
+    default="true"
+    class="org.eclipse.wst.server.ui.internal.editor.ServerEditor"
+    contributorClass="org.eclipse.wst.server.ui.internal.editor.ServerEditorActionBarContributor"/>
+</extension>
+
+<extension point="org.eclipse.ui.elementFactories">
+  <factory id="org.eclipse.wst.server.ui.editor.input.factory"
+    class="org.eclipse.wst.server.ui.internal.editor.ServerEditorInputFactory"/>
+</extension>
+
+<extension point="org.eclipse.ui.propertyPages">
+  <page
+    id="org.eclipse.wst.server.ui.project.properties"
+    name="%propertiesServer"
+    objectClass="org.eclipse.core.resources.IProject"
+    adaptable="true"
+    class="org.eclipse.wst.server.ui.internal.ProjectPropertyPage"/>
+</extension>
+
+<extension point="org.eclipse.ui.actionSets">
+  <actionSet
+    id="org.eclipse.wst.server.ui.new.actionSet"
+    label="%actionSetTitle"
+    visible="false">
+    <action
+      id="org.eclipse.wst.server.ui.action.new.server"
+      toolbarPath="servers"
+      label="%actionSetNewServer"
+      tooltip="%actionSetNewServer"
+      icon="icons/ctool16/wiz_new_server.gif"
+      class="org.eclipse.wst.server.ui.internal.actions.NewServerAction"/>
+
+    <action
+      id="org.eclipse.wst.server.ui.action.new.server.project"
+      toolbarPath="servers"
+      label="%actionSetNewServerProject"
+      tooltip="%actionSetNewServerProject"
+      icon="icons/ctool16/wiz_new_server_project.gif"
+      class="org.eclipse.wst.server.ui.internal.actions.NewServerProjectAction"/>
+  </actionSet>
+</extension>
+
+<extension point="org.eclipse.debug.ui.launchShortcuts">
+   <shortcut id="org.eclipse.wst.server.core.launchShortcut"
+      label="%serverLaunchShortcut"
+      class="org.eclipse.wst.server.ui.internal.ServerLaunchShortcut"
+      modes="run, debug, profile"
+      path="aa"
+      icon="icons/etool16/run_on_server.gif">
+      <contextualLaunch>
+        <enablement>
+           <with variable="selection">
+             <count value="1"/>
+             <!--<iterate>
+               <or>
+                 <test property="org.eclipse.debug.ui.matchesPattern" value="*.txt"/>
+                 <test property="org.eclipse.debug.ui.matchesPattern" value="*.java"/>
+                 <test property="org.eclipse.debug.ui.matchesPattern" value="*.class"/>
+               </or>
+               <test property="org.eclipse.wst.server.ui.isRunnable"/>
+             </iterate>-->
+           </with>
+         </enablement>
+      
+        <contextLabel
+           mode="run"
+           label="%actionRunOnServer"/>
+        <contextLabel
+           mode="debug"
+           label="%actionDebugOnServer"/>
+        <contextLabel
+           mode="profile"
+           label="%actionProfileOnServer"/>
+      </contextualLaunch>
+<!--    <perspective id="org.eclipse.wst.server.ui.perspective"/>
+    <perspective id="org.eclipse.jdt.ui.JavaPerspective"/>
+    <perspective id="org.eclipse.jdt.ui.JavaHierarchyPerspective"/>
+    <perspective id="org.eclipse.jdt.ui.JavaBrowsingPerspective"/>
+    <perspective id="org.eclipse.debug.ui.DebugPerspective"/>
+    <perspective id="com.ibm.etools.j2ee.J2EEPerspective"/>
+    <perspective id="org.eclipse.ui.resourcePerspective"/>-->
+   </shortcut>
+</extension>
+
+<extension point="org.eclipse.wst.server.core.publish">
+  <publish
+    id="org.eclipse.wst.server.ui.publish.visual"
+    name="%publisherVisualName"
+    description="%publisherVisualDescription"
+    class="org.eclipse.wst.server.ui.internal.publish.VisualPublisher"/>
+</extension>
+
+<extension point="org.eclipse.wst.server.ui.serverActions">
+  <serverAction id="org.eclipse.wst.server.ui.projects"
+    typeIds="*"
+    label="%actionModifyModules"
+    category="control"
+    icon="icons/ctool16/wiz_modify_modules.gif"
+    order="50"
+    class="org.eclipse.wst.server.ui.internal.actions.AddRemoveModulesAction"/>
+</extension>
+
+   <extension point="org.eclipse.wst.server.ui.editorPages">
+      <page
+         id="org.eclipse.wst.server.editor.overview"
+         order="-10000"
+         name="%serverEditorOverviewPage"
+         typeIds="*"
+         insertionIds="org.eclipse.wst.server.editor.overview.left, org.eclipse.wst.server.editor.overview.right"
+         class="org.eclipse.wst.server.ui.internal.editor.OverviewEditorFactory"/>
+   </extension>
+
+</plugin>
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/schema/editorActions.exsd b/plugins/org.eclipse.wst.server.ui/schema/editorActions.exsd
new file mode 100644
index 0000000..b3672a6
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/schema/editorActions.exsd
@@ -0,0 +1,130 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.ui">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.ui" id="editorActions" name="Editor Actions"/>

+      </appInfo>

+      <documentation>

+         This extension point provides a way to add actions to the toolbar of an existing server editor.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="editorAction" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="editorAction">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;ILaunchConfigurationDelegate&lt;/samp&gt;.
+Launch configuration instances of this type will delegate to instances of this class to perform launching.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="typeIds" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="order" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of an editor action extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+ 
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.ui/schema/editorPageSections.exsd b/plugins/org.eclipse.wst.server.ui/schema/editorPageSections.exsd
new file mode 100644
index 0000000..943d443
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/schema/editorPageSections.exsd
@@ -0,0 +1,137 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.ui">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.ui" id="EditorPageSections" name="Editor Page Sections"/>

+      </appInfo>

+      <documentation>

+         This extension point provides a way to add additional sections into an existing server editor page that contains insertion points.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <choice>

+            <element ref="section"/>

+         </choice>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="section">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;ILaunchConfigurationDelegate&lt;/samp&gt;.
+Launch configuration instances of this type will delegate to instances of this class to perform launching.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="typeIds" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="order" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="insertionId" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of an editor page section extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+ &lt;extension point=&quot;org.eclipse.wst.server.ui.editorPageSections&quot;&gt;
+    &lt;section
+       id=&quot;com.example&quot;
+       order=&quot;0&quot;
+       insertionId=&quot;com.example.left&quot;
+       typeIds=&quot;com.example.*&quot;
+         class=&quot;com.example.ExampleEditorSectionFactory&quot;/&gt;
+ &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.ui.editor.IServerEditorPageSectionFactoryDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.ui/schema/editorPages.exsd b/plugins/org.eclipse.wst.server.ui/schema/editorPages.exsd
new file mode 100644
index 0000000..d64852c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/schema/editorPages.exsd
@@ -0,0 +1,144 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.ui">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.ui" id="EditorPages" name="Editor Pages"/>

+      </appInfo>

+      <documentation>

+         This extension point provides a way to add an additional page to a server or server configuration editor.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <choice>

+            <element ref="page"/>

+         </choice>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="page">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;ILaunchConfigurationDelegate&lt;/samp&gt;.
+Launch configuration instances of this type will delegate to instances of this class to perform launching.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="typeIds" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="order" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="insertionIds" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of an editor page extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+  &lt;extension point=&quot;org.eclipse.wst.server.ui.editorPages&quot;&gt;
+    &lt;page
+       id=&quot;com.example&quot;
+       order=&quot;20&quot;
+       name=&quot;%editorPage&quot;
+       typeIds=&quot;com.example.*&quot;
+         class=&quot;com.example.ExampleEditorFactory&quot;/&gt;
+   &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.ui.editor.IServerEditorPartFactoryDelegate&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.ui/schema/serverActions.exsd b/plugins/org.eclipse.wst.server.ui/schema/serverActions.exsd
new file mode 100644
index 0000000..1095b93
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/schema/serverActions.exsd
@@ -0,0 +1,144 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.ui">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.ui" id="ServerActions" name="Server Actions"/>

+      </appInfo>

+      <documentation>

+         This extension point provides a way to add an action into the Servers view.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="serverAction" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="serverAction">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;ILaunchConfigurationDelegate&lt;/samp&gt;.
+Launch configuration instances of this type will delegate to instances of this class to perform launching.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="typeIds" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="label" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="category" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="icon" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="order" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a server action extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+ 
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.ui/schema/serverImages.exsd b/plugins/org.eclipse.wst.server.ui/schema/serverImages.exsd
new file mode 100644
index 0000000..5f0e36a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/schema/serverImages.exsd
@@ -0,0 +1,117 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.ui">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.ui" id="serverImages" name="Server Images"/>

+      </appInfo>

+      <documentation>

+         This extension point provides a way to provide an image for a runtime, server, server configuration or module type.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <choice>

+            <element ref="image" minOccurs="0" maxOccurs="unbounded"/>

+         </choice>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="image">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="icon" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="typeIds" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a server image extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+ &lt;extension point=&quot;org.eclipse.wst.server.ui.serverImages&quot;&gt;
+    &lt;image
+       id=&quot;com.example&quot;
+       icon=&quot;icons/obj16/runtime.gif&quot;
+       typeIds=&quot;com.example.runtime&quot;/&gt;
+ &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.ui/schema/wizardFragments.exsd b/plugins/org.eclipse.wst.server.ui/schema/wizardFragments.exsd
new file mode 100644
index 0000000..966da6d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/schema/wizardFragments.exsd
@@ -0,0 +1,121 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.server.ui">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.server.ui" id="WizardFragments" name="Wizard Fragments"/>

+      </appInfo>

+      <documentation>

+         This extension point provides a way to add pages or logic into wizards for a specific runtime, server, or server configuration type.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="fragment" minOccurs="0" maxOccurs="unbounded"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="fragment">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="name"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies a unique identifier for this extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  specifies the fully qualified name of the Java class that implements &lt;samp&gt;ILaunchConfigurationDelegate&lt;/samp&gt;.
+Launch configuration instances of this type will delegate to instances of this class to perform launching.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.server.core.model.IStartup"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="typeIds" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         The following is an example of a wizard fragment extension point:
+
+&lt;p&gt;
+&lt;pre&gt;
+ &lt;extension point=&quot;org.eclipse.wst.server.ui.wizardFragments&quot;&gt;
+   &lt;fragment
+      id=&quot;com.example&quot;
+      typeIds=&quot;com.example.runtime&quot;
+      class=&quot;com.example.ExampleWizardFragment&quot;/&gt;
+ &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface &lt;b&gt;org.eclipse.wst.server.ui.wizard.IWizardFragment&lt;/b&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2000, 2003 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made 
+available under the terms of the Common Public License v1.0 which accompanies 
+this distribution, and is available at 
+&lt;a href=&quot;http://www.eclipse.org/legal/cpl-v10.html&quot;&gt;http://www.eclipse.org/legal/cpl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/IServerUIPreferences.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/IServerUIPreferences.java
new file mode 100644
index 0000000..6593b9d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/IServerUIPreferences.java
@@ -0,0 +1,88 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui;
+/**
+ * Helper class that stores preference information for
+ * the server tools UI.
+ *
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerUIPreferences {
+	public static final byte SAVE_EDITORS_NEVER = 0;
+	public static final byte SAVE_EDITORS_PROMPT = 1;
+	public static final byte SAVE_EDITORS_AUTO = 2;
+
+	/**
+	 * Returns whether the publishing details should be shown.
+	 *
+	 * @return boolean
+	 */
+	public boolean getShowPublishingDetails();
+
+	/**
+	 * Returns whether the publishing details should be shown by default.
+	 *
+	 * @return boolean
+	 */
+	public boolean getDefaultShowPublishingDetails();
+
+	/**
+	 * Sets whether the publishing details should be shown.
+	 *
+	 * @return boolean
+	 */
+	public void setShowPublishingDetails(boolean b);
+
+	/**
+	 * Returns whether the user should be prompted before making an
+	 * irreversible change in the editor.
+	 * 
+	 * @return boolean
+	 */
+	public boolean getPromptBeforeIrreversibleChange();
+
+	/**
+	 * Returns the default value of whether the user should be prompted
+	 * before making an irreversible change in the editor.
+	 *
+	 * @return boolean
+	 */
+	public boolean getDefaultPromptBeforeIrreversibleChange();
+
+	/**
+	 * Sets whether the user should be prompted before making an
+	 * irreversible change in the editor.
+	 *
+	 * @return boolean
+	 */
+	public void setPromptBeforeIrreversibleChange(boolean b);
+	
+	/**
+	 * Returns the default setting for saving editors before launching.
+	 * 
+	 * @return byte
+	 */
+	public byte getDefaultSaveEditors();
+
+	/**
+	 * Returns the setting for saving editors before launching.
+	 * 
+	 * @return byte
+	 */
+	public byte getSaveEditors();
+
+	/**
+	 * Sets the value for saving editors before launching.
+	 * 
+	 * @param byte
+	 */
+	public void setSaveEditors(byte b);
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerImageResource.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerImageResource.java
new file mode 100644
index 0000000..97bc810
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerImageResource.java
@@ -0,0 +1,59 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.swt.graphics.Image;
+/**
+ * Provides access to server UI general images. getImage() and getImageDescriptor()
+ * provide access (through keys in the class header) to the images that can be used
+ * for server state, publishing, etc.
+ */
+public class ServerImageResource {
+	// server state images
+	public static final String IMG_SERVER_STATE_UNKNOWN = "stateUnknown";
+	public static final String IMG_SERVER_STATE_STARTING = "stateStarting1";
+	public static final String IMG_SERVER_STATE_STARTED = "stateStarted";
+	public static final String IMG_SERVER_STATE_STARTED_DEBUG = "stateStartedDebug";
+	public static final String IMG_SERVER_STATE_STOPPING = "stateStopping1";
+	public static final String IMG_SERVER_STATE_STOPPED = "stateStopped";
+
+	// misc images
+	public static final String IMG_SERVER_PROJECT = "serverProject";
+	public static final String IMG_SERVER_CONFIGURATION = "configuration";
+	public static final String IMG_SERVER = "server";
+	public static final String IMG_SERVER_CONFIGURATION_NONE = "noConfiguration";
+	public static final String IMG_SERVER_CONFIGURATION_MISSING = "configurationMissing";
+	public static final String IMG_SERVER_CONFIGURATION_FOLDER = "configurationFolder";
+	public static final String IMG_SERVER_FOLDER = "serverFolder";
+	public static final String IMG_PROJECT_MISSING = "projectMissing";
+
+	/**
+	 * Return the image with the given key.
+	 *
+	 * @param key java.lang.String
+	 * @return org.eclipse.swt.graphics.Image
+	 */
+	public static Image getImage(String key) {
+		return ImageResource.getImage(key);
+	}
+
+	/**
+	 * Return the image descriptor with the given key.
+	 *
+	 * @param key java.lang.String
+	 * @return import org.eclipse.jface.resource.ImageDescriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String key) {
+		return ImageResource.getImageDescriptor(key);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerLaunchConfigurationTab.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerLaunchConfigurationTab.java
new file mode 100644
index 0000000..8b53b11
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerLaunchConfigurationTab.java
@@ -0,0 +1,277 @@
+package org.eclipse.wst.server.ui;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.help.WorkbenchHelp;
+
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.internal.ContextIds;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+
+public class ServerLaunchConfigurationTab extends AbstractLaunchConfigurationTab {
+	protected String[] serverTypeIds;
+
+	protected Combo serverCombo;
+	
+	protected Label runtimeLabel;
+	protected Label runtimeLocation;
+	
+	protected IServer server;
+	
+	// list of servers that are in combo
+	protected List servers;
+
+	// flag to be used to decide whether to enable combo in launch config dialog
+	// after the user requests a launch, they cannot change it
+	private static final String READ_ONLY = "read-only";
+
+	public ServerLaunchConfigurationTab() {
+		this(new String[] {"*"});
+	}
+
+	public ServerLaunchConfigurationTab(String[] serverTypeIds) {
+		this.serverTypeIds = serverTypeIds;
+	}
+
+	/**
+	 * @see ILaunchConfigurationTab#createControl(Composite)
+	 */
+	public void createControl(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.marginWidth = 10;
+		layout.marginHeight = 10;
+		layout.numColumns = 1;
+		composite.setLayout(layout);
+
+		GridData data = new GridData(GridData.FILL_HORIZONTAL);
+		composite.setLayoutData(data);
+
+		Label label = new Label(composite, SWT.WRAP);
+		label.setText(ServerUIPlugin.getResource("%serverLaunchServer"));
+		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		serverCombo = new Combo(composite, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
+		serverCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		serverCombo.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+			public void widgetSelected(SelectionEvent e) {
+				handleServerSelection();
+			}
+		});
+		WorkbenchHelp.setHelp(serverCombo, ContextIds.LAUNCH_CONFIGURATION_SERVER_COMBO);
+
+		runtimeLabel = new Label(composite, SWT.NONE);
+		runtimeLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		runtimeLocation = new Label(composite, SWT.NONE);
+		runtimeLocation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		
+		// initialize
+		List servers2 = ServerCore.getResourceManager().getServers();
+		servers = new ArrayList();
+		Iterator iterator = servers2.iterator();
+		while (iterator.hasNext()) {
+			IServer server2 = (IServer) iterator.next();
+			if (isSupportedServer(server2.getServerType().getId())) {
+				serverCombo.add(server2.getName());
+				servers.add(server2);
+			}
+		}
+
+		// select first item in list
+		if (serverCombo.getItemCount() > 0)
+			serverCombo.select(0);
+
+		handleServerSelection();
+
+		serverCombo.forceFocus();
+
+		Dialog.applyDialogFont(composite);
+		setControl(composite);
+	}
+	
+	protected boolean isSupportedServer(String serverTypeId) {
+		if (serverTypeIds == null)
+			return true;
+		int size = serverTypeIds.length;
+		for (int i = 0; i < size; i++) {
+			if (matches(serverTypeId, serverTypeIds[i]))
+				return true;
+		}
+		return false;
+	}
+	
+	protected static boolean matches(String a, String b) {
+		if (a == null || b == null || "*".equals(a) || "*".equals(b) || a.startsWith(b) || b.startsWith(a))
+			return true;
+		else
+			return false;
+	}
+	
+	protected void handleServerSelection() {
+		if (servers.isEmpty())
+			server = null;
+		else
+			server = (IServer) servers.get(serverCombo.getSelectionIndex());
+		IRuntime runtime = null;
+		if (server != null) {
+			runtime = server.getRuntime();
+			runtimeLocation.setText("Location: " + server.getHostname());
+		} else
+			runtimeLocation.setText("Location:");
+			
+		if (runtime != null)
+			runtimeLabel.setText("Runtime: " + runtime.getName());
+		else
+			runtimeLabel.setText("Runtime:");
+
+		if (server == null)
+			setErrorMessage(ServerUIPlugin.getResource("%noServerSelected"));
+		else if (server.getServerState() != IServer.SERVER_STOPPED)
+			setErrorMessage(ServerUIPlugin.getResource("%errorServerAlreadyRunning"));
+		else
+			setErrorMessage(null);
+		/*if (server != null) {
+		 server.setLaunchDefaults(configuration);
+		 }*/
+		updateLaunchConfigurationDialog();
+	}
+
+	protected void setErrorMessage(String s) {
+		super.setErrorMessage(s);
+	}
+	
+	protected void updateLaunchConfigurationDialog() {
+		super.updateLaunchConfigurationDialog();
+	}
+
+	/**
+	 * @see ILaunchConfigurationTab#setDefaults(ILaunchConfigurationWorkingCopy)
+	 */
+	public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+		setErrorMessage(null);
+		if (serverCombo != null) {	
+			serverCombo.setEnabled(true);
+			if (serverCombo.getItemCount() > 0)
+				serverCombo.select(0);
+		}
+		
+		if (servers != null) {
+			server = (IServer) servers.get(serverCombo.getSelectionIndex());
+			if (server != null) {
+				server.setLaunchDefaults(configuration);
+			}
+		}
+	}
+
+	/**
+	 * @see ILaunchConfigurationTab#initializeFrom(ILaunchConfiguration)
+	 */
+	public void initializeFrom(ILaunchConfiguration configuration) {
+		serverCombo.setEnabled(true);
+		//remove error message that other instances may have set
+		setErrorMessage(null);
+
+		try {
+			String serverId = configuration.getAttribute(IServer.ATTR_SERVER_ID, "");
+			if (!serverId.equals("")) {
+				server = ServerCore.getResourceManager().getServer(serverId);
+
+				if (server == null) { //server no longer exists				
+					setErrorMessage(ServerUIPlugin.getResource("%errorInvalidServer"));
+					//serverCombo.clearSelection();  //appears to be broken...doesn't work with read only?												
+					serverCombo.setEnabled(false);
+					return;
+				}
+
+				serverCombo.setText(server.getName());
+				if (server.getServerState() != IServer.SERVER_STOPPED)
+					setErrorMessage(ServerUIPlugin.getResource("%errorServerAlreadyRunning"));
+			} else {
+				if (serverCombo.getItemCount() > 0)
+					serverCombo.select(0);
+			}
+			//flag should only be set if launch has been attempted on the config
+			if (configuration.getAttribute(READ_ONLY, false))
+				serverCombo.setEnabled(false);
+		} catch (CoreException e) {
+		}
+	}
+
+	/**
+	 * @see ILaunchConfigurationTab#performApply(ILaunchConfigurationWorkingCopy)
+	 */
+	public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+		if (server != null)
+			configuration.setAttribute(IServer.ATTR_SERVER_ID, server.getId());
+		else
+			configuration.setAttribute(IServer.ATTR_SERVER_ID, (String)null);
+	}
+
+	/**
+	 * @see ILaunchConfigurationTab#isValid() 
+	 */
+	public boolean isValid() {
+		if (serverCombo.getSelectionIndex() != -1)
+			return true;
+		return false;
+	}
+
+	/**
+	 * @see ILaunchConfigurationTab#isValid(ILaunchConfiguration) 
+	 */
+	public boolean isValid(ILaunchConfiguration launchConfig) {
+		try {
+			String id = launchConfig.getAttribute(IServer.ATTR_SERVER_ID, "");
+			if (!id.equals("")) {
+				IServer server2 = ServerCore.getResourceManager().getServer(id);
+				if (server2 == null)
+					return false;
+				if (server2.getServerState() == IServer.SERVER_STOPPED)
+					return true;
+			}
+		} catch (CoreException e) { }
+		return false;
+	}
+
+	public Image getImage() {
+		return ImageResource.getImage(ImageResource.IMG_SERVER);
+	}
+
+	/**
+	 * @see ILaunchConfigurationTab#getName()
+	 */
+	public String getName() {
+		return ServerUIPlugin.getResource("%serverLaunchConfigurationTab");
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerUICore.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerUICore.java
new file mode 100644
index 0000000..f55545b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerUICore.java
@@ -0,0 +1,145 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+
+import org.eclipse.wst.server.ui.internal.ServerLabelProvider;
+import org.eclipse.wst.server.ui.internal.ServerUIPreferences;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.wst.server.ui.internal.actions.RunOnServerActionDelegate;
+import org.eclipse.wst.server.ui.wizard.IWizardFragment;
+/**
+ * Server UI core.
+ */
+public class ServerUICore {
+	// server UI plugin id
+	public static final String PLUGIN_ID = "org.eclipse.wst.server.ui";
+
+	protected static ServerLabelProvider labelProvider;
+
+	// cached copy of all runtime wizards
+	private static Map wizardFragments;
+	
+	static class WizardFragmentData {
+		String id;
+		IConfigurationElement ce;
+		IWizardFragment fragment;
+		
+		public WizardFragmentData(String id, IConfigurationElement ce) {
+			this.id = id;
+			this.ce = ce;
+		}
+	}
+
+	/**
+	 * ServerUICore constructor comment.
+	 */
+	private ServerUICore() {
+		super();
+	}
+
+	/**
+	 * Return the UI preferences.
+	 * 
+	 * @return IServerUIPreferences
+	 */
+	public static IServerUIPreferences getPreferences() {
+		return new ServerUIPreferences();
+	}
+	
+	/**
+	 * Returns the wizard fragment with the given id.
+	 *
+	 * @return
+	 */
+	public static IWizardFragment getWizardFragment(String typeId) {
+		if (typeId == null)
+			return null;
+
+		if (wizardFragments == null)
+			loadWizardFragments();
+		
+		Iterator iterator = wizardFragments.keySet().iterator();
+		while (iterator.hasNext()) {
+			String key = (String) iterator.next();
+			if (typeId.equals(key)) {
+				WizardFragmentData data = (WizardFragmentData) wizardFragments.get(key);
+				return getWizardFragment(data);
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Load the server startups.
+	 */
+	private static void loadWizardFragments() {
+		Trace.trace(Trace.CONFIG, "->- Loading .wizardFragments extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerUICore.PLUGIN_ID, "wizardFragments");
+
+		int size = cf.length;
+		wizardFragments = new HashMap(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				String id = cf[i].getAttribute("typeIds");
+				wizardFragments.put(id, new WizardFragmentData(id, cf[i]));
+				Trace.trace(Trace.CONFIG, "  Loaded wizardFragment: " + id);
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load wizardFragment: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		
+		Trace.trace(Trace.CONFIG, "-<- Done loading .wizardFragments extension point -<-");
+	}
+	
+	protected static IWizardFragment getWizardFragment(WizardFragmentData fragment) {
+		if (fragment == null)
+			return null;
+	
+		if (fragment.fragment == null) {
+			try {
+				fragment.fragment = (IWizardFragment) fragment.ce.createExecutableExtension("class");
+			} catch (Exception cex) {
+				Trace.trace(Trace.SEVERE, "Could not create wizardFragment: " + fragment.ce.getAttribute("id"), cex);
+			}
+		}
+		return fragment.fragment;
+	}
+
+	public static ILabelProvider getLabelProvider() {
+		if (labelProvider == null)
+			labelProvider = new ServerLabelProvider();
+		return labelProvider;
+	}
+	
+	public static void runOnServer(Object object, String launchMode) {
+		RunOnServerActionDelegate delegate = new RunOnServerActionDelegate();
+		Action action = new Action() { };
+		if (object != null) {
+			StructuredSelection sel = new StructuredSelection(object);
+			delegate.selectionChanged(action, sel);
+		} else
+			delegate.selectionChanged(action, null);
+
+		delegate.run(action);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerUIUtil.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerUIUtil.java
new file mode 100644
index 0000000..3ead7e4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/ServerUIUtil.java
@@ -0,0 +1,265 @@
+package org.eclipse.wst.server.ui;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.List;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceNode;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.preference.PreferenceManager;
+import org.eclipse.jface.window.Window;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.ui.editor.IServerEditorInput;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.wst.server.ui.internal.editor.ServerEditorInput;
+import org.eclipse.wst.server.ui.internal.publish.PublishDialog;
+import org.eclipse.wst.server.ui.internal.task.FinishWizardFragment;
+import org.eclipse.wst.server.ui.internal.task.InputWizardFragment;
+import org.eclipse.wst.server.ui.internal.task.SaveRuntimeTask;
+import org.eclipse.wst.server.ui.internal.wizard.ClosableWizardDialog;
+import org.eclipse.wst.server.ui.internal.wizard.fragment.NewRuntimeWizardFragment;
+import org.eclipse.wst.server.ui.wizard.*;
+
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Server UI utility methods.
+ */
+public class ServerUIUtil {
+	/**
+	 * ServerUIUtil constructor comment.
+	 */
+	private ServerUIUtil() {
+		super();
+	}
+
+	/**
+	 * Open the passed server resources in the server editor.
+	 *
+	 * @param resource org.eclipse.core.resources.IServerResource
+	 */
+	public static void editServer(IServer server, IServerConfiguration configuration) {
+		if (server == null && configuration == null)
+			return;
+
+		String serverId = null;
+		if (server != null)
+			serverId = server.getId();
+		String configurationId = null;
+		if (configuration != null)
+			configurationId = configuration.getId();
+		editServer(serverId, configurationId);
+	}
+
+	/**
+	 * Open the passed resources in the server editor.
+	 *
+	 * @param resource org.eclipse.core.resources.IServerResource
+	 */
+	public static void editServer(String serverId, String configurationId) {
+		if (serverId == null && configurationId == null)
+			return;
+
+		IWorkbenchWindow workbenchWindow = ServerUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow();
+		IWorkbenchPage page = workbenchWindow.getActivePage();
+
+		try {
+			IServerEditorInput input = new ServerEditorInput(serverId, configurationId);
+			page.openEditor(input, IServerEditorInput.EDITOR_ID);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error opening server editor", e);
+		}
+	}
+	
+	/**
+	 * Publish with the given server control, and display
+	 * the publishing in a dialog. If keepOpen is true, the publish
+	 * dialog will remain open after publishing. If false, it will
+	 * only remain open if there was an error, info, or warning
+	 * message.
+	 *
+	 * @param control org.eclipse.wst.server.core.IServerControl
+	 * @param keepOpen boolean
+	 * @return IStatus
+	 */
+	public static IStatus publishWithDialog(IServer server, boolean keepOpen) {
+		Shell shell = ServerUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		return PublishDialog.publish(shell, server, keepOpen);
+	}
+
+	/**
+	 * Publish with the given server control, and display
+	 * the publishing in a dialog. If keepOpen is true, the publish
+	 * dialog will remain open after publishing. If false, it will
+	 * only remain open if there was an error, info, or warning
+	 * message.
+	 *
+	 * @param control org.eclipse.wst.server.core.IServerControl
+	 * @param keepOpen boolean
+	 * @return IStatus
+	 */
+	public static IStatus publishWithDialog(Shell shell, IServer server, boolean keepOpen) {
+		return PublishDialog.publish(shell, server, keepOpen);
+	}
+
+	/**
+	 * Prompts the user if the server is dirty. Returns true if the server was
+	 * not dirty or if the user decided to continue anyway. Returns false if
+	 * the server is dirty and the user chose to cancel the operation.
+	 *
+	 * @return boolean
+	 */
+	public static boolean promptIfDirty(Shell shell, IServer server) {
+		if (server == null)
+			return false;
+
+		String title = ServerUIPlugin.getResource("%resourceDirtyDialogTitle");
+		
+		if (server != null && server.isAWorkingCopyDirty()) {
+			String message = ServerUIPlugin.getResource("%resourceDirtyDialogMessage", server.getName());
+			String[] labels = new String[] {ServerUIPlugin.getResource("%resourceDirtyDialogContinue"), IDialogConstants.CANCEL_LABEL};
+			MessageDialog dialog = new MessageDialog(shell, title, null, message, MessageDialog.INFORMATION, labels, 0);
+	
+			if (dialog.open() != 0)
+				return false;
+		}
+	
+		IServerConfiguration config = server.getServerConfiguration();
+		if (config != null)
+			return promptIfDirty(shell, config);
+		else
+			return true;
+	}
+
+	/**
+	 * Prompts the user if the server configuration is dirty. Returns true if the server was
+	 * not dirty or if the user decided to continue anyway. Returns false if
+	 * the server is dirty and the user chose to cancel the operation.
+	 *
+	 * @return boolean
+	 */
+	public static boolean promptIfDirty(Shell shell, IServerConfiguration configuration) {
+		if (configuration == null)
+			return false;
+
+		String title = ServerUIPlugin.getResource("%resourceDirtyDialogTitle");
+
+		if (configuration != null && configuration.isAWorkingCopyDirty()) {
+			String message = ServerUIPlugin.getResource("%resourceDirtyDialogMessage", configuration.getName());
+			String[] labels = new String[] {ServerUIPlugin.getResource("%resourceDirtyDialogContinue"), IDialogConstants.CANCEL_LABEL};
+			MessageDialog dialog = new MessageDialog(shell, title, null, message, MessageDialog.INFORMATION, labels, 0);
+
+			if (dialog.open() != 0)
+				return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Use the preference to prompt the user to save dirty editors, if applicable.
+	 * 
+	 * @return boolean  - Returns false if the user cancelled the operation
+	 */
+	public static boolean saveEditors() {
+		byte b = ServerUICore.getPreferences().getSaveEditors();
+		if (b == IServerUIPreferences.SAVE_EDITORS_NEVER)
+			return true;
+		else
+			return ServerUIPlugin.getInstance().getWorkbench().saveAllEditors(b == IServerUIPreferences.SAVE_EDITORS_PROMPT);			
+	}
+
+	/**
+	 * Publishes to the given server, if the preference is set and publishing was required.
+	 * 
+	 * @return boolean - Returns false if the user cancelled the operation.
+	 */
+	public static boolean publish(IServer server) {
+		if (ServerCore.getServerPreferences().isAutoPublishing() && server.shouldPublish()) {
+			// publish first
+			IStatus status = publishWithDialog(server, false);
+
+			if (status == null || status.getSeverity() == IStatus.ERROR) // user cancelled
+				return false;
+		}
+		return true;
+	}
+	
+	/**
+	 * @deprecated - use showNewRuntimeWizard
+	 */
+	public static boolean showRuntimePreferencePage(Shell shell) {
+		PreferenceManager manager = PlatformUI.getWorkbench().getPreferenceManager();
+		IPreferenceNode node = manager.find("org.eclipse.wst.server.ui.preferencePage").findSubNode("org.eclipse.wst.server.ui.runtime.preferencePage");
+		PreferenceManager manager2 = new PreferenceManager();
+		manager2.addToRoot(node);
+		final PreferenceDialog dialog = new PreferenceDialog(shell, manager2);
+		final boolean[] result = new boolean[] { false };
+		BusyIndicator.showWhile(shell.getDisplay(), new Runnable() {
+			public void run() {
+				dialog.create();
+				if (dialog.open() == Window.OK)
+					result[0] = true;
+			}
+		});
+		return result[0];
+	}
+
+	public static boolean showNewRuntimeWizard(Shell shell) {
+		return showNewRuntimeWizard(shell, null, null);
+	}
+	
+	public static boolean showNewRuntimeWizard(Shell shell, final String runtimeTypeId) {
+		IRuntimeType runtimeType = ServerCore.getRuntimeType(runtimeTypeId);
+		if (runtimeType != null) {
+			try {
+				final IRuntimeWorkingCopy runtime = runtimeType.createRuntime(null);
+				IWizardFragment fragment = new WizardFragment() {
+					public void createSubFragments(List list) {
+						list.add(new InputWizardFragment(ITaskModel.TASK_RUNTIME, runtime));
+						list.add(ServerUICore.getWizardFragment(runtimeTypeId));
+						list.add(new FinishWizardFragment(new SaveRuntimeTask()));
+					}
+				};
+				TaskWizard wizard = new TaskWizard(ServerUIPlugin.getResource("%wizNewRuntimeWizardTitle"), fragment);
+				wizard.setForcePreviousAndNextButtons(true);
+				ClosableWizardDialog dialog = new ClosableWizardDialog(shell, wizard);
+				return (dialog.open() == IDialogConstants.OK_ID);
+			} catch (Exception e) {
+				return false;
+			}
+		} else
+			return showNewRuntimeWizard(shell, null, null, runtimeTypeId);
+	}
+
+	public static boolean showNewRuntimeWizard(Shell shell, final String type, final String version) {
+		return showNewRuntimeWizard(shell, type, version, null);
+	}
+
+	public static boolean showNewRuntimeWizard(Shell shell, final String type, final String version, final String runtimeTypeId) {
+		IWizardFragment fragment = new WizardFragment() {
+			public void createSubFragments(List list) {
+				list.add(new NewRuntimeWizardFragment(type, version, runtimeTypeId));
+				list.add(new FinishWizardFragment(new SaveRuntimeTask()));
+			}
+		};
+		TaskWizard wizard = new TaskWizard(ServerUIPlugin.getResource("%wizNewRuntimeWizardTitle"), fragment);
+		wizard.setForcePreviousAndNextButtons(true);
+		ClosableWizardDialog dialog = new ClosableWizardDialog(shell, wizard);
+		return (dialog.open() == IDialogConstants.OK_ID);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/DebugOnServerAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/DebugOnServerAction.java
new file mode 100644
index 0000000..91054d2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/DebugOnServerAction.java
@@ -0,0 +1,51 @@
+package org.eclipse.wst.server.ui.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.actions.DebugOnServerActionDelegate;
+/**
+ * "Debug on Server" menu action. Allows the user to select an
+ * object, and have automatic server creation, launching, and
+ * the appropriate client to appear. A new instance of this
+ * action must be created for each object that the user selects.
+ */
+public class DebugOnServerAction extends Action {
+	protected DebugOnServerActionDelegate delegate;
+
+	/**
+	 * DebugOnServerAction constructor comment.
+	 */
+	public DebugOnServerAction(Object object) {
+		super(ServerUIPlugin.getResource("%actionDebugOnServer"));
+	
+		setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DTOOL_DEBUG_ON_SERVER));
+		setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CTOOL_DEBUG_ON_SERVER));
+		setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ETOOL_DEBUG_ON_SERVER));
+	
+		delegate = new DebugOnServerActionDelegate();
+		if (object != null) {
+			StructuredSelection sel = new StructuredSelection(object);
+			delegate.selectionChanged(this, sel);
+		} else
+			delegate.selectionChanged(this, null);
+	}
+
+	/**
+	 * Implementation of method defined on <code>IAction</code>.
+	 */
+	public void run() {
+		delegate.run(this);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/IServerAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/IServerAction.java
new file mode 100644
index 0000000..ac3e1dd
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/IServerAction.java
@@ -0,0 +1,30 @@
+package org.eclipse.wst.server.ui.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/**
+ * 
+ */
+public interface IServerAction {
+	/**
+	 * Performs this action.
+	 * 
+	 */
+	public void run(Shell shell, IServer server, IServerConfiguration configuration);
+
+	/**
+	 * 
+	 */
+	public boolean supports(IServer server, IServerConfiguration configuration);
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/LaunchWizardAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/LaunchWizardAction.java
new file mode 100644
index 0000000..622d160
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/LaunchWizardAction.java
@@ -0,0 +1,59 @@
+package org.eclipse.wst.server.ui.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.eclipse.ui.PlatformUI;
+/**
+ * An abstract action that opens up a workbench wizard when run.
+ */
+abstract class LaunchWizardAction extends Action {
+	/**
+	 * NewServerAction constructor comment.
+	 */
+	public LaunchWizardAction() {
+		super();
+	}
+
+	/**
+	 * Return the wizard that should be opened.
+	 *
+	 * @return org.eclipse.ui.IWorkbenchWizard
+	 */
+	public abstract IWorkbenchWizard getWizard();
+
+	/**
+	 * Implementation of method defined on <code>IAction</code>.
+	 */
+	public void run() {
+		IWorkbench workbench = PlatformUI.getWorkbench();
+		IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow();
+		ISelection selection = workbenchWindow.getSelectionService().getSelection();
+	
+		IStructuredSelection selectionToPass = null;
+		if (selection instanceof IStructuredSelection)
+			selectionToPass = (IStructuredSelection) selection;
+		else
+			selectionToPass = StructuredSelection.EMPTY;
+	
+		IWorkbenchWizard wizard = getWizard();
+		wizard.init(workbench, selectionToPass);
+		WizardDialog dialog = new WizardDialog(workbench.getActiveWorkbenchWindow().getShell(), wizard);
+		dialog.open();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/NewServerAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/NewServerAction.java
new file mode 100644
index 0000000..ab44788
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/NewServerAction.java
@@ -0,0 +1,39 @@
+package org.eclipse.wst.server.ui.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.wizard.NewServerWizard;
+import org.eclipse.ui.IWorkbenchWizard;
+/**
+ * An action to invoke the new server and server configuration wizard.
+ */
+public class NewServerAction extends LaunchWizardAction {
+	/**
+	 * NewServerAction constructor comment.
+	 */
+	public NewServerAction() {
+		super();
+	
+		setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CTOOL_NEW_SERVER));
+		setText(ServerUIPlugin.getResource("%actionSetNewServer"));
+	}
+
+	/**
+	 * Return the wizard that should be opened.
+	 *
+	 * @return org.eclipse.ui.IWorkbenchWizard
+	 */
+	public IWorkbenchWizard getWizard() {
+		return new NewServerWizard();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/NewServerProjectAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/NewServerProjectAction.java
new file mode 100644
index 0000000..7acbdea
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/NewServerProjectAction.java
@@ -0,0 +1,34 @@
+package org.eclipse.wst.server.ui.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.wst.server.ui.internal.wizard.NewServerProjectWizard;
+import org.eclipse.ui.IWorkbenchWizard;
+/**
+ * An action to invoke the new server project wizard.
+ */
+public class NewServerProjectAction extends LaunchWizardAction {
+	/**
+	 * NewServerProjectAction constructor comment.
+	 */
+	public NewServerProjectAction() {
+		super();
+	}
+
+	/**
+	 * Return the wizard that should be opened.
+	 *
+	 * @return org.eclipse.ui.IWorkbenchWizard
+	 */
+	public IWorkbenchWizard getWizard() {
+		return new NewServerProjectWizard();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/ProfileOnServerAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/ProfileOnServerAction.java
new file mode 100644
index 0000000..8374ad4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/ProfileOnServerAction.java
@@ -0,0 +1,51 @@
+package org.eclipse.wst.server.ui.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.actions.ProfileOnServerActionDelegate;
+/**
+ * "Profile on Server" menu action. Allows the user to select an
+ * object, and have automatic server creation, launching, and
+ * the appropriate client to appear. A new instance of this
+ * action must be created for each object that the user selects.
+ */
+public class ProfileOnServerAction extends Action {
+	protected ProfileOnServerActionDelegate delegate;
+
+	/**
+	 * ProfileOnServerAction constructor comment.
+	 */
+	public ProfileOnServerAction(Object object) {
+		super(ServerUIPlugin.getResource("%actionProfileOnServer"));
+	
+		setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DTOOL_PROFILE_ON_SERVER));
+		setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CTOOL_PROFILE_ON_SERVER));
+		setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ETOOL_PROFILE_ON_SERVER));
+	
+		delegate = new ProfileOnServerActionDelegate();
+		if (object != null) {
+			StructuredSelection sel = new StructuredSelection(object);
+			delegate.selectionChanged(this, sel);
+		} else
+			delegate.selectionChanged(this, null);
+	}
+
+	/**
+	 * Implementation of method defined on <code>IAction</code>.
+	 */
+	public void run() {
+		delegate.run(this);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/RestartProjectAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/RestartProjectAction.java
new file mode 100644
index 0000000..97cde55
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/RestartProjectAction.java
@@ -0,0 +1,42 @@
+package org.eclipse.wst.server.ui.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.actions.RestartProjectActionDelegate;
+/**
+ * Action to restart an individual project on servers that
+ * support it.
+ */
+public class RestartProjectAction extends Action {
+	protected RestartProjectActionDelegate delegate;
+
+	/**
+	 * RestartProjectAction constructor comment.
+	 */
+	public RestartProjectAction(IProject project) {
+		super(ServerUIPlugin.getResource("%actionRestartProject"));
+	
+		delegate = new RestartProjectActionDelegate();
+		StructuredSelection sel = new StructuredSelection(project);
+		delegate.selectionChanged(this, sel);
+	}
+
+	/**
+	 * Implementation of method defined on <code>IAction</code>.
+	 */
+	public void run() {
+		delegate.run(this);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/RunOnServerAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/RunOnServerAction.java
new file mode 100644
index 0000000..1107cc5
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/actions/RunOnServerAction.java
@@ -0,0 +1,51 @@
+package org.eclipse.wst.server.ui.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.actions.RunOnServerActionDelegate;
+/**
+ * "Run on Server" menu action. Allows the user to select an
+ * object, and have automatic server creation, launching, and
+ * the appropriate client to appear. A new instance of this
+ * action must be created for each object that the user selects.
+ */
+public class RunOnServerAction extends Action {
+	protected RunOnServerActionDelegate delegate;
+
+	/**
+	 * RunOnServerAction constructor comment.
+	 */
+	public RunOnServerAction(Object object) {
+		super(ServerUIPlugin.getResource("%actionRunOnServer"));
+	
+		setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DTOOL_RUN_ON_SERVER));
+		setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CTOOL_RUN_ON_SERVER));
+		setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ETOOL_RUN_ON_SERVER));
+	
+		delegate = new RunOnServerActionDelegate();
+		if (object != null) {
+			StructuredSelection sel = new StructuredSelection(object);
+			delegate.selectionChanged(this, sel);
+		} else
+			delegate.selectionChanged(this, null);
+	}
+
+	/**
+	 * Implementation of method defined on <code>IAction</code>.
+	 */
+	public void run() {
+		delegate.run(this);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ICommandManager.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ICommandManager.java
new file mode 100644
index 0000000..47c07ae
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ICommandManager.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.editor;
+
+import org.eclipse.wst.server.core.ITask;
+/**
+ * A command manager.
+ */
+public interface ICommandManager {
+	/**
+	 * Execute the given command and place it in the undo stack.
+	 * If the command cannot be undone, the user will be notifed
+	 * before it is executed.
+	 *
+	 * @param command ICommand
+	 */
+	public void executeCommand(ITask task);
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorActionFactory.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorActionFactory.java
new file mode 100644
index 0000000..b949579
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorActionFactory.java
@@ -0,0 +1,56 @@
+package org.eclipse.wst.server.ui.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.action.IAction;
+import org.eclipse.ui.IEditorSite;
+
+import org.eclipse.wst.server.core.IOrdered;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/**
+ *
+ */
+public interface IServerEditorActionFactory extends IOrdered {
+	/**
+	 * 
+	 */
+	public String getId();
+
+	/**
+	 * 
+	 */
+	public String getName();
+
+	/**
+	 * Returns true if the given server resource type (given by the
+	 * id) can be opened with this editor. This result is based on
+	 * the result of the getFactoryIds() method.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsServerElementType(String id);
+
+	/**
+	 * Returns true if this editor page should be visible with the given
+	 * server and configuration combination. This allows (for
+	 * instance) complex configuration pages to only be shown when used
+	 * with non-unittest servers.
+	 *
+	 * <p>If the server or configuration is being opened by itself, the
+	 * other value (server or configuration) will be null.
+	 */
+	public boolean shouldDisplay(IServer server, IServerConfiguration configuration);
+
+	/**
+	 * Create the action.
+	 */
+	public IAction createAction(IEditorSite site, IServerEditorPartInput input);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorActionFactoryDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorActionFactoryDelegate.java
new file mode 100644
index 0000000..2d30e99
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorActionFactoryDelegate.java
@@ -0,0 +1,37 @@
+package org.eclipse.wst.server.ui.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.ui.IEditorSite;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/**
+ *
+ */
+public interface IServerEditorActionFactoryDelegate {
+	/**
+	 * Returns true if this editor action should be visible with the given
+	 * server and configuration combination. This allows (for
+	 * instance) complex configuration pages to only be shown when used
+	 * with non-unittest servers.
+	 *
+	 * <p>If the server or configuration is being opened by itself, the
+	 * other value (server or configuration) will be null.
+	 */
+	public boolean shouldDisplay(IServer server, IServerConfiguration configuration);
+
+	/**
+	 * Create the action.
+	 */
+	public IAction createAction(IEditorSite site, IServerEditorPartInput input);
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorInput.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorInput.java
new file mode 100644
index 0000000..6534bc2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorInput.java
@@ -0,0 +1,38 @@
+package org.eclipse.wst.server.ui.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.ui.IEditorInput;
+/**
+ * This is the editor input for the server and server
+ * configuration editor. The input includes both a server
+ * and server configuration.
+ *
+ * <p>This interface is not intended to be implemented by clients.</p>
+ */
+public interface IServerEditorInput extends IEditorInput {
+	public static final String EDITOR_ID = ServerUICore.PLUGIN_ID + ".editor";
+
+	/**
+	 * Returns the server id.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getServerId();
+
+	/**
+	 * Returns the server configuration id.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getServerConfigurationId();
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPageSectionFactory.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPageSectionFactory.java
new file mode 100644
index 0000000..f455dc8
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPageSectionFactory.java
@@ -0,0 +1,50 @@
+package org.eclipse.wst.server.ui.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.wst.server.core.IOrdered;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/**
+ *
+ */
+public interface IServerEditorPageSectionFactory extends IOrdered {
+	/**
+	 * 
+	 */
+	public String getId();
+
+	/**
+	 * Returns true if the given server resource type (given by the
+	 * id) can be opened with this editor. This result is based on
+	 * the result of the types attribute.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsType(String id);
+	
+	public String getInsertionId();
+	
+	/**
+	 * Returns true if this editor page section should be visible with the given
+	 * server and configuration combination. This allows (for
+	 * instance) complex configuration pages to only be shown when used
+	 * with non-unittest servers.
+	 *
+	 * <p>If the server or configuration is being opened by itself, the
+	 * other value (server or configuration) will be null.
+	 */
+	public boolean shouldCreateSection(IServer server, IServerConfiguration configuration);
+
+	/**
+	 * Create the editor page section.
+	 */
+	public IServerEditorSection createSection();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPageSectionFactoryDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPageSectionFactoryDelegate.java
new file mode 100644
index 0000000..8c1ad23
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPageSectionFactoryDelegate.java
@@ -0,0 +1,33 @@
+package org.eclipse.wst.server.ui.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/**
+ *
+ */
+public interface IServerEditorPageSectionFactoryDelegate {
+	/**
+	 * Returns true if this editor page section should be visible with the given
+	 * server and configuration combination. This allows (for
+	 * instance) complex configuration pages to only be shown when used
+	 * with non-unittest servers.
+	 *
+	 * <p>If the server or configuration is being opened by itself, the
+	 * other value (server or configuration) will be null.
+	 */
+	public boolean shouldCreateSection(IServer server, IServerConfiguration configuration);
+
+	/**
+	 * Create the editor page section.
+	 */
+	public IServerEditorSection createSection();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPartFactory.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPartFactory.java
new file mode 100644
index 0000000..9a7026e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPartFactory.java
@@ -0,0 +1,57 @@
+package org.eclipse.wst.server.ui.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.ui.IEditorPart;
+
+import org.eclipse.wst.server.core.IOrdered;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/**
+ *
+ */
+public interface IServerEditorPartFactory extends IOrdered {
+	/**
+	 * 
+	 */
+	public String getId();
+	
+	/**
+	 * 
+	 */
+	public String getName();
+
+	/**
+	 * Returns true if the given server resource type (given by the
+	 * id) can be opened with this editor. This result is based on
+	 * the result of the types attribute.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsType(String id);
+	
+	public boolean supportsInsertionId(String id);
+	
+	/**
+	 * Returns true if this editor page should be visible with the given
+	 * server and configuration combination. This allows (for
+	 * instance) complex configuration pages to only be shown when used
+	 * with non-unittest servers.
+	 *
+	 * <p>If the server or configuration is being opened by itself, the
+	 * other value (server or configuration) will be null.
+	 */
+	public boolean shouldCreatePage(IServer server, IServerConfiguration configuration);
+
+	/**
+	 * Create the editor page.
+	 */
+	public IEditorPart createPage();
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPartFactoryDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPartFactoryDelegate.java
new file mode 100644
index 0000000..6ef01af
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPartFactoryDelegate.java
@@ -0,0 +1,35 @@
+package org.eclipse.wst.server.ui.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.ui.IEditorPart;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+/**
+ *
+ */
+public interface IServerEditorPartFactoryDelegate {
+	/**
+	 * Returns true if this editor page should be visible with the given
+	 * server and configuration combination. This allows (for
+	 * instance) complex configuration pages to only be shown when used
+	 * with non-unittest servers.
+	 *
+	 * <p>If the server or configuration is being opened by itself, the
+	 * other value (server or configuration) will be null.
+	 */
+	public boolean shouldCreatePage(IServer server, IServerConfiguration configuration);
+
+	/**
+	 * Create the editor page.
+	 */
+	public IEditorPart createPage();
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPartInput.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPartInput.java
new file mode 100644
index 0000000..913f66b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorPartInput.java
@@ -0,0 +1,65 @@
+package org.eclipse.wst.server.ui.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.ui.IEditorInput;
+
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+/**
+ *
+ */
+public interface IServerEditorPartInput extends IEditorInput {
+	/**
+	 * Returns the server to be edited.
+	 *
+	 * @return IServerWorkingCopy
+	 */
+	public IServerWorkingCopy getServer();
+
+	/**
+	 * Returns true if the server is read-only.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isServerReadOnly();
+	
+	/**
+	 * Gets the command manager. The editor is only responsible for creating an
+	 * ICommand and passing it to the command manager, which actually performs
+	 * the action and updates the server.
+	 *
+	 * @param commandManager ICommandManager
+	 */
+	public ICommandManager getServerCommandManager();
+
+	/**
+	 * Returns the server configuration to be edited.
+	 * 
+	 * @return IServerConfigurationWorkingCopy
+	 */
+	public IServerConfigurationWorkingCopy getServerConfiguration();
+
+	/**
+	 * Returns true if the server configuration is read-only.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isServerConfigurationReadOnly();
+	
+	/**
+	 * Gets the command manager. The editor is only responsible for creating an
+	 * ICommand and passing it to the command manager, which actually performs
+	 * the action and updates the server configuration.
+	 *
+	 * @param commandManager ICommandManager
+	 */
+	public ICommandManager getServerConfigurationCommandManager();
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorSection.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorSection.java
new file mode 100644
index 0000000..65efdfd
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/IServerEditorSection.java
@@ -0,0 +1,32 @@
+package org.eclipse.wst.server.ui.editor;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+/**
+ * 
+ */
+public interface IServerEditorSection {
+	public void init(IEditorSite site, IEditorInput input);
+	
+	public void createSection(Composite parent);
+	
+	public void dispose();
+	
+	/**
+	 * Return the error message for this page.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getErrorMessage();
+
+	/**
+	 * Returns error or status messages that will be displayed when the
+	 * server resource is saved. If there are any error messages, the
+	 * user will be unable to save the editor.
+	 * 
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public IStatus[] getSaveStatus();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ServerEditorPartInput.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ServerEditorPartInput.java
new file mode 100644
index 0000000..cbd53ce
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ServerEditorPartInput.java
@@ -0,0 +1,110 @@
+package org.eclipse.wst.server.ui.editor;
+/*
+ * Licensed Material - Property of IBM 
+ * (C) Copyright IBM Corp. 2002, 2003 - All Rights Reserved. US Government Users
+ * Restricted Rights - Use, duplication or disclosure restricted by GSA ADP
+ * Schedule Contract with IBM Corp.
+ */
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IPersistableElement;
+
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+
+/**
+ * 
+ */
+public class ServerEditorPartInput implements IServerEditorPartInput {
+	protected IServerWorkingCopy server;
+	protected boolean serverReadOnly;
+	protected ICommandManager serverCommandManager;
+	
+	protected IServerConfigurationWorkingCopy configuration;
+	protected boolean configurationReadOnly;
+	protected ICommandManager configurationCommandManager;
+	
+	public ServerEditorPartInput(
+			ICommandManager serverCommandManager, IServerWorkingCopy server,  boolean serverReadOnly,
+			ICommandManager configurationCommandManager, IServerConfigurationWorkingCopy configuration,  boolean configurationReadOnly) {
+		
+		this.server = server;
+		this.serverReadOnly = serverReadOnly;
+		this.serverCommandManager = serverCommandManager;
+		
+		this.configuration = configuration;
+		this.configurationReadOnly = configurationReadOnly;
+		this.configurationCommandManager = configurationCommandManager;
+	}
+	
+	public String getName() {
+		return "-";
+	}
+
+	public String getToolTipText() {
+		return "-";
+	}
+
+	public boolean exists() {
+		return true;
+	}
+	
+	public Object getAdapter(Class adapter) {
+		return null;
+	}
+	
+	public ImageDescriptor getImageDescriptor() {
+		return null;
+	}
+	
+	public IPersistableElement getPersistable() {
+		return null;
+	}
+
+	/**
+	 * Returns the server to be edited.
+	 *
+	 * @return IServerResource
+	 */
+	public IServerWorkingCopy getServer() {
+		return server;
+	}
+
+	/**
+	 * Returns true if the server is read-only.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isServerReadOnly() {
+		return serverReadOnly;
+	}
+	
+	public ICommandManager getServerCommandManager() {
+		return serverCommandManager;
+	}
+
+	/**
+	 * Returns the server configuration to be edited.
+	 * 
+	 * @return IServerConfiguration
+	 */
+	public IServerConfigurationWorkingCopy getServerConfiguration() {
+		return configuration;
+	}
+
+	/**
+	 * Returns true if the server configuration is read-only.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isServerConfigurationReadOnly() {
+		return configurationReadOnly;
+	}
+	
+	public ICommandManager getServerConfigurationCommandManager() {
+		return configurationCommandManager;
+	}
+	
+	public String toString() {
+		return "ServerEditorPartInput [" + server + ", " + configuration + "]";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ServerResourceEditorPart.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ServerResourceEditorPart.java
new file mode 100644
index 0000000..382bca2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ServerResourceEditorPart.java
@@ -0,0 +1,232 @@
+package org.eclipse.wst.server.ui.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.*;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.part.EditorPart;
+
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.ui.internal.editor.ServerEditorCore;
+/**
+ * An abstract server editor which implements the most common methods
+ * from IEditorPart.
+ * 
+ * This class also provides each editor page with an error message which
+ * will be displayed on the status bar of the editor.
+ */
+public abstract class ServerResourceEditorPart extends EditorPart {
+	public static final int PROP_ERROR = 5;
+	
+	private String errorMessage = null;
+	
+	private Map sectionToInsertionId = null;
+	private List sections = null;
+	
+	protected IServerEditorPartFactory pageFactory;
+	protected IServerWorkingCopy server;
+	protected IServerConfigurationWorkingCopy serverConfiguration;
+	protected ICommandManager commandManager;
+	protected boolean readOnly;
+
+	public ServerResourceEditorPart() {
+		super();
+	}
+
+	public void setPageFactory(IServerEditorPartFactory pageFactory) {
+		this.pageFactory = pageFactory;
+	}
+
+	/**
+	 * @see IEditorPart#doSave(IProgressMonitor)
+	 */
+	public void doSave(IProgressMonitor monitor) { }
+
+	/**
+	 * @see IEditorPart#doSaveAs()
+	 */
+	public void doSaveAs() { }
+
+	/**
+	 * @see IEditorPart#gotoMarker(IMarker)
+	 */
+	public void gotoMarker(IMarker marker) { }
+
+	/**
+	 * @see IEditorPart#isDirty()
+	 */
+	public boolean isDirty() {
+		return false;
+	}
+
+	/**
+	 * @see IEditorPart#isSaveAsAllowed()
+	 */
+	public boolean isSaveAsAllowed() {
+		return false;
+	}
+
+	/**
+	 * Set an error message for this page.
+	 * 
+	 * @param error java.lang.String
+	 */
+	public void setErrorMessage(String error) {
+		if (error == null && errorMessage == null)
+			return;
+		
+		if (error != null && error.equals(errorMessage))
+			return;
+		
+		errorMessage = error;
+		super.firePropertyChange(PROP_ERROR);
+	}
+	
+	public void updateErrorMessage() {
+		super.firePropertyChange(PROP_ERROR);
+	}
+
+	/**
+	 * Return the error message for this page.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getErrorMessage() {
+		if (errorMessage == null) {
+			Iterator iterator = getSections().iterator();
+			while (iterator.hasNext()) {
+				IServerEditorSection section = (IServerEditorSection) iterator.next();
+				String error = section.getErrorMessage();
+				if (error != null)
+					return error;
+			}
+		}
+		return errorMessage;
+	}
+
+	/**
+	 * Returns error or status messages that will be displayed when the
+	 * server resource is saved. If there are any error messages, the
+	 * user will be unable to save the editor.
+	 * 
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public IStatus[] getSaveStatus() {
+		Iterator iterator = getSections().iterator();
+		List list = new ArrayList();
+		while (iterator.hasNext()) {
+			IServerEditorSection section = (IServerEditorSection) iterator.next();
+			IStatus[] status = section.getSaveStatus();
+			if (status != null) {
+				int size = status.length;
+				for (int i = 0; i < size; i++)
+					list.add(status[i]);
+			}
+		}
+		
+		int size = list.size();
+		IStatus[] status = new IStatus[size];
+		list.toArray(status);
+		return status;
+	}
+
+	protected List getSections() {
+		if (sections == null) {
+			sections = new ArrayList();
+			sectionToInsertionId = new HashMap();
+			Iterator iterator = ServerEditorCore.getServerEditorPageSectionFactories().iterator();
+			while (iterator.hasNext()) {
+				IServerEditorPageSectionFactory factory = (IServerEditorPageSectionFactory) iterator.next();
+				String insertionId = factory.getInsertionId();
+				
+				if (pageFactory.supportsInsertionId(insertionId)) {
+					String serverTypeId = null;
+					if (server != null) 
+						serverTypeId = server.getServerType().getId();
+					String serverConfigurationTypeId = null;
+					if (serverConfiguration != null) 
+						serverConfigurationTypeId = serverConfiguration.getServerConfigurationType().getId();
+					if (((serverTypeId != null && factory.supportsType(serverTypeId)) || 
+							(serverConfigurationTypeId != null && factory.supportsType(serverConfigurationTypeId)))
+							&& factory.shouldCreateSection(server, serverConfiguration)) {
+						IServerEditorSection section = factory.createSection();
+						if (section instanceof ServerResourceEditorSection)
+							((ServerResourceEditorSection) section).setServerResourceEditorPart(this);
+						sections.add(section);
+						sectionToInsertionId.put(section, insertionId);
+					}
+				}
+			}
+		}
+		return sections;
+	}
+	
+	protected List getSections(String insertionId) {
+		if (insertionId == null)
+			return null;
+		
+		getSections();
+		List list = new ArrayList();
+		Iterator iterator = sectionToInsertionId.keySet().iterator();
+		while (iterator.hasNext()) {
+			IServerEditorSection section = (IServerEditorSection) iterator.next();
+			String insertionId2 = (String) sectionToInsertionId.get(section);
+			if (insertionId.equals(insertionId2))
+				list.add(section);
+		}
+		return list;
+	}
+
+	public void init(IEditorSite site, IEditorInput input) {
+		setSite(site);
+		setInput(input);
+		if (input instanceof IServerEditorPartInput) {
+			IServerEditorPartInput sepi = (IServerEditorPartInput) input;
+			server = sepi.getServer();
+			serverConfiguration = sepi.getServerConfiguration();
+			commandManager = sepi.getServerCommandManager();
+			readOnly = sepi.isServerReadOnly();
+		}
+		
+		Iterator iterator = getSections().iterator();
+		while (iterator.hasNext()) {
+			IServerEditorSection section = (IServerEditorSection) iterator.next();
+			section.init(site, input);
+		}
+	}
+
+	public void insertSections(Composite parent, String id) {
+		if (id == null)
+			return;
+		
+		Iterator iterator = getSections(id).iterator();
+		while (iterator.hasNext()) {
+			IServerEditorSection section = (IServerEditorSection) iterator.next();
+			section.createSection(parent);
+		}
+	}
+	
+	public void dispose() {
+		super.dispose();
+
+		Iterator iterator = getSections().iterator();
+		while (iterator.hasNext()) {
+			IServerEditorSection section = (IServerEditorSection) iterator.next();
+			section.dispose();
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ServerResourceEditorSection.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ServerResourceEditorSection.java
new file mode 100644
index 0000000..57fba14
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/editor/ServerResourceEditorSection.java
@@ -0,0 +1,85 @@
+package org.eclipse.wst.server.ui.editor;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+/**
+ * 
+ */
+public abstract class ServerResourceEditorSection implements IServerEditorSection {
+	private String errorMessage = null;
+
+	public IServerWorkingCopy server;
+	public IServerConfigurationWorkingCopy serverConfiguration;
+	public ICommandManager commandManager;
+	protected boolean readOnly;
+	protected Composite parentComp;
+	protected ServerResourceEditorPart editor;
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.editor.IServerEditorSection#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
+	 */
+	public void init(IEditorSite site, IEditorInput input) {
+		if (input instanceof IServerEditorPartInput) {
+			IServerEditorPartInput sepi = (IServerEditorPartInput) input;
+			server = sepi.getServer();
+			serverConfiguration = sepi.getServerConfiguration();
+			commandManager = sepi.getServerCommandManager();
+			readOnly = sepi.isServerReadOnly();
+		}
+	}
+
+	public void createSection(Composite parent) {
+		this.parentComp = parent;
+	}
+
+	public Shell getShell() {
+		return parentComp.getShell();
+	}
+	
+	/**
+	 * Return the error message for this page.
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getErrorMessage() {
+		return errorMessage;
+	}
+
+	/**
+	 * Returns error or status messages that will be displayed when the
+	 * server resource is saved. If there are any error messages, the
+	 * user will be unable to save the editor.
+	 * 
+	 * @return org.eclipse.core.runtime.IStatus
+	 */
+	public IStatus[] getSaveStatus() {
+		return null;
+	}
+	
+	public void setServerResourceEditorPart(ServerResourceEditorPart editor) {
+		this.editor = editor;
+	}
+
+	/**
+	 * Set an error message for this page.
+	 * 
+	 * @param error java.lang.String
+	 */
+	public void setErrorMessage(String error) {
+		if (error == null && errorMessage == null)
+			return;
+		
+		if (error != null && error.equals(errorMessage))
+			return;
+		
+		errorMessage = error;
+		if (editor != null)
+			editor.updateErrorMessage();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ContextIds.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ContextIds.java
new file mode 100644
index 0000000..84660a2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ContextIds.java
@@ -0,0 +1,88 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.wst.server.ui.ServerUICore;
+/**
+ * Context help id constants.
+ */
+public interface ContextIds {
+	public static final String SELECT_SERVER_WIZARD = ServerUICore.PLUGIN_ID + ".swsi0000";
+	public static final String SELECT_SERVER_EXISTING = ServerUICore.PLUGIN_ID + ".swsi0002";
+	public static final String SELECT_SERVER_EXISTING_TABLE = ServerUICore.PLUGIN_ID + ".swsi0004";
+	public static final String SELECT_SERVER_CREATE = ServerUICore.PLUGIN_ID + ".swsi0010";
+	public static final String SELECT_SERVER_CREATE_TABLE = ServerUICore.PLUGIN_ID + ".swsi0012";
+	public static final String SELECT_SERVER_PREFERENCE = ServerUICore.PLUGIN_ID + ".swsi0014";
+
+	public static final String SELECT_CLIENT_WIZARD = ServerUICore.PLUGIN_ID + ".swsc0000";
+	public static final String SELECT_CLIENT = ServerUICore.PLUGIN_ID + ".swsc0002";
+
+	public static final String NEW_INSTANCE_WIZARD = ServerUICore.PLUGIN_ID + ".swni0000";
+	public static final String NEW_INSTANCE_NAME = ServerUICore.PLUGIN_ID + ".swni0002";
+	public static final String NEW_INSTANCE_FOLDER = ServerUICore.PLUGIN_ID + ".swni0004";
+	public static final String NEW_INSTANCE_FACTORY = ServerUICore.PLUGIN_ID + ".swni0006";
+	
+	public static final String NEW_CONFIGURATION_WIZARD = ServerUICore.PLUGIN_ID + ".swnc0000";
+	public static final String NEW_CONFIGURATION_NAME = ServerUICore.PLUGIN_ID + ".swnc0002";
+	public static final String NEW_CONFIGURATION_FOLDER = ServerUICore.PLUGIN_ID + ".swnc0004";
+	public static final String NEW_CONFIGURATION_FACTORY = ServerUICore.PLUGIN_ID + ".swnc0006";
+	
+	public static final String NEW_SERVER_WIZARD = ServerUICore.PLUGIN_ID + ".swns0000";
+	public static final String NEW_SERVER_NAME = ServerUICore.PLUGIN_ID + ".swns0002";
+	public static final String NEW_SERVER_FOLDER = ServerUICore.PLUGIN_ID + ".swns0004";
+	public static final String NEW_SERVER_INSTANCE_FACTORY = ServerUICore.PLUGIN_ID + ".swns0006";
+	
+	public static final String LAUNCH_CONFIGURATION_SERVER_COMBO = ServerUICore.PLUGIN_ID + ".swsl0000";
+	
+	public static final String SELECT_TASK_WIZARD = ServerUICore.PLUGIN_ID + ".sstw0000";
+
+	public static final String IMPORT_CONFIGURATION_WIZARD = ServerUICore.PLUGIN_ID + ".swic0000";
+	public static final String IMPORT_CONFIGURATION_NAME = ServerUICore.PLUGIN_ID + ".swic0002";
+	public static final String IMPORT_CONFIGURATION_FOLDER = ServerUICore.PLUGIN_ID + ".swic0004";
+	public static final String IMPORT_CONFIGURATION_FACTORY = ServerUICore.PLUGIN_ID + ".swic0006";
+	public static final String IMPORT_CONFIGURATION_LOCATION = ServerUICore.PLUGIN_ID + ".swic0008";
+	public static final String IMPORT_CONFIGURATION_LOCATION_BROWSE = ServerUICore.PLUGIN_ID + ".swic0010";
+	
+	public static final String MODIFY_MODULES_COMPOSITE = ServerUICore.PLUGIN_ID + ".swmm0000";
+
+	public static final String NEW_SERVER_PROJECT_DIALOG = ServerUICore.PLUGIN_ID + ".sdnp0000";
+
+	public static final String TERMINATE_SERVER_DIALOG = ServerUICore.PLUGIN_ID + ".sdti0000";
+
+	public static final String PREF_GENERAL = ServerUICore.PLUGIN_ID + ".spge0000";
+	public static final String PREF_GENERAL_SHOW_PUBLISHING_DETAILS = ServerUICore.PLUGIN_ID + ".spge0010";
+	public static final String PREF_GENERAL_PUBLISH_BEFORE_START = ServerUICore.PLUGIN_ID + ".spge0012";
+	public static final String PREF_GENERAL_AUTO_RESTART = ServerUICore.PLUGIN_ID + ".spge0014";
+	public static final String PREF_GENERAL_PUBLISHER = ServerUICore.PLUGIN_ID + ".spge0015";
+	public static final String PREF_GENERAL_REPAIR = ServerUICore.PLUGIN_ID + ".spge0018";
+	public static final String PREF_GENERAL_PROMPT_IRREVERSIBLE = ServerUICore.PLUGIN_ID + ".spge0020";
+	public static final String PREF_GENERAL_CREATE_IN_WORKSPACE = ServerUICore.PLUGIN_ID + ".spge0022";
+	public static final String PREF_GENERAL_SAVE_EDITORS = ServerUICore.PLUGIN_ID + ".spge0024";
+
+	public static final String VIEW_CONFIG = ServerUICore.PLUGIN_ID + ".svcf0000";
+
+	public static final String VIEW_CONTROL = ServerUICore.PLUGIN_ID + ".svcp0000";
+
+	public static final String PUBLISH_DETAILS_DIALOG = ServerUICore.PLUGIN_ID + ".sdpd0000";
+	public static final String PUBLISH_DETAILS_DIALOG_STATUS = ServerUICore.PLUGIN_ID + ".sdpd0002";
+	public static final String PUBLISH_DETAILS_DIALOG_DETAILS_BUTTON = ServerUICore.PLUGIN_ID + ".sdpd0004";
+	public static final String PUBLISH_DETAILS_DIALOG_DETAILS = ServerUICore.PLUGIN_ID + ".sdpd0006";
+
+	public static final String PUBLISHER_DIALOG = ServerUICore.PLUGIN_ID + ".sdpr0000";
+	public static final String PUBLISHER_DIALOG_TREE = ServerUICore.PLUGIN_ID + ".sdpr0002";
+	public static final String PUBLISHER_DIALOG_SELECT_ALL = ServerUICore.PLUGIN_ID + ".sdpr0004";
+	public static final String PUBLISHER_DIALOG_DESELECT_ALL = ServerUICore.PLUGIN_ID + ".sdpr0006";
+	public static final String PUBLISHER_DIALOG_FILTER = ServerUICore.PLUGIN_ID + ".sdpr0008";
+	public static final String PUBLISHER_DIALOG_FILTER_DIALOG = ServerUICore.PLUGIN_ID + ".sdpr0010";
+	
+	public static final String PROMPT_IRREVERSIBLE_DIALOG = ServerUICore.PLUGIN_ID + ".sdpi0000";
+	
+	public static final String EDITOR_OVERVIEW_PAGE = ServerUICore.PLUGIN_ID + ".seop0000";
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DefaultServerImageDescriptor.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DefaultServerImageDescriptor.java
new file mode 100644
index 0000000..bdad3ef
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DefaultServerImageDescriptor.java
@@ -0,0 +1,95 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.resource.CompositeImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+/**
+ * A OverlayImageDescriptor consists of a main icon and one or more overlays.
+ * The overlays are computed according to flags set on creation of the descriptor.
+ */
+public class DefaultServerImageDescriptor extends CompositeImageDescriptor {
+	private Image fBaseImage;
+	private Point fSize;
+	
+	/**
+	 * Create a new OverlayImageDescriptor.
+	 * 
+	 * @param baseImage an image descriptor used as the base image
+	 * @param flags flags indicating which adornments are to be rendered
+	 */
+	public DefaultServerImageDescriptor(Image baseImage) {
+		setBaseImage(baseImage);
+	}
+
+	/**
+	 * @see CompositeImageDescriptor#getSize()
+	 */
+	protected Point getSize() {
+		if (fSize == null) {
+			ImageData data = getBaseImage().getImageData();
+			setSize(new Point(data.width, data.height));
+		}
+		return fSize;
+	}
+	
+	/**
+	 * @see Object#equals(java.lang.Object)
+	 */
+	public boolean equals(Object object) {
+		if (!(object instanceof DefaultServerImageDescriptor))
+			return false;
+			
+		DefaultServerImageDescriptor other = (DefaultServerImageDescriptor) object;
+		return (getBaseImage().equals(other.getBaseImage()));
+	}
+	
+	/**
+	 * @see Object#hashCode()
+	 */
+	public int hashCode() {
+		return getBaseImage().hashCode();
+	}
+	
+	/**
+	 * @see CompositeImageDescriptor#drawCompositeImage(int, int)
+	 */
+	protected void drawCompositeImage(int width, int height) {
+		ImageData bg = getBaseImage().getImageData();
+		if (bg == null)
+			bg = DEFAULT_IMAGE_DATA;
+
+		drawImage(bg, 0, 0);
+		drawOverlays();
+	}
+
+	/**
+	 * Add any overlays to the image as specified in the flags.
+	 */
+	protected void drawOverlays() {
+		ImageData data = ImageResource.getImage(ImageResource.IMG_DEFAULT_SERVER_OVERLAY).getImageData();
+		int x = getSize().x - data.width;
+		drawImage(data, x, 0);
+	}
+	
+	protected Image getBaseImage() {
+		return fBaseImage;
+	}
+
+	protected void setBaseImage(Image baseImage) {
+		fBaseImage = baseImage;
+	}
+
+	protected void setSize(Point size) {
+		fSize = size;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DefaultServerLabelDecorator.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DefaultServerLabelDecorator.java
new file mode 100644
index 0000000..6c8626e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DefaultServerLabelDecorator.java
@@ -0,0 +1,72 @@
+package org.eclipse.wst.server.ui.internal;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.graphics.Image;
+/**
+ * 
+ */
+public class DefaultServerLabelDecorator implements ILabelDecorator {
+	protected Map map = new HashMap();
+
+	//protected Image image2;
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ILabelDecorator#decorateImage(org.eclipse.swt.graphics.Image, java.lang.Object)
+	 */
+	public Image decorateImage(Image image, Object element) {
+		try {
+			Image img = (Image) map.get(element);
+			if (img != null)
+				return img;
+		} catch (Exception e) { }
+		
+		DefaultServerImageDescriptor dsid = new DefaultServerImageDescriptor(image);
+		Image image2 = dsid.createImage();
+		map.put(element, image2);
+		return image2;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ILabelDecorator#decorateText(java.lang.String, java.lang.Object)
+	 */
+	public String decorateText(String text, Object element) {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
+	 */
+	public void addListener(ILabelProviderListener listener) { }
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
+	 */
+	public void dispose() {
+		try {
+			Iterator iterator = map.values().iterator();
+			while (iterator.hasNext()) {
+				Image image = (Image) iterator.next();
+				image.dispose();
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not dispose images", e);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
+	 */
+	public boolean isLabelProperty(Object element, String property) {
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
+	 */
+	public void removeListener(ILabelProviderListener listener) { }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DeleteServerDialog.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DeleteServerDialog.java
new file mode 100644
index 0000000..ed4fbee
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/DeleteServerDialog.java
@@ -0,0 +1,141 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.swt.SWT;
+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.swt.widgets.Shell;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+
+import org.eclipse.wst.server.core.IElement;
+/**
+ * Dialog that prompts a user to delete server(s) and/or server configuration(s).
+ */
+public class DeleteServerDialog extends Dialog {
+	protected List deleteList;
+	protected List configList;
+
+	protected Button check;
+
+	/**
+	 * DeleteServerDialog constructor comment.
+	 * @param parentShell org.eclipse.swt.widgets.Shell
+	 * @
+	 */
+	public DeleteServerDialog(Shell parentShell, List deleteList, List configList) {
+		super(parentShell);
+		
+		if (deleteList == null)
+			deleteList = new ArrayList(0);
+		if (configList == null)
+			configList = new ArrayList(0);
+		
+		this.deleteList = deleteList;
+		this.configList = configList;
+
+		setBlockOnOpen(true);
+	}
+
+	/**
+	 *
+	 */
+	protected void configureShell(Shell newShell) {
+		super.configureShell(newShell);
+		newShell.setText(ServerUIPlugin.getResource("%deleteServerResourceDialogTitle"));
+	}
+
+	/**
+	 * 
+	 */
+	protected Control createDialogArea(Composite parent) {
+		// create a composite with standard margins and spacing
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+		composite.setFont(parent.getFont());
+		//WorkbenchHelp.setHelp(composite, ContextIds.TERMINATE_SERVER_DIALOG);
+	
+		Label label = new Label(composite, SWT.NONE);
+		if (deleteList.size() == 1) {
+			IElement element = (IElement) deleteList.get(0);
+			label.setText(ServerUIPlugin.getResource("%deleteServerResourceDialogMessage", element.getName()));
+		} else
+			label.setText(ServerUIPlugin.getResource("%deleteServerResourceDialogMessageMany", deleteList.size() + ""));
+		label.setLayoutData(new GridData());
+		
+		if (!configList.isEmpty()) {
+			check = new Button(composite, SWT.CHECK);
+		
+			if (configList.size() == 1) {
+				IElement element = (IElement) configList.get(0);
+				check.setText(ServerUIPlugin.getResource("%deleteServerResourceDialogLooseConfigurations", element.getName()));
+			} else
+				check.setText(ServerUIPlugin.getResource("%deleteServerResourceDialogLooseConfigurationsMany", configList.size() + ""));
+			check.setSelection(true);
+			check.setLayoutData(new GridData());
+		}
+		
+		Dialog.applyDialogFont(composite);
+	
+		return composite;
+	}
+
+	protected void okPressed() {
+		final boolean checked = (check != null && check.getSelection());
+		
+		try {
+			WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
+				protected void execute(IProgressMonitor monitor) throws CoreException {
+					try {
+						Iterator iterator = deleteList.iterator();
+						while (iterator.hasNext()) {
+							IElement element = (IElement) iterator.next();
+							element.delete();
+						}
+						
+						if (checked) {
+							iterator = configList.iterator();
+							while (iterator.hasNext()) {
+								IElement element = (IElement) iterator.next();
+								element.delete();
+							}
+						}
+					} catch (Exception e) {
+						Trace.trace(Trace.SEVERE, "Error while deleting resources", e);
+					}
+				}
+			};
+			new ProgressMonitorDialog(getShell()).run(true, true, op);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error deleting resources", e);
+		}
+		
+		super.okPressed();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/EclipseUtil.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/EclipseUtil.java
new file mode 100644
index 0000000..2e32d40
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/EclipseUtil.java
@@ -0,0 +1,218 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.core.resources.IProject;
+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.NullProgressMonitor;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+import org.eclipse.wst.server.core.IElement;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ServerCore;
+/**
+ * Eclipse utility methods.
+ */
+public class EclipseUtil {
+	/**
+	 * EclipseUtil constructor comment.
+	 */
+	private EclipseUtil() {
+		super();
+	}
+
+	/**
+	 * Creates a new server project with the given name. If path is
+	 * null, it will be created in the default location.
+	 *
+	 * @param name java.lang.String
+	 * @param path org.eclipse.core.resource.IPath
+	 * @return org.eclipse.core.resources.IProject
+	 */
+	public static IStatus createNewServerProject(final Shell shell, String name, IPath path, IProgressMonitor monitor) {
+		final IStatus status = ServerCore.createServerProject(name, path, monitor);
+		if (!status.isOK()) {
+			Display.getDefault().asyncExec(new Runnable() {
+				public void run() {
+					openError(shell, ServerUIPlugin.getResource("%errorCouldNotCreateServerProject"), status);
+				}
+			});
+		}
+		return status;
+	}
+
+	/**
+	 * Returns the image for a project.
+	 *
+	 * @param project org.eclipse.core.resources.IProject
+	 * @return org.eclipse.jface.resource.ImageDescriptor
+	 */
+	public static ImageDescriptor getProjectImageDescriptor(IProject project) {
+		if (project == null)
+			return null;
+	
+		IWorkbenchAdapter adapter = (IWorkbenchAdapter) project.getAdapter(IWorkbenchAdapter.class);
+	
+		if (adapter != null)
+			return adapter.getImageDescriptor(project);
+		else
+			return null;
+	}
+
+	/**
+	 * Return a shell for the workbench.
+	 *
+	 * @return org.eclipse.swt.widgets.Shell
+	 */
+	public static Shell getShell() {
+		return getStandardDisplay().getActiveShell();
+	}
+	
+	/**
+	 * Returns the standard display to be used. The method first checks, if
+	 * the thread calling this method has an associated display. If so, this
+	 * display is returned. Otherwise the method returns the default display.
+	 */
+	public static Display getStandardDisplay() {
+		Display display = Display.getCurrent();
+		if (display == null)
+			display = Display.getDefault();
+
+		return display;		
+	}	
+	
+	/**
+	 * Open a dialog window.
+	 *
+	 * @param title java.lang.String
+	 * @param message java.lang.String
+	 */
+	public static void openError(final String message) {
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				Shell shell = getShell();
+				MessageDialog.openError(shell, ServerUIPlugin.getResource("%errorDialogTitle"), message);
+			}
+		});
+	}
+
+	/**
+	 * Open a dialog window.
+	 *
+	 * @param message java.lang.String
+	 * @param status IStatus
+	 */
+	public static void openError(final String message, final IStatus status) {
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				Shell shell = getShell();
+				ErrorDialog.openError(shell, ServerUIPlugin.getResource("%errorDialogTitle"), message, status);
+			}
+		});
+	}
+
+	/**
+	 * Open a dialog window.
+	 *
+	 * @param title java.lang.String
+	 * @param message java.lang.String
+	 */
+	public static void openError(Shell shell, String message) {
+		MessageDialog.openError(shell, ServerUIPlugin.getResource("%errorDialogTitle"), message);
+	}
+
+	/**
+	 * Open a dialog window.
+	 *
+	 * @param message java.lang.String
+	 * @param status IStatus
+	 */
+	public static void openError(Shell shell, String message, IStatus status) {
+		ErrorDialog.openError(shell, ServerUIPlugin.getResource("%errorDialogTitle"), message, status);
+	}
+	
+	/**
+	 * Start a server and display a dialog if it fails.
+	 */
+	public static ILaunch startServer(final Shell shell, final IServer server, final String mode, final ServerStartupListener listener) throws CoreException {
+		// Eclipse v2 workaround to make sure that the debug UI listeners are setup
+		DebugUIPlugin.getDefault();
+
+		try {
+			return server.start(mode, new NullProgressMonitor());
+		} catch (final CoreException e) {
+			Trace.trace(Trace.SEVERE, "Error starting server", e);
+			Display.getDefault().syncExec(new Runnable() {
+				public void run() {
+					EclipseUtil.openError(shell, ServerUIPlugin.getResource("%serverStartError"), e.getStatus());
+					listener.setEnabled(false);
+				}
+			});
+			throw e;
+		}
+	}
+
+	/**
+	 * Do a validateEdit() on the given server element.
+	 */
+	public static boolean validateEdit(Shell shell, IElement element) {
+		/*IFile file = null;
+		if (element instanceof IServer)
+			file = ((IServer) element).getFile();
+		else if (element instanceof IServerConfiguration)
+			file = ((IServerConfiguration) element).getFile();
+
+		IFile[] files = GlobalCommandManager.getReadOnlyFiles(element);
+		if (files.length == 0)
+			return true;
+		
+		int size = files.length;
+		long[] timestamps = new long[size];
+		for (int i = 0; i < size; i++) {
+			timestamps[i] = files[i].getFullPath().toFile().lastModified();
+		}
+		IStatus status = file.getWorkspace().validateEdit(files, shell);*/
+		IStatus status = element.validateEdit(shell);
+		
+		if (status != null && status.getSeverity() == IStatus.ERROR) {
+			// inform user
+			String message = ServerUIPlugin.getResource("%editorValidateEditFailureMessage");
+			ErrorDialog.openError(shell, ServerUIPlugin.getResource("%errorDialogTitle"), message, status);
+
+			// do not execute command
+			return false;
+		}/* else {
+			boolean reload = false;
+			for (int i = 0; !reload && i < size; i++) {
+				if (timestamps[i] != files[i].getFullPath().toFile().lastModified())
+					reload = true;
+			}
+			if (reload) {
+				try {
+					file.refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor());
+				} catch (Exception e) { }
+			}
+			
+			// allow edit
+			return true;
+		}*/
+		return true;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ImageResource.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ImageResource.java
new file mode 100644
index 0000000..eb37fc3
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ImageResource.java
@@ -0,0 +1,345 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+/**
+ * Utility class to handle image resources.
+ */
+public class ImageResource {
+	// the image registry
+	private static ImageRegistry imageRegistry;
+
+	// map of image descriptors since these
+	// will be lost by the image registry
+	private static Map imageDescriptors;
+
+	// map of IElement images
+	private static Map elementImages;
+
+	// base urls for images
+	private static URL ICON_BASE_URL;
+
+	static {
+		try {
+			String pathSuffix = "icons/";
+			ICON_BASE_URL = ServerUIPlugin.getInstance().getBundle().getEntry(pathSuffix);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not set icon base URL", e);
+		}
+	}
+
+	private static final String URL_CLCL = "clcl16/";
+	private static final String URL_CTOOL = "ctool16/";
+	
+	private static final String URL_ELCL = "elcl16/";
+	private static final String URL_ETOOL = "etool16/";
+	
+	private static final String URL_DLCL = "dlcl16/";
+	private static final String URL_DTOOL = "dtool16/";
+
+	private static final String URL_OBJ = "obj16/";
+	
+	private static final String URL_OVR = "ovr16/";
+
+	private static final String URL_WIZBAN = "wizban/";
+
+	// --- constants for images ---
+
+	// Server State Images
+	public static final String IMG_CLCL_START = "IMG_CLCL_START";
+	public static final String IMG_CLCL_START_DEBUG = "IMG_CLCL_START_DEBUG";
+	public static final String IMG_CLCL_START_PROFILE = "IMG_CLCL_START_PROFILE";
+	public static final String IMG_CLCL_RESTART = "IMG_CLCL_RESTART";
+	public static final String IMG_CLCL_STOP = "IMG_CLCL_STOP";
+	public static final String IMG_CLCL_PUBLISH = "IMG_CLCL_PUBLISH";
+	public static final String IMG_CLCL_DISCONNECT = "IMG_CLCL_DISCONNECT";
+
+	public static final String IMG_ELCL_START = "IMG_ELCL_START";
+	public static final String IMG_ELCL_START_DEBUG = "IMG_ELCL_START_DEBUG";
+	public static final String IMG_ELCL_START_PROFILE = "IMG_ELCL_START_PROFILE";
+	public static final String IMG_ELCL_RESTART = "IMG_ELCL_RESTART";
+	public static final String IMG_ELCL_STOP = "IMG_ELCL_STOP";
+	public static final String IMG_ELCL_PUBLISH = "IMG_ELCL_PUBLISH";
+	public static final String IMG_ELCL_DISCONNECT = "IMG_ELCL_DISCONNECT";
+
+	public static final String IMG_DLCL_START = "IMG_DLCL_START";
+	public static final String IMG_DLCL_START_DEBUG = "IMG_DLCL_START_DEBUG";
+	public static final String IMG_DLCL_START_PROFILE = "IMG_DLCL_START_PROFILE";
+	public static final String IMG_DLCL_RESTART = "IMG_DLCL_RESTART";
+	public static final String IMG_DLCL_STOP = "IMG_DLCL_STOP";
+	public static final String IMG_DLCL_PUBLISH = "IMG_DLCL_PUBLISH";
+	public static final String IMG_DLCL_DISCONNECT = "IMG_DLCL_DISCONNECT";
+
+	// Wizard Banner Images
+	public static final String IMG_WIZBAN_NEW_RUNTIME = "newServerWiz";
+	public static final String IMG_WIZBAN_NEW_SERVER = "newServerWiz";
+	public static final String IMG_WIZBAN_NEW_SERVER_PROJECT = "newServerProjectWiz";
+	public static final String IMG_WIZBAN_SELECT_SERVER_CLIENT = "wizClient";
+	public static final String IMG_WIZBAN_SELECT_SERVER = "selectServer";
+	public static final String IMG_WIZBAN_IMPORT_SERVER_CONFIGURATION = "importConfigWiz";
+	public static final String IMG_WIZBAN_VISUAL_PUBLISHER = "visualPublisher";
+
+	public static final String IMG_SERVER_STATE_STARTED = "stateStarted";
+	public static final String IMG_SERVER_STATE_STARTED_DEBUG = "stateStartedDebug";
+	public static final String IMG_SERVER_STATE_STARTED_PROFILE = "stateStartedProfile";
+	public static final String IMG_SERVER_STATE_STOPPED = "stateStopped";
+	
+	public static final String IMG_SERVER_STATE_STARTING_1 = "stateStarting1";
+	public static final String IMG_SERVER_STATE_STARTING_2 = "stateStarting2";
+	public static final String IMG_SERVER_STATE_STARTING_3 = "stateStarting3";
+	
+	public static final String IMG_SERVER_STATE_STOPPING_1 = "stateStopping1";
+	public static final String IMG_SERVER_STATE_STOPPING_2 = "stateStopping2";
+	public static final String IMG_SERVER_STATE_STOPPING_3 = "stateStopping3";
+
+	// Server Client Images
+	public static final String IMG_CTOOL_RUN_ON_SERVER = "IMG_CTOOL_CLIENT";
+	public static final String IMG_CTOOL_DEBUG_ON_SERVER = "IMG_CTOOL_CLIENT2";
+	public static final String IMG_CTOOL_PROFILE_ON_SERVER = "IMG_CTOOL_CLIENT3";
+	public static final String IMG_CTOOL_NEW_SERVER = "IMG_CTOOL_NEW_SERVER";
+	public static final String IMG_CTOOL_NEW_SERVER_INSTANCE = "IMG_CTOOL_NEW_SERVER_INSTANCE";
+	public static final String IMG_CTOOL_NEW_SERVER_CONFIGURATION = "IMG_CTOOL_NEW_SERVER_CONFIGURATION";
+	public static final String IMG_CTOOL_MODIFY_MODULES = "IMG_CTOOL_MODIFY_MODULES";
+
+	public static final String IMG_ETOOL_RUN_ON_SERVER = "IMG_ETOOL_CLIENT";
+	public static final String IMG_ETOOL_DEBUG_ON_SERVER = "IMG_ETOOL_CLIENT2";
+	public static final String IMG_ETOOL_PROFILE_ON_SERVER = "IMG_ETOOL_CLIENT3";
+	public static final String IMG_ETOOL_MODIFY_MODULES = "IMG_ETOOL_MODIFY_MODULES";
+
+	public static final String IMG_DTOOL_RUN_ON_SERVER = "IMG_DTOOL_CLIENT";
+	public static final String IMG_DTOOL_DEBUG_ON_SERVER = "IMG_DTOOL_CLIENT2";
+	public static final String IMG_DTOOL_PROFILE_ON_SERVER = "IMG_DTOOL_CLIENT3";
+	public static final String IMG_DTOOL_MODIFY_MODULES = "IMG_DTOOL_MODIFY_MODULES";
+
+	// General Object Images
+	public static final String IMG_SERVER_PROJECT = "serverProject";
+	public static final String IMG_SERVER_CONFIGURATION = "configuration";
+	public static final String IMG_SERVER = "server";
+	public static final String IMG_SERVER_CONFIGURATION_NONE = "noConfiguration";
+	public static final String IMG_SERVER_CONFIGURATION_MISSING = "configurationMissing";
+	public static final String IMG_PROJECT_MISSING = "projectMissing";
+	public static final String IMG_REPAIR_CONFIGURATION = "repairConfiguration";
+
+	public static final String IMG_PUBLISH_ENABLED = "publishEnabled";
+	public static final String IMG_PUBLISH_DISABLED = "publishDisabled";
+	
+	public static final String IMG_MONITOR_ON = "monitorOn";
+	public static final String IMG_MONITOR_OFF = "monitorOff";
+	
+	public static final String IMG_DEFAULT_SERVER_OVERLAY = "defaultServerOverlay";
+
+	/**
+	 * Cannot construct an ImageResource. Use static methods only.
+	 */
+	private ImageResource() { }
+	
+	/**
+	 * Dispose of element images that were created.
+	 */
+	protected static void dispose() {
+		try {
+			Trace.trace("Disposing of element images");
+			Iterator iterator = elementImages.values().iterator();
+			while (iterator.hasNext()) {
+				Image image = (Image) iterator.next();
+				image.dispose();
+			}
+		} catch (Exception e) {
+			Trace.trace("Could not dispose of images");
+		}
+	}
+
+	/**
+	 * Return the image with the given key.
+	 *
+	 * @param key java.lang.String
+	 * @return org.eclipse.swt.graphics.Image
+	 */
+	public static Image getImage(String key) {
+		if (imageRegistry == null)
+			initializeImageRegistry();
+		Image image = imageRegistry.get(key);
+		if (image == null) {
+			imageRegistry.put(key, ImageDescriptor.getMissingImageDescriptor());
+			image = imageRegistry.get(key);
+		}
+		return image;
+	}
+
+	/**
+	 * Return the image descriptor with the given key.
+	 *
+	 * @param key java.lang.String
+	 * @return org.eclipse.jface.resource.ImageDescriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String key) {
+		if (imageRegistry == null)
+			initializeImageRegistry();
+		ImageDescriptor id = (ImageDescriptor) imageDescriptors.get(key);
+		if (id != null)
+			return id;
+		else
+			return ImageDescriptor.getMissingImageDescriptor();
+	}
+
+	/**
+	 * Initialize the image resources.
+	 */
+	protected static void initializeImageRegistry() {
+		imageRegistry = new ImageRegistry();
+		imageDescriptors = new HashMap();
+
+		// wizard banners
+		registerImage(IMG_WIZBAN_NEW_SERVER, URL_WIZBAN + "new_server_wiz.gif");
+		registerImage(IMG_WIZBAN_NEW_SERVER_PROJECT, URL_WIZBAN + "new_server_project_wiz.gif");
+		registerImage(IMG_WIZBAN_IMPORT_SERVER_CONFIGURATION, URL_WIZBAN + "import_server_wiz.gif");
+		registerImage(IMG_WIZBAN_SELECT_SERVER_CLIENT, URL_WIZBAN + "select_client_wiz.gif");
+		registerImage(IMG_WIZBAN_SELECT_SERVER, URL_WIZBAN + "select_server_wiz.gif");
+		registerImage(IMG_WIZBAN_VISUAL_PUBLISHER, URL_WIZBAN + "pub_resource_server_wiz.gif");
+
+		// client images
+		registerImage(IMG_ETOOL_RUN_ON_SERVER, URL_ETOOL + "run_on_server.gif");
+		registerImage(IMG_ETOOL_DEBUG_ON_SERVER, URL_ETOOL + "debug_on_server.gif");
+		registerImage(IMG_ETOOL_PROFILE_ON_SERVER, URL_ETOOL + "profile_on_server.gif");
+		registerImage(IMG_ETOOL_MODIFY_MODULES, URL_ETOOL + "wiz_modify_modules.gif");
+
+		registerImage(IMG_CTOOL_RUN_ON_SERVER, URL_CTOOL + "run_on_server.gif");
+		registerImage(IMG_CTOOL_DEBUG_ON_SERVER, URL_CTOOL + "debug_on_server.gif");
+		registerImage(IMG_CTOOL_PROFILE_ON_SERVER, URL_CTOOL + "profile_on_server.gif");
+		registerImage(IMG_CTOOL_NEW_SERVER, URL_CTOOL + "wiz_new_server.gif");
+		registerImage(IMG_CTOOL_NEW_SERVER_INSTANCE, URL_CTOOL + "wiz_new_instance.gif");
+		registerImage(IMG_CTOOL_NEW_SERVER_CONFIGURATION, URL_CTOOL + "wiz_new_configuration.gif");
+		registerImage(IMG_CTOOL_MODIFY_MODULES, URL_CTOOL + "wiz_modify_modules.gif");
+
+		registerImage(IMG_DTOOL_RUN_ON_SERVER, URL_DTOOL + "run_on_server.gif");
+		registerImage(IMG_DTOOL_DEBUG_ON_SERVER, URL_DTOOL + "debug_on_server.gif");
+		registerImage(IMG_DTOOL_PROFILE_ON_SERVER, URL_DTOOL + "profile_on_server.gif");
+		registerImage(IMG_DTOOL_MODIFY_MODULES, URL_DTOOL + "wiz_modify_modules.gif");
+	
+		// load server state images
+		registerImage(IMG_SERVER_STATE_STARTED, URL_OBJ + "server_started.gif");
+		registerImage(IMG_SERVER_STATE_STARTED_DEBUG, URL_OBJ + "server_started_debug.gif");
+		registerImage(IMG_SERVER_STATE_STARTED_PROFILE, URL_OBJ + "server_started_profile.gif");
+		registerImage(IMG_SERVER_STATE_STOPPED, URL_OBJ + "server_stopped.gif");
+		
+		registerImage(IMG_SERVER_STATE_STARTING_1, URL_OBJ + "server_starting1.gif");
+		registerImage(IMG_SERVER_STATE_STARTING_2, URL_OBJ + "server_starting2.gif");
+		registerImage(IMG_SERVER_STATE_STARTING_3, URL_OBJ + "server_starting3.gif");
+		
+		registerImage(IMG_SERVER_STATE_STOPPING_1, URL_OBJ + "server_stopping1.gif");
+		registerImage(IMG_SERVER_STATE_STOPPING_2, URL_OBJ + "server_stopping2.gif");
+		registerImage(IMG_SERVER_STATE_STOPPING_3, URL_OBJ + "server_stopping3.gif");
+	
+		// load action images
+		registerImage(IMG_ELCL_PUBLISH, URL_ELCL + "launch_publish.gif");
+		registerImage(IMG_ELCL_START, URL_ELCL + "launch_run.gif");
+		registerImage(IMG_ELCL_START_DEBUG, URL_ELCL + "launch_debug.gif");
+		registerImage(IMG_ELCL_START_PROFILE, URL_ELCL + "launch_profile.gif");
+		registerImage(IMG_ELCL_RESTART, URL_ELCL + "launch_restart.gif");
+		registerImage(IMG_ELCL_STOP, URL_ELCL + "launch_stop.gif");
+		registerImage(IMG_ELCL_DISCONNECT, URL_ELCL + "launch_disconnect.gif");
+	
+		registerImage(IMG_CLCL_PUBLISH, URL_CLCL + "launch_publish.gif");
+		registerImage(IMG_CLCL_START, URL_CLCL + "launch_run.gif");
+		registerImage(IMG_CLCL_START_DEBUG, URL_CLCL + "launch_debug.gif");
+		registerImage(IMG_CLCL_START_PROFILE, URL_CLCL + "launch_profile.gif");
+		registerImage(IMG_CLCL_RESTART, URL_CLCL + "launch_restart.gif");
+		registerImage(IMG_CLCL_STOP, URL_CLCL + "launch_stop.gif");
+		registerImage(IMG_CLCL_DISCONNECT, URL_CLCL + "launch_disconnect.gif");
+	
+		registerImage(IMG_DLCL_PUBLISH, URL_DLCL + "launch_publish.gif");
+		registerImage(IMG_DLCL_START, URL_DLCL + "launch_run.gif");
+		registerImage(IMG_DLCL_START_DEBUG, URL_DLCL + "launch_debug.gif");
+		registerImage(IMG_DLCL_START_PROFILE, URL_DLCL + "launch_profile.gif");
+		registerImage(IMG_DLCL_RESTART, URL_DLCL + "launch_restart.gif");
+		registerImage(IMG_DLCL_STOP, URL_DLCL + "launch_stop.gif");
+		registerImage(IMG_DLCL_DISCONNECT, URL_DLCL + "launch_disconnect.gif");
+	
+		// load general object images
+		registerImage(IMG_SERVER_PROJECT, URL_OBJ + "server_project.gif");
+		registerImage(IMG_SERVER, URL_OBJ + "server.gif");
+		registerImage(IMG_SERVER_CONFIGURATION, URL_OBJ + "configuration.gif");
+		registerImage(IMG_SERVER_CONFIGURATION_NONE, URL_OBJ + "configuration_none.gif");
+		registerImage(IMG_SERVER_CONFIGURATION_MISSING, URL_OBJ + "configuration_missing.gif");
+		registerImage(IMG_PROJECT_MISSING, URL_OBJ + "project_missing.gif");
+		registerImage(IMG_REPAIR_CONFIGURATION, URL_OBJ + "repair_config.gif");
+	
+		registerImage(IMG_PUBLISH_ENABLED, URL_OBJ + "publish_enabled.gif");
+		registerImage(IMG_PUBLISH_DISABLED, URL_OBJ + "publish_disabled.gif");
+		
+		registerImage(IMG_MONITOR_ON, URL_OBJ + "monitorOn.gif");
+		registerImage(IMG_MONITOR_OFF, URL_OBJ + "monitorOff.gif");
+		
+		registerImage(IMG_DEFAULT_SERVER_OVERLAY, URL_OVR + "default_server_ovr.gif");
+		
+		loadServerImages();
+	}
+
+	/**
+	 * Register an image with the registry.
+	 *
+	 * @param key java.lang.String
+	 * @param partialURL java.lang.String
+	 */
+	private static void registerImage(String key, String partialURL) {
+		try {
+			ImageDescriptor id = ImageDescriptor.createFromURL(new URL(ICON_BASE_URL, partialURL));
+			imageRegistry.put(key, id);
+			imageDescriptors.put(key, id);
+		} catch (Exception e) {
+			Trace.trace("Error registering image " + key + " from " + partialURL, e);
+		}
+	}
+	
+	/**
+	 * Load the server images.
+	 */
+	private static void loadServerImages() {
+		Trace.trace(Trace.CONFIG, "->- Loading .serverImages extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerUICore.PLUGIN_ID, "serverImages");
+
+		int size = cf.length;
+		for (int i = 0; i < size; i++) {
+			try {
+				String pluginId = cf[i].getDeclaringExtension().getNamespace();
+				String iconPath = cf[i].getAttribute("icon");
+				ImageDescriptor imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, iconPath);
+				if (imageDescriptor == null)
+					ImageDescriptor.getMissingImageDescriptor();
+				
+				String typeId = cf[i].getAttribute("typeIds");
+				if (typeId == null)
+					typeId = cf[i].getAttribute("moduleId");
+				imageRegistry.put(typeId, imageDescriptor);		
+				imageDescriptors.put(typeId, imageDescriptor);
+				Trace.trace(Trace.CONFIG, "  Loaded serverImage: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load serverImage: " + cf[i].getAttribute("id"), t);
+			}
+		}
+
+		Trace.trace(Trace.CONFIG, "-<- Done loading .serverImages extension point -<-");
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ModuleRepairDialog.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ModuleRepairDialog.java
new file mode 100644
index 0000000..b1d2c1d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ModuleRepairDialog.java
@@ -0,0 +1,312 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.util.TaskModel;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+
+/**
+ * 
+ */
+public class ModuleRepairDialog extends Dialog {
+	private static final String ROOT = "root";
+	
+	protected static final Object[] EMPTY = new Object[0];
+
+	//protected List fixes;
+	protected IServerLifecycleEvent[] events;
+	protected List checkedList = new ArrayList();
+	protected Map childMap = new HashMap();
+	
+	public class TaskInfo {
+		ITask task;
+		IServerLifecycleEvent parent;
+		//boolean checked = true;
+	}
+	
+	protected CheckboxTreeViewer viewer;
+	
+	// content and label provider for repair dialog
+	public class RepairContentProvider implements ITreeContentProvider {
+		public void dispose() { }
+		
+		public Object getParent(Object element) {
+			if (element instanceof IServerLifecycleEvent)
+				return ROOT;
+			else if (element instanceof TaskInfo)
+				return ((TaskInfo) element).parent;
+			else
+				return null;
+		}
+		
+		public boolean hasChildren(Object element) {
+			return getChildren(element).length > 0;
+		}
+		
+		public Object[] getChildren(Object element) {
+			if (ROOT.equals(element)) {
+				return events;
+			} else if (element instanceof IServerLifecycleEvent) {
+				IServerLifecycleEvent mse = (IServerLifecycleEvent) element;
+				Object children = childMap.get(mse);
+				if (children == null) {
+					ITask[] tasks = mse.getTasks();
+					int size = tasks.length;
+					TaskInfo[] ti = new TaskInfo[size];
+					for (int i = 0; i < size; i++) {
+						ti[i] = new TaskInfo();
+						ti[i].task = tasks[i];
+						ti[i].parent = mse;
+						
+						ITaskModel taskModel = new TaskModel();
+						taskModel.putObject(ITaskModel.TASK_SERVER, mse.getServer());
+						IServerConfiguration config = mse.getServer().getServerConfiguration();
+						if (config != null)
+							taskModel.putObject(ITaskModel.TASK_SERVER_CONFIGURATION, config);
+						tasks[i].setTaskModel(taskModel);
+					}
+					children = ti;
+					childMap.put(mse, children);
+				}
+				return (Object[]) children;
+			}
+			return EMPTY;
+		}
+		
+		public Object[] getElements(Object element) {
+			return getChildren(element);
+		}
+		
+		public void inputChanged(Viewer newViewer, Object oldInput, Object newInput) { }
+	}
+	
+	public class RepairLabelProvider implements ILabelProvider {
+		public void addListener(ILabelProviderListener listener) { }
+		
+		public void removeListener(ILabelProviderListener listener) { }
+		
+		public Image getImage(Object element) {
+			if (element instanceof IServerLifecycleEvent) {
+				return ServerUICore.getLabelProvider().getImage(((IServerLifecycleEvent) element).getServer());
+			} else if (element instanceof TaskInfo) {
+				return ImageResource.getImage(ImageResource.IMG_REPAIR_CONFIGURATION);
+			} else
+				return null;
+		}
+		public String getText(Object element) {
+			if (element instanceof IServerLifecycleEvent) {
+				return ServerUICore.getLabelProvider().getText(((IServerLifecycleEvent) element).getServer());
+			} else if (element instanceof TaskInfo) {
+				return ((TaskInfo) element).task.getDescription();
+			}
+			return "";
+		}
+		
+		public boolean isLabelProperty(Object element, String property) {
+			return false;
+		}
+		
+		public void dispose() { }
+	}
+
+	public ModuleRepairDialog(Shell parent, IServerLifecycleEvent[] events) {
+		super(parent);
+		setShellStyle(SWT.BORDER | SWT.TITLE | SWT.APPLICATION_MODAL); // no close button
+		setBlockOnOpen(true);
+		
+		this.events = events;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared in Window.
+	 */
+	protected void configureShell(Shell shell) {
+		super.configureShell(shell);
+		shell.setText(ServerUIPlugin.getResource("%dialogRepairConfigurationTitle"));
+	}
+	
+	protected Control createDialogArea(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+		composite.setLayout(layout);
+		GridData data = new GridData(GridData.FILL_BOTH);
+		composite.setLayoutData(data);
+		composite.setFont(parent.getFont());
+		
+		Label label = new Label(composite, SWT.WRAP);
+		label.setText(ServerUIPlugin.getResource("%dialogRepairConfigurationMessage"));
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		label.setLayoutData(data);
+		
+		Tree tree = new Tree(composite, SWT.BORDER | SWT.CHECK | SWT.H_SCROLL | SWT.V_SCROLL);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.heightHint = 140;
+		data.widthHint = 400;
+		tree.setLayoutData(data);
+		
+		viewer = new CheckboxTreeViewer(tree);
+		viewer.setLabelProvider(new RepairLabelProvider());
+		viewer.setContentProvider(new RepairContentProvider());
+		viewer.setInput(ROOT);
+		viewer.addCheckStateListener(new ICheckStateListener() {
+			public void checkStateChanged(CheckStateChangedEvent event) {
+				checked(event.getElement(), event.getChecked());
+				viewer.refresh();
+			}
+		});
+		viewer.setSorter(new ViewerSorter() { });
+		viewer.expandToLevel(4);
+		
+		int size = events.length;
+		for (int i = 0; i < size; i++) {
+			viewer.setSubtreeChecked(events[i], true);
+			checked(events[i], true);
+		}
+		
+		Dialog.applyDialogFont(composite);
+		return composite;
+	}
+	
+	protected void addRemove(Object obj, boolean add) {
+		if (add) {
+			if (!checkedList.contains(obj))
+				checkedList.add(obj);
+		} else {
+			if (checkedList.contains(obj))
+				checkedList.remove(obj);
+		}
+	}
+
+	protected void checked(Object element, boolean checked) {
+		if (element instanceof IServerLifecycleEvent) {
+			addRemove(element, checked);
+			viewer.setSubtreeChecked(element, checked);
+			try {
+				RepairContentProvider rcp = (RepairContentProvider) viewer.getContentProvider();
+				Object[] children = rcp.getChildren(element);
+				int size = children.length;
+				for (int i = 0; i < size; i++)
+					addRemove(((TaskInfo)children[i]).task, checked);
+			} catch (Exception e) {
+				// do nothing
+			}
+		} else if (element instanceof TaskInfo) {
+			TaskInfo ti = (TaskInfo) element;
+			addRemove(ti.task, checked);
+			IServerLifecycleEvent mse = ti.parent;
+			if (!checked) { // && anyChildren(info, !checked)) {
+				addRemove(mse, checked);
+				viewer.setChecked(mse, checked);
+			} else if (checked && allChildren(mse, checked)) {
+				addRemove(mse, checked);
+				viewer.setChecked(mse, checked);
+			}
+		}
+	}
+
+	protected boolean allChildren(IServerLifecycleEvent mse, boolean b) {
+		ITask[] tasks = mse.getTasks();
+		if (tasks == null)
+			return false;
+		int size = tasks.length;
+		for (int i = 0; i < size; i++) {
+			if (b != checkedList.contains(tasks[i]))
+				return false;
+		}
+		return true;
+	}
+
+	protected void okPressed() {
+		super.okPressed();
+		
+		// perform commands
+		int size = events.length;
+		List list = new ArrayList();
+		for (int i = 0; i < size; i++) {
+			IServerLifecycleEvent mse = events[i];
+			if (checkedList.contains(mse)) {
+				IServer server = mse.getServer();
+				if (EclipseUtil.validateEdit(getShell(), server)) {
+					IServerWorkingCopy serverWC = server.getWorkingCopy();
+					IServerConfigurationWorkingCopy configWC = null;
+					if (server.getServerConfiguration() != null)
+						configWC = server.getServerConfiguration().getWorkingCopy();
+					
+					ITaskModel taskModel = new TaskModel();
+					taskModel.putObject(ITaskModel.TASK_SERVER, serverWC);
+					if (configWC != null)
+						taskModel.putObject(ITaskModel.TASK_SERVER_CONFIGURATION, configWC);
+					
+					try {
+						//IServerConfiguration config = info.configuration;
+						//IProgressMonitor monitor = new NullProgressMonitor();
+						//IResource resource = ServerCore.getResourceManager().getServerResourceLocation(serverResource);
+						//resource.refreshLocal(IResource.DEPTH_INFINITE, monitor);
+					} catch (Exception e) { }
+					
+					ITask[] tasks = mse.getTasks(); 
+					int size2 = tasks.length;
+					for (int j = 0; j < size2; j++) {
+						if (checkedList.contains(tasks[j])) {
+							try {
+								tasks[j].setTaskModel(taskModel);
+								tasks[j].execute(new NullProgressMonitor());
+							} catch (CoreException ce) {
+								Trace.trace(Trace.SEVERE, "Error executing repair task", ce);
+							}
+						}
+					}
+				
+					try {
+						serverWC.save(new NullProgressMonitor());
+						if (configWC != null)
+							configWC.save(new NullProgressMonitor());
+					} catch (Exception e) { }
+					
+					if (!list.contains(server) && server.isWorkingCopiesExist())
+						list.add(server);
+				}
+			}
+		}
+		
+		// TODO reload affected editors
+		/*size = list.size();
+		for (int i = 0; i < size; i++) {
+			IServerConfiguration config = (IServerConfiguration) list.get(i);
+			GlobalCommandManager.getInstance().reload(config.getId(), new NullProgressMonitor());
+			GlobalCommandManager.getInstance().resourceSaved(config.getId());
+			GlobalCommandManager.getInstance().updateTimestamps(config.getId());
+		}*/
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ModuleRepairSupport.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ModuleRepairSupport.java
new file mode 100644
index 0000000..22945a2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ModuleRepairSupport.java
@@ -0,0 +1,149 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.*;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IServerLifecycleEventHandler;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.ListSelectionDialog;
+
+/**
+ * 
+ */
+public class ModuleRepairSupport implements IServerLifecycleEventHandler {
+	private static final String ROOT = "root";
+	
+	protected static final Object[] EMPTY = new Object[0];
+	
+	// content and label provider for server editor save dialog
+	public class ServerEditorContentProvider implements IStructuredContentProvider {
+		protected List editors;
+		
+		public ServerEditorContentProvider(List editors) {
+			this.editors = editors;	
+		}
+		
+		public void dispose() { }
+		
+		public Object[] getElements(Object element) {
+			if (ROOT.equals(element)) {
+				int size = editors.size();
+				IServerConfiguration[] config = new IServerConfiguration[size];
+				editors.toArray(config);
+				return config;
+			} else
+				return EMPTY;
+		}
+		
+		public void inputChanged(Viewer viewer2, Object oldInput, Object newInput) { }
+	}
+
+	public class ServerEditorLabelProvider implements ILabelProvider {
+		public void addListener(ILabelProviderListener listener) { }
+		
+		public void removeListener(ILabelProviderListener listener) { }
+		
+		public Image getImage(Object element) {
+			return ServerUICore.getLabelProvider().getImage(element);
+		}
+		
+		public String getText(Object element) {
+			return ServerUICore.getLabelProvider().getText(element);
+		}
+		
+		public boolean isLabelProperty(Object element, String property) {
+			return false;
+		}
+		
+		public void dispose() { }
+	}
+	
+	public boolean[] handleModuleServerEvents(final IServerLifecycleEvent[] events) {
+		if (ServerCore.getServerPreferences().getModuleRepairStatus() == IServerPreferences.REPAIR_NEVER)
+			return null;
+			
+		// save open editors
+		final List list = new ArrayList();
+		int size = events.length;
+		boolean[] bool = new boolean[size];
+		for (int i = 0; i < size; i++) {
+			bool[i] = true;
+			IServer server = events[i].getServer();
+			
+			if (!list.contains(server) && server.isWorkingCopiesExist())
+				list.add(server);
+		}
+		
+		final ILabelProvider labelProvider = new ModuleRepairSupport.ServerEditorLabelProvider();
+		final IStructuredContentProvider contentProvider = new ServerEditorContentProvider(list);
+		
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				Shell shell = EclipseUtil.getShell();
+				
+				if (!list.isEmpty()) {
+					ListSelectionDialog dialog1 = new ListSelectionDialog(shell, ROOT,
+						contentProvider, labelProvider, ServerUIPlugin.getResource("%dialogRepairConfigurationSaveMessage"));
+					dialog1.setTitle(ServerUIPlugin.getResource("%dialogRepairConfigurationTitle"));
+					dialog1.setBlockOnOpen(true);
+					dialog1.setInitialSelections(list.toArray());
+					dialog1.open();
+					
+					Object[] result = dialog1.getResult();
+					// save selected editors
+					if (result != null) {
+						int size2 = result.length;
+						for (int i = 0; i < size2; i++) {
+							/*IServerConfiguration config = (IServerConfiguration) result[i];
+							IResource resource = ServerCore.getResourceManager().getServerResourceLocation(config);
+							IServerResource serverResource = ServerCore.getEditManager().getEditModel(resource, new NullProgressMonitor());
+							try {
+								serverResource.save(resource.getProject(), resource.getProjectRelativePath(), new NullProgressMonitor());
+								
+								GlobalCommandManager.getInstance().reload(resource, new NullProgressMonitor());
+								GlobalCommandManager.getInstance().resourceSaved(resource);
+								GlobalCommandManager.getInstance().updateTimestamps(resource);
+								list.remove(config);
+							} catch (CoreException e) {
+								// ignore error for now
+							}*/
+						}
+					}
+					
+					// TODO don't try to modify any unsaved configurations
+					/*int size3 = list.size();
+					for (int i = 0; i < size3; i++) {
+						IServer server = (IServer) list.get(i);
+						int size2 = diskFixes.size();
+						for (int j = size2 - 1; j >= 0; j--) {
+							FixInfo info = (FixInfo) diskFixes.get(j);
+							if (info.server.equals(server)) {
+								diskFixes.remove(j);
+								size2--;
+							}
+						}
+					}*/
+				}
+				
+				ModuleRepairDialog dialog = new ModuleRepairDialog(shell, events);
+				dialog.open();
+			}
+		});
+		
+		return bool;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/OverlayImageDescriptor.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/OverlayImageDescriptor.java
new file mode 100644
index 0000000..df489b7
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/OverlayImageDescriptor.java
@@ -0,0 +1,115 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jface.resource.CompositeImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+/**
+ * A OverlayImageDescriptor consists of a main icon and one or more overlays.
+ * The overlays are computed according to flags set on creation of the descriptor.
+ */
+public class OverlayImageDescriptor extends CompositeImageDescriptor {
+	// flag to render the error overlay
+	public final static int ERROR = 0x001;
+
+	private Image fBaseImage;
+	private int fFlags;
+	private Point fSize;
+	
+	/**
+	 * Create a new OverlayImageDescriptor.
+	 * 
+	 * @param baseImage an image descriptor used as the base image
+	 * @param flags flags indicating which adornments are to be rendered
+	 */
+	public OverlayImageDescriptor(Image baseImage, int flags) {
+		setBaseImage(baseImage);
+		setFlags(flags);
+	}
+
+	/**
+	 * @see CompositeImageDescriptor#getSize()
+	 */
+	protected Point getSize() {
+		if (fSize == null) {
+			ImageData data = getBaseImage().getImageData();
+			setSize(new Point(data.width, data.height));
+		}
+		return fSize;
+	}
+	
+	/**
+	 * @see Object#equals(java.lang.Object)
+	 */
+	public boolean equals(Object object) {
+		if (!(object instanceof OverlayImageDescriptor))
+			return false;
+			
+		OverlayImageDescriptor other = (OverlayImageDescriptor) object;
+		return (getBaseImage().equals(other.getBaseImage()) && getFlags() == other.getFlags());
+	}
+	
+	/**
+	 * @see Object#hashCode()
+	 */
+	public int hashCode() {
+		return getBaseImage().hashCode() | getFlags();
+	}
+	
+	/**
+	 * @see CompositeImageDescriptor#drawCompositeImage(int, int)
+	 */
+	protected void drawCompositeImage(int width, int height) {
+		ImageData bg = getBaseImage().getImageData();
+		if (bg == null)
+			bg = DEFAULT_IMAGE_DATA;
+
+		drawImage(bg, 0, 0);
+		drawOverlays();
+	}
+
+	/**
+	 * Add any overlays to the image as specified in the flags.
+	 */
+	protected void drawOverlays() {
+		int flags = getFlags();
+		ImageData data = null;
+		if ((flags & ERROR) != 0) {
+			data = DebugUITools.getImage(IDebugUIConstants.IMG_OVR_ERROR).getImageData();
+			int x = getSize().x - data.width;
+			drawImage(data, x, 0);
+		}
+	}
+	
+	protected Image getBaseImage() {
+		return fBaseImage;
+	}
+
+	protected void setBaseImage(Image baseImage) {
+		fBaseImage = baseImage;
+	}
+
+	protected int getFlags() {
+		return fFlags;
+	}
+
+	protected void setFlags(int flags) {
+		fFlags = flags;
+	}
+
+	protected void setSize(Point size) {
+		fSize = size;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ProjectPropertyPage.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ProjectPropertyPage.java
new file mode 100644
index 0000000..a14e712
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ProjectPropertyPage.java
@@ -0,0 +1,184 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IProjectModule;
+import org.eclipse.wst.server.ui.ServerUICore;
+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.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+/**
+ * PropertyPage for IProjects. It shows the server and runtime preference for the project.
+ */
+public class ProjectPropertyPage extends PropertyPage {
+	protected IProject project;
+	protected IProjectModule module;
+	protected IServer server;
+	
+	protected RuntimeTargetComposite rtComp;
+
+	/**
+	 * ProjectPropertyPage constructor comment.
+	 */
+	public ProjectPropertyPage() {
+		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();
+			if (element instanceof IProject)
+				project = (IProject) element;
+
+			Composite composite = new Composite(parent, SWT.NONE);
+			GridLayout layout = new GridLayout();
+			layout.marginHeight = 0;
+			layout.marginWidth = 0;
+			layout.numColumns = 3;
+			layout.verticalSpacing = 10;
+			composite.setLayout(layout);
+			composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+			
+			Label label = new Label(composite, SWT.WRAP);
+			label.setText(ServerUIPlugin.getResource("%prefProjectDescription"));
+			GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+			data.horizontalSpan = 3;
+			data.widthHint = 200;
+			label.setLayoutData(data);
+
+			module = ServerUtil.getModuleProject(project);
+
+			if (module == null) {
+				label = new Label(composite, SWT.NONE);
+				label.setText(ServerUIPlugin.getResource("%prefProjectNotModule"));
+				data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+				data.horizontalSpan = 3;
+				label.setLayoutData(data);
+			} else {
+				IModuleKind mk = ServerCore.getModuleKind(module.getType());
+				if (mk != null) {
+					label = new Label(composite, SWT.NONE);
+					label.setText(ServerUIPlugin.getResource("%prefProject"));
+					data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+					label.setLayoutData(data);
+				
+					Label moduleKind = new Label(composite, SWT.NONE);
+					data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+					data.horizontalSpan = 2;
+					moduleKind.setLayoutData(data);
+					moduleKind.setText(module.getName() + " (" + mk.getName() + ")");
+				}
+				
+				rtComp = new RuntimeTargetComposite(composite, project);
+				
+				IProjectProperties prefs = ServerCore.getProjectProperties(project);
+				IServer prefServer = prefs.getDefaultServer();
+	
+				label = new Label(composite, SWT.NONE);
+				label.setText(ServerUIPlugin.getResource("%prefProjectDefaultServer"));
+				data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
+				label.setLayoutData(data);
+				
+				final IServer[] servers = ServerUtil.getServersBySupportedModule(module);
+				if (servers == null || servers.length == 0) {
+					label = new Label(composite, SWT.WRAP);
+					label.setText(ServerUIPlugin.getResource("%prefProjectNotConfigured"));
+					data = new GridData();
+					data.horizontalSpan = 2;
+					label.setLayoutData(data);
+				} else {
+					final Table table = new Table(composite, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL);
+					data = new GridData(GridData.FILL_HORIZONTAL);
+					data.horizontalSpan = 2;
+					data.heightHint = 70;
+					table.setLayoutData(data);
+					
+					// add none option
+					TableItem item = new TableItem(table, SWT.NONE);
+					item.setText(ServerUIPlugin.getResource("%prefProjectNoServer"));
+					//item.setImage();
+					
+					int size2 = servers.length;
+					int count = 0;
+					for (int j = 0; j < size2; j++) {
+						item = new TableItem(table, SWT.NONE);
+						item.setText(ServerUICore.getLabelProvider().getText(servers[j]));
+						item.setImage(ServerUICore.getLabelProvider().getImage(servers[j]));
+						item.setData(servers[j]);
+						if (servers[j].equals(prefServer))
+							count = j + 1;
+					}
+
+					table.setSelection(count);
+
+					table.addSelectionListener(new SelectionAdapter() {
+						public void widgetSelected(SelectionEvent event) {
+							int index = table.getSelectionIndex();
+							if (index == 0) {
+								server = null;
+							} else if (index > 0) {
+								server = servers[index-1];
+							}
+						}
+					});
+				}
+			}
+			
+			Dialog.applyDialogFont(composite);
+
+			return composite;
+		} catch (Exception e) {
+			Trace.trace("Error creating project property page", e);
+			return null;
+		}
+	}
+
+	/** 
+	 * Method declared on IPreferencePage.
+	 * Subclasses should override
+	 */
+	public boolean performOk() {
+		if (module != null) {
+			try {
+				if (rtComp.hasChanged())
+					rtComp.apply(new NullProgressMonitor());
+				
+				IProjectProperties props = ServerCore.getProjectProperties(project);
+				props.setDefaultServer(server, new NullProgressMonitor());
+			} catch (CoreException e) {
+				Trace.trace(Trace.SEVERE, "Error setting preferred server", e);
+				EclipseUtil.openError(ServerUIPlugin.getResource("%errorCouldNotSavePreference"), e.getStatus());
+				return false;
+			}
+		}
+		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/RuntimePreferencePage.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/RuntimePreferencePage.java
new file mode 100644
index 0000000..4dfdc4d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/RuntimePreferencePage.java
@@ -0,0 +1,327 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+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.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.help.WorkbenchHelp;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IRuntimeLocatorListener;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.task.FinishWizardFragment;
+import org.eclipse.wst.server.ui.internal.task.SaveRuntimeTask;
+import org.eclipse.wst.server.ui.internal.viewers.RuntimeComposite;
+import org.eclipse.wst.server.ui.internal.wizard.ClosableWizardDialog;
+import org.eclipse.wst.server.ui.internal.wizard.fragment.NewRuntimeWizardFragment;
+import org.eclipse.wst.server.ui.wizard.IWizardFragment;
+import org.eclipse.wst.server.ui.wizard.TaskWizard;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+/**
+ * The preference page that holds server runtimes.
+ */
+public class RuntimePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+	protected Button edit;
+	protected Button remove;
+
+	/**
+	 * RuntimePreferencesPage constructor comment.
+	 */
+	public RuntimePreferencePage() {
+		super();
+		noDefaultAndApplyButton();
+	}
+	
+	/**
+	 * Create the preference options.
+	 *
+	 * @param parent org.eclipse.swt.widgets.Composite
+	 * @return org.eclipse.swt.widgets.Control
+	 */
+	protected Control createContents(Composite parent) {
+		initializeDialogUnits(parent);
+		
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(4);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 2;
+		composite.setLayout(layout);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
+		composite.setLayoutData(data);
+		WorkbenchHelp.setHelp(composite, ContextIds.PREF_GENERAL);
+		
+		Label label = new Label(composite, SWT.WRAP);
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 2;
+		label.setLayoutData(data);
+		label.setText(ServerUIPlugin.getResource("%preferenceRuntimesDescription"));
+		
+		final RuntimeComposite runtimeComp = new RuntimeComposite(composite, SWT.NONE, new RuntimeComposite.RuntimeSelectionListener() {
+			public void runtimeSelected(IRuntime runtime) {
+				if (runtime == null || runtime.isLocked()) {
+					edit.setEnabled(false);
+					remove.setEnabled(false);
+				} else {
+					edit.setEnabled(true);
+					remove.setEnabled(true);
+				}
+			}
+		});
+		runtimeComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
+		
+		Composite buttonComp = new Composite(composite, SWT.NONE);
+		layout = new GridLayout();
+		layout.horizontalSpacing = 0;
+		layout.verticalSpacing = convertVerticalDLUsToPixels(4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 1;
+		buttonComp.setLayout(layout);
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
+		buttonComp.setLayoutData(data);
+		
+		Button add = SWTUtil.createButton(buttonComp, ServerUIPlugin.getResource("%add"));
+		add.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				if (showWizard(null) == Window.CANCEL)
+					return;
+				runtimeComp.refresh();
+			}
+		});
+		
+		edit = SWTUtil.createButton(buttonComp, ServerUIPlugin.getResource("%edit"));
+		edit.setEnabled(false);
+		edit.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				IRuntime runtime = runtimeComp.getSelectedRuntime();
+				if (runtime != null) {
+					IRuntimeWorkingCopy runtimeWorkingCopy = runtime.getWorkingCopy();
+					if (showWizard(runtimeWorkingCopy) != Window.CANCEL) {
+						try {
+							runtimeWorkingCopy.save(new NullProgressMonitor());
+							runtimeComp.refresh(runtime);
+						} catch (Exception ex) { }
+					}
+				}
+			}
+		});
+		
+		remove = SWTUtil.createButton(buttonComp, ServerUIPlugin.getResource("%remove"));
+		remove.setEnabled(false);
+		remove.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				IRuntime runtime = runtimeComp.getSelectedRuntime();
+				if (shouldRemoveRuntime(runtime))
+					try {
+						runtime.delete();
+						runtimeComp.remove(runtime);
+					} catch (Exception ex) { }
+			}
+		});
+		
+		Button search = SWTUtil.createButton(buttonComp, ServerUIPlugin.getResource("%search"));
+		search.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				try {
+					ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());
+					dialog.setBlockOnOpen(false);
+					dialog.open();
+					final IProgressMonitor monitor = dialog.getProgressMonitor();
+					final List list = new ArrayList();
+					
+					IRuntimeLocatorListener listener = new IRuntimeLocatorListener() {
+						public void runtimeFound(IRuntime runtime) {
+							monitor.subTask(runtime.getName());
+							list.add(runtime);
+						}
+					};
+					Iterator iterator = ServerCore.getRuntimeLocators().iterator();
+					while (iterator.hasNext()) {
+						IRuntimeLocator locator = (IRuntimeLocator) iterator.next();
+						locator.searchForRuntimes(listener, monitor);
+					}
+					Trace.trace(Trace.FINER, "Found runtimes: " + list.size());
+					
+					// remove duplicates from list (based on location)
+					Trace.trace(Trace.FINER, "Removing duplicates");
+					List good = new ArrayList();
+					Iterator iterator2 = list.iterator();
+					while (iterator2.hasNext()) {
+						boolean dup = false;
+						IRuntime wc = (IRuntime) iterator2.next();
+						
+						iterator = ServerCore.getResourceManager().getRuntimes().iterator();
+						while (iterator.hasNext()) {
+							IRuntime runtime = (IRuntime) iterator.next();
+							if (runtime.getLocation().equals(wc.getLocation()))
+								dup = true;
+						}
+						if (!dup)
+							good.add(wc);
+					}
+					
+					// add to list
+					Trace.trace(Trace.FINER, "Adding runtimes: " + good.size());
+					iterator = good.iterator();
+					while (iterator.hasNext()) {
+						IRuntimeWorkingCopy wc = (IRuntimeWorkingCopy) iterator.next();
+						wc.save(monitor);
+					}
+					dialog.close();
+				} catch (Exception ex) {
+					Trace.trace(Trace.SEVERE, "Error finding runtimes", ex);
+				}
+				runtimeComp.refresh();
+			}
+		});
+		
+		Dialog.applyDialogFont(composite);
+	
+		return composite;
+	}
+	
+	protected boolean shouldRemoveRuntime(IRuntime runtime) {
+		if (runtime == null)
+			return false;
+
+		// check for use
+		boolean inUse = false;
+	
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (runtime.equals(server.getRuntime()))
+				inUse = true;
+		}
+		
+		IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+		if (projects != null) {
+			int size = projects.length;
+			for (int i = 0; i < size; i++) {
+				IProjectProperties props = ServerCore.getProjectProperties(projects[i]);
+				if (runtime.equals(props.getRuntimeTarget()))
+					inUse = true;
+			}
+		}
+		
+		if (inUse) {
+			if (!MessageDialog.openConfirm(getShell(), ServerUIPlugin.getResource("%defaultDialogTitle"), ServerUIPlugin.getResource("%dialogRuntimeInUse")))
+				return false;
+		}
+		
+		return true;
+	}
+	
+	protected int showWizard(final IRuntimeWorkingCopy runtimeWorkingCopy) {
+		String title = null;
+		IWizardFragment fragment = null;
+		if (runtimeWorkingCopy == null) {
+			title = ServerUIPlugin.getResource("%wizNewRuntimeWizardTitle");
+			fragment = new WizardFragment() {
+				public void createSubFragments(List list) {
+					list.add(new NewRuntimeWizardFragment());
+					list.add(new FinishWizardFragment(new SaveRuntimeTask()));
+				}
+			};
+		} else {
+			title = ServerUIPlugin.getResource("%wizEditRuntimeWizardTitle");
+			final IWizardFragment fragment2 = ServerUICore.getWizardFragment(runtimeWorkingCopy.getRuntimeType().getId());
+			if (fragment2 == null) {
+				edit.setEnabled(false);
+				return Window.CANCEL;
+			}
+			fragment = new WizardFragment() {
+				public void createSubFragments(List list) {
+					list.add(new WizardFragment() {
+						public void enter() {
+							getTaskModel().putObject(ITaskModel.TASK_RUNTIME, runtimeWorkingCopy);
+						}
+					});
+					list.add(fragment2);
+					list.add(new FinishWizardFragment(new SaveRuntimeTask()));
+				}
+			};
+		}
+		TaskWizard wizard = new TaskWizard(title, fragment);
+		wizard.setForcePreviousAndNextButtons(true);
+		ClosableWizardDialog dialog = new ClosableWizardDialog(getShell(), wizard);
+		return dialog.open();
+	}
+	
+	protected IRuntime getSelection(ISelection sel2) {
+		IStructuredSelection sel = (IStructuredSelection) sel2;
+		return (IRuntime) sel.getFirstElement();
+	}
+	
+	/**
+	 * Initializes this preference page using the passed desktop.
+	 *
+	 * @param desktop the current desktop
+	 */
+	public void init(IWorkbench workbench) { }
+
+	/**
+	 * Performs special processing when this page's Defaults button has been pressed.
+	 * <p>
+	 * This is a framework hook method for sublcasses to do special things when
+	 * the Defaults button has been pressed.
+	 * Subclasses may override, but should call <code>super.performDefaults</code>.
+	 * </p>
+	 */
+	protected void performDefaults() {
+		super.performDefaults();
+	}
+
+	/** 
+	 * Method declared on IPreferencePage.
+	 * Subclasses should override
+	 */
+	public boolean performOk() {
+		// TODO - should not save until user hits ok 
+		return true;
+	}
+
+	/**
+	 * 
+	 */
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		if (visible)
+			setTitle(ServerUIPlugin.getResource("%preferenceRuntimesTitleLong"));
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/RuntimeTargetComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/RuntimeTargetComposite.java
new file mode 100644
index 0000000..c399954
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/RuntimeTargetComposite.java
@@ -0,0 +1,247 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IProjectModule;
+import org.eclipse.wst.server.ui.ServerUIUtil;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Dialog that prompts a user to change the target runtime.
+ */
+public class RuntimeTargetComposite {
+	public interface RuntimeSelectionListener {
+		public void runtimeSelected(IRuntime runtime);
+	}
+
+	protected IProject project;
+	protected IProjectProperties props;
+	protected IRuntime currentRuntime;
+	protected IRuntime newRuntime;
+	protected List targets;
+	protected String[] items;
+	protected RuntimeSelectionListener listener;
+	
+	protected List childProjects;
+	protected boolean setChildren = true;
+	protected int offset = 0;
+
+	/**
+	 * RuntimeTargetComposite constructor comment.
+	 * @param parent Composite
+	 * @param project IProject
+	 */
+	public RuntimeTargetComposite(Composite parent, IProject project) {
+		this.project = project;
+		props = ServerCore.getProjectProperties(project);
+		currentRuntime = props.getRuntimeTarget();
+		if (currentRuntime == null)
+			offset = 1;
+		
+		// get child modules
+		IProjectModule projectModule = ServerUtil.getModuleProject(project);
+		List children = new ArrayList();
+		IModule[] child = projectModule.getChildModules();
+		if (child != null) {
+			int size = child.length;
+			for (int i = 0; i < size; i++)
+				children.add(child[i]);
+			int a = 0;
+			while (a < children.size()) {
+				IModule module = (IModule) children.get(a);
+				IModule[] child2 = module.getChildModules();
+				if (child2 != null) {
+					size = child2.length;
+					for (int i = 0; i < size; i++)
+						children.add(child2[i]);
+				}
+				a++;
+			}
+		}
+		
+		childProjects = new ArrayList();
+		Iterator iterator = children.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			if (module instanceof IProjectModule)
+				childProjects.add(module);
+		}
+		
+		createContents(parent);
+	}
+	
+	/**
+	 * RuntimeTargetComposite constructor comment.
+	 * @param parentShell org.eclipse.swt.widgets.Shell
+	 * @param project IProject
+	 */
+	public RuntimeTargetComposite(Composite parent, IProject project, RuntimeSelectionListener listener) {
+		this(parent, project);
+		this.listener = listener;
+	}
+
+	/**
+	 * 
+	 */
+	protected void createContents(final Composite parent) {
+		Label label = new Label(parent, SWT.NONE);
+		label.setText(ServerUIPlugin.getResource("%runtimeTargetCombo"));
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		label.setLayoutData(data);
+		
+		final Combo combo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		combo.setLayoutData(data);
+		
+		int sel = updateRuntimes();
+		combo.setItems(items);
+		if (items.length == 0)
+			combo.setEnabled(false);
+		else {
+			combo.addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					int select = combo.getSelectionIndex();
+					if (offset > 0 && select == 0)
+						newRuntime = null;
+					else
+						newRuntime = (IRuntime) targets.get(select - offset);
+					if (listener != null)
+						listener.runtimeSelected(newRuntime);
+				}
+			});
+			if (sel >= 0) {
+				combo.select(sel);
+				if (offset == 0 || sel > 0)
+					newRuntime = (IRuntime) targets.get(sel - offset);
+			} else
+				combo.select(0);
+		}
+
+		final IProjectModule projectModule = ServerUtil.getModuleProject(project);
+		
+		Button button = SWTUtil.createButton(parent, ServerUIPlugin.getResource("%runtimeTargetNewRuntime"));
+		button.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				String currentRuntime2 = combo.getText();
+				String type = null;
+				String version = null;
+				if (projectModule != null) {
+					type = projectModule.getType();
+					version = projectModule.getVersion();
+				}
+				if (ServerUIUtil.showNewRuntimeWizard(parent.getShell(), type, version)) {
+					int sel2 = updateRuntimes();
+					combo.setItems(items);
+					combo.setText(currentRuntime2);
+					if (combo.getSelectionIndex() == -1)
+						combo.select(sel2);
+				}
+			}
+		});
+		
+		/*label = new Label(parent, SWT.NONE);
+		label.setText("");
+		
+		label = new Label(parent, SWT.WRAP);
+		label.setText(ServerUIPlugin.getResource("%runtimeTargetInformation"));
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 2;
+		label.setLayoutData(data);*/
+		
+		// child module selection
+		if (!childProjects.isEmpty()) {
+			final Button includeChildren = new Button(parent, SWT.CHECK);
+			includeChildren.setText(ServerUIPlugin.getResource("%runtimeTargetChildren"));
+			data = new GridData();
+			data.horizontalSpan = 3;
+			includeChildren.setLayoutData(data);
+			includeChildren.setSelection(true);
+			
+			includeChildren.addSelectionListener(new SelectionListener() {
+				public void widgetSelected(SelectionEvent e) {
+					setChildren = includeChildren.getSelection();
+				}
+
+				public void widgetDefaultSelected(SelectionEvent e) {
+					widgetSelected(e);
+				}
+			});
+		}
+	}
+	
+	protected int updateRuntimes() {
+		IProjectModule pm = ServerUtil.getModuleProject(project);
+		if (pm != null)
+			targets = ServerUtil.getRuntimes(pm.getType(), pm.getVersion());
+
+		items = new String[0];
+		int sel = -1;
+		if (targets != null) {
+			int size = targets.size();
+			items = new String[size + offset];
+			if (offset > 0) {
+				items[0] = ServerUIPlugin.getResource("%runtimeTargetNone");
+				sel = 0;
+			}
+			for (int i = 0; i < size; i++) {
+				IRuntime target = (IRuntime) targets.get(i);
+				items[i+offset] = target.getName();
+				if (target.equals(currentRuntime))
+					sel = i;
+			}
+		}
+		return sel;
+	}
+	
+	public IRuntime getSelectedRuntime() {
+		return newRuntime;
+	}
+	
+	public boolean hasChanged() {
+		if (!childProjects.isEmpty())
+			return true;
+		if (newRuntime == null)
+			return false;
+		if (newRuntime.equals(currentRuntime))
+			return false;
+		return true;
+	}
+	
+	public void apply(IProgressMonitor monitor) throws CoreException {
+		props.setRuntimeTarget(newRuntime, monitor);
+		
+		if (setChildren) {
+			Iterator iterator = childProjects.iterator();
+			while (iterator.hasNext()) {
+				IProjectModule module = (IProjectModule) iterator.next();
+				IProject proj = module.getProject();
+				props = ServerCore.getProjectProperties(proj);
+				props.setRuntimeTarget(newRuntime, monitor);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/SWTUtil.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/SWTUtil.java
new file mode 100644
index 0000000..eee8713
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/SWTUtil.java
@@ -0,0 +1,68 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+/**
+ * SWT Utility class.
+ */
+public class SWTUtil {
+	private static FontMetrics fontMetrics;
+
+	protected static void initializeDialogUnits(Control testControl) {
+		// Compute and store a font metric
+		GC gc = new GC(testControl);
+		gc.setFont(JFaceResources.getDialogFont());
+		fontMetrics = gc.getFontMetrics();
+		gc.dispose();
+	}
+
+	/**
+	 * Returns a width hint for a button control.
+	 */
+	protected static int getButtonWidthHint(Button button) {
+		int widthHint = Dialog.convertHorizontalDLUsToPixels(fontMetrics, IDialogConstants.BUTTON_WIDTH);
+		return Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
+	}
+
+	public static Button createButton(Composite comp, String label) {
+		Button b = new Button(comp, SWT.PUSH);
+		b.setText(label);
+		if (fontMetrics == null)
+			initializeDialogUnits(comp);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
+		data.widthHint = getButtonWidthHint(b);
+		data.heightHint = Dialog.convertVerticalDLUsToPixels(fontMetrics, IDialogConstants.BUTTON_HEIGHT);
+		b.setLayoutData(data);
+		return b;
+	}
+	
+	public static int convertHorizontalDLUsToPixels(Composite comp, int x) {
+		if (fontMetrics == null)
+			initializeDialogUnits(comp);
+		return Dialog.convertHorizontalDLUsToPixels(fontMetrics, x);
+	}
+	
+	public static int convertVerticalDLUsToPixels(Composite comp, int y) {
+		if (fontMetrics == null)
+			initializeDialogUnits(comp);
+		return Dialog.convertVerticalDLUsToPixels(fontMetrics, y);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerLabelProvider.java
new file mode 100644
index 0000000..2d5a515
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerLabelProvider.java
@@ -0,0 +1,178 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * A label provider for all server related objects.
+ */
+public class ServerLabelProvider implements ILabelProvider {
+	public ServerLabelProvider() { }
+
+	protected Image getModuleImage(String typeId) {
+		if (typeId == null)
+			return null;
+
+		Image image = ImageResource.getImage(typeId);
+		int ind = typeId.indexOf(".");
+		while (image == null && ind >= 0) {
+			typeId = typeId.substring(0, ind);
+			image = ImageResource.getImage(typeId);
+		}
+		return image;
+	}
+	
+	protected ImageDescriptor getModuleImageDescriptor(String typeId) {
+		if (typeId == null)
+			return null;
+		
+		ImageDescriptor image = ImageResource.getImageDescriptor(typeId);
+		int ind = typeId.indexOf(".");
+		while (image == null && ind >= 0) {
+			typeId = typeId.substring(0, ind);
+			image = ImageResource.getImageDescriptor(typeId);
+		}
+		return image;
+	}
+
+	/*
+	 * @see ILabelProvider#getImage(Object)
+	 */
+	public ImageDescriptor getImageDescriptor(Object element) {
+		try {
+			if (element instanceof IRuntimeType) {
+				IRuntimeType runtimeType = (IRuntimeType) element;
+				return ImageResource.getImageDescriptor(runtimeType.getId());
+			} else if (element instanceof IRuntime) {
+				IRuntime runtime = (IRuntime) element;
+				return ImageResource.getImageDescriptor(runtime.getRuntimeType().getId());
+			} else if (element instanceof IServerType) {
+				IServerType serverType = (IServerType) element;
+				return ImageResource.getImageDescriptor(serverType.getId());
+			} else if (element instanceof IServer) {
+				IServer server = (IServer) element;
+				return ImageResource.getImageDescriptor(server.getServerType().getId());
+			} else if (element instanceof IServerConfigurationType) {
+				IServerConfigurationType configType = (IServerConfigurationType) element;
+				return ImageResource.getImageDescriptor(configType.getId());
+			} else if (element instanceof IServerConfiguration) {
+				IServerConfiguration config = (IServerConfiguration) element;
+				return ImageResource.getImageDescriptor(config.getServerConfigurationType().getId());
+			} else if (element instanceof IModule) {
+				IModule module = (IModule) element;
+				return getModuleImageDescriptor(module.getType());
+			} else if (element instanceof IWorkbenchAdapter) {
+				return ((IWorkbenchAdapter) element).getImageDescriptor(null);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not get image descriptor", e);
+		}
+		return null;
+	}
+
+	/*
+	 * @see ILabelProvider#getImage(Object)
+	 */
+	public Image getImage(Object element) {
+		try {
+			if (element instanceof IRuntimeType) {
+				IRuntimeType runtimeType = (IRuntimeType) element;
+				return ImageResource.getImage(runtimeType.getId());
+			} else if (element instanceof IRuntime) {
+				IRuntime runtime = (IRuntime) element;
+				return ImageResource.getImage(runtime.getRuntimeType().getId());
+			} else if (element instanceof IServerType) {
+				IServerType serverType = (IServerType) element;
+				return ImageResource.getImage(serverType.getId());
+			} else if (element instanceof IServer) {
+				IServer server = (IServer) element;
+				if (server.getServerType() == null)
+					return null;
+				else
+					return ImageResource.getImage(server.getServerType().getId());
+			} else if (element instanceof IServerConfigurationType) {
+				IServerConfigurationType configType = (IServerConfigurationType) element;
+				return ImageResource.getImage(configType.getId());
+			} else if (element instanceof IServerConfiguration) {
+				IServerConfiguration config = (IServerConfiguration) element;
+				return ImageResource.getImage(config.getServerConfigurationType().getId());
+			} else if (element instanceof IModule) {
+				IModule module = (IModule) element;
+				return getModuleImage(module.getType());
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not get image descriptor", e);
+		}
+		return null;
+	}
+
+	protected String getString(String s) {
+		if (s == null)
+			return "";
+		else
+			return s;
+	}
+
+	/*
+	 * @see ILabelProvider#getText(Object)
+	 */
+	public String getText(Object element) {
+		if (element == null)
+			return "";
+
+		if (element instanceof IElement) {
+			return getString(((IElement) element).getName());
+		} else if (element instanceof IRuntimeType) {
+			return ((IRuntimeType) element).getName();
+		} else if (element instanceof IServerType) {
+			return ((IServerType) element).getName();
+		} else if (element instanceof IServerConfigurationType) {
+			return ((IServerConfigurationType) element).getName();
+		} else if (element instanceof IClient) {
+			return ((IClient) element).getName();
+		} else if (element instanceof IModule) {
+			return ((IModule) element).getName();
+		} else if (element instanceof IWorkbenchAdapter) {
+			return ((IWorkbenchAdapter) element).getLabel(null);
+		}
+
+		return "";
+	}
+
+	/*
+	 * @see IBaseLabelProvider#addListener(ILabelProviderListener)
+	 */
+	public void addListener(ILabelProviderListener listener) { }
+
+	/*
+	 * @see IBaseLabelProvider#isLabelProperty(Object, String)
+	 */
+	public boolean isLabelProperty(Object element, String property) {
+		return false;
+	}
+
+	/*
+	 * @see IBaseLabelProvider#removeListener(ILabelProviderListener)
+	 */
+	public void removeListener(ILabelProviderListener listener) { }
+	
+	/*
+	 * @see IBaseLabelProvider#dispose()
+	 */
+	public void dispose() { }
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerLaunchShortcut.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerLaunchShortcut.java
new file mode 100644
index 0000000..2aba961
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerLaunchShortcut.java
@@ -0,0 +1,69 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.List;
+
+import org.eclipse.debug.ui.ILaunchShortcut;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+
+import org.eclipse.wst.server.core.ServerUtil;
+import org.eclipse.wst.server.ui.internal.actions.RunOnServerActionDelegate;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+/**
+ *
+ */
+public class ServerLaunchShortcut implements ILaunchShortcut {
+	/* (non-Javadoc)
+	 * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.jface.viewers.ISelection, java.lang.String)
+	 */
+	public void launch(ISelection selection, final String mode) {
+		RunOnServerActionDelegate del = new RunOnServerActionDelegate() {
+			protected String getLaunchMode() {
+				return mode;
+			}
+		};
+		IAction action = new Action() { };
+		del.selectionChanged(action, selection);
+		del.run(action);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.ui.IEditorPart, java.lang.String)
+	 */
+	public void launch(IEditorPart editor, String mode) {
+		if (editor == null)
+			return;
+		
+		// check if the editor input itself can be run. Otherwise, check if
+		// the editor has a file input that can be run
+		IEditorInput input = editor.getEditorInput();
+		List list = ServerUtil.getModuleObjects(input);
+		if (!list.isEmpty()) {
+			launch(new StructuredSelection(input), mode);
+		} else if (input instanceof IFileEditorInput) {
+			IFileEditorInput fei = (IFileEditorInput) input;
+			ISelection sel = new StructuredSelection(fei.getFile());
+			launch(sel, mode);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.debug.ui.ILaunchFilter#testAttribute(org.eclipse.core.resources.IResource, java.lang.String, java.lang.String)
+	 */
+	/*public boolean testAttribute(IResource target, String name, String value) {
+		return true;
+	}*/
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerPreferencePage.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerPreferencePage.java
new file mode 100644
index 0000000..78cf660
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerPreferencePage.java
@@ -0,0 +1,403 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.wst.server.core.IPublishManager;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerPreferences;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.IServerUIPreferences;
+import org.eclipse.wst.server.ui.ServerUICore;
+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.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.help.WorkbenchHelp;
+
+/**
+ * The preference page that holds server properties.
+ */
+public class ServerPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+	protected Button publishDetailsButton;
+	protected Button publishBeforeStart;
+	protected Button autoRestart;
+
+	protected Combo publisherCombo;
+	protected Label publisherDescription;
+	protected String[] publisherIds;
+
+	protected Button promptIrreversible;
+	
+	protected byte saveEditors;
+	protected byte repairServers;
+	
+	protected Button saveNever;
+	protected Button savePrompt;
+	protected Button saveAuto;
+	
+	protected Button repairNever;
+	protected Button repairPrompt;
+	protected Button repairAlways;
+	
+	protected Button createInWorkspace;
+
+	protected IServerPreferences preferences;
+	protected IServerUIPreferences uiPreferences;
+
+	/**
+	 * ServerPreferencesPage constructor comment.
+	 */
+	public ServerPreferencePage() {
+		super();
+	
+		preferences = ServerCore.getServerPreferences();
+		uiPreferences = ServerUICore.getPreferences();
+	}
+	
+	/**
+	 * Create the preference options.
+	 *
+	 * @param parent org.eclipse.swt.widgets.Composite
+	 * @return org.eclipse.swt.widgets.Control
+	 */
+	protected Control createContents(Composite parent) {
+		initializeDialogUnits(parent);
+		
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(4);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 3;
+		composite.setLayout(layout);
+		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
+		composite.setLayoutData(data);
+		WorkbenchHelp.setHelp(composite, ContextIds.PREF_GENERAL);
+		
+		publishBeforeStart = new Button(composite, SWT.CHECK);
+		publishBeforeStart.setText(ServerUIPlugin.getResource("%prefPublishBeforeStarting"));
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 3;
+		publishBeforeStart.setLayoutData(data);
+		publishBeforeStart.setSelection(preferences.isAutoPublishing());
+		WorkbenchHelp.setHelp(publishBeforeStart, ContextIds.PREF_GENERAL_PUBLISH_BEFORE_START);
+		
+		publishDetailsButton = new Button(composite, SWT.CHECK);
+		publishDetailsButton.setText(ServerUIPlugin.getResource("%prefShowPublishingDetails"));
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 3;
+		publishDetailsButton.setLayoutData(data);
+		publishDetailsButton.setSelection(uiPreferences.getShowPublishingDetails());
+		WorkbenchHelp.setHelp(publishDetailsButton, ContextIds.PREF_GENERAL_SHOW_PUBLISHING_DETAILS);
+	
+		autoRestart = new Button(composite, SWT.CHECK);
+		autoRestart.setText(ServerUIPlugin.getResource("%prefAutoRestart"));
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 3;
+		autoRestart.setLayoutData(data);
+		autoRestart.setSelection(preferences.isAutoRestarting());
+		WorkbenchHelp.setHelp(autoRestart, ContextIds.PREF_GENERAL_AUTO_RESTART);
+		
+		promptIrreversible = new Button(composite, SWT.CHECK);
+		promptIrreversible.setText(ServerUIPlugin.getResource("%prefPromptIrreversible"));
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 3;
+		promptIrreversible.setLayoutData(data);
+		promptIrreversible.setSelection(uiPreferences.getPromptBeforeIrreversibleChange());
+		WorkbenchHelp.setHelp(promptIrreversible, ContextIds.PREF_GENERAL_PROMPT_IRREVERSIBLE);
+		
+		createInWorkspace = new Button(composite, SWT.CHECK);
+		createInWorkspace.setText(ServerUIPlugin.getResource("%prefCreateInWorkspace"));
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 3;
+		createInWorkspace.setLayoutData(data);
+		createInWorkspace.setSelection(preferences.isCreateResourcesInWorkspace());
+		WorkbenchHelp.setHelp(createInWorkspace, ContextIds.PREF_GENERAL_CREATE_IN_WORKSPACE);
+		
+		// save editors group
+		Group saveEditorGroup = new Group(composite, SWT.NONE);
+		saveEditorGroup.setText(ServerUIPlugin.getResource("%prefSaveEditorsGroup"));
+		
+		layout = new GridLayout();
+		layout.numColumns = 3;
+		saveEditorGroup.setLayout(layout);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.horizontalSpan = 3;
+		saveEditorGroup.setLayoutData(data);
+		
+		saveNever = new Button(saveEditorGroup, SWT.RADIO);
+		saveNever.setText(ServerUIPlugin.getResource("%prefSaveEditorsNever"));
+		saveNever.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				saveEditors = IServerUIPreferences.SAVE_EDITORS_NEVER;
+			}
+		});
+		WorkbenchHelp.setHelp(saveNever, ContextIds.PREF_GENERAL_SAVE_EDITORS);
+		
+		savePrompt = new Button(saveEditorGroup, SWT.RADIO);
+		savePrompt.setText(ServerUIPlugin.getResource("%prefSaveEditorsPrompt"));
+		savePrompt.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				saveEditors = IServerUIPreferences.SAVE_EDITORS_PROMPT;
+			}
+		});
+		WorkbenchHelp.setHelp(savePrompt, ContextIds.PREF_GENERAL_SAVE_EDITORS);
+		
+		saveAuto = new Button(saveEditorGroup, SWT.RADIO);
+		saveAuto.setText(ServerUIPlugin.getResource("%prefSaveEditorsAutosave"));
+		saveAuto.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				saveEditors = IServerUIPreferences.SAVE_EDITORS_AUTO;
+			}
+		});
+		WorkbenchHelp.setHelp(saveAuto, ContextIds.PREF_GENERAL_SAVE_EDITORS);
+		
+		setSaveEditorStatus(uiPreferences.getSaveEditors());
+		
+		// repair group
+		Group repairGroup = new Group(composite, SWT.NONE);
+		repairGroup.setText(ServerUIPlugin.getResource("%prefRepairModuleGroup"));
+
+		layout = new GridLayout();
+		layout.numColumns = 3;
+		repairGroup.setLayout(layout);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.horizontalSpan = 3;
+		repairGroup.setLayoutData(data);
+
+		repairNever = new Button(repairGroup, SWT.RADIO);
+		repairNever.setText(ServerUIPlugin.getResource("%prefRepairModuleNever"));
+		repairNever.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				repairServers = IServerPreferences.REPAIR_NEVER;
+			}
+		});
+		WorkbenchHelp.setHelp(repairNever, ContextIds.PREF_GENERAL_REPAIR);
+
+		repairPrompt = new Button(repairGroup, SWT.RADIO);
+		repairPrompt.setText(ServerUIPlugin.getResource("%prefRepairModulePrompt"));
+		repairPrompt.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				repairServers = IServerPreferences.REPAIR_PROMPT;
+			}
+		});
+		WorkbenchHelp.setHelp(repairPrompt, ContextIds.PREF_GENERAL_REPAIR);
+
+		repairAlways = new Button(repairGroup, SWT.RADIO);
+		repairAlways.setText(ServerUIPlugin.getResource("%prefRepairModuleAutomatic"));
+		repairAlways.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				repairServers = IServerPreferences.REPAIR_ALWAYS;
+			}
+		});
+		WorkbenchHelp.setHelp(repairAlways, ContextIds.PREF_GENERAL_REPAIR);
+		
+		setRepairStatus(preferences.getModuleRepairStatus());
+	
+		// publish combo
+		new Label(composite, SWT.NONE).setText(ServerUIPlugin.getResource("%prefPublisher"));
+		
+		publisherCombo = new Combo(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
+		data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
+		data.horizontalSpan = 2;
+		publisherCombo.setLayoutData(data);
+	
+		Map map = ServerCore.getPublishManagers();
+		String[] s = new String[map.size()];
+		publisherIds = new String[map.size()];
+		int i = 0;
+		Iterator iterator = map.keySet().iterator();
+		while (iterator.hasNext()) {
+			String id = (String) iterator.next();
+			IPublishManager publisher = (IPublishManager) map.get(id);
+			publisherIds[i] = id;
+			s[i++] = publisher.getName();
+		}
+		publisherCombo.setItems(s);
+		publisherCombo.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				handlePublisherSelection();
+			}
+		});
+		WorkbenchHelp.setHelp(publisherCombo, ContextIds.PREF_GENERAL_PUBLISHER);
+	
+		new Label(composite, SWT.NONE).setText("");
+	
+		publisherDescription = new Label(composite, SWT.WRAP);
+		publisherDescription.setText("");
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
+		data.widthHint = 200;
+		data.heightHint = 100;
+		data.horizontalSpan = 2;
+		publisherDescription.setLayoutData(data);
+	
+		selectPublisher(preferences.getPublishManager());
+		
+		Dialog.applyDialogFont(composite);
+	
+		return composite;
+	}
+	
+	/**
+	 * Return the publisher id at the given index.
+	 * 
+	 * @return java.lang.String
+	 * @param index int
+	 */
+	protected String getPublisherId(int index) {
+		if (index < 0 || index >= publisherIds.length)
+			return null;
+		return publisherIds[index];
+	}
+	
+	/**
+	 * Handle a publisher selection
+	 */
+	protected void handlePublisherSelection() {
+		try {
+			int sel = publisherCombo.getSelectionIndex();
+			String id = getPublisherId(sel);
+			IPublishManager publisher = (IPublishManager) ServerCore.getPublishManagers().get(id);
+			publisherDescription.setText(publisher.getDescription());
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error showing publisher description", e);
+			publisherDescription.setText("");
+		}
+	}
+	
+	protected void setSaveEditorStatus(byte status) {
+		saveEditors = status;
+		saveNever.setSelection(saveEditors == IServerUIPreferences.SAVE_EDITORS_NEVER);
+		savePrompt.setSelection(saveEditors == IServerUIPreferences.SAVE_EDITORS_PROMPT);
+		saveAuto.setSelection(saveEditors == IServerUIPreferences.SAVE_EDITORS_AUTO); 
+	}
+	
+	protected void setRepairStatus(byte status) {
+		repairServers = status;
+		repairNever.setSelection(repairServers == IServerPreferences.REPAIR_NEVER);
+		repairPrompt.setSelection(repairServers == IServerPreferences.REPAIR_PROMPT);
+		repairAlways.setSelection(repairServers == IServerPreferences.REPAIR_ALWAYS);
+	}
+	
+	/**
+	 * Initializes this preference page using the passed desktop.
+	 *
+	 * @param desktop the current desktop
+	 */
+	public void init(IWorkbench workbench) { }
+	
+	/**
+	 * Performs special processing when this page's Defaults button has been pressed.
+	 * <p>
+	 * This is a framework hook method for sublcasses to do special things when
+	 * the Defaults button has been pressed.
+	 * Subclasses may override, but should call <code>super.performDefaults</code>.
+	 * </p>
+	 */
+	protected void performDefaults() {
+		publishDetailsButton.setSelection(uiPreferences.getDefaultShowPublishingDetails());
+		autoRestart.setSelection(preferences.isDefaultAutoRestarting());
+		publishBeforeStart.setSelection(preferences.isDefaultAutoPublishing());
+		selectPublisher(preferences.getDefaultPublishManager());
+		promptIrreversible.setSelection(uiPreferences.getDefaultPromptBeforeIrreversibleChange());
+		createInWorkspace.setSelection(preferences.isDefaultCreateResourcesInWorkspace());
+		
+		setRepairStatus(preferences.getDefaultModuleRepairStatus());
+		setSaveEditorStatus(uiPreferences.getDefaultSaveEditors());
+	
+		super.performDefaults();
+	}
+
+	/**
+	 * Method declared on IPreferencePage.
+	 * Subclasses should override
+	 */
+	public boolean performOk() {
+		uiPreferences.setShowPublishingDetails(publishDetailsButton.getSelection());
+		preferences.setAutoPublishing(publishBeforeStart.getSelection());
+		preferences.setAutoRestarting(autoRestart.getSelection());
+		preferences.setModuleRepairStatus(repairServers);
+		uiPreferences.setSaveEditors(saveEditors);
+		uiPreferences.setPromptBeforeIrreversibleChange(promptIrreversible.getSelection());
+		preferences.setCreateResourcesInWorkspace(createInWorkspace.getSelection());
+	
+		int sel = publisherCombo.getSelectionIndex();
+		preferences.setPublishManager(getPublisherId(sel));
+	
+		// auto restart any servers that are ready for restart
+		if (autoRestart.getSelection())
+			autoRestartAll();
+	
+		return true;
+	}
+
+	/**
+	 * Select a publisher.
+	 * 
+	 * @param id java.lang.String
+	 */
+	protected void selectPublisher(String id) {
+		if (id == null || id.length() == 0)
+			return;
+
+		for (int i = 0; i < publisherIds.length; i++) {
+			if (id.equals(publisherIds[i])) {
+				publisherCombo.select(i);
+				IPublishManager publisher = (IPublishManager) ServerCore.getPublishManagers().get(id);
+				publisherDescription.setText(publisher.getDescription());
+				return;
+			}
+		}
+	}
+	
+	/**
+	 * Automatically restart any servers that require it.
+	 */
+	protected static void autoRestartAll() {
+		Trace.trace(Trace.FINEST, "Auto restarting all dirty servers");
+	
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (server.isRestartNeeded()) {
+				byte state = server.getServerState();
+				String mode = ILaunchManager.RUN_MODE;
+				if (state == IServer.SERVER_STARTED_DEBUG)
+					mode = ILaunchManager.DEBUG_MODE;
+				else if (state == IServer.SERVER_STARTED_PROFILE)
+					mode = ILaunchManager.PROFILE_MODE;
+				if (server.canRestart(mode))
+					try {
+						Trace.trace(Trace.FINEST, "Attempting to auto restart " + server.getName());
+						server.restart(mode);
+					} catch (Exception e) {
+						Trace.trace(Trace.SEVERE, "Error restarting: " + server, e);
+					}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerStartupListener.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerStartupListener.java
new file mode 100644
index 0000000..9afe7c2
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerStartupListener.java
@@ -0,0 +1,195 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.wst.server.core.IClient;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.ILaunchable;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IServerListener;
+import org.eclipse.wst.server.core.util.ServerAdapter;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * A class that listens to the startup of a server. To use
+ * it, just create an instance using one of the two constructors.
+ *
+ * This class will listen immediately for errors in the server
+ * startup. However, it will not display an error until it has
+ * been enabled. (setEnabled(true)) If you decide you want to
+ * cancel the startup listener, just call setEnabled(false),
+ * and the listener will be disposed of.
+ */
+public class ServerStartupListener {
+	protected IServer server;
+	protected Shell shell;
+	protected IServerListener listener;
+
+	protected IClient client;
+	protected ILaunchable launchable;
+	protected String launchMode;
+	protected IModule module;
+
+	// if true, ignores the first shutdown
+	protected boolean ignoreShutdown = false;
+
+	// if true, will output error messages
+	protected boolean isEnabled = false;
+
+	// if true, an error has occurred while this class was
+	// disabled
+	protected boolean isError = false;
+
+	/**
+	 * ServerStartupListener constructor comment.
+	 */
+	public ServerStartupListener(Shell shell, IServer server) {
+		super();
+		this.shell = shell;
+		this.server = server;
+	
+		listener = new ServerAdapter() {
+			public void serverStateChange(IServer server2) {
+				handleStateChange(server2.getServerState());
+			}
+		};
+		server.addServerListener(listener);
+	}
+
+	/**
+	 * ServerStartupListener constructor comment.
+	 */
+	public ServerStartupListener(Shell shell, IServer server, IClient client, ILaunchable launchable, String launchMode, IModule module) {
+		this(shell, server);
+		this.client = client;
+		this.launchable = launchable;
+		this.launchMode = launchMode;
+		this.module = module;
+	}
+
+	/**
+	 * ServerStartupListener constructor comment.
+	 */
+	public ServerStartupListener(Shell shell, IServer server, boolean ignoreShutdown) {
+		this(shell, server);
+		this.ignoreShutdown = ignoreShutdown;
+	}
+	
+	/**
+	 * Display the startup error notice.
+	 */
+	protected void displayError() {
+		// display error notice
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				String message = ServerUIPlugin.getResource("%errorServerStartFailed", server.getName());
+				MessageDialog.openError(shell, ServerUIPlugin.getResource("%errorDialogTitle"), message);
+			}
+		});
+	}
+
+	/**
+	 * Dispose of the listener and quit.
+	 */
+	protected void dispose() {
+		if (listener != null)
+			server.removeServerListener(listener);
+		listener = null;
+	}
+
+	/**
+	 * Handle a state change in the starting server.
+	 *
+	 * @param state byte
+	 */
+	protected void handleStateChange(byte state) {
+		switch (state) {
+			case IServer.SERVER_STARTED:
+			case IServer.SERVER_STARTED_DEBUG:
+			case IServer.SERVER_STARTED_PROFILE: {
+				dispose();
+				openClient();
+				break;
+			}
+			case IServer.SERVER_STOPPED:
+			case IServer.SERVER_STOPPING: {
+				if (!ignoreShutdown) {
+					dispose();
+					if (isEnabled)
+						displayError();
+					else
+						isError = true;
+				} else if (ignoreShutdown && state == IServer.SERVER_STOPPED) {
+					ignoreShutdown = false;
+				}
+				break;
+			}
+		}
+	}
+
+	/**
+	 * Open the client, if one exists.
+	 */
+	protected void openClient() {
+		if (client == null)
+			return;
+		
+		launchClientUtil(server, module, launchable, launchMode, client);
+	}
+
+	/**
+	 * Allows the startup listener to be enabled or disabled.
+	 *
+	 * @param enabled boolean
+	 */
+	public void setEnabled(boolean enabled) {
+		if (enabled) {
+			if (isError)
+				displayError();
+			else
+				isEnabled = true;
+		} else
+			dispose();
+	}
+	
+	public static void launchClientUtil(final IServer server, final IModule module, final ILaunchable launchable, final String launchMode, final IClient client) {
+		if (client == null || server == null)
+			return;
+	
+		// initial implementation - should just wait for a module state change event
+		if (server.getModuleState(module) == IServer.MODULE_STATE_STARTING) {
+			boolean started = false;
+			int count = 10;
+			while (!started && count > 0) {
+				try {
+					Thread.sleep(3000);
+				} catch (Exception e) { }
+				count --;
+				if (server.getModuleState(module) != IServer.MODULE_STATE_STARTING)
+					started = false;
+			}
+		}
+	
+		// display client on UI thread
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				Trace.trace("Attempting to load client: " + client);
+				try {
+					client.launch(server, launchable, launchMode, server.getExistingLaunch());
+				} catch (Exception e) {
+					Trace.trace("Server client failed", e);
+				}
+			}
+		});
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerTree.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerTree.java
new file mode 100644
index 0000000..36160a5
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerTree.java
@@ -0,0 +1,368 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.wst.server.core.IElement;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.actions.NewServerAction;
+import org.eclipse.wst.server.ui.internal.view.servers.DeleteAction;
+import org.eclipse.wst.server.ui.internal.view.servers.OpenAction;
+import org.eclipse.wst.server.ui.internal.view.servers.PublishAction;
+import org.eclipse.wst.server.ui.internal.view.servers.RestartAction;
+import org.eclipse.wst.server.ui.internal.view.servers.StartAction;
+import org.eclipse.wst.server.ui.internal.view.tree.ServerElementAdapter;
+import org.eclipse.wst.server.ui.internal.view.tree.ServerTreeAction;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * 
+ */
+public class ServerTree {
+	/**
+	 * Constants for actions
+	 */
+	public static final byte ACTION_OPEN = 0;
+	public static final byte ACTION_DELETE = 1;
+	public static final byte ACTION_BOOKMARK = 2;
+
+	private ServerTree() { }
+	
+	public static void fillContextMenu(Shell shell, ISelection selection, IMenuManager menu) {
+		MenuManager newMenu = new MenuManager(ServerUIPlugin.getResource("%actionNew"));
+		fillNewContextMenu(shell, selection, newMenu);
+		menu.add(newMenu);
+		fillOtherContextMenu(shell, selection, menu);
+	}
+	
+	public static void fillNewContextMenu(Shell shell, ISelection selection, IMenuManager menu) {
+		IAction newServerAction = new NewServerAction();
+		newServerAction.setText(ServerUIPlugin.getResource("%actionNewServer"));
+		menu.add(newServerAction);
+	}
+
+	public static void fillOtherContextMenu(Shell shell, ISelection selection, IMenuManager menu) {
+		if (selection == null)
+			return;
+
+		if (selection.isEmpty() || !(selection instanceof IStructuredSelection))
+			return;
+
+		//IStructuredSelection sel = (IStructuredSelection) selection;
+		
+		//boolean singleSelect = (sel.size() == 1);
+		//Object first = sel.getFirstElement();
+
+		// open menu
+		/*if (singleSelect && first instanceof ServerResourceAdapter) {
+			ServerResourceAdapter adapter = (ServerResourceAdapter) first;
+			IServerResource resource = adapter.getServerResource();
+			menu.add(new OpenAction(resource));
+			menu.add(new Separator());
+		}
+		
+		// delete menu
+		List list = new ArrayList();
+		boolean canDelete = true;
+		Iterator iterator2 = sel.iterator();
+		while (iterator2.hasNext()) {
+			Object obj = iterator2.next();
+			
+			if (obj instanceof ServerResourceAdapter)
+				list.add(((ServerResourceAdapter) obj).getServerResource());
+			else
+				canDelete = false;
+		}
+		if (canDelete) {
+			IServerResource[] res = new IServerResource[list.size()];
+			list.toArray(res);
+			menu.add(new DeleteAction(shell, res));
+		}
+
+		if (singleSelect && first instanceof IServerElementTag)
+			menu.add(new Separator());
+
+		if (singleSelect && first instanceof ServerResourceAdapter) {
+			ServerResourceAdapter adapter = (ServerResourceAdapter) first;
+			IServerResource resource = adapter.getServerResource();
+
+			IServer server = null;
+			if (resource instanceof IServer)
+				server = (IServer) resource;
+
+			// switch configuration menu
+			if (server != null) {
+				addServerActions(shell, menu, server);
+
+				MenuManager menuManager = new MenuManager(ServerUIPlugin.getResource("%actionSwitchConfiguration"));
+				menuManager.add(new SwitchConfigurationAction(shell, ServerUIPlugin.getResource("%viewNoConfiguration"), server, null));
+
+				List configs = ServerUtil.getSupportedServerConfigurations(server);
+				Iterator iterator = configs.iterator();
+				while (iterator.hasNext()) {
+					IServerConfiguration config = (IServerConfiguration) iterator.next();
+					menuManager.add(new SwitchConfigurationAction(shell, ServerUtil.getName(config), server, config));
+				}
+
+				menu.add(menuManager);
+			}
+			
+			if (server != null && server instanceof IModuleRestartable) {
+				menu.add(new Separator());
+
+				MenuManager restartProjectMenu = new MenuManager(ServerUIPlugin.getResource("%actionRestartProject"));
+
+				IModuleRestartable restartable = (IModuleRestartable) server;
+
+				IServerConfiguration configuration = ServerUtil.getServerConfiguration(server);
+				if (configuration != null) {
+					Iterator iterator = ServerUtil.getAllContainedModules(configuration).iterator();
+					while (iterator.hasNext()) {
+						IModule module = (IModule) iterator.next();
+						Action action = new RestartModuleAction(restartable, module);
+						restartProjectMenu.add(action);
+					}
+				}
+				if (restartProjectMenu.isEmpty())
+					menu.add(new DisabledMenuManager(ServerUIPlugin.getResource("%actionRestartProject")));
+				else
+					menu.add(restartProjectMenu);
+			}
+		}
+		if (singleSelect && first instanceof ModuleResourceAdapter) {
+			ModuleResourceAdapter adapter = (ModuleResourceAdapter) first;
+			IServerConfiguration configuration = adapter.getServerConfiguration();
+			IModule module = adapter.getModule();
+			
+			IModule[] modules = configuration.getModules();
+			boolean found = false;
+			if (modules != null && module != null) {
+				int size = modules.length;
+				for (int i = 0; i < size; i++) {
+					if (module.equals(modules[i]) && configuration.canRemoveModule(module))
+						found = true;
+				}
+			}
+	
+			if (found)
+				menu.add(new ModifyConfigurationModulesAction(shell, configuration, module, false));
+		}
+		
+		if (singleSelect && first instanceof ServerResourceAdapter) {
+			ServerResourceAdapter adapter = (ServerResourceAdapter) first;
+			IServerResource resource = adapter.getServerResource();
+
+			IServer server = null;
+			IServerConfiguration configuration = null;
+			if (resource instanceof IServerConfiguration)
+				configuration = (IServerConfiguration) resource;
+			else if (resource instanceof IServer) {
+				server = (IServer) resource;
+				configuration = ServerUtil.getServerConfiguration(server);
+			}
+			
+			ServerAction.addServerMenuItems(shell, menu, server, configuration);
+		}*/
+	}
+
+	protected static void addServerActions(Shell shell, IMenuManager menu, IServer server) {
+		final ISelection selection = new StructuredSelection(server);
+		ISelectionProvider provider = new ISelectionProvider() {
+			public void addSelectionChangedListener(ISelectionChangedListener listener) { }
+			public ISelection getSelection() {
+				return selection;
+			}
+			public void removeSelectionChangedListener(ISelectionChangedListener listener) { }
+			public void setSelection(ISelection sel) { }
+		};
+	
+		// create the debug action
+		Action debugAction = new StartAction(shell, provider, "debug", ILaunchManager.DEBUG_MODE);
+		debugAction.setToolTipText(ServerUIPlugin.getResource("%actionDebugToolTip"));
+		debugAction.setText(ServerUIPlugin.getResource("%actionDebug"));
+		debugAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_START_DEBUG));
+		debugAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_START_DEBUG));
+		debugAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_START_DEBUG));
+		menu.add(debugAction);
+	
+		// create the start action
+		Action runAction = new StartAction(shell, provider, "start", ILaunchManager.RUN_MODE);
+		runAction.setToolTipText(ServerUIPlugin.getResource("%actionStartToolTip"));
+		runAction.setText(ServerUIPlugin.getResource("%actionStart"));
+		runAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_START));
+		runAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_START));
+		runAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_START));
+		menu.add(runAction);
+		
+		// create the profile action
+		Action profileAction = new StartAction(shell, provider, "profile", ILaunchManager.PROFILE_MODE);
+		profileAction.setToolTipText(ServerUIPlugin.getResource("%actionProfileToolTip"));
+		profileAction.setText(ServerUIPlugin.getResource("%actionProfile"));
+		profileAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_START_PROFILE));
+		profileAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_START_PROFILE));
+		profileAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_START_PROFILE));
+		menu.add(profileAction);
+	
+		// create the restart action
+		MenuManager menuManager = new MenuManager(ServerUIPlugin.getResource("%actionRestart"));
+		
+		Action restartAction = new RestartAction(shell, provider, "restart", ILaunchManager.RUN_MODE);
+		restartAction.setToolTipText(ServerUIPlugin.getResource("%actionRestartToolTip"));
+		restartAction.setText(ServerUIPlugin.getResource("%actionRestart"));
+		restartAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_RESTART));
+		restartAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_RESTART));
+		restartAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_RESTART));
+		menuManager.add(restartAction);
+		//menu.add(restartAction);
+		menu.add(menuManager);
+
+		// create the stop action
+		/*Action stopAction = new StopAction(shell, provider, "stop", IServerFactory.SERVER_STATE_SET_MANAGED);
+		stopAction.setToolTipText(ServerUIPlugin.getResource("%actionStopToolTip"));
+		stopAction.setText(ServerUIPlugin.getResource("%actionStop"));
+		stopAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_STOP));
+		stopAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_STOP));
+		stopAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_STOP));
+		menu.add(stopAction);
+
+		// create the disconnect action
+		Action disconnectAction = new StopAction(shell, provider, "disconnect", IServerFactory.SERVER_STATE_SET_ATTACHED);
+		disconnectAction.setToolTipText(ServerUIPlugin.getResource("%actionStopToolTip2"));
+		disconnectAction.setText(ServerUIPlugin.getResource("%actionStop2"));
+		disconnectAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_DISCONNECT));
+		disconnectAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_DISCONNECT));
+		disconnectAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_DISCONNECT));
+		menu.add(disconnectAction);*/
+
+		// create the publish action
+		Action publishAction = new PublishAction(shell, provider, "publish");
+		publishAction.setToolTipText(ServerUIPlugin.getResource("%actionPublishToolTip"));
+		publishAction.setText(ServerUIPlugin.getResource("%actionPublish"));
+		publishAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_PUBLISH));
+		publishAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_PUBLISH));
+		publishAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_PUBLISH));
+		menu.add(publishAction);
+	}
+
+	public static boolean isActionEnabled(ISelection selection, byte action) {
+		if (selection == null || action < 0)
+			return false;
+
+		if (selection.isEmpty() || !(selection instanceof IStructuredSelection))
+			return false;
+
+		IStructuredSelection sel = (IStructuredSelection) selection;
+		
+		if (action == ACTION_OPEN) {
+			if (sel.size() != 1)
+				return false;
+
+			Object obj = sel.getFirstElement();
+
+			return (obj instanceof ServerElementAdapter);
+		} else if (action == ACTION_DELETE) {
+			if (sel.size() == 0)
+				return false;
+			
+			Iterator iterator = sel.iterator();
+			while (iterator.hasNext()) {
+				Object obj = iterator.next();
+				
+				if (!(obj instanceof ServerElementAdapter) && !(obj instanceof IServer))
+					return false;
+			}
+			return true;
+		}
+
+		return false;
+	}
+
+	public static boolean performAction(Shell shell, ISelection selection, byte action) {
+		//if (!isActionEnabled(selection, action))
+		//	return false;
+
+		if (selection == null || action < 0)
+			return false;
+
+		if (selection.isEmpty() || !(selection instanceof IStructuredSelection))
+			return false;
+
+		IStructuredSelection sel = (IStructuredSelection) selection;
+
+		if (action == ACTION_OPEN) {
+			if (sel.size() != 1)
+				return false;
+
+			Object obj = sel.getFirstElement();
+			if (obj instanceof IServer) {
+				Action open = new OpenAction((IServer) obj);
+				open.run();
+				return true;
+			} else if (obj instanceof ServerElementAdapter) {
+				ServerElementAdapter adapter = (ServerElementAdapter) obj;
+				IElement element = adapter.getServerResource();
+				if (element instanceof IServer) {
+					Action open = new OpenAction((IServer) element);
+					open.run();
+					return true;
+				}
+				return false;
+			}
+			return false;
+		} else if (action == ACTION_DELETE) {
+			if (sel.size() == 0)
+				return false;
+			
+			List list = new ArrayList();
+			Iterator iterator = sel.iterator();
+			while (iterator.hasNext()) {
+				Object obj = iterator.next();
+				
+				if (obj instanceof IElement)
+					list.add(obj);
+				else if (obj instanceof ServerElementAdapter)
+					list.add(((ServerElementAdapter) obj).getServerResource());
+			}
+			
+			IElement[] res = new IElement[list.size()];
+			list.toArray(res);
+			
+			Action delete = new DeleteAction(shell, res);
+			delete.run();
+			return true;
+		}
+
+		return false;
+	}
+	
+	/**
+	 * Returns an action of the specified type, which can be used for global
+	 */
+	public static IAction getAction(Shell shell, ISelectionProvider provider, byte action) {
+		if (action == ACTION_DELETE) {
+			return new ServerTreeAction(shell, provider, ServerUIPlugin.getResource("%actionDelete"), ServerTree.ACTION_DELETE);
+		}
+		return null;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerTreeContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerTreeContentProvider.java
new file mode 100644
index 0000000..19d14cf
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerTreeContentProvider.java
@@ -0,0 +1,447 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.wst.server.core.IElement;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.model.IModuleEvent;
+import org.eclipse.wst.server.core.model.IModuleEventsListener;
+import org.eclipse.wst.server.core.model.IModuleFactoryEvent;
+import org.eclipse.wst.server.core.model.IServerListener;
+import org.eclipse.wst.server.core.model.IServerResourceListener;
+import org.eclipse.wst.server.core.util.ServerAdapter;
+import org.eclipse.wst.server.core.util.ServerResourceAdapter;
+import org.eclipse.wst.server.ui.internal.view.tree.ConfigurationProxyResourceAdapter;
+import org.eclipse.wst.server.ui.internal.view.tree.ModuleResourceAdapter;
+import org.eclipse.wst.server.ui.internal.view.tree.ServerElementAdapter;
+import org.eclipse.wst.server.ui.internal.view.tree.TextResourceAdapter;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+/**
+ * Provides tree contents for objects that have the IWorkbenchAdapter
+ * adapter registered. 
+ */
+public class ServerTreeContentProvider implements ITreeContentProvider {
+	protected TreeViewer viewer;
+	
+	// listeners
+	protected IServerResourceListener listener;
+	protected IServerListener serverListener;
+	protected IResourceChangeListener resourceChangeListener;
+	protected IModuleEventsListener moduleEventsListener;
+
+	/**
+	 * 
+	 */
+	public ServerTreeContentProvider() {
+		// add listeners
+		addServerResourceListener();
+		addServerConfigurationListener();
+		addModuleEventsListener();
+	}
+
+	public Object[] getServerTreeRoots(Object parent) {
+		/*looseConfig = getLooseConfigurations();
+		if (looseConfig.length == 0)
+			return new Object[] { new TextResourceAdapter(parent, TextResourceAdapter.STYLE_SERVERS) };
+		else*/
+			return new Object[] { new TextResourceAdapter(parent, TextResourceAdapter.STYLE_SERVERS) };
+				//new TextResourceAdapter(parent, TextResourceAdapter.STYLE_LOOSE_CONFIGURATIONS) };
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on IContentProvider.
+	 */
+	public void dispose() {
+		// remove listeners
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			server.removeServerListener(serverListener);
+		}
+
+		ServerCore.getResourceManager().removeResourceListener(listener);
+		
+		if (moduleEventsListener != null)
+			ServerCore.getResourceManager().removeModuleEventsListener(moduleEventsListener);
+	}
+
+	/**
+	 * Returns the implementation of IWorkbenchAdapter for the given
+	 * object.  Returns null if the adapter is not defined or the
+	 * object is not adaptable.
+	 */
+	protected IWorkbenchAdapter getAdapter(Object o) {
+		if (!(o instanceof IAdaptable))
+			return null;
+
+		return (IWorkbenchAdapter)((IAdaptable)o).getAdapter(IWorkbenchAdapter.class);
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on ITreeContentProvider.
+	 */
+	public Object[] getChildren(Object element) {
+		if (element instanceof TextResourceAdapter) {
+			TextResourceAdapter adapter = (TextResourceAdapter) element;
+			Object[] children = adapter.getChildren(null);
+			if (children != null) {
+				int size = children.length;
+				for (int i = 0; i < size; i++) {
+					if (children[i] instanceof ServerElementAdapter) {
+						ServerElementAdapter adapter2 = (ServerElementAdapter) children[i];
+						adapter2.setFlags((byte) 1);
+					}
+				}
+			}
+			return children;
+		} else if (element instanceof ModuleResourceAdapter) {
+			ModuleResourceAdapter adapter = (ModuleResourceAdapter) element;
+			return adapter.getChildren(null);
+		} else if (element instanceof ServerElementAdapter) {
+			ServerElementAdapter adapter = (ServerElementAdapter) element;
+			return adapter.getChildren();
+		}
+		
+		IWorkbenchAdapter adapter = getAdapter(element);
+		if (adapter != null)
+		    return adapter.getChildren(element);
+
+		return new Object[0];
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on IStructuredContentProvider.
+	 */
+	public Object[] getElements(Object element) {
+		return getChildren(element);
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on ITreeContentProvider.
+	 */
+	public Object getParent(Object element) {
+		IWorkbenchAdapter adapter = getAdapter(element);
+		if (adapter != null)
+		    return adapter.getParent(element);
+
+		return null;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on ITreeContentProvider.
+	 */
+	public boolean hasChildren(Object element) {
+		return getChildren(element).length > 0;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on IContentProvider.
+	 */
+	public void inputChanged(Viewer newViewer, Object oldInput, Object newInput) {
+		if (newViewer instanceof TreeViewer)
+			this.viewer = (TreeViewer) newViewer;
+	}
+	
+	/**
+	 * Add listeners for resource changes.
+	 */
+	private void addServerConfigurationListener() {
+		// add a listener for configuration child module changes
+		serverListener = new ServerAdapter() {
+			public void modulesChanged(final IServer server) {
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						handleServerModulesChanged(server);
+					}
+				});
+			}
+		};
+
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			server.addServerListener(serverListener);
+		}
+	}
+	
+	/**
+	 * Add listeners for server resource changes.
+	 */
+	private void addServerResourceListener() {
+		// add a listener for resources being added or removed
+		listener = new ServerResourceAdapter() {
+			public void serverAdded(final IServer server) {
+				server.addServerListener(serverListener);
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						handleServerResourceAdded(server);
+					}
+				});
+			}
+			public void serverRemoved(final IServer server) {
+				server.removeServerListener(serverListener);
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						handleServerResourceRemoved(server);
+					}
+				});
+			}
+			public void serverChanged(final IServer server) {
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						handleServerResourceChanged(server);
+					}
+				});
+			}
+			public void serverConfigurationAdded(final IServerConfiguration configuration) {
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						handleServerResourceAdded(configuration);
+					}
+				});
+			}
+			public void serverConfigurationRemoved(final IServerConfiguration configuration) {
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						handleServerResourceRemoved(configuration);
+					}
+				});
+			}
+			public void serverConfigurationChanged(final IServerConfiguration configuration) {
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						handleServerResourceChanged(configuration);
+					}
+				});
+			}
+		};
+		ServerCore.getResourceManager().addResourceListener(listener);
+	}
+	
+	/**
+	 * Add listener to refresh when modules are added.
+	 */
+	private void addModuleEventsListener() {
+		moduleEventsListener = new IModuleEventsListener() {
+			public void moduleEvents(IModuleFactoryEvent[] factoryEvent, IModuleEvent[] event) {
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						if (viewer != null)
+							viewer.refresh(true);
+					}
+				});
+			}
+		};
+		
+		ServerCore.getResourceManager().addModuleEventsListener(moduleEventsListener);
+	}
+
+	/**
+	 * Updates an element in the tree.
+	 *
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void handleServerModulesChanged(IServer server2) {
+		if (viewer != null) {
+			viewer.refresh(new ServerElementAdapter(null, server2));
+			Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server = (IServer) iterator.next(); 
+				if (server2.equals(server)) {
+					viewer.refresh(new ServerElementAdapter(null, server));
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Handles the add of a new server resource.
+	 *
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void handleServerResourceAdded(IElement element) {
+		//Trace.trace("add: " + element);
+		if (viewer == null)
+			return;
+
+		ServerElementAdapter adapter = new ServerElementAdapter(null, element);
+		adapter.setFlags((byte) 1);
+		if (element instanceof IServer) {
+			viewer.add(new TextResourceAdapter(null, TextResourceAdapter.STYLE_SERVERS), adapter);
+		} else {
+			IServerConfiguration configuration = (IServerConfiguration) element;
+			//boolean used = false;
+
+			Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server = (IServer) iterator.next();
+				IServerConfiguration cfg = server.getServerConfiguration();
+				if (cfg != null && cfg.equals(configuration)) {
+					ServerElementAdapter adapter2 = new ServerElementAdapter(null, server);
+					adapter2.setFlags((byte) 1);
+					viewer.refresh(adapter2);
+					
+					//used = true;
+				}
+			}
+			
+			/*if (!used) {
+				ServerResourceAdapter adapter2 = new ServerResourceAdapter(null, configuration);
+				adapter2.setFlags((byte) 1);
+				viewer.add(new TextResourceAdapter(null, TextResourceAdapter.STYLE_LOOSE_CONFIGURATIONS), adapter2);
+			}*/
+		}
+	}
+
+	/**
+	 * Updates an element in the tree.
+	 *
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void handleServerResourceChanged(IElement element) {
+		//Trace.trace("change: " + element);
+		if (viewer == null)
+			return;
+
+		if (element instanceof IServer) {
+			IServer server = (IServer) element;
+			ServerElementAdapter adapter = new ServerElementAdapter(null, element);
+			adapter.setFlags((byte) 1);
+			viewer.refresh(adapter);
+			
+			IServerConfiguration cfg = server.getServerConfiguration();
+			if (cfg != null) {
+				ServerElementAdapter adapter3 = new ServerElementAdapter(null, cfg);
+				adapter3.setFlags((byte) 1);
+				viewer.remove(adapter3);
+			}
+		} else {
+			IServerConfiguration configuration = (IServerConfiguration) element;
+			
+			// refresh servers
+			Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server = (IServer) iterator.next();
+				IServerConfiguration cfg = server.getServerConfiguration();
+				if (cfg != null && cfg.equals(configuration)) {
+					ServerElementAdapter adapter2 = new ServerElementAdapter(null, server);
+					adapter2.setFlags((byte) 1);
+					viewer.refresh(adapter2);
+				}
+			}
+			//viewer.refresh(new TextResourceAdapter(null, TextResourceAdapter.STYLE_LOOSE_CONFIGURATIONS));
+		}
+	}
+
+	/**
+	 * Handles the removal of a server resource.
+	 *
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void handleServerResourceRemoved(IElement element) {
+		//Trace.trace("remove: " + element);
+		if (viewer == null)
+			return;
+		
+		TextResourceAdapter.deleted = element;
+		if (element instanceof IServerConfiguration)
+			ConfigurationProxyResourceAdapter.deleted = (IServerConfiguration) element;
+
+		if (element instanceof IServer) {
+			//IServer server = (IServer) element;
+			TextResourceAdapter adapter = new TextResourceAdapter(null, TextResourceAdapter.STYLE_SERVERS);
+			viewer.refresh(adapter);
+			/*IServerConfiguration configuration = Reference.getServerConfigurationByRef(server.getConfigurationRef());
+			
+			boolean used = false;
+			Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server2 = (IServer) iterator.next();
+				if (!server.equals(server2)) {
+					IServerConfiguration cfg = Reference.getServerConfigurationByRef(server2.getConfigurationRef());
+					if (cfg != null && cfg.equals(configuration)) {
+						used = true;
+					}
+				}
+			}
+			if (!used) {
+				ServerResourceAdapter adapter2 = new ServerResourceAdapter(null, configuration);
+				adapter2.setFlags((byte) 1);
+				viewer.add(new TextResourceAdapter(null, TextResourceAdapter.STYLE_LOOSE_CONFIGURATIONS), adapter2);
+			}*/
+		} else {
+			//TextResourceAdapter adapter = new TextResourceAdapter(null, TextResourceAdapter.STYLE_CONFIGURATIONS);
+			//viewer.refresh(adapter);
+	
+			/*Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server = (IServer) iterator.next();
+				ServerResourceAdapter adapter2 = new ServerResourceAdapter(null, server);
+				adapter2.setFlags((byte) 1);
+				viewer.refresh(adapter2);
+			}*/
+			IServerConfiguration configuration = (IServerConfiguration) element;
+			
+			// refresh servers
+			//boolean used = false;
+			Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server = (IServer) iterator.next();
+				IServerConfiguration cfg = server.getServerConfiguration();
+				if (cfg != null && cfg.equals(configuration)) {
+					ServerElementAdapter adapter2 = new ServerElementAdapter(null, server);
+					adapter2.setFlags((byte) 1);
+					viewer.refresh(adapter2);
+					
+					//used = true;
+				}
+			}
+			
+			/*if (!used) {
+				TextResourceAdapter adapter = new TextResourceAdapter(null, TextResourceAdapter.STYLE_LOOSE_CONFIGURATIONS);
+				viewer.refresh(adapter);
+			}*/
+		}
+		ConfigurationProxyResourceAdapter.deleted = null;
+		TextResourceAdapter.deleted = null;
+	}
+	
+	public static IServerConfiguration[] getLooseConfigurations() {
+		java.util.List configs = ServerCore.getResourceManager().getServerConfigurations();
+		
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (!server.equals(TextResourceAdapter.deleted)) {
+				IServerConfiguration cfg = server.getServerConfiguration();
+				if (cfg != null && configs.contains(cfg))
+					configs.remove(cfg);
+			}
+		}
+		
+		if (configs.contains(ConfigurationProxyResourceAdapter.deleted))
+			configs.remove(ConfigurationProxyResourceAdapter.deleted);
+		
+		IServerConfiguration[] config = new IServerConfiguration[configs.size()];
+		configs.toArray(config);
+		return config;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPlugin.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPlugin.java
new file mode 100644
index 0000000..c559156
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPlugin.java
@@ -0,0 +1,224 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.dialogs.IDialogConstants;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.model.IServerListener;
+import org.eclipse.wst.server.core.model.IStartableServer;
+import org.eclipse.wst.server.core.util.ServerAdapter;
+import org.eclipse.wst.server.ui.IServerUIPreferences;
+import org.eclipse.wst.server.ui.ServerUICore;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The server UI plugin class.
+ */
+public class ServerUIPlugin extends AbstractUIPlugin {
+	public static final byte START = 0;
+	public static final byte STOP = 1;
+	public static final byte RESTART = 2;
+	
+	// singleton instance of this class
+	private static ServerUIPlugin singleton;
+
+	protected Map imageDescriptors = new HashMap();
+
+	protected static List terminationWatches = new ArrayList();
+	
+	protected ModuleRepairSupport moduleRepairSupport;
+
+	/**
+	 * Create the ServerUIPlugin.
+	 */
+	public ServerUIPlugin() {
+		super();
+		singleton = this;
+	}
+
+	/**
+	 * Returns the singleton instance of this plugin.
+	 *
+	 * @return org.eclipse.wst.server.ui.internal.plugin.ServerUIPlugin
+	 */
+	public static ServerUIPlugin getInstance() {
+		return singleton;
+	}
+
+	/**
+	 * Returns the translated String found with the given key.
+	 *
+	 * @param key java.lang.String
+	 * @return java.lang.String
+	 */
+	public static String getResource(String key) {
+		try {
+			return Platform.getResourceString(getInstance().getBundle(), key);
+		} catch (Exception e) {
+			return key;
+		}
+	}
+
+	/**
+	 * Returns the translated String found with the given key,
+	 * and formatted with the given arguments using java.text.MessageFormat.
+	 *
+	 * @param key java.lang.String
+	 * @param arg java.lang.String
+	 * @return java.lang.String
+	 */
+	public static String getResource(String key, String arg) {
+		return getResource(key, new String[] {arg});
+	}
+
+	/**
+	 * Returns the translated String found with the given key,
+	 * and formatted with the given arguments using java.text.MessageFormat.
+	 *
+	 * @param key java.lang.String
+	 * @param arguments java.lang.Object[]
+	 * @return java.lang.String
+	 */
+	public static String getResource(String key, Object[] arguments) {
+		try {
+			String text = getResource(key);
+			return MessageFormat.format(text, arguments);
+		} catch (Exception e) {
+			return key;
+		}
+	}
+
+	/**
+	 * Convenience method for logging.
+	 *
+	 * @param status org.eclipse.core.runtime.IStatus
+	 */
+	public static void log(IStatus status) {
+		getInstance().getLog().log(status);
+	}
+
+	/**
+	 * Start up this plug-in.
+	 *
+	 * @throws Exception
+	 */
+	public void start(BundleContext context) throws Exception {
+		Trace.trace(Trace.CONFIG, "----->----- Server UI plugin start ----->-----");
+		super.start(context);
+	
+		moduleRepairSupport = new ModuleRepairSupport();
+		ServerCore.getResourceManager().addServerLifecycleEventHandler(1000, moduleRepairSupport);
+		
+		IServerUIPreferences prefs = ServerUICore.getPreferences();
+		((ServerUIPreferences) prefs).setDefaults();
+	}
+	
+	/**
+	 * Shuts down this plug-in and saves all plug-in state.
+	 *
+	 * @exception Exception
+	 */
+	public void stop(BundleContext context) throws Exception {
+		Trace.trace(Trace.CONFIG, "-----<----- Server UI plugin stop -----<-----");
+		super.stop(context);
+		
+		ServerCore.getResourceManager().removeServerLifecycleEventHandler(moduleRepairSupport);
+	
+		ImageResource.dispose();
+	}
+
+	/**
+	 * Adds a watch to this server. If it hasn't stopped in a
+	 * reasonable amount of time, the user will be prompted to
+	 * terminate the server.
+	 *
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public static void addTerminationWatch(final Shell shell, final IServer server, final int mode) {
+		if (terminationWatches.contains(server))
+			return;
+	
+		terminationWatches.add(server);
+	
+		class TerminateThread extends Thread {
+			public boolean alive = true;
+			public IServerListener listener;
+	
+			public void run() {
+				while (alive) {
+					final IStartableServer startable = (IStartableServer) server.getDelegate();
+					int delay = startable.getStartTimeout();
+					if (mode == 1)
+						delay = startable.getStopTimeout();
+					else if (mode == 2)
+						delay += startable.getStopTimeout();
+					try {
+						Thread.sleep(delay);
+					} catch (InterruptedException e) { }
+					
+					if (server.getServerState() == IServer.SERVER_STOPPED)
+						alive = false;
+	
+					if (alive) {
+						Display.getDefault().syncExec(new Runnable() {
+							public void run() {
+								TerminationDialog dialog = new TerminationDialog(shell, server.getName());
+								dialog.open();
+								if (dialog.getReturnCode() == IDialogConstants.OK_ID) {
+									// only try calling terminate once. Also, make sure that it didn't stop while
+									// the dialog was open
+									if (server.getServerState() != IServer.SERVER_STOPPED)
+										server.terminate();
+									alive = false;
+								}
+							}
+						});
+					}
+					if (!alive) {
+						if (listener != null)
+							server.removeServerListener(listener);
+						terminationWatches.remove(server);
+					}
+				}
+			}
+		}
+	
+		final TerminateThread t = new TerminateThread();
+		t.setDaemon(true);
+		t.setPriority(Thread.NORM_PRIORITY - 2);
+	
+		// add listener to stop the thread if/when the server stops
+		IServerListener listener = new ServerAdapter() {
+			public void serverStateChange(IServer server2) {
+				if (server2.getServerState() == IServer.SERVER_STOPPED && t != null)
+					t.alive = false;
+			}
+		};
+		t.listener = listener;
+		server.addServerListener(listener);
+	
+		t.start();
+	}
+}
\ 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
new file mode 100644
index 0000000..8597b8c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPreferences.java
@@ -0,0 +1,202 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.Preferences;
+
+import org.eclipse.wst.server.ui.IServerUIPreferences;
+/**
+ * Helper class that stores preference information for
+ * the server tools.
+ */
+public class ServerUIPreferences implements IServerUIPreferences {
+	private static final String PREF_PUBLISHING_DETAILS = "publishing-details";
+	private static final String PREF_PROMPT_IRREVERSIBLE = "prompt-irreversible";
+	private static final String PREF_IMPORT_LOCATION = "import-location";
+	private static final String PREF_SAVE_EDITORS = "save-editors";
+	private static final String PREF_HOST_NAMES = "host-names";
+	
+	private static final int MAX_HOSTNAMES = 10;
+
+	private Preferences preferences;
+
+	/**
+	 * ServerUIPreference constructor comment.
+	 */
+	public ServerUIPreferences() {
+		super();
+		preferences = ServerUIPlugin.getInstance().getPluginPreferences();
+	}
+
+	public void setDefaults() {
+		preferences.setDefault(PREF_PUBLISHING_DETAILS, getDefaultShowPublishingDetails());
+		preferences.setDefault(PREF_PROMPT_IRREVERSIBLE, getDefaultPromptBeforeIrreversibleChange());
+		//preferences.setDefault(PREF_SERVER_SHUTDOWN_DELAY, getDefaultServerShutdownDelay());
+		preferences.setDefault(PREF_SAVE_EDITORS, getDefaultSaveEditors());
+		preferences.setDefault(PREF_HOST_NAMES, "localhost");
+	}
+
+	/**
+	 * Returns whether the publishing details should be shown.
+	 *
+	 * @return boolean
+	 */
+	public boolean getShowPublishingDetails() {
+		return preferences.getBoolean(PREF_PUBLISHING_DETAILS);
+	}
+	
+	/**
+	 * Returns whether the publishing details should be shown.
+	 *
+	 * @return boolean
+	 */
+	public boolean getDefaultShowPublishingDetails() {
+		return false;
+	}
+	
+	/**
+	 * Returns whether the publishing details should be shown.
+	 *
+	 * @return boolean
+	 */
+	public void setShowPublishingDetails(boolean b) {
+		preferences.setValue(PREF_PUBLISHING_DETAILS, b);
+		ServerUIPlugin.getInstance().savePluginPreferences();
+	}
+	
+	/**
+	 * Returns whether the user should be prompted before making an
+	 * irreversible change in the editor.
+	 * 
+	 * @return boolean
+	 */
+	public boolean getPromptBeforeIrreversibleChange() {
+		return preferences.getBoolean(PREF_PROMPT_IRREVERSIBLE);
+	}
+
+	/**
+	 * Returns the default value of whether the user should be prompted
+	 * before making an irreversible change in the editor.
+	 *
+	 * @return boolean
+	 */
+	public boolean getDefaultPromptBeforeIrreversibleChange() {
+		return true;
+	}
+
+	/**
+	 * Sets whether the user should be prompted before making an
+	 * irreversible change in the editor.
+	 *
+	 * @return boolean
+	 */
+	public void setPromptBeforeIrreversibleChange(boolean b) {
+		preferences.setValue(PREF_PROMPT_IRREVERSIBLE, b);
+		ServerUIPlugin.getInstance().savePluginPreferences();
+	}
+	
+	/**
+	 * Returns the import location.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getImportLocation() {
+		return preferences.getString(PREF_IMPORT_LOCATION);
+	}
+	
+	/**
+	 * Sets the import location.
+	 *
+	 * @return java.lang.String
+	 */
+	public void setImportLocation(String s) {
+		preferences.setValue(PREF_IMPORT_LOCATION, s);
+		ServerUIPlugin.getInstance().savePluginPreferences();
+	}
+	
+	/**
+	 * Returns the default setting for saving editors before launching.
+	 * 
+	 * @return byte
+	 */
+	public byte getDefaultSaveEditors() {
+		return SAVE_EDITORS_PROMPT;
+	}
+
+	/**
+	 * Returns the setting for saving editors before launching.
+	 * 
+	 * @return byte
+	 */
+	public byte getSaveEditors() {
+		return (byte) preferences.getInt(PREF_SAVE_EDITORS);
+	}
+
+	/**
+	 * Sets the value for saving editors before launching.
+	 * 
+	 * @param byte
+	 */
+	public void setSaveEditors(byte b) {
+		preferences.setValue(PREF_SAVE_EDITORS, b);
+		ServerUIPlugin.getInstance().savePluginPreferences();
+	}
+
+	/**
+	 * Return the list of most recently used hostnames.
+	 * 
+	 * @return
+	 */
+	public List getHostnames() {
+		String s = preferences.getString(PREF_HOST_NAMES);
+		StringTokenizer st = new StringTokenizer(s, "|*|");
+		List list = new ArrayList();
+		while (st.hasMoreTokens()) {
+			list.add(st.nextToken());
+		}
+		return list;
+	}
+
+	/**
+	 * Add a new hostname to the most recently used list.
+	 *  
+	 * @param hostname
+	 */
+	public void addHostname(String hostname) {
+		List list = getHostnames();
+		
+		// remove duplicates
+		if (list.contains(hostname))
+			list.remove(hostname);
+		
+		// always add second (leave localhost first)
+		list.add(1, hostname);
+		
+		// remove least used hostname
+		if (list.size() > MAX_HOSTNAMES)
+			list.remove(list.size() - 1);
+		
+		StringBuffer sb = new StringBuffer();
+		Iterator iterator = list.iterator();
+		while (iterator.hasNext()) {
+			String s = (String) iterator.next();
+			sb.append(s);
+			sb.append("|*|");
+		}
+		preferences.setValue(PREF_HOST_NAMES, sb.toString());
+		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/TerminationDialog.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/TerminationDialog.java
new file mode 100644
index 0000000..481e9ec
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/TerminationDialog.java
@@ -0,0 +1,84 @@
+package org.eclipse.wst.server.ui.internal;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.help.WorkbenchHelp;
+/**
+ * Dialog that prompts a user to see if a server should
+ * be terminated.
+ */
+public class TerminationDialog extends Dialog {
+	protected String serverName;
+
+	/**
+	 * TerminationDialog constructor comment.
+	 * @param parentShell org.eclipse.swt.widgets.Shell
+	 * @
+	 */
+	protected TerminationDialog(Shell parentShell, String serverName) {
+		super(parentShell);
+		this.serverName = serverName;
+		setBlockOnOpen(true);
+	}
+
+	/**
+	 *
+	 */
+	protected void configureShell(Shell newShell) {
+		super.configureShell(newShell);
+		newShell.setText(ServerUIPlugin.getResource("%terminateServerDialogTitle"));
+	}
+
+	/**
+	 * Creates and returns the contents of the upper part 
+	 * of this dialog (above the button bar).
+	 * <p>
+	 * The <code>Dialog</code> implementation of this framework method
+	 * creates and returns a new <code>Composite</code> with
+	 * standard margins and spacing. Subclasses should override.
+	 * </p>
+	 *
+	 * @param the parent composite to contain the dialog area
+	 * @return the dialog area control
+	 */
+	protected Control createDialogArea(Composite parent) {
+		// create a composite with standard margins and spacing
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+		composite.setFont(parent.getFont());
+		WorkbenchHelp.setHelp(composite, ContextIds.TERMINATE_SERVER_DIALOG);
+	
+		Label label = new Label(composite, SWT.WRAP);
+		label.setText(ServerUIPlugin.getResource("%terminateServerDialogMessage", new String[] {serverName}));
+		GridData data = new GridData();
+		data.widthHint = 400;
+		label.setLayoutData(data);
+		
+		Dialog.applyDialogFont(composite);
+	
+		return composite;
+	}
+}
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..1c33b7d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Trace.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.internal;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.eclipse.wst.server.ui.ServerUICore;
+
+/**
+ * Helper class to route trace output.
+ */
+public class Trace {
+	public static byte CONFIG = 0;
+	public static byte INFO = 1;
+	public static byte WARNING = 2;
+	public static byte SEVERE = 3;
+	public static byte FINEST = 4;
+	public static byte FINER = 5;
+	
+	protected static int pluginLength = -1;
+	
+	private static final String[] levelNames = new String[] {
+		"CONFIG ", "INFO   ", "WARNING", "SEVERE ", "FINER  ", "FINEST "};
+	private static final String spacer = "                                   ";
+
+	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 s java.lang.String
+	 */
+	public static void trace(byte level, String s) {
+		trace(level, s, null);
+	}
+	
+	/**
+	 * Trace the given message and exception.
+	 *
+	 * @param s java.lang.String
+	 * @param t java.lang.Throwable
+	 */
+	public static void trace(byte level, String s, Throwable t) {
+		if (!ServerUIPlugin.getInstance().isDebugging())
+			return;
+
+		String pluginId = ServerUICore.PLUGIN_ID;
+		StringBuffer sb = new StringBuffer(pluginId);
+		if (pluginId.length() > pluginLength)
+			pluginLength = pluginId.length();
+		else if (pluginId.length() < pluginLength)
+			sb.append(spacer.substring(0, pluginLength - pluginId.length()));
+		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();
+	}
+
+	/**
+	 * Trace the given text.
+	 *
+	 * @param s java.lang.String
+	 */
+	public static void trace(String s) {
+		trace(s, null);
+	}
+	
+	/**
+	 * Trace the given message and exception.
+	 *
+	 * @param s java.lang.String
+	 * @param t java.lang.Throwable
+	 */
+	public static void trace(String s, Throwable t) {
+		trace(FINEST, s, t);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/AbstractServerActionDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/AbstractServerActionDelegate.java
new file mode 100644
index 0000000..c38383b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/AbstractServerActionDelegate.java
@@ -0,0 +1,87 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.internal.EclipseUtil;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IActionDelegate;
+
+/**
+ * 
+ */
+public abstract class AbstractServerActionDelegate implements IActionDelegate {
+	protected List servers;
+
+	/**
+	 * Return true if this server can currently be acted on.
+	 *
+	 * @return boolean
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public abstract boolean accept(IServer server);
+
+	/**
+	 * Perform action on this server.
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public abstract void perform(Shell shell, IServer server);
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+	 */
+	public void run(IAction action) {
+		Shell shell = EclipseUtil.getShell();
+		Iterator iterator = servers.iterator();
+		Object obj = iterator.next();
+		if (obj instanceof IServer) {
+			IServer server = (IServer) obj;
+			if (accept(server))
+				perform(shell, server);
+			selectionChanged(action, new StructuredSelection(servers));
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
+	 */
+	public void selectionChanged(IAction action, ISelection selection) {
+		servers = new ArrayList();
+		if (selection.isEmpty() || !(selection instanceof StructuredSelection)) {
+			action.setEnabled(false);
+			return;
+		}
+		
+		boolean enabled = false;
+		Iterator iterator = ((StructuredSelection) selection).iterator();
+		while (iterator.hasNext()) {
+			Object obj = iterator.next();
+			if (obj instanceof IServer) {
+				IServer server = (IServer) obj;
+				if (accept(server)) {
+					servers.add(server);
+					enabled = true;
+				}
+			} else {
+				action.setEnabled(false);
+				return;
+			}
+		}
+		action.setEnabled(enabled);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/AddRemoveModulesAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/AddRemoveModulesAction.java
new file mode 100644
index 0000000..67bb35e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/AddRemoveModulesAction.java
@@ -0,0 +1,77 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.MessageDialog;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.ServerUtil;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.ui.ServerUIUtil;
+import org.eclipse.wst.server.ui.actions.IServerAction;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.wizard.ClosableWizardDialog;
+import org.eclipse.wst.server.ui.internal.wizard.ModifyModulesWizard;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * 
+ */
+public class AddRemoveModulesAction implements IServerAction {
+	public boolean supports(IServer server, IServerConfiguration configuration) {
+		if (server == null)
+			return false;
+		return (!server.getServerType().hasServerConfiguration() || configuration != null);
+	}
+
+	public void run(Shell shell, IServer server, IServerConfiguration configuration) {
+		if (!ServerUIUtil.promptIfDirty(shell, server))
+			return;
+		
+		// check if there are any projects first
+		// get currently deployed modules
+		List deployed = new ArrayList();
+		List modules = new ArrayList();
+		IModule[] currentModules = server.getModules();
+		if (currentModules != null) {
+			int size = currentModules.length;
+			for (int i = 0; i < size; i++) {
+				deployed.add(currentModules[i]);
+			}
+		}
+
+		// get remaining modules
+		Iterator iterator = ServerUtil.getModules().iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			if (!deployed.contains(module)) {
+				IStatus status = server.canModifyModules(new IModule[] { module }, null);
+				if (status != null && status.isOK())
+					modules.add(module);
+			}
+		}
+		
+		if (deployed.isEmpty() && modules.isEmpty()) {
+			MessageDialog.openInformation(shell, ServerUIPlugin.getResource("%defaultDialogTitle"), ServerUIPlugin.getResource("%dialogAddRemoveModulesNone"));
+			return;
+		}
+
+		ModifyModulesWizard wizard = new ModifyModulesWizard(server);
+		ClosableWizardDialog dialog = new ClosableWizardDialog(shell, wizard);
+		dialog.open();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/DebugOnServerActionDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/DebugOnServerActionDelegate.java
new file mode 100644
index 0000000..3173948
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/DebugOnServerActionDelegate.java
@@ -0,0 +1,24 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.debug.core.ILaunchManager;
+/**
+ * 
+ */
+public class DebugOnServerActionDelegate extends RunOnServerActionDelegate {
+	/**
+	 * Returns the start mode that the server should use.
+	 */
+	protected String getLaunchMode() {
+		return ILaunchManager.DEBUG_MODE;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/DeleteActionDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/DeleteActionDelegate.java
new file mode 100644
index 0000000..68ebf95
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/DeleteActionDelegate.java
@@ -0,0 +1,88 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.wst.server.core.IElement;
+import org.eclipse.wst.server.ui.internal.view.servers.DeleteAction;
+import org.eclipse.wst.server.ui.internal.view.tree.ServerElementAdapter;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * 
+ */
+public class DeleteActionDelegate implements IWorkbenchWindowActionDelegate {
+	protected IElement[] resources;
+	protected Shell shell;
+
+	/**
+	 * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
+	 */
+	public void dispose() { }
+
+	/**
+	 * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(IWorkbenchWindow)
+	 */
+	public void init(IWorkbenchWindow window) {
+		if (window != null)
+			shell = window.getShell();
+	}
+
+	/**
+	 * @see org.eclipse.ui.IActionDelegate#run(IAction)
+	 */
+	public void run(IAction action) {
+		if (action != null && action.isEnabled() && resources != null)
+			return;
+		DeleteAction delete = new DeleteAction(shell, resources);
+		delete.run();
+	}
+
+	/**
+	 * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection)
+	 */
+	public void selectionChanged(IAction action, ISelection selection) {
+		resources = null;
+		if (selection == null || selection.isEmpty() || !(selection instanceof IStructuredSelection)) {
+			action.setEnabled(false);
+			return;
+		}
+
+		IStructuredSelection select = (IStructuredSelection) selection;
+		Iterator iterator = select.iterator();
+		
+		List list = new ArrayList();
+		
+		while (iterator.hasNext()) {
+			Object obj = iterator.next();
+			if (obj instanceof IElement) {
+				list.add(obj);
+			} else if (obj instanceof ServerElementAdapter) {
+				list.add(((ServerElementAdapter) obj).getServerResource());
+			} else {
+				action.setEnabled(false);
+				return;
+			}
+		}
+		
+		resources = new IElement[list.size()];
+		list.toArray(resources);
+		action.setEnabled(true);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/NewServerAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/NewServerAction.java
new file mode 100644
index 0000000..603c747
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/NewServerAction.java
@@ -0,0 +1,43 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.action.IAction;
+
+import org.eclipse.wst.server.ui.internal.wizard.ClosableWizardDialog;
+import org.eclipse.wst.server.ui.internal.wizard.NewServerWizard;
+/**
+ * Action to create a new server.
+ */
+public class NewServerAction extends NewWizardAction {
+	/**
+	 * NewServerAction constructor comment.
+	 */
+	public NewServerAction() {
+		super();
+	}
+
+	/**
+	 * Performs this action.
+	 * <p>
+	 * This method is called when the delegating action has been triggered.
+	 * Implement this method to do the actual work.
+	 * </p>
+	 *
+	 * @param action the action proxy that handles the presentation portion of the
+	 *   action
+	 */
+	public void run(IAction action) {
+		NewServerWizard wizard = new NewServerWizard();
+		wizard.init(workbench, selection);
+		ClosableWizardDialog dialog = new ClosableWizardDialog(workbench.getActiveWorkbenchWindow().getShell(), wizard);
+		dialog.open();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/NewServerProjectAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/NewServerProjectAction.java
new file mode 100644
index 0000000..f58b7a0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/NewServerProjectAction.java
@@ -0,0 +1,43 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.wst.server.ui.internal.wizard.NewServerProjectWizard;
+/**
+ * Action to create a new server project.
+ */
+public class NewServerProjectAction extends NewWizardAction {
+	/**
+	 * NewServerProjectAction constructor comment.
+	 */
+	public NewServerProjectAction() {
+		super();
+	}
+
+	/**
+	 * Performs this action.
+	 * <p>
+	 * This method is called when the delegating action has been triggered.
+	 * Implement this method to do the actual work.
+	 * </p>
+	 *
+	 * @param action the action proxy that handles the presentation portion of the
+	 *   action
+	 */
+	public void run(IAction action) {
+		NewServerProjectWizard wizard = new NewServerProjectWizard();
+		wizard.init(workbench, selection);
+		WizardDialog dialog = new WizardDialog(workbench.getActiveWorkbenchWindow().getShell(), wizard);
+		dialog.open();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/NewWizardAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/NewWizardAction.java
new file mode 100644
index 0000000..1c7da0f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/NewWizardAction.java
@@ -0,0 +1,64 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+/**
+ * Action to create a new server element through a wizard.
+ */
+public abstract class NewWizardAction implements IWorkbenchWindowActionDelegate {
+	protected IWorkbench workbench;
+	protected IStructuredSelection selection;
+
+	/**
+	 * NewWizardAction constructor comment.
+	 */
+	public NewWizardAction() {
+		super();
+	}
+
+	/**
+	 * Disposes this action delegate.  The implementor should unhook any references
+	 * to itself so that garbage collection can occur.
+	 */
+	public void dispose() {}
+
+	/**
+	 * Initializes this action delegate with the workbench window it will work in.
+	 *
+	 * @param window the window that provides the context for this delegate
+	 */
+	public void init(IWorkbenchWindow window) {
+		workbench = window.getWorkbench();
+	}
+
+	/**
+	 * Notifies this action delegate that the selection in the workbench has changed.
+	 * <p>
+	 * Implementers can use this opportunity to change the availability of the
+	 * action or to modify other presentation properties.
+	 * </p>
+	 *
+	 * @param action the action proxy that handles presentation portion of the action
+	 * @param selection the current selection in the workbench
+	 */
+	public void selectionChanged(IAction action, ISelection sel) {
+		if (sel instanceof IStructuredSelection)
+			selection = (IStructuredSelection) sel;
+		else
+			selection = null;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/ProfileOnServerActionDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/ProfileOnServerActionDelegate.java
new file mode 100644
index 0000000..583c790
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/ProfileOnServerActionDelegate.java
@@ -0,0 +1,24 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.debug.core.ILaunchManager;
+/**
+ * 
+ */
+public class ProfileOnServerActionDelegate extends RunOnServerActionDelegate {
+	/**
+	 * Returns the start mode that the server should use.
+	 */
+	protected String getLaunchMode() {
+		return ILaunchManager.PROFILE_MODE;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RestartProjectActionDelegate.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RestartProjectActionDelegate.java
new file mode 100644
index 0000000..5e6d36f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RestartProjectActionDelegate.java
@@ -0,0 +1,150 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ServerUtil;
+import org.eclipse.wst.server.core.model.IProjectModule;
+import org.eclipse.wst.server.core.model.IRestartableModule;
+import org.eclipse.wst.server.core.model.IServerDelegate;
+import org.eclipse.wst.server.ui.internal.EclipseUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IActionDelegate;
+
+/**
+ * Action delegate for restarting a project within a running
+ * server.
+ */
+public class RestartProjectActionDelegate implements IActionDelegate {
+	protected IProject project;
+
+	/**
+	 * RestartProjectAction constructor comment.
+	 */
+	public RestartProjectActionDelegate() {
+		super();
+	}
+	
+	/**
+	 * Performs this action.
+	 * <p>
+	 * This method is called when the delegating action has been triggered.
+	 * Implement this method to do the actual work.
+	 * </p>
+	 *
+	 * @param action the action proxy that handles the presentation portion of the
+	 *   action
+	 */
+	public void run(IAction action) {
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				Shell shell = EclipseUtil.getShell();
+				MessageDialog dialog = new MessageDialog(shell, ServerUIPlugin.getResource("%defaultDialogTitle"), null, ServerUIPlugin.getResource("%dialogRestartingProject", project.getName()), MessageDialog.INFORMATION, new String[0], 0);
+				dialog.setBlockOnOpen(false);
+				dialog.open();
+	
+				IProjectModule module = ServerUtil.getModuleProject(project);
+				if (module != null) {
+					IServer[] servers = ServerUtil.getServersByModule(module);
+					if (servers != null) {
+						int size2 = servers.length;
+						for (int j = 0; j < size2; j++) {
+							byte state = servers[j].getServerState();
+							IServerDelegate delegate = servers[j].getDelegate();
+							if ((state == IServer.SERVER_STARTED || state == IServer.SERVER_STARTED_DEBUG) &&
+								(delegate instanceof IRestartableModule)) {
+								IRestartableModule restartable = (IRestartableModule)delegate;
+								if (restartable.canRestartModule(module)) {
+									try {
+										restartable.restartModule(module, new NullProgressMonitor());
+									} catch (Exception e) {
+										Trace.trace("Error restarting project", e);
+									}
+								}
+							}
+						}
+					}
+				}
+				dialog.close();
+			}
+		});
+	}
+	
+	/**
+	 * Notifies this action delegate that the selection in the workbench has changed.
+	 * <p>
+	 * Implementers can use this opportunity to change the availability of the
+	 * action or to modify other presentation properties.
+	 * </p>
+	 *
+	 * @param action the action proxy that handles presentation portion of the action
+	 * @param selection the current selection in the workbench
+	 */
+	public void selectionChanged(IAction action, ISelection sel) {
+		if (sel.isEmpty() || !(sel instanceof IStructuredSelection)) {
+			action.setEnabled(false);
+			return;
+		}
+	
+		IStructuredSelection select = (IStructuredSelection) sel;
+		Iterator iterator = select.iterator();
+		Object selection = iterator.next();
+		if (iterator.hasNext() || selection == null) {
+			// more than one selection (should never happen)
+			action.setEnabled(false);
+			return;
+		}
+	
+		if (!(selection instanceof IProject)) {
+			action.setEnabled(false);
+			return;
+		}
+	
+		project = (IProject) selection;
+		if (!project.isOpen()) {
+			action.setEnabled(false);
+			return;
+		}
+	
+		IProjectModule module = ServerUtil.getModuleProject(project);
+		if (module != null) {
+			IServer[] servers = ServerUtil.getServersByModule(module);
+			if (servers != null) {
+				int size2 = servers.length;
+				for (int j = 0; j < size2; j++) {
+					byte state = servers[j].getServerState();
+					IServerDelegate delegate = servers[j].getDelegate();
+					if ((state == IServer.SERVER_STARTED || state == IServer.SERVER_STARTED_DEBUG) &&
+						(delegate instanceof IRestartableModule)) {
+						IRestartableModule restartable = (IRestartableModule)delegate;
+						if (restartable.canRestartModule(module)) {
+							action.setEnabled(true);
+							return;
+						}
+					}
+				}
+			}
+		}
+
+		action.setEnabled(false);
+	}
+}
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
new file mode 100644
index 0000000..1ce1b8f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/RunOnServerActionDelegate.java
@@ -0,0 +1,535 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+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.*;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.*;
+import org.eclipse.wst.server.ui.ServerUIUtil;
+import org.eclipse.wst.server.ui.internal.*;
+import org.eclipse.wst.server.ui.internal.wizard.*;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * Support for starting/stopping server and clients for resources running on a server.
+ */
+public class RunOnServerActionDelegate implements IWorkbenchWindowActionDelegate {
+	protected static final String[] launchModes = {
+		ILaunchManager.RUN_MODE, ILaunchManager.DEBUG_MODE, ILaunchManager.PROFILE_MODE };
+
+	protected Object selection;
+
+	protected IWorkbenchWindow window;
+	
+	protected static boolean initialized = false;
+	
+	protected static Object globalSelection;
+
+	protected static Map globalLaunchMode;
+
+	private static transient List propertyListeners;
+
+	/**
+	 * RunOnServerActionDelegate constructor comment.
+	 */
+	public RunOnServerActionDelegate() {
+		super();
+	}
+
+	/**
+	 * Disposes this action delegate.  The implementor should unhook any references
+	 * to itself so that garbage collection can occur.
+	 */
+	public void dispose() {
+		window = null;
+	}
+
+	/**
+	 * Initializes this action delegate with the workbench window it will work in.
+	 *
+	 * @param window the window that provides the context for this delegate
+	 */
+	public void init(IWorkbenchWindow newWindow) {
+		window = newWindow;
+	}
+	
+	/**
+	 * Add a property change listener to this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public static void addPropertyChangeListener(PropertyChangeListener listener) {
+		if (propertyListeners == null)
+			propertyListeners = new ArrayList();
+		propertyListeners.add(listener);
+	}
+	
+	/**
+	 * Remove a property change listener from this server.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public static void removePropertyChangeListener(PropertyChangeListener listener) {
+		if (propertyListeners != null)
+			propertyListeners.remove(listener);
+	}
+	
+	/**
+	 * Fire a property change event.
+	 */
+	protected void firePropertyChangeEvent(String propertyName, Object oldValue, Object newValue) {
+		if (propertyListeners == null)
+			return;
+	
+		PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
+		try {
+			Iterator iterator = propertyListeners.iterator();
+			while (iterator.hasNext()) {
+				try {
+					PropertyChangeListener listener = (PropertyChangeListener) iterator.next();
+					listener.propertyChange(event);
+				} catch (Exception e) {
+					Trace.trace("Error firing property change event", e);
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace("Error in property event", e);
+		}
+	}
+
+	/**
+	 * Run the resource on a server.
+	 *
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 */
+	protected void run(IProgressMonitor monitor) {
+		String launchMode = getLaunchMode();
+		firePropertyChangeEvent("launchMode", null, launchMode);
+
+		List moduleObjects = ServerUtil.getModuleObjects(selection);
+		
+		Shell shell;
+		if (window != null)
+			shell = window.getShell();
+		else
+			shell = ServerUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+
+		if (moduleObjects == null || moduleObjects.isEmpty()) {
+			EclipseUtil.openError(ServerUIPlugin.getResource("%errorNoModules"));
+			Trace.trace(Trace.FINEST, "No modules");
+			return;
+		}
+		IModule module = ((IModuleObject) moduleObjects.get(0)).getModule();
+		if (moduleObjects.size() > 1) {
+			// check if the modules are all in the same module
+			int size = moduleObjects.size();
+			for (int i = 0; i < size; i++) {
+				IModule module2 = ((IModuleObject) moduleObjects.get(i)).getModule();
+				if (!module.equals(module2)) {
+					EclipseUtil.openError("Too many module objects");
+					Trace.trace(Trace.SEVERE, "Too many module objects! Unsupported!");
+					return;
+				}
+			}
+		}
+
+		// check for servers with the given start mode
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		boolean found = false;
+		while (!found && iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (ServerUtil.isCompatibleWithLaunchMode(server, launchMode)) {
+				try {
+					List parents = server.getParentModules(module);
+					if (parents != null && parents.size() > 0)
+						found = true;
+				} catch (Exception e) { }
+			}
+		}
+
+		if (!found) {
+			// no existing server supports the project and start mode!
+			// check if there might be another one that can be created
+			iterator = ServerCore.getServerTypes().iterator();
+			boolean found2 = false;
+			while (!found2 && iterator.hasNext()) {
+				IServerType type = (IServerType) iterator.next();
+				List moduleTypes = type.getRuntimeType().getModuleTypes();
+				if (type.supportsLaunchMode(launchMode) && ServerUtil.isSupportedModule(moduleTypes, module.getType(), module.getVersion())) {
+					found2 = true;
+				}
+			}
+			if (!found2) {
+				EclipseUtil.openError(ServerUIPlugin.getResource("%errorNoServer"));
+				Trace.trace(Trace.FINEST, "No server for start mode");
+				return;
+			}
+		}
+		
+		if (!ServerUIUtil.saveEditors())
+			return;
+
+		IServer server = null;
+		if (module instanceof IProjectModule) {
+			IProjectModule dp = (IProjectModule) module;
+			server = ServerCore.getProjectProperties(dp.getProject()).getDefaultServer();
+		}
+		
+		// ignore preference if the server doesn't support this mode.
+		if (server != null && !ServerUtil.isCompatibleWithLaunchMode(server, launchMode))
+			server = null;
+
+		boolean tasksRun = false;	
+		if (server == null) {
+			// try the full wizard
+			SelectServerWizard wizard = new SelectServerWizard(module, launchMode);
+			ClosableWizardDialog dialog = new ClosableWizardDialog(shell, wizard);
+			if (dialog.open() == Window.CANCEL) {
+				return;
+			}
+
+			server = wizard.getServer();
+			boolean preferred = wizard.isPreferredServer();
+			tasksRun = true;
+
+			// set preferred server if requested
+			if (server != null && preferred && module instanceof IProjectModule) {
+				try {
+					IProjectModule dp = (IProjectModule) module;
+					ServerCore.getProjectProperties(dp.getProject()).setDefaultServer(server, new NullProgressMonitor());
+				} catch (CoreException ce) {
+					String message = ServerUIPlugin.getResource("%errorCouldNotSavePreference");
+					ErrorDialog.openError(shell, ServerUIPlugin.getResource("%errorDialogTitle"), message, ce.getStatus());
+				}
+			}
+		}
+		Trace.trace(Trace.FINEST, "Server: " + server);
+		
+		if (server == null) {
+			EclipseUtil.openError(ServerUIPlugin.getResource("%errorNoServer"));
+			Trace.trace(Trace.SEVERE, "No server found");
+			return;
+		}
+
+		if (!ServerUIUtil.promptIfDirty(shell, server))
+			return;
+		
+		if (!tasksRun) {
+			SelectTasksWizard wizard = getTasksWizard(server, module);
+			if (wizard.hasTasks() && wizard.hasOptionalTasks()) {
+				WizardDialog dialog = new WizardDialog(shell, wizard);
+				if (dialog.open() == Window.CANCEL)
+					return;
+			} else
+				wizard.performFinish();
+		}
+
+		ILaunchable launchable = ServerUtil.getLaunchable(server, moduleObjects);
+		List list = new ArrayList();
+		if (launchable != null)
+			list = ServerUtil.getLaunchableClients(server, launchable, launchMode);
+
+		Trace.trace(Trace.FINEST, "Launchable clients: " + list);
+
+		IClient client = null;
+		if (list == null || list.isEmpty()) {
+			EclipseUtil.openError(ServerUIPlugin.getResource("%errorNoClient"));
+			Trace.trace(Trace.SEVERE, "No launchable clients!");
+			return;
+		} else if (list.size() == 1) {
+			client = (IClient) list.get(0);
+		} else {
+			SelectClientWizard wizard = new SelectClientWizard(list);
+			ClosableWizardDialog dialog = new ClosableWizardDialog(shell, wizard);
+			dialog.open();
+			client = wizard.getSelectedClient();
+			if (client == null)
+				return;
+		}
+
+		Trace.trace(Trace.FINEST, "Ready to launch");
+
+		final IServerPreferences preferences = ServerCore.getServerPreferences();
+
+		// start server if it's not already started
+		// and cue the client to start
+		byte state = server.getServerState();
+		if (state == IServer.SERVER_STARTING) {
+			ServerStartupListener listener = new ServerStartupListener(shell, server, client, launchable, launchMode, module);
+			listener.setEnabled(true);
+		} else if (state == IServer.SERVER_STARTED || state == IServer.SERVER_STARTED_DEBUG || state == IServer.SERVER_STARTED_PROFILE) {
+			boolean restart = false;
+			if (state != IServer.SERVER_STARTED_DEBUG && ILaunchManager.DEBUG_MODE.equals(launchMode)) {
+				int result = openWarningDialog(shell, ServerUIPlugin.getResource("%dialogModeWarningDebug"));
+				if (result == 1) {
+					if (state == IServer.SERVER_STARTED)
+						launchMode = ILaunchManager.RUN_MODE;
+					else
+						launchMode = ILaunchManager.PROFILE_MODE;
+				} else if (result == 0)
+					restart = true;
+				else
+					return;
+			} else if (state != IServer.SERVER_STARTED_PROFILE && ILaunchManager.PROFILE_MODE.equals(launchMode)) {
+				int result = openWarningDialog(shell, ServerUIPlugin.getResource("%dialogModeWarningProfile"));
+				if (result == 1) {
+					if (state == IServer.SERVER_STARTED)
+						launchMode = ILaunchManager.RUN_MODE;
+					else
+						launchMode = ILaunchManager.DEBUG_MODE;
+				} else if (result == 0)
+					restart = true;
+				else
+					return;
+			}
+			if (restart) {
+				server.synchronousStop();
+			
+				ServerStartupListener listener = new ServerStartupListener(shell, server, client, launchable, launchMode, module);
+				if (preferences.isAutoPublishing() && !autoPublish(server))
+					return;
+
+				try {
+					EclipseUtil.startServer(shell, server, launchMode, listener);
+				} catch (CoreException e) { }
+			} else {
+				if (preferences.isAutoPublishing() && !autoPublish(server))
+					return;
+	
+				// open client
+				ServerStartupListener.launchClientUtil(server, module, launchable, launchMode, client);
+			}
+		} else if (state != IServer.SERVER_STOPPING) {
+			ServerStartupListener listener = new ServerStartupListener(shell, server, client, launchable, launchMode, module);
+			if (preferences.isAutoPublishing() && !autoPublish(server))
+				return;
+
+			try {
+				EclipseUtil.startServer(shell, server, launchMode, listener);
+			} catch (CoreException e) { }
+		}
+	}
+	
+	private SelectTasksWizard getTasksWizard(IServer server, IModule module) {
+		// ---- temp
+		class Helper {
+			List parentList = new ArrayList();
+			List moduleList = new ArrayList();
+		}
+		final Helper help = new Helper();
+		ServerUtil.visit(server, new IModuleVisitor() {
+			public boolean visit(List parents, IModule module2) {
+				help.parentList.add(parents);
+				help.moduleList.add(module2);
+				return true;
+			}
+		});
+		if (!help.moduleList.contains(module)) {
+			help.parentList.add(new ArrayList()); // FIX-ME
+			help.moduleList.add(module);
+		}
+		int size = help.parentList.size();
+		List[] parents = new List[size];
+		help.parentList.toArray(parents);
+		IModule[] modules = new IModule[size];
+		help.moduleList.toArray(modules);
+		// ---- temp
+	
+		return new SelectTasksWizard(server, server.getServerConfiguration(), parents, modules);
+	}
+
+	/**
+	 * Automatically publish to the given server.
+	 *
+	 * @param server
+	 * @return boolean - false if the current operation should be stopped
+	 */
+	protected boolean autoPublish(IServer server) {
+		// publish first
+		if (server.shouldPublish()) {
+			IStatus publishStatus = ServerUIUtil.publishWithDialog(server, false);
+	
+			if (publishStatus == null || publishStatus.getSeverity() == IStatus.ERROR)
+				return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Open a message dialog.
+	 * 
+	 * @param shell
+	 * @param message
+	 * @return
+	 */
+	protected int openWarningDialog(Shell shell, String message) {
+		MessageDialog dialog = new MessageDialog(shell, ServerUIPlugin.getResource("%errorDialogTitle"), null,
+			message,	MessageDialog.WARNING, new String[] {ServerUIPlugin.getResource("%dialogModeWarningRestart"),
+			ServerUIPlugin.getResource("%dialogModeWarningContinue"), IDialogConstants.CANCEL_LABEL}, 0);
+		return dialog.open();
+	}
+
+	/**
+	 * The delegating action has been performed. Implement
+	 * this method to do the actual work.
+	 *
+	 * @param action action proxy that handles the presentation
+	 * portion of the plugin action
+	 */
+	public void run(IAction action) {
+		Trace.trace(Trace.FINEST, "Running on Server...");
+		if (!initialized) {
+			initialized = true;
+			
+			Iterator iterator = ServerCore.getModuleFactories().iterator();
+			while (iterator.hasNext()) {
+				IModuleFactory factory = (IModuleFactory) iterator.next();
+				factory.getModules();
+			}
+			
+			try {
+				IModule module = ServerUtil.getModule(globalSelection, true);
+				findGlobalLaunchModes(module);
+				action.setEnabled(isEnabled());
+			} catch (Exception e) { }
+			if (!isEnabled()) {
+				EclipseUtil.openError(ServerUIPlugin.getResource("%errorNoServer"));
+				Trace.trace(Trace.FINEST, "Uninitialized");
+				return;
+			}
+		}
+
+		try {
+			run(new NullProgressMonitor());
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Run on Server Error", e);
+		}
+	}
+	
+	protected boolean isEnabled() {
+		try {
+			Boolean b = (Boolean) globalLaunchMode.get(getLaunchMode());
+			return b.booleanValue();
+		} catch (Exception e) { }
+		return false;
+	}
+
+	/**
+	 * Returns the start mode that the server should use.
+	 */
+	protected String getLaunchMode() {
+		return ILaunchManager.RUN_MODE;
+	}
+
+	/**
+	 * Determine which clients can act on the current selection.
+	 *
+	 * @param action action proxy that handles presentation
+	 * portion of the plugin action
+	 * @param selection current selection in the desktop
+	 */
+	public void selectionChanged(IAction action, ISelection sel) {
+		Trace.trace(Trace.FINEST, "> selectionChanged");
+		selection = null;
+		long time = System.currentTimeMillis();
+		if (sel == null || sel.isEmpty() || !(sel instanceof IStructuredSelection)) {
+			action.setEnabled(false);
+			globalSelection = null;
+			return;
+		}
+
+		IStructuredSelection select = (IStructuredSelection) sel;
+		Iterator iterator = select.iterator();
+		selection = iterator.next();
+		if (iterator.hasNext()) { // more than one selection (should never happen)
+			action.setEnabled(false);
+			selection = null;
+			globalSelection = null;
+			return;
+		}
+
+		if (selection != globalSelection || !initialized) {
+			Trace.trace(Trace.FINEST, "Selection: " + selection);
+			if (selection != null)	
+				Trace.trace(Trace.FINEST, "Selection type: " + selection.getClass().getName());
+			globalSelection = selection;
+			globalLaunchMode = new HashMap();
+			try {
+				Trace.trace(Trace.FINEST, "calling getModule() " + initialized);
+				IModule module = ServerUtil.getModule(globalSelection, initialized);
+				Trace.trace(Trace.FINEST, "module: " + module);
+				findGlobalLaunchModes(module);
+			} catch (Exception e) {
+				Trace.trace(Trace.FINEST, "not initialized");
+				globalLaunchMode.put(ILaunchManager.RUN_MODE, new Boolean(true));
+				globalLaunchMode.put(ILaunchManager.DEBUG_MODE, new Boolean(true));
+				globalLaunchMode.put(ILaunchManager.PROFILE_MODE, new Boolean(true));
+			}
+		}
+
+		action.setEnabled(isEnabled());
+		Trace.trace(Trace.FINEST, "< selectionChanged " + (System.currentTimeMillis() - time));
+	}
+	
+	/**
+	 * Determines whether there is a server factory available for the given module
+	 * and the various start modes.
+	 */
+	protected boolean findGlobalLaunchModes(IModule module) {
+		Iterator iterator = ServerCore.getServerTypes().iterator();
+		while (iterator.hasNext()) {
+			IServerType type = (IServerType) iterator.next();
+			if (isValidServerType(type, module)) {
+				for (byte b = 0; b < launchModes.length; b++) {
+					if (type.supportsLaunchMode(launchModes[b])) {
+						globalLaunchMode.put(launchModes[b], new Boolean(true));
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Returns true if the given server type can launch the module. 
+	 */
+	protected boolean isValidServerType(IServerType type, IModule module) {
+		try {
+			IRuntimeType runtimeType = type.getRuntimeType();
+			ServerUtil.isSupportedModule(runtimeType.getModuleTypes(), module.getType(), module.getVersion());
+		} catch (Exception e) {
+			return false;
+		}
+		return true;
+	}
+
+	protected boolean supportsLaunchMode(IServer server, String launchMode) {
+		return server.getServerType().supportsLaunchMode(launchMode);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/ServerAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/ServerAction.java
new file mode 100644
index 0000000..7df5bf5
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/actions/ServerAction.java
@@ -0,0 +1,269 @@
+package org.eclipse.wst.server.ui.internal.actions;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.wst.server.core.IOrdered;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.ServerUtil;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.actions.IServerAction;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+/**
+ *
+ */
+public class ServerAction implements IOrdered {
+	public static class RealServerAction extends Action {
+		protected Shell shell;
+		protected ServerAction action;
+		protected IServer server;
+		protected IServerConfiguration configuration;
+		
+		public RealServerAction(Shell shell, ServerAction action, IServer server, IServerConfiguration configuration) {
+			super(action.getLabel());
+			this.shell = shell;
+			this.action = action;
+			this.server = server;
+			this.configuration = configuration;
+			setImageDescriptor(action.getImageDescriptor());
+			setEnabled(action.getDelegate().supports(server, configuration));
+		}
+		
+		public void run() {
+			action.getDelegate().run(shell, server, configuration);
+		}
+	}
+	
+	private static List serverActions;
+
+	private IConfigurationElement element;
+	private IServerAction delegate;
+	private ImageDescriptor imageDescriptor;
+
+	/**
+	 * ServerAction constructor comment.
+	 */
+	public ServerAction(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * 
+	 */
+	public IConfigurationElement getConfigurationElement() {
+		return element;
+	}
+
+	/**
+	 * Returns the id.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+	
+	/**
+	 * Returns the label.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getLabel() {
+		return element.getAttribute("label");
+	}
+	
+	/**
+	 * Returns the order.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			String o = element.getAttribute("order");
+			return Integer.parseInt(o);
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+	
+	/**
+	 * Returns the icon.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getIcon() {
+		return element.getAttribute("icon");
+	}
+	
+	public String getCategory() {
+		return element.getAttribute("category");
+	}
+	
+	protected ImageDescriptor getImageDescriptor() {
+		if (imageDescriptor != null)
+			return imageDescriptor;
+		
+		try {
+			String pluginId = element.getDeclaringExtension().getNamespace();
+			imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, getIcon());
+		} catch (Exception e) {
+			// ignore
+		}
+		return imageDescriptor;
+	}
+
+	/**
+	 * Return the ids of the server resource factories (specified
+	 * using Java-import style) that this page may support.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	public String[] getTypeIds() {
+		try {
+			List list = new ArrayList();
+			StringTokenizer st = new StringTokenizer(element.getAttribute("typeIds"), ",");
+			while (st.hasMoreTokens()) {
+				String str = st.nextToken();
+				if (str != null && str.length() > 0)
+					list.add(str.trim());
+			}
+			String[] s = new String[list.size()];
+			list.toArray(s);
+			return s;
+		} catch (Exception e) {
+			//Trace.trace("Could not get server resource from: " + element.getAttribute("serverResources"));
+			return null;
+		}
+	}
+	
+	/**
+	 * Returns true if the given server resource type (given by the
+	 * id) can use this action. This result is based on
+	 * the result of the getTypeIds() method.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsServerResource(String id) {
+		if (id == null || id.length() == 0)
+			return false;
+
+		String[] s = getTypeIds();
+		if (s == null)
+			return false;
+		
+		int size = s.length;
+		for (int i = 0; i < size; i++) {
+			if (s[i].endsWith("*")) {
+				if (id.length() >= s[i].length() && id.startsWith(s[i].substring(0, s[i].length() - 1)))
+					return true;
+			} else if (id.equals(s[i]))
+				return true;
+		}
+		return false;
+	}
+
+	public IServerAction getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IServerAction) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace("Could not create action delegate", e);
+			}
+		}
+		return delegate;
+	}
+	
+	/**
+	 * Returns a List of all server actions.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getServerActions() {
+		if (serverActions == null)
+			loadServerActions();
+		return serverActions;
+	}
+
+	/**
+	 * Load the server action extension point.
+	 */
+	private static void loadServerActions() {
+		Trace.trace(Trace.CONFIG, "->- Loading .serverActions extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerUICore.PLUGIN_ID, "serverActions");
+
+		int size = cf.length;
+		serverActions = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				serverActions.add(new ServerAction(cf[i]));
+				Trace.trace(Trace.CONFIG, "  Loaded serverAction: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load serverAction: " + cf[i].getAttribute("id"), t);
+			}
+		}
+
+		// sort actions
+		ServerUtil.sortOrderedList(serverActions);
+		Trace.trace(Trace.CONFIG, "-<- Done loading .serverActions extension point -<-");
+	}
+
+	public static void addServerMenuItems(Shell shell, IMenuManager menu, IServer server) {
+		addServerMenuItems(shell, menu, server, server.getServerConfiguration());
+	}
+	
+	/**
+	 * 
+	 */
+	public static void addServerMenuItems(Shell shell, IMenuManager menu, IServer server, IServerConfiguration configuration) {
+		boolean addedSeparator = false;
+		String category = null;
+		
+		Iterator iterator = getServerActions().iterator();
+		while (iterator.hasNext()) {
+			ServerAction serverAction = (ServerAction) iterator.next();
+			if (category == null)
+				category = serverAction.getCategory();
+			else if (!category.equals(serverAction.getCategory())) {
+				category = serverAction.getCategory();
+				menu.add(new Separator());
+			}
+			if ((server != null && server.getServerType() != null && serverAction.supportsServerResource(server.getServerType().getId())) ||
+					(configuration != null && serverAction.supportsServerResource(configuration.getServerConfigurationType().getId()))) {
+				if (!addedSeparator) {
+					addedSeparator = true;
+					menu.add(new Separator());
+				}
+				try {
+					Action action = new RealServerAction(shell, serverAction, server, configuration);
+					menu.add(action);
+				} catch (Exception e) {
+					// could not add menu item
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/ConfigurationCommand.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/ConfigurationCommand.java
new file mode 100644
index 0000000..0cdff87
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/ConfigurationCommand.java
@@ -0,0 +1,43 @@
+package org.eclipse.wst.server.ui.internal.command;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.util.Task;
+/**
+ * Configuration command.
+ */
+public abstract class ConfigurationCommand extends Task {
+	protected IServerConfigurationWorkingCopy configuration;
+
+	/**
+	 * ConfigurationCommand constructor comment.
+	 */
+	public ConfigurationCommand(IServerConfigurationWorkingCopy configuration) {
+		super();
+		this.configuration = configuration;
+	}
+
+	/**
+	 * Returns true if this command can be undone.
+	 * @return boolean
+	 */
+	public boolean canUndo() {
+		return true;
+	}
+	
+	public abstract boolean execute();
+	
+	public void execute(IProgressMonitor monitor) {
+		execute();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/ServerCommand.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/ServerCommand.java
new file mode 100644
index 0000000..b6a0cd0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/ServerCommand.java
@@ -0,0 +1,42 @@
+package org.eclipse.wst.server.ui.internal.command;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.core.util.Task;
+/**
+ * A command on a server.
+ */
+public abstract class ServerCommand extends Task {
+	protected IServerWorkingCopy server;
+
+	/**
+	 * ServerCommand constructor comment.
+	 */
+	public ServerCommand(IServerWorkingCopy server) {
+		super();
+		this.server = server;
+	}
+
+	/**
+	 * Returns true if this command can be undone.
+	 * @return boolean
+	 */
+	public boolean canUndo() {
+		return true;
+	}
+	
+	public abstract boolean execute();
+	
+	public void execute(IProgressMonitor monitor) {
+		execute();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/SetServerConfigurationNameCommand.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/SetServerConfigurationNameCommand.java
new file mode 100644
index 0000000..eae0f0d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/SetServerConfigurationNameCommand.java
@@ -0,0 +1,61 @@
+package org.eclipse.wst.server.ui.internal.command;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * Command to change the server configuration name.
+ */
+public class SetServerConfigurationNameCommand extends ConfigurationCommand {
+	protected String name;
+	protected String oldName;
+
+	/**
+	 * SetServerConfigurationNameCommand constructor comment.
+	 */
+	public SetServerConfigurationNameCommand(IServerConfigurationWorkingCopy config, String name) {
+		super(config);
+		this.name = name;
+	}
+
+	/**
+	 * Execute the command.
+	 * @return boolean
+	 */
+	public boolean execute() {
+		oldName = configuration.getName();
+		configuration.setName(name);
+		return true;
+	}
+
+	/**
+	 * Returns this command's description.
+	 * @return java.lang.String
+	 */
+	public String getDescription() {
+		return ServerUIPlugin.getResource("%serverEditorOverviewServerConfigurationNameDescription");
+	}
+
+	/**
+	 * Returns this command's label.
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		return ServerUIPlugin.getResource("%serverEditorOverviewServerConfigurationNameCommand");
+	}
+
+	/**
+	 * Undo the command.
+	 */
+	public void undo() {
+		configuration.setName(oldName);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/SetServerHostnameCommand.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/SetServerHostnameCommand.java
new file mode 100644
index 0000000..1499497
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/SetServerHostnameCommand.java
@@ -0,0 +1,61 @@
+package org.eclipse.wst.server.ui.internal.command;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * Command to change the server hostname.
+ */
+public class SetServerHostnameCommand extends ServerCommand {
+	protected String name;
+	protected String oldName;
+
+	/**
+	 * SetServerHostnameCommand constructor comment.
+	 */
+	public SetServerHostnameCommand(IServerWorkingCopy server, String name) {
+		super(server);
+		this.name = name;
+	}
+
+	/**
+	 * Execute the command.
+	 * @return boolean
+	 */
+	public boolean execute() {
+		oldName = server.getHostname();
+		server.setHostname(name);
+		return true;
+	}
+
+	/**
+	 * Returns this command's description.
+	 * @return java.lang.String
+	 */
+	public String getDescription() {
+		return ServerUIPlugin.getResource("%serverEditorOverviewServerHostnameDescription");
+	}
+
+	/**
+	 * Returns this command's label.
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		return ServerUIPlugin.getResource("%serverEditorOverviewServerHostnameCommand");
+	}
+
+	/**
+	 * Undo the command.
+	 */
+	public void undo() {
+		server.setHostname(oldName);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/SetServerNameCommand.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/SetServerNameCommand.java
new file mode 100644
index 0000000..8519fa9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/command/SetServerNameCommand.java
@@ -0,0 +1,61 @@
+package org.eclipse.wst.server.ui.internal.command;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * Command to change the server name.
+ */
+public class SetServerNameCommand extends ServerCommand {
+	protected String name;
+	protected String oldName;
+
+	/**
+	 * SetServerNameCommand constructor comment.
+	 */
+	public SetServerNameCommand(IServerWorkingCopy server, String name) {
+		super(server);
+		this.name = name;
+	}
+
+	/**
+	 * Execute the command.
+	 * @return boolean
+	 */
+	public boolean execute() {
+		oldName = server.getName();
+		server.setName(name);
+		return true;
+	}
+
+	/**
+	 * Returns this command's description.
+	 * @return java.lang.String
+	 */
+	public String getDescription() {
+		return ServerUIPlugin.getResource("%serverEditorOverviewServerNameDescription");
+	}
+
+	/**
+	 * Returns this command's label.
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		return ServerUIPlugin.getResource("%serverEditorOverviewServerNameCommand");
+	}
+
+	/**
+	 * Undo the command.
+	 */
+	public void undo() {
+		server.setName(oldName);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/GlobalCommandManager.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/GlobalCommandManager.java
new file mode 100644
index 0000000..62df876
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/GlobalCommandManager.java
@@ -0,0 +1,688 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.wst.server.core.IElement;
+import org.eclipse.wst.server.core.IElementWorkingCopy;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.core.ITask;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.editor.ICommandManager;
+import org.eclipse.wst.server.ui.editor.IServerEditorPartInput;
+import org.eclipse.wst.server.ui.editor.ServerEditorPartInput;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+
+public class GlobalCommandManager {
+	// maximum number of commands in the history
+	private static final int MAX_HISTORY = 200;
+
+	class ServerResourceCommand {
+		ITask command;
+		String id;
+	}
+	
+	// commands in the undo history
+	protected List undoList = new ArrayList();
+
+	// commands in the redo history
+	protected List redoList = new ArrayList();
+
+	class CommandManagerInfo {
+		// number of open editors on this resource
+		int count;
+		
+		// true if the resource has not been saved since
+		// the last change
+		boolean isDirty;
+		
+		// true if the resource is read-only
+		boolean isReadOnly;
+		
+		// true if all changes can be undone, false if
+		// a non-reversable change has been made
+		boolean canCompletelyUndo = true;
+		
+		// the element id
+		String id;
+		
+		// the working copy
+		IElementWorkingCopy wc;
+		
+		// files and timestamps
+		Map fileMap;
+	}
+
+	protected Map commandManagers = new HashMap();
+
+	// property change listeners
+	protected List propertyListeners;
+	public static final String PROP_DIRTY = "dirtyState";
+	public static final String PROP_UNDO = "undoAction";
+	public static final String PROP_REDO = "redoAction";
+	public static final String PROP_RELOAD = "reload";
+
+	protected static GlobalCommandManager instance;
+
+	public static GlobalCommandManager getInstance() {
+		if (instance == null)
+			instance = new GlobalCommandManager();
+		return instance;
+	}
+
+	/**
+	 * Add a property change listener to this instance.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void addPropertyChangeListener(PropertyChangeListener listener) {
+		if (propertyListeners == null)
+			propertyListeners = new ArrayList();
+		propertyListeners.add(listener);
+	}
+
+	/**
+	 * Remove a property change listener from this instance.
+	 *
+	 * @param listener java.beans.PropertyChangeListener
+	 */
+	public void removePropertyChangeListener(PropertyChangeListener listener) {
+		if (propertyListeners != null)
+			propertyListeners.remove(listener);
+	}
+
+	/**
+	 * Fire a property change event.
+	 */
+	protected void firePropertyChangeEvent(String propertyName, Object oldValue, Object newValue) {
+		if (propertyListeners == null)
+			return;
+
+		PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
+		//Trace.trace("Firing: " + event + " " + oldValue);
+		try {
+			int size = propertyListeners.size();
+			PropertyChangeListener[] pcl = new PropertyChangeListener[size];
+			propertyListeners.toArray(pcl);
+			
+			for (int i = 0; i < size; i++)
+				try {
+					pcl[i].propertyChange(event);
+				} catch (Exception e) { }
+		} catch (Exception e) { }
+	}
+
+	/**
+	 * 
+	 */
+	public void getCommandManager(String id) {
+		Trace.trace("Getting command manager for " + id);
+		try {
+			CommandManagerInfo info = (CommandManagerInfo) commandManagers.get(id);
+			if (info != null) {
+				info.count ++;
+				return;
+			}
+		} catch (Exception e) {
+			Trace.trace("Could not find existing command manager", e);
+		}
+		Trace.trace("Creating new command manager for " + id);
+		try {
+			CommandManagerInfo info = new CommandManagerInfo();
+			info.count = 1;
+			info.id = id;
+			IServer server = ServerCore.getResourceManager().getServer(id);
+			if (server != null)
+				info.wc = server.getWorkingCopy();
+			else {
+				IServerConfiguration config = ServerCore.getResourceManager().getServerConfiguration(id);
+				if (config != null)
+					info.wc = config.getWorkingCopy();
+			}
+			info.isDirty = false;
+			info.isReadOnly = false;
+			commandManagers.put(id, info);
+			updateTimestamps(id);
+		} catch (Exception e) {
+			Trace.trace("Could not obtain command manager", e);
+		}
+		return;
+	}
+
+	/**
+	 * 
+	 */
+	public void releaseCommandManager(String id) {
+		Trace.trace("Releasing command manager for " + id);
+		try {
+			CommandManagerInfo info = (CommandManagerInfo) commandManagers.get(id);
+			if (info != null) {
+				info.count --;
+				if (info.count == 0) {
+					if (info.wc instanceof IServerWorkingCopy) {
+						IServerWorkingCopy wc = (IServerWorkingCopy) info.wc;
+						wc.release();
+					} else {
+						IServerConfigurationWorkingCopy wc = (IServerConfigurationWorkingCopy) info.wc;
+						wc.release();
+					}
+					
+					commandManagers.remove(id);
+					clearUndoList(id);
+					clearRedoList(id);
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace("Could not release command manager", e);
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public void reload(String id, IProgressMonitor monitor) {
+		try {
+			CommandManagerInfo info = getExistingCommandManagerInfo(id);
+			if (info != null) {
+				IServer server = ServerCore.getResourceManager().getServer(id);
+				if (server != null)
+					info.wc = server.getWorkingCopy();
+				else {
+					IServerConfiguration config = ServerCore.getResourceManager().getServerConfiguration(id);
+					if (config != null)
+						info.wc = config.getWorkingCopy();
+				}
+				//info.serverElement = ServerCore.getResourceManager().getServer()
+				//info.serverElement = ServerCore.getEditManager().reloadEditModel(info.file, monitor);
+				firePropertyChangeEvent(PROP_RELOAD, id, null);
+			}
+		} catch (Exception e) {
+			Trace.trace("Could not release command manager", e);
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	protected CommandManagerInfo getExistingCommandManagerInfo(String id) {
+		try {
+			return (CommandManagerInfo) commandManagers.get(id);
+		} catch (Exception e) {
+			Trace.trace("Could not find existing command manager info");
+		}
+		return null;
+	}
+
+	/**
+	 * Returns true if there is only one command manager.
+	 */
+	public boolean isOnlyCommandManager(String id) {
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		return (info != null && info.count == 1);
+	}
+	
+	protected IServerEditorPartInput getPartInput(String serverId, ICommandManager serverCommandManager, String configurationId, ICommandManager configurationCommandManager) {
+		CommandManagerInfo serverInfo = null;
+		IServerWorkingCopy server = null;
+		boolean serverReadOnly = false;
+		if (serverId != null) {
+			serverInfo = getExistingCommandManagerInfo(serverId);
+			if (serverInfo == null)
+				return null;
+			else {
+				server = (IServerWorkingCopy) serverInfo.wc;
+				serverReadOnly = serverInfo.isReadOnly;
+			}
+		}
+		
+		CommandManagerInfo configurationInfo = null;
+		IServerConfigurationWorkingCopy configuration = null;
+		boolean configurationReadOnly = false;
+		if (configurationId != null) {
+			configurationInfo = getExistingCommandManagerInfo(configurationId);
+			if (configurationInfo == null)
+				return null;
+			else {
+				configuration = (IServerConfigurationWorkingCopy) configurationInfo.wc;
+				configurationReadOnly = configurationInfo.isReadOnly;
+			}
+		}
+
+		return new ServerEditorPartInput(serverCommandManager, server, serverReadOnly,
+			configurationCommandManager, configuration, configurationReadOnly);
+	}
+	
+	/**
+	 * 
+	 */
+	protected IElement getServerResource(String id) {
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		if (info == null)
+			return null;
+			
+		return info.wc;
+	}
+
+	/**
+	 * Execute the given command and place it in the undo stack.
+	 * If the command cannot be undone, the user will be notifed
+	 * before it is executed.
+	 *
+	 * @param command ICommand
+	 */
+	public void executeCommand(String id, ITask command) {
+		if (!command.canUndo() && !undoList.isEmpty() && ServerUICore.getPreferences().getPromptBeforeIrreversibleChange()) {
+			try {
+				Display d = Display.getCurrent();
+				if (d == null)
+					d = Display.getDefault();
+		
+				Shell shell = d.getActiveShell();
+				if (!MessageDialog.openConfirm(shell, ServerUIPlugin.getResource("%editorServerEditor"), ServerUIPlugin.getResource("%editorPromptIrreversible")))
+					return;
+			} catch (Exception e) { }
+		}
+		
+		ServerResourceCommand src = new ServerResourceCommand();
+		src.id = id;
+		src.command = command;
+
+		try {
+			command.execute(new NullProgressMonitor());
+		} catch (CoreException ce) {
+			return;
+		}
+
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		if (info == null)
+			return;
+
+		if (command.canUndo())
+			addToUndoList(src);
+		else {
+			info.canCompletelyUndo = false;
+			clearUndoList(id);
+		}
+
+		// clear redo list since a new command has been executed.
+		clearRedoList(id);
+
+		setDirtyState(id, true);
+	}
+
+	/**
+	 * Add a command to the history.
+	 */
+	private void addToUndoList(ServerResourceCommand src) {
+		undoList.add(src);
+
+		// limit history growth
+		if (undoList.size() > MAX_HISTORY)
+			undoList.remove(0);
+
+		firePropertyChangeEvent(PROP_UNDO, src.id, null);
+	}
+
+	/**
+	 * Clears the undo of a particular resource.
+	 */
+	private void clearUndoList(String id) {
+		int i = 0;
+		boolean modified = false;
+		while (i < undoList.size()) {
+			ServerResourceCommand src = (ServerResourceCommand) undoList.get(i);
+			if (src.id.equals(id)) {
+				modified = true;
+				undoList.remove(i);
+			} else
+				i++;
+		}
+		if (modified)
+			firePropertyChangeEvent(PROP_UNDO, id, null);
+	}
+
+	/**
+	 * Clears the redo of a particular resource.
+	 */
+	private void clearRedoList(String id) {
+		int i = 0;
+		boolean modified = false;
+		while (i < redoList.size()) {
+			ServerResourceCommand src = (ServerResourceCommand) redoList.get(i);
+			if (src.id.equals(id)) {
+				redoList.remove(i);
+				modified = true;
+			} else
+				i++;
+		}
+		if (modified)
+			firePropertyChangeEvent(PROP_REDO, id, null);
+	}
+
+	/**
+	 * Returns true if there is a command that can be undone.
+	 * @return boolean
+	 */
+	protected boolean canUndo(String a, String b) {
+		Iterator iterator = undoList.iterator();
+		while (iterator.hasNext()) {
+			ServerResourceCommand src = (ServerResourceCommand) iterator.next();
+			if (src.id == a || src.id == b)
+				return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Returns true if there is a command that can be redone.
+	 * @return boolean
+	 */
+	protected boolean canRedo(String a, String b) {
+		Iterator iterator = redoList.iterator();
+		while (iterator.hasNext()) {
+			ServerResourceCommand src = (ServerResourceCommand) iterator.next();
+			if (src.id == a || src.id == b)
+				return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Returns the command that would be undone next.
+	 * 
+	 * @return org.eclipse.wst.server.ui.editor.ICommand
+	 */
+	public ITask getUndoCommand(String a, String b) {
+		int size = undoList.size();
+		for (int i = size - 1; i >= 0; i--) {
+			ServerResourceCommand src = (ServerResourceCommand) undoList.get(i);
+			if (src.id == a || src.id == b)
+				return src.command;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the command that would be redone next.
+	 * 
+	 * @return org.eclipse.wst.server.ui.editor.ICommand
+	 */
+	public ITask getRedoCommand(String a, String b) {
+		int size = redoList.size();
+		for (int i = size - 1; i >= 0; i--) {
+			ServerResourceCommand src = (ServerResourceCommand) redoList.get(i);
+			if (src.id == a || src.id == b)
+				return src.command;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns true if the server resource is "dirty".
+	 *
+	 * @return boolean
+	 */
+	public boolean isDirty(String id) {
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		if (info == null)
+			return false;
+		else
+			return info.isDirty;
+	}
+	
+	/**
+	 * Returns true if the server resource is read-only.
+	 *
+	 * @return boolean
+	 */
+	public boolean isReadOnly(String id) {
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		if (info == null)
+			return false;
+		else
+			return info.isReadOnly;
+	}
+	
+	/**
+	 * Returns the server resource read-only flag.
+	 */
+	public void setReadOnly(String id, boolean readOnly) {
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		if (info == null)
+			return;
+		else {
+			if (info.isReadOnly == readOnly)
+				return;
+			info.isReadOnly = readOnly;
+			firePropertyChangeEvent(PROP_RELOAD, id, null);
+		}
+	}
+
+	/**
+	 * Returns true if the server resource files are read-only.
+	 *
+	 * @return boolean
+	 */
+	public boolean areFilesReadOnly(String id) {
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		if (info == null)
+			return false;
+		else
+			return (getReadOnlyFiles(id).length > 0);
+	}
+	
+	/**
+	 * Sets the dirty state and fires an event if needed.
+	 * @param dirty boolean
+	 */
+	private void setDirtyState(String id, boolean dirty) {
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		if (info.isDirty == dirty)
+			return;
+
+		info.isDirty = dirty;
+		firePropertyChangeEvent(PROP_DIRTY, id, null);
+	}
+
+	/**
+	 * Undo the last command.
+	 */
+	protected void undo(String a, String b) {
+		ServerResourceCommand src = null;
+		Iterator iterator = undoList.iterator();
+		while (iterator.hasNext()) {
+			ServerResourceCommand src2 = (ServerResourceCommand) iterator.next();
+			if (src2.id == a || src2.id == b)
+				src = src2;
+		}
+		if (src == null)
+			return;
+
+		src.command.undo();
+		undoList.remove(src);
+		firePropertyChangeEvent(PROP_UNDO, src.id, null);
+		redoList.add(src);
+		firePropertyChangeEvent(PROP_REDO, src.id, null);
+
+		CommandManagerInfo info = getExistingCommandManagerInfo(src.id);
+		if (info.canCompletelyUndo && getUndoCommand(src.id, null) == null)
+			setDirtyState(src.id, false);
+	}
+
+	/**
+	 * Redo the last command.
+	 */
+	protected void redo(String a, String b) {
+		ServerResourceCommand src = null;
+		Iterator iterator = redoList.iterator();
+		while (iterator.hasNext()) {
+			ServerResourceCommand src2 = (ServerResourceCommand) iterator.next();
+			if (src2.id == a || src2.id == b)
+				src = src2;
+		}
+		if (src == null)
+			return;
+
+		try {
+			src.command.execute(new NullProgressMonitor());
+		} catch (CoreException ce) {
+			return;
+		}
+		redoList.remove(src);
+		firePropertyChangeEvent(PROP_REDO, src.id, null);
+		undoList.add(src);
+		firePropertyChangeEvent(PROP_UNDO, src.id, null);
+
+		setDirtyState(src.id, true);
+	}
+
+	/**
+	 * Clears the history list.
+	 */
+	public void resourceSaved(String id) {
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		//clearUndoList(resource);
+		//clearRedoList(resource);
+		info.canCompletelyUndo = true;
+		setDirtyState(id, false);
+	}
+	
+	/**
+	 * 
+	 */
+	public static IFile[] getReadOnlyFiles(IElement element) {
+		try {
+			List list = new ArrayList();
+			IFile file = null;
+			if (element instanceof IServer)
+				file = ((IServer) element).getFile();
+			else if (element instanceof IServerConfiguration)
+				file = ((IServerConfiguration) element).getFile();
+			
+			if (file != null)
+				list.add(file);
+			
+			//if ()
+			//IServerConfiguration config = (IServerConfiguration) element;
+			// TODO
+			IFile[] files = new IFile[list.size()];
+			list.toArray(files);
+			return files;
+		} catch (Exception e) {
+			Trace.trace("getReadOnlyFiles", e);
+		}
+		return null;
+	}
+	
+	/**
+	 * 
+	 */
+	protected IFile[] getServerResourceFiles(String id) {
+		if (id == null)
+			return new IFile[0];
+
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		if (info == null)
+			return new IFile[0];
+
+		return getReadOnlyFiles(info.wc);
+	}
+	
+	protected IFile[] getReadOnlyFiles(String id) {
+		java.util.List list = new ArrayList();
+		IFile[] files = getServerResourceFiles(id);
+		int size = files.length;
+		for (int i = 0; i < size; i++) {
+			if (files[i].isReadOnly())
+				list.add(files[i]);
+		}
+		
+		IFile[] fileList = new IFile[list.size()];
+		list.toArray(fileList);
+		return fileList;
+	}
+
+	/**
+	 * 
+	 */
+	public void updateTimestamps(String id) {
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		if (info == null)
+			return;
+			
+		info.fileMap = new HashMap();
+		IFile[] files = getServerResourceFiles(id);
+		if (files == null)
+			return;
+
+		int size = files.length;
+		
+		for (int i = 0; i < size; i++) {
+			if (files[i] != null) {
+				File f = files[i].getLocation().toFile();
+				if (f != null) {
+					long time = f.lastModified();
+					info.fileMap.put(files[i], new Long(time));
+				}
+			}
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	protected boolean hasChanged(String id) {
+		CommandManagerInfo info = getExistingCommandManagerInfo(id);
+		if (info == null)
+			return false;
+		IFile[] files = getServerResourceFiles(id);
+		int size = files.length;
+
+		int count = 0;
+		for (int i = 0; i < size; i++) {
+			count++;
+			File f = files[i].getLocation().toFile();
+			try {
+				Long time = (Long) info.fileMap.get(files[i]);
+				if (time.longValue() != f.lastModified())
+					return true;
+			} catch (Exception e) {
+				return true;
+			}
+		}
+
+		if (count != info.fileMap.size())
+			return true;
+		else
+			return false;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/OverviewEditorFactory.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/OverviewEditorFactory.java
new file mode 100644
index 0000000..74bd92d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/OverviewEditorFactory.java
@@ -0,0 +1,34 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.ui.IEditorPart;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.ui.editor.IServerEditorPartFactoryDelegate;
+/**
+ *
+ */
+public class OverviewEditorFactory implements IServerEditorPartFactoryDelegate {
+	/*
+	 * @see IServerEditorPartFactoryDelegate#shouldCreatePage(IServer, IServerConfiguration)
+	 */
+	public boolean shouldCreatePage(IServer server, IServerConfiguration configuration) {
+		return true;
+	}
+
+	/*
+	 * @see IServerEditorPartFactoryDelegate#createPage()
+	 */
+	public IEditorPart createPage() {
+		return new OverviewEditorPart();
+	}
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..4d14fb0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/OverviewEditorPart.java
@@ -0,0 +1,289 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.forms.FormColors;
+import org.eclipse.ui.forms.widgets.*;
+import org.eclipse.ui.help.WorkbenchHelp;
+
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.ui.editor.*;
+import org.eclipse.wst.server.ui.internal.ContextIds;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.command.SetServerConfigurationNameCommand;
+import org.eclipse.wst.server.ui.internal.command.SetServerHostnameCommand;
+import org.eclipse.wst.server.ui.internal.command.SetServerNameCommand;
+/**
+ * Server general editor page.
+ */
+public class OverviewEditorPart extends ServerResourceEditorPart {
+	protected Text serverName;
+	protected Text serverConfigurationName;
+	protected Text hostname;
+	
+	protected boolean updating;
+
+	protected PropertyChangeListener listener;
+
+	/**
+	 * OverviewEditorPart constructor comment.
+	 */
+	protected OverviewEditorPart() {
+		super();
+	}
+	
+	protected ICommandManager getCommandManager() {
+		return commandManager;
+	}
+	
+	protected IServerWorkingCopy getServer() {
+		return server;
+	}
+	
+	protected IServerConfigurationWorkingCopy getServerConfiguration() {
+		return serverConfiguration;
+	}
+
+	/**
+	 * 
+	 */
+	protected void addChangeListener() {
+		listener = new PropertyChangeListener() {
+			public void propertyChange(PropertyChangeEvent event) {
+				if (updating)
+					return;
+				updating = true;
+				if (event.getPropertyName().equals("name"))
+					updateNames();
+				else if (event.getPropertyName().equals("hostname") && hostname != null) {
+					hostname.setText((String) event.getNewValue());
+				}
+				updating = false;
+			}
+		};
+		if (server != null)
+			server.addPropertyChangeListener(listener);
+		if (serverConfiguration != null)
+			serverConfiguration.addPropertyChangeListener(listener);
+	}
+
+	protected void updateNames() {
+		if (serverName != null)
+			serverName.setText(server.getName());
+		if (serverConfigurationName != null)
+			serverConfigurationName.setText(serverConfiguration.getName());
+	}
+
+	/**
+	 * Creates the SWT controls for this workbench part.
+	 *
+	 * @param parent the parent control
+	 */
+	public final void createPartControl(Composite parent) {
+		FormToolkit toolkit = new FormToolkit(parent.getDisplay());
+		
+		ScrolledForm form = toolkit.createScrolledForm(parent);
+		form.setText(ServerUIPlugin.getResource("%serverEditorOverviewPageTitle"));
+		form.getBody().setLayout(new GridLayout());
+		form.getBody().setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
+		
+		Composite columnComp = toolkit.createComposite(form.getBody());
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		//layout.marginHeight = 10;
+		//layout.marginWidth = 10;
+		layout.verticalSpacing = 0;
+		layout.horizontalSpacing = 10;
+		columnComp.setLayout(layout);
+		columnComp.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
+		
+		// left column
+		Composite leftColumnComp = toolkit.createComposite(columnComp);
+		layout = new GridLayout();
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		layout.verticalSpacing = 10;
+		layout.horizontalSpacing = 0;
+		leftColumnComp.setLayout(layout);
+		leftColumnComp.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
+		
+		//Composite section = toolkit.createSectionComposite(leftColumnComp, ServerUIPlugin.getResource("%serverEditorOverviewSection"), ServerUIPlugin.getResource("%serverEditorOverviewDescription"));
+		Section section = toolkit.createSection(leftColumnComp, ExpandableComposite.TWISTIE|ExpandableComposite.EXPANDED|ExpandableComposite.TITLE_BAR|Section.DESCRIPTION);
+		section.setText(ServerUIPlugin.getResource("%serverEditorOverviewSection"));
+		section.setDescription(ServerUIPlugin.getResource("%serverEditorOverviewDescription"));
+		section.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
+
+		Composite composite = toolkit.createComposite(section);
+		layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.marginHeight = 5;
+		layout.marginWidth = 10;
+		layout.verticalSpacing = 5;
+		layout.horizontalSpacing = 15;
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
+		WorkbenchHelp.setHelp(composite, ContextIds.EDITOR_OVERVIEW_PAGE);
+		toolkit.paintBordersFor(composite);
+		section.setClient(composite);
+
+		// server name
+		if (server != null) {
+			createLabel(toolkit, composite, ServerUIPlugin.getResource("%serverEditorOverviewServerName"));
+			
+			serverName = toolkit.createText(composite, server.getName());
+			GridData data = new GridData(GridData.FILL_HORIZONTAL);
+			serverName.setLayoutData(data);
+			serverName.addModifyListener(new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					if (updating)
+						return;
+					updating = true;
+					getCommandManager().executeCommand(new SetServerNameCommand(getServer(), serverName.getText()));
+					updating = false;
+				}
+			});
+		}
+		
+		// server configuration name
+		if (serverConfiguration != null) {
+			createLabel(toolkit, composite, ServerUIPlugin.getResource("%serverEditorOverviewServerConfigurationName"));
+			
+			serverConfigurationName = toolkit.createText(composite, serverConfiguration.getName());
+			GridData data = new GridData(GridData.FILL_HORIZONTAL);
+			serverConfigurationName.setLayoutData(data);
+			serverConfigurationName.addModifyListener(new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					if (updating)
+						return;
+					updating = true;
+					getCommandManager().executeCommand(new SetServerConfigurationNameCommand(getServerConfiguration(), serverConfigurationName.getText()));
+					updating = false;
+				}
+			});
+		}
+		
+		// hostname
+		if (server != null) {
+			createLabel(toolkit, composite, ServerUIPlugin.getResource("%serverEditorOverviewServerHostname"));
+			
+			hostname = toolkit.createText(composite, server.getHostname());
+			GridData data = new GridData(GridData.FILL_HORIZONTAL);
+			hostname.setLayoutData(data);
+			hostname.addModifyListener(new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					if (updating)
+						return;
+					updating = true;
+					getCommandManager().executeCommand(new SetServerHostnameCommand(getServer(), hostname.getText()));
+					updating = false;
+				}
+			});
+		}
+		
+		insertSections(leftColumnComp, "org.eclipse.wst.server.editor.overview.left");
+		
+		// left column
+		Composite rightColumnComp = toolkit.createComposite(columnComp);
+		layout = new GridLayout();
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		layout.verticalSpacing = 10;
+		layout.horizontalSpacing = 0;
+		rightColumnComp.setLayout(layout);
+		rightColumnComp.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
+		
+		insertSections(rightColumnComp, "org.eclipse.wst.server.editor.overview.right");
+
+		initialize();
+	}
+	
+	protected Label createLabel(FormToolkit toolkit, Composite parent, String text) {
+		Label label = toolkit.createLabel(parent, text);
+		label.setForeground(toolkit.getColors().getColor(FormColors.TITLE));
+		return label;
+	}
+	
+	public void dispose() {
+		if (server != null)
+			server.removePropertyChangeListener(listener);
+		if (serverConfiguration != null)
+			serverConfiguration.removePropertyChangeListener(listener);
+	}
+	
+	/* (non-Javadoc)
+	 * Initializes the editor part with a site and input.
+	 * <p>
+	 * Subclasses of <code>EditorPart</code> must implement this method.  Within
+	 * the implementation subclasses should verify that the input type is acceptable
+	 * and then save the site and input.  Here is sample code:
+	 * </p>
+	 * <pre>
+	 *		if (!(input instanceof IFileEditorInput))
+	 *			throw new PartInitException("Invalid Input: Must be IFileEditorInput");
+	 *		setSite(site);
+	 *		setInput(editorInput);
+	 * </pre>
+	 */
+	public void init(IEditorSite site, IEditorInput input) {
+		super.init(site, input);
+		
+		addChangeListener();
+		initialize();
+	}
+	
+	/**
+	 * Initialize the fields in this editor.
+	 */
+	protected void initialize() {
+		if (serverName == null)
+			return;
+		updating = true;
+		
+		if (server != null) {
+			serverName.setText(server.getName());
+			if (readOnly)
+				serverName.setEnabled(false);
+			else
+				serverName.setEnabled(true);
+		}
+		if (serverConfiguration != null) {
+			serverConfigurationName.setText(serverConfiguration.getName());
+			if (readOnly)
+				serverConfigurationName.setEnabled(false);
+			else
+				serverConfigurationName.setEnabled(true);
+		}
+		
+		updating = false;
+	}
+	
+	protected void validate() { }
+
+	/**
+	 * @see IWorkbenchPart#setFocus()
+	 */
+	public void setFocus() {
+		if (serverName != null)
+			serverName.setFocus();
+		else if (serverConfigurationName != null)
+			serverConfigurationName.setFocus();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditor.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditor.java
new file mode 100644
index 0000000..19853f8
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditor.java
@@ -0,0 +1,993 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.*;
+import org.eclipse.ui.part.MultiPageEditorPart;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.internal.ServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.internal.ServerWorkingCopy;
+import org.eclipse.wst.server.core.model.IServerResourceListener;
+import org.eclipse.wst.server.core.util.ProgressUtil;
+import org.eclipse.wst.server.core.util.ServerResourceAdapter;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.editor.*;
+import org.eclipse.wst.server.ui.internal.*;
+/**
+ * A multi-page server resource editor.
+ */
+public class ServerEditor extends MultiPageEditorPart {
+	/**
+	 * Internal part and shell activation listener
+	 */
+	class ActivationListener extends ShellAdapter implements IPartListener {
+		private IWorkbenchPart fActivePart;
+		private boolean fIsHandlingActivation = false;
+		
+		public void partActivated(IWorkbenchPart part) {
+			fActivePart = part;
+			handleActivation();
+		}
+
+		public void partBroughtToTop(IWorkbenchPart part) { }
+
+		public void partClosed(IWorkbenchPart part) { }
+
+		public void partDeactivated(IWorkbenchPart part) {
+			fActivePart = null;
+		}
+
+		public void partOpened(IWorkbenchPart part) { }
+
+		public void shellActivated(ShellEvent e) {
+			handleActivation();
+		}
+
+		private void handleActivation() {
+			if (fIsHandlingActivation)
+				return;
+			
+			if (fActivePart == ServerEditor.this) {
+				fIsHandlingActivation = true;
+				try {
+					checkResourceState();
+				} finally {
+					fIsHandlingActivation= false;
+				}
+			}
+		}
+	}
+
+	protected IServerWorkingCopy server;
+	protected IServerConfigurationWorkingCopy serverConfiguration;
+	protected String serverId;
+	protected String serverConfigurationId;
+
+	protected GlobalCommandManager commandManager;
+
+	protected PropertyChangeListener listener;
+
+	protected IAction undoAction;
+	protected IAction redoAction;
+	
+	protected TextAction cutAction;
+	protected TextAction copyAction;
+	protected TextAction pasteAction;
+	protected boolean updatingActions;
+	
+	protected IAction[] editorActions;
+
+	protected java.util.List serverPages;
+	
+	// on focus change flag
+	protected boolean resourceDeleted;
+	
+	// input given to the contained pages
+	protected IServerEditorPartInput editorPartInput;
+	
+	// status line and status
+	protected IStatusLineManager status;
+	protected StatusLineContributionItem statusItem;
+	
+	private ActivationListener activationListener = new ActivationListener();
+	protected IServerResourceListener resourceListener;
+	
+	// Used for disabling resource change check when saving through editor.
+	protected boolean isSaving = false;
+
+	/**
+	 * ServerEditor constructor comment.
+	 */
+	public ServerEditor() {
+		super();
+		
+		ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
+
+		undoAction = new Action() {
+			public void run() {
+				getCommandManager().undo(serverId, serverConfigurationId);
+			}
+		};
+		undoAction.setEnabled(false);
+		undoAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO));
+		//undoAction.setHoverImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO_HOVER));
+		//undoAction.setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO_DISABLED));
+	
+		redoAction = new Action() {
+			public void run() {
+				getCommandManager().redo(serverId, serverConfigurationId);
+			}
+		};
+		redoAction.setEnabled(false);
+		redoAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO));
+		//redoAction.setHoverImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO_HOVER));
+		//redoAction.setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO_DISABLED));
+	}
+
+	/**
+	 * Close the editor correctly.
+	 */
+	protected void closeEditor() {
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				getEditorSite().getPage().closeEditor(ServerEditor.this, false);
+			}
+		});
+	}
+	
+	protected void createActions() {
+		List actionList = new ArrayList();
+		
+		// add server actions
+		if (server != null && server.getServerType() != null) {
+			Iterator iterator = ServerEditorCore.getServerEditorActionFactories().iterator();
+			String id = server.getServerType().getId();
+			while (iterator.hasNext()) {
+				ServerEditorActionFactory factory = (ServerEditorActionFactory) iterator.next();
+				if (factory.supportsServerElementType(id) && factory.shouldDisplay(server, serverConfiguration))
+					actionList.add(factory.createAction(getEditorSite(), editorPartInput));
+			}
+		}
+		
+		// add server configuration actions
+		if (serverConfiguration != null && serverConfiguration.getServerConfigurationType() != null) {
+			Iterator iterator = ServerEditorCore.getServerEditorActionFactories().iterator();
+			String id = serverConfiguration.getServerConfigurationType().getId();
+			while (iterator.hasNext()) {
+				ServerEditorActionFactory factory = (ServerEditorActionFactory) iterator.next();
+				if (factory.supportsServerElementType(id) && factory.shouldDisplay(server, serverConfiguration))
+					actionList.add(factory.createAction(getEditorSite(), editorPartInput));
+			}
+		}
+
+		editorActions = new IAction[actionList.size()];
+		actionList.toArray(editorActions);
+	}
+
+	/**
+	 * Creates the pages of this multi-page editor.
+	 * <p>
+	 * Subclasses of <code>MultiPageEditor</code> must implement this method.
+	 * </p>
+	 */
+	protected void createPages() {	
+		try {
+			int index = 0;
+			serverPages = new ArrayList();
+			
+			// add editor pages
+			int pageCount = 0;
+			
+			String serverTypeId = null;
+			String serverConfigurationTypeId = null;
+			if (server != null && server.getServerType() != null)
+				serverTypeId = server.getServerType().getId();
+			if (serverConfiguration != null && serverConfiguration.getServerConfigurationType() != null)
+				serverConfigurationTypeId = serverConfiguration.getServerConfigurationType().getId();
+	
+			Iterator iterator = ServerEditorCore.getServerEditorPageFactories().iterator();
+			while (iterator.hasNext()) {
+				IServerEditorPartFactory factory = (IServerEditorPartFactory) iterator.next();
+				if (((serverTypeId != null && factory.supportsType(serverTypeId)) || 
+						(serverConfigurationTypeId != null && factory.supportsType(serverConfigurationTypeId)))
+						&& factory.shouldCreatePage(server, serverConfiguration)) {
+					Trace.trace(Trace.FINEST, "Adding page: " + factory.getId() + " " + editorPartInput);
+					try {
+						IEditorPart page = factory.createPage();
+						if (page instanceof ServerResourceEditorPart) {
+							ServerResourceEditorPart srep = (ServerResourceEditorPart) page;
+							srep.setPageFactory(factory);
+						}
+						index = addPage(page, editorPartInput);
+						serverPages.add(page);
+	
+						setPageText(index, factory.getName());
+				
+						pageCount ++;
+					} catch (Exception e) {
+						Trace.trace(Trace.SEVERE, "Could not display editor page " + factory.getId(), e);
+					}
+				}
+			}
+			
+			setActivePage(0);
+			
+			// register for events that might change the cut/copy/paste actions
+			int count = getPageCount();
+			for (int i = 0; i < count; i++) {
+				Control control = getControl(i);
+				registerEvents(control);
+			}
+			updateActions();
+		} catch (Exception e) {
+			Trace.trace("Error creating server editor pages", e);
+		}
+	}
+
+	public void dispose() {
+		if (activationListener != null) {
+			IWorkbenchWindow window = getSite().getWorkbenchWindow();
+			window.getPartService().removePartListener(activationListener);
+			Shell shell = window.getShell();
+			if (shell != null && !shell.isDisposed())
+				shell.removeShellListener(activationListener);
+			activationListener = null;
+		}
+		
+		if (resourceListener != null)
+			ServerCore.getResourceManager().removeResourceListener(resourceListener);
+
+		super.dispose();
+		if (commandManager != null)
+			commandManager.removePropertyChangeListener(listener);
+
+		if (serverId != null)
+			commandManager.releaseCommandManager(serverId);
+			
+		if (serverConfigurationId != null)
+			commandManager.releaseCommandManager(serverConfigurationId);
+	}
+
+	/* (non-Javadoc)
+	 * Saves the contents of this editor.
+	 * <p>
+	 * Subclasses must override this method to implement the open-save-close lifecycle
+	 * for an editor.  For greater details, see <code>IEditorPart</code>
+	 * </p>
+	 *
+	 * @see IEditorPart
+	 */
+	public void doSave(IProgressMonitor monitor) {
+		// Set the isSaving flag to true.
+		isSaving = true;
+		
+		// check pages for errors first
+		java.util.List errors = new ArrayList();
+		Iterator iterator = serverPages.iterator();
+		int count = 0;
+		while (iterator.hasNext()) {
+			IEditorPart part = (IEditorPart) iterator.next();
+			if (part instanceof ServerResourceEditorPart) {
+				IStatus[] status2 = ((ServerResourceEditorPart) part).getSaveStatus();
+				if (status2 != null) {
+					int size = status2.length;
+					for (int i = 0; i < size; i++)
+						errors.add("[" + getPageText(count) + "] " + status2[i].getMessage());
+				}
+			}
+			count ++;
+		}
+		if (!errors.isEmpty()) {
+			StringBuffer sb = new StringBuffer();
+			sb.append(ServerUIPlugin.getResource("%errorEditorCantSave") + "\n");
+			iterator = errors.iterator();
+			while (iterator.hasNext())
+				sb.append("\t" + ((String) iterator.next()) + "\n");
+
+			EclipseUtil.openError(getEditorSite().getShell(), sb.toString());
+			monitor.setCanceled(true);
+			// Reset the isSaving flag.
+			isSaving = false;
+			return;
+		}
+		
+		try {
+			monitor = ProgressUtil.getMonitorFor(monitor);
+			int ticks = 2000;
+			String name = "";
+			if (server != null)
+				name = server.getName();
+			else
+				name = serverConfiguration.getName();
+			monitor.beginTask(ServerUIPlugin.getResource("%savingTask", name), ticks);
+			if (server != null && serverConfiguration != null)
+				ticks /= 2;
+
+			if (server != null)  {
+				((ServerWorkingCopy)server).save(ProgressUtil.getSubMonitorFor(monitor, ticks), false);
+				getCommandManager().resourceSaved(serverId);
+				commandManager.updateTimestamps(serverId);
+			}
+
+			if (serverConfiguration != null) {
+				((ServerConfigurationWorkingCopy)serverConfiguration).save(ProgressUtil.getSubMonitorFor(monitor, ticks), false);
+				getCommandManager().resourceSaved(serverConfigurationId);
+				commandManager.updateTimestamps(serverConfigurationId);
+			}
+			
+			ILabelProvider labelProvider = ServerUICore.getLabelProvider();
+			if (server != null)
+				setPartName(labelProvider.getText(server));
+			else
+				setPartName(labelProvider.getText(serverConfiguration));
+		} catch (Exception e) {
+			Trace.trace("Error saving from configuration editor", e);
+	
+			monitor.setCanceled(true);
+	
+			String title = ServerUIPlugin.getResource("%editorSaveErrorDialog");
+			String message = ServerUIPlugin.getResource("%editorSaveErrorMessage", e.getLocalizedMessage());
+			MessageDialog.openError(getEditorSite().getShell(), title,  message);
+		} finally {
+			monitor.done();
+		}
+		// Reset the isSaving flag.
+		isSaving = false;
+	}
+
+	/* (non-Javadoc)
+	 * Saves the contents of this editor to another object.
+	 * <p>
+	 * Subclasses must override this method to implement the open-save-close lifecycle
+	 * for an editor.  For greater details, see <code>IEditorPart</code>
+	 * </p>
+	 *
+	 * @see IEditorPart
+	 */
+	public void doSaveAs() { }
+
+	/**
+	 * Fire a property change event.
+	 *
+	 * @param i int
+	 */
+	protected void firePropertyChange(int i) {
+		if (i == ServerResourceEditorPart.PROP_ERROR)
+			updateStatusError();
+		super.firePropertyChange(i);
+	}
+
+	/**
+	 * 
+	 */
+	public GlobalCommandManager getCommandManager() {
+		return commandManager;
+	}
+
+	/**
+	 * Return the redo action.
+	 *
+	 * @return org.eclipse.jface.action.Action
+	 */
+	public IAction getRedoAction() {
+		return redoAction;
+	}
+
+	/**
+	 * Return the undo action.
+	 *
+	 * @return org.eclipse.jface.action.Action
+	 */
+	public IAction getUndoAction() {
+		return undoAction;
+	}
+
+	/* (non-Javadoc)
+	 * Sets the cursor and selection state for this editor to the passage defined
+	 * by the given marker.
+	 * <p>
+	 * Subclasses may override.  For greater details, see <code>IEditorPart</code>
+	 * </p>
+	 *
+	 * @see IEditorPart
+	 */
+	public void gotoMarker(IMarker marker) { }
+
+	/**
+	 * Update the cut, copy, and paste actions.
+	 */
+	public void updateActionsImpl() {
+		if (updatingActions)
+			return;
+		
+		updatingActions = true;
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				updatingActions = false;
+				updateActions();
+			}
+		});
+	}
+
+	/**
+	 * Update the cut, copy, and paste actions.
+	 */
+	public void updateActions() {
+		cutAction.update();
+		copyAction.update();
+		pasteAction.update();
+	}
+	
+	/**
+	 * Update the cut, copy, and paste actions.
+	 */
+	protected void updateStatusLine() {
+		if (statusItem != null) {
+			boolean readOnly = false;
+			if (server != null && commandManager.isReadOnly(serverId))
+				readOnly = true;
+			else if (serverConfiguration != null && commandManager.areFilesReadOnly(serverConfigurationId))
+				readOnly = true;
+			
+			if (readOnly)
+				statusItem.setText(ServerUIPlugin.getResource("%editorReadOnly"));
+			else
+				statusItem.setText(ServerUIPlugin.getResource("%editorWritable"));
+		}
+
+		if (status != null) {
+			StringBuffer sb = new StringBuffer();
+			boolean first = true;
+			if (server != null) {
+				IFile[] files = commandManager.getReadOnlyFiles(serverId);
+				for (int i = 0; i < files.length; i++) {
+					if (!first)
+						sb.append(", ");
+					sb.append(files[i].getName());
+					first = false;
+				}
+			}
+			if (serverConfiguration != null) {
+				IFile[] files = commandManager.getReadOnlyFiles(serverConfigurationId);
+				for (int i = 0; i < files.length; i++) {
+					if (!first)
+						sb.append(", ");
+					sb.append(files[i].getName());
+					first = false;
+				}
+			}
+			if (sb.length() > 1)
+				status.setMessage(ServerUIPlugin.getResource("%editorReadOnlyFiles", sb.toString()));
+			else
+				status.setMessage("");
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	public void updateStatusError() {
+		if (status == null)
+			return;
+
+		String error = null;
+		IEditorPart part = getActiveEditor();
+		if (part instanceof ServerResourceEditorPart)
+			error = ((ServerResourceEditorPart) part).getErrorMessage();
+		
+		Iterator iterator = serverPages.iterator();
+		int count = 0;
+		while (error == null && iterator.hasNext()) {
+			part = (IEditorPart) iterator.next();
+			if (part instanceof ServerResourceEditorPart) {
+				error = ((ServerResourceEditorPart) part).getErrorMessage();
+				if (error != null)
+					error = "[" + getPageText(count) + "] " + error;
+			}
+			count ++;
+		}
+		status.setErrorMessage(error);
+	}
+	
+	/**
+	 * 
+	 */
+	protected void pageChange(int newPageIndex) {
+		super.pageChange(newPageIndex);
+		updateStatusError();
+	}
+	
+	/**
+	 * 
+	 */
+	public void setStatus(IStatusLineManager status, StatusLineContributionItem item) {
+		this.status = status;
+		this.statusItem = item;
+		updateStatusError();
+	}
+	
+	/**
+	 * Register for key and traversal events to enable/disable the cut/copy/paste actions.
+	 */
+	protected void registerEvents(Control control) {
+		if (control == null)
+			return;
+		
+		if (control instanceof Text || control instanceof Combo) {
+			// register the world... any of these actions could cause the state to change
+			control.addTraverseListener(new TraverseListener() {
+				public void keyTraversed(TraverseEvent event) {
+					updateActionsImpl();
+				}
+			});
+			control.addKeyListener(new KeyListener() {
+				public void keyPressed(KeyEvent event) {
+					updateActionsImpl();
+				}
+				public void keyReleased(KeyEvent event) {
+					updateActionsImpl();
+				}
+			});
+			control.addMouseListener(new MouseListener() {
+				public void mouseDown(MouseEvent event) { }
+				public void mouseUp(MouseEvent event) {
+					updateActionsImpl();
+				}
+				public void mouseDoubleClick(MouseEvent event) {
+					updateActionsImpl();
+				}
+			});
+			control.addFocusListener(new FocusListener() {
+				public void focusGained(FocusEvent event) {
+					updateActionsImpl();
+				}
+				public void focusLost(FocusEvent event) {
+					updateActionsImpl();
+				}
+			});
+			if (control instanceof Text) {
+				Text text = (Text) control;
+				text.addModifyListener(new ModifyListener() {
+					public void modifyText(ModifyEvent event) {
+						updateActionsImpl();
+					}
+				});
+				text.addSelectionListener(new SelectionListener() {
+					public void widgetSelected(SelectionEvent event) {
+						updateActionsImpl();
+					}
+					public void widgetDefaultSelected(SelectionEvent event) {
+						updateActionsImpl();
+					}
+				});
+			} else {
+				Combo combo = (Combo) control;
+				combo.addModifyListener(new ModifyListener() {
+					public void modifyText(ModifyEvent event) {
+						updateActionsImpl();
+					}
+				});
+				combo.addSelectionListener(new SelectionListener() {
+					public void widgetSelected(SelectionEvent event) {
+						updateActionsImpl();
+					}
+					public void widgetDefaultSelected(SelectionEvent event) {
+						updateActionsImpl();
+					}
+				});
+			}
+		}
+		
+		if (control instanceof Composite) {
+			Control[] children = ((Composite)control).getChildren();
+			if (children != null) {
+				int size = children.length;
+				for (int i = 0; i < size; i++)
+					registerEvents(children[i]);
+			}
+		}
+	}
+
+	/* (non-Javadoc)
+	 * Initializes the editor part with a site and input.
+	 * <p>
+	 * Subclasses of <code>EditorPart</code> must implement this method.  Within
+	 * the implementation subclasses should verify that the input type is acceptable
+	 * and then save the site and input.  Here is sample code:
+	 * </p>
+	 * <pre>
+	 *		if (!(input instanceof IFileEditorInput))
+	 *			throw new PartInitException("Invalid Input: Must be IFileEditorInput");
+	 *		setSite(site);
+	 *		setInput(editorInput);
+	 * </pre>
+	 */
+	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+		commandManager = GlobalCommandManager.getInstance();
+		
+		super.init(site, input);
+
+		if (input instanceof IFileEditorInput) {
+			IFileEditorInput fei = (IFileEditorInput) input;
+			IFile file = fei.getFile();
+			if (file != null && file.exists()) {
+				IResourceManager rm = ServerCore.getResourceManager();
+				IServer server2 = rm.getServer(file);
+				if (server2 != null) {
+					serverId = server2.getId();
+					if (server2.getServerConfiguration() != null)
+						serverConfigurationId = server2.getServerConfiguration().getId();
+				} else {
+					IServerConfiguration configuration = rm.getServerConfiguration(file);
+					if (configuration != null)
+						serverConfigurationId = configuration.getId();
+				}
+			}
+		} else if (input instanceof IServerEditorInput) {
+			IServerEditorInput sei = (IServerEditorInput) input;
+			serverId = sei.getServerId();
+			serverConfigurationId = sei.getServerConfigurationId();
+		}
+
+		if (serverId != null) {
+			commandManager.getCommandManager(serverId);
+			server = (IServerWorkingCopy) commandManager.getServerResource(serverId);
+		}
+
+		if (serverConfigurationId != null) {
+			commandManager.getCommandManager(serverConfigurationId);
+			serverConfiguration = (IServerConfigurationWorkingCopy) commandManager.getServerResource(serverConfigurationId);
+		}
+
+		ILabelProvider labelProvider = ServerUICore.getLabelProvider();
+		if (server != null) {
+			setPartName(labelProvider.getText(server));
+			setTitleImage(labelProvider.getImage(server));
+			setTitleToolTip(serverId);
+		} else if (serverConfiguration != null) {
+			setPartName(labelProvider.getText(serverConfiguration));
+			setTitleImage(labelProvider.getImage(serverConfiguration));
+			setTitleToolTip(serverConfigurationId);
+		} else {
+			setPartName("-");	
+		}
+
+		cutAction = new TextAction(site.getShell().getDisplay(), TextAction.CUT_ACTION);
+		copyAction = new TextAction(site.getShell().getDisplay(), TextAction.COPY_ACTION);
+		pasteAction = new TextAction(site.getShell().getDisplay(), TextAction.PASTE_ACTION);
+
+		listener = new PropertyChangeListener() {
+			public void propertyChange(PropertyChangeEvent event) {
+				if (GlobalCommandManager.PROP_DIRTY.equals(event.getPropertyName())) {
+					Object obj = event.getOldValue();
+					if (obj == serverId || obj == serverConfigurationId)
+						firePropertyChange(PROP_DIRTY);
+				} else if (GlobalCommandManager.PROP_UNDO.equals(event.getPropertyName())) {
+					Object obj = event.getOldValue();
+					if (obj == serverId || obj == serverConfigurationId)
+						updateUndoAction();
+				} else if (GlobalCommandManager.PROP_REDO.equals(event.getPropertyName())) {
+					Object obj = event.getOldValue();
+					if (obj == serverId || obj == serverConfigurationId)
+						updateRedoAction();
+				} else if (GlobalCommandManager.PROP_RELOAD.equals(event.getPropertyName())) {
+					Object obj = event.getOldValue();
+					if (obj == serverId) {
+						server = (IServerWorkingCopy) commandManager.getServerResource(serverId);
+						refresh();
+					} else if (obj == serverConfigurationId) {
+						serverConfiguration = (IServerConfigurationWorkingCopy) commandManager.getServerResource(serverConfigurationId);
+						refresh();
+					}
+				}
+			}
+		};
+		if ((server != null && commandManager.isDirty(serverId)) ||
+			(serverConfiguration != null && commandManager.isDirty(serverConfigurationId)))
+			firePropertyChange(PROP_DIRTY);
+
+		commandManager.addPropertyChangeListener(listener);
+		
+		// create editor input
+		ICommandManager serverCommandManager = null;
+		if (server != null)
+			serverCommandManager = new ServerResourceCommandManager(this, serverId, commandManager);
+		ICommandManager configurationCommandManager = null;
+		if (serverConfiguration != null)
+			configurationCommandManager = new ServerResourceCommandManager(this, serverConfigurationId, commandManager);
+		editorPartInput = commandManager.getPartInput(serverId, serverCommandManager, serverConfigurationId, configurationCommandManager);
+		
+		createActions();
+		
+		// add resource listener
+		ServerCore.getResourceManager().addResourceListener(new ServerResourceAdapter() {
+			public void serverRemoved(IServer oldServer) {
+				if (oldServer.equals(server) && !isDirty())
+					closeEditor();
+			}
+
+			public void serverConfigurationRemoved(IServerConfiguration oldServerConfiguration) {
+				if (oldServerConfiguration.equals(serverConfiguration) && !isDirty())
+					closeEditor();
+			}
+		});
+		
+		IWorkbenchWindow window = getSite().getWorkbenchWindow();
+		window.getPartService().addPartListener(activationListener);
+		window.getShell().addShellListener(activationListener);
+	}
+
+	/* (non-Javadoc)
+	 * Returns whether the contents of this editor have changed since the last save
+	 * operation.
+	 * <p>
+	 * Subclasses must override this method to implement the open-save-close lifecycle
+	 * for an editor.  For greater details, see <code>IEditorPart</code>
+	 * </p>
+	 *
+	 * @see IEditorPart
+	 */
+	public boolean isDirty() {
+		if (commandManager != null) {
+			if (server != null && commandManager.isDirty(serverId))
+				return true;
+			if (serverConfiguration != null && commandManager.isDirty(serverConfigurationId))
+				return true;
+		}
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * Returns whether the "save as" operation is supported by this editor.
+	 * <p>
+	 * Subclasses must override this method to implement the open-save-close lifecycle
+	 * for an editor.  For greater details, see <code>IEditorPart</code>
+	 * </p>
+	 *
+	 * @see IEditorPart
+	 */
+	public boolean isSaveAsAllowed() {
+		return false;
+	}
+
+	/**
+	 * Update the undo action.
+	 */
+	protected void updateUndoAction() {
+		ITask command = commandManager.getUndoCommand(serverId, serverConfigurationId);
+		if (command == null) {
+			undoAction.setText(ServerUIPlugin.getResource("%editorUndoDisabled"));
+			undoAction.setToolTipText("");
+			undoAction.setDescription("");
+			undoAction.setEnabled(false);
+		} else {
+			String text = ServerUIPlugin.getResource("%editorUndoEnabled", new Object[] {command.getName()});
+			undoAction.setText(text);
+			undoAction.setToolTipText(command.getDescription());
+			undoAction.setDescription(command.getDescription());
+			undoAction.setEnabled(true);
+		}
+	}
+
+	/**
+	 * Update the redo action.
+	 */
+	protected void updateRedoAction() {
+		ITask command = commandManager.getRedoCommand(serverId, serverConfigurationId);
+		if (command == null) {
+			redoAction.setText(ServerUIPlugin.getResource("%editorRedoDisabled"));
+			redoAction.setToolTipText("");
+			redoAction.setDescription("");
+			redoAction.setEnabled(false);
+		} else {
+			String text = ServerUIPlugin.getResource("%editorRedoEnabled", new Object[] {command.getName()});
+			redoAction.setText(text);
+			redoAction.setToolTipText(command.getDescription());
+			redoAction.setDescription(command.getDescription());
+			redoAction.setEnabled(true);
+		}
+	}
+	
+	/**
+	 * Return the cut action.
+	 * 
+	 * @return org.eclipse.jface.action.IAction
+	 */
+	public IAction getCutAction() {
+		return cutAction;
+	}
+	
+	/**
+	 * Return the copy action.
+	 * 
+	 * @return org.eclipse.jface.action.IAction
+	 */
+	public IAction getCopyAction() {
+		return copyAction;
+	}
+	
+	/**
+	 * Return the paste action.
+	 * 
+	 * @return org.eclipse.jface.action.IAction
+	 */
+	public IAction getPasteAction() {
+		return pasteAction;
+	}
+	
+	/**
+	 * Returns the editor actions.
+	 * 
+	 * @return org.eclipse.jface.action.IAction
+	 */
+	public IAction[] getEditorActions() {
+		return editorActions;
+	}
+	
+	/**
+	 * Update the server pages with new input.
+	 */
+	protected void refresh() {
+		// create editor input
+		ICommandManager serverCommandManager = null;
+		if (server != null)
+			serverCommandManager = new ServerResourceCommandManager(this, serverId, commandManager);
+		ICommandManager configurationCommandManager = null;
+		if (serverConfiguration != null)
+			configurationCommandManager = new ServerResourceCommandManager(this, serverConfigurationId, commandManager);
+		editorPartInput = commandManager.getPartInput(serverId, serverCommandManager, serverConfigurationId, configurationCommandManager);
+		
+		Iterator iterator = serverPages.iterator();
+		while (iterator.hasNext()) {
+			IEditorPart part = (IEditorPart) iterator.next();						
+			try {
+				part.init(part.getEditorSite(), editorPartInput);
+			} catch (Exception e) {
+				Trace.trace("Error refresh()ing editor part", e);
+			}
+		}	
+	}
+	
+	/**
+	 * 
+	 */
+	protected void promptReadOnlyServerFile(String id) {
+		commandManager.setReadOnly(id, true);
+		String title = ServerUIPlugin.getResource("%editorResourceModifiedTitle");
+		String message = ServerUIPlugin.getResource("%editorReadOnlyMessage");
+		MessageDialog.openInformation(getEditorSite().getShell(), title, message);
+	}
+
+	/**
+	 * 
+	 */
+	protected void promptReloadServerFile(String id, IElement serverFile2) {
+		String title = ServerUIPlugin.getResource("%editorResourceModifiedTitle");
+		String message = null;
+		if (serverFile2 instanceof IServer)
+			message = ServerUIPlugin.getResource("%editorServerModifiedMessage");
+		else
+			message = ServerUIPlugin.getResource("%editorServerConfigurationModifiedMessage");
+
+		if (MessageDialog.openQuestion(getEditorSite().getShell(), title, message)) {
+			try {
+				//file.refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor());
+				//TODO
+			} catch (Exception e) {
+				Trace.trace("Error refreshing server", e);
+			}
+			commandManager.reload(id, new NullProgressMonitor());
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public void setFocus() {
+		super.setFocus();
+	}
+	
+	/**
+	 * 
+	 */
+	protected void checkResourceState() {
+		// Do not check the resource state change if saving through the editor.
+		if (isSaving) {
+			// Do nothing.
+			return;
+		}
+		
+		// check for deleted files
+		if (resourceDeleted) {
+			String title = ServerUIPlugin.getResource("%editorResourceDeleteTitle");
+			String message = null;
+			if (server != null && serverConfiguration != null)
+				message = ServerUIPlugin.getResource("%editorResourceDeleteBothMessage", new String[] {server.getName(), serverConfiguration.getName()});
+			else if (server != null)
+				message = ServerUIPlugin.getResource("%editorResourceDeleteServerMessage", server.getName());
+			else
+				message = ServerUIPlugin.getResource("%editorResourceDeleteServerConfigurationMessage", serverConfiguration.getName());
+			String[] labels = new String[] {ServerUIPlugin.getResource("%editorResourceDeleteSave"), IDialogConstants.CLOSE_LABEL};
+			MessageDialog dialog = new MessageDialog(getEditorSite().getShell(), title, null, message, MessageDialog.INFORMATION, labels, 0);
+
+			if (dialog.open() == 0)
+				doSave(new NullProgressMonitor());
+			else
+				closeEditor();
+			return;
+		}
+		resourceDeleted = false;
+
+		// check for server changes
+		if (serverId != null) {
+			if (!commandManager.isDirty(serverId)) {
+				if (commandManager.hasChanged(serverId))
+					promptReloadServerFile(serverId, server);
+			} else {
+				if (commandManager.hasChanged(serverId) && !commandManager.areFilesReadOnly(serverId))
+					promptReloadServerFile(serverId, server);
+				else if (commandManager.areFilesReadOnly(serverId) && !commandManager.isReadOnly(serverId))
+					promptReadOnlyServerFile(serverId);
+			}
+			if (commandManager.isReadOnly(serverId) && !commandManager.areFilesReadOnly(serverId))
+				commandManager.setReadOnly(serverId, false);
+			commandManager.updateTimestamps(serverId);
+		}
+
+		// check for server configuration changes
+		if (serverConfigurationId != null) {
+			if (!commandManager.isDirty(serverConfigurationId)) {
+				if (commandManager.hasChanged(serverConfigurationId))
+					promptReloadServerFile(serverConfigurationId, serverConfiguration);
+			} else {
+				if (commandManager.hasChanged(serverConfigurationId) && !commandManager.areFilesReadOnly(serverConfigurationId))
+					promptReloadServerFile(serverConfigurationId, serverConfiguration);
+				else if (commandManager.areFilesReadOnly(serverConfigurationId) && !commandManager.isReadOnly(serverConfigurationId))
+					promptReadOnlyServerFile(serverConfigurationId);
+			}		
+			if (commandManager.isReadOnly(serverConfigurationId) && !commandManager.areFilesReadOnly(serverConfigurationId))
+				commandManager.setReadOnly(serverConfigurationId, false);
+			commandManager.updateTimestamps(serverConfigurationId);
+		}
+
+		updateStatusLine();
+	}
+	
+	/**
+	 * Set the tooltip.
+	 */
+	public String getTitleToolTip() {
+		if (server != null && server.getFile() != null)
+			return server.getFile().getFullPath().toString();
+		else if (serverConfiguration != null && serverConfiguration.getFile() != null)
+			return serverConfiguration.getFile().getFullPath().toString();
+		else if (server != null)
+			return server.getName();
+		else if (serverConfiguration != null)
+			return serverConfiguration.getName();
+		else
+			return "error";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorActionBarContributor.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorActionBarContributor.java
new file mode 100644
index 0000000..3516513
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorActionBarContributor.java
@@ -0,0 +1,127 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.part.EditorActionBarContributor;
+/**
+ * Server editor action bar contributor.
+ */
+public class ServerEditorActionBarContributor extends EditorActionBarContributor {
+	public static final String SERVER_EDITOR_SEPARATOR = "server-editor-additions";
+
+	// current editor
+	protected ServerEditor editor;
+
+	/**
+	 * ServerEditorActionBarContributor constructor comment.
+	 */
+	public ServerEditorActionBarContributor() {
+		super();
+	}
+
+	/**
+	 * Sets the active editor for the contributor.
+	 * <p>
+	 * The <code>EditorActionBarContributor</code> implementation of this method does
+	 * nothing. Subclasses may reimplement. This generally entails disconnecting
+	 * from the old editor, connecting to the new editor, and updating the actions
+	 * to reflect the new editor.
+	 * </p>
+	 * 
+	 * @param targetEditor the new target editor
+	 */
+	public void setActiveEditor(IEditorPart targetEditor) {
+		super.setActiveEditor(targetEditor);
+
+		if (targetEditor != null && targetEditor.equals(editor))
+			return;
+		
+		IActionBars actionBars = getActionBars();
+		boolean actionBarsUpdated = false;
+
+		if (editor != null) {
+			editor.setStatus(null, null);
+			
+			IStatusLineManager status = actionBars.getStatusLineManager();
+			status.removeAll();
+
+			IToolBarManager tbm = actionBars.getToolBarManager();
+			tbm.removeAll();
+			
+			actionBarsUpdated = true;
+		}
+
+		if (targetEditor instanceof ServerEditor) {
+			editor = (ServerEditor) targetEditor;
+			Trace.trace(Trace.FINEST, "Editor action bar contributor for: " + editor);
+			editor.updateUndoAction();
+			editor.updateRedoAction();
+			
+			actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(), editor.getUndoAction());
+			actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(), editor.getRedoAction());
+			
+			actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), editor.getCopyAction());
+			actionBars.setGlobalActionHandler(ActionFactory.CUT.getId(), editor.getCutAction());
+			actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), editor.getPasteAction());
+			
+			IStatusLineManager status = actionBars.getStatusLineManager();
+			StatusLineContributionItem item = new StatusLineContributionItem("id");
+			status.add(item);
+
+			editor.setStatus(status, item);
+			editor.updateStatusLine();
+
+			IAction[] actions = editor.getEditorActions();
+			IToolBarManager tbm = actionBars.getToolBarManager();
+			tbm.add(new Separator(SERVER_EDITOR_SEPARATOR));
+			boolean modified = false;
+			if (actions != null) {
+				int size = actions.length;
+				Trace.trace(Trace.FINEST, "Attempting to add editor actions: " + size);
+				for (int i = 0; i < size; i++) {
+					Trace.trace(Trace.FINEST, "action: " + actions[i]);
+					tbm.appendToGroup(SERVER_EDITOR_SEPARATOR, actions[i]);
+					modified = true;
+				}
+			}
+			
+			if (modified)
+				tbm.update(false);
+			actionBarsUpdated = true;
+		} else
+			editor = null;
+		
+		if (actionBarsUpdated)
+			actionBars.updateActionBars();
+	}
+	
+	/**
+	 * Contributes to the given tool bar.
+	 * <p>
+	 * The <code>EditorActionBarContributor</code> implementation of this method
+	 * does nothing. Subclasses may reimplement to add to the tool bar portion of
+	 * this contribution.
+	 * </p>
+	 *
+	 * @param toolBarManager the manager that controls the workbench tool bar
+	 */
+	public void contributeToToolBar(IToolBarManager toolBarManager) {
+		super.contributeToToolBar(toolBarManager);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorActionFactory.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorActionFactory.java
new file mode 100644
index 0000000..8192efc
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorActionFactory.java
@@ -0,0 +1,174 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.ui.editor.IServerEditorActionFactory;
+import org.eclipse.wst.server.ui.editor.IServerEditorActionFactoryDelegate;
+import org.eclipse.wst.server.ui.editor.IServerEditorPartInput;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.ui.IEditorSite;
+
+/**
+ * A default server that can be created for a set of given
+ * natures.
+ */
+public class ServerEditorActionFactory implements IServerEditorActionFactory {
+	private IConfigurationElement element;
+	private IServerEditorActionFactoryDelegate delegate;
+
+	/**
+	 * ServerEditorActionFactory constructor comment.
+	 */
+	public ServerEditorActionFactory(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * 
+	 */
+	public IConfigurationElement getConfigurationElement() {
+		return element;
+	}
+
+	/**
+	 * Returns the id of this default server.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+	
+	/**
+	 * Returns the id of this default server.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		return element.getAttribute("name");
+	}
+	
+	/**
+	 * Returns the order.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			String o = element.getAttribute("order");
+			return Integer.parseInt(o);
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+
+	/**
+	 * Return the ids of the server resource factories (specified
+	 * using Java-import style) that this page may support.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	public String[] getTypeIds() {
+		try {
+			List list = new ArrayList();
+			StringTokenizer st = new StringTokenizer(element.getAttribute("typeIds"), ",");
+			while (st.hasMoreTokens()) {
+				String str = st.nextToken();
+				if (str != null && str.length() > 0)
+					list.add(str);
+			}
+			String[] s = new String[list.size()];
+			list.toArray(s);
+			return s;
+		} catch (Exception e) {
+			//Trace.trace("Could not get server resource from: " + element.getAttribute("serverResources"));
+			return null;
+		}
+	}
+	
+	/**
+	 * Returns true if the given server resource type (given by the
+	 * id) can be opened with this editor. This result is based on
+	 * the result of the getServerResources() method.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsServerElementType(String id) {
+		if (id == null || id.length() == 0)
+			return false;
+
+		String[] s = getTypeIds();
+		if (s == null)
+			return false;
+		
+		int size = s.length;
+		for (int i = 0; i < size; i++) {
+			if (s[i].endsWith("*")) {
+				if (id.length() >= s[i].length() && id.startsWith(s[i].substring(0, s[i].length() - 1)))
+					return true;
+			} else if (id.equals(s[i]))
+				return true;
+		}
+		return false;
+	}
+
+	/*
+	 * @see IPublishManager#getDelegate()
+	 */
+	public IServerEditorActionFactoryDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IServerEditorActionFactoryDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace("Could not create server editorpage delegate", e);
+			}
+		}
+		return delegate;
+	}
+	
+	/**
+	 * Returns true if this editor page should be visible with the given
+	 * server instance and configuration combination. This allows (for
+	 * instance) complex configuration pages to only be shown when used
+	 * with non-unittest servers.
+	 *
+	 * <p>If the instance or configuration is being opened by itself, the
+	 * other value (instance or configuration) will be null.
+	 */
+	public boolean shouldDisplay(IServer server, IServerConfiguration serverConfiguration) {
+		try {
+			return getDelegate().shouldDisplay(server, serverConfiguration);
+		} catch (Exception e) {
+			Trace.trace("Error calling delegate", e);
+			return false;
+		}
+	}
+
+	/**
+	 * Create the editor page.
+	 */
+	public IAction createAction(IEditorSite site, IServerEditorPartInput input) {
+		try {
+			return getDelegate().createAction(site, input);
+		} catch (Exception e) {
+			Trace.trace("Error calling delegate", e);
+			return null;
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorCore.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorCore.java
new file mode 100644
index 0000000..5dbc227
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorCore.java
@@ -0,0 +1,136 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.server.core.ServerUtil;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.Trace;
+
+/**
+ * 
+ */
+public class ServerEditorCore {
+	// cached copy of all editor factories and actions
+	private static List editorPageFactories;
+	private static List editorPageSectionFactories;
+	private static List editorActionFactories;
+	
+	/**
+	 * Returns a List of all editor page factories
+	 *
+	 * @return java.util.List
+	 */
+	public static List getServerEditorPageFactories() {
+		if (editorPageFactories == null)
+			loadEditorPageFactories();
+		return editorPageFactories;
+	}
+	
+	/**
+	 * Returns a List of all editor page section factories
+	 *
+	 * @return java.util.List
+	 */
+	public static List getServerEditorPageSectionFactories() {
+		if (editorPageSectionFactories == null)
+			loadEditorPageSectionFactories();
+		return editorPageSectionFactories;
+	}
+	
+	/**
+	 * Load the editor page factory extension point.
+	 */
+	private static void loadEditorPageFactories() {
+		Trace.trace(Trace.CONFIG, "->- Loading .editorPages extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerUICore.PLUGIN_ID, "editorPages");
+
+		int size = cf.length;
+		editorPageFactories = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				editorPageFactories.add(new ServerEditorPartFactory(cf[i]));
+				Trace.trace(Trace.CONFIG, "  Loaded editorPage: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load editorPage: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		
+		// sort pages
+		ServerUtil.sortOrderedList(editorPageFactories);
+		Trace.trace(Trace.CONFIG, "-<- Done loading .editorPages extension point -<-");
+	}
+	
+	/**
+	 * Load the editor page section factory extension point.
+	 */
+	private static void loadEditorPageSectionFactories() {
+		Trace.trace(Trace.CONFIG, "->- Loading .editorPageSections extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerUICore.PLUGIN_ID, "editorPageSections");
+
+		int size = cf.length;
+		editorPageSectionFactories = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				editorPageSectionFactories.add(new ServerEditorPageSectionFactory(cf[i]));
+				Trace.trace(Trace.CONFIG, "  Loaded editorPageSection: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load editorPageSection: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		
+		// sort sections
+		ServerUtil.sortOrderedList(editorPageSectionFactories);
+		Trace.trace(Trace.CONFIG, "-<- Done loading .editorPageSections extension point -<-");
+	}
+
+	/**
+	 * Returns a List of all editor action factories.
+	 *
+	 * @return java.util.List
+	 */
+	public static List getServerEditorActionFactories() {
+		if (editorActionFactories == null)
+			loadEditorActionFactories();
+		return editorActionFactories;
+	}
+	
+	/**
+	 * Load the editor action factories extension point.
+	 */
+	private static void loadEditorActionFactories() {
+		Trace.trace(Trace.CONFIG, "->- Loading .editorActions extension point ->-");
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerUICore.PLUGIN_ID, "editorActions");
+
+		int size = cf.length;
+		editorActionFactories = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			try {
+				editorActionFactories.add(new ServerEditorActionFactory(cf[i]));
+				Trace.trace(Trace.CONFIG, "  Loaded editorAction: " + cf[i].getAttribute("id"));
+			} catch (Throwable t) {
+				Trace.trace(Trace.SEVERE, "  Could not load editorAction: " + cf[i].getAttribute("id"), t);
+			}
+		}
+		
+		// sort pages
+		ServerUtil.sortOrderedList(editorActionFactories);
+		Trace.trace(Trace.CONFIG, "-<- Done loading .editorActions extension point -<-");
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorInput.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorInput.java
new file mode 100644
index 0000000..faa3bf0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorInput.java
@@ -0,0 +1,224 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.wst.server.core.IResourceManager;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.editor.IServerEditorInput;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IPersistableElement;
+
+/**
+ * The editor input for server configurations and instances. The
+ * input points to a resource that is either an instance or
+ * configuration.
+ *
+ * <p>Editors supporting this editor input should use the ResourceManager
+ * to load their own copy of the resource. Each editor is responsible
+ * for managing this resource and making sure that only one copy is
+ * loaded from disk when multiple editors are opened on the same
+ * resource.</p>
+ *
+ * <p>When the editor saves back to the resource, the server tooling
+ * will notice the change and reload the new configuration.</p>
+ *
+ * <p>Editors should call setEditing(resource, true) when the first
+ * editor opens on a particular resource, and setEditing(resource,
+ * false) when the last editor on a resource closes. This will
+ * ensure that the server tooling does not try to edit the resource
+ * and cause conflicting changes while an editor is open.</p>
+ */
+public class ServerEditorInput implements IServerEditorInput, IPersistableElement {
+	private String serverId;
+	private String configurationId;
+
+	/**
+	 * ServerEditorInput constructor comment.
+	 */
+	public ServerEditorInput(String serverId, String configurationId) {
+		super();
+		this.serverId = serverId;
+		this.configurationId = configurationId;
+	}
+	
+	/**
+	 * Returns the server id.
+	 * @return org.eclipse.core.resources.IResource
+	 */
+	public String getServerId() {
+		return serverId;
+	}
+
+	/**
+	 * Returns the server configuration id.
+	 * @return org.eclipse.core.resources.IResource
+	 */
+	public String getServerConfigurationId() {
+		return configurationId;
+	}
+
+	/**
+	 * Indicates whether some other object is "equal to" this one.
+	 * In this case it means that the underlying IFolders are equal.
+	 */
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (!(obj instanceof ServerEditorInput))
+			return false;
+		ServerEditorInput other = (ServerEditorInput) obj;
+		if (serverId == null) {
+			if (other.serverId != null)
+				return false;	
+		} else if (!serverId.equals(other.serverId))
+			return false;
+		if (configurationId == null) {
+			if (other.configurationId != null)
+				return false;	
+		} else if (!configurationId.equals(other.configurationId))
+			return false;
+		return true;
+	}
+
+	/**
+	 * Returns whether the editor input exists.  
+	 * <p>
+	 * This method is primarily used to determine if an editor input should 
+	 * appear in the "File Most Recently Used" menu.  An editor input will appear 
+	 * in the list until the return value of <code>exists</code> becomes 
+	 * <code>false</code> or it drops off the bottom of the list.
+	 *
+	 * @return <code>true</code> if the editor input exists; <code>false</code>
+	 *		otherwise
+	 */
+	public boolean exists() {
+		IResourceManager rm = ServerCore.getResourceManager();
+		if (serverId != null && rm.getServer(serverId) == null)
+			return false;
+		else if (configurationId != null && rm.getServerConfiguration(configurationId) == null)
+			return false;
+		else
+			return true;
+	}
+
+	/**
+	 * Returns an object which is an instance of the given class
+	 * associated with this object. Returns <code>null</code> if
+	 * no such object can be found.
+	 *
+	 * @param adapter the adapter class to look up
+	 * @return a object castable to the given class, 
+	 *    or <code>null</code> if this object does not
+	 *    have an adapter for the given class
+	 */
+	public Object getAdapter(Class adapter) {
+		return Platform.getAdapterManager().getAdapter(this, adapter);
+	}
+
+	/**
+	 * Returns the ID of an element factory which can be used to recreate 
+	 * this object.  An element factory extension with this ID must exist
+	 * within the workbench registry.
+	 * 
+	 * @return the element factory ID
+	 */
+	public String getFactoryId() {
+		return ServerEditorInputFactory.FACTORY_ID;
+	}
+
+	public ImageDescriptor getImageDescriptor() {
+		if (serverId != null)
+			return ImageResource.getImageDescriptor(ImageResource.IMG_SERVER);
+		else
+			return ImageResource.getImageDescriptor(ImageResource.IMG_SERVER_CONFIGURATION);
+	}
+	
+	/**
+	 * Returns the name of this editor input for display purposes.
+	 * <p>
+	 * For instance, if the fully qualified input name is
+	 * <code>"a\b\MyFile.gif"</code>, the return value would be just
+	 * <code>"MyFile.gif"</code>.
+	 *
+	 * @return the file name string
+	 */
+	public String getName() {
+		IResourceManager rm = ServerCore.getResourceManager();
+		if (serverId != null) {
+			IServer server = rm.getServer(serverId);
+			if (server != null)
+				return server.getName();
+			else
+				return serverId;
+		} else if (configurationId != null) {
+			IServerConfiguration configuration = rm.getServerConfiguration(configurationId);
+			if (configuration != null)
+				return configuration.getName();
+			else
+				return configurationId;
+		} else
+			return "";
+	}
+
+	/*
+	 * Returns an object that can be used to save the state of this editor input.
+	 *
+	 * @return the persistable element, or <code>null</code> if this editor input
+	 *   cannot be persisted
+	 */
+	public IPersistableElement getPersistable() {
+		return this;
+	}
+
+	public String getToolTipText() {
+		String s = null;
+		IResourceManager rm = ServerCore.getResourceManager();
+		if (serverId != null) {
+			IServer server = rm.getServer(serverId);
+			if (server != null) {
+				if (server.getFile() != null) {
+					s = server.getFile().getFullPath().makeRelative().toString();
+					if (s.startsWith("/"))
+						s = s.substring(1);
+				} else
+					s = server.getName();
+			}
+		}
+		if (s == null && configurationId != null) {
+			IServerConfiguration configuration = rm.getServerConfiguration(configurationId);
+			if (configuration != null) {
+				if (configuration.getFile() != null) {
+					s = configuration.getFile().getFullPath().makeRelative().toString();
+					if (s.startsWith("/"))
+						s = s.substring(1);
+				} else
+					s = configuration.getName();
+			}
+		}
+		if (s == null)
+			s = "";
+		return s;
+	}
+
+	/**
+	 * Saves the state of an element within a memento.
+	 *
+	 * @param memento the storage area for element state
+	 */
+	public void saveState(IMemento memento) {
+		ServerEditorInputFactory.saveState(memento, this);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorInputFactory.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorInputFactory.java
new file mode 100644
index 0000000..a0d20a6
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorInputFactory.java
@@ -0,0 +1,61 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ui.IElementFactory;
+import org.eclipse.ui.IMemento;
+/**
+ * This factory is used in the persistence of ServerResourceEditorInput
+ * instances. This allows the user to close the workbench with an
+ * open editor and reopen to the same editor.
+ */
+public class ServerEditorInputFactory implements IElementFactory {
+	protected final static String FACTORY_ID = "org.eclipse.wst.server.ui.editor.input.factory";
+	protected final static String SERVER_ID = "server-id";
+	protected final static String SERVER_CONFIGURATION_ID = "server-configuration-id";
+
+	/**
+	 * ServerEditorInputFactory constructor comment.
+	 */
+	public ServerEditorInputFactory() {
+	}
+
+	/**
+	 * Creates an <code>IElement</code> from the state captured within 
+	 * an <code>IMemento</code>.
+	 *
+	 * @param memento a memento containing the state for an element
+	 * @return an element, or <code>null</code> if the element could not be created
+	 */
+	public IAdaptable createElement(IMemento memento) {
+		// get the resource names
+		String serverId = memento.getString(SERVER_ID);
+		String configurationId = memento.getString(SERVER_CONFIGURATION_ID);
+
+		return new ServerEditorInput(serverId, configurationId);
+	}
+
+	/**
+	 * Saves the state of an element within a memento.
+	 *
+	 * @param memento the storage area for element state
+	 */
+	public static void saveState(IMemento memento, ServerEditorInput input) {
+		if (input == null)
+			return;
+			
+		if (input.getServerId() != null)
+			memento.putString(SERVER_ID, input.getServerId());
+		if (input.getServerConfigurationId() != null)
+			memento.putString(SERVER_CONFIGURATION_ID, input.getServerConfigurationId());
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorPageSectionFactory.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorPageSectionFactory.java
new file mode 100644
index 0000000..8f7eaeb
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorPageSectionFactory.java
@@ -0,0 +1,170 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.ui.editor.*;
+import org.eclipse.wst.server.ui.internal.Trace;
+
+/**
+ * 
+ */
+public class ServerEditorPageSectionFactory implements IServerEditorPageSectionFactory {
+	private IConfigurationElement element;
+	private IServerEditorPageSectionFactoryDelegate delegate;
+
+	/**
+	 * ServerEditorPageSectionFactory constructor comment.
+	 */
+	public ServerEditorPageSectionFactory(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * 
+	 */
+	public IConfigurationElement getConfigurationElement() {
+		return element;
+	}
+
+	/**
+	 * Returns the id of this factory.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+	
+	/**
+	 * Returns the order.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			String o = element.getAttribute("order");
+			return Integer.parseInt(o);
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+	
+	/**
+	 * Returns the insertion id of this factory.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getInsertionId() {
+		return element.getAttribute("insertionId");
+	}
+
+	/**
+	 * Return the ids of the server resource factories (specified
+	 * using Java-import style) that this page may support.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	protected String[] getTypeIds() {
+		try {
+			List list = new ArrayList();
+			StringTokenizer st = new StringTokenizer(element.getAttribute("typeIds"), ",");
+			while (st.hasMoreTokens()) {
+				String str = st.nextToken();
+				if (str != null && str.length() > 0)
+					list.add(str.trim());
+			}
+			String[] s = new String[list.size()];
+			list.toArray(s);
+			return s;
+		} catch (Exception e) {
+			//Trace.trace("Could not get server resource from: " + element.getAttribute("serverResources"));
+			return null;
+		}
+	}
+	
+	/**
+	 * Returns true if the given server resource type (given by the
+	 * id) can be opened with this editor. This result is based on
+	 * the result of the getServerResources() method.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsType(String id) {
+		if (id == null || id.length() == 0)
+			return false;
+
+		String[] s = getTypeIds();
+		if (s == null)
+			return false;
+		
+		int size = s.length;
+		for (int i = 0; i < size; i++) {
+			if (s[i].endsWith("*")) {
+				if (id.length() >= s[i].length() && id.startsWith(s[i].substring(0, s[i].length() - 1)))
+					return true;
+			} else if (id.equals(s[i]))
+				return true;
+		}
+		return false;
+	}
+
+	/*
+	 * 
+	 */
+	public IServerEditorPageSectionFactoryDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IServerEditorPageSectionFactoryDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace("Could not create server editorpage delegate", e);
+			}
+		}
+		return delegate;
+	}
+	
+	/**
+	 * Returns true if this editor page should be visible with the given
+	 * server instance and configuration combination. This allows (for
+	 * instance) complex configuration pages to only be shown when used
+	 * with non-unittest servers.
+	 *
+	 * <p>If the instance or configuration is being opened by itself, the
+	 * other value (instance or configuration) will be null.
+	 */
+	public boolean shouldCreateSection(IServer server, IServerConfiguration serverConfiguration) {
+		try {
+			return getDelegate().shouldCreateSection(server, serverConfiguration);
+		} catch (Exception e) {
+			Trace.trace("Error calling delegate", e);
+			return false;
+		}
+	}
+
+	/**
+	 * Create the editor page.
+	 */
+	public IServerEditorSection createSection() {
+		try {
+			return getDelegate().createSection();
+		} catch (Exception e) {
+			Trace.trace("Error calling delegate", e);
+			return null;
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorPartFactory.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorPartFactory.java
new file mode 100644
index 0000000..ce5f01e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerEditorPartFactory.java
@@ -0,0 +1,205 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.ui.editor.IServerEditorPartFactory;
+import org.eclipse.wst.server.ui.editor.IServerEditorPartFactoryDelegate;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * 
+ */
+public class ServerEditorPartFactory implements IServerEditorPartFactory {
+	private IConfigurationElement element;
+	private IServerEditorPartFactoryDelegate delegate;
+
+	/**
+	 * ServerEditorPartFactory constructor comment.
+	 */
+	public ServerEditorPartFactory(IConfigurationElement element) {
+		super();
+		this.element = element;
+	}
+
+	/**
+	 * 
+	 */
+	public IConfigurationElement getConfigurationElement() {
+		return element;
+	}
+
+	/**
+	 * Returns the id of this part factory.
+	 *
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return element.getAttribute("id");
+	}
+	
+	/**
+	 * Returns the name of this part factory. 
+	 *
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		return element.getAttribute("name");
+	}
+
+	protected String[] getInsertionIds() {
+		try {
+			List list = new ArrayList();
+			StringTokenizer st = new StringTokenizer(element.getAttribute("insertionIds"), ",");
+			while (st.hasMoreTokens()) {
+				String str = st.nextToken();
+				if (str != null && str.length() > 0)
+					list.add(str.trim());
+			}
+			String[] s = new String[list.size()];
+			list.toArray(s);
+			return s;
+		} catch (Exception e) {
+			//Trace.trace("Could not get server resource from: " + element.getAttribute("serverResources"));
+			return null;
+		}
+	}
+	
+	public boolean supportsInsertionId(String id) {
+		if (id == null || id.length() == 0)
+			return false;
+
+		String[] s = getInsertionIds();
+		if (s == null)
+			return false;
+		
+		int size = s.length;
+		for (int i = 0; i < size; i++) {
+			if (s[i].endsWith("*")) {
+				if (id.length() >= s[i].length() && id.startsWith(s[i].substring(0, s[i].length() - 1)))
+					return true;
+			} else if (id.equals(s[i]))
+				return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Returns the order.
+	 *
+	 * @return int
+	 */
+	public int getOrder() {
+		try {
+			String o = element.getAttribute("order");
+			return Integer.parseInt(o);
+		} catch (NumberFormatException e) {
+			return -1;
+		}
+	}
+	
+	/**
+	 * Return the ids of the server and server configuration type ids (specified
+	 * using Java-import style) that this page may support.
+	 * 
+	 * @return java.lang.String[]
+	 */
+	protected String[] getTypeIds() {
+		try {
+			List list = new ArrayList();
+			StringTokenizer st = new StringTokenizer(element.getAttribute("typeIds"), ",");
+			while (st.hasMoreTokens()) {
+				String str = st.nextToken();
+				if (str != null && str.length() > 0)
+					list.add(str.trim());
+			}
+			String[] s = new String[list.size()];
+			list.toArray(s);
+			return s;
+		} catch (Exception e) {
+			//Trace.trace("Could not get server resource from: " + element.getAttribute("serverResources"));
+			return null;
+		}
+	}
+	
+	/**
+	 * Returns true if the given server or server configuration type id
+	 * can be opened with this editor. This result is based on
+	 * the result of the getTypeIds() method.
+	 *
+	 * @return boolean
+	 */
+	public boolean supportsType(String id) {
+		if (id == null || id.length() == 0)
+			return false;
+
+		String[] s = getTypeIds();
+		if (s == null)
+			return false;
+		
+		int size = s.length;
+		for (int i = 0; i < size; i++) {
+			if (s[i].endsWith("*")) {
+				if (id.length() >= s[i].length() && id.startsWith(s[i].substring(0, s[i].length() - 1)))
+					return true;
+			} else if (id.equals(s[i]))
+				return true;
+		}
+		return false;
+	}
+
+	public IServerEditorPartFactoryDelegate getDelegate() {
+		if (delegate == null) {
+			try {
+				delegate = (IServerEditorPartFactoryDelegate) element.createExecutableExtension("class");
+			} catch (Exception e) {
+				Trace.trace("Could not create server editorpage delegate", e);
+			}
+		}
+		return delegate;
+	}
+	
+	/**
+	 * Returns true if this editor page should be visible with the given
+	 * server and server configuration combination. This allows (for
+	 * instance) complex configuration pages to only be shown when used
+	 * with non-unittest servers.
+	 *
+	 * <p>If the server or server configuration is being opened by itself, the
+	 * other value (server or configuration) will be null.
+	 */
+	public boolean shouldCreatePage(IServer server, IServerConfiguration serverConfiguration) {
+		try {
+			return getDelegate().shouldCreatePage(server, serverConfiguration);
+		} catch (Exception e) {
+			Trace.trace("Error calling delegate", e);
+			return false;
+		}
+	}
+
+	/**
+	 * Create the editor page.
+	 */
+	public IEditorPart createPage() {
+		try {
+			return getDelegate().createPage();
+		} catch (Exception e) {
+			Trace.trace("Error calling delegate", e);
+			return null;
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerResourceCommandManager.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerResourceCommandManager.java
new file mode 100644
index 0000000..4c6132c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/ServerResourceCommandManager.java
@@ -0,0 +1,99 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.wst.server.core.IElement;
+import org.eclipse.wst.server.core.ITask;
+import org.eclipse.wst.server.ui.editor.ICommandManager;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+
+/**
+ * A command manager for a single server resource.
+ */
+public class ServerResourceCommandManager implements ICommandManager {
+	protected ServerEditor editor;
+	protected GlobalCommandManager commandManager;
+	protected String id;
+
+	public ServerResourceCommandManager(ServerEditor editor, String id, GlobalCommandManager commandManager) {
+		this.editor = editor;
+		this.commandManager = commandManager;
+		this.id = id;
+	}
+	
+	public boolean isReadOnly() {
+		return commandManager.isReadOnly(id);
+	}
+
+	/**
+	 * Execute the given command and place it in the undo stack.
+	 * If the command cannot be undone, the user will be notifed
+	 * before it is executed.
+	 *
+	 * @param command ICommand
+	 */
+	public void executeCommand(ITask command) {
+		if (!validateEdit())
+			return;
+
+		if (commandManager.isReadOnly(id)) {
+			warnReadOnly();
+			return;
+		}
+		commandManager.executeCommand(id, command);
+	}
+
+	protected void warnReadOnly() {
+		String title = ServerUIPlugin.getResource("%editorfileWarnTitle");
+		String message = ServerUIPlugin.getResource("%editorfileWarnMessage");
+		
+		MessageDialog.openWarning(editor.getEditorSite().getShell(), title, message);
+	}
+
+	/**
+	 * 
+	 */
+	protected boolean validateEdit() {
+		if (commandManager.isDirty(id))
+			return true;
+
+		IFile[] files = commandManager.getReadOnlyFiles(id);
+		if (files.length == 0)
+			return true;
+		
+		IStatus status = ResourcesPlugin.getWorkspace().validateEdit(files, editor.getEditorSite().getShell());
+		
+		if (status.getSeverity() == IStatus.ERROR) {
+			// inform user
+			String message = ServerUIPlugin.getResource("%editorValidateEditFailureMessage");
+			ErrorDialog.openError(editor.getEditorSite().getShell(), ServerUIPlugin.getResource("%errorDialogTitle"), message, status);
+			
+			// change to read-only
+			commandManager.setReadOnly(id, true);
+			
+			// do not execute command
+			return false;
+		} else {
+			// check file timestamp
+			IElement serverfile = commandManager.getServerResource(id);
+			if (commandManager.hasChanged(id))
+				editor.promptReloadServerFile(id, serverfile);
+			
+			// allow edit
+			return true;
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/StatusLineContributionItem.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/StatusLineContributionItem.java
new file mode 100644
index 0000000..b877a9a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/StatusLineContributionItem.java
@@ -0,0 +1,84 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.texteditor.IStatusField;
+/**
+ * Contribution item for the status line.
+ */
+public class StatusLineContributionItem extends ContributionItem implements IStatusField {
+
+	static class StatusLineLabel extends CLabel {
+		
+		private static int INDENT= 3; // left and right margin used in CLabel
+		
+		private Point fFixedSize;
+		
+		public StatusLineLabel(Composite parent, int style) {
+			super(parent, style);
+			
+			GC gc= new GC(parent);
+			gc.setFont(parent.getFont());
+			Point extent= gc.textExtent("MMMMMMMMM"); //$NON-NLS-1$
+			gc.dispose();
+			
+			fFixedSize= new Point(extent.x + INDENT * 2, 10);
+		}
+		
+		public Point computeSize(int wHint, int hHint, boolean changed) {
+			return fFixedSize;
+		}
+	}
+	
+	private String fText;
+	private Image fImage;
+	private StatusLineLabel fLabel;
+	
+	/**
+	 * Creates a new item with the given id.
+	 * 
+	 * @param id the item's id
+	 */
+	StatusLineContributionItem(String id) {
+		super(id);
+	}
+	
+	/*
+	 * @see IStatusField#setText
+	 */
+	public void setText(String text) {
+		fText= text;
+		if (fLabel != null && !fLabel.isDisposed()) {
+			fLabel.setText(fText);
+		}		
+	}
+	
+	/*
+	 * @see IStatusField#setImage(Image)
+	 */
+	public void setImage(Image image) {
+		fImage= image;
+		if (fLabel != null && !fLabel.isDisposed()) {
+			fLabel.setImage(fImage);
+		}
+	}
+	
+	/*
+	 * @see IContributionItem#fill(Composite)
+	 */
+	public void fill(Composite parent) {
+		fLabel= new StatusLineLabel(parent, SWT.SHADOW_IN);
+		fLabel.setData(this);
+		
+		if (fText != null)
+			fLabel.setText(fText);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/TextAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/TextAction.java
new file mode 100644
index 0000000..8a83d56
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/editor/TextAction.java
@@ -0,0 +1,264 @@
+package org.eclipse.wst.server.ui.internal.editor;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.action.Action;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Text;
+/**
+ * Text actions (cut, copy, paste) for the Web browser.
+ */
+public class TextAction extends Action {
+	protected Display display;
+	protected Clipboard clipboard;
+	protected byte type;
+
+	public static final byte CUT_ACTION = 0;
+	public static final byte COPY_ACTION = 1;
+	public static final byte PASTE_ACTION = 2;
+	
+	/**
+	 * TextAction constructor comment.
+	 */
+	protected TextAction(Display display, byte type) {
+		super("Text action: " + type);
+		this.display = display;
+		clipboard = new Clipboard(display);
+		this.type = type;
+	}
+
+	protected Control getControl() {
+		Control control = display.getFocusControl();
+		return control;
+	}
+	
+	protected Point getControlSelection() {
+		Control control = getControl();
+		if (control == null)
+			return null;
+
+		if (control instanceof Text) {
+			Text text = (Text) control;
+			return text.getSelection();
+		} else if (control instanceof Combo) {
+			Combo combo = (Combo) control;
+			return combo.getSelection();
+		} else
+			return null;
+	}
+	
+	protected void setControlSelection(Point sel) {
+		Control control = getControl();
+		if (control == null)
+			return;
+
+		if (control instanceof Text) {
+			Text text = (Text) control;
+			text.setSelection(sel);
+		} else if (control instanceof Combo) {
+			Combo combo = (Combo) control;
+			combo.setSelection(sel);
+		}
+	}
+	
+	protected String getControlText() {
+		Control control = getControl();
+		if (control == null)
+			return null;
+
+		if (control instanceof Text) {
+			Text text = (Text) control;
+			return text.getText();
+		} else if (control instanceof Combo) {
+			Combo combo = (Combo) control;
+			return combo.getText();
+		} else
+			return null;
+	}
+	
+	protected void setControlText(String text) {
+		Control control = getControl();
+		if (control == null)
+			return;
+
+		if (control instanceof Text) {
+			Text text2 = (Text) control;
+			text2.setText(text);
+		} else if (control instanceof Combo) {
+			Combo combo = (Combo) control;
+			combo.setText(text);
+		}
+	}
+	
+	/**
+	 * Copies the selected text to the clipboard.  The text will be put in the 
+	 * clipboard in plain text format.
+	 * <p>
+	 *
+	 * @exception SWTException <ul>
+	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+	 * </ul>
+	 */
+	public void copy() {
+		Point selection = getControlSelection();
+		String text = getControlText();
+		if (selection == null || text == null)
+			return;
+	
+		int length = selection.y - selection.x;
+		if (length > 0) {
+			TextTransfer plainTextTransfer = TextTransfer.getInstance();
+			try {
+				clipboard.setContents(
+					new String[] { text.substring(selection.x, selection.y) }, 
+					new Transfer[] { plainTextTransfer });
+			} catch (SWTError error) {
+				// Copy to clipboard failed. This happens when another application 
+				// is accessing the clipboard while we copy. Ignore the error.
+			}
+		}
+	}
+	
+	/**
+	 * Moves the selected text to the clipboard.  The text will be put in the 
+	 * clipboard in plain text format and RTF format.
+	 * <p>
+	 *
+	 * @exception SWTException <ul>
+	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+	 * </ul>
+	 */
+	public void cut(){
+		Point selection = getControlSelection();
+		if (selection == null)
+			return;
+
+		if (selection.y > selection.x) {
+			copy();
+			delete();
+		}
+	}
+	
+	/**
+	 * Deletes the character to the right of the caret. Delete the selected text if any.
+	 */
+	public void delete() {
+		Point selection = getControlSelection();
+		String text = getControlText();
+		if (selection == null || text == null)
+			return;
+	
+		if (selection.x != selection.y) {
+			text = text.substring(0, selection.x) + text.substring(selection.y);
+			setControlText(text);
+			setControlSelection(new Point(selection.x, selection.x));
+		}
+	}
+	
+	/** 
+	 * Replaces the selection with the clipboard text or insert the text at 
+	 * the current caret offset if there is no selection. 
+	 * If the widget has the SWT.SINGLE style and the clipboard text contains
+	 * more than one line, only the first line without line delimiters is 
+	 * inserted in the widget.
+	 * <p>
+	 *
+	 * @exception SWTException <ul>
+	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+	 * </ul>
+	 */
+	public void paste() {
+		TextTransfer transfer = TextTransfer.getInstance();
+		Point selection = getControlSelection();
+		String text = getControlText();
+		if (selection == null)
+			return;
+		
+		String newText = (String) clipboard.getContents(transfer);
+		if (newText != null && newText.length() > 0) {
+			if (text == null)
+				text = newText;
+			else
+				text = text.substring(0, selection.x) + newText + text.substring(selection.y);
+			setControlText(text);
+	
+			// set the selection to the end of the paste
+			int x = selection.x + newText.length();
+			setControlSelection(new Point(x, x));
+		}
+	}
+	
+	/**
+	 * Execute the action.
+	 */
+	public void run() {
+		if (display == null)
+			return;
+		if (type == CUT_ACTION)
+			cut();
+		else if (type == COPY_ACTION)
+			copy();
+		else if (type == PASTE_ACTION)
+			paste();
+	}
+	
+	/**
+	 * Update the actions enabled/disabled state.
+	 */
+	protected void update() {
+		if (getControl() == null) {
+			setEnabled(false);
+			return;
+		}
+		Point selection = getControlSelection();
+		String text = getControlText();
+
+		try {
+			if (type == CUT_ACTION)
+				setEnabled(text != null && text.length() > 0 && selection != null && selection.x < selection.y);
+			else if (type == COPY_ACTION)
+				setEnabled(text != null && text.length() > 0 && selection != null && selection.x < selection.y);
+			else if (type == PASTE_ACTION) {
+				Control control = getControl();
+				if (!control.isEnabled()) {
+					setEnabled(false);
+					return;
+				}
+				if (!(control instanceof Text)) {
+					setEnabled(false);
+					return;
+				}
+
+				Text text2 = (Text) control;
+				if (!text2.getEditable()) {
+					setEnabled(false);
+					return;
+				}
+				TextTransfer transfer = TextTransfer.getInstance();
+				String newText = (String) clipboard.getContents(transfer);
+				setEnabled(newText != null && newText.length() > 0);
+			}
+		} catch (Exception e) {
+			Trace.trace("Error updating text action", e);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/ModuleDeletedResourceFolder.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/ModuleDeletedResourceFolder.java
new file mode 100644
index 0000000..6a38e2a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/ModuleDeletedResourceFolder.java
@@ -0,0 +1,50 @@
+package org.eclipse.wst.server.ui.internal.publish;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.wst.server.core.model.IModule;
+/**
+ * Folder of deleted resources for a project.
+ */
+public class ModuleDeletedResourceFolder {
+	protected IModule module;
+	
+	/**
+	 * ProjectDeletedResourceFolder constructor comment.
+	 */
+	public ModuleDeletedResourceFolder(IModule module) {
+		super();
+		this.module = module;
+	}
+
+	/**
+	 * Returns true if the object is equal to this one.
+	 *
+	 * @param obj java.lang.Object
+	 * @return boolean
+	 */
+	public boolean equals(Object obj) {
+		if (!(obj instanceof ModuleDeletedResourceFolder))
+			return false;
+
+		ModuleDeletedResourceFolder folder = (ModuleDeletedResourceFolder) obj;
+		return (module != null && module.equals(folder.getModule()));
+	}
+
+	/**
+	 * Returns the project.
+	 *
+	 * @return org.eclipse.core.resources.IProject
+	 */
+	public IModule getModule() {
+		return module;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/ModuleRemoteResource.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/ModuleRemoteResource.java
new file mode 100644
index 0000000..55eb582
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/ModuleRemoteResource.java
@@ -0,0 +1,84 @@
+package org.eclipse.wst.server.ui.internal.publish;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.resources.IRemoteResource;
+/**
+ * Helper class to keep a reference to the project that a
+ * remote resource belongs to.
+ */
+public class ModuleRemoteResource {
+	protected IRemoteResource remote;
+	protected ModuleDeletedResourceFolder folder;
+	protected IModule module;
+
+	/**
+	 * ProjectRemoteResource constructor comment.
+	 */
+	public ModuleRemoteResource(ModuleDeletedResourceFolder folder, IModule module, IRemoteResource remote) {
+		super();
+		this.folder = folder;
+		this.module = module;
+		this.remote = remote;
+	}
+
+	/**
+	 * Returns true if the object is equal to this one.
+	 *
+	 * @param obj java.lang.Object
+	 * @return boolean
+	 */
+	public boolean equals(Object obj) {
+		if (!(obj instanceof ModuleRemoteResource))
+			return false;
+
+		ModuleRemoteResource remote2 = (ModuleRemoteResource) obj;
+		return (module != null && module.equals(remote2.getModule()) &&
+			remote != null && remote.equals(remote2.getRemote()));
+	}
+
+	/**
+	 * Returns the folder.
+	 *
+	 * @return 
+	 */
+	public ModuleDeletedResourceFolder getFolder() {
+		return folder;
+	}
+
+	/**
+	 * Returns the project.
+	 *
+	 * @return org.eclipse.core.resources.IProject
+	 */
+	public IModule getModule() {
+		return module;
+	}
+
+	/**
+	 * Returns the remote resource.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IRemoteResource
+	 */
+	public IRemoteResource getRemote() {
+		return remote;
+	}
+
+	/**
+	 * Converts to a String.
+	 *
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return remote.toString();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishDialog.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishDialog.java
new file mode 100644
index 0000000..545608f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishDialog.java
@@ -0,0 +1,849 @@
+package org.eclipse.wst.server.ui.internal.publish;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.lang.reflect.InvocationTargetException;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.ProgressIndicator;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.operation.ModalContext;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.wst.server.core.IPublishManager;
+import org.eclipse.wst.server.core.IPublishStatus;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerPreferences;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IPublishListener;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+import org.eclipse.wst.server.core.resources.IRemoteResource;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ContextIds;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+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.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+/**
+ * A modal dialog for publishing.
+ */
+public class PublishDialog extends Dialog implements IRunnableContext {
+	// name to use for task when normal task name is empty string.
+	protected static final String DEFAULT_TASKNAME = JFaceResources.getString("ProgressMonitorDialog.message"); //$NON-NLS-1$
+
+	// The progress indicator control.
+	protected ProgressIndicator progressIndicator;
+
+	// The label control for the task.
+	protected Label taskLabel;
+
+	// The label control for the subtask.
+	protected Label subTaskLabel;
+
+	// list of previous tasks
+	protected ArrayList taskList;
+
+	protected Table statusTable;
+	protected TableItem currentTableItem = null;
+
+	// buttons
+	protected Button cancel;
+	protected Button ok;
+	protected Button detailsButton;
+
+	protected Composite details;
+	protected boolean detailsVisible;
+	protected static IStatus globalStatus;
+
+	protected boolean remainOpen = false;
+	protected boolean showCancel = false;
+
+	protected WorkbenchLabelProvider workbenchLabelProvider;
+
+	// The progress monitor.
+	protected ProgressMonitor progressMonitor = new ProgressMonitor();
+
+	// The name of the current task (used by ProgressMonitor).
+	protected String task;
+
+	// The number of currently running runnables.
+	private int runningRunnables;
+
+	// The cursors used.
+	private Cursor cancelArrowCursor;
+
+	// The cursor used in the shell;
+	private Cursor waitCursor;
+
+	protected List publishInfo = new ArrayList();
+
+	// Internal progress monitor implementation.
+	private class ProgressMonitor implements IProgressMonitor {
+
+		private String fSubTask= "";//$NON-NLS-1$
+		private boolean fIsCanceled;
+
+		public void beginTask(String name, int totalWork) {
+			if (progressIndicator.isDisposed())
+				return;
+
+			if (name == null)
+				task = "";//$NON-NLS-1$
+			else
+				task = name;
+
+			String s = task;
+			if (s.length() <= 0)
+				s = DEFAULT_TASKNAME;
+			taskLabel.setText(s);
+
+			if (totalWork == UNKNOWN)
+				progressIndicator.beginAnimatedTask();
+			else
+				progressIndicator.beginTask(totalWork);
+		}
+
+		public void done() {
+			if (!progressIndicator.isDisposed()) {
+				progressIndicator.sendRemainingWork();
+				//progressIndicator.done();
+				ok.setEnabled(true);
+				ok.setFocus();
+			}
+		}
+
+		public void setTaskName(final String name) {
+			if (taskLabel.isDisposed())
+				return;
+			if (name == null)
+				task = "";//$NON-NLS-1$
+			else
+				task = name;
+
+			String s = task;
+			if (s.length() <= 0)
+				s= DEFAULT_TASKNAME;
+			taskLabel.setText(s);
+		}
+	
+		public boolean isCanceled() {
+			return fIsCanceled;
+		}
+
+		public void setCanceled(boolean b) {
+			fIsCanceled = b;
+		}
+
+		public void subTask(final String name) {
+			if (subTaskLabel.isDisposed())
+				return;
+				
+			if (name == null)
+				fSubTask = "";//$NON-NLS-1$
+			else
+				fSubTask = name;
+
+			subTaskLabel.setText(fSubTask);
+		}
+
+		public void worked(int work) {
+			internalWorked(work);
+		}
+
+		public void internalWorked(double work) {
+			if (!progressIndicator.isDisposed())
+				progressIndicator.worked(work);
+		}
+	}
+
+	/**
+	 * Creates a progress monitor dialog under the given shell.
+	 * The dialog has a standard title and no image. 
+	 * <code>open</code> is non-blocking.
+	 *
+	 * @param parent the parent shell
+	 */
+	public PublishDialog(Shell parent, boolean keepOpen) {
+		super(parent);
+		setShellStyle(SWT.BORDER | SWT.TITLE | SWT.APPLICATION_MODAL | SWT.RESIZE); // no close button
+		setBlockOnOpen(false);
+		taskList = new ArrayList();
+	
+		remainOpen = keepOpen;
+		if (!remainOpen) // part of a bigger task
+			showCancel = true;
+		
+		workbenchLabelProvider = new WorkbenchLabelProvider();
+	}
+
+	/**
+	 * Add a single publish event to the UI.
+	 *
+	 * @param status org.eclipse.core.runtime.IStatus
+	 */
+	protected void addPublishEvent(final IModule module, final IStatus status) {
+		Trace.trace(Trace.FINEST, "PublishDialog.addPublishEvent: " + module + " " + status);
+		if (status != null && !status.isOK())
+			remainOpen = true;
+	
+		if (module == null) {
+			if (status != null)
+				globalStatus = status;
+			return;
+		}
+	
+		if (status == null) {
+			getShell().getDisplay().asyncExec(new Runnable() {
+				public void run() {
+					currentTableItem = new TableItem(statusTable, SWT.NONE);
+					currentTableItem.setImage(new Image[] {ServerUICore.getLabelProvider().getImage(module)});
+					currentTableItem.setText(new String[] {ServerUICore.getLabelProvider().getText(module), ServerUIPlugin.getResource("%publishingBusy")});
+				}
+			});
+		} else {
+			getShell().getDisplay().asyncExec(new Runnable() {
+				public void run() {
+					currentTableItem.setImage(1, getStatusImage(status));
+					currentTableItem.setText(1, getStatusText(status));
+				}
+			});
+		}
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on Dialog.
+	 * Handles the pressing of the Ok or Details button in this dialog.
+	 * If the Ok button was pressed then close this dialog.  If the Details
+	 * button was pressed then toggle the displaying of the error details area.
+	 * Note that the Details button will only be visible if the error being
+	 * displayed specifies child details.
+	 */
+	protected void buttonPressed(int id) {
+		if (id == IDialogConstants.DETAILS_ID) // was the details button pressed?
+			toggleDetailsArea();
+		else
+			super.buttonPressed(id);
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on Window.
+	 */
+	public boolean close() {
+		if (runningRunnables <= 0) {
+			workbenchLabelProvider.dispose();
+		
+			cancel.setCursor(null);
+			getShell().setCursor(null);
+			if (cancelArrowCursor != null)
+				cancelArrowCursor.dispose();
+			cancelArrowCursor = null;
+	
+			// Make sure that all events in the asynchronous event queue
+			// are dispatched.
+			Display display = getShell().getDisplay();
+			display.syncExec(new Runnable() {
+				public void run() {
+					// do nothing
+				}
+			});
+					
+			// Stop event dispatching
+			Cursor temp = waitCursor;
+			waitCursor = null;
+					
+			// Force the event loop to return from sleep () so that
+			// it stops event dispatching.
+			display.asyncExec(null);
+	
+			try {
+				synchronized (temp) {
+					temp.notifyAll();
+				}
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error notifying publish dialog closure", e);
+			}
+			if (temp != null)
+				temp.dispose();
+			return super.close();
+		}
+		return false;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared in Window.
+	 */
+	protected void configureShell(Shell shell) {
+		super.configureShell(shell);
+		shell.setText(ServerUIPlugin.getResource("%publishingTitle"));
+		if (waitCursor == null)
+			waitCursor = new Cursor(shell.getDisplay(), SWT.CURSOR_WAIT);
+		shell.setCursor(waitCursor);
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on Dialog.
+	 */
+	protected void createButtonsForButtonBar(Composite parent) {
+		ok = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, false);
+		//ok.setCursor(arrowCursor);
+		ok.setEnabled(false);
+		
+		// cancel button
+		cancel = createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, true);
+		if (cancelArrowCursor == null)
+			cancelArrowCursor = new Cursor(cancel.getDisplay(), SWT.CURSOR_ARROW);
+		cancel.setCursor(cancelArrowCursor);
+		cancel.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event e) {
+				remainOpen = true;
+				cancel.setEnabled(false);
+				progressMonitor.setCanceled(true);
+			}
+		});
+	
+		detailsButton = createButton(parent, IDialogConstants.DETAILS_ID, IDialogConstants.SHOW_DETAILS_LABEL, false);
+		detailsButton.setEnabled(false);
+		WorkbenchHelp.setHelp(detailsButton, ContextIds.PUBLISH_DETAILS_DIALOG_DETAILS_BUTTON);
+	}
+	
+	/**
+	 * Create this dialog's drop-down list component.
+	 *
+	 * @param parent the parent composite
+	 * @return the drop-down list component
+	 */
+	protected Composite createDetails(Composite parent) {
+		Color bg = getShell().getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+		Font font = JFaceResources.getFontRegistry().get(JFaceResources.BANNER_FONT);
+	
+		details = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+		details.setLayout(layout);
+	
+		GridData data = new GridData(
+			GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL |
+			GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL);
+		data.heightHint = 300;
+		details.setLayoutData(data);
+		
+		// Create the title area which will contain
+		// a title, message, and image.
+		ScrolledComposite sc = new ScrolledComposite(details, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+		data = new GridData(
+			GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL |
+			GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL);
+		sc.setLayoutData(data);
+	
+		Composite infoArea = new Composite(sc, SWT.NONE);
+		layout = new GridLayout();
+		layout.marginHeight = 5;
+		layout.verticalSpacing = 0;
+		layout.numColumns = 2;
+		infoArea.setLayout(layout);
+		data = new GridData(
+			GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL |
+			GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL);
+		infoArea.setLayoutData(data);
+		infoArea.setBackground(bg);
+		WorkbenchHelp.setHelp(infoArea, ContextIds.PUBLISH_DETAILS_DIALOG_DETAILS);
+	
+		// fill in the details
+		if (globalStatus != null) {
+		IStatus[] children = globalStatus.getChildren();
+		if (children != null) {
+			int size = children.length;
+			for (int i = 0; i < size; i++) {
+				IStatus status = children[i];
+	
+				if (status != null) {
+	
+				if (status instanceof IPublishStatus) {
+					IPublishStatus ps = (IPublishStatus) status;
+					createPublishStatusDetails(ps, infoArea);
+				} else {
+					String title = null;
+					title = status.getMessage();
+			
+					Label label = new Label(infoArea, SWT.NONE);
+					label.setBackground(bg);
+	
+					label = new Label(infoArea, SWT.NONE);
+					label.setText(title);
+					label.setFont(font);
+					label.setBackground(bg);
+	
+					IStatus[] status2 = status.getChildren();
+					if (status2 != null && status2.length > 0) {
+						label = new Label(infoArea, SWT.NONE); // spacer
+		
+						StyledText styledText = new StyledText(infoArea, SWT.MULTI | SWT.READ_ONLY);
+						styledText.setCursor(null);
+						styledText.getCaret().setVisible(false);
+						styledText.setBackground(bg);
+	
+						StringBuffer sb = new StringBuffer();
+						int size2 = status2.length;
+						for (int j = 0; j < size2; j++)
+							if (status2[j] != null)
+								sb.append(status2[j].getMessage() + "\n");
+	
+						styledText.setText(sb.toString());
+						data = new GridData(GridData.FILL_HORIZONTAL);
+						styledText.setLayoutData(data);
+					}
+	
+					// add final status, indented
+					label = new Label(infoArea, SWT.NONE); // spacer
+		
+					Composite statusComp = new Composite(infoArea, SWT.NONE);
+					layout = new GridLayout();
+					layout.numColumns = 2;
+					layout.marginHeight = 4;
+					layout.marginWidth = 0;
+					layout.verticalSpacing = 0;
+					layout.horizontalSpacing = 4;
+					statusComp.setLayout(layout);
+					statusComp.setBackground(bg);
+	
+					label = new Label(statusComp, SWT.NONE);
+					label.setBackground(bg);
+					label.setImage(getStatusImage(status));
+	
+					label = new Label(statusComp, SWT.NONE);
+					label.setBackground(bg);
+					label.setText(getStatusText(status));
+				}
+				}
+			}
+		}
+		}
+	
+		detailsVisible = true;
+	
+		sc.setContent(infoArea);
+		Point p = infoArea.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
+		sc.setMinHeight(p.y);
+		sc.setMinWidth(p.x);
+		sc.setExpandHorizontal(true);
+		sc.setExpandVertical(true);
+	
+		return details;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on Dialog.
+	 */
+	protected Control createDialogArea(Composite parent) {
+		Composite c = (Composite) super.createDialogArea(parent);
+		((GridLayout) c.getLayout()).numColumns = 2;
+		((GridData) c.getLayoutData()).widthHint = 450;
+		WorkbenchHelp.setHelp(c, ContextIds.PUBLISH_DETAILS_DIALOG);
+	
+		// icon
+		Label iconLabel = new Label(c, SWT.LEFT);
+		GridData gd = new GridData();
+		iconLabel.setLayoutData(gd);
+		iconLabel.setFont(parent.getFont());
+		Image i = iconLabel.getDisplay().getSystemImage(SWT.ICON_INFORMATION);
+		if (i != null)
+			iconLabel.setImage(i);
+		else
+			iconLabel.setText(JFaceResources.getString("Image_not_found")); //$NON-NLS-1$
+	
+		// label on right hand side of icon
+		taskLabel = new Label(c, SWT.LEFT | SWT.WRAP);
+		taskLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		taskLabel.setText(DEFAULT_TASKNAME);
+		taskLabel.setFont(parent.getFont());
+	
+		statusTable = new Table(c, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY | SWT.FULL_SELECTION);
+		gd = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL);
+		gd.heightHint = 55;
+		gd.horizontalSpan = 2;
+		statusTable.setLayoutData(gd);
+		statusTable.setHeaderVisible(false);
+		statusTable.setLinesVisible(false);
+		WorkbenchHelp.setHelp(statusTable, ContextIds.PUBLISH_DETAILS_DIALOG_STATUS);
+	
+		// add columns
+		TableColumn column = new TableColumn(statusTable, SWT.SINGLE);
+		column.setWidth(175);
+	
+		column = new TableColumn(statusTable, SWT.SINGLE);
+		column.setWidth(225);
+	
+		// progress indicator
+		progressIndicator = new ProgressIndicator(c);
+		gd = new GridData();
+		gd.heightHint = 15;
+		gd.horizontalAlignment = GridData.FILL;
+		gd.grabExcessHorizontalSpace = true;
+		gd.horizontalSpan = 2;
+		progressIndicator.setLayoutData(gd);
+	
+		// label showing current task
+		subTaskLabel = new Label(c, SWT.LEFT | SWT.WRAP);
+		gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.heightHint = 40;	
+		gd.horizontalSpan = 2;
+		subTaskLabel.setLayoutData(gd);
+		subTaskLabel.setFont(parent.getFont());
+		
+		Dialog.applyDialogFont(c);
+	
+		return c;
+	}
+	
+	/**
+	 * 
+	 * @param comp org.eclipse.swt.widgets.Composite
+	 */
+	protected void createPublishStatusDetails(IPublishStatus status, Composite infoArea) {
+		Color bg = getShell().getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+		Font font = JFaceResources.getFontRegistry().get(JFaceResources.BANNER_FONT);
+	
+		String title = null;
+		Image image = null;
+		title = status.getMessage();
+		image = ServerUICore.getLabelProvider().getImage(status.getModule());
+	
+		Label label = new Label(infoArea, SWT.NONE);
+		label.setImage(image);
+		label.setBackground(bg);
+	
+		Composite comp = new Composite(infoArea, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginHeight = 2;
+		layout.marginWidth = 0;
+		layout.verticalSpacing = 2;
+		layout.horizontalSpacing = 0;
+		comp.setLayout(layout);
+		comp.setBackground(bg);
+	
+		label = new Label(comp, SWT.NONE);
+		label.setText(title);
+		label.setFont(font);
+		label.setBackground(bg);
+	
+		IStatus[] status2 = status.getChildren();
+		if (status2 != null) {
+			int size2 = status2.length;
+			for (int j = 0; j < size2; j++) {
+				if (status2[j] != null) {
+					label = new Label(infoArea, SWT.NONE); // spacer
+		
+					StyledText styledText = new StyledText(infoArea, SWT.MULTI | SWT.READ_ONLY);
+					styledText.setCursor(null);
+					styledText.getCaret().setVisible(false);
+					styledText.setBackground(bg);
+					String text = status2[j].getMessage();
+					//if (!status2[j].isOK()) {
+						IStatus[] children = status2[j].getChildren();
+						if (children != null && children.length > 0)
+							for (int k = 0; k < children.length; k++) {
+								text += "\n\t" + children[k].getMessage();
+							}
+						styledText.setForeground(getStatusColor(status2[j]));
+					//}
+		
+					styledText.setText(text);
+					GridData data = new GridData(GridData.FILL_HORIZONTAL);
+					styledText.setLayoutData(data);
+				}
+			}
+		}
+	
+		// add final status, indented
+		label = new Label(infoArea, SWT.NONE); // spacer
+	
+		Composite statusComp = new Composite(infoArea, SWT.NONE);
+		layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.marginHeight = 4;
+		layout.marginWidth = 0;
+		layout.verticalSpacing = 0;
+		layout.horizontalSpacing = 4;
+		statusComp.setLayout(layout);
+		statusComp.setBackground(bg);
+	
+		label = new Label(statusComp, SWT.NONE);
+		label.setBackground(bg);
+		label.setImage(getStatusImage(status));
+	
+		label = new Label(statusComp, SWT.NONE);
+		label.setBackground(bg);
+		String text = getStatusText(status);
+	
+		long time = status.getTime();
+		if (time > 5) {
+			NumberFormat format = NumberFormat.getNumberInstance();
+			format.setMinimumFractionDigits(2);
+			format.setMaximumFractionDigits(2);
+			text += " (" + ServerUIPlugin.getResource("%publishingTime", format.format(time / 1000.0)) + ")";
+		}
+	
+		label.setText(text);
+	}
+
+	/**
+	 * Returns the progress monitor to use for operations run in 
+	 * this progress dialog.
+	 *
+	 * @return the progress monitor
+	 */
+	public IProgressMonitor getProgressMonitor() {
+		return progressMonitor;
+	}
+	
+	/**
+	 * 
+	 * @return java.lang.String
+	 * @param status org.eclipse.core.runtime.IStatus
+	 */
+	protected Color getStatusColor(IStatus status) {
+		switch (status.getSeverity()) {
+			case IStatus.OK:
+				return getShell().getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+			case IStatus.INFO:
+				return getShell().getDisplay().getSystemColor(SWT.COLOR_DARK_BLUE);
+			case IStatus.WARNING:
+				return getShell().getDisplay().getSystemColor(SWT.COLOR_DARK_MAGENTA);
+			case IStatus.ERROR:
+				return getShell().getDisplay().getSystemColor(SWT.COLOR_DARK_RED);
+		}
+		return null;
+	}
+	
+	/**
+	 * 
+	 * @return java.lang.String
+	 * @param status org.eclipse.core.runtime.IStatus
+	 */
+	protected static Image getStatusImage(IStatus status) {
+		ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
+		switch (status.getSeverity()) {
+			case IStatus.OK:
+				return sharedImages.getImage(ISharedImages.IMG_OBJS_INFO_TSK);
+			case IStatus.INFO:
+				return sharedImages.getImage(ISharedImages.IMG_OBJS_INFO_TSK);
+			case IStatus.WARNING:
+				return sharedImages.getImage(ISharedImages.IMG_OBJS_WARN_TSK);
+			case IStatus.ERROR:
+				return sharedImages.getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
+		}
+		return null;
+	}
+	
+	/**
+	 * 
+	 * @return java.lang.String
+	 * @param status org.eclipse.core.runtime.IStatus
+	 */
+	protected static String getStatusText(IStatus status) {
+		if (status == null)
+			return "n/a";
+	
+		switch (status.getSeverity()) {
+			case IStatus.OK:
+				return ServerUIPlugin.getResource("%publishingOK");
+			case IStatus.INFO:
+				return ServerUIPlugin.getResource("%publishingInfo");
+			case IStatus.WARNING:
+				return ServerUIPlugin.getResource("%publishingWarning");
+			case IStatus.ERROR:
+				return ServerUIPlugin.getResource("%publishingError");
+		}
+		return "getStatusText() invalid";
+	}
+	
+	/**
+	 * Publish to the given server instance control using the current publisher.
+	 *
+	 * @param control org.eclipse.wst.server.core.IServerControl
+	 * @param keepOpen boolean
+	 */
+	public static IStatus publish(Shell shell, final IServer server2, boolean keepOpen) {
+		globalStatus = null;
+	
+		// create listener
+		IPublishListener listener = null;
+	
+		// publish the code
+		try {
+			final PublishDialog dialog = new PublishDialog(shell, keepOpen);
+	
+			listener = new IPublishListener() {
+				public void moduleStateChange(IServer server, List parents, IModule module) { }
+	
+				public void publishStarting(IServer server, List[] parents, IModule[] modules) { }
+				
+				public void publishStarted(IServer server, IPublishStatus status) {
+					dialog.addPublishEvent(null, status);
+				}
+	
+				public void moduleStarting(IServer server, List parents, IModule module) {
+					dialog.addPublishEvent(module, null);
+				}
+	
+				public void moduleResourcesPublished(IServer server, List parents, IModule module, IModuleResource[] published, IPublishStatus[] status) { }
+				
+				public void moduleResourcesDeleted(IServer server, List parents, IModule module, IRemoteResource[] deleted, IPublishStatus[] status) { }
+	
+				public void moduleFinished(IServer server, List parents, IModule module, IPublishStatus status) {
+					dialog.addPublishEvent(module, status);
+				}
+	
+				public void publishFinished(IServer server, IPublishStatus globalStatus2) {
+					dialog.addPublishEvent(null, globalStatus2);
+				}
+			};
+	
+			server2.addPublishListener(listener);
+	
+			IRunnableWithProgress runnable = new IRunnableWithProgress() {
+				public void run(IProgressMonitor monitor) {
+					IServerPreferences preferences = ServerCore.getServerPreferences();
+					IPublishManager publisher = (IPublishManager) ServerCore.getPublishManagers().get(preferences.getPublishManager());
+					if (publisher == null)
+						publisher = (IPublishManager) ServerCore.getPublishManagers().get(preferences.getDefaultPublishManager());
+	
+					globalStatus = server2.publish(publisher, monitor);
+					Trace.trace(Trace.FINEST, "Publishing done: " + globalStatus);
+				}
+			};
+	
+			dialog.run(true, true, runnable);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error in publishing dialog", e);
+			return new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerUIPlugin.getResource("%errorPublishing"), e);
+		} finally {
+			server2.removePublishListener(listener);
+		}
+	
+		return globalStatus;
+	}
+	
+	/* (non-Javadoc)
+	 * Method declared on IRunnableContext.
+	 * Runs the given <code>IRunnableWithProgress</code> with the progress monitor for this
+	 * progress dialog.  The dialog is opened before it is run, and closed after it completes.
+	 */
+	public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException {
+		open();
+		try {
+			runningRunnables++;
+			ModalContext.run(runnable, fork, getProgressMonitor(), getShell().getDisplay());
+		} finally {	
+			runningRunnables--;
+			if (remainOpen || ServerUICore.getPreferences().getShowPublishingDetails()) {
+				try {
+					updateTaskLabel();
+					cancel.setEnabled(showCancel);
+					ok.setEnabled(true);
+					detailsButton.setEnabled(true);
+					subTaskLabel.setText("");
+					progressIndicator.setEnabled(false);
+					getShell().setCursor(null);
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Error reseting publishing dialog", e);
+				}
+			} else
+				close();
+	
+			if (waitCursor != null)
+				waitForClose();
+		}
+	}
+	
+	/**
+	 * Toggles the unfolding of the details area.  This is triggered by
+	 * the user pressing the details button.
+	 */
+	private void toggleDetailsArea() {
+		Point windowSize = getShell().getSize();
+		Point windowComputeSize = getContents().computeSize(SWT.DEFAULT, SWT.DEFAULT);
+		
+		if (detailsVisible) {
+			details.dispose();
+			detailsVisible = false;
+			detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL);
+		} else {
+			details = createDetails((Composite)getContents());
+			detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL);
+		}
+	
+		Point newSize = getContents().computeSize(SWT.DEFAULT, SWT.DEFAULT);
+		int height = Math.max(newSize.y, windowSize.y + (newSize.y - windowComputeSize.y));
+		
+		getShell().setSize(new Point(windowSize.x, height));
+	}
+	
+	/**
+	 * 
+	 */
+	protected void updateTaskLabel() {
+		if (getProgressMonitor().isCanceled())
+			taskLabel.setText(ServerUIPlugin.getResource("%publishingCancelled"));
+		else
+			taskLabel.setText(getStatusText(globalStatus));
+	}
+	
+	/**
+	 * 
+	 */
+	private void waitForClose() {
+		// keep the dialog open...
+		
+		Display display = getShell().getDisplay();
+		if (display == Display.getCurrent()) {
+			while (waitCursor != null) {
+				if (!display.readAndDispatch())
+					display.sleep();
+			}
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishTableTreeViewer.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishTableTreeViewer.java
new file mode 100644
index 0000000..e274715
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishTableTreeViewer.java
@@ -0,0 +1,272 @@
+package org.eclipse.wst.server.ui.internal.publish;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.CheckboxCellEditor;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.TableTreeViewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.custom.TableTree;
+import org.eclipse.swt.custom.TableTreeItem;
+
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.resources.IModuleFolder;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+import org.eclipse.wst.server.core.resources.IRemoteFolder;
+import org.eclipse.wst.server.core.resources.IRemoteResource;
+/**
+ * Publish tree viewer.
+ */
+public class PublishTableTreeViewer extends TableTreeViewer {
+	protected VisualPublisher visualPublisher;
+	protected PublishViewerFilter filter;
+
+	/**
+	 * PublishTableTreeViewer constructor comment.
+	 * @param tree org.eclipse.swt.custom.TableTree
+	 */
+	public PublishTableTreeViewer(TableTree tree, VisualPublisher visualPublisher2) {
+		super(tree);
+		this.visualPublisher = visualPublisher2;
+	
+		setContentProvider(new PublishTreeContentProvider(visualPublisher));
+		setLabelProvider(new PublishTreeLabelProvider(visualPublisher));
+		setInput(visualPublisher.getModules());
+		setSorter(new ViewerSorter() {
+			public int category(Object element) {
+				if (element instanceof IModuleFolder)
+					return 0;
+				else if (element instanceof IModuleResource)
+					return 1;
+				else if (element instanceof IRemoteFolder)
+					return 0;
+				else if (element instanceof IRemoteResource)
+					return 1;
+				else
+					return 2;
+			}
+		});
+	
+		filter = new PublishViewerFilter(visualPublisher);
+		addFilter(filter);
+	
+		setColumnProperties(new String[] {"local", "remote", "status", "action"});
+		setCellEditors(new CellEditor[] {null, null, null, new CheckboxCellEditor(tree)});
+	
+		ICellModifier cellModifier = new ICellModifier() {
+			public Object getValue(Object element, String property) {
+				//Trace.trace("getValue " + element + " " + property);
+	
+				if (element instanceof IModuleResource) {
+					IModuleResource resource = (IModuleResource) element;
+					IPath path = visualPublisher.getPublishControl(resource.getModule()).getMappedLocation(resource);
+					if (path == null || path.toString() == null)
+						return new Boolean(false);
+					else {
+						if (visualPublisher.getResourcesToPublish(resource.getModule()).contains(resource))
+							return new Boolean(true);
+						else
+							return new Boolean(false);
+					}
+				} else if (element instanceof ModuleRemoteResource) {
+					ModuleRemoteResource prr = (ModuleRemoteResource) element;
+					IRemoteResource remote = prr.getRemote();
+					IPath path = remote.getPath();
+					if (path == null || path.toString() == null)
+						return new Boolean(false);
+					else {
+						IModule module = prr.getModule();
+						if (visualPublisher.getResourcesToDelete(module).contains(remote))
+							return new Boolean(true);
+						else
+							return new Boolean(false);
+					}
+				}
+				return new Boolean(false);
+			}
+	
+			public boolean canModify(Object element, String property) {
+				//Trace.trace("canModify " + element + " " + property);
+				if ("action".equals(property)) {
+					// check that it is mapped!!
+					if (element instanceof IModuleResource) {
+						IModuleResource resource = (IModuleResource) element;
+						IPath path = visualPublisher.getPublishControl(resource.getModule()).getMappedLocation(resource);
+						if (path == null)
+							return false;
+						if (resource instanceof IModuleFolder) {
+							byte status = visualPublisher.getResourceStatus(resource, path);
+							if (status != VisualPublisher.STATUS_NEW)
+								return false;
+						}
+						return true;
+					} else
+						return true;
+				}
+				else
+					return false;
+			}
+	
+			public void modify(Object element, String property, Object value) {
+				if (!"action".equals(property))
+					return;
+	
+				TableTreeItem tti = (TableTreeItem) element;
+				Object obj = tti.getData();
+				//Trace.trace("modify " + element + " " + property + " " + value + " " + obj);
+				boolean val = ((Boolean) value).booleanValue();
+	
+				if (obj instanceof IModuleResource) {
+					IModuleResource resource = (IModuleResource) obj;
+					IModule module = resource.getModule();
+					List publishList = visualPublisher.getResourcesToPublish(module);
+					if (val) {
+						publishList.add(resource);
+						handlePublishResource(module, publishList, resource);
+					} else {
+						publishList.remove(resource);
+						if (resource instanceof IModuleFolder)
+							handleUnpublishContainer(module, publishList, (IModuleFolder) resource);
+					}
+				} else if (obj instanceof ModuleRemoteResource) {
+					ModuleRemoteResource prr = (ModuleRemoteResource) obj;
+					IRemoteResource remote = prr.getRemote();
+					IModule module = prr.getModule();
+					List deleteList = visualPublisher.getResourcesToDelete(module);
+					if (val) {
+						deleteList.add(remote);
+						if (remote instanceof IRemoteFolder)
+							handleDeleteRemoteFolder(module, deleteList, prr.getFolder(), (IRemoteFolder) remote);
+					} else {
+						deleteList.remove(remote);
+						handleUndeleteRemoteResource(module, deleteList, prr.getFolder(), remote);
+					}
+				}
+				refresh(obj);
+			}
+		};
+		setCellModifier(cellModifier);
+		expandToLevel(3);
+	}
+
+	/**
+	 * Returns the filter.
+	 *
+	 * @return org.eclipse.wst.server.ui.internal.publish.PublishViewerFilter
+	 */
+	public PublishViewerFilter getFilter() {
+		return filter;
+	}
+
+	/**
+	 * Handles a deletion by making sure that the child resources
+	 * are also deleted.
+	 *
+	 * @param remote IRemoteResource
+	 */
+	protected void handleDeleteRemoteFolder(IModule module, List deleteList, ModuleDeletedResourceFolder folder, IRemoteFolder remoteFolder) {
+		Iterator iterator = remoteFolder.getContents().iterator();
+		while (iterator.hasNext()) {
+			IRemoteResource remote = (IRemoteResource) iterator.next();
+	
+			if (!deleteList.contains(remote)) {
+				deleteList.add(remote);
+				refresh(new ModuleRemoteResource(folder, module, remote));
+			}
+			if (remote instanceof IRemoteFolder)
+				handleDeleteRemoteFolder(module, deleteList, folder, (IRemoteFolder) remote);
+		}
+	}
+
+	/**
+	 * Handles a file publishing by making sure that the
+	 * parent directories are published.
+	 * !Should really check remote parent instead of local parent!
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 */
+	protected void handlePublishResource(IModule module, List publishList, IModuleResource resource) {
+		IModuleFolder container = resource.getParent();
+		while (container != null) {
+			IPath path = visualPublisher.getPublishControl(module).getMappedLocation(container);
+			if (path != null) {
+				byte status = visualPublisher.getResourceStatus(container, path);
+				if (status == VisualPublisher.STATUS_NEW && !publishList.contains(container)) {
+					publishList.add(container);
+					refresh(container);
+				}
+			}
+			container = container.getParent();
+		}
+	}
+	
+	/**
+	 * Handles a deletion by making sure that the parent resources
+	 * are also deleted.
+	 *
+	 * @param remote IRemoteResource
+	 */
+	protected void handleUndeleteRemoteResource(IModule module, List deleteList, ModuleDeletedResourceFolder folder, IRemoteResource remote) {
+		IRemoteFolder remoteFolder = remote.getParent();
+		while (remoteFolder != null) {
+			if (deleteList.contains(remoteFolder)) {
+				deleteList.remove(remoteFolder);
+				refresh(new ModuleRemoteResource(folder, module, remoteFolder));
+			}
+	
+			remoteFolder = remoteFolder.getParent();
+		}
+	}
+
+	/**
+	 * Handles a container not being published by deselecting anything
+	 * in the container,
+	 * !Should really check remote children instead of local children!
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 */
+	protected void handleUnpublishContainer(IModule module, List publishList, IModuleFolder container) {
+		IModuleResource[] children = null;
+		try {
+			children = container.members();
+		} catch (Exception e) {
+		}
+		if (children == null)
+			return;
+	
+		int size = children.length;
+		for (int i = 0; i < size; i++) {
+			IPath path = visualPublisher.getPublishControl(module).getMappedLocation(children[i]);
+			if (path != null && publishList.contains(children[i])) {
+				publishList.remove(children[i]);
+				refresh(children[i]);
+			}
+	
+			if (children[i] instanceof IModuleFolder)
+				handleUnpublishContainer(module, publishList, (IModuleFolder) children[i]);
+		}
+	}
+
+	/**
+	 * Updates the filter.
+	 *
+	 * @param filter org.eclipse.wst.server.ui.internal.publish.PublishViewerFilter
+	 */
+	public void updateFilter() {
+		removeFilter(filter);
+		addFilter(filter);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishTreeContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishTreeContentProvider.java
new file mode 100644
index 0000000..a9c06ee
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishTreeContentProvider.java
@@ -0,0 +1,198 @@
+package org.eclipse.wst.server.ui.internal.publish;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.resources.IModuleFolder;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+import org.eclipse.wst.server.core.resources.IRemoteResource;
+import org.eclipse.wst.server.ui.internal.Trace;
+
+/**
+ * Content provider for the publisher wizard.
+ */
+public class PublishTreeContentProvider implements ITreeContentProvider {
+	protected VisualPublisher visualPublisher;
+
+	protected Map remoteToProject = new HashMap();
+	
+	/**
+	 * PublishTreeContentProvider constructor comment.
+	 */
+	public PublishTreeContentProvider(VisualPublisher visualPublisher) {
+		super();
+		this.visualPublisher = visualPublisher;
+	}
+
+	/**
+	 * Disposes of this content provider.  
+	 * This is called by the viewer when it is disposed.
+	 */
+	public void dispose() {}
+
+	/**
+	 * Returns the child elements of the given parent element.
+	 * <p>
+	 * The difference between this method and <code>IStructuredContentProvider.getElements</code> 
+	 * is that <code>getElements</code> is called to obtain the 
+	 * tree viewer's root elements, whereas <code>getChildren</code> is used
+	 * to obtain the children of a given parent element in the tree (including a root).
+	 * </p>
+	 * The result is not modified by the viewer.
+	 *
+	 * @param parentElement the parent element
+	 * @return an array of child elements
+	 */
+	public Object[] getChildren(Object element) {
+		if (element instanceof IModule) {
+			try {
+				IModule module = (IModule) element;
+				IModuleResource[] children = module.members();
+				
+				// add deleted remote elements
+				List del = visualPublisher.getDeletedResources((IModule) element);
+				if (del == null || del.size() == 0)
+					return children;
+	
+				Object[] res = new Object[children.length + 1];
+				System.arraycopy(children, 0, res, 0, children.length);
+				res[children.length] = new ModuleDeletedResourceFolder((IModule) element);
+				return res;
+			} catch (Exception e) {
+				Trace.trace("Error getting module children", e);
+			}
+		} else if (element instanceof IModuleFolder) {
+			IModuleFolder folder = (IModuleFolder) element;
+			try {
+				return folder.members();
+			} catch (Exception e) {
+				Trace.trace("Error getting ModuleFolder members", e);
+			}
+		} else if (element instanceof ModuleDeletedResourceFolder) {
+			ModuleDeletedResourceFolder folder = (ModuleDeletedResourceFolder) element;
+			IModule module = folder.getModule();
+			List del = visualPublisher.getDeletedResources(module);
+			if (del == null || del.size() == 0)
+				return new Object[0];
+	
+			int size = del.size();
+			ModuleRemoteResource[] remote = new ModuleRemoteResource[size];
+			for (int i = 0; i < size; i++)
+				remote[i] = new ModuleRemoteResource(folder, module, (IRemoteResource) del.get(i));
+	
+			return remote;
+		}
+		return new Object[0];
+	}
+
+	/**
+	 * 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 inputElement the input element
+	 * @return the array of elements to display in the viewer
+	 */
+	public Object[] getElements(Object element) {
+		if (element instanceof List) {
+			List l = (List) element;
+			return l.toArray();
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the parent for the given element, or <code>null</code> 
+	 * indicating that the parent can't be computed. 
+	 * In this case the tree-structured viewer can't expand
+	 * a given node correctly if requested.
+	 *
+	 * @param element the element
+	 * @return the parent element, or <code>null</code> if it
+	 *   has none or if the parent cannot be computed
+	 */
+	public Object getParent(Object element) {
+		if (element instanceof IModuleResource) {
+			IModuleResource resource = (IModuleResource) element;
+			if (resource.getParent() != null)
+				return resource.getParent();
+			else
+				return resource.getModule();
+		} else if (element instanceof ModuleDeletedResourceFolder) {
+			ModuleDeletedResourceFolder folder = (ModuleDeletedResourceFolder) element;
+			return folder.getModule();
+		} else if (element instanceof ModuleRemoteResource) {
+			ModuleRemoteResource remote = (ModuleRemoteResource) element;
+			if (remote.getFolder() != null)
+				return remote.getFolder();
+			else
+				return remote.getModule();
+		}
+		return null;
+	}
+
+	/**
+	 * Returns whether the given element has children.
+	 * <p>
+	 * Intended as an optimization for when the viewer does not
+	 * need the actual children.  Clients may be able to implement
+	 * this more efficiently than <code>getChildren</code>.
+	 * </p>
+	 *
+	 * @param element the element
+	 * @return <code>true</code> if the given element has children,
+	 *  and <code>false</code> if it has no children
+	 */
+	public boolean hasChildren(Object element) {
+		if (element instanceof IModuleFolder) {
+			IModuleFolder container = (IModuleFolder) element;
+			try {
+				IModuleResource[] children = container.members();
+				if (children != null && children.length > 0)
+					return true;
+				else if (container instanceof IModule) {
+					return (!visualPublisher.getDeletedResources((IModule) element).isEmpty());
+				}
+				return false;
+			} catch (Exception e) {
+				Trace.trace("Project members", e);
+			}
+		} else if (element instanceof ModuleDeletedResourceFolder) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * 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) {}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishTreeLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishTreeLabelProvider.java
new file mode 100644
index 0000000..fca6020
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishTreeLabelProvider.java
@@ -0,0 +1,210 @@
+package org.eclipse.wst.server.ui.internal.publish;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.resources.IModuleFolder;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+import org.eclipse.wst.server.core.resources.IRemoteResource;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Label provider for the publisher wizard tree.
+ */
+public class PublishTreeLabelProvider implements ITableLabelProvider {
+	protected VisualPublisher visualPublisher;
+	protected static final ILabelProvider labelProvider = ServerUICore.getLabelProvider();
+
+	protected static final String[] statusStrings = new String[] {
+		ServerUIPlugin.getResource("%wizPublishStateNew"),
+		ServerUIPlugin.getResource("%wizPublishStateUnmodified"),
+		ServerUIPlugin.getResource("%wizPublishStateModifiedLocal"),
+		ServerUIPlugin.getResource("%wizPublishStateModifiedRemote"),
+		ServerUIPlugin.getResource("%wizPublishStateModifiedBoth")};
+
+	/**
+	 * PublishTreeLabelProvider constructor comment.
+	 */
+	public PublishTreeLabelProvider(VisualPublisher visualPublisher) {
+		super();
+		this.visualPublisher = visualPublisher;
+	}
+
+	/**
+	 * Adds a listener to this label provider. 
+	 * Has no effect if an identical listener is already registered.
+	 * <p>
+	 * Label provider listeners are informed about state changes 
+	 * that affect the rendering of the viewer that uses this label provider.
+	 * </p>
+	 *
+	 * @param listener a label provider listener
+	 */
+	public void addListener(ILabelProviderListener listener) {}
+
+	/**
+	 * Disposes of this label provider.  When a label provider is
+	 * attached to a viewer, the viewer will automatically call
+	 * this method when the viewer is being closed.  When label providers
+	 * are used outside of the context of a viewer, it is the client's
+	 * responsibility to ensure that this method is called when the
+	 * provider is no longer needed.
+	 */
+	public void dispose() { }
+
+	/**
+	 * Returns the label image for the given column of the given element.
+	 *
+	 * @param element the object representing the entire row, or 
+	 *    <code>null</code> indicating that no input object is set
+	 *    in the viewer
+	 * @param columnIndex the zero-based index of the column in which
+	 *   the label appears
+	 */
+	public Image getColumnImage(Object element, int columnIndex) {
+		if (element instanceof IModule) {
+			if (columnIndex == 0)
+				return labelProvider.getImage(element);
+			else
+				return null;
+		} else if (element instanceof IModuleResource) {
+			IModuleResource resource = (IModuleResource) element;
+			IPath path = visualPublisher.getPublishControl(resource.getModule()).getMappedLocation(resource);
+			if (columnIndex == 3) {
+				if (resource instanceof IModuleFolder) {
+					byte status = visualPublisher.getResourceStatus(resource, path);
+					if (status != VisualPublisher.STATUS_NEW)
+						return null;
+				}
+				if (path == null || path.toString() == null)
+					return null;
+				else {
+					if (visualPublisher.getResourcesToPublish(resource.getModule()).contains(resource))
+						return ImageResource.getImage(ImageResource.IMG_PUBLISH_ENABLED);
+					else
+						return ImageResource.getImage(ImageResource.IMG_PUBLISH_DISABLED);
+				}
+			}
+		} else if (element instanceof ModuleRemoteResource) {
+			ModuleRemoteResource prr = (ModuleRemoteResource) element;
+			IRemoteResource remote = prr.getRemote();
+			IPath path = remote.getPath();
+			if (columnIndex == 3) {
+				if (path == null || path.toString() == null)
+					return null;
+				else {
+					IModule module = prr.getModule();
+					if (visualPublisher.getResourcesToDelete(module).contains(remote))
+						return ImageResource.getImage(ImageResource.IMG_PUBLISH_ENABLED);
+					else
+						return ImageResource.getImage(ImageResource.IMG_PUBLISH_DISABLED);
+				}
+			}
+		}
+	
+		return null;
+	}
+
+	/**
+	 * Returns the label text for the given column of the given element.
+	 *
+	 * @param element the object representing the entire row, or
+	 *   <code>null</code> indicating that no input object is set
+	 *   in the viewer
+	 * @param columnIndex the zero-based index of the column in which the label appears
+	 */
+	public String getColumnText(Object element, int columnIndex) {
+		if (element instanceof IModule) {
+			if (columnIndex == 0)
+				return labelProvider.getText(element);
+			else
+				return "";
+		} else if (element instanceof IModuleResource) {
+			IModuleResource resource = (IModuleResource) element;
+			IPath path = visualPublisher.getPublishControl(resource.getModule()).getMappedLocation(resource);
+			byte status = visualPublisher.getResourceStatus(resource, path);
+			if (columnIndex == 0)
+				return resource.getName();
+			else if (columnIndex == 1) {
+				if (path == null || path.toString() == null)
+					return "";
+				else
+					return path.toString();
+			} else if (columnIndex == 2) {
+				if (path == null || path.toString() == null)
+					return "";
+				else {
+					return statusStrings[status];
+				}
+			} else if (columnIndex == 3) {
+				if (path == null || path.toString() == null)
+					return "";
+				else {
+					if (resource instanceof IModuleFolder && status != VisualPublisher.STATUS_NEW)
+						return "";
+					else
+						return ServerUIPlugin.getResource("%wizPublishActionPublish");
+				}
+			}
+		} else if (element instanceof ModuleRemoteResource) {
+			if (columnIndex == 0)
+				return ServerUIPlugin.getResource("%wizPublishDeletedResource");
+			else if (columnIndex == 1) {
+				ModuleRemoteResource prr = (ModuleRemoteResource) element;
+				IPath path = prr.getRemote().getPath();
+				if (path == null || path.toString() == null)
+					return "";
+				else
+					return path.toString();
+			} else if (columnIndex == 2) {
+				return ServerUIPlugin.getResource("%wizPublishStateDeleted");
+			} else if (columnIndex == 3)
+				return ServerUIPlugin.getResource("%wizPublishActionDelete");
+		} else if (element instanceof ModuleDeletedResourceFolder) {
+			if (columnIndex == 0)
+				return ServerUIPlugin.getResource("%wizPublishDeletedFolder");
+			else
+				return "";
+		}
+		return "";
+	}
+
+	/**
+	 * Returns whether the label would be affected 
+	 * by a change to the given property of the given element.
+	 * This can be used to optimize a non-structural viewer update.
+	 * If the property mentioned in the update does not affect the label,
+	 * then the viewer need not update the label.
+	 *
+	 * @param element the element
+	 * @param property the property
+	 * @return <code>true</code> if the label would be affected,
+	 *    and <code>false</code> if it would be unaffected
+	 */
+	public boolean isLabelProperty(Object element, String property) {
+		return "action".equals(property);
+	}
+
+	/**
+	 * Removes a listener to this label provider.
+	 * Has no affect if an identical listener is not registered.
+	 *
+	 * @param listener a label provider listener
+	 */
+	public void removeListener(ILabelProviderListener listener) { }
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishViewerFilter.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishViewerFilter.java
new file mode 100644
index 0000000..acb1dce
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishViewerFilter.java
@@ -0,0 +1,174 @@
+package org.eclipse.wst.server.ui.internal.publish;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+import org.eclipse.wst.server.core.resources.IModuleFolder;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+/**
+ * A filter for the visual publisher's dialog.
+ */
+public class PublishViewerFilter extends ViewerFilter {
+	protected VisualPublisher visualPublisher;
+
+	protected boolean filterUnpublishable = true;
+	protected boolean filterDeleted = false;
+	protected boolean filterNew = false;
+	protected boolean filterModified = false;
+	protected boolean filterUnmodified = false;
+
+	/**
+	 * PublishViewerFilter constructor comment.
+	 */
+	protected PublishViewerFilter(VisualPublisher visualPublisher) {
+		super();
+		this.visualPublisher = visualPublisher;
+	}
+
+	/**
+	 * Returns true if deleted files are filtered.
+	 *
+	 * @return boolean
+	 */
+	public boolean isFilteringDeleted() {
+		return filterDeleted;
+	}
+
+	/**
+	 * Returns true if modified files are filtered.
+	 *
+	 * @return boolean
+	 */
+	public boolean isFilteringModified() {
+		return filterModified;
+	}
+
+	/**
+	 * Returns true if new files are filtered.
+	 *
+	 * @return boolean
+	 */
+	public boolean isFilteringNew() {
+		return filterNew;
+	}
+
+	/**
+	 * Returns true if unmodified files are filtered.
+	 *
+	 * @return boolean
+	 */
+	public boolean isFilteringUnmodified() {
+		return filterUnmodified;
+	}
+
+	/**
+	 * Returns true if files that are not publishable are filtered.
+	 *
+	 * @return boolean
+	 */
+	public boolean isFilteringUnpublishable() {
+		return filterUnpublishable;
+	}
+
+	/**
+	 * Returns whether the given element makes it through this filter.
+	 *
+	 * @param viewer the viewer
+	 * @param parentElement the parent element
+	 * @param element the element
+	 * @return <code>true</code> if element is included in the
+	 *   filtered set, and <code>false</code> if excluded
+	 */
+	public boolean select(Viewer viewer, Object parentElement, Object element) {
+		if (element instanceof IModuleResource) {
+			IModuleResource resource = (IModuleResource) element;
+			IPath path = visualPublisher.getPublishControl(resource.getModule()).getMappedLocation(resource);
+			if (filterUnpublishable && path == null) {
+				if (resource instanceof IModuleFolder) {
+					if (visualPublisher.getPublishControl(resource.getModule()).shouldMapMembers((IModuleFolder) resource))
+						return true;
+					else
+						return false;
+				} else
+					return false;
+			}
+			byte status = visualPublisher.getResourceStatus(resource, path);
+			if (status == VisualPublisher.STATUS_NEW && filterNew)
+				return false;
+			
+			if (status == VisualPublisher.STATUS_UNCHANGED && filterUnmodified)
+				return false;
+	
+			if ((status == VisualPublisher.STATUS_NEWER_LOCALLY || status == VisualPublisher.STATUS_NEWER_REMOTELY) &&
+				filterModified)
+				return false;
+		} else if (element instanceof ModuleRemoteResource) {
+			if (filterDeleted)
+				return false;
+			else
+				return true;
+		} else if (element instanceof ModuleDeletedResourceFolder) {
+			if (filterDeleted)
+				return false;
+			else
+				return true;
+		}
+		return true;
+	}
+
+	/**
+	 * Set whether deleted files are filtered.
+	 *
+	 * @param boolean
+	 */
+	public void setFilteringDeleted(boolean b) {
+		filterDeleted = b;
+	}
+
+	/**
+	 * Set whether modified files are filtered.
+	 *
+	 * @param boolean
+	 */
+	public void setFilteringModified(boolean b) {
+		filterModified = b;
+	}
+
+	/**
+	 * Set whether new files are filtered.
+	 *
+	 * @param boolean
+	 */
+	public void setFilteringNew(boolean b) {
+		filterNew = b;
+	}
+
+	/**
+	 * Set whether unmodified files are filtered.
+	 *
+	 * @param boolean
+	 */
+	public void setFilteringUnmodified(boolean b) {
+		filterUnmodified = b;
+	}
+
+	/**
+	 * Set whether unpublishable files are filtered.
+	 *
+	 * @param boolean
+	 */
+	public void setFilteringUnpublishable(boolean b) {
+		filterUnpublishable = b;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishViewerFilterDialog.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishViewerFilterDialog.java
new file mode 100644
index 0000000..0e8a2f1
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublishViewerFilterDialog.java
@@ -0,0 +1,197 @@
+package org.eclipse.wst.server.ui.internal.publish;
+
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.wst.server.ui.internal.ContextIds;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.help.WorkbenchHelp;
+/**
+ * Dialog to modify the filter used in the publish viewer
+ * of the visual publisher.
+ */
+public class PublishViewerFilterDialog extends Dialog {
+	protected PublishViewerFilter filter;
+	protected CheckboxTableViewer viewer;
+
+	protected static final String[] filterStrings = new String[] {
+		ServerUIPlugin.getResource("%wizPublishFilterUnpublished"),
+		ServerUIPlugin.getResource("%wizPublishFilterNew"),
+		ServerUIPlugin.getResource("%wizPublishFilterUnmodified"),
+		ServerUIPlugin.getResource("%wizPublishFilterModified"),
+		ServerUIPlugin.getResource("%wizPublishFilterDeleted")};
+
+	protected static final String[] filterDescriptions = new String[] {
+		ServerUIPlugin.getResource("%wizPublishFilterUnpublishedDescription"),
+		ServerUIPlugin.getResource("%wizPublishFilterNewDescription"),
+		ServerUIPlugin.getResource("%wizPublishFilterUnmodifiedDescription"),
+		ServerUIPlugin.getResource("%wizPublishFilterModifiedDescription"),
+		ServerUIPlugin.getResource("%wizPublishFilterDeletedDescription")};
+
+	public class FilterLabelProvider implements ITableLabelProvider {
+		public void addListener(ILabelProviderListener listener) { }
+		public void dispose() { }
+		
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+		
+		public String getColumnText(Object element, int columnIndex) {
+			return filterStrings[((Integer) element).intValue()];
+		}
+		public boolean isLabelProperty(Object element, String property) {
+			return false;
+		}
+		public void removeListener(ILabelProviderListener listener) { }
+	}
+	
+	public class FilterContentProvider implements IStructuredContentProvider {
+		public void dispose() { }
+	
+		public Object[] getElements(Object element) {
+			return new Integer[] {
+				new Integer(0), new Integer(1), new Integer(2),
+				new Integer(3), new Integer(4)};
+		}
+	
+		public void inputChanged(Viewer newViewer, Object oldInput, Object newInput) { }
+	}
+
+	/**
+	 * PublishViewerFilterDialog constructor comment.
+	 * @param parentShell org.eclipse.swt.widgets.Shell
+	 */
+	public PublishViewerFilterDialog(Shell parentShell, PublishViewerFilter filter) {
+		super(parentShell);
+		this.filter = filter;
+	}
+
+	/**
+	 *
+	 */
+	protected void configureShell(Shell newShell) {
+		super.configureShell(newShell);
+		newShell.setText(ServerUIPlugin.getResource("%wizPublishFilterTitle"));
+	}
+
+	/**
+	 * Creates and returns the contents of the upper part 
+	 * of this dialog (above the button bar).
+	 * <p>
+	 * The <code>Dialog</code> implementation of this framework method
+	 * creates and returns a new <code>Composite</code> with
+	 * standard margins and spacing. Subclasses should override.
+	 * </p>
+	 *
+	 * @param the parent composite to contain the dialog area
+	 * @return the dialog area control
+	 */
+	protected Control createDialogArea(Composite parent) {
+		// create a composite with standard margins and spacing
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+		composite.setFont(parent.getFont());
+		WorkbenchHelp.setHelp(composite, ContextIds.PUBLISHER_DIALOG_FILTER_DIALOG);
+	
+		Label label = new Label(composite, SWT.NONE);
+		label.setText(ServerUIPlugin.getResource("%wizPublishFilterMessage"));
+	
+		viewer = CheckboxTableViewer.newCheckList(composite, SWT.BORDER);
+		viewer.setContentProvider(new FilterContentProvider());
+		viewer.setLabelProvider(new FilterLabelProvider());
+		viewer.setInput("root");
+		WorkbenchHelp.setHelp(viewer.getTable(), ContextIds.PUBLISHER_DIALOG_FILTER_DIALOG);
+	
+		GridData data = new GridData(GridData.FILL_HORIZONTAL);
+		data.widthHint = 200;
+		data.heightHint = 90;
+		viewer.getTable().setLayoutData(data);
+	
+		if (filter.isFilteringUnpublishable())
+			viewer.setChecked(new Integer(0), true);
+		if (filter.isFilteringNew())
+			viewer.setChecked(new Integer(1), true);
+		if (filter.isFilteringUnmodified())
+			viewer.setChecked(new Integer(2), true);
+		if (filter.isFilteringModified())
+			viewer.setChecked(new Integer(3), true);
+		if (filter.isFilteringDeleted())
+			viewer.setChecked(new Integer(4), true);
+	
+		final Label description = new Label(composite, SWT.WRAP);
+		description.setText(" \n ");
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
+		data.heightHint = 35;
+		description.setLayoutData(data);
+		
+		viewer.getTable().addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				try {
+					TableItem item = viewer.getTable().getSelection()[0];
+					Integer in = (Integer) item.getData();
+					description.setText(filterDescriptions[in.intValue()]);
+				} catch (Exception e) {
+					description.setText("");
+				}
+			}
+			public void widgetDefaultSelected(SelectionEvent event) {
+			}
+		});
+		
+		Dialog.applyDialogFont(composite);
+	
+		return composite;
+	}
+
+	/**
+	 * Return the filter.
+	 *
+	 * @return org.eclipse.wst.server.ui.internal.publish.PublishViewerFilter
+	 */
+	public PublishViewerFilter getFilter() {
+		return filter;
+	}
+
+	protected void okPressed() {
+		filter.setFilteringUnpublishable(viewer.getChecked(new Integer(0)));
+		filter.setFilteringNew(viewer.getChecked(new Integer(1)));
+		filter.setFilteringUnmodified(viewer.getChecked(new Integer(2)));
+		filter.setFilteringModified(viewer.getChecked(new Integer(3)));
+		filter.setFilteringDeleted(viewer.getChecked(new Integer(4)));
+	
+		super.okPressed();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublisherWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublisherWizard.java
new file mode 100644
index 0000000..6b38ff7
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublisherWizard.java
@@ -0,0 +1,43 @@
+package org.eclipse.wst.server.ui.internal.publish;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * PublisherWizard
+ */
+public class PublisherWizard extends Wizard {
+	protected VisualPublisher visualPublisher;
+
+	/**
+	 * PublisherWizard constructor comment.
+	 */
+	public PublisherWizard(VisualPublisher visualPublisher) {
+		super();
+		setWindowTitle(ServerUIPlugin.getResource("%wizPublishWizardTitle"));
+	
+		this.visualPublisher = visualPublisher;
+	}
+
+	public void addPages() {
+		PublisherWizardPage page = new PublisherWizardPage(visualPublisher);
+		addPage(page);
+	}
+
+	/**
+	 * Subclasses must implement this <code>IWizard</code> method 
+	 * to perform any special finish processing for their wizard.
+	 */
+	public boolean performFinish() {
+		return true;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublisherWizardPage.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublisherWizardPage.java
new file mode 100644
index 0000000..3cf81cf
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/PublisherWizardPage.java
@@ -0,0 +1,162 @@
+package org.eclipse.wst.server.ui.internal.publish;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TableTree;
+import org.eclipse.swt.custom.TableTreeItem;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+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.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+/**
+ * Publish Wizard that allows that user to select which files
+ * to publish.
+ */
+public class PublisherWizardPage extends WizardPage {
+	protected TableTree tableTree;
+
+	protected VisualPublisher visualPublisher;
+
+	protected static final String[] descriptionStrings = new String[] {
+		ServerUIPlugin.getResource("%wizPublishStateNewDescription"),
+		ServerUIPlugin.getResource("%wizPublishStateUnmodifiedDescription"),
+		ServerUIPlugin.getResource("%wizPublishStateModifiedLocalDescription"),
+		ServerUIPlugin.getResource("%wizPublishStateModifiedRemoteDescription"),
+		ServerUIPlugin.getResource("%wizPublishStateModifiedBothDescription"),
+		ServerUIPlugin.getResource("%wizPublishStateDeletedDescription")};
+
+	/**
+	 * PublisherWizardPage constructor comment.
+	 * @param parentShell org.eclipse.swt.widgets.Shell
+	 */
+	public PublisherWizardPage(VisualPublisher visualPublisher) {
+		super("publish wizard page");
+		this.visualPublisher = visualPublisher;
+	
+		setTitle(ServerUIPlugin.getResource("%wizPublishTitle"));
+		setDescription(ServerUIPlugin.getResource("%wizPublishDescription"));
+		setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_VISUAL_PUBLISHER));
+	}
+
+	/**
+	 * Creates the top level control for this dialog
+	 * page under the given parent composite.
+	 * <p>
+	 * Implementors are responsible for ensuring that
+	 * the created control can be accessed via <code>getControl</code>
+	 * </p>
+	 *
+	 * @param parent the parent composite
+	 */
+	public void createControl(Composite parent) {
+		Composite c = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		c.setLayout(layout);
+	
+		tableTree = new TableTree(c, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.SINGLE);
+	
+		Table table = tableTree.getTable();
+		table.setLinesVisible(true);
+		table.setHeaderVisible(true);
+	
+		TableColumn column = new TableColumn(table, SWT.SINGLE);
+		column.setText(ServerUIPlugin.getResource("%wizPublishColumnLocal"));
+		column.setWidth(150);
+	
+		column = new TableColumn(table, SWT.SINGLE);
+		column.setText(ServerUIPlugin.getResource("%wizPublishColumnRemote"));
+		column.setWidth(140);
+	
+		column = new TableColumn(table, SWT.SINGLE);
+		column.setText(ServerUIPlugin.getResource("%wizPublishColumnStatus"));
+		column.setWidth(135);
+	
+		column = new TableColumn(table, SWT.SINGLE);
+		column.setText(ServerUIPlugin.getResource("%wizPublishColumnAction"));
+		column.setWidth(120);
+	
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = 550;
+		data.heightHint = 400;
+		tableTree.setLayoutData(data);
+	
+		final PublishTableTreeViewer viewer = new PublishTableTreeViewer(tableTree, visualPublisher);
+	
+		final Label description = new Label(c, SWT.WRAP);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		description.setLayoutData(data);
+	
+		tableTree.addSelectionListener(new SelectionListener() {
+			public void widgetSelected(SelectionEvent event) {
+				try {
+					TableTreeItem item = tableTree.getSelection()[0];
+					Object obj = item.getData();
+					description.setText(getDescription(obj));
+				} catch (Exception e) {
+					description.setText("!");
+				}
+			}
+			public void widgetDefaultSelected(SelectionEvent event) {
+			}
+		});
+	
+		final Button filter = new Button(c, SWT.NONE);
+		filter.setText(ServerUIPlugin.getResource("%wizPublishFilter"));
+		filter.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				PublishViewerFilterDialog dialog = new PublishViewerFilterDialog(getShell(), viewer.getFilter());
+				if (dialog.open() == Window.OK)
+					viewer.updateFilter();
+			}
+		});
+		
+		Dialog.applyDialogFont(c);
+		
+		setControl(c);
+	}
+
+	/**
+	 * Returns a description for the element.
+	 *
+	 * @param element java.lang.Object
+	 * @return java.lang.String
+	 */
+	protected String getDescription(Object element) {
+		if (element instanceof IModuleResource) {
+			IModuleResource resource = (IModuleResource) element;
+			IPath path = visualPublisher.getPublishControl(resource.getModule()).getMappedLocation(resource);
+			if (path == null || path.toString() == null)
+				return "";
+			else {
+				byte status = visualPublisher.getResourceStatus(resource, path);
+				return descriptionStrings[status];
+			}
+		} else if (element instanceof ModuleRemoteResource) {
+			return descriptionStrings[5];
+		}
+		return "";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/VisualPublisher.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/VisualPublisher.java
new file mode 100644
index 0000000..5f6e0a0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/publish/VisualPublisher.java
@@ -0,0 +1,373 @@
+package org.eclipse.wst.server.ui.internal.publish;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+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.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.wst.server.core.IPublishControl;
+import org.eclipse.wst.server.core.internal.AbstractPublisher;
+import org.eclipse.wst.server.core.internal.SmartPublisher;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IPublishManagerDelegate;
+import org.eclipse.wst.server.core.resources.IModuleFolder;
+import org.eclipse.wst.server.core.resources.IModuleResource;
+import org.eclipse.wst.server.core.resources.IRemoteFolder;
+import org.eclipse.wst.server.core.resources.IRemoteResource;
+import org.eclipse.wst.server.ui.internal.EclipseUtil;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * A visual publisher that allows the user to select
+ * which files to publish from a tree table.
+ */
+public class VisualPublisher implements IPublishManagerDelegate {
+	//protected IPublishControl control;
+	protected Map publishControls;
+	protected List modules;
+
+	// use a smart publisher to initially fill in publish selection
+	protected SmartPublisher smartPublisher;
+
+	protected Map deleteMap;
+	protected Map publishMap;
+
+	protected Map deletedResources;
+
+	public static final byte STATUS_NEW = 0;
+	public static final byte STATUS_UNCHANGED = 1;
+	public static final byte STATUS_NEWER_LOCALLY = 2;
+	public static final byte STATUS_NEWER_REMOTELY = 3;
+	public static final byte STATUS_NEWER_UNKNOWN = 4;
+
+	/**
+	 * VisualPublisher constructor comment.
+	 */
+	public VisualPublisher() {
+		super();
+	}
+
+	protected IRemoteResource findRemoteResource(IRemoteFolder folder, IPath path) {
+		Iterator iterator = folder.getContents().iterator();
+		while (iterator.hasNext()) {
+			IRemoteResource remote = (IRemoteResource) iterator.next();
+			if (path.equals(remote.getPath()))
+				return remote;
+			if (remote instanceof IRemoteFolder) {
+				IRemoteFolder folder2 = (IRemoteFolder) remote;
+				IPath folderPath = folder2.getPath();
+				if (folderPath.isPrefixOf(path)) {
+					IRemoteResource rem = findRemoteResource(folder2, path);
+					if (rem != null)
+						return rem;
+				}
+			}
+		}
+		return null;
+	}
+
+	protected IRemoteResource findRemoteResource(IModule module, IPath path) {
+		if (path == null)
+			return null;
+	
+		IRemoteResource[] remoteResources = getPublishControl(module).getRemoteResources();
+		if (remoteResources != null) {
+			int size = remoteResources.length;
+			for (int i = 0; i < size; i++) {
+				IRemoteResource remote = remoteResources[i];
+				if (path.equals(remote.getPath()))
+					return remote;
+				if (remote instanceof IRemoteFolder) {
+					IRemoteFolder folder2 = (IRemoteFolder) remote;
+					IPath folderPath = folder2.getPath();
+					if (folderPath.isPrefixOf(path)) {
+						IRemoteResource rem = findRemoteResource(folder2, path);
+						if (rem != null)
+							return rem;
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the resources that should be deleted from
+	 * the server because they no longer exist in the
+	 * workbench.
+	 *
+	 * @return java.util.List
+	 */
+	public List getDeletedResources(IModule module) {
+		try {
+			List list = (List) deletedResources.get(module);
+			if (list != null)
+				return list;
+		} catch (Exception e) {
+		}
+	
+		List visited = new ArrayList();
+		List unvisited = new ArrayList();
+	
+		try {
+			IModuleResource resources[] = module.members();
+			int size = resources.length;
+			for (int i = 0; i < size; i++) {
+				visit(module, visited, resources[i]);
+			}
+		} catch (Exception e) {
+			Trace.trace("Error visiting resources", e);
+		}
+	
+		IRemoteResource[] remoteResources = getPublishControl(module).getRemoteResources();
+		if (remoteResources != null) {
+			int size = remoteResources.length;
+			for (int i = 0; i < size; i++) {
+				IRemoteResource remote = remoteResources[i];
+				IPath path = remote.getPath();
+				if (!visited.contains(path) && !unvisited.contains(remote))
+					unvisited.add(remote);
+	
+				if (remote instanceof IRemoteFolder)
+					unvisit(visited, unvisited, (IRemoteFolder) remote);
+			}
+		}
+	
+		deletedResources.put(module, unvisited);
+		return unvisited;
+	}
+
+	/**
+	 * Returns the publish control, used to obtain information about
+	 * the publishing.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IPublishControl
+	 */
+	public IPublishControl getPublishControl(IModule module) {
+		try {
+			return (IPublishControl) publishControls.get(module);
+		} catch (Exception e) {
+			return null;
+		}
+	}
+	
+	/**
+	 * Returns the modules.
+	 *
+	 * @return java.util.List
+	 */
+	public List getModules() {
+		return modules;
+	}
+
+	/**
+	 * Returns the resource state.
+	 *
+	 * @return byte
+	 */
+	public byte getResourceStatus(IModuleResource resource, IPath path) {
+		IModule module = resource.getModule();
+		IRemoteResource remote = findRemoteResource(module, path);
+		if (remote == null)
+			return STATUS_NEW;
+	
+		if (resource instanceof IModuleFolder) {
+			return STATUS_UNCHANGED;
+		}
+	
+		boolean changedRemote = false;
+		long timestamp = getPublishControl(module).getPublishedTimestamp(remote);
+		if (timestamp == IRemoteResource.TIMESTAMP_UNKNOWN || remote.getTimestamp() != timestamp)
+			changedRemote = true;
+	
+		boolean changedLocally = false;
+		timestamp = getPublishControl(module).getPublishedTimestamp(resource);
+		if (timestamp == IRemoteResource.TIMESTAMP_UNKNOWN || resource.getTimestamp() != timestamp)
+			changedLocally = true;
+	
+		if (changedLocally && changedRemote)
+			return STATUS_NEWER_UNKNOWN;
+		else if (changedLocally)
+			return STATUS_NEWER_LOCALLY;
+		else if (changedRemote)
+			return STATUS_NEWER_REMOTELY;
+		else
+			return STATUS_UNCHANGED;
+	}
+
+	/**
+	 * Returns the list of remote resources to delete from the
+	 * remote system.
+	 *
+	 * @param project org.eclipse.core.resources.IProject
+	 * @return java.util.List
+	 */
+	public List getResourcesToDelete(IModule module) {
+		try {
+			List list = (List) deleteMap.get(module);
+			if (list != null)
+				return list;
+		} catch (Exception e) {	}
+	
+		List list = new ArrayList();
+		deleteMap.put(module, list);
+		return list;
+	}
+
+	/**
+	 * Returns the list of resources to publish to the remote
+	 * system.
+	 *
+	 * @param project org.eclipse.core.resources.IProject
+	 * @return java.util.List
+	 */
+	public List getResourcesToPublish(IModule module) {
+		try {
+			List list = (List) publishMap.get(module);
+			if (list != null)
+				return list;
+		} catch (Exception e) {	}
+	
+		List list = new ArrayList();
+		publishMap.put(module, list);
+		return list;
+	}
+
+	/**
+	 * Sets the publish control, used to obtain information about
+	 * the publishing.
+	 *
+	 * Sets the publish state, used to determine the timestamps
+	 * of the last publishing action.
+	 * 
+	 * Resolve which resources to publish or delete.
+	 *
+	 * @param control org.eclipse.wst.server.core.IPublishControl[]
+	 * @param module org.eclipse.wst.server.core.model.IModule[]
+	 * @param monitor org.eclipse.core.runtime.IProgressMonitor
+	 */
+	public void resolve(IPublishControl[] control, IModule[] module, IProgressMonitor monitor) {
+		int size = control.length;
+		
+		deleteMap = new HashMap();
+		publishMap = new HashMap();
+		deletedResources = new HashMap();
+		
+		publishControls = new HashMap(size);
+		modules = new ArrayList(size);
+		for (int i = 0; i < size; i++) {
+			publishControls.put(module[i], control[i]);
+			modules.add(module[i]);
+		}
+		
+		smartPublisher = new SmartPublisher();	
+		smartPublisher.resolve(control, module, new NullProgressMonitor());
+	
+		Iterator iterator = getModules().iterator();
+		while (iterator.hasNext()) {
+			IModule module2 = (IModule) iterator.next();
+			
+			List publish = smartPublisher.getResourcesToPublish(module2);
+			publishMap.put(module2, publish);
+			
+			List delete = smartPublisher.getResourcesToDelete(module2);
+			deleteMap.put(module2, delete);
+		}
+		
+		class Temp {
+			boolean cancel = false;
+		}
+		final Temp temp = new Temp();
+		Display.getDefault().syncExec(new Runnable() {
+			public void run() {
+				Shell shell = EclipseUtil.getShell();
+				PublisherWizard wizard = new PublisherWizard(VisualPublisher.this);
+				WizardDialog dialog = new WizardDialog(shell, wizard);
+				temp.cancel = (dialog.open() == Window.CANCEL);
+			}
+		});
+		if (temp.cancel) {
+			deleteMap = new HashMap();
+			publishMap = new HashMap();
+			monitor.setCanceled(true);
+			return;
+		}
+		
+		// sort delete and publish lists
+		iterator = getModules().iterator();
+		while (iterator.hasNext()) {
+			IModule module2 = (IModule) iterator.next();
+			
+			List publish = getResourcesToPublish(module2);
+			AbstractPublisher.sortPublishList(publish);
+	
+			List delete = getResourcesToDelete(module2);
+			AbstractPublisher.sortDeletionList(delete);
+		}
+	}
+
+	/**
+	 * 
+	 */
+	private void unvisit(List visited, List unvisited, IRemoteFolder folder) {
+		try {
+			Iterator iterator = folder.getContents().iterator();
+			while (iterator.hasNext()) {
+				IRemoteResource remote = (IRemoteResource) iterator.next();
+				IPath path = remote.getPath();
+				if (!visited.contains(path) && !unvisited.contains(remote))
+					unvisited.add(remote);
+	
+				if (remote instanceof IRemoteFolder)
+					unvisit(visited, unvisited, (IRemoteFolder) remote);
+			}
+		} catch (Exception e) {
+			Trace.trace("Error unvisiting in visual publish", e);
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	private void visit(IModule module, List visited, IModuleResource resource) {
+		try {
+			IPath path = getPublishControl(module).getMappedLocation(resource);
+			if (path != null && !visited.contains(path))
+				visited.add(path);
+		
+			if (resource instanceof IModuleFolder) {
+				IModuleResource[] resources = ((IModuleFolder) resource).members();
+				int size = resources.length;
+				for (int i = 0; i < size; i++) {
+					if (resources[i] instanceof IModuleFolder) {
+						visit(module, visited, resources[i]);
+					} else {
+						path = getPublishControl(module).getMappedLocation(resources[i]);
+						if (path != null && !visited.contains(path))
+							visited.add(path);
+					}
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace("Error in visual publish visit", e);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/AddModuleTask.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/AddModuleTask.java
new file mode 100644
index 0000000..4f89936
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/AddModuleTask.java
@@ -0,0 +1,67 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.task;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.util.Task;
+import org.eclipse.wst.server.ui.internal.Trace;
+
+/**
+ * 
+ */
+public class AddModuleTask extends Task {
+	protected IModule module;
+
+	public AddModuleTask(IModule module) {
+		this.module = module;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.ITask#doTask()
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException {
+		if (module == null)
+			return;
+
+		IServer server = (IServer) getTaskModel().getObject(ITaskModel.TASK_SERVER);
+		IModule parentModule = null;
+		try {
+			List parents = server.getParentModules(module);
+			if (parents != null && parents.size() > 0) {
+				parentModule = (IModule) parents.get(0);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not find parent module", e);
+		}
+		
+		if (parentModule == null) {
+			// Use the original module since no parent module is available.
+			parentModule = module;
+		}
+
+		IModule[] modules = server.getModules();
+		int size = modules.length;
+		for (int i = 0; i < size; i++) {
+			if (parentModule.equals(modules[i]))
+				return;
+		}
+
+		IServerWorkingCopy workingCopy = server.getWorkingCopy();
+		workingCopy.modifyModules(new IModule[] { parentModule }, new IModule[0], monitor);
+		workingCopy.save(monitor);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/CompositeTask.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/CompositeTask.java
new file mode 100644
index 0000000..aff8d27
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/CompositeTask.java
@@ -0,0 +1,13 @@
+package org.eclipse.wst.server.ui.internal.task;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.util.Task;
+/**
+ * 
+ */
+public class CompositeTask extends Task {
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.Task#doTask(org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public void execute(IProgressMonitor monitor) { }
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/FinishWizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/FinishWizardFragment.java
new file mode 100644
index 0000000..0328917
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/FinishWizardFragment.java
@@ -0,0 +1,19 @@
+package org.eclipse.wst.server.ui.internal.task;
+
+import org.eclipse.wst.server.core.ITask;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+
+/**
+ * 
+ */
+public class FinishWizardFragment extends WizardFragment {
+	protected ITask finishTask;
+	
+	public FinishWizardFragment(ITask finishTask) {
+		this.finishTask = finishTask;
+	}
+	
+	public ITask createFinishTask() {
+		return finishTask;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/InputTask.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/InputTask.java
new file mode 100644
index 0000000..c91fc13
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/InputTask.java
@@ -0,0 +1,27 @@
+package org.eclipse.wst.server.ui.internal.task;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.util.Task;
+/**
+ * 
+ */
+public class InputTask extends Task {
+	protected String[] ids;
+	protected Object[] values;
+	
+	public InputTask(String id, Object value) {
+		this(new String[] { id }, new Object[] { value });
+	}
+
+	public InputTask(String[] ids, Object[] values) {
+		this.ids = ids;
+		this.values = values;
+	}
+	
+	public void execute(IProgressMonitor monitor) {
+		int size = ids.length;
+		for (int i = 0; i < size; i++) {
+			getTaskModel().putObject(ids[i], values[i]);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/InputWizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/InputWizardFragment.java
new file mode 100644
index 0000000..5faa7fc
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/InputWizardFragment.java
@@ -0,0 +1,26 @@
+package org.eclipse.wst.server.ui.internal.task;
+
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+/**
+ * 
+ */
+public class InputWizardFragment extends WizardFragment {
+	protected String[] ids;
+	protected Object[] values;
+	
+	public InputWizardFragment(String id, Object value) {
+		this(new String[] { id }, new Object[] { value });
+	}
+
+	public InputWizardFragment(String[] ids, Object[] values) {
+		this.ids = ids;
+		this.values = values;
+	}
+	
+	public void enter() {
+		int size = ids.length;
+		for (int i = 0; i < size; i++) {
+			getTaskModel().putObject(ids[i], values[i]);
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/ModifyModulesTask.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/ModifyModulesTask.java
new file mode 100644
index 0000000..a8ad006
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/ModifyModulesTask.java
@@ -0,0 +1,53 @@
+package org.eclipse.wst.server.ui.internal.task;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.util.Task;
+
+/**
+ * 
+ */
+public class ModifyModulesTask extends Task {
+	protected List add;
+	protected List remove;
+	
+	public ModifyModulesTask() { }
+	
+	public void setAddModules(List add) {
+		this.add = add;
+	}
+	
+	public void setRemoveModules(List remove) {
+		this.remove = remove;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.ITask#doTask()
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException {
+		if ((add == null || add.isEmpty()) && (remove == null || remove.isEmpty()))
+			return;
+
+		IServerWorkingCopy workingCopy = (IServerWorkingCopy) getTaskModel().getObject(ITaskModel.TASK_SERVER);
+
+		// modify modules
+		IModule[] remove2 = new IModule[0];
+		if (remove != null) {
+			remove2 = new IModule[remove.size()];
+			remove.toArray(remove2);
+		}
+		
+		IModule[] add2 = new IModule[0];
+		if (add != null) {
+			add2 = new IModule[add.size()];
+			add.toArray(add2);
+		}
+		
+		workingCopy.modifyModules(add2, remove2, monitor);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/ReleaseServerConfigurationTask.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/ReleaseServerConfigurationTask.java
new file mode 100644
index 0000000..4ad9135
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/ReleaseServerConfigurationTask.java
@@ -0,0 +1,23 @@
+package org.eclipse.wst.server.ui.internal.task;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.core.util.Task;
+
+/**
+ * 
+ */
+public class ReleaseServerConfigurationTask extends Task {
+	public ReleaseServerConfigurationTask() { }
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.ITask#doTask()
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException {
+		IServerConfigurationWorkingCopy workingCopy = (IServerConfigurationWorkingCopy) getTaskModel().getObject(ITaskModel.TASK_SERVER_CONFIGURATION);
+		if (workingCopy != null)
+			workingCopy.release();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/ReleaseServerTask.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/ReleaseServerTask.java
new file mode 100644
index 0000000..7bd5836
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/ReleaseServerTask.java
@@ -0,0 +1,23 @@
+package org.eclipse.wst.server.ui.internal.task;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.core.util.Task;
+
+/**
+ * 
+ */
+public class ReleaseServerTask extends Task {
+	public ReleaseServerTask() { }
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.ITask#doTask()
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException {
+		IServerWorkingCopy workingCopy = (IServerWorkingCopy) getTaskModel().getObject(ITaskModel.TASK_SERVER);
+		if (workingCopy != null)
+			workingCopy.release();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/SaveRuntimeTask.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/SaveRuntimeTask.java
new file mode 100644
index 0000000..d5231bf
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/SaveRuntimeTask.java
@@ -0,0 +1,26 @@
+package org.eclipse.wst.server.ui.internal.task;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IRuntimeWorkingCopy;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.core.util.Task;
+
+/**
+ * 
+ */
+public class SaveRuntimeTask extends Task {
+	public SaveRuntimeTask() { }
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.ITask#doTask()
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException {
+		IRuntime runtime = (IRuntime) getTaskModel().getObject(ITaskModel.TASK_RUNTIME);
+		if (runtime instanceof IRuntimeWorkingCopy) {
+			IRuntimeWorkingCopy workingCopy = (IRuntimeWorkingCopy) runtime; 
+			workingCopy.save(monitor);
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/SaveServerConfigurationTask.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/SaveServerConfigurationTask.java
new file mode 100644
index 0000000..71d1801
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/SaveServerConfigurationTask.java
@@ -0,0 +1,32 @@
+package org.eclipse.wst.server.ui.internal.task;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.util.Task;
+
+/**
+ * 
+ */
+public class SaveServerConfigurationTask extends Task {
+	public SaveServerConfigurationTask() { }
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.ITask#doTask()
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException {
+		IServerConfigurationWorkingCopy workingCopy = (IServerConfigurationWorkingCopy) getTaskModel().getObject(ITaskModel.TASK_SERVER_CONFIGURATION);
+		if (workingCopy != null) {
+			IFile file = workingCopy.getFile();
+			if (file != null && !file.getProject().exists()) {
+				IProject project = file.getProject();
+				ServerCore.createServerProject(project.getName(), null, monitor);
+			}
+			workingCopy.save(monitor);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/SaveServerTask.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/SaveServerTask.java
new file mode 100644
index 0000000..9232fea
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/task/SaveServerTask.java
@@ -0,0 +1,32 @@
+package org.eclipse.wst.server.ui.internal.task;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.util.Task;
+
+/**
+ * 
+ */
+public class SaveServerTask extends Task {
+	public SaveServerTask() { }
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.ITask#doTask()
+	 */
+	public void execute(IProgressMonitor monitor) throws CoreException {
+		IServerWorkingCopy workingCopy = (IServerWorkingCopy) getTaskModel().getObject(ITaskModel.TASK_SERVER);
+		if (workingCopy != null) {
+			IFile file = workingCopy.getFile();
+			if (file != null && !file.getProject().exists()) {
+				IProject project = file.getProject();
+				ServerCore.createServerProject(project.getName(), null, monitor);
+			}
+			workingCopy.save(monitor);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/AbstractServerAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/AbstractServerAction.java
new file mode 100644
index 0000000..4672a4d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/AbstractServerAction.java
@@ -0,0 +1,81 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.Iterator;
+
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.actions.SelectionProviderAction;
+
+import org.eclipse.wst.server.core.IServer;
+/**
+ * An abstract class for an action on a server.
+ */
+public abstract class AbstractServerAction extends SelectionProviderAction {
+	public Shell shell;
+
+	public AbstractServerAction(Shell shell, ISelectionProvider selectionProvider, String name) {
+		super(selectionProvider, name);
+		this.shell = shell;
+		setEnabled(false);
+	}
+
+	/**
+	 * Return true if this server can currently be acted on.
+	 *
+	 * @return boolean
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public abstract boolean accept(IServer server);
+
+	/**
+	 * Perform action on this server.
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public abstract void perform(IServer server);
+
+	public void run() {
+		Iterator iterator = getStructuredSelection().iterator();
+		Object obj = iterator.next();
+		if (obj instanceof IServer) {
+			IServer server = (IServer) obj;
+			if (accept(server))
+				perform(server);
+			selectionChanged(getStructuredSelection());
+		}
+	}
+
+	/**
+	 * Update the enable state.
+	 */
+	public void selectionChanged(IStructuredSelection sel) {
+		if (sel.isEmpty()) {
+			setEnabled(false);
+			return;
+		}
+		boolean enabled = false;
+		Iterator iterator = sel.iterator();
+		while (iterator.hasNext()) {
+			Object obj = iterator.next();
+			if (obj instanceof IServer) {
+				IServer server = (IServer) obj;
+				if (accept(server))
+					enabled = true;
+			} else {
+				setEnabled(false);
+				return;
+			}
+		}
+		setEnabled(enabled);	
+	}
+}
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..2e465e9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/DeleteAction.java
@@ -0,0 +1,81 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.wst.server.core.IElement;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.internal.DeleteServerDialog;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Action for deleting server resources.
+ */
+public class DeleteAction extends Action {
+	protected List deleteList = new ArrayList();
+	protected List deleteExtraList = new ArrayList();
+	protected Shell shell;
+
+	/**
+	 * DeleteAction constructor comment.
+	 */
+	public DeleteAction(Shell shell, IElement serverResource) {
+		this(shell, new IElement[] { serverResource });
+	}
+
+	/**
+	 * DeleteAction constructor comment.
+	 */
+	public DeleteAction(Shell shell, IElement[] serverResources) {
+		super(ServerUIPlugin.getResource("%actionDelete"));
+		this.shell = shell;
+		
+		int size = serverResources.length;
+		for (int i = 0; i < size; i++) {
+			deleteList.add(serverResources[i]);
+		}
+		
+		for (int i = 0; i < size; i++) {
+			if (serverResources[i] instanceof IServer) {
+				IServer server = (IServer) serverResources[i];
+				IServerConfiguration config = server.getServerConfiguration();
+				if (config != null && !deleteList.contains(config))
+					deleteExtraList.add(config);
+			}
+		}
+		
+		// remove configurations that are still referenced
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (!deleteList.contains(server)) {
+				IServerConfiguration config = server.getServerConfiguration();
+				if (deleteExtraList.contains(config))
+					deleteExtraList.remove(config);
+			}
+		}
+	}
+
+	/**
+	 * Invoked when an action occurs. 
+	 */
+	public void run() {
+		DeleteServerDialog dsd = new DeleteServerDialog(shell, deleteList, deleteExtraList);
+		dsd.open();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ModuleSloshAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ModuleSloshAction.java
new file mode 100644
index 0000000..ff236c7
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ModuleSloshAction.java
@@ -0,0 +1,48 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.wst.server.core.IServer;
+/**
+ * 
+ */
+public class ModuleSloshAction extends AbstractServerAction {
+	public ModuleSloshAction(Shell shell, ISelectionProvider selectionProvider, String name) {
+		super(shell, selectionProvider, name);
+	}
+
+	/**
+	 * Return true if this server can currently be acted on.
+	 * @return boolean
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public boolean accept(IServer server) {
+		return true;
+	}
+
+	/**
+	 * Perform action on this server.
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public void perform(final IServer server) {
+		/*if (!ServerUIUtil.promptIfDirty(shell, server))
+			return;
+
+		IServerConfiguration configuration = ServerUtil.getServerConfiguration(server);
+		ModifyModulesWizard wizard = new ModifyModulesWizard(configuration);
+		ClosableWizardDialog dialog = new ClosableWizardDialog(shell, wizard);
+		if (dialog.open() == Window.CANCEL)
+			return;*/
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/MonitorServerAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/MonitorServerAction.java
new file mode 100644
index 0000000..b7fa424
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/MonitorServerAction.java
@@ -0,0 +1,40 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.action.Action;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * Action for monitoring a server.
+ */
+public class MonitorServerAction extends Action {
+	protected IServer server;
+	protected Shell shell;
+
+	/**
+	 * MonitorServerAction constructor comment.
+	 */
+	public MonitorServerAction(Shell shell, IServer server) {
+		super(ServerUIPlugin.getResource("%actionMonitorProperties"));
+		this.shell = shell;
+		this.server = server;
+	}
+
+	/**
+	 * Invoked when an action occurs. 
+	 */
+	public void run() {
+		MonitorServerDialog msd = new MonitorServerDialog(shell, server);
+		msd.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/MonitorServerDialog.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/MonitorServerDialog.java
new file mode 100644
index 0000000..1bb395b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/MonitorServerDialog.java
@@ -0,0 +1,87 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.viewers.MonitorComposite;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Dialog that prompts a user to monitor ports from a given server.
+ */
+public class MonitorServerDialog extends Dialog {
+	protected IServer server;
+	protected MonitorComposite monitorComp;
+
+	/**
+	 * MonitorServerDialog constructor comment.
+	 * @param parentShell org.eclipse.swt.widgets.Shell
+	 * @
+	 */
+	public MonitorServerDialog(Shell parentShell, IServer server) {
+		super(parentShell);
+		this.server = server;
+
+		setBlockOnOpen(true);
+	}
+
+	/**
+	 *
+	 */
+	protected void configureShell(Shell newShell) {
+		super.configureShell(newShell);
+		newShell.setText(ServerUIPlugin.getResource("%dialogMonitorTitle"));
+	}
+	
+	protected void createButtonsForButtonBar(Composite parent) {
+		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+	}
+
+	/**
+	 * 
+	 */
+	protected Control createDialogArea(Composite parent) {
+		// create a composite with standard margins and spacing
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+		composite.setLayout(layout);
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = 550;
+		composite.setLayoutData(data);
+		composite.setFont(parent.getFont());
+		//WorkbenchHelp.setHelp(composite, ContextIds.TERMINATE_SERVER_DIALOG);
+	
+		Label label = new Label(composite, SWT.WRAP);
+		label.setText(ServerUIPlugin.getResource("%dialogMonitorDescription", new String[] { server.getName() } ));
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		label.setLayoutData(data);
+
+		monitorComp = new MonitorComposite(composite, SWT.NONE, null, server);
+		monitorComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
+		
+		Dialog.applyDialogFont(composite);
+	
+		return composite;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/MonitorServerPortAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/MonitorServerPortAction.java
new file mode 100644
index 0000000..df75ffe
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/MonitorServerPortAction.java
@@ -0,0 +1,69 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.Iterator;
+
+import org.eclipse.jface.action.Action;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IServerPort;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Monitor a server port.
+ */
+public class MonitorServerPortAction extends Action {
+	protected Shell shell;
+	protected IServer server;
+	protected IServerPort port;
+	protected IMonitoredServerPort monitoredPort;
+	protected boolean checked;
+	
+	public MonitorServerPortAction(Shell shell, IServer server, IServerPort port) {
+		super(ServerUIPlugin.getResource("%actionMonitorPort", new String[] { port.getPort() + "", port.getName() }));
+		
+		this.shell = shell;
+		this.server = server;
+		this.port = port;
+		
+		Iterator iterator = ServerCore.getServerMonitorManager().getMonitoredPorts(server).iterator();
+		while (iterator.hasNext()) {
+			IMonitoredServerPort msp = (IMonitoredServerPort) iterator.next();
+			if (port.equals(msp.getServerPort()) && msp.isStarted() &&
+					(msp.getContentTypes() == null || (port.getContentTypes() != null && msp.getContentTypes().length == port.getContentTypes().length)))
+				monitoredPort = msp;
+		}
+
+		checked = monitoredPort != null && monitoredPort.isStarted();
+		setChecked(checked);
+	}
+
+	/**
+	 * Enable or disable monitoring.
+	 */
+	public void run() {
+		if (checked) {
+			ServerCore.getServerMonitorManager().removeMonitor(monitoredPort);
+		} else {
+			IServerMonitorManager smm = ServerCore.getServerMonitorManager();
+			if (monitoredPort == null)
+				monitoredPort = smm.createMonitor(server, port, -1, null);
+			
+			try {
+				smm.startMonitor(monitoredPort);
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not monitor", e);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/OpenAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/OpenAction.java
new file mode 100644
index 0000000..359a48e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/OpenAction.java
@@ -0,0 +1,45 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.action.Action;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.ServerUIUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+
+/**
+ * "Open" menu action.
+ */
+public class OpenAction extends Action {
+	protected IServer server;
+
+	/**
+	 * OpenAction constructor comment.
+	 */
+	public OpenAction(IServer server) {
+		super(ServerUIPlugin.getResource("%actionOpen"));
+	
+		this.server = server;
+		setEnabled(server.getServerType() != null);
+	}
+
+	/**
+	 * Implementation of method defined on <code>IAction</code>.
+	 */
+	public void run() {
+		try {
+			ServerUIUtil.editServer(server, server.getServerConfiguration());
+		} catch (Exception e) {
+			Trace.trace("Error editing element", e);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/PublishAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/PublishAction.java
new file mode 100644
index 0000000..d2b38d4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/PublishAction.java
@@ -0,0 +1,51 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.ServerUIUtil;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Publish to a server.
+ */
+public class PublishAction extends AbstractServerAction {
+	public PublishAction(Shell shell, ISelectionProvider selectionProvider, String name) {
+		super(shell, selectionProvider, name);
+		try {
+			selectionChanged((IStructuredSelection) selectionProvider.getSelection());
+		} catch (Exception e) { }
+	}
+
+	/**
+	 * Return true if this server can currently be acted on.
+	 * @return boolean
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public boolean accept(IServer server) {
+		return server.canPublish();
+	}
+
+	/**
+	 * Perform action on this server.
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public void perform(final IServer server) {
+		if (!ServerUIUtil.promptIfDirty(shell, server))
+			return;
+		
+		if (!ServerUIUtil.saveEditors())
+			return;
+
+		ServerUIUtil.publishWithDialog(server, true);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RestartAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RestartAction.java
new file mode 100644
index 0000000..fa02a22
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RestartAction.java
@@ -0,0 +1,98 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerType;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.model.IRestartableServer;
+import org.eclipse.wst.server.ui.ServerUIUtil;
+import org.eclipse.wst.server.ui.internal.ServerStartupListener;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Restart a server.
+ */
+public class RestartAction extends AbstractServerAction {
+	protected String mode;
+
+	public RestartAction(Shell shell, ISelectionProvider selectionProvider, String name) {
+		this(shell, selectionProvider, name, null);
+	}
+
+	public RestartAction(Shell shell, ISelectionProvider selectionProvider, String name, String mode) {
+		super(shell, selectionProvider, name);
+		try {
+			selectionChanged((IStructuredSelection) selectionProvider.getSelection());
+		} catch (Exception e) { }
+		this.mode = mode;
+	}
+
+	/**
+	 * Return true if this server can currently be acted on.
+	 *
+	 * @return boolean
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public boolean accept(IServer server) {
+		String newMode = mode;
+		if (mode == null) {
+			byte state = server.getServerState();
+			newMode = ILaunchManager.RUN_MODE;
+			if (state == IServer.SERVER_STARTED_DEBUG)
+				newMode = ILaunchManager.DEBUG_MODE;
+			else if (state == IServer.SERVER_STARTED_PROFILE)
+				newMode = ILaunchManager.PROFILE_MODE;
+		}
+		return server.getServerType() != null && server.getServerType().getServerStateSet() == IServerType.SERVER_STATE_SET_MANAGED && server.canRestart(newMode);
+	}
+
+	/**
+	 * Perform action on this server.
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public void perform(IServer server) {
+		if (!ServerUIUtil.promptIfDirty(shell, server))
+			return;
+	
+		if (ServerCore.getServerPreferences().isAutoPublishing() && server.shouldPublish()) {
+			// publish first
+			IStatus status = status = ServerUIUtil.publishWithDialog(server, false);
+	
+			if (status == null || status.getSeverity() == IStatus.ERROR) // user cancelled
+				return;
+		}
+	
+		if (!(server instanceof IRestartableServer)) {
+			ServerStartupListener listener = new ServerStartupListener(shell, server, true);
+			listener.setEnabled(true);
+			ServerTableViewer.registerStartupListener(server, listener);
+	
+			ServerUIPlugin.addTerminationWatch(shell, server, ServerUIPlugin.RESTART);
+		}
+	
+		String newMode = mode;
+		if (mode == null) {
+			byte state = server.getServerState();
+			newMode = ILaunchManager.RUN_MODE;
+			if (state == IServer.SERVER_STARTED_DEBUG)
+				newMode = ILaunchManager.DEBUG_MODE;
+			else if (state == IServer.SERVER_STARTED_PROFILE)
+				newMode = ILaunchManager.PROFILE_MODE;
+		}
+		server.restart(newMode);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RestartModuleAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RestartModuleAction.java
new file mode 100644
index 0000000..2294203
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RestartModuleAction.java
@@ -0,0 +1,67 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IProjectModule;
+import org.eclipse.wst.server.core.model.IRestartableModule;
+import org.eclipse.wst.server.ui.internal.EclipseUtil;
+
+/**
+ * Restart a module on a server.
+ */
+public class RestartModuleAction extends Action {
+	protected IRestartableModule rm;
+	protected IModule module;
+
+	public RestartModuleAction(IRestartableModule rm, IModule module) {
+		super();
+		this.rm = rm;
+		this.module = module;
+	
+		setText(module.getName());
+		
+		if (module instanceof IProjectModule) {
+			IProjectModule project = (IProjectModule) module;
+			ImageDescriptor descriptor = EclipseUtil.getProjectImageDescriptor(project.getProject());
+			if (descriptor != null)
+				setImageDescriptor(descriptor);
+		}
+	
+		// enable or disable
+		if (rm == null || module == null) {
+			setEnabled(false);
+			return;
+		}
+
+		/*if (!(dr.getServerState() == IServer2.SERVER_STARTED ||
+			dr.getServerState() == IServer2.SERVER_STARTED_DEBUG) ||
+			!dr.canRestartModule(module)) {
+			setEnabled(false);
+			return;
+		}*/
+	
+		setEnabled(rm.canRestartModule(module));
+	}
+
+	/**
+	 * Implementation of method defined on <code>IAction</code>.
+	 */
+	public void run() {
+		try {
+			rm.restartModule(module, new NullProgressMonitor());
+		} catch (CoreException e) {
+		}
+	}
+}
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
new file mode 100644
index 0000000..1fa4db4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServerTableLabelProvider.java
@@ -0,0 +1,245 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.internal.view.servers;
+
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerType;
+import org.eclipse.wst.server.ui.internal.DefaultServerLabelDecorator;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Server table label provider.
+ */
+public class ServerTableLabelProvider implements ITableLabelProvider {
+	private static final Image[] serverStateImage = new Image[] {
+		null,
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STARTING_1),
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STARTED),
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STARTED_DEBUG),
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STARTED_PROFILE),
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STOPPING_1),
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STOPPED),
+		null};
+	
+	private static final Image[] startingImages = new Image[] {
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STARTING_1),
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STARTING_2),
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STARTING_3)
+	};
+	
+	private static final Image[] stoppingImages = new Image[] {
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STOPPING_1),
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STOPPING_2),
+		ImageResource.getImage(ImageResource.IMG_SERVER_STATE_STOPPING_2)
+	};
+	
+	private static final String[] serverState = new String[] {
+		"",
+		ServerUIPlugin.getResource("%viewStatusStarting"),
+		ServerUIPlugin.getResource("%viewStatusStarted"),
+		ServerUIPlugin.getResource("%viewStatusStartedDebug"),
+		ServerUIPlugin.getResource("%viewStatusStartedProfile"),
+		ServerUIPlugin.getResource("%viewStatusStopping"),
+		ServerUIPlugin.getResource("%viewStatusStopped"),
+		ServerUIPlugin.getResource("%viewStatusUnsupported")};
+		
+	private static final String[] serverStateUnmanaged = new String[] {
+		"",
+		ServerUIPlugin.getResource("%viewStatusStarting4"),
+		ServerUIPlugin.getResource("%viewStatusStarted2"),
+		ServerUIPlugin.getResource("%viewStatusStartedDebug2"),
+		ServerUIPlugin.getResource("%viewStatusStartedProfile2"),
+		ServerUIPlugin.getResource("%viewStatusStopping4"),
+		ServerUIPlugin.getResource("%viewStatusStopped2"),
+		ServerUIPlugin.getResource("%viewStatusUnsupported2")};
+
+	public static final String[] syncState = new String[] {
+		ServerUIPlugin.getResource("%viewSyncOkay"),
+		ServerUIPlugin.getResource("%viewSyncRestart"),
+		ServerUIPlugin.getResource("%viewSyncPublish"),
+		ServerUIPlugin.getResource("%viewSyncRestartPublish"),
+		ServerUIPlugin.getResource("%viewSyncPublishing")};
+	
+	public static final String[] syncStateUnmanaged = new String[] {
+		ServerUIPlugin.getResource("%viewSyncOkay2"),
+		ServerUIPlugin.getResource("%viewSyncRestart2"),
+		ServerUIPlugin.getResource("%viewSyncPublish2"),
+		ServerUIPlugin.getResource("%viewSyncRestartPublish2"),
+		ServerUIPlugin.getResource("%viewSyncPublishing2")};
+		
+	private static final String[] startingText = new String[] {
+		ServerUIPlugin.getResource("%viewStatusStarting1"),
+		ServerUIPlugin.getResource("%viewStatusStarting2"),
+		ServerUIPlugin.getResource("%viewStatusStarting3")};
+	
+	private static final String[] stoppingText = new String[] {
+		ServerUIPlugin.getResource("%viewStatusStopping1"),
+		ServerUIPlugin.getResource("%viewStatusStopping2"),
+		ServerUIPlugin.getResource("%viewStatusStopping3")};
+
+	private int count = 0;
+	
+	protected DefaultServerLabelDecorator decorator = new DefaultServerLabelDecorator();
+	
+	protected IServer defaultServer;
+
+	/**
+	 * ServerTableLabelProvider constructor comment.
+	 */
+	public ServerTableLabelProvider() {
+		super();
+	}
+
+	public void addListener(ILabelProviderListener listener) { }
+
+	public void dispose() {
+		decorator.dispose();
+	}
+
+	public void setDefaultServer(IServer ds) {
+		defaultServer = ds;
+	}
+	
+	public IServer getDefaultServer() {
+		return defaultServer;
+	}
+
+	public Image getColumnImage(Object element, int columnIndex) {
+		IServer server = (IServer) element;
+		if (columnIndex == 0) {
+			if (server.getServerType() != null) {
+				Image image = ImageResource.getImage(server.getServerType().getId());
+				if (defaultServer != null && defaultServer.equals(server)) {
+					Image decorated = decorator.decorateImage(image, element);
+					if (decorated != null)
+						return decorated;
+				}
+				return image;
+			} else
+				return null;
+		} else if (columnIndex == 2) {
+			IServerType serverType = server.getServerType();
+			if (serverType == null)
+				return null;
+			if (serverType.getServerStateSet() == IServerType.SERVER_STATE_SET_PUBLISHED)
+				return null;
+			else return getServerStateImage(server);
+		} else
+			return null;
+	}
+
+	public String getColumnText(Object element, int columnIndex) {
+		IServer server = (IServer) element;
+		if (columnIndex == 0)
+			return notNull(server.getName());
+		else if (columnIndex == 1) {
+			return notNull(server.getHostname());
+		} else if (columnIndex == 2) {
+			IServerType serverType = server.getServerType();
+			if (serverType != null)
+				return getServerStateLabel(server, serverType.getServerStateSet());
+			else
+				return "";
+		} else if (columnIndex == 3) {
+			if (server.getServerType() == null)
+				return "";
+			if (server.getServerType().hasServerConfiguration() && server.getServerConfiguration() == null)
+				return ServerUIPlugin.getResource("%viewNoConfiguration");
+			
+			String serverId = server.getId();
+			if (ServerTableViewer.publishing.contains(serverId))
+				return syncState[4];
+			
+			boolean republish = false;
+			if (server.getConfigurationSyncState() != IServer.SYNC_STATE_IN_SYNC)
+				republish = true;
+			else {
+				if (!server.getUnpublishedModules().isEmpty())
+					republish = true;
+			}
+			
+			int i = 0;
+			if (server.isRestartNeeded())
+				i = 1;
+			if (republish)
+				i += 2;
+			
+			IServerType serverType = server.getServerType();
+			if (serverType.getServerStateSet() == IServerType.SERVER_STATE_SET_MANAGED)
+				return syncState[i];
+			else
+				return syncStateUnmanaged[i];
+		} else
+			return "X";
+	}
+	
+	protected String notNull(String s) {
+		if (s != null)
+			return s;
+		else
+			return "";
+	}
+
+	public boolean isLabelProperty(Object element, String property) {
+		return false;
+	}
+
+	public void removeListener(ILabelProviderListener listener) { }
+
+	/**
+	 * Returns an image representing the server's state.
+	 * @return org.eclipse.jface.parts.IImage
+	 * @param server org.eclipse.wst.server.core.IServer
+	 */
+	protected Image getServerStateImage(IServer server) {
+		byte state = server.getServerState();
+		if (state == IServer.SERVER_STARTING)
+			return startingImages[count];
+		else if (state == IServer.SERVER_STOPPING)
+			return stoppingImages[count];
+		else
+			return serverStateImage[server.getServerState()];
+	}
+	
+	/**
+	 * Returns a string representing the server's state.
+	 *
+	 * @return java.lang.String
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	protected String getServerStateLabel(IServer server, byte stateSet) {
+		if (stateSet == IServerType.SERVER_STATE_SET_PUBLISHED) {
+			return "";
+		} else {
+			if (stateSet == IServerType.SERVER_STATE_SET_MANAGED) {
+				byte state = server.getServerState();
+				if (state == IServer.SERVER_STARTING)
+					return startingText[count];
+				else if (state == IServer.SERVER_STOPPING)
+					return stoppingText[count];
+				else
+					return serverState[server.getServerState()];
+			} else
+				return serverStateUnmanaged[server.getServerState()];
+		}
+	}
+	
+	protected void animate() {
+		count ++;
+		if (count > 2)
+			count = 0;
+	}
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..f1c56c9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServerTableViewer.java
@@ -0,0 +1,477 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.viewers.*;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IPublishListener;
+import org.eclipse.wst.server.core.model.IServerListener;
+import org.eclipse.wst.server.core.model.IServerResourceListener;
+import org.eclipse.wst.server.core.util.PublishAdapter;
+import org.eclipse.wst.server.core.util.ServerResourceAdapter;
+import org.eclipse.wst.server.ui.internal.ServerStartupListener;
+import org.eclipse.wst.server.ui.internal.ServerTree;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.wst.server.ui.internal.view.tree.ServerTreeAction;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.actions.ActionFactory;
+
+/**
+ * Tree view showing servers and their associations.
+ */
+public class ServerTableViewer extends TableViewer {
+	protected static final String ROOT = "root";
+
+	protected IServerResourceListener serverResourceListener;
+	protected IPublishListener publishListener;
+	protected IServerListener serverListener;
+
+	protected static IElement deletedElement = null;
+
+	// servers that are currently publishing and starting
+	protected static List publishing = new ArrayList();
+	protected static List starting = new ArrayList();
+	
+	protected ServerTableLabelProvider labelProvider;
+	protected ISelectionListener dsListener;
+
+	protected static Map startupWatch = new HashMap();
+
+	protected ServersView view;
+	
+	public class ServerContentProvider implements IStructuredContentProvider {
+		public Object[] getElements(Object inputElement) {
+			List list = new ArrayList();
+			Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server = (IServer) iterator.next();
+				if (!server.isPrivate())
+					list.add(server);
+			}
+			return list.toArray();
+		}
+
+		public void inputChanged(Viewer theViewer, Object oldInput, Object newInput) { }
+		
+		public void dispose() { }
+	}
+
+	/*protected void createHover(Shell parent, Point p) {
+		final Shell fShell = new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | SWT.RESIZE | SWT.NO_TRIM);
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = 1;
+		layout.marginWidth = 1;
+		fShell.setLayout(layout);
+		
+		Display display = parent.getDisplay();
+		StyledText text = new StyledText(fShell, SWT.NONE);
+		text.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+		text.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+		text.append("Testing <b>me</b>");
+		
+		fShell.setLocation(p.x, p.y);
+		fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+		fShell.pack();
+		fShell.setVisible(true);
+		
+		Thread t = new Thread() {
+			public void run() {
+				try {
+					Thread.sleep(2000);
+				} catch (Exception e) { }
+				Display.getDefault().asyncExec(new Runnable() {
+					public void run() {
+						fShell.dispose();
+					}
+				});
+			}
+		};
+		t.start();
+	}*/
+	
+	protected Thread thread = null;
+	protected boolean stopThread = false;
+	
+	protected void startThread() {
+		stopThread = false;
+		if (thread != null)
+			return;
+		
+		thread = new Thread("Servers view animator") {
+			public void run() {
+				while (!stopThread) {
+					try {
+						labelProvider.animate();
+						Display.getDefault().asyncExec(new Runnable() {
+							public void run() {
+								if (getTable() != null && !getTable().isDisposed())
+									refresh();
+							}
+						});
+						Thread.sleep(150);
+					} catch (Exception e) {
+						Trace.trace(Trace.FINEST, "Error in animated server view", e);
+					}
+					thread = null;
+				}
+			}
+		};
+		thread.setDaemon(true);
+		thread.start();
+	}
+	
+	protected void stopThread() {
+		stopThread = true;
+	}
+	
+	/**
+	 * ServerTableViewer constructor comment.
+	 */
+	public ServerTableViewer(final ServersView view, final Table table) {
+		super(table);
+		this.view = view;
+		/*table.addMouseTrackListener(new MouseTrackListener() {
+			public void mouseEnter(MouseEvent event) {
+			}
+
+			public void mouseExit(MouseEvent event) {
+			}
+
+			public void mouseHover(MouseEvent event) {
+				createHover(table.getShell(), table.toDisplay(event.x, event.y));
+			}
+		});*/
+	
+		setContentProvider(new ServerContentProvider());
+		labelProvider = new ServerTableLabelProvider();
+		setLabelProvider(labelProvider);
+		setSorter(new ViewerSorter() { });
+	
+		setInput(ROOT);
+	
+		addListeners();
+		
+		IActionBars actionBars = view.getViewSite().getActionBars();
+		actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), new ServerTreeAction(getControl().getShell(), this, "Delete it!", ServerTree.ACTION_DELETE));
+		
+		dsListener = new ISelectionListener() {
+			public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+				if (!(selection instanceof IStructuredSelection))
+					return;
+				IStructuredSelection sel = (IStructuredSelection) selection;
+				final Object obj = sel.getFirstElement();
+				IProject proj = null;
+				if (obj instanceof IResource) {
+					IResource res = (IResource) obj;
+					proj = res.getProject();
+				}
+				if (proj == null) {
+					try {
+						IResource res = (IResource) Platform.getAdapterManager().getAdapter(obj, IResource.class);
+						if (res != null)
+							proj = res.getProject();
+					} catch (Exception e) { }
+				}
+				if (proj != null) {
+					final IProject project = proj;
+					Display.getDefault().asyncExec(new Runnable() {
+						public void run() {
+							if (getTable() == null || getTable().isDisposed())
+								return;
+
+							IServer defaultServer = null;
+							if (project != null) {
+								IProjectProperties props = ServerCore.getProjectProperties(project);
+								defaultServer = props.getDefaultServer();
+							}
+							IServer oldDefaultServer = labelProvider.getDefaultServer();
+							if ((oldDefaultServer == null && defaultServer == null)
+									|| (oldDefaultServer != null && oldDefaultServer.equals(defaultServer)))
+								return;
+							labelProvider.setDefaultServer(defaultServer);
+							
+							if (oldDefaultServer != null)
+								refresh(oldDefaultServer);
+							if (defaultServer != null)
+								refresh(defaultServer);
+						}
+					});
+				}
+			}
+		};
+		view.getViewSite().getPage().addSelectionListener(dsListener);
+	}
+
+	protected void addListeners() {
+		serverResourceListener = new ServerResourceAdapter() {
+			public void serverAdded(IServer server) {
+				addServer(server);
+				server.addServerListener(serverListener);
+				server.addPublishListener(publishListener);
+			}
+			public void serverChanged(IServer server) {
+				refreshServer(server);
+			}
+			public void serverRemoved(IServer server) {
+				removeServer(server);
+				server.removeServerListener(serverListener);
+				server.removePublishListener(publishListener);
+			}
+		};
+		ServerCore.getResourceManager().addResourceListener(serverResourceListener);
+		
+		publishListener = new PublishAdapter() {
+			public void moduleStateChange(IServer server, List parents, IModule module) {
+				refreshServer(server);
+			}
+			
+			public void publishStarting(IServer server, List[] parents, IModule[] module) {
+				handlePublishChange(server, true);
+			}
+			
+			public void publishFinished(IServer server, IPublishStatus globalStatus) {
+				handlePublishChange(server, false);
+			}
+		};
+		
+		serverListener = new IServerListener() {
+			public void serverStateChange(IServer server) {
+				refreshServer(server);
+				int state = server.getServerState();
+				String id = server.getId();
+				if (state == IServer.SERVER_STARTING || state == IServer.SERVER_STOPPING) {
+					if (!starting.contains(id)) {
+						if (starting.isEmpty())
+							startThread();
+						starting.add(id);
+					}
+				} else {
+					if (starting.contains(id)) {
+						starting.remove(id);
+						if (starting.isEmpty())
+							stopThread();
+					}
+				}
+			}
+			public void configurationSyncStateChange(IServer server) {
+				refreshServer(server);
+			}
+			public void restartStateChange(IServer server) {
+				refreshServer(server);
+			}
+			public void modulesChanged(IServer server) {
+				handleServerModulesChanged(server);
+			}
+			public void moduleStateChange(IServer server, IModule module) { }
+		};
+		
+		// add listeners to servers
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			server.addServerListener(serverListener);
+			server.addPublishListener(publishListener);
+		}
+	}
+	
+	/**
+	 * Respond to a configuration being added or deleted.
+	 * @param configuration org.eclipse.wst.server.core.model.IServerConfiguration
+	 * @param add boolean
+	 */
+	protected void configurationChange(IServerConfiguration configuration, boolean add) {
+		if (configuration == null)
+			return;
+
+		if (!add)
+			deletedElement = configuration;
+	
+		List servers = ServerCore.getResourceManager().getServers();
+		Iterator iterator = servers.iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (configuration.equals(server.getServerConfiguration()))
+				refresh(server);
+		}
+		deletedElement = null;
+	}
+	
+	protected void refreshServer(final IServer server) {
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				try {
+					refresh(server);
+					ISelection sel = ServerTableViewer.this.getSelection();
+					ServerTableViewer.this.setSelection(sel);
+				} catch (Exception e) { }
+			}
+		});
+	}
+
+	protected void handleDispose(DisposeEvent event) {
+		stopThread();
+		view.getViewSite().getPage().removeSelectionListener(dsListener);
+
+		IResourceManager rm = ServerCore.getResourceManager();
+		rm.removeResourceListener(serverResourceListener);
+		
+		// remove listeners from server
+		List servers = rm.getServers();
+		Iterator iterator = servers.iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			server.removeServerListener(serverListener);
+			server.removePublishListener(publishListener);
+		}
+	
+		super.handleDispose(event);
+	}
+
+	/**
+	 * Called when the publish state changes.
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void handlePublishChange(IServer server, boolean isPublishing) {
+		String serverId = server.getId();
+		if (isPublishing)
+			publishing.add(serverId);
+		else
+			publishing.remove(serverId);
+	
+		refreshServer(server);
+	}
+	
+	/**
+	 * 
+	 */
+	protected void handleServerModulesChanged(IServer server2) {
+		if (server2 == null)
+			return;
+
+		Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+		while (iterator.hasNext()) {
+			IServer server = (IServer) iterator.next();
+			if (server2.equals(server))
+				refresh(server);
+		}
+	}
+	
+	/**
+	 * Called when an element is added.
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void handleServerResourceAdded(IElement element) {
+		if (element instanceof IServer) {
+			IServer server = (IServer) element;
+			add(server);
+
+		} else if (element instanceof IServerConfiguration) {
+			IServerConfiguration configuration = (IServerConfiguration) element;
+			configurationChange(configuration, true);
+		}
+	}
+	
+	/**
+	 * Called when an element is changed.
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void handleServerResourceChanged(IElement element) {
+		if (element instanceof IServer) {
+			refresh(element);
+		} else if (element instanceof IServerConfiguration) {
+			Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server = (IServer) iterator.next();
+				IServerConfiguration config = server.getServerConfiguration();
+				if (element.equals(config))
+					refresh(server);
+			}
+		}
+	}
+	
+	/**
+	 * Called when an element is removed.
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 */
+	protected void handleServerResourceRemoved(IElement element) {
+		if (element instanceof IServer) {
+			IServer server = (IServer) element;
+			remove(server);
+	
+			String serverId = server.getId();
+			publishing.remove(serverId);
+	
+			view.getViewSite().getActionBars().getStatusLineManager().setMessage(null, null);
+		} else if (element instanceof IServerConfiguration) {
+			IServerConfiguration configuration = (IServerConfiguration) element;
+			configurationChange(configuration, false);
+		}
+	}
+	
+	/**
+	 * Register a startup listener.
+	 *
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 * @param listener org.eclipse.wst.server.core.internal.ServerStartupListener
+	 */
+	protected static void registerStartupListener(IServer server, ServerStartupListener listener) {
+		String id = server.getId();
+		startupWatch.put(id, listener);
+	}
+	
+	/**
+	 * Remove a startup listener.
+	 *
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	protected static void removeStartupListener(IServer server) {
+		/*String ref = ServerCore.getServerRef(server);
+		try {
+			ServerStartupListener listener = (ServerStartupListener) startupWatch.get(ref);
+			if (listener != null)
+				listener.setEnabled(false);
+		} catch (Exception e) {
+		}
+	
+		startupWatch.remove(ref);*/
+	}
+	
+	protected void addServer(final IServer server) {
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				add(server);
+			}
+		});
+	}
+	
+	protected void removeServer(final IServer server) {
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				remove(server);
+			}
+		});
+	}
+}
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..0bd0d37
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServersView.java
@@ -0,0 +1,404 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.IDebugView;
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.*;
+import org.eclipse.wst.server.ui.ServerUIUtil;
+import org.eclipse.wst.server.ui.internal.*;
+import org.eclipse.wst.server.ui.internal.actions.ServerAction;
+import org.eclipse.wst.server.ui.internal.view.tree.DisabledMenuManager;
+import org.eclipse.wst.server.ui.internal.view.tree.SwitchConfigurationAction;
+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.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.*;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * View of server, their configurations and status.
+ */
+public class ServersView extends ViewPart {
+	//private static final String LAUNCH_CONFIGURATION_TYPE_ID = "org.eclipse.wst.server.core.launchConfigurationTypes";
+
+	protected Table table;
+	protected ServerTableViewer tableViewer;
+
+	// actions on a server
+	protected Action[] actions;
+	protected MenuManager restartMenu;
+
+	/**
+	 * ServersView constructor comment.
+	 */
+	public ServersView() {
+		super();
+	}
+	
+	/**
+	 * createPartControl method comment.
+	 */
+	public void createPartControl(Composite parent) {
+		table = new Table(parent, SWT.SINGLE | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.NONE);
+		table.setHeaderVisible(true);
+		table.setLinesVisible(false);
+		table.setLayoutData(new GridData(GridData.FILL_BOTH));
+		table.setFont(parent.getFont());
+		WorkbenchHelp.setHelp(table, ContextIds.VIEW_CONTROL);
+		
+		TableLayout tableLayout = new TableLayout();
+	
+		// add columns
+		TableColumn column = new TableColumn(table, SWT.SINGLE);
+		column.setText(ServerUIPlugin.getResource("%viewServer"));
+		ColumnWeightData colData = new ColumnWeightData(200, 200, true);
+		tableLayout.addColumnData(colData);
+		
+		column = new TableColumn(table, SWT.SINGLE);
+		column.setText(ServerUIPlugin.getResource("%viewHost"));
+		colData = new ColumnWeightData(100, 150, true);
+		tableLayout.addColumnData(colData);
+	
+		column = new TableColumn(table, SWT.SINGLE);
+		column.setText(ServerUIPlugin.getResource("%viewStatus"));
+		colData = new ColumnWeightData(100, 150, true);
+		tableLayout.addColumnData(colData);
+	
+		column = new TableColumn(table, SWT.SINGLE);
+		column.setText(ServerUIPlugin.getResource("%viewSync"));
+		colData = new ColumnWeightData(100, 150, true);
+		tableLayout.addColumnData(colData);
+		
+		table.setLayout(tableLayout);
+	
+		tableViewer = new ServerTableViewer(this, table);
+		initializeActions(tableViewer);
+	
+		table.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				try {
+					/*TableItem item = table.getSelection()[0];
+					IServerResource resource = (IServerResource) item.getData();
+					IServerResourceFactory factory = ServerUtil.getServerResourceFactory(resource);
+					String label = ServerLabelProvider.getInstance().getText(factory);
+					label += " (";
+					label += ServerCore.getResourceManager().getServerResourceLocation(resource).getFullPath().toString().substring(1);
+					label += ")";
+					getViewSite().getActionBars().getStatusLineManager().setMessage(ServerLabelProvider.getInstance().getImage(factory), label);
+					
+					if (resource instanceof IServer) {
+						IServer server = (IServer) resource;
+						ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
+						ILaunch[] launches = launchManager.getLaunches();
+						int size = launches.length;
+						for (int i = size-1; i >= 0; i--) {
+							ILaunchConfiguration config = launches[i].getLaunchConfiguration();
+							if (LAUNCH_CONFIGURATION_TYPE_ID.equals(config.getType().getIdentifier()) &&
+									ServerCore.getServerRef(server).equals(config.getAttribute(SERVER_REF, (String)null))) {
+								selectServerProcess(launches[i]);
+								return;
+							}
+						}
+					}*/
+				} catch (Exception e) {
+					getViewSite().getActionBars().getStatusLineManager().setMessage(null, "");
+				}
+			}
+			public void widgetDefaultSelected(SelectionEvent event) {
+				try {
+					TableItem item = table.getSelection()[0];
+					IServer server = (IServer) item.getData();
+					ServerUIUtil.editServer(server, server.getServerConfiguration());
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Could not open server", e);
+				}
+			}
+		});
+		
+		MenuManager menuManager = new MenuManager("#PopupMenu");
+		menuManager.setRemoveAllWhenShown(true);
+		final Shell shell = table.getShell();
+		menuManager.addMenuListener(new IMenuListener() {
+			public void menuAboutToShow(IMenuManager mgr) {
+				fillContextMenu(shell, mgr);
+			}
+		});
+		Menu menu = menuManager.createContextMenu(parent);
+		table.setMenu(menu);
+		getSite().registerContextMenu(menuManager, tableViewer);
+	}
+
+	protected void selectServerProcess(Object process) {
+		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow() ;
+		if (window != null) {
+			IWorkbenchPage page = window.getActivePage();
+			if (page != null) {
+				IWorkbenchPart part = page.findView(IDebugUIConstants.ID_DEBUG_VIEW);
+				if (part != null) {
+					IDebugView view = (IDebugView)part.getAdapter(IDebugView.class);
+					if (view != null) {
+						Viewer viewer = view.getViewer();
+						if (viewer != null) {
+							viewer.setSelection(new StructuredSelection(process));
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Initialize actions
+	 */
+	public void initializeActions(ISelectionProvider provider) {
+		Shell shell = getSite().getShell();
+
+		// create the debug action
+		Action debugAction = new StartAction(shell, provider, "debug", ILaunchManager.DEBUG_MODE);
+		debugAction.setToolTipText(ServerUIPlugin.getResource("%actionDebugToolTip"));
+		debugAction.setText(ServerUIPlugin.getResource("%actionDebug"));
+		debugAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_START_DEBUG));
+		debugAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_START_DEBUG));
+		debugAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_START_DEBUG));
+	
+		// create the start action
+		Action runAction = new StartAction(shell, provider, "start", ILaunchManager.RUN_MODE);
+		runAction.setToolTipText(ServerUIPlugin.getResource("%actionStartToolTip"));
+		runAction.setText(ServerUIPlugin.getResource("%actionStart"));
+		runAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_START));
+		runAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_START));
+		runAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_START));
+		
+		// create the profile action
+		Action profileAction = new StartAction(shell, provider, "profile", ILaunchManager.PROFILE_MODE);
+		profileAction.setToolTipText(ServerUIPlugin.getResource("%actionProfileToolTip"));
+		profileAction.setText(ServerUIPlugin.getResource("%actionProfile"));
+		profileAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_START_PROFILE));
+		profileAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_START_PROFILE));
+		profileAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_START_PROFILE));
+	
+		// create the restart menu
+		restartMenu = new MenuManager(ServerUIPlugin.getResource("%actionRestart"));
+		
+		Action restartAction = new RestartAction(shell, provider, "restartDebug", ILaunchManager.DEBUG_MODE);
+		restartAction.setToolTipText(ServerUIPlugin.getResource("%actionDebugToolTip"));
+		restartAction.setText(ServerUIPlugin.getResource("%actionDebug"));
+		restartAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_START_DEBUG));
+		restartAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_START_DEBUG));
+		restartAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_START_DEBUG));
+		restartMenu.add(restartAction);
+		
+		restartAction = new RestartAction(shell, provider, "restartRun", ILaunchManager.RUN_MODE);
+		restartAction.setToolTipText(ServerUIPlugin.getResource("%actionRestartToolTip"));
+		restartAction.setText(ServerUIPlugin.getResource("%actionStart"));
+		restartAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_START));
+		restartAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_START));
+		restartAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_START));
+		restartMenu.add(restartAction);
+		
+		restartAction = new RestartAction(shell, provider, "restartProfile", ILaunchManager.PROFILE_MODE);
+		restartAction.setToolTipText(ServerUIPlugin.getResource("%actionRestartToolTip"));
+		restartAction.setText(ServerUIPlugin.getResource("%actionProfile"));
+		restartAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_START_PROFILE));
+		restartAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_START_PROFILE));
+		restartAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_START_PROFILE));
+		restartMenu.add(restartAction);
+		
+		// create the restart action
+		restartAction = new RestartAction(shell, provider, "restart");
+		restartAction.setToolTipText(ServerUIPlugin.getResource("%actionRestartToolTip"));
+		restartAction.setText(ServerUIPlugin.getResource("%actionRestart"));
+		restartAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_RESTART));
+		restartAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_RESTART));
+		restartAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_RESTART));
+
+		// create the stop action
+		Action stopAction = new StopAction(shell, provider, "stop", IServerType.SERVER_STATE_SET_MANAGED);
+		stopAction.setToolTipText(ServerUIPlugin.getResource("%actionStopToolTip"));
+		stopAction.setText(ServerUIPlugin.getResource("%actionStop"));
+		stopAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_STOP));
+		stopAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_STOP));
+		stopAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_STOP));
+
+		// create the disconnect action
+		Action disconnectAction = new StopAction(shell, provider, "disconnect", IServerType.SERVER_STATE_SET_ATTACHED);
+		disconnectAction.setToolTipText(ServerUIPlugin.getResource("%actionStopToolTip2"));
+		disconnectAction.setText(ServerUIPlugin.getResource("%actionStop2"));
+		disconnectAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_DISCONNECT));
+		disconnectAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_DISCONNECT));
+		disconnectAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_DISCONNECT));
+
+		// create the publish action
+		Action publishAction = new PublishAction(shell, provider, "publish");
+		publishAction.setToolTipText(ServerUIPlugin.getResource("%actionPublishToolTip"));
+		publishAction.setText(ServerUIPlugin.getResource("%actionPublish"));
+		publishAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ELCL_PUBLISH));
+		publishAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CLCL_PUBLISH));
+		publishAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DLCL_PUBLISH));
+		
+		// create the module slosh dialog action
+		Action addModuleAction = new ModuleSloshAction(shell, provider, "modules");
+		addModuleAction.setToolTipText(ServerUIPlugin.getResource("%actionModifyModulesToolTip"));
+		addModuleAction.setText(ServerUIPlugin.getResource("%actionModifyModules"));
+		addModuleAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ETOOL_MODIFY_MODULES));
+		addModuleAction.setHoverImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_CTOOL_MODIFY_MODULES));
+		addModuleAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DTOOL_MODIFY_MODULES));
+		
+		actions = new Action[8];
+		actions[0] = debugAction;
+		actions[1] = runAction;
+		actions[2] = profileAction;
+		actions[3] = restartAction;
+		actions[4] = stopAction;
+		actions[5] = disconnectAction;
+		actions[6] = publishAction;
+		actions[7] = addModuleAction;
+		
+		// add toolbar buttons
+		IContributionManager cm = getViewSite().getActionBars().getToolBarManager();
+		for (int i = 0; i < actions.length - 1; i++) {
+			cm.add(actions[i]);
+		}
+	}
+	
+	protected void fillContextMenu(Shell shell, IMenuManager menu) {
+		// get selection but avoid no selection or multiple selection
+		IServer server = null;
+		IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection();
+		if (!selection.isEmpty()) {
+			Iterator iterator = selection.iterator();
+			server = (IServer) iterator.next();
+			if (iterator.hasNext())
+				server = null;
+		}
+		
+		// new action
+		MenuManager newMenu = new MenuManager(ServerUIPlugin.getResource("%actionNew"));
+		ServerTree.fillNewContextMenu(null, selection, newMenu);
+		menu.add(newMenu);
+		
+		// open action
+		if (server != null) {
+			menu.add(new OpenAction(server));
+			menu.add(new Separator());
+			
+			menu.add(new DeleteAction(shell, server));
+			menu.add(new Separator());
+		
+			// server actions
+			for (int i = 0; i < actions.length - 1; i++) {
+				if (i == 3)
+					menu.add(restartMenu);
+				else
+					menu.add(actions[i]);
+			}
+		
+			// switch config
+			if (server.getServerType() != null && server.getServerType().hasServerConfiguration()) {
+				MenuManager menuManager = new MenuManager(ServerUIPlugin.getResource("%actionSwitchConfiguration"));
+				menuManager.add(new SwitchConfigurationAction(shell, ServerUIPlugin.getResource("%viewNoConfiguration"), server, null));
+	
+				List configs = ServerUtil.getSupportedServerConfigurations(server);
+				Iterator iterator = configs.iterator();
+				while (iterator.hasNext()) {
+					IServerConfiguration config = (IServerConfiguration) iterator.next();
+					menuManager.add(new SwitchConfigurationAction(shell, config.getName(), server, config));
+				}
+	
+				menu.add(menuManager);
+			}
+			
+			// monitor
+			if (server.getServerType() != null && server.getServerType().isMonitorable()) {
+				final MenuManager menuManager = new MenuManager(ServerUIPlugin.getResource("%actionMonitor"));
+				
+				final IServer server2 = server;
+				final Shell shell2 = shell;
+				menuManager.addMenuListener(new IMenuListener() {
+					public void menuAboutToShow(IMenuManager manager) {
+						menuManager.removeAll();
+						if (server2.isDelegatePluginActivated()) {
+							IServerDelegate delegate = server2.getDelegate();
+							if (delegate instanceof IMonitorableServer) {
+								Iterator iterator = ((IMonitorableServer) delegate).getServerPorts().iterator();
+								while (iterator.hasNext()) {
+									IServerPort port = (IServerPort) iterator.next();
+									if (!port.isAdvanced()) {
+										menuManager.add(new MonitorServerPortAction(shell2, server2, port));
+									}
+								}
+							}
+						}
+						
+						menuManager.add(new MonitorServerAction(shell2, server2));
+					}
+				});
+				
+				// add an initial menu item so that the menu appears correctly
+				menuManager.add(new MonitorServerAction(shell, server));
+				menu.add(menuManager);
+			}
+		}
+	
+		if (server != null && server.isDelegateLoaded()) {
+			IServerDelegate delegate = server.getDelegate();
+			if (delegate instanceof IRestartableModule) {
+				menu.add(new Separator());
+		
+				MenuManager restartProjectMenu = new MenuManager(ServerUIPlugin.getResource("%actionRestartProject"));
+				IRestartableModule restartable = (IRestartableModule) delegate;
+		
+				if (server != null) {
+					Iterator iterator = ServerUtil.getAllContainedModules(server).iterator();
+					while (iterator.hasNext()) {
+						IModule module = (IModule) iterator.next();
+						Action action = new RestartModuleAction(restartable, module);
+						restartProjectMenu.add(action);
+					}
+				}
+				if (restartProjectMenu.isEmpty())
+					menu.add(new DisabledMenuManager(ServerUIPlugin.getResource("%actionRestartProject")));
+				else
+					menu.add(restartProjectMenu);
+			}
+		}
+		
+		if (server != null) {
+			ServerAction.addServerMenuItems(shell, menu, server);
+		}
+	
+		menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+		menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS+"-end"));
+	}
+	
+	/**
+	 * 
+	 */
+	public void setFocus() {
+		if (table != null)
+			table.setFocus();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/StartAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/StartAction.java
new file mode 100644
index 0000000..ee418ec
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/StartAction.java
@@ -0,0 +1,64 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.ServerUIUtil;
+import org.eclipse.wst.server.ui.internal.EclipseUtil;
+import org.eclipse.wst.server.ui.internal.ServerStartupListener;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Start a server.
+ */
+public class StartAction extends AbstractServerAction {
+	protected String launchMode = ILaunchManager.RUN_MODE;
+	
+	public StartAction(Shell shell, ISelectionProvider selectionProvider, String name, String launchMode) {
+		super(shell, selectionProvider, name);
+		this.launchMode = launchMode;
+		try {
+			selectionChanged((IStructuredSelection) selectionProvider.getSelection());
+		} catch (Exception e) { }
+	}
+
+	/**
+	 * Return true if this server can currently be acted on.
+	 * @return boolean
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public boolean accept(IServer server) {
+		return server.canStart(launchMode);
+	}
+
+	/**
+	 * Perform action on this server.
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public void perform(final IServer server) {
+		if (!ServerUIUtil.promptIfDirty(shell, server))
+			return;				
+	
+		if (!ServerUIUtil.saveEditors())
+			return;
+		
+		if (!ServerUIUtil.publish(server))
+			return;
+		
+		ServerStartupListener listener = new ServerStartupListener(shell, server);
+		try {
+			EclipseUtil.startServer(shell, server, launchMode, listener);
+		} catch (CoreException e) { }
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/StopAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/StopAction.java
new file mode 100644
index 0000000..7e05559
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/StopAction.java
@@ -0,0 +1,65 @@
+package org.eclipse.wst.server.ui.internal.view.servers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Stop (terminate) a server.
+ */
+public class StopAction extends AbstractServerAction {
+	protected byte serverStateSet;
+
+	public StopAction(Shell shell, ISelectionProvider selectionProvider, String name, byte serverStateSet) {
+		super(shell, selectionProvider, name);
+		this.serverStateSet = serverStateSet;
+		try {
+			selectionChanged((IStructuredSelection) selectionProvider.getSelection());
+		} catch (Exception e) { }
+	}
+
+	/**
+	 * Return true if this server can currently be acted on.
+	 * @return boolean
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public boolean accept(IServer server) {
+		return server.getServerType() != null && server.getServerType().getServerStateSet() == serverStateSet && server.canStop();
+	}
+
+	/**
+	 * Perform action on this server.
+	 * @param server org.eclipse.wst.server.core.model.IServer
+	 */
+	public void perform(final IServer server) {
+		ServerTableViewer.removeStartupListener(server);
+		
+		ServerUIPlugin.addTerminationWatch(shell, server, ServerUIPlugin.STOP);
+	
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				MessageDialog dialog = new MessageDialog(shell, ServerUIPlugin.getResource("%defaultDialogTitle"), null,
+					ServerUIPlugin.getResource("%dialogStoppingServer", server.getName()), MessageDialog.INFORMATION, new String[0], 0);
+				dialog.setBlockOnOpen(false);
+				dialog.open();
+	
+				server.stop();
+				dialog.close();
+			}
+		});
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ConfigurationProxyResourceAdapter.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ConfigurationProxyResourceAdapter.java
new file mode 100644
index 0000000..88e73a4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ConfigurationProxyResourceAdapter.java
@@ -0,0 +1,122 @@
+package org.eclipse.wst.server.ui.internal.view.tree;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerLabelProvider;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+/**
+ *
+ */
+public class ConfigurationProxyResourceAdapter implements IAdaptable, IWorkbenchAdapter, IServerElementTag {
+	private static final Object[] NO_CHILDREN = new Object[0];
+	
+	public static IServerConfiguration deleted;
+
+	protected IServer server;
+	protected Object parent;
+
+	public ConfigurationProxyResourceAdapter(Object parent, IServer server) {
+		super();
+		this.parent = parent;
+		this.server = server;
+	}
+
+	/*
+	 * @see IAdaptable#getAdapter(Class)
+	 */
+	public Object getAdapter(Class adapter) {
+		if (adapter.equals(IAdaptable.class))
+			return this;
+		else if (adapter.equals(IWorkbenchAdapter.class))
+			return this;
+		else
+			return Platform.getAdapterManager().getAdapter(this, adapter);
+	}
+	
+	public Object[] getChildren(Object o) {
+		return NO_CHILDREN;
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getImageDescriptor(Object)
+	 */
+	public ImageDescriptor getImageDescriptor(Object object) {
+		IServerConfiguration config = server.getServerConfiguration();
+		if (config != null && config != deleted)
+			return ((ServerLabelProvider)ServerUICore.getLabelProvider()).getImageDescriptor(config);
+		else
+			return ImageResource.getImageDescriptor(ImageResource.IMG_SERVER_CONFIGURATION_MISSING);
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getLabel(Object)
+	 */
+	public String getLabel(Object o) {
+		IServerConfiguration config = server.getServerConfiguration();
+		if (config != null && config != deleted)
+			return config.getName();
+		else
+			return ServerUIPlugin.getResource("%viewNoConfiguration");
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getParent(Object)
+	 */
+	public Object getParent(Object o) {
+		return parent;
+	}
+
+	/**
+	 * Return true if the object is the same as this object.
+	 * @return boolean
+	 * @param obj java.lang.Object
+	 */
+	public boolean equals(Object obj) {
+		if (obj instanceof ConfigurationProxyResourceAdapter) {
+			ConfigurationProxyResourceAdapter proxy = (ConfigurationProxyResourceAdapter) obj;
+
+			IServer inst = proxy.getServer();
+			if ((server == null && inst != null) ||
+				server != null && !server.equals(inst))
+				return false;
+	
+			return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Return the server.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IServer
+	 */
+	public IServer getServer() {
+		return server;
+	}
+	
+	public int hashCode() {
+		if (server != null) {
+			IFile file = server.getFile();
+			return file.hashCode();
+		} else
+			return 0;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/DisabledMenuManager.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/DisabledMenuManager.java
new file mode 100644
index 0000000..f124d58
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/DisabledMenuManager.java
@@ -0,0 +1,24 @@
+package org.eclipse.wst.server.ui.internal.view.tree;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.action.MenuManager;
+/**
+ * 
+ */
+public class DisabledMenuManager extends MenuManager {
+	public DisabledMenuManager(String label) {
+		super(label);
+	}
+	public boolean isEnabled() {
+		return false;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/IServerElementTag.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/IServerElementTag.java
new file mode 100644
index 0000000..edea318
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/IServerElementTag.java
@@ -0,0 +1,17 @@
+package org.eclipse.wst.server.ui.internal.view.tree;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+/**
+ * Tagging interface for identifying elements on a server tree.
+ */
+public interface IServerElementTag {
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ModuleResourceAdapter.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ModuleResourceAdapter.java
new file mode 100644
index 0000000..f76e8a3
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ModuleResourceAdapter.java
@@ -0,0 +1,121 @@
+package org.eclipse.wst.server.ui.internal.view.tree;
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.util.MissingModule;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ServerLabelProvider;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+/**
+ *
+ */
+public class ModuleResourceAdapter implements IAdaptable, IWorkbenchAdapter, IServerElementTag {
+	private static final Object[] NO_CHILDREN = new Object[0];
+
+	protected IServer server;
+	protected IModule module;
+	protected Object parent;
+
+	public ModuleResourceAdapter(Object parent, IServer server, IModule module) {
+		super();
+		this.parent = parent;
+		this.server = server;
+		this.module = module;
+	}
+
+	/*
+	 * @see IAdaptable#getAdapter(Class)
+	 */
+	public Object getAdapter(Class adapter) {
+		if (adapter.equals(IAdaptable.class))
+			return this;
+		else if (adapter.equals(IWorkbenchAdapter.class))
+			return this;
+		else
+			return Platform.getAdapterManager().getAdapter(this, adapter);
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getChildren(Object)
+	 */
+	public Object[] getChildren(Object o) {
+		List childModules = server.getChildModules(module);
+		if (childModules == null)
+			return NO_CHILDREN;
+		Iterator iterator = childModules.iterator();
+
+		List child = new ArrayList();
+		while (iterator.hasNext()) {
+			IModule module2 = (IModule) iterator.next();
+			child.add(new ModuleResourceAdapter(this, server, module2));
+		}
+
+		ModuleResourceAdapter[] adapters = new ModuleResourceAdapter[child.size()];
+		child.toArray(adapters);
+		return adapters;
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getImageDescriptor(Object)
+	 */
+	public ImageDescriptor getImageDescriptor(Object object) {
+		return ((ServerLabelProvider)ServerUICore.getLabelProvider()).getImageDescriptor(module);
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getLabel(Object)
+	 */
+	public String getLabel(Object o) {
+		if (module == null)
+			return "";
+		else if (module instanceof MissingModule)
+			return "(" + module.getName() + ")";
+		else
+			return module.getName();
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getParent(Object)
+	 */
+	public Object getParent(Object o) {
+		return parent;
+	}
+	
+	public IModule getModules() {
+		return module;
+	}
+	
+	public IServer getServer() {
+		return server;
+	}
+	
+	public int hashCode() {
+		int hash = 0;
+		if (server != null) {
+			IFile file = server.getFile();
+			if (file != null)
+				hash = file.hashCode();
+		}
+		if (module != null)
+			hash += module.hashCode();
+		return hash;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ServerElementAdapter.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ServerElementAdapter.java
new file mode 100644
index 0000000..e7be49e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ServerElementAdapter.java
@@ -0,0 +1,169 @@
+package org.eclipse.wst.server.ui.internal.view.tree;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.wst.server.core.IElement;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ServerLabelProvider;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+/**
+ * 
+ */
+public class ServerElementAdapter implements IAdaptable, IWorkbenchAdapter, IServerElementTag {
+	private static final Object[] NO_CHILDREN = new Object[0];
+
+	protected IElement resource;
+	protected Object parent;
+	protected byte flags;
+
+	public ServerElementAdapter(Object parent, IElement resource) {
+		this.parent = parent;
+		this.resource = resource;
+	}
+	
+	public void setFlags(byte b) {
+		flags = b;
+	}
+	
+	public byte getFlags() {
+		return flags;
+	}
+
+	/*
+	 * @see IAdaptable#getAdapter(Class)
+	 */
+	public Object getAdapter(Class adapter) {
+		if (adapter.equals(IAdaptable.class))
+			return this;
+		else if (adapter.equals(IWorkbenchAdapter.class))
+			return this;
+		/*else if (adapter.equals(IResource.class)) {
+			IResourceManager rm = ServerCore.getResourceManager();
+			return rm.getServerResourceLocation(resource);
+		}*/
+		else
+			return Platform.getAdapterManager().getAdapter(this, adapter);
+	}
+
+	public Object[] getChildren(Object o) {
+		return NO_CHILDREN;
+	}
+	
+	/*
+	 * @see IWorkbenchAdapter#getChildren(Object)
+	 */
+	public Object[] getChildren() {
+		if (resource instanceof IServer) {
+			IServer server = (IServer) resource;
+			IServerConfiguration configuration = server.getServerConfiguration();
+			if (configuration == null)
+				//return new Object[] { new TextResourceAdapter(this, TextResourceAdapter.STYLE_NO_CONFIGURATION) };
+				return new Object[] { new ConfigurationProxyResourceAdapter(this, server) };
+				//return NO_CHILDREN;
+
+			IModule[] modules = server.getModules();
+			if (modules == null || modules.length == 0) {
+				//return new Object[] { new TextResourceAdapter(this, TextResourceAdapter.STYLE_NO_MODULES)};
+				return NO_CHILDREN;
+			} else {
+				int size = modules.length;
+				Object[] obj = new Object[size];
+				for (int i = 0; i < size; i++)
+					obj[i] = new ModuleResourceAdapter(this, server, modules[i]);
+
+				return obj;
+			}
+		}/* else if (resource instanceof IServerConfiguration) {
+			IServerConfiguration configuration = (IServerConfiguration) resource;
+			
+			List list = new ArrayList();
+			
+			// add modules
+			IModule[] modules = server.getModules();
+			if (modules == null || modules.length == 0) {
+				//list.add(new TextResourceAdapter(this, TextResourceAdapter.STYLE_NO_MODULES));
+			} else {
+				int size = modules.length;
+				for (int i = 0; i < size; i++)
+					list.add(new ModuleResourceAdapter(this, configuration, modules[i]));
+			}
+
+			Object[] obj = new Object[list.size()];
+			list.toArray(obj);
+			return obj;
+		}*/
+		return NO_CHILDREN;
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getImageDescriptor(Object)
+	 */
+	public ImageDescriptor getImageDescriptor(Object object) {
+		/*try {
+			IServerResourceFactory factory = ServerUtil.getServerResourceFactory(resource);
+			String icon = factory.getConfigurationElement().getAttribute("icon");
+			URL url = factory.getConfigurationElement().getDeclaringExtension().getDeclaringPluginDescriptor().getInstallURL();
+			return ImageDescriptor.createFromURL(new URL(url, icon));
+		} catch (Exception e) {
+			Trace.trace("Error getting image descriptor", e);
+		}*/
+		return ((ServerLabelProvider)ServerUICore.getLabelProvider()).getImageDescriptor(resource);
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getLabel(Object)
+	 */
+	public String getLabel(Object o) {
+		return ServerUICore.getLabelProvider().getText(resource);
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getParent(Object)
+	 */
+	public Object getParent(Object o) {
+		return parent;
+	}
+
+	public IElement getServerResource() {
+		return resource;
+	}
+	
+	protected IFile getFile() {
+		if (resource instanceof IServer)
+			return ((IServer) resource).getFile();
+		else if (resource instanceof IServerConfiguration)
+			return ((IServerConfiguration) resource).getFile();
+		else
+			return null;
+	}
+	
+	public boolean equals(Object obj) {
+		if (!(obj instanceof ServerElementAdapter))
+			return false;
+		
+		ServerElementAdapter adapter = (ServerElementAdapter) obj;
+		IFile file1 = getFile();
+		IFile file2 = adapter.getFile();
+		return ((file1 == null && file2 == null)) ||
+			(file1 != null && file1.equals(file2));
+	}
+	
+	public int hashCode() {
+		return getFile().hashCode();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ServerRootAdapter.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ServerRootAdapter.java
new file mode 100644
index 0000000..c2909ce
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ServerRootAdapter.java
@@ -0,0 +1,79 @@
+package org.eclipse.wst.server.ui.internal.view.tree;
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+/**
+ * 
+ */
+public class ServerRootAdapter implements IAdaptable, IWorkbenchAdapter {
+	protected Object[] children;
+
+	public ServerRootAdapter() { }
+	
+	public void setChildren(Object[] obj) {
+		children = obj;
+	}
+
+	/*
+	 * @see IAdaptable#getAdapter(Class)
+	 */
+	public Object getAdapter(Class adapter) {
+		if (adapter.equals(IAdaptable.class))
+			return this;
+		else if (adapter.equals(IWorkbenchAdapter.class))
+			return this;
+		else
+			return Platform.getAdapterManager().getAdapter(this, adapter);
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getChildren(Object)
+	 */
+	public Object[] getChildren(Object o) {
+		return children;
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getImageDescriptor(Object)
+	 */
+	public ImageDescriptor getImageDescriptor(Object object) {
+		return null;
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getLabel(Object)
+	 */
+	public String getLabel(Object o) {
+		return "Server Root";
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getParent(Object)
+	 */
+	public Object getParent(Object o) {
+		return null;
+	}
+	
+	public boolean equals(Object obj) {
+		if (!(obj instanceof ServerRootAdapter))	
+			return false;
+		
+		ServerRootAdapter adapter = (ServerRootAdapter) obj;
+		return (adapter.children.equals(children));
+	}
+	
+	public int hashCode() {
+		return 0;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ServerTreeAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ServerTreeAction.java
new file mode 100644
index 0000000..b74a40b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/ServerTreeAction.java
@@ -0,0 +1,59 @@
+package org.eclipse.wst.server.ui.internal.view.tree;
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.wst.server.ui.internal.ServerTree;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.actions.SelectionProviderAction;
+/**
+ * 
+ */
+public class ServerTreeAction extends SelectionProviderAction {
+	protected Shell shell;
+	protected byte action;
+
+	public ServerTreeAction(Shell shell, ISelectionProvider provider, String label, byte action) {
+		super(provider, label);
+		this.shell = shell;
+		this.action = action;
+		setEnabled(ServerTree.isActionEnabled(getSelection(), action));
+	}
+	
+	/**
+	 * Notifies this action that the given (non-structured) selection has changed
+	 * in the selection provider.
+	 * <p>
+	 * The <code>SelectionProviderAction</code> implementation of this method
+	 * does nothing. Subclasses may reimplement to react to this selection change.
+	 * </p>
+	 *
+	 * @param selection the new selection
+	 */
+	public void selectionChanged(ISelection selection) {
+		setEnabled(ServerTree.isActionEnabled(selection, action));
+	}
+	
+	public void selectionChanged(IStructuredSelection selection) {
+		setEnabled(ServerTree.isActionEnabled(selection, action));
+	}
+	
+	/**
+	 * The default implementation of this <code>IAction</code> method
+	 * does nothing.  Subclasses should override this method
+	 * if they do not need information from the triggering event,
+	 * or override <code>run(Event)</code> if they do.
+	 */
+	public void run() {
+		ServerTree.performAction(shell, getSelection(), action);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/SwitchConfigurationAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/SwitchConfigurationAction.java
new file mode 100644
index 0000000..b69110b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/SwitchConfigurationAction.java
@@ -0,0 +1,90 @@
+package org.eclipse.wst.server.ui.internal.view.tree;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.IServerType;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.core.util.ProgressUtil;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.EclipseUtil;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerLabelProvider;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Action to add or remove configuration to/from a server.
+ */
+public class SwitchConfigurationAction extends Action {
+	protected IServer server;
+	protected IServerConfiguration config;
+	protected Shell shell;
+	protected IStatus status;
+
+	/**
+	 * SwitchConfigurationAction constructor comment.
+	 */
+	public SwitchConfigurationAction(Shell shell, String label, IServer server, IServerConfiguration config) {
+		super(label);
+		this.shell = shell;
+		this.server = server;
+		this.config = config;
+
+		IServerConfiguration tempConfig = server.getServerConfiguration();
+		if ((tempConfig == null && config == null) || (tempConfig != null && tempConfig.equals(config)))
+			setChecked(true);
+
+		if (config == null)
+			setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_SERVER_CONFIGURATION_NONE));
+		else
+			setImageDescriptor(((ServerLabelProvider)ServerUICore.getLabelProvider()).getImageDescriptor(config));
+		
+		IServerType type = server.getServerType();
+		if (type.getServerStateSet() == IServerType.SERVER_STATE_SET_MANAGED &&
+				server.getServerState() != IServer.SERVER_STOPPED)
+			setEnabled(false);
+	}
+	
+	public void run() {
+		IServerConfiguration tempConfig = server.getServerConfiguration();
+		if ((tempConfig == null && config == null) || (tempConfig != null && tempConfig.equals(config)))
+			return;
+			
+		if (!EclipseUtil.validateEdit(shell, server))
+			return;
+
+		IRunnableWithProgress runnable = new IRunnableWithProgress() {
+			public void run(IProgressMonitor monitor) {
+				try {
+					monitor = ProgressUtil.getMonitorFor(monitor);
+					IServerWorkingCopy workingCopy = server.getWorkingCopy();
+					workingCopy.setServerConfiguration(config);
+					workingCopy.save(monitor);
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Could not save configuration", e);
+				}
+			}
+		};
+
+		try {
+			ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
+			dialog.run(true, true, runnable);
+		} catch (Exception e) {
+			Trace.trace("Error switching server configuration", e);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/TextResourceAdapter.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/TextResourceAdapter.java
new file mode 100644
index 0000000..bb1c693
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/tree/TextResourceAdapter.java
@@ -0,0 +1,171 @@
+package org.eclipse.wst.server.ui.internal.view.tree;
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.wst.server.core.IElement;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.ServerImageResource;
+import org.eclipse.wst.server.ui.internal.ServerTreeContentProvider;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+/**
+ * 
+ */
+public class TextResourceAdapter implements IAdaptable, IWorkbenchAdapter, IServerElementTag {
+	protected Object parent;
+	protected byte thisStyle;
+	
+	public static IElement deleted;
+	
+	public final static byte STYLE_SERVERS = 0;
+	public final static byte STYLE_CONFIGURATIONS = 1;
+	//public final static byte STYLE_SERVERS_AND_CONFIGURATIONS = 2;
+	//public final static byte STYLE_NO_CONFIGURATION = 3;
+	public final static byte STYLE_NO_MODULES = 4;
+	public final static byte STYLE_NO_SERVERS = 5;
+	public final static byte STYLE_LOOSE_CONFIGURATIONS = 6;
+
+	public TextResourceAdapter(Object parent, byte thisStyle) {
+		this.parent = parent;
+		this.thisStyle = thisStyle;
+	}
+	
+	public byte getStyle() {
+		return thisStyle;
+	}
+	
+	public void setStyle(byte b) {
+		thisStyle = b;
+	}
+
+	/*
+	 * @see IAdaptable#getAdapter(Class)
+	 */
+	public Object getAdapter(Class adapter) {
+		if (adapter.equals(IAdaptable.class))
+			return this;
+		else if (adapter.equals(IWorkbenchAdapter.class))
+			return this;
+		else
+			return Platform.getAdapterManager().getAdapter(this, adapter);
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getChildren(Object)
+	 */
+	public Object[] getChildren(Object o) {
+		if (thisStyle == STYLE_NO_MODULES || thisStyle == STYLE_NO_SERVERS)
+			return new Object[0];
+		if (thisStyle == STYLE_LOOSE_CONFIGURATIONS) {
+			IServerConfiguration[] looseCfg = ServerTreeContentProvider.getLooseConfigurations();
+			int size = looseCfg.length;
+			Object[] obj = new Object[size];
+			for (int i = 0; i < size; i++) {
+				obj[i] = new ServerElementAdapter(this, looseCfg[i]);
+			}
+			
+			return obj;
+		}
+		/*else if (thisStyle == STYLE_SERVERS_AND_CONFIGURATIONS) 
+			return new Object[] {
+				new TextResourceAdapter(this, STYLE_SERVERS),
+				new TextResourceAdapter(this, STYLE_CONFIGURATIONS)
+			};*/
+
+		Iterator iterator = null;
+		if (thisStyle == STYLE_SERVERS)
+			iterator = ServerCore.getResourceManager().getServers().iterator();
+		else if (thisStyle == STYLE_CONFIGURATIONS)
+			iterator = ServerCore.getResourceManager().getServerConfigurations().iterator();
+
+		List list = new ArrayList();
+		while (iterator.hasNext()) {
+			IElement resource = (IElement) iterator.next();
+			if (resource != deleted)
+				list.add(new ServerElementAdapter(this, resource));
+		}
+		return list.toArray();
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getImageDescriptor(Object)
+	 */
+	public ImageDescriptor getImageDescriptor(Object object) {
+		if (thisStyle == STYLE_SERVERS)
+			return ServerImageResource.getImageDescriptor(ServerImageResource.IMG_SERVER_FOLDER);
+		else if (thisStyle == STYLE_CONFIGURATIONS || thisStyle == STYLE_LOOSE_CONFIGURATIONS)
+			return ServerImageResource.getImageDescriptor(ServerImageResource.IMG_SERVER_CONFIGURATION_FOLDER);
+		//else if (thisStyle == STYLE_SERVERS_AND_CONFIGURATIONS)
+		//	return ServerImageResource.getImageDescriptor(ServerImageResource.IMG_SERVER_PROJECT);
+		//else if (thisStyle == STYLE_NO_CONFIGURATION)
+		//	return ServerImageResource.getImageDescriptor(ServerImageResource.IMG_SERVER_CONFIGURATION_NONE);
+		else if (thisStyle == STYLE_NO_MODULES) {
+			ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
+			return sharedImages.getImageDescriptor(IDE.SharedImages.IMG_OBJ_PROJECT);
+		}
+		else if (thisStyle == STYLE_NO_SERVERS)
+			return ServerImageResource.getImageDescriptor(ServerImageResource.IMG_SERVER_CONFIGURATION_MISSING);
+		else
+			return null;
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getLabel(Object)
+	 */
+	public String getLabel(Object o) {
+		if (thisStyle == STYLE_SERVERS)
+			return ServerUIPlugin.getResource("%viewServers");
+		else if (thisStyle == STYLE_CONFIGURATIONS)
+			return ServerUIPlugin.getResource("%viewConfigurations");
+		//else if (thisStyle == STYLE_SERVERS_AND_CONFIGURATIONS)
+		//	return "Server Info";
+		//else if (thisStyle == STYLE_NO_CONFIGURATION)
+		//	return "No configuration";
+		else if (thisStyle == STYLE_NO_MODULES)
+			return ServerUIPlugin.getResource("%viewNoModules");
+		else if (thisStyle == STYLE_NO_SERVERS)
+			return ServerUIPlugin.getResource("%viewConfigurationUnused");
+		else if (thisStyle == STYLE_LOOSE_CONFIGURATIONS)
+			return ServerUIPlugin.getResource("%viewLooseConfigurations");
+		else
+			return "n/a";
+	}
+
+	/*
+	 * @see IWorkbenchAdapter#getParent(Object)
+	 */
+	public Object getParent(Object o) {
+		return parent;
+	}
+	
+	public boolean equals(Object obj) {
+		if (!(obj instanceof TextResourceAdapter))	
+			return false;
+		
+		TextResourceAdapter adapter = (TextResourceAdapter) obj;
+		return (adapter.getStyle() == thisStyle);
+	}
+	
+	public int hashCode() {
+		return thisStyle;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTableComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTableComposite.java
new file mode 100644
index 0000000..0207305
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTableComposite.java
@@ -0,0 +1,78 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+/**
+ * 
+ */
+public abstract class AbstractTableComposite extends Composite {
+	protected Table table;
+	protected TableViewer tableViewer;
+
+	public AbstractTableComposite(Composite parent, int style) {
+		super(parent, style);
+		
+		createWidgets();
+	}
+
+	protected void createWidgets() {
+		GridLayout layout = new GridLayout();
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 1;
+		setLayout(layout);
+
+		GridData data = new GridData(GridData.FILL_BOTH);
+		setLayoutData(data);
+		
+		createTable();
+		data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
+		table.setLayoutData(data);
+		table.setLinesVisible(true);
+		createTableViewer();
+	}
+	
+	protected void createTable() {
+		table = new Table(this, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE);
+	}
+	
+	protected void createTableViewer() {
+		tableViewer = new LockedTableViewer(table);
+	}
+
+	protected TableViewer getTableViewer() {
+		return tableViewer;
+	}
+
+	protected Object getSelection(ISelection sel2) {
+		IStructuredSelection sel = (IStructuredSelection) sel2;
+		return sel.getFirstElement();
+	}
+	
+	public void refresh() {
+		tableViewer.refresh();
+	}
+	
+	public void refresh(Object obj) {
+		tableViewer.refresh(obj);
+	}
+
+	public void remove(Object obj) {
+		tableViewer.remove(obj);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeComposite.java
new file mode 100644
index 0000000..1f325ab
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeComposite.java
@@ -0,0 +1,157 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+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.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Tree;
+
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * 
+ */
+public abstract class AbstractTreeComposite extends Composite {
+	protected Tree tree;
+	protected TreeViewer treeViewer;
+	protected Label description;
+	
+	public AbstractTreeComposite(Composite parent, int style) {
+		super(parent, style);
+		
+		createWidgets();
+	}
+	
+	protected void createWidgets() {
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = 3;
+		layout.verticalSpacing = 3;
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 2;
+		setLayout(layout);
+
+		//GridData data = new GridData(GridData.FILL_BOTH);
+		//setLayoutData(data);
+		
+		String descriptionText = getDescriptionLabel();
+		if (descriptionText != null) {
+			Label label = new Label(this, SWT.WRAP);
+			label.setText(descriptionText);
+			GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
+			data.horizontalSpan = 2;
+			label.setLayoutData(data);
+		}
+		
+		Label label = new Label(this, SWT.WRAP);
+		label.setText(getTitleLabel());
+		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
+		data.horizontalSpan = 2;
+		label.setLayoutData(data);
+
+		tree = new Tree(this, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE);
+		data = new GridData(GridData.FILL_BOTH);
+		data.horizontalSpan = 2;
+		tree.setLayoutData(data);
+		treeViewer = new TreeViewer(tree);
+		
+		treeViewer.setSorter(new ViewerSorter());
+		
+		label = new Label(this, SWT.NONE);
+		label.setText("");
+		data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
+		label.setLayoutData(data);
+		
+		// view composite
+		Composite comp = new Composite(this, SWT.NONE);
+		layout = new GridLayout();
+		layout.horizontalSpacing = 3;
+		layout.verticalSpacing = 0;
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 2;
+		comp.setLayout(layout);
+
+		data = new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_CENTER);
+		comp.setLayoutData(data);
+		
+		label = new Label(comp, SWT.NONE);
+		label.setText(ServerUIPlugin.getResource("%viewBy"));
+		data = new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_CENTER);
+		label.setLayoutData(data);
+	
+		final Combo combo = new Combo(comp, SWT.DROP_DOWN | SWT.READ_ONLY);
+		combo.setItems(getComboOptions());
+		combo.select(1);
+		combo.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_CENTER));
+		combo.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				int sel = combo.getSelectionIndex();
+				viewOptionSelected((byte) sel);
+			}
+		});
+		
+		if (hasDescription()) {
+			description = new Label(this, SWT.WRAP);
+			description.setText(ServerUIPlugin.getResource("%wizDescription"));
+			data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
+			data.horizontalSpan = 2;
+			data.heightHint = 35;
+			description.setLayoutData(data);
+		}
+	}
+	
+	protected abstract String getDescriptionLabel();
+	
+	protected abstract String getTitleLabel();
+	
+	protected abstract String[] getComboOptions();
+	
+	protected boolean hasDescription() {
+		return true;
+	}
+	
+	protected void setDescription(String text) {
+		if (description != null && text != null)
+			description.setText(ServerUIPlugin.getResource("%wizDescription") + " " + text);
+	}
+	
+	protected abstract void viewOptionSelected(byte option);
+	
+	protected TreeViewer getTreeViewer() {
+		return treeViewer;
+	}
+
+	protected Object getSelection(ISelection sel2) {
+		IStructuredSelection sel = (IStructuredSelection) sel2;
+		return sel.getFirstElement();
+	}
+	
+	public void refresh() {
+		treeViewer.refresh();
+	}
+	
+	public void refresh(Object obj) {
+		treeViewer.refresh(obj);
+	}
+
+	public void remove(Object obj) {
+		treeViewer.remove(obj);
+	}
+}
\ 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..f7ccf92
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeContentProvider.java
@@ -0,0 +1,178 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+/**
+ * Runtime type content provider.
+ */
+public abstract class AbstractTreeContentProvider implements ITreeContentProvider {
+	public static final byte STYLE_FLAT = 0;
+
+	public static final String ROOT = "root";
+	
+	protected byte style;
+	
+	protected Object initialSelection;
+	protected int initialSelectionOrder;
+	
+	public class TreeElement {
+		String text;
+		List contents;
+	}
+
+	protected Object[] elements;
+	protected Map elementToParentMap = new HashMap();
+	protected Map textMap = new HashMap();
+
+	/**
+	 * AbstractTreeContentProvider constructor comment.
+	 */
+	public AbstractTreeContentProvider(byte style) {
+		super();
+		this.style = style;
+		
+		fillTree();
+	}
+	
+	public AbstractTreeContentProvider(byte style, boolean init) {
+		super();
+		this.style = style;
+	}
+	
+	protected abstract void fillTree();
+	
+	protected TreeElement getOrCreate(List 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();
+		textMap.put(text, element);
+		list.add(element);
+		return element;
+	}
+	
+	protected TreeElement getOrCreate(List 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();
+		textMap.put(id, element);
+		list.add(element);
+		return element;
+	}
+
+	protected TreeElement getByText(String text) {
+		try {
+			return (TreeElement) textMap.get(text);
+		} catch (Exception e) {
+			return null;
+		}
+	}
+	
+	protected TreeElement getParentImpl(Object obj) {
+		try {
+			return (TreeElement) 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() { }
+
+	/**
+	 * 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 inputElement 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 (style == STYLE_FLAT)
+			return null;
+		else if (!(element instanceof TreeElement))
+			return null;
+		
+		TreeElement rte = (TreeElement) element;
+		return rte.contents.toArray();
+	}
+
+	public Object getParent(Object element) {
+		if (style == STYLE_FLAT)
+			return null;
+		//else if (element instanceof TreeElement)
+		//	return null;
+
+		return getParentImpl(element);
+	}
+
+	public boolean hasChildren(Object element) {
+		if (style == STYLE_FLAT)
+			return false;
+		//else if (!(element instanceof TreeElement))
+		//	return false;
+		Object[] children = getChildren(element);
+		return children != null && children.length > 0;
+
+		//return true;
+	}
+
+	/**
+	 * 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) { }
+	
+	public Object getInitialSelection() {
+		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/AbstractTreeLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeLabelProvider.java
new file mode 100644
index 0000000..d1e2317
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeLabelProvider.java
@@ -0,0 +1,61 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+/**
+ * Abstract tree label provider.
+ */
+public abstract class AbstractTreeLabelProvider extends BaseLabelProvider {
+	/**
+	 * AbstractTreeLabelProvider constructor comment.
+	 */
+	public AbstractTreeLabelProvider() {
+		super();
+	}
+
+	/**
+	 * Returns the label image for the given column of the given element.
+	 *
+	 * @param element the object representing the entire row, or 
+	 *    <code>null</code> indicating that no input object is set
+	 *    in the viewer
+	 * @param columnIndex the zero-based index of the column in which
+	 *   the label appears
+	 */
+	public Image getImage(Object element) {
+		if (element instanceof ServerTreeContentProvider.TreeElement) {
+			ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
+			return sharedImages.getImage(ISharedImages.IMG_OBJ_FOLDER);
+		} else
+			return getImageImpl(element);
+	}
+	
+	protected abstract Image getImageImpl(Object element);
+
+	/**
+	 * Returns the label text for the given column of the given element.
+	 *
+	 * @param element the object representing the entire row, or
+	 *   <code>null</code> indicating that no input object is set
+	 *   in the viewer
+	 * @param columnIndex the zero-based index of the column in which the label appears
+	 */
+	public String getText(Object element) {
+		if (element instanceof ServerTreeContentProvider.TreeElement) {
+			return ((ServerTreeContentProvider.TreeElement) element).text;
+		} else
+			return getTextImpl(element);
+	}
+	
+	protected abstract String getTextImpl(Object element);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/BaseLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/BaseLabelProvider.java
new file mode 100644
index 0000000..785cb87
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/BaseLabelProvider.java
@@ -0,0 +1,104 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.graphics.Image;
+/**
+ * A basic label provider.
+ */
+public abstract class BaseLabelProvider implements ILabelProvider {
+	/**
+	 * BaseLabelProvider constructor comment.
+	 */
+	public BaseLabelProvider() {
+		super();
+	}
+
+	/**
+	 * Adds a listener to this label provider. 
+	 * Has no effect if an identical listener is already registered.
+	 * <p>
+	 * Label provider listeners are informed about state changes 
+	 * that affect the rendering of the viewer that uses this label provider.
+	 * </p>
+	 *
+	 * @param listener a label provider listener
+	 */
+	public void addListener(ILabelProviderListener listener) { }
+
+	/**
+	 * Disposes of this label provider.  When a label provider is
+	 * attached to a viewer, the viewer will automatically call
+	 * this method when the viewer is being closed.  When label providers
+	 * are used outside of the context of a viewer, it is the client's
+	 * responsibility to ensure that this method is called when the
+	 * provider is no longer needed.
+	 */
+	public void dispose() { }
+
+	/**
+	 * Returns the label image for the given column of the given element.
+	 *
+	 * @param element the object representing the entire row, or 
+	 *    <code>null</code> indicating that no input object is set
+	 *    in the viewer
+	 * @param columnIndex the zero-based index of the column in which
+	 *   the label appears
+	 */
+	public Image getImage(Object element) {
+		return null;
+	}
+
+	/**
+	 * Returns the label text for the given column of the given element.
+	 *
+	 * @param element the object representing the entire row, or
+	 *   <code>null</code> indicating that no input object is set
+	 *   in the viewer
+	 * @param columnIndex the zero-based index of the column in which the label appears
+	 */
+	public String getText(Object element) {
+		return "";
+	}
+
+	/**
+	 * Returns whether the label would be affected 
+	 * by a change to the given property of the given element.
+	 * This can be used to optimize a non-structural viewer update.
+	 * If the property mentioned in the update does not affect the label,
+	 * then the viewer need not update the label.
+	 *
+	 * @param element the element
+	 * @param property the property
+	 * @return <code>true</code> if the label would be affected,
+	 *    and <code>false</code> if it would be unaffected
+	 */
+	public boolean isLabelProperty(Object element, String property) {
+		return false;
+	}
+
+	/**
+	 * Removes a listener to this label provider.
+	 * Has no affect if an identical listener is not registered.
+	 *
+	 * @param listener a label provider listener
+	 */
+	public void removeListener(ILabelProviderListener listener) { }
+	
+	protected String notNull(String s) {
+		if (s != null)
+			return s;
+		else
+			return "";
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ILockedLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ILockedLabelProvider.java
new file mode 100644
index 0000000..bebc7a9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ILockedLabelProvider.java
@@ -0,0 +1,28 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+/**
+ * Extends <code>ITableLabelProvider</code> with methods to provide
+ * lock information.
+ *
+ * @see TableViewer
+ */
+public interface ILockedLabelProvider {
+	/**
+	 * Returns the lock info for the element. This value will be used
+	 * to change the presentation of the table row.
+	 *
+	 * @param element the object representing the entire row, or 
+	 *    <code>null</code> indicating that no input object is set
+	 *    in the viewer
+	 */
+	public boolean isLocked(Object element);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/LockedCheckboxTableViewer.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/LockedCheckboxTableViewer.java
new file mode 100644
index 0000000..84af6d0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/LockedCheckboxTableViewer.java
@@ -0,0 +1,55 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Widget;
+/**
+ *
+ */
+public class LockedCheckboxTableViewer extends CheckboxTableViewer {
+	protected Color color;
+
+	public LockedCheckboxTableViewer(Table table) {
+		super(table);
+		createColor(table);
+	}
+
+	protected void createColor(Control c) {
+		color = new Color(c.getDisplay(), 255, 255, 225);
+		c.addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				color.dispose();
+			}
+		});
+	}
+
+	public void doUpdateItem(Widget widget, Object element, boolean fullMap) {
+		if (color == null)
+			return;
+		if (widget instanceof TableItem) {
+			TableItem item = (TableItem) widget;
+			if (getLabelProvider() instanceof ILockedLabelProvider) {
+				ILockedLabelProvider provider = (ILockedLabelProvider) getLabelProvider();
+				if (provider.isLocked(element)) {
+					item.setBackground(color);
+					item.setImage(0, null);
+				}
+			}
+		}
+		super.doUpdateItem(widget, element, fullMap);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/LockedTableViewer.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/LockedTableViewer.java
new file mode 100644
index 0000000..6a1e45b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/LockedTableViewer.java
@@ -0,0 +1,66 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Widget;
+/**
+ *
+ */
+public class LockedTableViewer extends TableViewer {
+	protected Color color;
+
+	public LockedTableViewer(Composite parent) {
+		super(parent);
+		createColor(parent);
+	}
+	
+	public LockedTableViewer(Composite parent, int style) {
+		super(parent, style);
+		createColor(parent);
+	}
+
+	public LockedTableViewer(Table table) {
+		super(table);
+		createColor(table);
+	}
+
+	protected void createColor(Control c) {
+		color = new Color(c.getDisplay(), 255, 255, 225);
+		c.addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				color.dispose();
+			}
+		});
+	}
+
+	public void doUpdateItem(Widget widget, Object element, boolean fullMap) {
+		if (color == null)
+			return;
+		if (widget instanceof TableItem) {
+			TableItem item = (TableItem) widget;
+			if (getLabelProvider() instanceof ILockedLabelProvider) {
+				ILockedLabelProvider provider = (ILockedLabelProvider) getLabelProvider();
+				if (provider.isLocked(element)) {
+					item.setBackground(color);
+					item.setImage(0, null);
+				}
+			}
+		}
+		super.doUpdateItem(widget, element, fullMap);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorComposite.java
new file mode 100644
index 0000000..b117e45
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorComposite.java
@@ -0,0 +1,223 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.window.Window;
+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.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+import org.eclipse.wst.server.core.IMonitoredServerPort;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerMonitorManager;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.model.IServerPort;
+import org.eclipse.wst.server.ui.internal.EclipseUtil;
+import org.eclipse.wst.server.ui.internal.SWTUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * 
+ */
+public class MonitorComposite extends Composite {
+	//protected IServerPort selection;
+	protected PortSelectionListener listener;
+	protected IServer server;
+	
+	protected IServerMonitorManager smm;
+	
+	protected Table monitorTable;
+	protected TableViewer monitorTableViewer;
+	
+	public interface PortSelectionListener {
+		public void portSelected(IServerPort port);
+	}
+	
+	public MonitorComposite(Composite parent, int style, PortSelectionListener listener2, IServer server) {
+		super(parent, style);
+		this.listener = listener2;
+		this.server = server;
+		
+		smm = ServerCore.getServerMonitorManager();
+		
+		GridLayout layout = new GridLayout();
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 2;
+		setLayout(layout);
+
+		GridData data = new GridData(GridData.FILL_BOTH);
+		setLayoutData(data);
+		
+		monitorTable = new Table(this, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
+		data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
+		//data.horizontalSpan = 2;
+		data.heightHint = 150;
+		//data.widthHint = 340;
+		monitorTable.setLayoutData(data);
+		monitorTable.setLinesVisible(true);
+		monitorTableViewer = new TableViewer(monitorTable);
+		
+		TableLayout tableLayout = new TableLayout();
+		monitorTable.setLayout(tableLayout);
+		monitorTable.setHeaderVisible(true);
+		
+		tableLayout.addColumnData(new ColumnWeightData(8, 80, true));
+		TableColumn col = new TableColumn(monitorTable, SWT.NONE);
+		col.setText(ServerUIPlugin.getResource("%dialogMonitorColumnStatus"));
+		
+		tableLayout.addColumnData(new ColumnWeightData(12, 120, true));
+		col = new TableColumn(monitorTable, SWT.NONE);
+		col.setText(ServerUIPlugin.getResource("%dialogMonitorColumnType"));
+		
+		tableLayout.addColumnData(new ColumnWeightData(8, 80, true));
+		col = new TableColumn(monitorTable, SWT.NONE);
+		col.setText(ServerUIPlugin.getResource("%dialogMonitorColumnPort"));
+		
+		tableLayout.addColumnData(new ColumnWeightData(8, 80, true));
+		col = new TableColumn(monitorTable, SWT.NONE);
+		col.setText(ServerUIPlugin.getResource("%dialogMonitorColumnMonitorPort"));
+		
+		tableLayout.addColumnData(new ColumnWeightData(8, 80, true));
+		col = new TableColumn(monitorTable, SWT.NONE);
+		col.setText(ServerUIPlugin.getResource("%dialogMonitorColumnContentType"));
+		
+		monitorTableViewer.setContentProvider(new MonitorContentProvider(server));
+		monitorTableViewer.setLabelProvider(new MonitorLabelProvider(server));
+		monitorTableViewer.setInput(AbstractTreeContentProvider.ROOT);
+		
+		monitorTableViewer.setSorter(new ViewerSorter() {
+			public int compare(Viewer viewer, Object e1, Object e2) {
+				IMonitoredServerPort port1 = (IMonitoredServerPort) e1;
+				IMonitoredServerPort port2 = (IMonitoredServerPort) e2;
+				if (port1.getServerPort().getPort() == port2.getServerPort().getPort()) {
+					if (port1.getMonitorPort() == port2.getMonitorPort()) {
+						return 0;
+					} else if (port1.getMonitorPort() > port2.getMonitorPort())
+						return 1;
+					else
+						return -1;
+				} else if (port1.getServerPort().getPort() > port2.getServerPort().getPort())
+					return 1;
+				else
+					return -1;
+			}
+		});
+		
+		Composite buttonComp = new Composite(this, SWT.NONE);
+		buttonComp.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING));
+		layout = new GridLayout();
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		buttonComp.setLayout(layout);
+		
+		final IServer server2 = server;
+		Button add = SWTUtil.createButton(buttonComp, ServerUIPlugin.getResource("%add"));
+		add.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				MonitorDialog dialog = new MonitorDialog(getShell(), server2);
+				if (dialog.open() != Window.CANCEL) {
+					IServerPort port = dialog.getServerPort();
+					monitorTableViewer.add(smm.createMonitor(server2, port, dialog.getMonitorPort(), dialog.getContentTypes()));
+				}
+			}
+		});
+		
+		final Button edit = SWTUtil.createButton(buttonComp, ServerUIPlugin.getResource("%edit"));
+		edit.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				IStructuredSelection sel = (IStructuredSelection) monitorTableViewer.getSelection();
+				IMonitoredServerPort port = (IMonitoredServerPort) sel.getFirstElement();
+				MonitorDialog dialog = new MonitorDialog(getShell(), server2, port.getServerPort(), port.getMonitorPort(), port.getContentTypes());
+				if (dialog.open() != Window.CANCEL) {
+					smm.removeMonitor(port);
+					monitorTableViewer.remove(port);
+					port = smm.createMonitor(server2, dialog.getServerPort(), dialog.getMonitorPort(), dialog.getContentTypes());
+					monitorTableViewer.add(port);
+					monitorTableViewer.setSelection(new StructuredSelection(port));
+				}
+			}
+		});
+		edit.setEnabled(false);
+		
+		final Button remove = SWTUtil.createButton(buttonComp, ServerUIPlugin.getResource("%remove"));
+		remove.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				IMonitoredServerPort msp = (IMonitoredServerPort) getSelection(monitorTableViewer.getSelection());
+				if (msp.isStarted())
+					smm.stopMonitor(msp);
+				smm.removeMonitor(msp);
+				monitorTableViewer.remove(msp);
+			}
+		});
+		remove.setEnabled(false);
+		
+		final Button start = SWTUtil.createButton(buttonComp, ServerUIPlugin.getResource("%start"));
+		start.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				IStructuredSelection sel = (IStructuredSelection) monitorTableViewer.getSelection();
+				IMonitoredServerPort msp = (IMonitoredServerPort) sel.getFirstElement();
+				try {
+					smm.startMonitor(msp);
+				} catch (CoreException ce) {
+					EclipseUtil.openError(getShell(), ce.getLocalizedMessage());
+				}
+				monitorTableViewer.refresh(msp);
+				monitorTableViewer.setSelection(new StructuredSelection(msp));
+			}
+		});
+		start.setEnabled(false);
+		
+		final Button stop = SWTUtil.createButton(buttonComp, ServerUIPlugin.getResource("%stop"));
+		stop.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				IStructuredSelection sel = (IStructuredSelection) monitorTableViewer.getSelection();
+				IMonitoredServerPort msp = (IMonitoredServerPort) sel.getFirstElement();
+				smm.stopMonitor(msp);
+				monitorTableViewer.refresh(msp);
+				monitorTableViewer.setSelection(new StructuredSelection(msp));
+			}
+		});
+		stop.setEnabled(false);
+		
+		monitorTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				IMonitoredServerPort port = (IMonitoredServerPort) getSelection(monitorTableViewer.getSelection());
+				if (port != null) {
+					edit.setEnabled(!port.isStarted());
+					remove.setEnabled(true);
+					start.setEnabled(!port.isStarted());
+					stop.setEnabled(port.isStarted());
+				} else {
+					edit.setEnabled(false);
+					remove.setEnabled(false);
+					start.setEnabled(false);
+					stop.setEnabled(false);
+				}
+			}
+		});
+		
+		// TODO - if elements > 0
+		//tableViewer.setSelection(new StructuredSelection(tableViewer.getElementAt(0)));
+	}
+	
+	protected Object getSelection(ISelection sel2) {
+		IStructuredSelection sel = (IStructuredSelection) sel2;
+		return sel.getFirstElement();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorContentProvider.java
new file mode 100644
index 0000000..0e696ff
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorContentProvider.java
@@ -0,0 +1,36 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ServerCore;
+/**
+ * Monitor port content provider.
+ */
+public class MonitorContentProvider implements IStructuredContentProvider {
+	protected IServer server;
+
+	public MonitorContentProvider(IServer server) {
+		super();
+		this.server = server;
+	}
+
+	public void dispose() { }
+
+	public Object[] getElements(Object inputElement) {
+		return ServerCore.getServerMonitorManager().getMonitoredPorts(server).toArray();
+	}
+
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorDialog.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorDialog.java
new file mode 100644
index 0000000..07d3142
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorDialog.java
@@ -0,0 +1,237 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.IServerPort;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * Dialog that prompts a user to add or edit a server monitor.
+ */
+public class MonitorDialog extends Dialog {
+	protected IServer server;
+	protected IServerPort port;
+	protected int monitorPort = -1;
+	protected String[] portContentTypes;
+	protected String[] contentTypes;
+	protected boolean isEdit = false;
+	protected boolean portChanged = false;
+	
+	protected Button ok;
+	
+	protected Table table;
+	protected TableViewer tableViewer;
+	protected boolean init;
+
+	/**
+	 * MonitorDialog constructor comment.
+	 * @param parentShell org.eclipse.swt.widgets.Shell
+	 * @
+	 */
+	public MonitorDialog(Shell parentShell, IServer server) {
+		super(parentShell);
+
+		this.server = server;
+	}
+	
+	public MonitorDialog(Shell parentShell, IServer server, IServerPort port, int monitorPort, String[] contentTypes) {
+		this(parentShell, server);
+		this.monitorPort = monitorPort;
+		this.contentTypes = contentTypes;
+		this.port = port;
+		isEdit = true;
+	}
+
+	/**
+	 *
+	 */
+	protected void configureShell(Shell newShell) {
+		super.configureShell(newShell);
+		newShell.setText(ServerUIPlugin.getResource("%dialogMonitorTitle"));
+	}
+	
+	protected void createButtonsForButtonBar(Composite parent) {
+		ok = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+
+	/**
+	 * 
+	 */
+	protected Control createDialogArea(Composite parent) {
+		// create a composite with standard margins and spacing
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+		layout.numColumns = 2;
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+		composite.setFont(parent.getFont());
+		//WorkbenchHelp.setHelp(composite, ContextIds.TERMINATE_SERVER_DIALOG);
+		
+		Label label = new Label(composite, SWT.WRAP);
+		label.setText(ServerUIPlugin.getResource("%dialogMonitorAddDescription", new String[] { server.getName() } ));
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 2;
+		data.widthHint = 275;
+		label.setLayoutData(data);
+		
+		table = new Table(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION);
+		data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
+		data.heightHint = 100;
+		data.horizontalSpan = 2;
+		table.setLayoutData(data);
+		table.setLinesVisible(true);
+		tableViewer = new TableViewer(table);
+		
+		TableLayout tableLayout = new TableLayout();
+		table.setLayout(tableLayout);
+		table.setHeaderVisible(true);
+		
+		tableLayout.addColumnData(new ColumnWeightData(12, 120, true));
+		TableColumn col = new TableColumn(table, SWT.NONE);
+		col.setText(ServerUIPlugin.getResource("%dialogMonitorColumnType"));
+		
+		tableLayout.addColumnData(new ColumnWeightData(4, 40, true));
+		col = new TableColumn(table, SWT.NONE);
+		col.setText(ServerUIPlugin.getResource("%dialogMonitorColumnPort"));
+		
+		tableViewer.setContentProvider(new PortContentProvider(server));
+		tableViewer.setLabelProvider(new PortLabelProvider(server));
+		tableViewer.setInput(AbstractTreeContentProvider.ROOT);
+		
+		tableViewer.setSorter(new ViewerSorter() {
+			public int compare(Viewer viewer, Object e1, Object e2) {
+				IServerPort port1 = (IServerPort) e1;
+				IServerPort port2 = (IServerPort) e2;
+				if (port1.getPort() == port2.getPort())
+					return 0;
+				else if (port1.getPort() > port2.getPort())
+					return 1;
+				else
+					return -1;
+			}
+		});
+		
+		label = new Label(composite, SWT.NONE);
+		label.setText(ServerUIPlugin.getResource("%dialogMonitorMonitorPort"));
+		
+		final Text portText = new Text(composite, SWT.BORDER);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.widthHint = 150;
+		portText.setLayoutData(data);
+		if (monitorPort >= 0)
+			portText.setText(monitorPort + "");
+
+		portText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				try {
+					monitorPort = Integer.parseInt(portText.getText());
+					if (ok != null)
+						ok.setEnabled(true);
+				} catch (Exception ex) {
+					monitorPort = -1;
+					if (ok != null)
+						ok.setEnabled(false);
+				}
+				portChanged = true;
+			}
+		});
+		
+		label = new Label(composite, SWT.NONE);
+		label.setText(ServerUIPlugin.getResource("%dialogMonitorContentType"));
+		
+		final Combo combo = new Combo(composite, SWT.READ_ONLY);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.widthHint = 150;
+		combo.setLayoutData(data);
+		combo.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				int size = combo.getItemCount();
+				int sel = combo.getSelectionIndex();
+				if (sel == size - 1)
+					contentTypes = portContentTypes;
+				else
+					contentTypes = new String[] { portContentTypes[sel] };
+			}
+		});
+		
+		tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				port = (IServerPort) getSelection(tableViewer.getSelection());
+				if (port == null)
+					return;
+				if (!portChanged) {
+					portText.setText((port.getPort() + 1) + "");
+					portChanged = false;
+				}
+				portContentTypes = port.getContentTypes();
+				String[] s = null;
+				String all = ServerUIPlugin.getResource("%dialogMonitorContentTypeAll");
+				if (portContentTypes == null || portContentTypes.length == 1) {
+					s = new String[] { all };
+				} else {
+					int size = portContentTypes.length;
+					s = new String[size+1];
+					for (int i = 0; i < size; i++) {
+						s[i] = MonitorLabelProvider.getContentTypeString(portContentTypes[i]);
+					}
+					s[size] = all;
+				}
+				combo.setItems(s);
+				combo.setText(all);
+			}
+		});
+		
+		Dialog.applyDialogFont(composite);
+		
+		if (port != null) {
+			portChanged = true;
+			String[] ct = contentTypes;
+			tableViewer.setSelection(new StructuredSelection(port));
+			if (ct != null)
+				combo.setText(MonitorLabelProvider.getContentTypeString(ct[0]));
+		} else
+			tableViewer.setSelection(new StructuredSelection(tableViewer.getElementAt(0)));
+		portChanged = false;
+	
+		return composite;
+	}
+	
+	protected Object getSelection(ISelection sel2) {
+		IStructuredSelection sel = (IStructuredSelection) sel2;
+		return sel.getFirstElement();
+	}
+	
+	public int getMonitorPort() {
+		return monitorPort;
+	}
+
+	public IServerPort getServerPort() {
+		return port;
+	}
+
+	public String[] getContentTypes() {
+		return contentTypes;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorLabelProvider.java
new file mode 100644
index 0000000..6e57727
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/MonitorLabelProvider.java
@@ -0,0 +1,79 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.wst.server.core.IMonitoredServerPort;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * Monitor port label provider.
+ */
+public class MonitorLabelProvider extends BaseLabelProvider implements ITableLabelProvider {
+	protected IServer server;
+
+	public MonitorLabelProvider(IServer server) {
+		super();
+		this.server = server;
+	}
+
+	public Image getColumnImage(Object element, int columnIndex) {
+		IMonitoredServerPort port = (IMonitoredServerPort) element;
+		if (columnIndex == 0) {
+			if (port.isStarted())
+				return ImageResource.getImage(ImageResource.IMG_MONITOR_ON);
+			else
+				return ImageResource.getImage(ImageResource.IMG_MONITOR_OFF);
+		} else
+			return null;
+	}
+
+	public String getColumnText(Object element, int columnIndex) {
+		IMonitoredServerPort port = (IMonitoredServerPort) element;
+		if (columnIndex == 0) {
+			if (port.isStarted())
+				return ServerUIPlugin.getResource("%started");
+			else
+				return ServerUIPlugin.getResource("%stopped");
+		} else if (columnIndex == 1)
+			return notNull(port.getServerPort().getName());
+		else if (columnIndex == 2)
+			return port.getServerPort().getPort() + "";
+		else if (columnIndex == 3)
+			return port.getMonitorPort() + "";
+		else {
+			String[] content = port.getContentTypes();
+			if (content == null || content.length == 0)
+				return ServerUIPlugin.getResource("%dialogMonitorContentTypeAll");
+			else {
+				StringBuffer sb = new StringBuffer();
+				int size = content.length;
+				for (int i = 0; i < size; i++) {
+					if (i > 0)
+						sb.append(",");
+					sb.append(getContentTypeString(content[i]));
+				}
+				return sb.toString();
+			}
+		}
+	}
+	
+	protected static String getContentTypeString(String s) {
+		if ("web".equals(s))
+			return ServerUIPlugin.getResource("%dialogMonitorContentTypeWeb");
+		else if ("webservices".equals(s))
+			return ServerUIPlugin.getResource("%dialogMonitorContentTypeWebServices");
+		else
+			return s;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/PortContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/PortContentProvider.java
new file mode 100644
index 0000000..bf1401a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/PortContentProvider.java
@@ -0,0 +1,36 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.IMonitorableServer;
+/**
+ * Monitor port content provider.
+ */
+public class PortContentProvider implements IStructuredContentProvider {
+	protected IServer server;
+
+	public PortContentProvider(IServer server) {
+		super();
+		this.server = server;
+	}
+
+	public void dispose() { }
+
+	public Object[] getElements(Object inputElement) {
+		IMonitorableServer monitorableServer = (IMonitorableServer) server.getDelegate();
+		return monitorableServer.getServerPorts().toArray();
+	}
+
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/PortLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/PortLabelProvider.java
new file mode 100644
index 0000000..a5c2d86
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/PortLabelProvider.java
@@ -0,0 +1,41 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.IServerPort;
+/**
+ * Server port label provider.
+ */
+public class PortLabelProvider extends BaseLabelProvider implements ITableLabelProvider {
+	protected IServer server;
+
+	public PortLabelProvider(IServer server) {
+		super();
+		this.server = server;
+	}
+
+	public Image getColumnImage(Object element, int columnIndex) {
+		return null;
+	}
+
+	public String getColumnText(Object element, int columnIndex) {
+		IServerPort port = (IServerPort) element;
+		if (columnIndex == 0)
+			return notNull(port.getName());
+		else if (columnIndex == 1)
+			return port.getPort() + "";
+		else
+			return "";
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeComposite.java
new file mode 100644
index 0000000..9e35468
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeComposite.java
@@ -0,0 +1,100 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+/**
+ * 
+ */
+public class RuntimeComposite extends AbstractTableComposite {
+	protected IRuntime selection;
+	protected IRuntime defaultRuntime;
+	protected RuntimeSelectionListener listener;
+	
+	public interface RuntimeSelectionListener {
+		public void runtimeSelected(IRuntime runtime);
+	}
+	
+	public RuntimeComposite(Composite parent, int style, RuntimeSelectionListener listener2) {
+		super(parent, style);
+		this.listener = listener2;
+		
+		TableLayout tableLayout = new TableLayout();
+		table.setLayout(tableLayout);
+		table.setHeaderVisible(true);
+
+		tableLayout.addColumnData(new ColumnWeightData(60, 160, true));
+		TableColumn col = new TableColumn(table, SWT.NONE);
+		col.setText(ServerUIPlugin.getResource("%columnName"));
+		
+		/*tableLayout.addColumnData(new ColumnWeightData(12, 120, true));
+		col = new TableColumn(table, SWT.NONE);
+		col.setText("Location");*/
+
+		tableLayout.addColumnData(new ColumnWeightData(45, 125, true));
+		col = new TableColumn(table, SWT.NONE);
+		col.setText(ServerUIPlugin.getResource("%columnType"));
+		
+		tableViewer.setContentProvider(new RuntimeContentProvider());
+		tableViewer.setLabelProvider(new RuntimeTableLabelProvider());
+		tableViewer.setInput(AbstractTreeContentProvider.ROOT);
+		tableViewer.setColumnProperties(new String[] {"name", "location", "type"});
+
+		tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				Object obj = getSelection(event.getSelection());
+				if (obj instanceof IRuntime)
+					selection = (IRuntime) obj;
+				else
+					selection = null;
+				listener.runtimeSelected(selection);
+			}
+		});
+		
+		defaultRuntime = ServerCore.getResourceManager().getDefaultRuntime();
+		if (defaultRuntime != null)
+			((CheckboxTableViewer)tableViewer).setChecked(defaultRuntime, true);
+
+		((CheckboxTableViewer)tableViewer).addCheckStateListener(new ICheckStateListener() {
+			public void checkStateChanged(CheckStateChangedEvent event) {
+				try {
+					IRuntime runtime = (IRuntime) event.getElement();
+					if (event.getChecked()) {
+						if (defaultRuntime != null)
+							((CheckboxTableViewer)tableViewer).setChecked(defaultRuntime, false);
+						ServerCore.getResourceManager().setDefaultRuntime(runtime);
+						defaultRuntime = runtime;
+					} else
+						ServerCore.getResourceManager().setDefaultRuntime(null);
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Error setting default runtime", e);
+				}
+			}
+		});
+	}
+
+	protected void createTable() {
+		table = new Table(this, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE | SWT.CHECK);
+	}
+
+	protected void createTableViewer() {
+		tableViewer = new LockedCheckboxTableViewer(table);
+	}
+
+	public IRuntime getSelectedRuntime() {
+		return selection;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeContentProvider.java
new file mode 100644
index 0000000..aa62719
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeContentProvider.java
@@ -0,0 +1,75 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.ServerCore;
+/**
+ * Runtime content provider.
+ */
+public class RuntimeContentProvider implements IStructuredContentProvider {
+	/**
+	 * RuntimeContentProvider constructor comment.
+	 */
+	public RuntimeContentProvider() {
+		super();
+	}
+
+	/**
+	 * Disposes of this content provider.  
+	 * This is called by the viewer when it is disposed.
+	 */
+	public void dispose() { }
+
+	/**
+	 * 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 inputElement the input element
+	 * @return the array of elements to display in the viewer
+	 */
+	public Object[] getElements(Object inputElement) {
+		List list = new ArrayList();
+		Iterator iterator = ServerCore.getResourceManager().getRuntimes().iterator();
+		while (iterator.hasNext()) {
+			IRuntime runtime = (IRuntime) iterator.next();
+			if (!runtime.isPrivate())
+				list.add(runtime);
+		}
+		return list.toArray();
+	}
+
+	/**
+	 * 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) {}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTableLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTableLabelProvider.java
new file mode 100644
index 0000000..8913d80
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTableLabelProvider.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IRuntimeType;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Runtime table label provider.
+ */
+public class RuntimeTableLabelProvider extends BaseLabelProvider implements ITableLabelProvider, ILockedLabelProvider {
+	/**
+	 * RuntimeTableLabelProvider constructor comment.
+	 */
+	public RuntimeTableLabelProvider() {
+		super();
+	}
+
+	/**
+	 * Returns the label image for the given column of the given element.
+	 *
+	 * @param element the object representing the entire row, or 
+	 *    <code>null</code> indicating that no input object is set
+	 *    in the viewer
+	 * @param columnIndex the zero-based index of the column in which
+	 *   the label appears
+	 */
+	public Image getColumnImage(Object element, int columnIndex) {
+		if (columnIndex == 0) {
+			IRuntime runtime = (IRuntime) element;
+			IRuntimeType runtimeType = runtime.getRuntimeType();
+			if (runtimeType != null)
+				return ImageResource.getImage(runtimeType.getId());
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the label text for the given column of the given element.
+	 *
+	 * @param element the object representing the entire row, or
+	 *   <code>null</code> indicating that no input object is set
+	 *   in the viewer
+	 * @param columnIndex the zero-based index of the column in which the label appears
+	 */
+	public String getColumnText(Object element, int columnIndex) {
+		IRuntime runtime = (IRuntime) element;
+		if (columnIndex == 0)
+			return notNull(runtime.getName());
+		/*else if (columnIndex == 1) {
+			IPath location = runtime.getLocation();
+			if (location == null)
+				return "";
+			else
+				return notNull(location.toOSString());
+		}*/
+		else if (columnIndex == 1) {
+			IRuntimeType runtimeType = runtime.getRuntimeType();
+			if (runtimeType != null)
+				return notNull(runtimeType.getName());
+			else
+				return "";
+		} else
+			return "X";
+	}
+	
+	public boolean isLocked(Object element) {
+		IRuntime runtime = (IRuntime) element;
+		return runtime.isLocked();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTreeContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTreeContentProvider.java
new file mode 100644
index 0000000..b00ae7e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTreeContentProvider.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IRuntimeType;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.internal.Trace;
+
+/**
+ * Runtime content provider.
+ */
+public class RuntimeTreeContentProvider extends AbstractTreeContentProvider {
+	public static final byte STYLE_VENDOR = 1;
+	public static final byte STYLE_VERSION = 2;
+	public static final byte STYLE_TYPE = 3;
+
+	/**
+	 * RuntimeTreeContentProvider constructor comment.
+	 */
+	public RuntimeTreeContentProvider(byte style) {
+		super(style);
+	}
+	
+	public void fillTree() {
+		List list = new ArrayList();
+		if (style != STYLE_FLAT) {
+			Iterator iterator = ServerCore.getResourceManager().getRuntimes().iterator();
+			while (iterator.hasNext()) {
+				IRuntime runtime = (IRuntime) iterator.next();
+				IRuntimeType runtimeType = runtime.getRuntimeType();
+				try {
+					TreeElement ele = null;
+					if (style == STYLE_VENDOR)
+						ele = getOrCreate(list, runtimeType.getVendor());
+					else if (style == STYLE_VERSION)
+						ele = getOrCreate(list, runtimeType.getVersion());
+					else if (style == STYLE_TYPE)
+						ele = getOrCreate(list, runtimeType.getName());
+					ele.contents.add(runtime);
+					elementToParentMap.put(runtime, ele);
+				} catch (Exception e) {
+					Trace.trace(Trace.WARNING, "Error in runtime content provider", e);
+				}
+			}
+		} else {
+			Iterator iterator = ServerCore.getResourceManager().getRuntimes().iterator();
+			while (iterator.hasNext()) {
+				IRuntime runtime = (IRuntime) iterator.next();
+				list.add(runtime);
+			}
+		}
+		elements = list.toArray();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTreeLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTreeLabelProvider.java
new file mode 100644
index 0000000..3008342
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTreeLabelProvider.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Runtime label provider.
+ */
+public class RuntimeTreeLabelProvider extends AbstractTreeLabelProvider implements ITableLabelProvider {
+	/**
+	 * RuntimeTreeLabelProvider constructor comment.
+	 */
+	public RuntimeTreeLabelProvider() {
+		super();
+	}
+
+	/**
+	 * 
+	 */
+	protected Image getImageImpl(Object element) {
+		IRuntime runtime = (IRuntime) element;
+		if (runtime.getRuntimeType() != null)
+			return ImageResource.getImage(runtime.getRuntimeType().getId());
+		else
+			return null;
+	}
+
+	/**
+	 * 
+	 */
+	protected String getTextImpl(Object element) {
+		IRuntime runtime = (IRuntime) element;
+		return notNull(runtime.getName());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+	 */
+	public Image getColumnImage(Object element, int columnIndex) {
+		if (columnIndex == 0) {
+			if (element instanceof ServerTreeContentProvider.TreeElement) {
+				ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
+				return sharedImages.getImage(ISharedImages.IMG_OBJ_FOLDER);
+			} else
+				return getImageImpl(element);
+		} else
+			return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+	 */
+	public String getColumnText(Object element, int columnIndex) {
+		if (element instanceof ServerTreeContentProvider.TreeElement) {
+			if (columnIndex == 0)
+				return ((ServerTreeContentProvider.TreeElement) element).text;
+			else
+				return "";
+		} else {
+			IRuntime runtime = (IRuntime) element;
+			if (columnIndex == 0)
+				return runtime.getName();
+			else if (columnIndex == 1) {
+				if (runtime.getRuntimeType() != null)
+					return notNull(runtime.getRuntimeType().getName());
+				else
+					return "";
+			} else
+				return "X";
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTypeComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTypeComposite.java
new file mode 100644
index 0000000..0fc8990
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTypeComposite.java
@@ -0,0 +1,119 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.wst.server.core.IRuntimeType;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * 
+ */
+public class RuntimeTypeComposite extends AbstractTreeComposite {
+	protected IRuntimeType selection;
+	protected RuntimeTypeSelectionListener listener;
+	protected boolean creation;
+	protected String type;
+	protected String version;
+	protected String runtimeTypeId;
+	
+	protected RuntimeTypeTreeContentProvider contentProvider;
+	protected boolean initialSelection = true;
+	
+	public interface RuntimeTypeSelectionListener {
+		public void runtimeTypeSelected(IRuntimeType runtimeType);
+	}
+	
+	public RuntimeTypeComposite(Composite parent, int style, boolean creation, RuntimeTypeSelectionListener listener2, String type, String version, String runtimeTypeId) {
+		super(parent, style);
+		this.listener = listener2;
+		this.creation = creation;
+		this.type = type;
+		this.version = version;
+		this.runtimeTypeId = runtimeTypeId;
+	
+		contentProvider = new RuntimeTypeTreeContentProvider(RuntimeTypeTreeContentProvider.STYLE_VENDOR, creation, type, version, runtimeTypeId);
+		treeViewer.setContentProvider(contentProvider);
+		treeViewer.setLabelProvider(new RuntimeTypeTreeLabelProvider());
+		treeViewer.setInput(AbstractTreeContentProvider.ROOT);
+
+		treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				Object obj = getSelection(event.getSelection());
+				if (obj instanceof IRuntimeType) {
+					selection = (IRuntimeType) obj;
+					setDescription(selection.getDescription());
+				} else {
+					selection = null;
+					setDescription("");
+				}
+				listener.runtimeTypeSelected(selection);
+			}
+		});
+		
+		treeViewer.setSorter(new ViewerSorter() {
+			public int compare(Viewer viewer, Object e1, Object e2) {
+				if (e1 instanceof IRuntimeType && !(e2 instanceof IRuntimeType))
+					return 1;
+				if (!(e1 instanceof IRuntimeType) && e2 instanceof IRuntimeType)
+					return -1;
+				if (!(e1 instanceof IRuntimeType && e2 instanceof IRuntimeType))
+					return super.compare(viewer, e1, e2);
+				IRuntimeType r1 = (IRuntimeType) e1;
+				IRuntimeType r2 = (IRuntimeType) e2;
+				if (r1.getOrder() > r2.getOrder())
+					return -1;
+				else if (r1.getOrder() < r2.getOrder())
+					return 1;
+				else
+					return super.compare(viewer, e1, e2);
+			}
+		});
+	}
+	
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		if (visible && initialSelection) {
+			initialSelection = false;
+			if (contentProvider.getInitialSelection() != null)
+				treeViewer.setSelection(new StructuredSelection(contentProvider.getInitialSelection()), true);
+		}
+	}
+	
+	protected String getTitleLabel() {
+		return ServerUIPlugin.getResource("%runtimeTypeCompTree");
+	}
+
+	protected String getDescriptionLabel() {
+		return ServerUIPlugin.getResource("%runtimeTypeCompDescription");
+	}
+
+	protected String[] getComboOptions() {
+		return new String[] { ServerUIPlugin.getResource("%name"),
+			ServerUIPlugin.getResource("%vendor"), ServerUIPlugin.getResource("%version"),
+			ServerUIPlugin.getResource("%moduleSupport") };
+	}
+
+	protected void viewOptionSelected(byte option) {
+		ISelection sel = treeViewer.getSelection();
+		treeViewer.setContentProvider(new RuntimeTypeTreeContentProvider(option, creation, type, version, runtimeTypeId));
+		treeViewer.setSelection(sel);
+	}
+
+	public IRuntimeType getSelectedRuntimeType() {
+		return selection;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTypeTreeContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTypeTreeContentProvider.java
new file mode 100644
index 0000000..12bc693
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTypeTreeContentProvider.java
@@ -0,0 +1,106 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.server.core.IModuleKind;
+import org.eclipse.wst.server.core.IModuleType;
+import org.eclipse.wst.server.core.IRuntimeType;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.ServerUtil;
+/**
+ * Runtime type content provider.
+ */
+public class RuntimeTypeTreeContentProvider extends AbstractTreeContentProvider {
+	public static final byte STYLE_VENDOR = 1;
+	public static final byte STYLE_VERSION = 2;
+	public static final byte STYLE_MODULE_TYPE = 3;
+	
+	protected boolean creation;
+	protected String type;
+	protected String version;
+	protected String runtimeTypeId;
+
+	/**
+	 * RuntimeTypeContentProvider constructor comment.
+	 */
+	public RuntimeTypeTreeContentProvider(byte style, boolean creation) {
+		super(style);
+		this.creation = creation;
+	}
+	
+	public RuntimeTypeTreeContentProvider(byte style, boolean creation, String type, String version, String runtimeTypeId) {
+		super(style, false);
+		this.type = type;
+		this.version = version;
+		this.runtimeTypeId = runtimeTypeId;
+		this.creation = creation;
+		
+		fillTree();
+	}
+	
+	public void fillTree() {
+		initialSelection = null;
+		initialSelectionOrder = -1000;
+		List list = new ArrayList();
+		if (style != STYLE_FLAT) {
+			Iterator iterator = ServerUtil.getRuntimeTypes(type, version, runtimeTypeId).iterator();
+			while (iterator.hasNext()) {
+				IRuntimeType runtimeType = (IRuntimeType) iterator.next();
+				if (!creation || runtimeType.canCreate()) {
+					if (runtimeType.getOrder() > initialSelectionOrder) {
+						initialSelection = runtimeType;
+						initialSelectionOrder = runtimeType.getOrder();
+					}
+					TreeElement ele = null;
+					if (style == STYLE_VENDOR) {
+						ele = getOrCreate(list, runtimeType.getVendor());
+						ele.contents.add(runtimeType);
+						elementToParentMap.put(runtimeType, ele);
+					} else if (style == STYLE_VERSION) {
+						ele = getOrCreate(list, runtimeType.getVersion());
+						ele.contents.add(runtimeType);
+						elementToParentMap.put(runtimeType, ele);
+					} else if (style == STYLE_MODULE_TYPE) {
+						Iterator iterator2 = runtimeType.getModuleTypes().iterator();
+						while (iterator2.hasNext()) {
+							IModuleType mb = (IModuleType) iterator2.next();
+							IModuleKind mt = ServerCore.getModuleKind(mb.getType());
+							if (mt != null) {
+								ele = getOrCreate(list, mt.getName());
+								TreeElement ele2 = getOrCreate(ele.contents, mt.getName() + "/" + mb.getVersion(), mb.getVersion());
+								ele2.contents.add(runtimeType);
+								elementToParentMap.put(runtimeType, ele2);
+								elementToParentMap.put(ele2, ele);
+							}
+						}
+					}
+				}
+			}
+		} else {
+			Iterator iterator = ServerUtil.getRuntimeTypes(type, version, runtimeTypeId).iterator();
+			while (iterator.hasNext()) {
+				IRuntimeType runtimeType = (IRuntimeType) iterator.next();
+				if (!creation || runtimeType.canCreate()) {
+					if (runtimeType.getOrder() > initialSelectionOrder) {
+						initialSelection = runtimeType;
+						initialSelectionOrder = runtimeType.getOrder();
+					}
+					list.add(runtimeType);
+				}
+			}
+		}
+		elements = list.toArray();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTypeTreeLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTypeTreeLabelProvider.java
new file mode 100644
index 0000000..7ddfcb4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/RuntimeTypeTreeLabelProvider.java
@@ -0,0 +1,43 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.wst.server.core.IRuntimeType;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Runtime type label provider.
+ */
+public class RuntimeTypeTreeLabelProvider extends AbstractTreeLabelProvider {
+	/**
+	 * RuntimeTypeTreeLabelProvider constructor comment.
+	 */
+	public RuntimeTypeTreeLabelProvider() {
+		super();
+	}
+
+	/**
+	 * 
+	 */
+	protected Image getImageImpl(Object element) {
+		IRuntimeType runtimeType = (IRuntimeType) element;
+		return ImageResource.getImage(runtimeType.getId());
+	}
+
+	/**
+	 * 
+	 */
+	protected String getTextImpl(Object element) {
+		IRuntimeType runtimeType = (IRuntimeType) element;
+		return notNull(runtimeType.getName());
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/SView.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/SView.java
new file mode 100644
index 0000000..f2ee95b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/SView.java
@@ -0,0 +1,274 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Region;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TypedListener;
+/**
+ * Simple SWT widget with an image banner and a label.
+ */
+public class SView extends Canvas {
+	protected Color focusColor;
+	protected boolean mouseOver = false;
+	protected boolean hasFocus = false;
+	//protected boolean isOpen = true;
+	
+	//protected String name;
+	//protected String description;
+	
+	protected Color one;
+	protected Color two;
+	protected Color three;
+	
+	protected Color grone;
+	protected Color grtwo;
+	protected Color grthree;
+	
+	private Cursor cursor;
+
+	public SView(Composite parent, int style) {
+		super(parent, style);
+		
+		cursor = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND);
+		setCursor(cursor);
+		
+		one = new Color(getDisplay(), 224, 244, 252);
+		two = new Color(getDisplay(), 178, 212, 247);
+		three = new Color(getDisplay(), 138, 185, 242);
+		
+		grone = new Color(getDisplay(), 229, 255, 193);
+		grtwo = new Color(getDisplay(), 63, 214, 16);
+		grthree = new Color(getDisplay(), 21, 157, 4);
+
+		addPaintListener(new PaintListener() {
+			public void paintControl(PaintEvent e) {
+				SView.this.paintControl(e);
+			}
+		});
+		addMouseListener(new MouseListener() {
+			public void mouseDown(MouseEvent e) {
+				//changeTwistie(!isOpen);
+			}
+			public void mouseUp(MouseEvent e) {
+			}
+			public void mouseDoubleClick(MouseEvent e) {
+			}
+		});
+		addMouseTrackListener(new MouseTrackListener() {
+			public void mouseEnter(MouseEvent e) {
+				mouseOver = true;
+				SView.this.redraw();
+			}
+			public void mouseExit(MouseEvent e) {
+				mouseOver = false;
+				SView.this.redraw();
+			}
+			public void mouseHover(MouseEvent e) {
+			}
+		});
+		addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				//changeTwistie(!isOpen);
+				redraw();
+			}
+		});
+		addListener(SWT.Traverse, new Listener () {
+			public void handleEvent(Event e) {
+				if (e.detail != SWT.TRAVERSE_RETURN)
+					e.doit = true;
+			}
+		});
+		addFocusListener(new FocusListener() {
+			public void focusGained(FocusEvent e) {
+				hasFocus = true;
+				redraw();
+			}
+			public void focusLost(FocusEvent e) {
+				hasFocus = false;
+				redraw();
+			}
+		});
+		addKeyListener(new KeyAdapter() {
+			public void keyPressed(KeyEvent e) {
+				if (e.character == '\r') {
+					// Activation
+					notifyListeners(SWT.Selection);
+				}
+			}
+		});
+		addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				disposeImpl();
+			}
+		});
+		
+		getAccessible().addAccessibleListener(new AccessibleAdapter() {
+			public void getName(AccessibleEvent e) {
+				//e.result = name;
+			}
+
+			public void getDescription(AccessibleEvent e) {
+				//e.result = description;
+			}
+		});
+
+		getAccessible().addAccessibleControlListener(new AccessibleControlAdapter() {
+			public void getLocation(AccessibleControlEvent e) {
+				Rectangle location = getBounds();
+				Point pt = toDisplay(new Point(location.x, location.y));
+				e.x = pt.x;
+				e.y = pt.y;
+				e.width = location.width;
+				e.height = location.height;
+			}
+
+			public void getChildCount(AccessibleControlEvent e) {
+				e.detail = 0;
+			}
+
+			public void getRole(AccessibleControlEvent e) {
+				e.detail = ACC.ROLE_TREE;
+			}
+
+			public void getState(AccessibleControlEvent e) {
+				//e.detail = isOpen ? ACC.STATE_EXPANDED : ACC.STATE_COLLAPSED;
+			}
+		});
+	}
+	
+	protected void disposeImpl() {
+		if (cursor != null) {
+			cursor.dispose();
+			cursor = null;
+			one.dispose();
+			two.dispose();
+			three.dispose();
+			
+			grone.dispose();
+			grtwo.dispose();
+			grthree.dispose();
+		}
+	}
+
+	public void addSelectionListener(SelectionListener listener) {
+		checkWidget ();
+		if (listener == null) return;
+		TypedListener typedListener = new TypedListener (listener);
+		addListener (SWT.Selection,typedListener);
+	}
+	
+	public void removeSelectionListener(SelectionListener listener) {
+		checkWidget ();
+		if (listener == null) return;
+		removeListener (SWT.Selection, listener);
+	}
+	
+	protected void notifyListeners(int eventType) {
+		Event event = new Event();
+		event.type = eventType;
+		event.widget = this;
+		notifyListeners(eventType, event);
+	}
+	
+	protected void paintRect(GC gc, int x, int y, Color a, Color b, Color c) {
+		int[] p = new int[] { 0, 2, 2, 0, 30, 0, 32, 2, 32, 30, 30, 32, 2, 32, 0, 30};
+		
+		int[] q = new int[p.length];
+		for (int i = 0; i < p.length / 2; i++) {
+			q[i*2] = p[i*2] + x;
+			q[i*2+1] = p[i*2+1] + y;
+		}
+		
+		Region region = new Region(getDisplay());
+		region.add(q);
+		
+		gc.setClipping(region);
+		
+		gc.setBackground(a);
+		gc.setForeground(b);
+		gc.fillGradientRectangle(x, y, 32, 32, true);
+		gc.setClipping((Region)null);
+		gc.setForeground(c);
+		gc.drawPolygon(q);
+		
+		gc.setForeground(getForeground());
+		gc.setBackground(getBackground());
+		String st = "Tomcat Test Environment";
+		Point stp = gc.stringExtent(st);
+		gc.drawString(st, x+16 - stp.x / 2, y + 32 + 2);
+	}
+
+	void paintControl(PaintEvent e) {
+		GC gc = e.gc;
+		
+		Point s = getSize();
+
+		gc.setBackground(getBackground());
+		gc.fillRectangle(0, 0, s.x, s.y);
+
+		/*if (mouseOver)
+			gc.setBackground(getFocusColor());
+		else
+			gc.setBackground(getForeground());*/
+		
+		// one
+		paintRect(gc, 60, 0, one, two, three);
+		
+		paintRect(gc, 140, 0, grone, grtwo, grthree);
+		
+		/*if (hasFocus) {
+			gc.setBackground(getBackground());
+	   		gc.setForeground(getFocusColor());
+	   		gc.drawFocus(0, 0, 10, 11);
+		}*/
+	}
+
+	/*public Color getFocusColor() {
+		return focusColor;
+	}
+
+	public void setFocusColor(Color color) {
+		focusColor = color;
+	}*/
+
+	public Point computeSize(int wHint, int hHint, boolean changed) {
+		return new Point(200, 60);
+	}
+}
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..8a7eca1
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerComposite.java
@@ -0,0 +1,110 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * 
+ */
+public class ServerComposite extends AbstractTreeComposite {
+	protected IServer selection;
+	protected ServerSelectionListener listener;
+	protected ServerTreeContentProvider contentProvider;
+	protected boolean initialSelection = true;
+	protected byte viewOption;
+	
+	protected IModule module;
+	protected String launchMode;
+	
+	public interface ServerSelectionListener {
+		public void serverSelected(IServer server);
+	}
+	
+	public ServerComposite(Composite parent, int style, ServerSelectionListener listener2, IModule module, String launchMode) {
+		super(parent, style);
+		this.module = module;
+		this.launchMode = launchMode;
+		
+		this.listener = listener2;
+		
+		contentProvider = new ServerTreeContentProvider(ServerTreeContentProvider.STYLE_HOST, module, launchMode);
+		viewOption = ServerTreeContentProvider.STYLE_HOST;
+		treeViewer.setContentProvider(contentProvider);
+		treeViewer.setLabelProvider(new ServerTreeLabelProvider());
+		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);
+			}
+		});
+	}
+
+	public ServerComposite(Composite parent, int style, ServerSelectionListener listener2) {
+		this(parent, style, listener2, null, null);
+	}
+
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		if (visible && initialSelection) {
+			initialSelection = false;
+			if (contentProvider.getInitialSelection() != null)
+				treeViewer.setSelection(new StructuredSelection(contentProvider.getInitialSelection()), true);
+		}
+	}
+
+	public void refreshAll() {
+		ISelection sel = treeViewer.getSelection();
+		contentProvider = new ServerTreeContentProvider(viewOption, module, launchMode);
+		treeViewer.setContentProvider(contentProvider);
+		treeViewer.setSelection(sel);
+	}
+	
+	/*protected boolean hasDescription() {
+		return true;
+	}*/
+	
+	protected String getDescriptionLabel() {
+		return null; //ServerUIPlugin.getResource("%serverTypeCompDescription");
+	}
+	
+	protected String getTitleLabel() {
+		return "Select the server that you want to use:";
+	}
+
+	protected String[] getComboOptions() {
+		return new String[] { ServerUIPlugin.getResource("%name"), ServerUIPlugin.getResource("%host"), 
+			ServerUIPlugin.getResource("%vendor"), ServerUIPlugin.getResource("%version")};
+	}
+
+	protected void viewOptionSelected(byte option) {
+		ISelection sel = treeViewer.getSelection();
+		viewOption = option;
+		contentProvider = new ServerTreeContentProvider(option, module, launchMode);
+		treeViewer.setContentProvider(contentProvider);
+		treeViewer.setSelection(sel);
+	}
+	
+	public IServer getSelectedServer() {
+		return selection;
+	}
+	
+	public void setSelection(IServer server) {
+		treeViewer.setSelection(new StructuredSelection(server), true);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerConfigurationTypeComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerConfigurationTypeComposite.java
new file mode 100644
index 0000000..a080b01
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerConfigurationTypeComposite.java
@@ -0,0 +1,64 @@
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.wst.server.core.IServerConfigurationType;
+/**
+ * 
+ */
+public class ServerConfigurationTypeComposite extends AbstractTreeComposite {
+	protected IServerConfigurationType selection;
+	protected ServerConfigurationTypeSelectionListener listener;
+	
+	public interface ServerConfigurationTypeSelectionListener {
+		public void configurationTypeSelected(IServerConfigurationType type);
+	}
+	
+	public ServerConfigurationTypeComposite(Composite parent, int style, ServerConfigurationTypeSelectionListener listener2) {
+		super(parent, style);
+		this.listener = listener2;
+	
+		treeViewer.setContentProvider(new ServerConfigurationTypeTreeContentProvider(RuntimeTreeContentProvider.STYLE_VENDOR));
+		treeViewer.setLabelProvider(new ServerConfigurationTypeTreeLabelProvider());
+		treeViewer.setInput(AbstractTreeContentProvider.ROOT);
+
+		treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				Object obj = getSelection(event.getSelection());
+				if (obj instanceof IServerConfigurationType) {
+					selection = (IServerConfigurationType) obj;
+					setDescription(selection.getDescription());
+				} else {
+					selection = null;
+					setDescription("");
+				}
+				listener.configurationTypeSelected(selection);
+			}
+		});
+	}
+	
+	protected String getDescriptionLabel() {
+		return null; //ServerUIPlugin.getResource("%serverTypeCompDescription");
+	}
+
+	protected String getTitleLabel() {
+		return "Select the server configuration type:";
+	}
+
+	protected String[] getComboOptions() {
+		return new String[] {"Name", "Vendor", "Version"};
+	}
+
+	protected void viewOptionSelected(byte option) {
+		ISelection sel = treeViewer.getSelection();
+		treeViewer.setContentProvider(new ServerConfigurationTypeTreeContentProvider(option));
+		treeViewer.setSelection(sel);
+	}
+
+	public IServerConfigurationType getSelectedServerConfigurationType() {
+		return selection;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerConfigurationTypeTreeContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerConfigurationTypeTreeContentProvider.java
new file mode 100644
index 0000000..77eca6f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerConfigurationTypeTreeContentProvider.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.server.core.IServerConfigurationType;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.internal.Trace;
+
+/**
+ * Server configuration type content provider.
+ */
+public class ServerConfigurationTypeTreeContentProvider extends AbstractTreeContentProvider {
+	public static final byte STYLE_VENDOR = 1;
+	public static final byte STYLE_VERSION = 2;
+	public static final byte STYLE_HOST = 3;
+	public static final byte STYLE_TYPE = 4;
+
+	/**
+	 * ServerConfigurationTypeTreeContentProvider constructor comment.
+	 */
+	public ServerConfigurationTypeTreeContentProvider(byte style) {
+		super(style);
+	}
+	
+	public void fillTree() {
+		List list = new ArrayList();
+		Iterator iterator = ServerCore.getServerConfigurationTypes().iterator();
+		while (iterator.hasNext()) {
+			IServerConfigurationType type = (IServerConfigurationType) iterator.next();
+			if (style == STYLE_FLAT) {
+				list.add(type);
+			} else {
+				try {
+					/*TreeElement ele = null;
+					if (style == STYLE_VENDOR)
+						ele = getOrCreate(list, runtimeType.getVendor());
+					else if (style == STYLE_VERSION)
+						ele = getOrCreate(list, runtimeType.getVersion());
+					else if (style == STYLE_HOST)
+						ele = getOrCreate(list, runtime.getHost());
+					else if (style == STYLE_TYPE)
+						ele = getOrCreate(list, runtimeType.getLabel());
+					ele.contents.add(type);
+					elementToParentMap.put(type, ele);*/
+				} catch (Exception e) {
+					Trace.trace(Trace.WARNING, "Error in server configuration content provider", e);
+				}
+			}
+		}
+		elements = list.toArray();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerConfigurationTypeTreeLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerConfigurationTypeTreeLabelProvider.java
new file mode 100644
index 0000000..08b91d6
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerConfigurationTypeTreeLabelProvider.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.wst.server.core.IServerConfigurationType;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Server configuration type label provider.
+ */
+public class ServerConfigurationTypeTreeLabelProvider extends AbstractTreeLabelProvider {
+	/**
+	 * ServerConfigurationTypeTreeLabelProvider constructor comment.
+	 */
+	public ServerConfigurationTypeTreeLabelProvider() {
+		super();
+	}
+
+	/**
+	 * 
+	 */
+	protected Image getImageImpl(Object element) {
+		IServerConfigurationType type = (IServerConfigurationType) element;
+		return ImageResource.getImage(type.getId());
+	}
+
+	/**
+	 * 
+	 */
+	protected String getTextImpl(Object element) {
+		IServerConfigurationType type = (IServerConfigurationType) element;
+		return notNull(type.getName());
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTreeContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTreeContentProvider.java
new file mode 100644
index 0000000..ab7ec3f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTreeContentProvider.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+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.ServerCore;
+import org.eclipse.wst.server.core.ServerUtil;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * Runtime type content provider.
+ */
+public class ServerTreeContentProvider extends AbstractTreeContentProvider {
+	public static final byte STYLE_HOST = 1;
+	public static final byte STYLE_VENDOR = 2;
+	public static final byte STYLE_VERSION = 3;
+	
+	protected IModule module;
+	protected String launchMode;
+
+	/**
+	 * ServerTreeContentProvider constructor comment.
+	 */
+	public ServerTreeContentProvider(byte style) {
+		super(style);
+	}
+	
+	public ServerTreeContentProvider(byte style, IModule module, String launchMode) {
+		super(style, false);
+		this.module = module;
+		this.launchMode = launchMode;
+		
+		fillTree();
+	}
+	
+	protected void fillTree() {
+		List list = new ArrayList();
+		if (style != STYLE_FLAT) {
+			Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server = (IServer) iterator.next();
+				if (acceptServer(server)) {
+					IServerType serverType = server.getServerType();
+					IRuntimeType runtimeType = serverType.getRuntimeType();
+					if (serverType.getOrder() > initialSelectionOrder) {
+						initialSelection = server;
+						initialSelectionOrder = serverType.getOrder();
+					}
+					TreeElement te = null;
+					if (style == STYLE_HOST) {
+						te = getOrCreate(list, server.getHostname());
+					} else if (style == STYLE_VERSION) {
+						String version = ServerUIPlugin.getResource("%elementUnknownName");
+						if (runtimeType != null)
+							version = runtimeType.getVersion();
+						te = getOrCreate(list, version);
+					} else if (style == STYLE_VENDOR) {
+						String vendor = ServerUIPlugin.getResource("%elementUnknownName");
+						if (runtimeType != null)
+							vendor = runtimeType.getVendor();
+						te = getOrCreate(list, vendor);
+					}
+					te.contents.add(server);
+					elementToParentMap.put(server, te);
+				}
+			}
+		} else {
+			Iterator iterator = ServerCore.getResourceManager().getServers().iterator();
+			while (iterator.hasNext()) {
+				IServer server = (IServer) iterator.next();
+				if (acceptServer(server)) {
+					IServerType serverType = server.getServerType();
+					list.add(server);
+					if (serverType.getOrder() > initialSelectionOrder) {
+						initialSelection = server;
+						initialSelectionOrder = serverType.getOrder();
+					}
+				}
+			}
+		}
+		elements = list.toArray();
+	}
+
+	protected boolean acceptServer(IServer server) {
+		if (module == null || launchMode == null)
+			return true;
+		if (!ServerUtil.isCompatibleWithLaunchMode(server, launchMode))
+			return false;
+		if (!ServerUtil.isSupportedModule(server.getServerType().getRuntimeType().getModuleTypes(), module.getType(), module.getVersion()))
+			return false;
+		return true;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTreeLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTreeLabelProvider.java
new file mode 100644
index 0000000..126b486
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTreeLabelProvider.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Server tree label provider.
+ */
+public class ServerTreeLabelProvider extends AbstractTreeLabelProvider {
+	/**
+	 * ServerTreeLabelProvider constructor comment.
+	 */
+	public ServerTreeLabelProvider() {
+		super();
+	}
+
+	/**
+	 * 
+	 */
+	public Image getImageImpl(Object element) {
+		IServer server = (IServer) element;
+		return ImageResource.getImage(server.getServerType().getId());
+	}
+
+	/**
+	 * 
+	 */
+	public String getTextImpl(Object element) {
+		IServer server = (IServer) element;
+		return server.getName();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTypeComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTypeComposite.java
new file mode 100644
index 0000000..f52fbe1
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTypeComposite.java
@@ -0,0 +1,131 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.wst.server.core.IServerType;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * 
+ */
+public class ServerTypeComposite extends AbstractTreeComposite {
+	protected IServerType selection;
+	protected ServerTypeSelectionListener listener;
+	protected ServerTypeTreeContentProvider contentProvider;
+	protected boolean initialSelection = true;
+	
+	public interface ServerTypeSelectionListener {
+		public void serverTypeSelected(IServerType type);
+	}
+	
+	public ServerTypeComposite(Composite parent, int style, ServerTypeSelectionListener listener2) {
+		super(parent, style);
+		this.listener = listener2;
+	
+		contentProvider = new ServerTypeTreeContentProvider(ServerTypeTreeContentProvider.STYLE_VENDOR);
+		treeViewer.setContentProvider(contentProvider);
+		treeViewer.setLabelProvider(new ServerTypeTreeLabelProvider());
+		treeViewer.setInput(AbstractTreeContentProvider.ROOT);
+
+		treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				Object obj = getSelection(event.getSelection());
+				if (obj instanceof IServerType) {
+					selection = (IServerType) obj;
+					setDescription(selection.getDescription());
+				} else {
+					selection = null;
+					setDescription("");
+				}
+				listener.serverTypeSelected(selection);
+			}
+		});
+		
+		treeViewer.setSorter(new ViewerSorter() {
+			public int compare(Viewer viewer, Object e1, Object e2) {
+				if (e1 instanceof IServerType && !(e2 instanceof IServerType))
+					return 1;
+				if (!(e1 instanceof IServerType) && e2 instanceof IServerType)
+					return -1;
+				if (!(e1 instanceof IServerType && e2 instanceof IServerType))
+					return super.compare(viewer, e1, e2);
+				IServerType r1 = (IServerType) e1;
+				IServerType r2 = (IServerType) e2;
+				/*if (r1.getOrder() > r2.getOrder())
+					return -1;
+				else if (r1.getOrder() < r2.getOrder())
+					return 1;
+				else
+					return super.compare(viewer, e1, e2);*/
+				return r1.getName().compareTo(r2.getName());
+			}
+		});
+	}
+	
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		if (visible && initialSelection) {
+			initialSelection = false;
+			if (contentProvider.getInitialSelection() != null)
+				treeViewer.setSelection(new StructuredSelection(contentProvider.getInitialSelection()), true);
+		}
+	}
+	
+	public void setHost(boolean localhost) {
+		if (localhost == contentProvider.getHost())
+			return;
+		
+		ISelection sel = treeViewer.getSelection();
+		contentProvider.setHost(localhost);
+		contentProvider.fillTree();
+		treeViewer.refresh();
+		//treeViewer.expandToLevel(2);
+		treeViewer.setSelection(sel, true);
+	}
+	
+	public void setIncludeTestEnvironments(boolean b) {
+		contentProvider.setIncludeTestEnvironments(b);
+		contentProvider.fillTree();
+		treeViewer.refresh();
+		//treeViewer.expandToLevel(2);
+	}
+	
+	protected String getDescriptionLabel() {
+		return null; //ServerUIPlugin.getResource("%serverTypeCompDescription");
+	}
+
+	protected String getTitleLabel() {
+		return ServerUIPlugin.getResource("%serverTypeCompDescription");
+	}
+
+	protected String[] getComboOptions() {
+		return new String[] { ServerUIPlugin.getResource("%name"),
+			ServerUIPlugin.getResource("%vendor"), ServerUIPlugin.getResource("%version"),
+			ServerUIPlugin.getResource("%moduleSupport") };
+	}
+
+	protected void viewOptionSelected(byte option) {
+		ISelection sel = treeViewer.getSelection();
+		treeViewer.setContentProvider(new ServerTypeTreeContentProvider(option));
+		treeViewer.setSelection(sel);
+	}
+
+	public IServerType getSelectedServerType() {
+		return selection;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTypeTreeContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTypeTreeContentProvider.java
new file mode 100644
index 0000000..2a3d7ae
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTypeTreeContentProvider.java
@@ -0,0 +1,133 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.ui.internal.Trace;
+
+/**
+ * Server type content provider.
+ */
+public class ServerTypeTreeContentProvider extends AbstractTreeContentProvider {
+	public static final byte STYLE_VENDOR = 1;
+	public static final byte STYLE_VERSION = 2;
+	public static final byte STYLE_MODULE_TYPE = 3;
+	public static final byte STYLE_TYPE = 4; // not used yet
+	
+	protected boolean localhost;
+	protected boolean includeTestEnvironments = true;
+
+	/**
+	 * ServerTypeTreeContentProvider constructor comment.
+	 */
+	public ServerTypeTreeContentProvider(byte style) {
+		super(style, false);
+		localhost = true;
+		
+		fillTree();
+	}
+	
+	public void fillTree() {
+		elementToParentMap = new HashMap();
+		textMap = new HashMap();
+		initialSelection = null;
+		initialSelectionOrder = -1000;
+
+		List list = new ArrayList();
+		Iterator iterator = ServerCore.getServerTypes().iterator();
+		while (iterator.hasNext()) {
+			IServerType type = (IServerType) iterator.next();
+			if (include(type)) {
+				if (type.getOrder() > initialSelectionOrder) {
+					initialSelection = type;
+					initialSelectionOrder = type.getOrder();
+				}
+				if (style == STYLE_FLAT) {
+					list.add(type);
+				} else if (style != STYLE_MODULE_TYPE) {
+					try {
+						IRuntimeType runtimeType = type.getRuntimeType();
+						TreeElement ele = null;
+						if (style == STYLE_VENDOR)
+							ele = getOrCreate(list, runtimeType.getVendor());
+						else if (style == STYLE_VERSION)
+							ele = getOrCreate(list, runtimeType.getVersion());
+						else if (style == STYLE_TYPE)
+							ele = getOrCreate(list, runtimeType.getName());
+						ele.contents.add(type);
+						elementToParentMap.put(type, ele);
+					} catch (Exception e) {
+						Trace.trace(Trace.WARNING, "Error in server configuration content provider", e);
+					}
+				} else { // style = MODULE_TYPE
+					IRuntimeType runtimeType = type.getRuntimeType();
+					Iterator iterator2 = runtimeType.getModuleTypes().iterator();
+					while (iterator2.hasNext()) {
+						IModuleType mb = (IModuleType) iterator2.next();
+						IModuleKind mt = ServerCore.getModuleKind(mb.getType());
+						if (mt != null) {
+							TreeElement ele = getOrCreate(list, mt.getName());
+							TreeElement ele2 = getOrCreate(ele.contents, mt.getName() + "/" + mb.getVersion(), mb.getVersion());
+							ele2.contents.add(type);
+							elementToParentMap.put(type, ele2);
+							elementToParentMap.put(ele2, ele);
+						}
+					}
+				}
+			}
+		}
+		elements = list.toArray();
+	}
+
+	protected boolean include(IServerType type) {
+		if (!includeTestEnvironments && type.isTestEnvironment()) {
+			if (!checkForTestEnvironmentRuntime(type))
+				return false;
+		}
+		if (type.supportsRemoteHosts())
+			return true;
+		if (localhost && type.supportsLocalhost())
+			return true;
+		return false;
+	}
+
+	protected boolean checkForTestEnvironmentRuntime(IServerType serverType) {
+		IRuntimeType runtimeType = serverType.getRuntimeType();
+		List list = ServerCore.getResourceManager().getRuntimes(runtimeType);
+		if (list.isEmpty())
+			return false;
+		
+		Iterator iterator = list.iterator();
+		while (iterator.hasNext()) {
+			IRuntime runtime = (IRuntime) iterator.next();
+			if (runtime.isTestEnvironment())
+				return true;
+		}
+		return false;
+	}
+	
+	public boolean getHost() {
+		return localhost;
+	}
+
+	public void setHost(boolean local) {
+		localhost = local;
+	}
+	
+	public void setIncludeTestEnvironments(boolean te) {
+		includeTestEnvironments = te;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTypeTreeLabelProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTypeTreeLabelProvider.java
new file mode 100644
index 0000000..41f044a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerTypeTreeLabelProvider.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package org.eclipse.wst.server.ui.internal.viewers;
+
+import org.eclipse.wst.server.core.IServerType;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Server type label provider.
+ */
+public class ServerTypeTreeLabelProvider extends AbstractTreeLabelProvider {
+	/**
+	 * ServerTypeTreeLabelProvider constructor comment.
+	 */
+	public ServerTypeTreeLabelProvider() {
+		super();
+	}
+
+	/**
+	 * 
+	 */
+	protected Image getImageImpl(Object element) {
+		IServerType type = (IServerType) element;
+		return ImageResource.getImage(type.getId());
+	}
+
+	/**
+	 * 
+	 */
+	protected String getTextImpl(Object element) {
+		IServerType type = (IServerType) element;
+		return notNull(type.getName());
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/AbstractWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/AbstractWizard.java
new file mode 100644
index 0000000..6f8b17c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/AbstractWizard.java
@@ -0,0 +1,49 @@
+package org.eclipse.wst.server.ui.internal.wizard;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.IWorkbench;
+/**
+ * An abstract Wizard that contains helper methods.
+ */
+public abstract class AbstractWizard extends Wizard {
+	protected IWorkbench workbench;
+	protected IStructuredSelection selection;
+
+	/**
+	 * AbstractWizard constructor comment.
+	 */
+	public AbstractWizard() {
+		super();
+	}
+
+	/**
+	 * Return the current workbench.
+	 * 
+	 * @return org.eclipse.ui.IWorkbench
+	 */
+	public IWorkbench getWorkbench() {
+		return workbench;
+	}
+
+	/**
+	 * Initialize the workbench and current selection.
+	 * 
+	 * @param org.eclipse.ui.IWorkbench
+	 * @param org.eclipse.jface.viewers.IStructuredSelection
+	 */
+	public void init(IWorkbench newWorkbench, IStructuredSelection newSelection) {
+		workbench = newWorkbench;
+		selection = newSelection;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ClosableWizardDialog.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ClosableWizardDialog.java
new file mode 100644
index 0000000..79ed55f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ClosableWizardDialog.java
@@ -0,0 +1,35 @@
+package org.eclipse.wst.server.ui.internal.wizard;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.jface.wizard.IWizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.widgets.Shell;
+/**
+ * A closable wizard dialog.
+ */
+public class ClosableWizardDialog extends WizardDialog {
+	/**
+	 * Constructor for ClosableWizardDialog.
+	 * @param shell
+	 * @param wizard
+	 */
+	public ClosableWizardDialog(Shell shell, IWizard wizard) {
+		super(shell, wizard);
+	}
+	
+	/**
+	 * The Finish button has been pressed.
+	 */
+	public void finishPressed() {
+		super.finishPressed();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ImportServerConfigurationWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ImportServerConfigurationWizard.java
new file mode 100644
index 0000000..dda7d0b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ImportServerConfigurationWizard.java
@@ -0,0 +1,40 @@
+package org.eclipse.wst.server.ui.internal.wizard;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.wizard.page.ImportConfigurationWizardPage;
+import org.eclipse.wst.server.ui.internal.wizard.page.WizardUtil;
+import org.eclipse.ui.IImportWizard;
+/**
+ * A wizard to import existing server configurations.
+ */
+public class ImportServerConfigurationWizard extends AbstractWizard implements IImportWizard {
+	protected ImportConfigurationWizardPage page;
+
+	/**
+	 * ImportServerConfiguration constructor comment.
+	 */
+	public ImportServerConfigurationWizard() {
+		super();
+		setWindowTitle(ServerUIPlugin.getResource("%wizImportConfigurationWizardTitle"));
+	}
+	
+	public void addPages() {
+		page = new ImportConfigurationWizardPage();
+		page.setDefaultContainer(WizardUtil.getSelectionContainer(selection));
+		addPage(page);
+	}
+	
+	public boolean performFinish() {
+		return page.performFinish();
+	}
+}
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
new file mode 100644
index 0000000..6e84f81
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ModifyModulesWizard.java
@@ -0,0 +1,59 @@
+package org.eclipse.wst.server.ui.internal.wizard;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.List;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.task.ReleaseServerTask;
+import org.eclipse.wst.server.ui.internal.task.SaveServerTask;
+import org.eclipse.wst.server.ui.internal.wizard.fragment.ModifyModulesWizardFragment;
+import org.eclipse.wst.server.ui.wizard.TaskWizard;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+
+/**
+ * A wizard used to add and remove modules.
+ */
+public class ModifyModulesWizard extends TaskWizard {
+	static class ModifyModulesWizard2 extends WizardFragment {
+		protected IServer server;
+		
+		public ModifyModulesWizard2(IServerWorkingCopy server) {
+			this.server = server;
+		}
+
+		public void createSubFragments(List list) {
+			list.add(new WizardFragment() {
+				public void enter() {
+					getTaskModel().putObject(ITaskModel.TASK_SERVER, server);
+				}
+			});
+			list.add(new ModifyModulesWizardFragment());
+		}
+		
+		public ITask createCancelTask() {
+			return new ReleaseServerTask();
+		}
+		
+		public ITask createFinishTask() {
+			return new SaveServerTask();
+		}
+	}
+
+	/**
+	 * ModifyModulesWizard constructor comment.
+	 */
+	public ModifyModulesWizard(IServer server) {
+		super(ServerUIPlugin.getResource("%wizModuleWizardTitle"), new ModifyModulesWizard2(server.getWorkingCopy()));
+	
+		setNeedsProgressMonitor(true);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/NewRuntimeWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/NewRuntimeWizard.java
new file mode 100644
index 0000000..5c66b42
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/NewRuntimeWizard.java
@@ -0,0 +1,43 @@
+package org.eclipse.wst.server.ui.internal.wizard;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.List;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.task.FinishWizardFragment;
+import org.eclipse.wst.server.ui.internal.task.SaveRuntimeTask;
+import org.eclipse.wst.server.ui.internal.wizard.fragment.NewRuntimeWizardFragment;
+import org.eclipse.wst.server.ui.wizard.TaskWizard;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+/**
+ * A wizard to create a new runtime.
+ */
+public class NewRuntimeWizard extends TaskWizard implements INewWizard {
+	/**
+	 * NewRuntimeWizard constructor comment.
+	 */
+	public NewRuntimeWizard() {
+		super(ServerUIPlugin.getResource("%wizNewRuntimeWizardTitle"), new WizardFragment() {
+			public void createSubFragments(List list) {
+				list.add(new NewRuntimeWizardFragment());
+				list.add(new FinishWizardFragment(new SaveRuntimeTask()));
+			}
+		});
+
+		setForcePreviousAndNextButtons(true);
+	}
+	
+	public void init(IWorkbench newWorkbench, IStructuredSelection newSelection) { }
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/NewServerProjectWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/NewServerProjectWizard.java
new file mode 100644
index 0000000..b4e199b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/NewServerProjectWizard.java
@@ -0,0 +1,75 @@
+package org.eclipse.wst.server.ui.internal.wizard;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
+
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.wizard.page.CreateServerProjectWizardPage;
+/**
+ * Wizard to create a new server project.
+ */
+public class NewServerProjectWizard extends AbstractWizard implements INewWizard, IExecutableExtension {
+	protected CreateServerProjectWizardPage page;
+	private IConfigurationElement configElement;
+
+	/**
+	 * NewServerProjectWizard constructor comment.
+	 */
+	public NewServerProjectWizard() {
+		super();
+		setHelpAvailable(false);
+		setNeedsProgressMonitor(true);
+		
+		setWindowTitle(ServerUIPlugin.getResource("%wizNewServerProjectWizardTitle"));
+	}
+	
+	/**
+	 * Create a new default wizard page.
+	 */
+	public void addPages() {
+		page = new CreateServerProjectWizardPage();
+		addPage(page);
+	}
+	
+	public boolean performFinish() {
+		boolean finish = page.performFinish();
+		if (finish)
+			BasicNewProjectResourceWizard.updatePerspective(configElement);
+		return finish;
+	}
+	
+	/**
+	 * This method is called by the implementation of the method
+	 * <code>IConfigurationElement.createExecutableExtension</code>
+	 * on a newly constructed extension, passing it its relevant configuration 
+	 * information. Most executable extensions only make use of the first 
+	 * two call arguments.
+	 *
+	 * @param config the configuration element used to trigger this execution. 
+	 *		It can be queried by the executable extension for specific
+	 *		configuration properties
+	 * @param propertyName the name of an attribute of the configuration element
+	 *		used on the <code>createExecutableExtension(String)</code> call. This
+	 *		argument can be used in the cases where a single configuration element
+	 *		is used to define multiple executable extensions.
+	 * @param data adapter data in the form of a <code>String</code>, 
+	 *		a <code>Hashtable</code>, or <code>null</code>.
+	 * @exception CoreException if error(s) detected during initialization processing
+	 * @see IConfigurationElement#createExecutableExtension
+	 */
+	public void setInitializationData(IConfigurationElement config, String propertyName, Object data) {
+		configElement = config;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/NewServerWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/NewServerWizard.java
new file mode 100644
index 0000000..ce9b25e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/NewServerWizard.java
@@ -0,0 +1,70 @@
+package org.eclipse.wst.server.ui.internal.wizard;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.core.util.Task;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.ServerUIPreferences;
+import org.eclipse.wst.server.ui.internal.task.*;
+import org.eclipse.wst.server.ui.internal.wizard.fragment.ModifyModulesWizardFragment;
+import org.eclipse.wst.server.ui.internal.wizard.fragment.NewServerWizardFragment;
+import org.eclipse.wst.server.ui.wizard.TaskWizard;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+/**
+ * A wizard to create a new server and server configuration.
+ */
+public class NewServerWizard extends TaskWizard implements INewWizard {
+	/**
+	 * NewServerWizard constructor comment.
+	 */
+	public NewServerWizard() {
+		super(ServerUIPlugin.getResource("%wizNewServerWizardTitle"), new WizardFragment() {
+			public void createSubFragments(List list) {
+				list.add(new NewServerWizardFragment());
+				//list.add(new ServerConfigurationWizardFragment());
+				list.add(new ModifyModulesWizardFragment());
+				list.add(new FinishWizardFragment(new SaveRuntimeTask()));
+				list.add(new FinishWizardFragment(new SaveServerTask()));
+				list.add(new FinishWizardFragment(new SaveServerConfigurationTask()));
+				list.add(new FinishWizardFragment(new Task() {
+					public void execute(IProgressMonitor monitor) throws CoreException {
+						try {
+							IServer server = (IServer) getTaskModel().getObject(ITaskModel.TASK_SERVER);
+							((ServerUIPreferences)ServerUICore.getPreferences()).addHostname(server.getHostname());
+						} catch (Exception e) { }
+					}
+				}));
+			}
+		});
+		
+		setForcePreviousAndNextButtons(true);
+	}
+	
+	public void init(IWorkbench newWorkbench, IStructuredSelection newSelection) { }
+	
+	public IServer getServer() {
+		try {
+			return (IServer) getRootFragment().getTaskModel().getObject(ITaskModel.TASK_SERVER);
+		} catch (Exception e) {
+			return null;
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/SelectClientWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/SelectClientWizard.java
new file mode 100644
index 0000000..dfe0fdd
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/SelectClientWizard.java
@@ -0,0 +1,59 @@
+package org.eclipse.wst.server.ui.internal.wizard;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.List;
+
+import org.eclipse.wst.server.core.IClient;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.wizard.page.SelectClientComposite;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+import org.eclipse.wst.server.ui.wizard.TaskWizard;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * A wizard used to select a server client from a list.
+ */
+public class SelectClientWizard extends TaskWizard {
+	protected static SelectClientComposite comp;
+
+	/**
+	 * SelectClientWizard constructor comment.
+	 */
+	public SelectClientWizard(final List elements) {
+		super(ServerUIPlugin.getResource("%wizSelectClientWizardTitle"),
+			new WizardFragment() {						
+				public boolean hasComposite() {
+					return true;
+				}
+
+				/* (non-Javadoc)
+				 * @see org.eclipse.wst.server.ui.internal.task.WizardTask#getWizardPage()
+				 */
+				public Composite createComposite(Composite parent, IWizardHandle wizard) {
+					comp = new SelectClientComposite(parent, wizard, elements);
+					return comp;
+				}
+			}
+		);
+
+		setForcePreviousAndNextButtons(true);
+	}
+
+	/**
+	 * Return the selected client.
+	 * @return org.eclipse.wst.server.core.model.IServerClient
+	 */
+	public IClient getSelectedClient() {
+		return comp.getSelectedClient();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/SelectServerWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/SelectServerWizard.java
new file mode 100644
index 0000000..d98e7db
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/SelectServerWizard.java
@@ -0,0 +1,80 @@
+package org.eclipse.wst.server.ui.internal.wizard;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ITask;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.util.Task;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.ServerUIPreferences;
+import org.eclipse.wst.server.ui.internal.task.AddModuleTask;
+import org.eclipse.wst.server.ui.internal.task.FinishWizardFragment;
+import org.eclipse.wst.server.ui.internal.wizard.fragment.NewServerWizardFragment;
+import org.eclipse.wst.server.ui.wizard.TaskWizard;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+
+/**
+ * A wizard used to select a server from various lists.
+ */
+public class SelectServerWizard extends TaskWizard {
+	protected static NewServerWizardFragment task;
+
+	/**
+	 * SelectServerWizard constructor comment.
+	 */
+	public SelectServerWizard(final IModule module, final String launchMode) {
+		super(ServerUIPlugin.getResource("%wizSelectServerWizardTitle"), new WizardFragment() {
+			public void createSubFragments(List list) {
+				//task = new ServerSelectionWizardFragment(module, launchMode);
+				task = new NewServerWizardFragment(module, launchMode);
+				list.add(task);
+				list.add(new FinishWizardFragment(new Task() {
+					public void execute(IProgressMonitor monitor) throws CoreException {
+						try {
+							IServer server = (IServer) getTaskModel().getObject(ITaskModel.TASK_SERVER);
+							((ServerUIPreferences)ServerUICore.getPreferences()).addHostname(server.getHostname());
+						} catch (Exception e) { }
+					}
+				}));
+			}
+			public ITask createFinishTask() {
+				return new AddModuleTask(module);
+			}
+		});
+	
+		setNeedsProgressMonitor(true);
+	}
+
+	/**
+	 * Return the server.
+	 * @return org.eclipse.wst.server.core.model.IServer
+	 */
+	public IServer getServer() {
+		if (task == null)
+			return null;
+		else
+			return task.getServer();
+	}
+	
+	public boolean isPreferredServer() {
+		if (task == null)
+			return false;
+		else
+			return task.isPreferredServer();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/SelectTasksWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/SelectTasksWizard.java
new file mode 100644
index 0000000..3153667
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/SelectTasksWizard.java
@@ -0,0 +1,58 @@
+package org.eclipse.wst.server.ui.internal.wizard;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.List;
+
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.task.FinishWizardFragment;
+import org.eclipse.wst.server.ui.internal.task.SaveServerTask;
+import org.eclipse.wst.server.ui.internal.wizard.fragment.TasksWizardFragment;
+import org.eclipse.wst.server.ui.wizard.TaskWizard;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+
+/**
+ * A wizard used to select server and module tasks.
+ */
+public class SelectTasksWizard extends TaskWizard {
+	protected TasksWizardFragment fragment;
+	
+	/**
+	 * SelectTasksWizard constructor comment.
+	 */
+	public SelectTasksWizard(final IServer server, final IServerConfiguration configuration,
+			final List[] parents, final IModule[] modules) {
+		super(ServerUIPlugin.getResource("%wizTaskWizardTitle"));
+		
+		setRootFragment(new WizardFragment() {
+			public void createSubFragments(List list) {
+				fragment = new TasksWizardFragment(server, configuration, parents, modules);
+				list.add(fragment);
+				list.add(new FinishWizardFragment(new SaveServerTask()));
+			}
+		});
+		addPages();
+	}
+
+	/**
+	 * 
+	 */
+	public boolean hasTasks() {
+		return fragment.hasTasks();
+	}
+
+	public boolean hasOptionalTasks() {
+		return fragment.hasOptionalTasks();
+	}
+}
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
new file mode 100644
index 0000000..77019b8
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ModifyModulesWizardFragment.java
@@ -0,0 +1,63 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.wizard.fragment;
+
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.core.ITask;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.ui.internal.task.ModifyModulesTask;
+import org.eclipse.wst.server.ui.internal.wizard.page.ModifyModulesComposite;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * 
+ */
+public class ModifyModulesWizardFragment extends WizardFragment {
+	protected ModifyModulesComposite comp;
+	protected ModifyModulesTask task;
+
+	public ModifyModulesWizardFragment() { }
+	
+	public boolean hasComposite() {
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.WizardTask#getWizardPage()
+	 */
+	public Composite createComposite(Composite parent, IWizardHandle handle) {
+		comp = new ModifyModulesComposite(parent, handle);
+		return comp;
+	}
+
+	public void enter() {
+		if (comp != null) {
+			IServerWorkingCopy server = (IServerWorkingCopy) getTaskModel().getObject(ITaskModel.TASK_SERVER);
+			comp.setServer(server);
+		}
+	}
+
+	public void exit() {
+		if (comp != null) {
+			createFinishTask();
+			task.setAddModules(comp.getModulesToAdd());
+			task.setRemoveModules(comp.getModulesToRemove());
+		}
+	}
+
+	public ITask createFinishTask() {
+		if (task == null)
+			task = new ModifyModulesTask(); 
+		return task;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/NewRuntimeWizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/NewRuntimeWizardFragment.java
new file mode 100644
index 0000000..a90941a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/NewRuntimeWizardFragment.java
@@ -0,0 +1,81 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.wizard.fragment;
+
+import java.util.List;
+
+import org.eclipse.wst.server.core.IRuntimeWorkingCopy;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.wizard.page.NewRuntimeComposite;
+import org.eclipse.wst.server.ui.wizard.IWizardFragment;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * 
+ */
+public class NewRuntimeWizardFragment extends WizardFragment {
+	protected NewRuntimeComposite page;
+	
+	// filter by type/version
+	protected String type;
+	protected String version;
+	
+	// filter by partial runtime type id
+	protected String runtimeTypeId;
+	
+	public NewRuntimeWizardFragment() { }
+	
+	public NewRuntimeWizardFragment(String type, String version, String runtimeTypeId) {
+		this.type = type;
+		this.version = version;
+		this.runtimeTypeId = runtimeTypeId;
+	}
+
+	public boolean hasComposite() {
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.WizardTask#getWizardPage()
+	 */
+	public Composite createComposite(Composite parent, IWizardHandle wizard) {
+		page = new NewRuntimeComposite(parent, wizard, getTaskModel(), type, version, runtimeTypeId);
+		return page;
+	}
+
+	public boolean isComplete() {
+		if (page != null) {
+			if (page.getRuntime() == null)
+				return false;
+			IStatus status = page.getRuntime().validate();
+			return status == null || status.isOK();
+		} else
+			return true;
+	}
+
+	public void createSubFragments(List list) {
+		if (getTaskModel() == null)
+			return;
+	
+		IRuntimeWorkingCopy runtime = (IRuntimeWorkingCopy) getTaskModel().getObject(ITaskModel.TASK_RUNTIME);
+		if (runtime == null)
+			return;
+
+		IWizardFragment sub = ServerUICore.getWizardFragment(runtime.getRuntimeType().getId());
+		if (sub != null)
+			list.add(sub);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/NewServerWizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/NewServerWizardFragment.java
new file mode 100644
index 0000000..4865df6
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/NewServerWizardFragment.java
@@ -0,0 +1,215 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.wizard.fragment;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IModuleVisitor;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.wst.server.ui.internal.wizard.page.NewServerComposite;
+import org.eclipse.wst.server.ui.internal.wizard.page.WizardUtil;
+import org.eclipse.wst.server.ui.wizard.IWizardFragment;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * 
+ */
+public class NewServerWizardFragment extends WizardFragment {
+	public static final String MODE = "mode";
+	public static final byte MODE_EXISTING = 0;
+	public static final byte MODE_DETECT = 1;
+	public static final byte MODE_MANUAL= 2;
+
+	protected NewServerComposite comp;
+	protected IModule module;
+	protected String launchMode;
+	
+	protected Map fragmentMap = new HashMap();
+	protected Map configMap = new HashMap();
+	
+	public NewServerWizardFragment() { }
+	
+	public NewServerWizardFragment(IModule module, String launchMode) {
+		this.module = module;
+		this.launchMode = launchMode;
+	}
+
+	public boolean hasComposite() {
+		return true;
+	}
+	
+	/*public void exit() {
+		if (comp != null)
+			getTaskModel().putObject(ITaskModel.TASK_SERVER, comp.getServer());
+	}*/
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.WizardTask#getWizardPage()
+	 */
+	public Composite createComposite(Composite parent, IWizardHandle wizard) {
+		comp = new NewServerComposite(parent, wizard, module, launchMode);
+		if (getTaskModel() != null)
+			comp.setTaskModel(getTaskModel());
+		return comp;
+	}
+
+	protected void createConfiguration(IServerWorkingCopy server) {
+		ITaskModel model = getTaskModel();
+		IRuntime runtime = (IRuntime) model.getObject(ITaskModel.TASK_RUNTIME);
+		
+		IServerType type = server.getServerType();
+		if (type.hasServerConfiguration()) {
+			server.setServerConfiguration(null);
+			IStatus status = null;
+			if (runtime != null)
+				status = runtime.validate();
+			if (status == null || status.isOK()) {
+				try {
+					IFile file = null;
+					if (ServerCore.getServerPreferences().isCreateResourcesInWorkspace())
+						file = ServerUtil.getUnusedServerConfigurationFile(WizardUtil.getServerProject(), type.getServerConfigurationType());
+					
+					/*IServerConfigurationWorkingCopy serverConfiguration = type.getServerConfigurationType().importFromRuntime(null, file, runtime, new NullProgressMonitor());
+					ServerUtil.setServerConfigurationDefaultName(serverConfiguration);*/
+					IServerConfigurationWorkingCopy serverConfiguration = getServerConfiguration(type.getServerConfigurationType(), file, runtime);
+					model.putObject(ITaskModel.TASK_SERVER_CONFIGURATION, serverConfiguration);
+					server.setServerConfiguration(serverConfiguration);
+				} catch (Exception e) {
+					Trace.trace(Trace.SEVERE, "Could not create configuration", e);
+				}
+			}
+		}
+	}
+	
+	protected IServerConfigurationWorkingCopy getServerConfiguration(IServerConfigurationType type, IFile file, IRuntime runtime) throws CoreException {
+		Object key = type.getId() + "|" + file + "|" + runtime;
+		try {
+			IServerConfigurationWorkingCopy serverConfiguration = (IServerConfigurationWorkingCopy) configMap.get(key);
+			if (serverConfiguration != null)
+				return serverConfiguration;
+		} catch (Exception e) { }
+
+		IServerConfigurationWorkingCopy serverConfiguration = type.importFromRuntime(null, file, runtime, new NullProgressMonitor());
+		ServerUtil.setServerConfigurationDefaultName(serverConfiguration);
+		configMap.put(key, serverConfiguration);
+		return serverConfiguration;
+	}
+
+	protected IWizardFragment getWizardFragment(String typeId) {
+		try {
+			IWizardFragment fragment = (IWizardFragment) fragmentMap.get(typeId);
+			if (fragment != null)
+				return fragment;
+		} catch (Exception e) { }
+		
+		IWizardFragment fragment = ServerUICore.getWizardFragment(typeId);
+		if (fragment != null)
+			fragmentMap.put(typeId, fragment);
+		return fragment;
+	}
+	
+	public List getChildFragments() {
+		listImpl = new ArrayList();
+		createSubFragments(listImpl);
+		return listImpl;
+	}
+
+	public void createSubFragments(List list) {
+		if (getTaskModel() == null)
+			return;
+
+		Byte b = (Byte) getTaskModel().getObject(MODE);
+		if (b != null && b.byteValue() == MODE_MANUAL) {
+			IRuntime runtime = (IRuntime) getTaskModel().getObject(ITaskModel.TASK_RUNTIME);
+			if (runtime != null && runtime instanceof IRuntimeWorkingCopy) {
+				IWizardFragment sub = getWizardFragment(runtime.getRuntimeType().getId());
+				if (sub != null)
+					list.add(sub);
+			}
+			
+			IServerWorkingCopy server = (IServerWorkingCopy) getTaskModel().getObject(ITaskModel.TASK_SERVER);
+			if (server != null) {
+				createConfiguration(server);
+				IWizardFragment sub = getWizardFragment(server.getServerType().getId());
+				if (sub != null)
+					list.add(sub);
+			
+				IServerConfiguration serverConfiguration = server.getServerConfiguration();
+				if (serverConfiguration != null) {
+					sub = getWizardFragment(serverConfiguration.getServerConfigurationType().getId());
+					if (sub != null)
+						list.add(sub);
+				}
+			}
+		} else if (b != null && b.byteValue() == MODE_EXISTING) {
+			if (comp == null)
+				return;
+			
+			IServer server = comp.getServer();
+			if (server == null)
+				return;
+
+			// ---- temp
+			class Helper {
+				List parentList = new ArrayList();
+				List moduleList = new ArrayList();
+			}
+			final Helper help = new Helper();
+			ServerUtil.visit(server, new IModuleVisitor() {
+				public boolean visit(List parents, IModule module2) {
+					help.parentList.add(parents);
+					help.moduleList.add(module2);
+					return true;
+				}
+			});
+			if (!help.moduleList.contains(module)) {
+				help.parentList.add(new ArrayList()); // FIX-ME
+				help.moduleList.add(module);
+			}
+			int size = help.parentList.size();
+			List[] parents = new List[size];
+			help.parentList.toArray(parents);
+			IModule[] modules = new IModule[size];
+			help.moduleList.toArray(modules);
+			// ---- temp
+			
+			TasksWizardFragment fragment = new TasksWizardFragment(server, server.getServerConfiguration(), parents, modules);
+			if (fragment.hasTasks())
+				list.add(fragment);
+		}
+	}
+	
+	public IServer getServer() {
+		if (comp == null)
+			return null;
+		else
+			return comp.getServer();
+	}
+
+	public boolean isPreferredServer() {
+		if (comp == null)
+			return false;
+		else
+			return comp.isPreferredServer();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ServerConfigurationWizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ServerConfigurationWizardFragment.java
new file mode 100644
index 0000000..7210598
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ServerConfigurationWizardFragment.java
@@ -0,0 +1,68 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.wizard.fragment;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.wst.server.ui.internal.wizard.page.WizardUtil;
+import org.eclipse.wst.server.ui.wizard.IWizardFragment;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+
+/**
+ * 
+ */
+public class ServerConfigurationWizardFragment extends WizardFragment {
+	public ServerConfigurationWizardFragment() { }
+
+	public boolean hasComposite() {
+		return false;
+	}
+	
+	public void enter() {
+		ITaskModel model = getTaskModel();
+		IRuntime runtime = (IRuntime) model.getObject(ITaskModel.TASK_RUNTIME);
+		IServerWorkingCopy server = (IServerWorkingCopy) model.getObject(ITaskModel.TASK_SERVER);
+		
+		IServerType type = server.getServerType();
+		if (type.hasServerConfiguration() && server.getServerConfiguration() == null) {
+			try {
+				IFile file = null;
+				if (ServerCore.getServerPreferences().isCreateResourcesInWorkspace())
+					file = ServerUtil.getUnusedServerConfigurationFile(WizardUtil.getServerProject(), type.getServerConfigurationType());
+				
+				IServerConfigurationWorkingCopy serverConfiguration = type.getServerConfigurationType().importFromRuntime(null, file, runtime, new NullProgressMonitor());
+				ServerUtil.setServerConfigurationDefaultName(serverConfiguration);
+				model.putObject(ITaskModel.TASK_SERVER_CONFIGURATION, serverConfiguration);
+				server.setServerConfiguration(serverConfiguration);
+				updateSubFragments();
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Could not create configuration", e);
+			}
+		}
+	}
+
+	public void createSubFragments(List list) {
+		IServerWorkingCopy server = (IServerWorkingCopy) getTaskModel().getObject(ITaskModel.TASK_SERVER);
+		IServerConfiguration serverConfiguration = null;
+		if (server != null)
+			serverConfiguration = server.getServerConfiguration();
+		if (serverConfiguration != null) {
+			IWizardFragment sub = ServerUICore.getWizardFragment(serverConfiguration.getServerConfigurationType().getId());
+			if (sub != null)
+				list.add(sub);
+		}
+	}
+}
\ 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..cc474b1
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/TasksWizardFragment.java
@@ -0,0 +1,233 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.internal.wizard.fragment;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.wst.server.core.IModuleTask;
+import org.eclipse.wst.server.core.IOrdered;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.IServerTask;
+import org.eclipse.wst.server.core.ITask;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.ServerUtil;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.core.model.IModuleTaskDelegate;
+import org.eclipse.wst.server.core.model.IServerTaskDelegate;
+import org.eclipse.wst.server.core.util.ProgressUtil;
+import org.eclipse.wst.server.core.util.Task;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.wst.server.ui.internal.wizard.page.TasksComposite;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * 
+ */
+public class TasksWizardFragment extends WizardFragment {
+	public abstract class TaskInfo implements IOrdered {
+		public IServer server;
+		public IServerConfiguration configuration;
+		public boolean selected;
+		public byte status;
+	}
+
+	public class ServerTaskInfo extends TaskInfo {
+		public IServerTask task2;
+		public List[] parents;
+		public IModule[] modules;
+		
+		public int getOrder() {
+			return task2.getOrder();
+		}
+	}
+	
+	public class ModuleTaskInfo extends TaskInfo {
+		public IModuleTask task2;
+		public List parents;
+		public IModule module;
+		
+		public int getOrder() {
+			return task2.getOrder();
+		}
+	}
+
+	protected TasksComposite comp;
+
+	protected List tasks = new ArrayList();
+	protected boolean hasOptionalTasks;
+	
+	public TasksWizardFragment(IServer server, IServerConfiguration configuration, List[] parents, IModule[] modules) {
+		createTasks(server, configuration, parents, modules);
+	}
+	
+	protected void createTasks(IServer server, IServerConfiguration configuration, List[] parents, IModule[] modules) {
+		// server tasks
+		Iterator iterator = ServerCore.getServerTasks().iterator();
+		while (iterator.hasNext()) {
+			IServerTask task = (IServerTask) iterator.next();
+			task.init(server, configuration, parents, modules);
+			byte status = task.getTaskStatus();
+			if (status != IServerTaskDelegate.TASK_UNNECESSARY) {
+				if (status == IServerTaskDelegate.TASK_READY || status == IServerTaskDelegate.TASK_PREFERRED)
+					hasOptionalTasks = true;
+				addServerTask(server, configuration, parents, modules, task);
+			}
+		}
+		
+		// module tasks
+		int size = modules.length;
+		for (int i = 0; i < size; i++) {
+			iterator = ServerCore.getModuleTasks().iterator();
+			while (iterator.hasNext()) {
+				IModuleTask task = (IModuleTask) iterator.next();
+				task.init(server, configuration, parents[i], modules[i]);
+				byte status = task.getTaskStatus();
+				if (status != IServerTaskDelegate.TASK_UNNECESSARY) {
+					if (status == IServerTaskDelegate.TASK_READY || status == IServerTaskDelegate.TASK_PREFERRED)
+						hasOptionalTasks = true;
+					addModuleTask(server, configuration, parents[i], modules[i], task);
+				}
+			}
+		}
+	}
+	
+	public void addServerTask(IServer server, IServerConfiguration configuration, List[] parents, IModule[] modules, IServerTask task2) {
+		ServerTaskInfo sti = new ServerTaskInfo();
+		sti.server = server;
+		sti.configuration = configuration;
+		sti.parents = parents;
+		sti.modules = modules;
+		sti.task2 = task2;
+		sti.status = task2.getTaskStatus();
+		if (sti.status == IModuleTaskDelegate.TASK_PREFERRED || sti.status == IModuleTaskDelegate.TASK_MANDATORY)
+			sti.selected = true;
+		
+		tasks.add(sti);
+	}
+	
+	public void addModuleTask(IServer server, IServerConfiguration configuration, List parents, IModule module, IModuleTask task2) {
+		ModuleTaskInfo dti = new ModuleTaskInfo();
+		dti.server = server;
+		dti.configuration = configuration;
+		dti.parents = parents;
+		dti.module = module;
+		dti.task2 = task2;
+		dti.status = task2.getTaskStatus();
+		if (dti.status == IModuleTaskDelegate.TASK_PREFERRED || dti.status == IModuleTaskDelegate.TASK_MANDATORY)
+			dti.selected = true;
+		tasks.add(dti);
+	}
+	
+	public boolean hasComposite() {
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.WizardTask#getWizardPage()
+	 */
+	public Composite createComposite(Composite parent, IWizardHandle wizard) {
+		comp = new TasksComposite(parent, wizard, tasks);
+		return comp;
+	}
+
+	public ITask createFinishTask() {
+		return new Task() {
+			public void execute(IProgressMonitor monitor) {
+				performFinish(monitor);
+			}
+		};
+	}
+	
+	/**
+	 * Returns the number of tasks run, or -1 if there was an error.
+	 *
+	 * @param monitor
+	 * @return int
+	 */
+	public void performFinish(IProgressMonitor monitor) {
+		List performTasks = new ArrayList();
+
+		int size = tasks.size();
+		int count = 0;
+		for (int i = 0; i < size; i++) {
+			TaskInfo ti = (TaskInfo) tasks.get(i);
+			if (ti.selected)
+				performTasks.add(tasks.get(i));
+		}
+		
+		monitor.beginTask(ServerUIPlugin.getResource("%performingTasks"), count * 1000);
+		
+		ServerUtil.sortOrderedList(performTasks);
+
+		Iterator iterator = performTasks.iterator();
+		while (iterator.hasNext()) {
+			count++;
+			IProgressMonitor subMonitor = ProgressUtil.getSubMonitorFor(monitor, 1000);
+			Object obj = iterator.next();
+			if (obj instanceof TasksWizardFragment.ServerTaskInfo) {
+				TasksWizardFragment.ServerTaskInfo sti = (TasksWizardFragment.ServerTaskInfo) obj;
+				try {
+					Trace.trace(Trace.FINER, "Executing task: " + sti.task2.getId());
+					sti.task2.execute(subMonitor);
+				} catch (final CoreException ce) {
+					Trace.trace(Trace.SEVERE, "Error executing task " + sti.task2.getId(), ce);
+					Display.getDefault().syncExec(new Runnable() {
+						public void run() {
+							Shell shell = Display.getDefault().getActiveShell();
+							MessageDialog.openError(shell, ServerUIPlugin.getResource("%defaultDialogTitle"), ce.getMessage());
+						}
+					});
+					return;
+				}
+			} else if (obj instanceof ModuleTaskInfo) {
+				ModuleTaskInfo dti = (ModuleTaskInfo) obj;
+				try {
+					Trace.trace(Trace.FINER, "Executing task: " + dti.task2.getId());
+					dti.task2.execute(subMonitor);
+				} catch (final CoreException ce) {
+					Trace.trace(Trace.SEVERE, "Error executing task " + dti.task2.getId(), ce);
+					Display.getDefault().syncExec(new Runnable() {
+						public void run() {
+							Shell shell = Display.getDefault().getActiveShell();
+							MessageDialog.openError(shell, ServerUIPlugin.getResource("%defaultDialogTitle"), ce.getMessage());
+						}
+					});
+					return;
+				}
+			}
+			subMonitor.done();
+		}
+		
+		monitor.done();
+	}
+
+	/**
+	 * 
+	 */
+	public boolean hasTasks() {
+		return !tasks.isEmpty();
+	}
+	
+	public boolean hasOptionalTasks() {
+		return hasOptionalTasks;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/CreateServerProjectWizardPage.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/CreateServerProjectWizardPage.java
new file mode 100644
index 0000000..79dfd5d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/CreateServerProjectWizardPage.java
@@ -0,0 +1,103 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.wst.server.ui.internal.EclipseUtil;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
+/**
+ * Wizard page for creating a new server project.
+ */
+public class CreateServerProjectWizardPage extends WizardNewProjectCreationPage {
+	/**
+	 * WizardNewServerProjectPage constructor comment.
+	 */
+	public CreateServerProjectWizardPage() {
+		super("create server project");
+	
+		setTitle(ServerUIPlugin.getResource("%wizNewServerProjectTitle"));
+		setDescription(ServerUIPlugin.getResource("%wizNewServerProjectDescription"));
+		setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_NEW_SERVER_PROJECT));
+	}
+	
+	/** (non-Javadoc)
+	 * Method declared on IDialogPage.
+	 */
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+
+		Control control = getControl();
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = convertHorizontalDLUsToPixels(475);
+		control.setLayoutData(data);
+	}
+
+	/**
+	 * Creates a project resource handle for the current project name field value.
+	 * <p>
+	 * This method does not create the project resource; this is the responsibility
+	 * of <code>IProject::create</code> invoked by the new project resource wizard.
+	 * </p>
+	 *
+	 * @return the new project resource handle
+	 */
+	public IProject getProjectHandle() {
+		return ResourcesPlugin.getWorkspace().getRoot().getProject(getProjectName());
+	}
+	
+	/**
+	 * Creates the server project and adds the nature.
+	 * @return boolean
+	 */
+	public boolean performFinish() {
+		final String name = getProjectName();
+		IPath path2 = null;
+		if (!useDefaults())
+			path2 = getLocationPath();
+		final IPath path = path2;
+	
+		if (name == null || name.length() == 0)
+			return false;
+	
+		IRunnableWithProgress runnable = new IRunnableWithProgress() {
+			public void run(IProgressMonitor monitor) throws InvocationTargetException {
+				try {
+					IStatus status = EclipseUtil.createNewServerProject(getShell(), name, path, monitor);
+					if (!status.isOK())
+						monitor.setCanceled(true);
+					if (monitor.isCanceled())
+						throw new Exception("Creation canceled");
+				} catch (Exception e) {
+					throw new InvocationTargetException(e);
+				}
+			}
+		};
+		try {
+			getWizard().getContainer().run(true, true, runnable);
+			return true;
+		} catch (Exception e) {
+			Trace.trace("Could not create server project", e);
+			return false;
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ElementCreationCache.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ElementCreationCache.java
new file mode 100644
index 0000000..0fc3fe8
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ElementCreationCache.java
@@ -0,0 +1,163 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementations
+ **********************************************************************/
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IServerConfigurationType;
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+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.ServerUtil;
+/**
+ * A helper class used to cache the creation of server elements.
+ */
+public class ElementCreationCache {
+	protected Map elementCache;
+	protected Map taskCache;
+
+	/**
+	 * ElementCreationCache constructor comment.
+	 */
+	public ElementCreationCache() {
+		super();
+		elementCache = new HashMap();
+		taskCache = new HashMap();
+	}
+	
+	/**
+	 * Return the key to use for the given factory.
+	 *
+	 * @param factory
+	 * @return
+	 */
+	protected String getKey(IServerType type) {
+		return type.getId() + "|";
+	}
+
+	protected String getKey(IServerConfigurationType type) {
+		return type.getId() + "|";
+	}
+
+	/**
+	 * Returns a server configuration. 
+	 *
+	 * @param type org.eclipse.wst.server.core.IServerConfigurationTpye
+	 * @return org.eclipse.wst.server.core.IServerConfigurationWorkingCopy
+	 */
+	public IServerConfigurationWorkingCopy getServerConfiguration(IServerConfigurationType type, IRuntime runtime, IProgressMonitor monitor) throws CoreException {
+		try {
+			IServerConfigurationWorkingCopy configuration = getCachedServerConfiguration(type);
+			if (configuration != null)
+				return configuration;
+		} catch (Exception e) { }
+
+		try {
+			IFile file = null;
+			if (ServerCore.getServerPreferences().isCreateResourcesInWorkspace())
+				file = ServerUtil.getUnusedServerConfigurationFile(WizardUtil.getServerProject(), type);
+			
+			IServerConfigurationWorkingCopy configuration = type.createServerConfiguration(null, file, monitor);
+			if (runtime != null)
+				elementCache.put(getKey(type) + runtime.getId(), configuration);
+			return configuration;
+		} catch (CoreException ce) {
+			throw ce;
+		}
+	}
+
+	/**
+	 * Returns a server. 
+	 *
+	 * @param type org.eclipse.wst.server.core.IServerType
+	 * @return org.eclipse.wst.server.core.IServerWorkingCopy
+	 */
+	public IServerWorkingCopy getServer(IServerType type, IProgressMonitor monitor) throws CoreException {
+		try {
+			IServerWorkingCopy server = getCachedServer(type);
+			if (server != null)
+				return server;
+		} catch (Exception e) { }
+	
+		try {
+			IFile file = null;
+			if (ServerCore.getServerPreferences().isCreateResourcesInWorkspace())
+				file = ServerUtil.getUnusedServerFile(WizardUtil.getServerProject(), type);
+			
+			IServerWorkingCopy server = type.createServer(null, file, (IRuntime)null);
+			elementCache.put(getKey(type), server);
+			return server;
+		} catch (CoreException ce) {
+			throw ce;
+		}
+	}
+
+	/**
+	 * Returns a cached server resource. 
+	 *
+	 * @param factory org.eclipse.wst.server.core.model.IServerFactory
+	 * @return org.eclipse.wst.server.core.model.IServerResource
+	 */
+	public IServerWorkingCopy getCachedServer(IServerType type) {
+		try {
+			IServerWorkingCopy server = (IServerWorkingCopy) elementCache.get(getKey(type));
+			if (server != null)
+				return server;
+		} catch (Exception e) { }
+
+		return null;
+	}
+	
+	/**
+	 * Returns a cached server resource. 
+	 *
+	 * @param factory org.eclipse.wst.server.core.model.IServerFactory
+	 * @return org.eclipse.wst.server.core.model.IServerResource
+	 */
+	public IServerConfigurationWorkingCopy getCachedServerConfiguration(IServerConfigurationType type) {
+		try {
+			IServerConfigurationWorkingCopy wc = (IServerConfigurationWorkingCopy) elementCache.get(getKey(type));
+			if (wc != null)
+				return wc;
+		} catch (Exception e) { }
+
+		return null;
+	}
+
+	/**
+	 * Returns an element's wizard. 
+	 *
+	 * @param parent org.eclipse.jface.wizard.IWizard
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 * @return org.eclipse.jface.wizard.IWizard
+	 */
+	/*public IWizardFragment getCreationTask(IElement element) {
+		try {
+			IWizardFragment task = (IWizardFragment) taskCache.get(element);
+			if (task != null)
+				return task;
+		} catch (Exception e) { }
+	
+		try {
+			IWizardFragment task = ServerUICore.getServerWizardFragment(element.getId());
+			taskCache.put(element, task);
+			return task;
+		} catch (Exception e) { }
+	
+		return null;
+	}*/
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/FixedTableLayout.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/FixedTableLayout.java
new file mode 100644
index 0000000..47dabd5
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/FixedTableLayout.java
@@ -0,0 +1,40 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+
+//import java.util.ArrayList;
+//import java.util.List;
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+/**
+ * 
+ */
+public class FixedTableLayout extends Layout {
+	//private List columns = new ArrayList();
+	
+	/*public void addColumnData(Integer data) {
+		columns.add(data);
+	}*/
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
+	 */
+	protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
+		Table table = (Table) composite;
+		Point result = table.computeSize(wHint, hHint, flushCache);
+		return result;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
+	 */
+	protected void layout(Composite composite, boolean flushCache) {
+		Table table = (Table) composite;
+		TableColumn[] tableColumns = table.getColumns();
+		int width = table.getClientArea().width - 10;
+		
+		tableColumns[0].setWidth(width);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/HostnameComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/HostnameComposite.java
new file mode 100644
index 0000000..84e72f6
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/HostnameComposite.java
@@ -0,0 +1,140 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.List;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.resource.JFaceResources;
+
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.SWTUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.ServerUIPreferences;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+/**
+ * A composite used to select a hostname.
+ */
+public class HostnameComposite extends Composite {
+	private static final String LOCALHOST = "localhost";
+	protected String host;
+	protected IHostnameSelectionListener listener;
+	
+	protected Combo combo;
+	
+	public interface IHostnameSelectionListener {
+		public void hostnameSelected(String host);
+	}
+
+	/**
+	 * Create a new HostComposite.
+	 */
+	public HostnameComposite(Composite parent, IHostnameSelectionListener listener2) {
+		super(parent, SWT.NONE);
+		this.listener = listener2;
+		
+		createControl();
+	}
+
+	protected Label createHeadingLabel(Composite parent, String text, int span) {
+		Label label = createLabel(parent, text, span, true, false);
+		label.setFont(JFaceResources.getBannerFont());
+		return label;
+	}
+
+	protected Label createLabel(Composite parent, String text, int span, boolean alignTop, boolean indent) {
+		Label label = new Label(parent, SWT.WRAP);
+		label.setText(text);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER);
+		if (alignTop)
+			data.verticalAlignment = GridData.BEGINNING;
+		data.horizontalSpan = span;
+		if (indent)
+			data.horizontalIndent = 10;
+		label.setLayoutData(data);
+		return label;
+	}
+	
+	protected Combo createCombo(Composite parent, String[] items, String text2, int span) {
+		Combo combo2 = new Combo(parent, SWT.DROP_DOWN);
+		combo2.setItems(items);
+		combo2.setText(text2);
+		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
+		data.horizontalSpan = span;
+		combo2.setLayoutData(data);
+		return combo2;
+	}
+
+	/**
+	 * Creates the UI of the page.
+	 *
+	 * @param org.eclipse.swt.widgets.Composite parent
+	 */
+	protected void createControl() {
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 3;
+		setLayout(layout);
+		//WorkbenchHelp.setHelp(this, ContextIds.SELECT_CLIENT_WIZARD);
+	
+		createHeadingLabel(this, ServerUIPlugin.getResource("%hostnameTitle"), 3);
+
+		createLabel(this, ServerUIPlugin.getResource("%hostname"), 1, false, true);
+		
+		List hosts = ((ServerUIPreferences)ServerUICore.getPreferences()).getHostnames();
+		String[] s = new String[hosts.size()];
+		hosts.toArray(s);
+		combo = createCombo(this, s, LOCALHOST, 2);
+		combo.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				hostnameChanged(combo.getText());
+			}
+		});
+		combo.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				hostnameChanged(combo.getText());
+			}
+		});
+	
+		Dialog.applyDialogFont(this);
+	}
+
+	protected void hostnameChanged(String newHost) {
+		if (newHost == null)
+			return;
+		
+		if (newHost.equals(host))
+			return;
+
+		host = newHost;
+		listener.hostnameSelected(host);
+	}
+
+	public String getHostname() {
+		return host;
+	}
+
+	public void setHostname(String hostname) {
+		combo.setText(hostname);
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ImportConfigurationWizardPage.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ImportConfigurationWizardPage.java
new file mode 100644
index 0000000..4bbd60e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ImportConfigurationWizardPage.java
@@ -0,0 +1,552 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.wst.server.core.IServerConfiguration;
+import org.eclipse.wst.server.core.IServerConfigurationType;
+import org.eclipse.wst.server.core.IServerConfigurationWorkingCopy;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.internal.ServerPlugin;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ContextIds;
+import org.eclipse.wst.server.ui.internal.EclipseUtil;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.SWTUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.ServerUIPreferences;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.wst.server.ui.internal.viewers.ServerConfigurationTypeComposite;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.help.WorkbenchHelp;
+
+/**
+ * Wizard page to import a configuration.
+ */
+public class ImportConfigurationWizardPage extends WizardPage {
+	protected IServerConfigurationType selectedConfigType;
+	protected IServerConfigurationWorkingCopy configuration;
+	protected Combo serverProject;
+	protected Button create;
+	protected Text name;
+	protected Text filename;
+	protected ServerConfigurationTypeComposite configTypeComposite;
+	private Label description;
+	protected Button browse;
+	private IContainer defaultContainer;
+	
+	protected boolean createServerProject = false;
+
+	private String[] validationErrors = new String[5];
+	private static final int INVALID_NAME = 0;
+	private static final int INVALID_FOLDER = 1;
+	private static final int INVALID_TYPE = 2;
+	private static final int INVALID_FILENAME = 3;
+	private static final int INVALID_IMPORT = 4;
+	
+	protected LoadThread thread;
+	protected boolean threadDone;
+
+	class LoadThread extends Thread {
+		final int DELAY = 800;
+		String filename2;
+		public void run() {
+			boolean b = true;
+			while (b) {
+				try {
+					sleep(DELAY);
+					b = false;
+					thread = null;
+				} catch (InterruptedException ie) { }
+			}
+			try {
+				performLoadConfiguration(filename2);
+				Display.getDefault().asyncExec(new Runnable() {
+					public void run() {
+						validatePage(INVALID_IMPORT);
+					}
+				});
+			} catch (Exception e) {
+				Trace.trace(Trace.SEVERE, "Error importing configuration", e);
+			}
+			threadDone = true;
+		}
+	}
+
+	/**
+	 * ImportConfigurationWizardPage constructor comment.
+	 */
+	public ImportConfigurationWizardPage() {
+		super("import configuration");
+	
+		setTitle(ServerUIPlugin.getResource("%wizImportConfigurationTitle"));
+		setDescription(ServerUIPlugin.getResource("%wizImportConfigurationDescription"));
+		setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_IMPORT_SERVER_CONFIGURATION));
+	}
+	
+	/**
+	 * Creates the UI part of the page. Subclasses must reimplement 
+	 * this method to provide their own graphical page content.
+	 */
+	public void createControl(Composite parent) {
+		initializeDialogUnits(parent);
+	
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 3;
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(4);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(4);
+		layout.marginWidth = convertHorizontalDLUsToPixels(5);
+		layout.marginHeight = convertVerticalDLUsToPixels(5);
+		composite.setLayout(layout);
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = convertHorizontalDLUsToPixels(500);
+		data.heightHint = convertVerticalDLUsToPixels(470);
+		WorkbenchHelp.setHelp(composite, ContextIds.IMPORT_CONFIGURATION_WIZARD);
+	
+		new Label(composite, SWT.NONE).setText(ServerUIPlugin.getResource("%wizNewConfigurationName"));
+	
+		name = new Text(composite, SWT.BORDER);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.horizontalSpan = 2;
+		name.setLayoutData(data);
+		name.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent me) {
+				validateName();
+				validatePage(INVALID_NAME);
+			}
+		});
+		name.addFocusListener(new FocusAdapter() {
+			public void focusGained(FocusEvent e) {
+				 validatePage(INVALID_NAME);
+			}
+		});
+		WorkbenchHelp.setHelp(name, ContextIds.IMPORT_CONFIGURATION_NAME);
+	
+		// choose a server project
+		new Label(composite, SWT.NONE).setText(ServerUIPlugin.getResource("%wizFolder"));
+		serverProject = new Combo(composite, SWT.BORDER);
+		WizardUtil.fillComboWithServerProjectFolders(serverProject);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.horizontalSpan = 2;
+		serverProject.setLayoutData(data);
+		if (defaultContainer != null)
+			serverProject.setText(WizardUtil.getContainerText(defaultContainer));
+		else if (serverProject.getItemCount() == 0)
+			serverProject.setText(ServerPlugin.getResource("%defaultServerProjectName", ""));
+	
+		serverProject.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent me) {
+				createServerProject = false;
+				validateName();
+				validateFolder();
+				validatePage(INVALID_FOLDER);
+			}
+		});
+		serverProject.addFocusListener(new FocusAdapter() {
+			public void focusGained(FocusEvent e) {
+				 validatePage(INVALID_FOLDER);
+			}
+		});
+		WorkbenchHelp.setHelp(serverProject, ContextIds.IMPORT_CONFIGURATION_FOLDER);
+
+		Label label2 = new Label(composite, SWT.NONE);
+		label2.setText(ServerUIPlugin.getResource("%wizImportConfigurationType"));
+		data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+		label2.setLayoutData(data);
+	
+		configTypeComposite = new ServerConfigurationTypeComposite(composite, SWT.NONE, new ServerConfigurationTypeComposite.ServerConfigurationTypeSelectionListener() {
+			public void configurationTypeSelected(IServerConfigurationType type) {
+				handleFactorySelection(type);
+				validateName();
+				validatePage(INVALID_TYPE);
+			}
+		});
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.heightHint = 130;
+		data.horizontalSpan = 2;
+		configTypeComposite.setLayoutData(data);
+		WorkbenchHelp.setHelp(configTypeComposite, ContextIds.IMPORT_CONFIGURATION_FACTORY);
+	
+		Label label = new Label(composite, SWT.NONE);
+		label.setText(ServerUIPlugin.getResource("%wizDescription"));
+		data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+		label.setLayoutData(data);
+	
+		description = new Label(composite, SWT.WRAP);
+		description.setText("");
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.heightHint = 58;
+		data.horizontalSpan = 2;
+		description.setLayoutData(data);
+	
+		label = new Label(composite, SWT.NONE);
+		label.setText(ServerUIPlugin.getResource("%wizImportConfigurationLocation"));
+	
+		filename = new Text(composite, SWT.BORDER);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.widthHint = 300;
+		filename.setLayoutData(data);
+		filename.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent me) {
+				handleFileSelection();
+				validatePage(INVALID_TYPE);
+			}
+		});
+		WorkbenchHelp.setHelp(filename, ContextIds.IMPORT_CONFIGURATION_LOCATION);
+	
+		browse = SWTUtil.createButton(composite, ServerUIPlugin.getResource("%wizBrowse")); 
+		browse.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent se) {
+				if (selectedConfigType == null)
+					return;
+				String[] filter = selectedConfigType.getImportFilterExtensions();
+				if (filter != null) {
+					int size = filter.length;
+					String[] s = new String[size];
+					for (int i = 0; i < size; i++) {
+						if (!filter[i].startsWith("*."))
+							s[i] = "*." + filter[i];
+						else
+							s[i] = filter[i];
+					}
+					FileDialog dialog = new FileDialog(getShell());
+					dialog.setText(ServerUIPlugin.getResource("%wizImportConfigurationFile"));
+					dialog.setFilterPath(filename.getText());
+					dialog.setFilterExtensions(s);
+					String selectedFile = dialog.open();
+					if (selectedFile != null)
+						filename.setText(selectedFile);
+				} else {
+					DirectoryDialog dialog = new DirectoryDialog(getShell());
+					dialog.setMessage(ServerUIPlugin.getResource("%wizImportConfigurationDirectory"));
+					dialog.setFilterPath(filename.getText());
+					String selectedDirectory = dialog.open();
+					if (selectedDirectory != null)
+						filename.setText(selectedDirectory);
+				}
+			}
+		});
+		browse.setEnabled(false);
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		//data.widthHint = 75;
+		data.heightHint = 22;
+		browse.setLayoutData(data);
+		WorkbenchHelp.setHelp(browse, ContextIds.IMPORT_CONFIGURATION_LOCATION_BROWSE);
+	
+		//fillFactoryTree();
+		validationErrors[INVALID_TYPE] = "";
+		validationErrors[INVALID_FILENAME] = "";
+		
+		ServerUIPreferences sp = (ServerUIPreferences) ServerUICore.getPreferences();
+		if (sp.getImportLocation() != null) {
+			filename.setText(sp.getImportLocation());
+			handleFileSelection();
+			validatePage(INVALID_TYPE);
+		}
+	
+		setControl(composite);
+		Dialog.applyDialogFont(composite);
+	}
+	
+	protected void loadConfiguration() {
+		if (thread != null) {
+			try {
+				thread.interrupt();
+				thread.filename2 = filename.getText();
+			} catch (Exception e) { }
+		} else {
+			// try to avoid multiple threads
+			if (!threadDone) {
+				try {
+					Thread.sleep(200);
+				} catch (Exception e) { }
+			}
+			if (validationErrors[INVALID_TYPE] != null || validationErrors[INVALID_FILENAME] != null)
+				return;
+			thread = new LoadThread();
+			thread.filename2 = filename.getText();
+			getContainer().updateButtons();
+			threadDone = false;
+			thread.start();
+		}
+	}
+	
+	/**
+	 * Handle the server factory selection.
+	 */
+	protected void handleFactorySelection(IServerConfigurationType type) {
+		validationErrors[INVALID_IMPORT] = null;
+		configuration = null;
+		selectedConfigType = type;
+	
+		validationErrors[INVALID_TYPE] = null;
+		
+		if (selectedConfigType == null) {
+			browse.setEnabled(false);
+			description.setText("");
+			return;
+		}
+	
+		try {
+			String text = selectedConfigType.getDescription();
+			if (text == null)
+				text = "";
+			description.setText(text);
+			browse.setEnabled(true);
+			
+			loadConfiguration();
+		} catch (Exception e) {
+			validationErrors[INVALID_TYPE] = ServerUIPlugin.getResource("%wizErrorImport");
+			Trace.trace(Trace.SEVERE, "Could not import from " + filename.getText(), e);
+		}
+	}
+	
+	protected void handleFileSelection() {
+		validationErrors[INVALID_IMPORT] = null;
+		String text = filename.getText();
+		if (text == null || text.length() == 0)
+			validationErrors[INVALID_FILENAME] = "";
+		else {
+			validationErrors[INVALID_FILENAME] = null;
+			loadConfiguration();
+		}
+	}
+	
+	protected void performLoadConfiguration(String filename2) {
+		try {
+			try {
+				//configuration = selectedFactory.load(file.toURL(), null, new NullProgressMonitor());
+				configuration = selectedConfigType.importFromPath(null, null, new Path(filename2), new NullProgressMonitor());
+				if (configuration == null)
+					validationErrors[INVALID_IMPORT] = ServerUIPlugin.getResource("%wizErrorImport");
+				else
+					validationErrors[INVALID_IMPORT] = null;
+			} catch (CoreException ce) {
+				IStatus status = ce.getStatus();
+				if (status != null && status.getMessage() != null && status.getMessage().length() > 1)
+					validationErrors[INVALID_IMPORT] = ce.getStatus().getMessage();
+				else
+					validationErrors[INVALID_IMPORT] = ServerUIPlugin.getResource("%wizErrorImport");
+			}
+		} catch (Exception e) {
+			validationErrors[INVALID_IMPORT] = ServerUIPlugin.getResource("%wizErrorImport");
+			Trace.trace(Trace.SEVERE, "Could not import from " + filename, e);
+		}
+	}
+	
+	/**
+	 * Return true if this page is complete.
+	 * @return boolean
+	 */
+	public boolean isPageComplete() {
+		// check for validation first
+		for (int i = 0; i < validationErrors.length; i++) {
+			if (validationErrors[i] != null)
+				return false;
+		}
+	
+		if (configuration == null)
+			return false;
+			
+		if (thread != null)
+			return false;
+	
+		// otherwise, defer to superclass
+		return super.isPageComplete();
+	}
+	
+	/**
+	 * Finish the wizard by saving the configuration into
+	 * the selected folder.
+	 * @return boolean
+	 */
+	public boolean performFinish() {
+		if (configuration == null)
+			return false;
+			
+		ServerUIPreferences sp = (ServerUIPreferences) ServerUICore.getPreferences();
+		sp.setImportLocation(filename.getText());
+
+		// prompt for server project creation
+		final String projectName = serverProject.getText();
+		IContainer container2 = WizardUtil.findContainer(projectName);
+		if ((container2 == null || !container2.exists()) && !createServerProject) {
+			IStatus status = ResourcesPlugin.getWorkspace().validateName(projectName, IResource.PROJECT);
+			if (status.isOK()) {
+				if (ServerCore.getServerProjects().isEmpty() || WizardUtil.promptForServerProjectCreation(getShell(), projectName))
+					createServerProject = true;
+				else
+					return false;
+			} else
+				return false;
+		}
+	
+		try {
+			final String theName = name.getText();
+			IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+				public void run(IProgressMonitor monitor) throws CoreException {
+					saveConfiguration(configuration, theName, projectName, new NullProgressMonitor());
+				}
+			};
+			
+			getWizard().getContainer().run(true, true, new WorkspaceRunnableAdapter(runnable));
+
+			return true;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error saving imported configuration", e);
+			return false;
+		}
+	}
+	
+	/**
+	 * Save the element to the given file name.
+	 * @param element org.eclipse.wst.server.core.model.IServerResource
+	 * @param name java.lang.String
+	 * @param org.eclipse.core.runtime.IProgressMonitor monitor
+	 */
+	protected void saveConfiguration(IServerConfigurationWorkingCopy config, String theName, String projectName, IProgressMonitor monitor) throws CoreException {
+		// save the element
+		try {
+			if (createServerProject) {
+				if (!EclipseUtil.createNewServerProject(getShell(), projectName, null, monitor).isOK())
+					throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, "Could not create server project", null));
+			}
+			IContainer container = WizardUtil.findContainer(projectName);
+			if (container == null)
+				throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, "Could not find container", null));
+
+			config.setName(theName);
+			config.save(monitor);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error saving created element", e);
+			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, "Could not create server project", null));
+		}
+	}
+	
+	/**
+	 * Sets the default container.
+	 * @param org.eclipse.core.resources.IContainer
+	 */
+	public void setDefaultContainer(IContainer container) {
+		defaultContainer = container;
+	}
+	
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+	
+		if (visible) {
+			// force the focus to initially validate the fields
+			validateName();
+			validateFolder();
+			handleFactorySelection(null);
+			validatePage(INVALID_NAME);
+	
+			name.forceFocus();
+		}
+	}
+	
+	/**
+	 * Validates the folder.
+	 */
+	protected void validateFolder() {
+		String text = serverProject.getText();
+		if (text == null || text.length() == 0) {
+			validationErrors[INVALID_FOLDER] = "";
+			return;
+		}
+	
+		validationErrors[INVALID_FOLDER] = WizardUtil.validateContainer(text);
+	}
+	
+	/**
+	 * Validates the name.
+	 */
+	protected void validateName() {
+		String text = name.getText();
+		if (text == null || text.length() == 0) {
+			validationErrors[INVALID_NAME] = "";
+			return;
+		}
+	
+		IStatus status = ResourcesPlugin.getWorkspace().validateName(text, IResource.FILE);
+		if (status.isOK())
+			status = ResourcesPlugin.getWorkspace().validateName(text, IResource.FOLDER);
+		
+		if (!status.isOK())
+			validationErrors[INVALID_NAME] = status.getMessage();
+		else {
+			// check if file exists
+			String fileName = text;
+			if (selectedConfigType != null) {
+				String ext = IServerConfiguration.FILE_EXTENSION;
+				if (ext != null && !fileName.endsWith("." + ext))
+					fileName += "." + ext;
+			}
+		
+			IContainer container = WizardUtil.findContainer(serverProject.getText());
+			if (container != null && container.getLocation().append(fileName).toFile().exists()) {
+				validationErrors[INVALID_NAME] = ServerUIPlugin.getResource("%wizErrorResourceAlreadyExists");
+			} else
+				validationErrors[INVALID_NAME] = null;
+		}
+	}
+	
+	/**
+	 * Display the correct error message and enable/disable
+	 * the Finish or Next button.
+	 * @param x the current control (error message gets precedence)
+	 */
+	protected void validatePage(int x) {
+		if (x >= 0 && validationErrors[x] != null && validationErrors[x].length() > 0) {
+			setErrorMessage(validationErrors[x]);
+			getContainer().updateButtons();
+			return;
+		}
+		int size = validationErrors.length;
+		for (int i = 0; i < size; i++) {
+			if (validationErrors[i] != null && validationErrors[i].length() > 0) {
+				setErrorMessage(validationErrors[i]);
+				getContainer().updateButtons();
+				return;
+			}
+		}
+		setErrorMessage(null);
+		getContainer().updateButtons();
+	}
+}
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..ed29f18
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ModifyModulesComposite.java
@@ -0,0 +1,403 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+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.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ServerUtil;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ContextIds;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.SWTUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+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.Label;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.help.WorkbenchHelp;
+
+/**
+ * A wizard page used to add and remove modules.
+ */
+public class ModifyModulesComposite extends Composite {
+	protected static final ILabelProvider slp = ServerUICore.getLabelProvider();
+	
+	protected IWizardHandle wizard;
+	
+	protected IServer server;
+	protected boolean disabled = false;
+
+	protected Map childModuleMap = new HashMap();
+	protected Map parentTreeItemMap = new HashMap();
+
+	protected List originalModules = new ArrayList();
+	protected List modules = new ArrayList();
+	protected List deployed = new ArrayList();
+
+	protected Tree availableTree;
+	protected Tree deployedTree;
+	
+	protected Button add, addAll;
+	protected Button remove, removeAll;
+
+	/**
+	 * Create a new ModifyModulesWizardPage.
+	 *
+	 */
+	public ModifyModulesComposite(Composite parent, IWizardHandle wizard) {
+		super(parent, SWT.NONE);
+		this.wizard = wizard;
+		
+		wizard.setTitle(ServerUIPlugin.getResource("%wizModuleTitle"));
+		wizard.setDescription(ServerUIPlugin.getResource("%wizModuleDescription"));
+		wizard.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_SELECT_SERVER));
+		
+		createControl();
+	}
+	
+	public void setServer(IServer server) {
+		if (server == this.server)
+			return;
+
+		this.server = server;
+		originalModules = new ArrayList();
+		deployed = new ArrayList();
+		modules = new ArrayList();
+		
+		childModuleMap = new HashMap();
+		
+		if (server == null)
+			return;
+
+		// get currently deployed modules
+		IModule[] currentModules = server.getModules();
+		if (currentModules != null) {
+			int size = currentModules.length;
+			for (int i = 0; i < size; i++) {
+				deployed.add(currentModules[i]);
+				originalModules.add(currentModules[i]);
+			}
+		}
+
+		// get remaining modules
+		Iterator iterator = ServerUtil.getModules().iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			if (!deployed.contains(module)) {
+				IStatus status = server.canModifyModules(new IModule[] { module }, null);
+				if (status != null && status.isOK())
+					modules.add(module);
+			}
+		}
+
+		// build child map
+		iterator = deployed.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			try {
+				List children = server.getChildModules(module);
+				childModuleMap.put(module, children);
+			} catch (Exception e) { }
+		}
+
+		iterator = modules.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			try {
+				List children = server.getChildModules(module);
+				childModuleMap.put(module, children);
+			} catch (Exception e) { }
+		}
+		
+		if (server.isAWorkingCopyDirty()) {
+			wizard.setMessage(ServerUIPlugin.getResource("%errorCloseEditor", server.getName()), IMessageProvider.ERROR);
+			disabled = true;
+		}
+		
+		if (availableTree != null) {
+			parentTreeItemMap = new HashMap();
+			fillTree(availableTree, modules);
+			fillTree(deployedTree, deployed);
+			setEnablement();
+		}
+	}
+
+	/**
+	 * Creates the UI of the page.
+	 *
+	 * @param org.eclipse.swt.widgets.Composite parent
+	 */
+	protected void createControl() {
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 3;
+		setLayout(layout);
+		setFont(getParent().getFont());
+		WorkbenchHelp.setHelp(this, ContextIds.MODIFY_MODULES_COMPOSITE);
+
+		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(ServerUIPlugin.getResource("%wizModuleMessage"));
+
+		label = new Label(this, SWT.NONE);
+		label.setText(ServerUIPlugin.getResource("%wizModuleAvailableList"));
+		
+		label = new Label(this, SWT.NONE);
+		label.setText("");
+		
+		label = new Label(this, SWT.NONE);
+		label.setText(ServerUIPlugin.getResource("%wizModuleDeployedList"));
+
+		availableTree = new Tree(this, SWT.BORDER);
+		data = new GridData(GridData.FILL_BOTH);
+		data.heightHint = 200;
+		data.widthHint = 150;
+		availableTree.setLayoutData(data);
+		availableTree.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				setEnablement();
+			}
+		});
+
+		// 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(ServerUIPlugin.getResource("%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(ServerUIPlugin.getResource("%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(ServerUIPlugin.getResource("%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(ServerUIPlugin.getResource("%wizModuleRemoveAll"));
+		removeAll.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		removeAll.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				remove(true);
+			}
+		});
+		
+		deployedTree = new Tree(this, SWT.BORDER);
+		data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = 150;
+		deployedTree.setLayoutData(data);
+		deployedTree.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				setEnablement();
+			}
+		});
+		
+		parentTreeItemMap = new HashMap();
+		fillTree(availableTree, modules);
+		fillTree(deployedTree, deployed);
+		
+		setEnablement();
+		
+		availableTree.setFocus();
+		
+		Dialog.applyDialogFont(this);
+	}
+	
+	protected void setEnablement() {
+		if (disabled) {
+			add.setEnabled(false);
+			addAll.setEnabled(false);
+			remove.setEnabled(false);
+			removeAll.setEnabled(false);
+			return;
+		}
+
+		boolean enabled = false;
+		if (availableTree.getItemCount() > 0) {
+			try {
+				TreeItem item = availableTree.getSelection()[0];
+				item = (TreeItem) parentTreeItemMap.get(item);
+				IModule module = (IModule) item.getData();
+				if (modules.contains(module))
+					enabled = true;
+			} catch (Exception e) { }
+		}
+		add.setEnabled(enabled);
+		addAll.setEnabled(availableTree.getItemCount() > 0);
+		
+		enabled = false;
+		if (deployedTree.getItemCount() > 0) {
+			try {
+				TreeItem item = deployedTree.getSelection()[0];
+				item = (TreeItem) parentTreeItemMap.get(item);
+				IModule module = (IModule) item.getData();
+				if (deployed.contains(module))
+					enabled = true;
+			} catch (Exception e) { }
+		}
+		remove.setEnabled(enabled);
+		removeAll.setEnabled(deployedTree.getItemCount() > 0);
+	}
+
+	protected void addChildren(TreeItem item, IModule module) {
+		try {
+			List children = (List) childModuleMap.get(module);
+			Iterator iterator = children.iterator();
+			while (iterator.hasNext()) {
+				IModule child = (IModule) iterator.next();
+				TreeItem childItem = new TreeItem(item, SWT.NONE);
+				childItem.setText(slp.getText(child));
+				childItem.setImage(slp.getImage(child));
+				childItem.setData(child);
+				parentTreeItemMap.put(childItem, item);
+				addChildren(childItem, child);
+			}
+		} catch (Exception e) { }
+	}
+
+	protected void fillTree(Tree tree, List modules2) {
+		tree.removeAll();
+
+		Iterator iterator = modules2.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			TreeItem item = new TreeItem(tree, SWT.NONE);
+			item.setText(slp.getText(module));
+			item.setImage(slp.getImage(module));
+			item.setData(module);
+			parentTreeItemMap.put(item, item);
+			addChildren(item, module);
+		}
+	}
+
+	protected void add(boolean all) {
+		if (all)
+			moveAll(availableTree.getItems(), true);
+		else
+			moveAll(availableTree.getSelection(), true);
+	}
+
+	protected void remove(boolean all) {
+		if (all)
+			moveAll(deployedTree.getItems(), false);
+		else
+			moveAll(deployedTree.getSelection(), false);
+	}
+
+	protected void moveAll(TreeItem[] items, boolean add2) {
+		int size = items.length;
+		List list = new ArrayList();
+		for (int i = 0; i < size; i++) {
+			TreeItem item = (TreeItem) parentTreeItemMap.get(items[i]);
+			IModule module = (IModule) item.getData();
+			
+			if (!list.contains(module))
+				list.add(module);
+		}
+
+		Iterator iterator = list.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			if (add2) {
+				modules.remove(module);
+				deployed.add(module);
+			} else {
+				modules.add(module);
+				deployed.remove(module);
+			}
+		}
+
+		parentTreeItemMap = new HashMap();
+		fillTree(availableTree, modules);
+		fillTree(deployedTree, deployed);
+
+		setEnablement();
+	}
+
+	/**
+	 * Return true if this page is complete.
+	 * @return boolean
+	 */
+	public boolean isPageComplete() {
+		return (!disabled);
+	}
+	
+	public List getModulesToRemove() {
+		List list = new ArrayList();
+		Iterator iterator = originalModules.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			if (!deployed.contains(module))
+				list.add(module);
+		}
+		return list;
+	}
+	
+	public List getModulesToAdd() {
+		List list = new ArrayList();
+		Iterator iterator = deployed.iterator();
+		while (iterator.hasNext()) {
+			IModule module = (IModule) iterator.next();
+			if (!originalModules.contains(module))
+				list.add(module);
+		}
+		return list;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewDetectServerComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewDetectServerComposite.java
new file mode 100644
index 0000000..efcdc0d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewDetectServerComposite.java
@@ -0,0 +1,219 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerWorkingCopy;
+import org.eclipse.wst.server.ui.internal.SWTUtil;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+/**
+ * A wizard page used to select a server client.
+ */
+public class NewDetectServerComposite extends Composite {
+	protected String host;
+	
+	protected IServerWorkingCopy server;
+	protected IServerSelectionListener listener;
+	
+	protected List servers = new ArrayList();
+	
+	protected Button detect;
+	protected Table table;
+	protected TableViewer tableViewer;
+	protected Label hostLabel;
+
+	public interface IServerSelectionListener {
+		public void serverSelected(IServer server);
+	}
+	
+	public class ServerContentProvider implements IStructuredContentProvider {
+		public void dispose() { }
+
+		public Object[] getElements(Object inputElement) {
+			return servers.toArray();
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
+	}
+	
+	public class ServerLabelProvider implements ITableLabelProvider {
+		public void addListener(ILabelProviderListener listener2) { }
+
+		public void dispose() { }
+
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+
+		public String getColumnText(Object element, int columnIndex) {
+			IServer server2 = (IServer) element;
+			if (columnIndex == 0)
+				return server2.getName();
+			else if (columnIndex == 0)
+				return "n/a";
+			return null;
+		}
+
+		public boolean isLabelProperty(Object element, String property) {
+			return false;
+		}
+
+		public void removeListener(ILabelProviderListener listener2) { }
+	}
+
+	/**
+	 * Create a new NewDetectServerComposite.
+	 */
+	public NewDetectServerComposite(Composite parent, IServerSelectionListener listener2) {
+		super(parent, SWT.NONE);
+		this.listener = listener2;
+
+		createControl();
+	}
+	
+	protected Label createHeadingLabel(Composite parent, String text, int span) {
+		Label label = createLabel(parent, text, span, true, false);
+		label.setFont(JFaceResources.getBannerFont());
+		return label;
+	}
+	
+	protected Label createLabel(Composite parent, String text, int span, boolean alignTop, boolean indent) {
+		Label label = new Label(parent, SWT.WRAP);
+		label.setText(text);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER);
+		if (alignTop)
+			data.verticalAlignment = GridData.BEGINNING;
+		data.horizontalSpan = span;
+		if (indent)
+			data.horizontalIndent = 10;
+		label.setLayoutData(data);
+		return label;
+	}
+
+	/**
+	 * Creates the UI of the page.
+	 *
+	 * @param org.eclipse.swt.widgets.Composite parent
+	 */
+	protected void createControl() {
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 2;
+		setLayout(layout);
+		//WorkbenchHelp.setHelp(this, ContextIds.SELECT_CLIENT_WIZARD);
+	
+		createHeadingLabel(this, "Select the Server", 2);
+		
+		table = new Table(this, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE);
+		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
+		data.heightHint = 60;
+		data.widthHint = 50;
+		data.horizontalSpan = 2;
+		data.horizontalIndent = 10;
+		table.setLayoutData(data);
+		
+		TableLayout tableLayout = new TableLayout();
+		table.setHeaderVisible(true);
+
+		tableLayout.addColumnData(new ColumnWeightData(50, 100, true));
+		TableColumn col = new TableColumn(table, SWT.NONE);
+		col.setText("Server");
+		
+		tableLayout.addColumnData(new ColumnWeightData(40, 80, true));
+		TableColumn col2 = new TableColumn(table, SWT.NONE);
+		col2.setText("Status");
+		
+		table.setLayout(tableLayout);
+		
+		tableViewer = new TableViewer(table);
+		tableViewer.setContentProvider(new ServerContentProvider());
+		tableViewer.setLabelProvider(new ServerLabelProvider());
+		tableViewer.setColumnProperties(new String[] {"name", "status"});
+		tableViewer.setInput("root");
+		
+		String date = "<now>";
+		hostLabel = createLabel(this, "Last detected servers on " + host + " at " + date + ":", 1, false, true);
+		
+		detect = SWTUtil.createButton(this, "Refresh");
+		detect.setEnabled(false);
+		data = (GridData) detect.getLayoutData();
+		data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_END;
+
+		// listeners
+		detect.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				
+			}
+		});
+
+		tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				IStructuredSelection sel = (IStructuredSelection) event.getSelection();
+				Object obj = sel.getFirstElement();
+				IServerWorkingCopy newServer = null;
+				if (obj instanceof IServerWorkingCopy)
+					newServer = (IServerWorkingCopy) obj;
+				
+				if ((newServer == null && server != null) || (newServer != null && !newServer.equals(server))) {
+					server = newServer;
+					listener.serverSelected(server);
+				}
+			}
+		});
+		
+		setHost(null);
+	
+		Dialog.applyDialogFont(this);
+	}
+
+	public String getHost() {
+		return host;
+	}
+
+	public void setHost(String host) {
+		this.host = host;
+		servers = new ArrayList();
+		tableViewer.refresh();
+		if (host != null) {
+			hostLabel.setText("Detected servers on " + host + ":");
+			detect.setEnabled(true);
+			table.setEnabled(true);
+		} else {
+			hostLabel.setText("No host selected");
+			detect.setEnabled(false);
+			table.setEnabled(false);
+		}
+	}
+
+	public IServerWorkingCopy getServer() {
+		return server;
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewManualServerComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewManualServerComposite.java
new file mode 100644
index 0000000..7205955
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewManualServerComposite.java
@@ -0,0 +1,272 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.lang.reflect.InvocationTargetException;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.util.ProgressUtil;
+import org.eclipse.wst.server.core.util.SocketUtil;
+import org.eclipse.wst.server.ui.internal.ContextIds;
+import org.eclipse.wst.server.ui.internal.SWTUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.wst.server.ui.internal.viewers.ServerTypeComposite;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.help.WorkbenchHelp;
+
+/**
+ * Wizard page used to create a server and configuration at the same time.
+ */
+public class NewManualServerComposite extends Composite {
+	public interface ServerSelectionListener {
+		public void serverSelected(IServer server);
+	}
+
+	public interface IWizardHandle2 {
+		public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) throws InterruptedException, InvocationTargetException;
+		public void update();
+		public void setMessage(String newMessage, int newType);
+	}
+	protected IWizardHandle2 wizard;
+
+	//private IContainer defaultContainer;
+	//private String defaultServerTypeId;
+	private ServerTypeComposite serverTypeComposite;
+
+	//protected IRuntimeWorkingCopy runtime;
+	protected IRuntime runtime;
+	protected IServerWorkingCopy server;
+	protected ServerSelectionListener listener;
+	
+	protected String host;
+
+	protected ElementCreationCache cache = new ElementCreationCache();
+
+	/**
+	 * Creates a new server and server configuration.  If the initial
+	 * resource selection contains exactly one container resource then it will be
+	 * used as the default container resource.
+	 *
+	 * @param org.eclipse.jface.wizard.IWizard parent
+	 */
+	public NewManualServerComposite(Composite parent, IWizardHandle2 wizard, ServerSelectionListener listener) {
+		super(parent, SWT.NONE);
+		this.wizard = wizard;
+		this.listener = listener;
+
+		createControl();
+		wizard.setMessage("", IMessageProvider.ERROR);
+	}
+
+	/**
+	 * Returns this page's initial visual components.
+	 *
+	 * @param parent a <code>Composite</code> that is to be used as the parent of this
+	 *     page's collection of visual components
+	 */
+	protected void createControl() {
+		// top level group
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		setLayout(layout);
+
+		this.setFont(getParent().getFont());
+		WorkbenchHelp.setHelp(this, ContextIds.NEW_SERVER_WIZARD);
+		
+		serverTypeComposite = new ServerTypeComposite(this, SWT.NONE, new ServerTypeComposite.ServerTypeSelectionListener() {
+			public void serverTypeSelected(IServerType type) {
+				handleTypeSelection(type);
+				//WizardUtil.defaultSelect(parent, CreateServerWizardPage.this);
+			}
+		});
+		serverTypeComposite.setIncludeTestEnvironments(false);
+		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
+		data.horizontalSpan = 2;
+		serverTypeComposite.setLayoutData(data);
+		WorkbenchHelp.setHelp(serverTypeComposite, ContextIds.NEW_SERVER_INSTANCE_FACTORY);
+		
+		Dialog.applyDialogFont(this);
+	}
+
+	public void setHost(String host) {
+		this.host = host;
+		if (serverTypeComposite == null)
+			return;
+		if (host == null) {
+			serverTypeComposite.setHost(true);
+		} else if (SocketUtil.isLocalhost(host))
+			serverTypeComposite.setHost(true);
+		else
+			serverTypeComposite.setHost(false);
+		if (server != null) {
+			server.setHostname(host);
+			ServerUtil.setServerDefaultName(server);
+		}
+	}
+	
+	/**
+	 * Return the current editable element.
+	 * @return org.eclipse.wst.server.core.model.IServer
+	 */
+	protected void loadServerImpl(final IServerType type) {
+		runtime = null;
+		server = null;
+		
+		if (type == null)
+			return;
+	
+		server = cache.getCachedServer(type);
+		if (server != null) {
+			server.setHostname(host);
+			ServerUtil.setServerDefaultName(server);
+			runtime = server.getRuntime();
+			return;
+		}
+	
+		final CoreException[] ce = new CoreException[1];
+
+		IRunnableWithProgress runnable = new IRunnableWithProgress() {
+			public void run(IProgressMonitor monitor) {
+				try {
+					monitor = ProgressUtil.getMonitorFor(monitor);
+					int ticks = 200;
+					monitor.beginTask(ServerUIPlugin.getResource("%loadingTask", type.getName()), ticks);
+	
+					server = cache.getServer(type, ProgressUtil.getSubMonitorFor(monitor, 200));
+					if (server != null) {
+						server.setHostname(host);
+						ServerUtil.setServerDefaultName(server);
+					
+						if (type.hasRuntime() && server.getRuntime() == null) {
+							// look for existing runtime
+							IServerType serverType = server.getServerType();
+							IRuntimeType runtimeType = serverType.getRuntimeType();
+							runtime = getRuntime(runtimeType, serverType);
+							if (runtime == null) {
+								// create runtime
+								try {
+									IRuntimeWorkingCopy runtimeWC = runtimeType.createRuntime(null);
+									runtimeWC.setName(server.getName());
+									runtime = runtimeWC;
+								} catch (Exception e) {
+									Trace.trace(Trace.SEVERE, "Couldn't create runtime", e);
+								}
+							}
+							server.setRuntime(runtime);
+						}
+					}
+				} catch (CoreException cex) {
+					ce[0] = cex;
+				} catch (Throwable t) {
+					Trace.trace(Trace.SEVERE, "Error creating element", t);
+				} finally {
+					monitor.done();
+				}
+			}
+		};
+		try {
+			wizard.run(true, false, runnable);
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error with runnable", e);
+		}
+	
+		if (ce[0] != null)
+			wizard.setMessage(ce[0].getLocalizedMessage(), IMessageProvider.ERROR);
+		else if (server == null)
+			wizard.setMessage(ServerUIPlugin.getResource("%wizErrorServerCreationError"), IMessageProvider.ERROR);
+	}
+
+	/**
+	 * Look for test environment runtime first. Otherwise, pick any runtime.
+	 * 
+	 * @param runtimeType
+	 * @param serverType
+	 * @return
+	 */
+	protected IRuntime getRuntime(IRuntimeType runtimeType, IServerType serverType) {
+		List list = ServerCore.getResourceManager().getRuntimes(runtimeType);
+		if (list.isEmpty())
+			return null;
+		Iterator iterator = list.iterator();
+		while (iterator.hasNext()) {
+			IRuntime runtime2 = (IRuntime) iterator.next();
+			if (runtime2.isTestEnvironment())
+				return runtime2;
+		}
+		return (IRuntime) list.get(0);
+	}
+
+	/**
+	 * Handle the server type selection.
+	 */
+	protected void handleTypeSelection(IServerType type) {
+		if (type == null) {
+			wizard.setMessage("", IMessageProvider.ERROR);
+		} else {
+			wizard.setMessage(null, IMessageProvider.NONE);
+			loadServerImpl(type);
+		}
+		listener.serverSelected(server);
+		wizard.update();
+	}
+
+	/**
+	 * Sets the default container.
+	 * @param org.eclipse.core.resources.IContainer
+	 */
+	/*public void setDefaultContainer(IContainer container) {
+		defaultContainer = container;
+	}*/
+	
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+	
+		if (visible) {
+			/*if (defaultServerFactory != null) {
+				tree.setSelection(new TreeItem[] { defaultServerFactory });
+				tree.showItem(tree.getItems()[0]);
+			}*/
+			// force the focus to initially validate the fields
+			handleTypeSelection(null);
+		}
+		
+		Control[] c = getChildren();
+		if (c != null) {
+			int size = c.length;
+			for (int i = 0; i < size; i++)
+				if (c[i] != null)
+					c[i].setVisible(visible);
+		}
+	}
+	
+	public IRuntime getRuntime() {
+		return runtime;
+	}
+	
+	public IServerWorkingCopy getServer() {
+		return server;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewRuntimeComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewRuntimeComposite.java
new file mode 100644
index 0000000..e0fdfbc
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewRuntimeComposite.java
@@ -0,0 +1,122 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.SWTUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.viewers.RuntimeTypeComposite;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Tree;
+
+/**
+ * 
+ */
+public class NewRuntimeComposite extends Composite {
+	protected Tree tree;
+	protected TreeViewer treeViewer;
+
+	protected IRuntimeWorkingCopy runtime;
+	protected Map runtimeMap = new HashMap();
+	
+	protected ITaskModel taskModel;
+	protected IWizardHandle wizard;
+	
+	protected String type;
+	protected String version;
+	protected String runtimeTypeId;
+
+	public NewRuntimeComposite(Composite parent, IWizardHandle wizard, ITaskModel tm, String type, String version, String runtimeTypeId) {
+		super(parent, SWT.NONE);
+		
+		this.wizard = wizard;
+		this.taskModel = tm;
+		this.type = type;
+		this.version = version;
+		this.runtimeTypeId = runtimeTypeId;
+		
+		createControl();
+		
+		wizard.setTitle(ServerUIPlugin.getResource("%wizNewRuntimeTitle"));
+		wizard.setDescription(ServerUIPlugin.getResource("%wizNewRuntimeDescription"));
+		wizard.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_NEW_RUNTIME));
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createControl() {
+		//initializeDialogUnits(parent);
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 1;
+		setLayout(layout);
+		
+		RuntimeTypeComposite comp = new RuntimeTypeComposite(this, SWT.NONE, true, new RuntimeTypeComposite.RuntimeTypeSelectionListener() {
+			public void runtimeTypeSelected(IRuntimeType runtimeType) {
+				handleSelection(runtimeType);
+			}
+		}, type, version, runtimeTypeId);
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.heightHint = 200;
+		comp.setLayoutData(data);
+	}
+
+	protected void handleSelection(IRuntimeType runtimeType) {
+		if (runtimeType == null)
+			runtime = null;
+		else {
+			try {
+				runtime = null;
+				runtime = (IRuntimeWorkingCopy) runtimeMap.get(runtimeType);
+			} catch (Exception e) { }
+			if (runtime == null) {
+				try {
+					runtime = runtimeType.createRuntime(null);
+					ServerUtil.setRuntimeDefaultName(runtime);
+					if (runtime != null)
+						runtimeMap.put(runtimeType, runtime);
+				} catch (Exception e) { }
+			}
+		}
+
+		taskModel.putObject(ITaskModel.TASK_RUNTIME, runtime);
+		wizard.update();
+	}
+
+	public IRuntimeWorkingCopy getRuntime() {
+		return runtime;
+	}
+	
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		
+		Control[] c = getChildren();
+		if (c != null) {
+			int size = c.length;
+			for (int i = 0; i < size; i++)
+				if (c[i] != null)
+					c[i].setVisible(visible);
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewServerComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewServerComposite.java
new file mode 100644
index 0000000..b7937f3
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/NewServerComposite.java
@@ -0,0 +1,403 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.resource.JFaceResources;
+
+import org.eclipse.wst.server.core.IRuntime;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.core.model.IModule;
+import org.eclipse.wst.server.ui.internal.*;
+import org.eclipse.wst.server.ui.internal.viewers.ServerComposite;
+import org.eclipse.wst.server.ui.internal.wizard.fragment.NewServerWizardFragment;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.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.swt.widgets.Text;
+import org.eclipse.ui.help.WorkbenchHelp;
+
+/**
+ * A wizard page used to select a server client.
+ */
+public class NewServerComposite extends Composite {
+	protected IWizardHandle wizard;
+	protected ITaskModel taskModel;
+	protected IModule module;
+	protected String launchMode;
+	
+	protected static final byte MODE_EXISTING = 0;
+	protected static final byte MODE_DETECT = 1;
+	protected static final byte MODE_MANUAL= 2;
+	protected byte mode;
+
+	protected Composite detectComp2;
+	protected NewDetectServerComposite detectComp;
+	protected HostnameComposite detectHostComp;
+	protected Composite manualComp2;
+	protected NewManualServerComposite manualComp;
+	protected HostnameComposite manualHostComp;
+	protected ServerComposite existingComp;
+	
+	protected Composite stack;
+	protected StackLayout stackLayout; 
+	
+	protected String lastHostname;
+	
+	protected Button pref;
+	protected boolean preferred;
+
+	/**
+	 * Create a new NewServerComposite.
+	 */
+	public NewServerComposite(Composite parent, IWizardHandle wizard, IModule module, String launchMode) {
+		super(parent, SWT.NONE);
+		this.wizard = wizard;
+		this.module = module;
+		this.launchMode = launchMode;
+	
+		wizard.setTitle(ServerUIPlugin.getResource("%wizNewServerTitle"));
+		wizard.setDescription(ServerUIPlugin.getResource("%wizNewServerDescription"));
+		wizard.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_NEW_SERVER));
+		
+		createControl();
+	}
+
+	public NewServerComposite(Composite parent, IWizardHandle wizard) {
+		this(parent, wizard, null, null);
+	}
+	
+	protected Label createHeadingLabel(Composite parent, String text, int span) {
+		Label label = createLabel(parent, text, span);
+		label.setFont(JFaceResources.getBannerFont());
+		return label;
+	}
+	
+	protected Label createLabel(Composite parent, String text, int span) {
+		Label label = new Label(parent, SWT.WRAP);
+		label.setText(text);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
+		data.horizontalSpan = span;
+		label.setLayoutData(data);
+		return label;
+	}
+	
+	protected Label createLabel(Composite parent, String text) {
+		return createLabel(parent, text, 1);
+	}
+	
+	protected Button createRadioButton(Composite parent, String text, int span) {
+		Button button = new Button(parent, SWT.RADIO);
+		button.setText(text);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
+		data.horizontalSpan = span;
+		data.horizontalIndent = 10;
+		button.setLayoutData(data);
+		return button;
+	}
+	
+	protected Text createText(Composite parent, String text2, int span) {
+		Text text = new Text(parent, SWT.NONE);
+		text.setText(text2);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
+		data.horizontalSpan = span;
+		text.setLayoutData(data);
+		return text;
+	}
+
+	/**
+	 * Creates the UI of the page.
+	 *
+	 * @param org.eclipse.swt.widgets.Composite parent
+	 */
+	protected void createControl() {
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 1;
+		setLayout(layout);
+		//WorkbenchHelp.setHelp(this, ContextIds.SELECT_CLIENT_WIZARD);
+	
+		createHeadingLabel(this, "How do you want to select the server?", 1);
+		
+		Button existing = null;
+		if (module != null) {
+			final Button predefined = createRadioButton(this, "Choose an e&xisting server", 1);
+			predefined.addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					if (predefined.getSelection())
+						toggleMode(MODE_EXISTING);
+				}
+			});
+			existing = predefined;
+		}
+		
+		
+		final Button auto = createRadioButton(this, "&Automatically detect servers", 1);
+		auto.setEnabled(false);
+		auto.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				if (auto.getSelection())
+					toggleMode(MODE_DETECT);
+			}
+		});
+	
+		final Button manual = createRadioButton(this, "&Manually define a server", 1);
+		manual.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				if (manual.getSelection())
+					toggleMode(MODE_MANUAL);
+			}
+		});
+		
+		stack = new Composite(this, SWT.NONE);
+		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING);
+		stack.setLayoutData(data);
+		stackLayout = new StackLayout();
+		stackLayout.marginHeight = 0;
+		stackLayout.marginWidth = 0;
+		stack.setLayout(stackLayout);
+		
+		if (module != null)
+			createExistingComposite(stack);
+		createAutoComposite(stack);
+		createManualComposite(stack);
+	
+		if (existingComp != null) {
+			mode = MODE_EXISTING;
+			stackLayout.topControl = existingComp;
+			existing.setSelection(true);
+		} else {
+			mode = MODE_MANUAL;
+			stackLayout.topControl = manualComp2;
+			manualComp.setVisible(true);
+			manual.setSelection(true);
+		}
+		
+		if (module != null) {
+			// preferred server button
+			pref = new Button(this, SWT.CHECK | SWT.WRAP);
+			pref.setText(ServerUIPlugin.getResource("%wizSelectServerPreferred"));
+			data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_END);
+			//pref.setSelection(true);
+			//preferred = true;
+			data.horizontalSpan = 1;
+			pref.setLayoutData(data);
+			pref.addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					preferred = pref.getSelection();
+				}
+			});
+			WorkbenchHelp.setHelp(pref, ContextIds.SELECT_SERVER_PREFERENCE);
+		}
+		
+		Dialog.applyDialogFont(this);
+	}
+	
+	protected void toggleMode(byte newMode) {
+		if (!isVisible())
+			return;
+
+		if (newMode == mode)
+			return;
+		
+		mode = newMode;
+		
+		if (mode == MODE_EXISTING)
+			stackLayout.topControl = existingComp;
+		else if (mode == MODE_DETECT) {
+			stackLayout.topControl = detectComp2;
+			detectComp.setVisible(true);
+		} else {
+			stackLayout.topControl = manualComp2;
+			manualComp.setVisible(true);
+		}
+		stack.layout();
+		if (taskModel != null) {
+			taskModel.putObject(NewServerWizardFragment.MODE, new Byte(mode));
+			updateTaskModel();
+		}
+	}
+	
+	protected HostnameComposite createHostComposite(Composite comp) {
+		HostnameComposite hostComp = new HostnameComposite(comp, new HostnameComposite.IHostnameSelectionListener() {
+			public void hostnameSelected(String host) {
+				lastHostname = host;
+				if (detectComp != null)
+					detectComp.setHost(host);
+				if (manualComp != null)
+					manualComp.setHost(host);
+			}
+		});
+		
+		if (lastHostname != null)
+			hostComp.setHostname(lastHostname);
+		
+		GridData data = new GridData(GridData.FILL_HORIZONTAL);
+		data.horizontalSpan = 3;
+		hostComp.setLayoutData(data);
+		return hostComp;
+	}
+	
+	protected void createAutoComposite(Composite comp) {
+		detectComp2 = new Composite(comp, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 1;
+		detectComp2.setLayout(layout);
+		
+		detectHostComp = createHostComposite(detectComp2);
+		
+		detectComp = new NewDetectServerComposite(detectComp2, new NewDetectServerComposite.IServerSelectionListener() {
+			public void serverSelected(IServer server) {
+			}
+		});
+
+		if (lastHostname != null)
+			detectComp.setHost(lastHostname);
+		else
+			detectComp.setHost("localhost");
+		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
+		data.horizontalSpan = 3;
+		data.heightHint = 120;
+		detectComp.setLayoutData(data);
+	}
+
+	protected void createExistingComposite(Composite comp) {
+		existingComp = new ServerComposite(comp, SWT.NONE, new ServerComposite.ServerSelectionListener() {
+			public void serverSelected(IServer server) {
+				wizard.setMessage(null, IMessageProvider.NONE);
+				updateTaskModel();
+			}
+		}, module, launchMode);
+		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
+		data.horizontalSpan = 3;
+		data.heightHint = 120;
+		existingComp.setLayoutData(data);
+	}
+
+	protected void createManualComposite(Composite comp) {
+		manualComp2 = new Composite(comp, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 1;
+		manualComp2.setLayout(layout);
+		
+		manualHostComp = createHostComposite(manualComp2);
+		
+		manualComp = new NewManualServerComposite(manualComp2, new NewManualServerComposite.IWizardHandle2() {
+			public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) throws InterruptedException, InvocationTargetException {
+				wizard.run(fork, cancelable, runnable);
+			}
+			public void update() {
+				wizard.update();
+			}
+			public void setMessage(String newMessage, int newType) {
+				wizard.setMessage(newMessage, newType);
+			}
+		}, new NewManualServerComposite.ServerSelectionListener() {
+			public void serverSelected(IServer server) {
+				updateTaskModel();
+			}
+		});
+		
+		if (lastHostname != null)
+			manualComp.setHost(lastHostname);
+		else
+			manualComp.setHost("localhost");
+
+		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
+		data.horizontalSpan = 3;
+		data.heightHint = 200;
+		manualComp.setLayoutData(data);
+	}
+
+	protected void updateTaskModel() {
+		if (taskModel != null) {
+			IServer server = getServer();
+			taskModel.putObject(ITaskModel.TASK_SERVER, server);
+			if (server != null)
+				taskModel.putObject(ITaskModel.TASK_RUNTIME, server.getRuntime());
+			else
+				taskModel.putObject(ITaskModel.TASK_RUNTIME, null);
+			wizard.update();
+		}
+	}
+
+	public void setTaskModel(ITaskModel model) {
+		taskModel = model;
+		taskModel.putObject(NewServerWizardFragment.MODE, new Byte(mode));
+		updateTaskModel();
+	}
+
+	public IServer getServer() {
+		if (mode == MODE_EXISTING)
+			return existingComp.getSelectedServer();
+		else if (mode == MODE_DETECT)
+			return detectComp.getServer();
+		else
+			return manualComp.getServer();
+	}
+
+	public IRuntime getRuntime() {
+		if (mode == MODE_EXISTING) {
+			IServer server = existingComp.getSelectedServer();
+			if (server != null)
+				return server.getRuntime();
+			else
+				return null;
+		} else if (mode == MODE_DETECT)
+			return null;
+		else
+			return manualComp.getRuntime();
+	}
+	
+	/**
+	 * Returns true if this server should become the preferred server.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isPreferredServer() {
+		return preferred;
+	}
+	
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		
+		Control[] c = getChildren();
+		if (c != null) {
+			int size = c.length;
+			for (int i = 0; i < size; i++)
+				if (c[i] != null)
+					c[i].setVisible(visible);
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/SelectClientComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/SelectClientComposite.java
new file mode 100644
index 0000000..59e503d
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/SelectClientComposite.java
@@ -0,0 +1,165 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.wst.server.core.IClient;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ContextIds;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.SWTUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.help.WorkbenchHelp;
+
+/**
+ * A wizard page used to select a server client.
+ */
+public class SelectClientComposite extends Composite {
+	protected IWizardHandle wizard;
+
+	// the list of elements to select from
+	protected List elements;
+
+	// the currently selected element
+	protected IClient selectedClient;
+
+	// the table containing the elements
+	protected Table elementTable;
+
+	// the description of the selected client
+	protected Label description;
+
+	/**
+	 * Create a new SelectClientWizardPage.
+	 *
+	 * @param elements java.util.List
+	 */
+	public SelectClientComposite(Composite parent, IWizardHandle wizard, List elements) {
+		super(parent, SWT.NONE);
+		this.wizard = wizard;
+		this.elements = elements;
+	
+		wizard.setTitle(ServerUIPlugin.getResource("%wizSelectClientTitle"));
+		wizard.setDescription(ServerUIPlugin.getResource("%wizSelectClientDescription"));
+		wizard.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_SELECT_SERVER_CLIENT));
+		
+		createControl();
+	}
+
+	/**
+	 * Clears the selected client.
+	 */
+	public void clearSelectedClient() {
+		selectedClient = null;
+	}
+
+	/**
+	 * Creates the UI of the page.
+	 *
+	 * @param org.eclipse.swt.widgets.Composite parent
+	 */
+	protected void createControl() {
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		setLayout(layout);
+
+		WorkbenchHelp.setHelp(this, ContextIds.SELECT_CLIENT_WIZARD);
+	
+		Label label = new Label(this, SWT.WRAP);
+		label.setText(ServerUIPlugin.getResource("%wizSelectClientMessage"));
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
+		label.setLayoutData(data);
+	
+		elementTable = new Table(this, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+		data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
+		data.heightHint = 80;
+		data.horizontalIndent = 20;
+		elementTable.setLayoutData(data);
+		elementTable.addSelectionListener(new SelectionListener() {
+			public void widgetSelected(SelectionEvent e) {
+				handleSelection();
+			}
+			public void widgetDefaultSelected(SelectionEvent e) {
+				handleSelection();
+				//TODO: WizardUtil.defaultSelect(getWizard(), SelectClientWizardPage.this);
+			}
+		});
+		WorkbenchHelp.setHelp(elementTable, ContextIds.SELECT_CLIENT);
+	
+		Iterator iterator = elements.iterator();
+		while (iterator.hasNext()) {
+			IClient element = (IClient) iterator.next();
+			TableItem item = new TableItem(elementTable, SWT.NONE);
+			item.setText(0, ServerUICore.getLabelProvider().getText(element));
+			item.setImage(0, ServerUICore.getLabelProvider().getImage(element));
+			item.setData(element);
+		}
+	
+		description = new Label(this, SWT.WRAP);
+		description.setText("");
+		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
+		data.heightHint = 70;
+		description.setLayoutData(data);
+	
+		Dialog.applyDialogFont(this);
+	}
+
+	/**
+	 * Return the selected client.
+	 *
+	 * @return org.eclipse.wst.server.core.model.IServerClient
+	 */
+	public IClient getSelectedClient() {
+		return selectedClient;
+	}
+
+	/**
+	 * Handle the selection of a client.
+	 */
+	protected void handleSelection() {
+		int index = elementTable.getSelectionIndex();
+		if (index < 0)
+			selectedClient = null;
+		else
+			selectedClient = (IClient) elements.get(index);
+		
+		if (selectedClient != null)
+			wizard.setMessage(null, IMessageProvider.NONE);
+		else
+			wizard.setMessage("", IMessageProvider.ERROR);
+	
+		String desc = null;
+		if (selectedClient != null)
+			desc = selectedClient.getDescription();
+		if (desc == null)
+			desc = "";
+		description.setText(desc);
+	
+		wizard.update();
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/TasksComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/TasksComposite.java
new file mode 100644
index 0000000..e667554
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/TasksComposite.java
@@ -0,0 +1,218 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.util.List;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.wst.server.core.model.IModuleTaskDelegate;
+import org.eclipse.wst.server.core.model.IServerTaskDelegate;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.ContextIds;
+import org.eclipse.wst.server.ui.internal.ImageResource;
+import org.eclipse.wst.server.ui.internal.SWTUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.wizard.fragment.TasksWizardFragment;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+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.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.help.WorkbenchHelp;
+
+/**
+ * A wizard page used to select server and module tasks.
+ */
+public class TasksComposite extends Composite {
+	protected IWizardHandle wizard;
+
+	// the list of elements to select from
+	protected List tasks;
+
+	/**
+	 * Create a new TasksWizardPage.
+	 *
+	 * @param elements java.util.List
+	 */
+	public TasksComposite(Composite parent, IWizardHandle wizard, List tasks) {
+		super(parent, SWT.NONE);
+		this.wizard = wizard;
+		this.tasks = tasks;
+	
+		wizard.setTitle(ServerUIPlugin.getResource("%wizTaskTitle"));
+		wizard.setDescription(ServerUIPlugin.getResource("%wizTaskDescription"));
+		wizard.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_SELECT_SERVER));
+		
+		createControl();
+	}
+
+	/**
+	 * Creates the UI of the page.
+	 *
+	 * @param org.eclipse.swt.widgets.Composite parent
+	 */
+	protected void createControl() {
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.numColumns = 3;
+		setLayout(layout);
+		WorkbenchHelp.setHelp(this, ContextIds.SELECT_TASK_WIZARD);
+		
+		int size = tasks.size();
+		
+		Object cont = null;
+		Group group = null;
+		int count = 0;
+	
+		for (int i = 0; i < size; i++) {
+			Object obj = tasks.get(i);
+			if (obj instanceof TasksWizardFragment.ServerTaskInfo) {
+				final TasksWizardFragment.ServerTaskInfo sti = (TasksWizardFragment.ServerTaskInfo) obj;
+				if (cont != sti.server) {
+					if (group != null && count == 0)
+						group.setEnabled(false);
+
+					if (cont != null) {
+						Label spacer = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL);
+						GridData data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
+						data.horizontalSpan = 3;
+						spacer.setLayoutData(data);
+					}
+					
+					group = new Group(this, SWT.SHADOW_NONE);
+					group.setText(ServerUIPlugin.getResource("%wizTaskDetail") + " " + ServerUICore.getLabelProvider().getText(sti.server));
+					GridData data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
+					data.horizontalSpan = 3;
+					group.setLayoutData(data);
+					
+					layout = new GridLayout();
+					layout.horizontalSpacing = 0;
+					layout.verticalSpacing = 3;
+					layout.marginWidth = 5;
+					layout.marginHeight = 5;
+					group.setLayout(layout);
+
+					cont = sti.server;
+				}
+				final Button checkbox = new Button(group, SWT.CHECK);
+				checkbox.setText(sti.task2.getName());
+				GridData data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL);
+				checkbox.setLayoutData(data);
+				checkbox.setFocus();
+			
+				checkbox.addSelectionListener(new SelectionListener() {
+					public void widgetSelected(SelectionEvent event) {
+						sti.selected = checkbox.getSelection();
+					}
+					public void widgetDefaultSelected(SelectionEvent event) {
+						sti.selected = checkbox.getSelection();
+					}
+				});
+				
+				Label description = new Label(group, SWT.WRAP);
+				data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL);
+				data.heightHint = 50;
+				data.horizontalIndent = 20;
+				description.setLayoutData(data);
+				description.setText(sti.task2.getDescription());
+				
+				byte status = sti.status;
+				if (status == IServerTaskDelegate.TASK_COMPLETED) {
+					checkbox.setEnabled(false);
+					description.setEnabled(false);
+				} else if (status == IServerTaskDelegate.TASK_PREFERRED) {
+					checkbox.setSelection(true);
+					count++;
+				} else if (status == IServerTaskDelegate.TASK_MANDATORY) {
+					checkbox.setSelection(true);
+					checkbox.setEnabled(false);
+					description.setEnabled(false);
+				} else
+					count++;
+			} else if (obj instanceof TasksWizardFragment.ModuleTaskInfo) {
+				final TasksWizardFragment.ModuleTaskInfo dti = (TasksWizardFragment.ModuleTaskInfo) obj;
+				if (cont != dti.module) {
+					if (group != null && count == 0)
+						group.setEnabled(false);
+
+					if (cont != null) {
+						Label spacer = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL);
+						GridData data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL);
+						data.horizontalSpan = 3;
+						spacer.setLayoutData(data);
+					}
+					
+					group = new Group(this, SWT.SHADOW_NONE);
+					group.setText(ServerUIPlugin.getResource("%wizTaskDetail") + " " + ServerUICore.getLabelProvider().getText(dti.module));
+					GridData data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
+					data.horizontalSpan = 3;
+					group.setLayoutData(data);
+					
+					layout = new GridLayout();
+					layout.horizontalSpacing = 0;
+					layout.verticalSpacing = 3;
+					layout.marginWidth = 5;
+					layout.marginHeight = 5;
+					group.setLayout(layout);
+
+					cont = dti.module;
+				}
+				final Button checkbox = new Button(group, SWT.CHECK);
+				checkbox.setText(dti.task2.getName());
+				GridData data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL);
+				checkbox.setLayoutData(data);
+				checkbox.setFocus();
+				
+				checkbox.addSelectionListener(new SelectionListener() {
+					public void widgetSelected(SelectionEvent event) {
+						dti.selected = checkbox.getSelection();
+					}
+					public void widgetDefaultSelected(SelectionEvent event) {
+						dti.selected = checkbox.getSelection();
+					}
+				});
+				
+				Label description = new Label(group, SWT.WRAP);
+				data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL);
+				data.heightHint = 50;
+				data.horizontalIndent = 20;
+				description.setLayoutData(data);
+				description.setText(dti.task2.getDescription());
+				
+				byte status = dti.status;
+				if (status == IModuleTaskDelegate.TASK_COMPLETED) {
+					checkbox.setEnabled(false);
+					description.setEnabled(false);
+				} else if (status == IModuleTaskDelegate.TASK_PREFERRED) {
+					checkbox.setSelection(true);
+					count++;
+				} else if (status == IModuleTaskDelegate.TASK_MANDATORY) {
+					checkbox.setSelection(true);
+					checkbox.setEnabled(false);
+					description.setEnabled(false);
+				} else
+					count++;
+			}
+		}
+		if (group != null && count == 0)
+			group.setEnabled(false);
+
+		Dialog.applyDialogFont(this);
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/WizardUtil.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/WizardUtil.java
new file mode 100644
index 0000000..e0b8c55
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/WizardUtil.java
@@ -0,0 +1,265 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.IWizard;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.wst.server.core.IResourceManager;
+import org.eclipse.wst.server.core.IServerProject;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.core.ServerUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.wizard.ClosableWizardDialog;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * A helper class for wizards.
+ */
+public class WizardUtil {
+	/**
+	 * Use static methods.
+	 */
+	private WizardUtil() { }
+
+	/**
+	 * Fill the combo box with all server project folders in
+	 * the workbench.
+	 *
+	 * @param combo org.eclipse.swt.widgets.Combo
+	 */
+	public static void fillComboWithServerProjectFolders(Combo combo) {
+		List list = new ArrayList();
+		Iterator iterator = ServerCore.getServerNatures().iterator();
+		while (iterator.hasNext()) {
+			IServerProject project = (IServerProject) iterator.next();
+			if (project.getProject().isOpen()) {
+				Iterator iter = project.getAvailableFolders().iterator();
+				while (iter.hasNext())
+					list.add(iter.next());
+			}
+		}
+	
+		// convert to strings
+		int size = list.size();
+		for (int i = 0; i < size; i++){
+			IContainer container = (IContainer) list.get(i);
+			list.set(i, getContainerText(container));
+		}
+	
+		// sort results
+		for (int i = 0; i < size - 1; i++) {
+			for (int j = i + 1; j < size; j++) {
+				String s1 = (String) list.get(i);
+				String s2 = (String) list.get(j);
+				if (s1.compareTo(s2) > 0) {
+					list.set(j, s1);
+					list.set(i, s2);
+				}
+			}
+		}
+	
+		String[] s = new String[size];
+		list.toArray(s);
+		combo.setItems(s);
+		if (s.length > 0)
+			combo.select(0);
+	}
+
+	/**
+	 * Return the container with the given name, if one exists.
+	 *
+	 * @param containerName java.lang.String
+	 * @return org.eclipse.core.resources.IContainer
+	 */
+	public static IContainer findContainer(String containerName) {
+		if (containerName == null || containerName.equals(""))
+			return null;
+	
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		try {
+			IProject project = root.getProject(containerName);
+			if (project != null && project.exists())
+				return project;
+		} catch (Exception e) { }
+	
+		try {
+			IFolder folder = root.getFolder(new Path(containerName));
+			if (folder != null && folder.exists())
+				return folder;
+		} catch (Exception e) { }
+		return null;
+	}
+
+	/**
+	 * Tries to find a server project folder in the heirarchy
+	 * of the given resource. If it finds one, it returns the
+	 * folder that the resource is or is in.
+	 *
+	 * @param resource org.eclipse.core.resources.IResource
+	 * @return org.eclipse.core.resources.IContainer
+	 */
+	protected static IContainer findServerProjectContainer(IResource resource) {
+		IResourceManager rm = ServerCore.getResourceManager();
+		IContainer container = null;
+		while (resource != null) {
+			if (container == null && resource instanceof IContainer)
+				container = (IContainer) resource;
+	
+			if (resource instanceof IFile) {
+				IFile file = (IFile) resource;
+				if (rm.getServerConfiguration(file) != null || rm.getServer(file) != null)
+				return null;
+			}
+	
+			if (resource instanceof IProject) {
+				if (ServerUtil.isServerProject((IProject) resource) && ((IProject)resource).isOpen())
+					return container;
+			}
+			resource = resource.getParent();
+		}
+		return null;
+	}
+
+	/**
+	 * Return the full pathname of a container.
+	 *
+	 * @param container org.eclipse.core.resources.Container
+	 * @return java.lang.String
+	 */
+	public static String getContainerText(IContainer container) {
+		String name = container.getName();
+		while (container != null && !(container instanceof IProject)) {
+			container = container.getParent();
+			name = container.getName() + "/" + name;
+		}
+		return name;
+	}
+
+	/**
+	 * Returns the selected container from this selection.
+	 *
+	 * @param sel org.eclipse.jface.viewers.IStructuredSelection
+	 * @return org.eclipse.core.resources.IContainer
+	 */
+	public static IContainer getSelectionContainer(IStructuredSelection selection) {
+		if (selection == null || selection.isEmpty())
+			return null;
+	
+		Object obj = selection.getFirstElement();
+		if (obj instanceof IResource)
+			return findServerProjectContainer((IResource) obj);
+	
+		return null;
+	}
+
+	/**
+	 * Return true if the container is a valid server project
+	 * folder and is not "within" a server instance or configuration.
+	 *
+	 * @return String
+	 * @param container IContainer
+	 */
+	public static String validateContainer(String name) {
+		IContainer container = WizardUtil.findContainer(name);
+		if (container == null || !container.exists()) {
+			IStatus status = ResourcesPlugin.getWorkspace().validateName(name, IResource.PROJECT);
+			if (status.isOK())
+				return null; // we can create one later
+			else
+				return status.getMessage();
+		}
+		
+		String error = ServerUIPlugin.getResource("%wizErrorInvalidFolder");
+		try {
+			// find project of this container
+			IProject project = null;
+			if (container instanceof IProject) {
+				project = (IProject) container;
+			} else {
+				// look up hierarchy for project
+				IContainer temp = container.getParent();
+				while (project == null && temp != null && !(temp instanceof IProject)) {
+					temp = temp.getParent();
+				}
+				if (temp != null && temp instanceof IProject)
+					project = (IProject) temp;
+			}
+	
+			// validate the project
+			if (project != null && !project.isOpen())
+				return ServerUIPlugin.getResource("%wizErrorClosedProject");
+
+			if (project == null || !project.exists() || !project.isOpen() || !ServerUtil.isServerProject(project))
+				return error;
+	
+			// make sure we're not embedding in another server element
+			IResource temp = container;
+			IResourceManager rm = ServerCore.getResourceManager();
+			while (temp != null && !(temp instanceof IProject)) {
+				if (temp instanceof IFile) {
+					IFile file = (IFile) temp;
+					if (rm.getServerConfiguration(file) != null || rm.getServer(file) != null)
+						return error;
+				}
+				temp = temp.getParent();
+			}
+		} catch (Exception e) {
+			return error;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns true if no server projects exist.
+	 *
+	 * @return boolean
+	 */
+	public static boolean noServerProjectsExist() {
+		return (ServerCore.getServerProjects().isEmpty());
+	}
+	
+	public static IProject getServerProject() {
+		return ServerUtil.getDefaultServerProject();
+	}
+
+	/**
+	 * Returns true if the user said okay to creating a new server
+	 * project.
+	 *
+	 * @return boolean
+	 */
+	public static boolean promptForServerProjectCreation(Shell shell, String projectName) {
+		String msg = ServerUIPlugin.getResource("%createServerProjectDialogMessage", projectName);
+		return MessageDialog.openQuestion(shell, ServerUIPlugin.getResource("%createServerProjectDialogTitle"), msg);
+	}
+	
+	/**
+	 * Handles default selection within a wizard by going to the next
+	 * page, or finishing the wizard if possible.
+	 */
+	public static void defaultSelect(IWizard wizard, IWizardPage page) {
+		if (page.canFlipToNextPage() && page.getNextPage() != null)
+			wizard.getContainer().showPage(page.getNextPage());
+		else if (wizard.canFinish() && wizard.getContainer() instanceof ClosableWizardDialog) {
+			ClosableWizardDialog dialog = (ClosableWizardDialog) wizard.getContainer();
+			dialog.finishPressed();
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/WorkspaceRunnableAdapter.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/WorkspaceRunnableAdapter.java
new file mode 100644
index 0000000..5f6e84a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/WorkspaceRunnableAdapter.java
@@ -0,0 +1,40 @@
+package org.eclipse.wst.server.ui.internal.wizard.page;
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ *
+ **********************************************************************/
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+/**
+ * IRunnableWithProgressAdapter to allow it to run an IWorkspaceRunnable.
+ */
+public class WorkspaceRunnableAdapter implements IRunnableWithProgress {
+	private IWorkspaceRunnable workspaceRunnable;
+	
+	public WorkspaceRunnableAdapter(IWorkspaceRunnable runnable) {
+		workspaceRunnable = runnable;
+	}
+
+	/*
+	 * @see IRunnableWithProgress#run(IProgressMonitor)
+	 */
+	public void run(IProgressMonitor monitor) throws InvocationTargetException {
+		try {
+			ResourcesPlugin.getWorkspace().run(workspaceRunnable, monitor);
+		} catch (CoreException e) {
+			throw new InvocationTargetException(e);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/IWizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/IWizardFragment.java
new file mode 100644
index 0000000..042e45c
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/IWizardFragment.java
@@ -0,0 +1,44 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.wizard;
+
+import java.util.List;
+
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.wst.server.core.ITask;
+import org.eclipse.wst.server.core.ITaskModel;
+/**
+ * 
+ */
+public interface IWizardFragment {
+	public boolean hasComposite();
+
+	public Composite createComposite(Composite parent, IWizardHandle handle);
+
+	public void setTaskModel(ITaskModel model);
+	
+	public ITaskModel getTaskModel();
+
+	public void enter();
+
+	public void exit();
+
+	public ITask createFinishTask();
+
+	public ITask createCancelTask();
+
+	public List getChildFragments();
+
+	public void updateSubFragments();
+
+	public boolean isComplete();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/IWizardHandle.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/IWizardHandle.java
new file mode 100644
index 0000000..24b3165
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/IWizardHandle.java
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.wizard;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.resource.ImageDescriptor;
+/**
+ * 
+ */
+public interface IWizardHandle extends IMessageProvider {
+	public void update();
+
+	public void setTitle(String title);
+
+	public void setDescription(String desc);
+
+	public void setImageDescriptor(ImageDescriptor image);
+
+	public void setMessage(String newMessage, int newType);
+
+	public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) throws InterruptedException, InvocationTargetException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/TaskWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/TaskWizard.java
new file mode 100644
index 0000000..892eb74
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/TaskWizard.java
@@ -0,0 +1,499 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.wizard;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.wizard.IWizard;
+import org.eclipse.jface.wizard.IWizardContainer;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.wst.server.core.ITask;
+import org.eclipse.wst.server.core.ITaskModel;
+import org.eclipse.wst.server.core.util.TaskModel;
+import org.eclipse.wst.server.ui.internal.Trace;
+import org.eclipse.wst.server.ui.internal.wizard.page.WorkspaceRunnableAdapter;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * A wizard used to execute tasks.
+ */
+public class TaskWizard implements IWizard {
+	private static final byte FINISH = 2;
+	private static final byte CANCEL = 3;
+
+	private List pages;
+	private Map fragmentData = new HashMap();
+	protected ITaskModel taskModel = new TaskModel();
+	
+	private IWizardContainer container = null;
+	
+	private boolean needsProgressMonitor = false;
+	
+	private boolean forcePreviousAndNextButtons = false;
+
+	private boolean isHelpAvailable = false;
+	
+	private Image defaultImage = null;
+	
+	private RGB titleBarColor = null;
+
+	private String windowTitle = null;
+	
+	private IDialogSettings dialogSettings = null;
+	
+	private IWizardFragment rootFragment;
+	private IWizardFragment currentFragment;
+	
+	private static TaskWizard current; // TODO temp fix
+
+	class FragmentData {
+		public TaskWizardPage page;
+		public ITask finishTask;
+		public ITask cancelTask;
+		
+		public FragmentData(IWizardFragment fragment) {
+			finishTask = fragment.createFinishTask();
+			if (finishTask != null)
+				finishTask.setTaskModel(taskModel);
+			
+			cancelTask = fragment.createCancelTask();
+			if (cancelTask != null)
+				cancelTask.setTaskModel(taskModel);
+		}
+	}
+	
+	/**
+	 * TaskWizard constructor comment.
+	 */
+	public TaskWizard() {
+		super();
+		
+		setNeedsProgressMonitor(true);
+		setForcePreviousAndNextButtons(true);
+		
+		current = this; // TODO temp fix
+	}
+
+	/**
+	 * TaskWizard constructor comment.
+	 */
+	public TaskWizard(IWizardFragment rootFragment) {
+		this();
+		this.rootFragment = rootFragment;
+	}
+	
+	public TaskWizard(String title) {
+		this();
+		setWindowTitle(title);
+	}
+	
+	public TaskWizard(String title, IWizardFragment rootFragment) {
+		this(rootFragment);
+		setWindowTitle(title);
+	}
+	
+	public void setRootFragment(IWizardFragment rootFragment) {
+		this.rootFragment = rootFragment;
+	}
+	
+	public IWizardFragment getRootFragment() {
+		return rootFragment;
+	}
+
+	/**
+	 * Cancel the client selection.
+	 *
+	 * @return boolean
+	 */
+	public boolean performCancel() {
+		final List list = getAllWizardFragments();
+		IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+			public void run(IProgressMonitor monitor) throws CoreException {
+				Iterator iterator = list.iterator();
+				while (iterator.hasNext())
+					executeTask((IWizardFragment) iterator.next(), CANCEL);
+			}
+		};
+		
+		try {
+			getContainer().run(true, true, new WorkspaceRunnableAdapter(runnable));
+			return true;
+		} catch (Exception e) {
+			return false;
+		}
+	}
+
+	public boolean performFinish() {
+		if (currentFragment != null)
+			currentFragment.exit();
+		
+		final IWizardFragment cFragment = currentFragment;
+
+		final List list = getAllWizardFragments();
+		IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+			public void run(IProgressMonitor monitor) throws CoreException {
+				// enter & exit the remaining pages
+				int index = list.indexOf(cFragment);
+				while (index > 0 && index < list.size() - 1) {
+					IWizardFragment fragment = (IWizardFragment) list.get(++index);
+					try {
+						fragment.enter();
+						fragment.exit();
+					} catch (Exception e) {
+						Trace.trace(Trace.WARNING, "Could not enter/exit page", e);
+					}
+				}
+				
+				// finish
+				Iterator iterator = list.iterator();
+				while (iterator.hasNext())
+					executeTask((IWizardFragment) iterator.next(), FINISH);
+			}
+		};
+		
+		try {
+			if (getContainer() != null)
+				getContainer().run(true, true, new WorkspaceRunnableAdapter(runnable));
+			else
+				runnable.run(new NullProgressMonitor());
+			return true;
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error finishing task wizard", e);
+			return false;
+		}
+	}
+	
+	public void addPage(IWizardPage page) {
+		pages.add(page);
+		page.setWizard(this);
+	}
+	
+	protected void executeTask(IWizardFragment fragment, byte type) throws CoreException {
+		if (fragment == null)
+			return;
+		
+		FragmentData data = getFragmentData(fragment);
+		if (type == FINISH && data.finishTask != null)
+			data.finishTask.execute(new NullProgressMonitor());
+		else if (type == CANCEL && data.cancelTask != null)
+			data.cancelTask.execute(new NullProgressMonitor());
+	}
+	
+	protected boolean safeExecuteTask(IWizardFragment fragment, byte type) {
+		try {
+			executeTask(fragment, type);
+			return true;
+		} catch (CoreException ce) {
+			Trace.trace(Trace.SEVERE, "Error executing wizard fragment task", ce);
+			return false;
+		}
+	}
+	
+	protected IWizardFragment getCurrentWizardFragment() {
+		return currentFragment;
+	}
+	
+	protected void switchWizardFragment(IWizardFragment newFragment) {
+		List list = getAllWizardFragments();
+		int oldIndex = list.indexOf(currentFragment);
+		int newIndex = list.indexOf(newFragment);
+		if (oldIndex == newIndex)
+			return;
+		
+		//safeExecuteTask(currentFragment, DEPARTURE);
+		if (currentFragment != null)
+			currentFragment.exit();
+		
+		if (oldIndex < newIndex)
+			oldIndex ++;
+		else
+			oldIndex --;
+		
+		while (oldIndex != newIndex) {
+			IWizardFragment fragment = (IWizardFragment) list.get(oldIndex);
+			//safeExecuteTask(fragment, ARRIVAL);
+			//safeExecuteTask(fragment, DEPARTURE);
+			fragment.enter();
+			fragment.exit();
+			if (oldIndex < newIndex)
+				oldIndex ++;
+			else
+				oldIndex --;
+		}
+		
+		currentFragment = newFragment;
+		//safeExecuteTask(currentFragment, ARRIVAL);
+		currentFragment.enter();
+	}
+	
+	protected List getAllWizardFragments() {
+		List list = new ArrayList();
+		list.add(rootFragment);
+		addSubWizardFragments(rootFragment, list);
+		
+		Iterator iterator = list.iterator();
+		while (iterator.hasNext()) {
+			IWizardFragment fragment = (IWizardFragment) iterator.next();
+			if (!taskModel.equals(fragment.getTaskModel()))
+				fragment.setTaskModel(taskModel);
+		}
+		return list;
+	}
+
+	protected void addSubWizardFragments(IWizardFragment fragment, List list) {
+		Iterator iterator = fragment.getChildFragments().iterator();
+		while (iterator.hasNext()) {
+			IWizardFragment child = (IWizardFragment) iterator.next();
+			list.add(child);
+			addSubWizardFragments(child, list);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#addPages()
+	 */
+	public void addPages() {
+		try {
+			pages = new ArrayList();
+			Iterator iterator = getAllWizardFragments().iterator();
+			while (iterator.hasNext()) {
+				IWizardFragment fragment = (IWizardFragment) iterator.next();
+				FragmentData data = getFragmentData(fragment);
+				if (data.page != null) {
+					addPage(data.page);
+				} else if (fragment.hasComposite()) {
+					TaskWizardPage page = new TaskWizardPage(fragment);
+					data.page = page;
+					addPage(page);
+				}	
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error adding fragments to wizard", e);
+		}
+	}
+	
+	protected static void updateWizardPages() {
+		try { // TODO temp fix
+			current.updatePages();
+			current.getContainer().updateButtons();
+		} catch (Exception e) {
+			Trace.trace("Error updating wizard pages", e);
+		}
+	}
+	
+	protected FragmentData getFragmentData(IWizardFragment fragment) {
+		try {
+			FragmentData data = (FragmentData) fragmentData.get(fragment);
+			if (data != null)
+				return data;
+		} catch (Exception e) {
+			Trace.trace("Error getting fragment data", e);
+		}
+		
+		FragmentData data = new FragmentData(fragment);
+		fragmentData.put(fragment, data);
+		return data;
+	}
+	
+	protected void updatePages() {
+		addPages();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#canFinish()
+	 */
+	public boolean canFinish() {
+		// Default implementation is to check if all pages are complete.
+		for (int i= 0; i < pages.size(); i++) {
+			if (!((IWizardPage)pages.get(i)).isPageComplete())
+				return false;
+		}
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#createPageControls(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createPageControls(Composite pageContainer) {
+		// the default behavior is to create all the pages controls
+		for (int i = 0; i < pages.size(); i++){
+			IWizardPage page = (IWizardPage) pages.get(i);
+			page.createControl(pageContainer);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#dispose()
+	 */
+	public void dispose() {
+		// notify pages
+		for (int i = 0; i < pages.size(); i++){
+			((IWizardPage)pages.get(i)).dispose();
+		}
+
+		// dispose of image
+		if (defaultImage != null) {
+			defaultImage.dispose();
+			defaultImage = null;
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getContainer()
+	 */
+	public IWizardContainer getContainer() {
+		return container;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getDefaultPageImage()
+	 */
+	public Image getDefaultPageImage() {
+		return defaultImage;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getDialogSettings()
+	 */
+	public IDialogSettings getDialogSettings() {
+		return dialogSettings;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getNextPage(org.eclipse.jface.wizard.IWizardPage)
+	 */
+	public IWizardPage getNextPage(IWizardPage page) {
+		int index = pages.indexOf(page);
+		if (index == pages.size() - 1 || index == -1)
+			// last page or page not found
+			return null;
+		
+		return (IWizardPage)pages.get(index + 1);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getPage(java.lang.String)
+	 */
+	public IWizardPage getPage(String name) {
+		for (int i= 0; i < pages.size(); i++) {
+			IWizardPage page = (IWizardPage)pages.get(i);
+			String pageName = page.getName();
+			if (pageName.equals(name))
+				return page;
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getPageCount()
+	 */
+	public int getPageCount() {
+		return pages.size();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getPages()
+	 */
+	public IWizardPage[] getPages() {
+		return (IWizardPage[])pages.toArray(new IWizardPage[pages.size()]);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getPreviousPage(org.eclipse.jface.wizard.IWizardPage)
+	 */
+	public IWizardPage getPreviousPage(IWizardPage page) {
+		int index = pages.indexOf(page);
+		if (index == 0 || index == -1)
+			// first page or page not found
+			return null;
+		else
+			return (IWizardPage)pages.get(index - 1);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getStartingPage()
+	 */
+	public IWizardPage getStartingPage() {
+		if (pages.size() == 0)
+			return null;
+		
+		return (IWizardPage) pages.get(0);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getTitleBarColor()
+	 */
+	public RGB getTitleBarColor() {
+		return titleBarColor;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#getWindowTitle()
+	 */
+	public String getWindowTitle() {
+		return windowTitle;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#isHelpAvailable()
+	 */
+	public boolean isHelpAvailable() {
+		return isHelpAvailable;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#needsPreviousAndNextButtons()
+	 */
+	public boolean needsPreviousAndNextButtons() {
+		return forcePreviousAndNextButtons || pages.size() > 1;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#needsProgressMonitor()
+	 */
+	public boolean needsProgressMonitor() {
+		return needsProgressMonitor;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.IWizard#setContainer(org.eclipse.jface.wizard.IWizardContainer)
+	 */
+	public void setContainer(IWizardContainer wizardContainer) {
+		this.container = wizardContainer;
+	}
+	
+	public void setDialogSettings(IDialogSettings settings) {
+		dialogSettings = settings;
+	}
+	
+	public void setNeedsProgressMonitor(boolean b) {
+		needsProgressMonitor = b;
+	}
+	
+	public void setForcePreviousAndNextButtons(boolean b) {
+		forcePreviousAndNextButtons = b;
+	}
+	
+	public void setWindowTitle(String title) {
+		windowTitle = title;
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/TaskWizardPage.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/TaskWizardPage.java
new file mode 100644
index 0000000..d574ed3
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/TaskWizardPage.java
@@ -0,0 +1,102 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.wizard;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+/**
+ * 
+ */
+class TaskWizardPage extends WizardPage implements IWizardHandle {
+	protected IWizardFragment fragment;
+	
+	protected boolean isEmptyError = false;
+
+	public TaskWizardPage(IWizardFragment fragment) {
+		super(fragment.toString());
+		this.fragment = fragment;
+	}
+	
+	public void createControl(Composite parentComp) {
+		Composite comp = fragment.createComposite(parentComp, this);
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = convertHorizontalDLUsToPixels(350);
+		//data.heightHint = convertVerticalDLUsToPixels(350);
+		comp.setLayoutData(data);
+		setControl(comp);
+	}
+
+	public IWizardPage getNextPage() {
+		return getWizard().getNextPage(this);
+	}
+
+	public IWizardPage getPreviousPage() {
+		return getWizard().getPreviousPage(this);
+	}
+
+	public boolean isPageComplete() {
+		if (!fragment.isComplete())
+			return false;
+		if (isEmptyError)
+			return false;
+		return (getMessage() == null || getMessageType() != ERROR);
+	}
+
+	public boolean canFlipToNextPage() {
+		if (getNextPage() == null)
+			return false;
+		if (isEmptyError)
+			return false;
+		return (getMessage() == null || getMessageType() != ERROR);
+	}
+
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		
+		if (visible) {
+			TaskWizard wizard = (TaskWizard) getWizard();
+			wizard.switchWizardFragment(fragment);
+			
+			if (getContainer().getCurrentPage() != null)
+				getContainer().updateButtons();
+		}
+	}
+	
+	public void setMessage(String message, int type) {
+		if (type == IMessageProvider.ERROR && "".equals(message)) {
+			isEmptyError = true;
+			message = null;
+		} else
+			isEmptyError = false;
+		super.setMessage(message, type);
+		IWizardFragment frag = ((TaskWizard) getWizard()).getCurrentWizardFragment();
+		if (!fragment.equals(frag))
+			return;
+		getContainer().updateButtons();
+	}
+	
+	public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) throws InterruptedException, InvocationTargetException {
+		getWizard().getContainer().run(fork, cancelable, runnable);
+	}
+
+	public void update() {
+		fragment.updateSubFragments();
+		((TaskWizard) getWizard()).updatePages();
+		if (getContainer().getCurrentPage() != null)
+			getContainer().updateButtons();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/WizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/WizardFragment.java
new file mode 100644
index 0000000..7972e2a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/wizard/WizardFragment.java
@@ -0,0 +1,88 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.server.ui.wizard;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.wst.server.core.ITask;
+import org.eclipse.wst.server.core.ITaskModel;
+/**
+ * 
+ */
+public class WizardFragment implements IWizardFragment {
+	protected List listImpl;
+	private boolean isComplete = true;
+	private ITaskModel model;
+
+	public boolean hasComposite() {
+		return false;
+	}
+
+	public Composite createComposite(Composite parent, IWizardHandle handle) {
+		return null;
+	}
+
+	public void setTaskModel(ITaskModel model) {
+		this.model = model;
+	}
+
+	public ITaskModel getTaskModel() {
+		return model;
+	}
+
+	public void enter() { }
+
+	public void exit() { }
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.IWizardFragment#createFinishTask()
+	 */
+	public ITask createFinishTask() {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.IWizardFragment#createCancelTask()
+	 */
+	public ITask createCancelTask() {
+		return null;
+	}
+
+	public void createSubFragments(List list) {
+		// add to list
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.server.ui.internal.task.IWizardFragment#getChildren()
+	 */
+	public List getChildFragments() {
+		if (listImpl == null) {
+			listImpl = new ArrayList();
+			createSubFragments(listImpl);
+		}
+		return listImpl;
+	}
+
+	public void updateSubFragments() {
+		listImpl = null;
+	}
+
+	public boolean isComplete() {
+		return isComplete;
+	}
+
+	protected void setComplete(boolean complete) {
+		this.isComplete = complete;
+	}
+}
\ No newline at end of file