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 ch