/**********************************************************************
 * Copyright (c) 2003, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - Initial API and implementation
 **********************************************************************/
package org.eclipse.wst.server.core.internal;

import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.debug.core.*;

import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.server.core.*;
import org.eclipse.wst.server.core.model.*;
import org.eclipse.wst.server.core.util.SocketUtil;
/**
 * 
 */
public class Server extends Base implements IServer {
	/**
	 * Server id attribute (value "server-id") of launch configurations.
	 * This attribute is used to tag a launch configuration with the
	 * id of the corresponding server.
	 * 
	 * @see ILaunchConfiguration
	 */
	public static final String ATTR_SERVER_ID = "server-id";

	protected static final List EMPTY_LIST = new ArrayList(0);

	/**
	 * File extension (value "server") for serialized representation of
	 * server instances.
	 * <p>
	 * [issue: What is relationship between this file extension and
	 * the file passed to IServerType.create(...) or returned by
	 * IServer.getFile()? That is, are server files expected to end
	 * in ".server", or is this just a default? If the former
	 * (as I suspect), then IServerType.create needs to say so,
	 * and the implementation should enforce the restriction.]
	 * </p>
	 */
	public static final String FILE_EXTENSION = "server";

	public static final int AUTO_PUBLISH_DEFAULT = 0;
	public static final int AUTO_PUBLISH_DISABLE = 1;
	public static final int AUTO_PUBLISH_OVERRIDE = 2;

	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 static final String MODULE_LIST = "modules";
	protected static final String PROP_DISABLED_PERFERRED_TASKS = "disabled-preferred-publish-tasks";
	protected static final String PROP_ENABLED_OPTIONAL_TASKS = "enabled-optional-publish-tasks";
	public static final String PROP_AUTO_PUBLISH_TIME = "auto-publish-time";
	public static final String PROP_AUTO_PUBLISH_SETTING = "auto-publish-setting";

	protected static final char[] INVALID_CHARS = new char[] {'\\', '/', ':', '*', '?', '"', '<', '>', '|', '\0', '@', '&'};

	protected IServerType serverType;
	protected ServerDelegate delegate;
	protected ServerBehaviourDelegate behaviourDelegate;

	protected IRuntime runtime;
	protected IFolder configuration;

	// the list of modules that are to be published to the server
	protected List modules;

	// transient fields
	protected transient String mode = ILaunchManager.RUN_MODE;
	protected transient int serverState = STATE_UNKNOWN;
	protected transient int serverSyncState;
	protected transient boolean serverRestartNeeded;

	protected transient Map moduleState = new HashMap();
	protected transient Map modulePublishState = new HashMap();
	protected transient Map moduleRestartState = new HashMap();

	protected transient IStatus serverStatus;
	protected transient Map moduleStatus = new HashMap();

	protected transient ServerPublishInfo publishInfo;
	protected transient AutoPublishThread autoPublishThread;

/*	private static final String[] stateStrings = new String[] {
		"unknown", "starting", "started", "started_debug",
		"stopping", "stopped", "started_unsupported", "started_profile"
	};*/

	// publish listeners
	protected transient List publishListeners;

	// Server listeners
	protected transient ServerNotificationManager notificationManager;

	public class AutoPublishThread extends Thread {
		public boolean stop;
		public int time = 0;

		public AutoPublishThread() {
			super("Automatic Publishing");
		}

		public void run() {
			Trace.trace(Trace.FINEST, "Auto-publish thread starting for " + Server.this + " - " + time + "s");
			if (stop)
				return;
			
			try {
				sleep(time * 1000);
			} catch (Exception e) {
				// ignore
			}
			
			if (stop)
				return;
			
			Trace.trace(Trace.FINEST, "Auto-publish thread publishing " + Server.this);
			
			if (getServerState() != IServer.STATE_STARTED)
				return;
			
			PublishServerJob publishJob = new PublishServerJob(Server.this, IServer.PUBLISH_AUTO, false);
			publishJob.schedule();
		}
	}

	public class ResourceChangeJob extends ChainedJob {
		private IModule module;

		public ResourceChangeJob(IModule module, IServer server) {
			super(NLS.bind(Messages.jobUpdateServer, server.getName()), server);
			this.module = module;
			
			if (module.getProject() == null)
				setRule(new ServerSchedulingRule(server));
			else {
				ISchedulingRule[] rules = new ISchedulingRule[2];
				IResourceRuleFactory ruleFactory = ResourcesPlugin.getWorkspace().getRuleFactory();
				rules[0] = ruleFactory.createRule(module.getProject());
				rules[1] = new ServerSchedulingRule(server);
				setRule(MultiRule.combine(rules));
			}
		}

		protected IModule getModule() {
			return module;
		}

		protected IStatus run(IProgressMonitor monitor) {
			final boolean[] changed = new boolean[1];
			final List modules2 = new ArrayList();
			
			IModuleVisitor visitor = new IModuleVisitor() {
				public boolean visit(IModule[] module2) {
					modules2.add(module2);
					
					int size = module2.length;
					IModule m = module2[size - 1];
					if (m.getProject() == null)
						return true;
					
					if (getModule().equals(m)) {
						if (hasPublishedResourceDelta(module2)) {
							changed[0] = true;
							setModulePublishState(module2, IServer.PUBLISH_STATE_INCREMENTAL);
						}
					}
					return true;
				}
			};
			
			visit(visitor, null);
			
			if (getServerPublishInfo().hasStructureChanged(modules2))
				setServerPublishState(IServer.PUBLISH_STATE_INCREMENTAL);
			
			if (!changed[0])
				return Status.OK_STATUS;
			
			if (getServerState() != IServer.STATE_STOPPED && behaviourDelegate != null)
				behaviourDelegate.handleResourceChange();
			
			if (getServerState() == IServer.STATE_STARTED)
				autoPublish();
			
			return Status.OK_STATUS;
		}
	}
	
	private static final Comparator PUBLISH_OPERATION_COMPARTOR = new Comparator() {
      public int compare(Object leftOp, Object rightOp) {
          PublishOperation left = (PublishOperation) leftOp;
          PublishOperation right = (PublishOperation) rightOp;
          if (left.getOrder() > right.getOrder())
              return 1;
          if (left.getOrder() < right.getOrder())
              return -1;
          return 0;
      }
	};

	// 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 createWorkingCopy() {
		return new ServerWorkingCopy(this); 
	}

	public boolean isWorkingCopy() {
		return false;
	}

	protected void deleteFromMetadata() {
		ResourceManager.getInstance().removeServer(this);
	}

	protected void saveToMetadata(IProgressMonitor monitor) {
		super.saveToMetadata(monitor);
		ResourceManager.getInstance().addServer(this);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.wst.server.core.IServerAttributes#getRuntime()
	 */
	public IRuntime getRuntime() {
		return runtime;
	}

	protected String getRuntimeId() {
		return getAttribute(RUNTIME_ID, (String) null);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.wst.server.core.IServerAttributes#getServerConfiguration()
	 */
	public IFolder getServerConfiguration() {
		return configuration;
	}

	protected ServerDelegate getDelegate(IProgressMonitor monitor) {
		if (delegate != null || serverType == null)
			return delegate;
		
		synchronized (this) {
			if (delegate == null) {
				try {
					long time = System.currentTimeMillis();
					delegate = ((ServerType) serverType).createServerDelegate();
					InternalInitializer.initializeServerDelegate(delegate, Server.this, monitor);
					Trace.trace(Trace.PERFORMANCE, "Server.getDelegate(): <" + (System.currentTimeMillis() - time) + "> " + getServerType().getId());
				} catch (Throwable t) {
					Trace.trace(Trace.SEVERE, "Could not create delegate " + toString(), t);
				}
			}
		}
		return delegate;
	}

	protected ServerBehaviourDelegate getBehaviourDelegate(IProgressMonitor monitor) {
		if (behaviourDelegate != null || serverType == null)
			return behaviourDelegate;
		
		synchronized (this) {
			if (behaviourDelegate == null) {
				try {
					long time = System.currentTimeMillis();
					behaviourDelegate = ((ServerType) serverType).createServerBehaviourDelegate();
					InternalInitializer.initializeServerBehaviourDelegate(behaviourDelegate, Server.this, monitor);
					Trace.trace(Trace.PERFORMANCE, "Server.getBehaviourDelegate(): <" + (System.currentTimeMillis() - time) + "> " + getServerType().getId());
					
					if (getServerState() == IServer.STATE_STARTED)
						autoPublish();
				} catch (Throwable t) {
					Trace.trace(Trace.SEVERE, "Could not create behaviour delegate " + toString(), t);
				}
			}
		}
		return behaviourDelegate;
	}

	public void dispose() {
		if (delegate != null) {
			delegate.dispose();
			delegate = null;
		}
		if (behaviourDelegate != null) {
			behaviourDelegate.dispose();
			behaviourDelegate = null;
		}
	}

	public String getHost() {
		return getAttribute(PROP_HOSTNAME, "localhost");
	}

	public int getAutoPublishTime() {
		return getAttribute(PROP_AUTO_PUBLISH_TIME, -1);
	}

	public int getAutoPublishSetting() {
		return getAttribute(PROP_AUTO_PUBLISH_SETTING, AUTO_PUBLISH_DEFAULT);
	}

	/**
    * Returns a list of id (String) of preferred publish operations that will not be run
    * during publish.
    * 
    * @return a list of publish operation ids
    */
	public List getDisabledPreferredPublishOperationIds() {
		return getAttribute(PROP_DISABLED_PERFERRED_TASKS, EMPTY_LIST);		
	}

	/**
    * Returns a list of id (String) of optional publish operations that are enabled to 
    * be run during publish.
    * 
    * @return a list of publish operation ids
    */
	public List getEnabledOptionalPublishOperationIds() {
		return getAttribute(PROP_ENABLED_OPTIONAL_TASKS, EMPTY_LIST);
	}

	/**
	 * Returns the current state of the server. (see SERVER_XXX constants)
	 *
	 * @return int
	 */
	public int getServerState() {
		return serverState;
	}

	public String getMode() {
		return mode;
	}

	public void setServerState(int 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) {
		if (listener == null)
			throw new IllegalArgumentException("Module cannot be null");
		Trace.trace(Trace.LISTENERS, "Adding server listener " + listener + " to " + this);
		getServerNotificationManager().addListener(listener);
	}

	/**
	 * Add a listener to this server with the given event mask.
	 *
	 * @param listener org.eclipse.wst.server.model.IServerListener
	 * @param eventMask to limit listening to certain types of events
	 */
	public void addServerListener(IServerListener listener, int eventMask) {
		if (listener == null)
			throw new IllegalArgumentException("Module cannot be null");
		Trace.trace(Trace.LISTENERS, "Adding server listener " + listener + " to " + this + " with eventMask " + eventMask);
		getServerNotificationManager().addListener(listener, eventMask);
	}

	/**
	 * Remove a listener from this server.
	 *
	 * @param listener org.eclipse.wst.server.model.IServerListener
	 */
	public void removeServerListener(IServerListener listener) {
		if (listener == null)
			throw new IllegalArgumentException("Module cannot be null");
		Trace.trace(Trace.LISTENERS, "Removing server listener " + listener + " from " + this);
		getServerNotificationManager().removeListener(listener);
	}
	
	/**
	 * Fire a server listener restart state change event.
	 */
	protected void fireRestartStateChangeEvent() {
		Trace.trace(Trace.LISTENERS, "->- Firing server restart change event: " + getName() + " ->-");
		
		if (notificationManager == null || notificationManager.hasListenerEntries())
			return;
		
		notificationManager.broadcastChange(
			new ServerEvent(ServerEvent.SERVER_CHANGE | ServerEvent.RESTART_STATE_CHANGE, this, getServerState(), 
				getServerPublishState(), getServerRestartState()));
	}

	/**
	 * Fire a server listener state change event.
	 */
	protected void fireServerStateChangeEvent() {
		Trace.trace(Trace.LISTENERS, "->- Firing server state change event: " + getName() + ", " + getServerState() + " ->-");
	
		if (notificationManager == null || notificationManager.hasListenerEntries())
			return;
	
		notificationManager.broadcastChange(
			new ServerEvent(ServerEvent.SERVER_CHANGE | ServerEvent.STATE_CHANGE, this, getServerState(), 
				getServerPublishState(), getServerRestartState()));
	}

	/**
	 * Fire a server listener module state change event.
	 */
	protected void fireModuleStateChangeEvent(IModule[] module) {
		Trace.trace(Trace.LISTENERS, "->- Firing module state change event: " + getName() + ", " + getServerState() + " ->-");
		
		if (notificationManager == null || notificationManager.hasListenerEntries())
			return;
		
		notificationManager.broadcastChange(
			new ServerEvent(ServerEvent.MODULE_CHANGE | ServerEvent.STATE_CHANGE, this, module, getModuleState(module), 
				getModulePublishState(module), getModuleRestartState(module)));
	}

	/**
	 * Fire a server listener module publish state change event.
	 */
	protected void fireModulePublishStateChangeEvent(IModule[] module) {
		Trace.trace(Trace.LISTENERS, "->- Firing module publish state change event: " + getName() + ", " + getServerState() + " ->-");
		
		if (notificationManager == null || notificationManager.hasListenerEntries())
			return;
		
		notificationManager.broadcastChange(
			new ServerEvent(ServerEvent.MODULE_CHANGE | ServerEvent.PUBLISH_STATE_CHANGE, this, module, getModuleState(module), 
				getModulePublishState(module), getModuleRestartState(module)));
	}

	/**
	 * Fire a server listener module state change event.
	 */
	protected void fireModuleRestartChangeEvent(IModule[] module) {
		Trace.trace(Trace.LISTENERS, "->- Firing module restart change event: " + getName() + ", " + getServerState() + " ->-");
		
		if (notificationManager == null || notificationManager.hasListenerEntries())
			return;
		
		notificationManager.broadcastChange(
			new ServerEvent(ServerEvent.MODULE_CHANGE | ServerEvent.RESTART_STATE_CHANGE, this, module, getModuleState(module), 
				getModulePublishState(module), getModuleRestartState(module)));
	}

	public void setMode(String m) {
		if (m == mode)
			return;

		this.mode = m;
		fireServerStateChangeEvent();
	}

	public void setModuleState(IModule[] module, int state) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		int oldState = getModuleState(module);
		if (oldState == state)
			return;
		
		Integer in = new Integer(state);
		moduleState.put(getKey(module), in);
		fireModuleStateChangeEvent(module);
	}

	public void setModulePublishState(IModule[] module, int state) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		int oldState = getModulePublishState(module);
		if (oldState == state)
			return;
		
		Integer in = new Integer(state);
		if (state == -1)
			modulePublishState.remove(getKey(module));
		modulePublishState.put(getKey(module), in);
		fireModulePublishStateChangeEvent(module);
	}

	public void setModuleRestartState(IModule[] module, boolean r) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		boolean oldState = getModuleRestartState(module);
		if (oldState == r)
			return;
		
		Boolean b = new Boolean(r);
		moduleState.put(getKey(module), b);
		fireModuleRestartChangeEvent(module);
	}

	protected void handleModuleProjectChange(IModule module) {
		Trace.trace(Trace.FINEST, "> handleDeployableProjectChange() " + this + " " + module);
		
		// check for duplicate jobs already waiting and don't create a new one
		Job[] jobs = Job.getJobManager().find(ServerPlugin.PLUGIN_ID);
		if (jobs != null) {
			int size = jobs.length;
			for (int i = 0; i < size; i++) {
				if (jobs[i] instanceof ResourceChangeJob) {
					ResourceChangeJob rcj = (ResourceChangeJob) jobs[i];
					if (rcj.getServer().equals(this) && rcj.getModule().equals(module) && rcj.getState() == Job.WAITING)
						return;
				}
			}
		}
		
		ResourceChangeJob job = new ResourceChangeJob(module, this);
		job.setSystem(true);
		job.setPriority(Job.BUILD);
		job.schedule();
		
		Trace.trace(Trace.FINEST, "< handleDeployableProjectChange()");
	}

	protected void stopAutoPublish() {
		if (autoPublishThread == null)
			return;
		
		autoPublishThread.stop = true;
		autoPublishThread.interrupt();
		autoPublishThread = null;
	}

	/**
	 * Reset automatic publish thread if it is running and start a new
	 * thread if automatic publishing is currently enabled.
	 */
	protected void autoPublish() {
		stopAutoPublish();
		
		if (getAutoPublishSetting() == AUTO_PUBLISH_DISABLE)
			return;
		
		int time = 0;
		if (getAutoPublishSetting() == AUTO_PUBLISH_DEFAULT) {
			ServerPreferences pref = ServerPreferences.getInstance();
			boolean local = SocketUtil.isLocalhost(getHost());
			if (local && pref.getAutoPublishLocal())
				time = pref.getAutoPublishLocalTime();
			else if (!local && pref.getAutoPublishRemote())
				time = pref.getAutoPublishRemoteTime();
		} else
			time = getAutoPublishTime();
		
		if (time > 0) {
			autoPublishThread = new AutoPublishThread();
			autoPublishThread.time = time;
			autoPublishThread.setPriority(Thread.MIN_PRIORITY + 1);
			autoPublishThread.start();
		}
	}

	private ServerNotificationManager getServerNotificationManager() {
		if (notificationManager == null) {
			notificationManager = new ServerNotificationManager();
		}
		return notificationManager;
	}

	/**
	 * Returns the configuration's sync state.
	 *
	 * @return int
	 */
	public int getServerPublishState() {
		return serverSyncState;
	}

	/**
	 * Sets the configuration sync state.
	 *
	 * @param state int
	 */
	public void setServerPublishState(int state) {
		if (state == serverSyncState)
			return;
		serverSyncState = state;
		firePublishStateChange();
	}

	/**
	 * Adds a publish listener to this server.
	 * Has no effect if an identical listener is already registered.
	 *
	 * @param listener the publish listener
	 * @see #removePublishListener(IPublishListener)
	 */
	public void addPublishListener(IPublishListener listener) {
		if (listener == null)
			throw new IllegalArgumentException("Listener cannot be null");
		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.
	 * Has no effect if the listener is not registered.
	 *
	 * @param listener the publish listener
	 * @see #addPublishListener(IPublishListener)
	 */
	public void removePublishListener(IPublishListener listener) {
		if (listener == null)
			throw new IllegalArgumentException("Listener cannot be null");
		Trace.trace(Trace.LISTENERS, "Removing publish listener " + listener + " from " + this);

		if (publishListeners != null)
			publishListeners.remove(listener);
	}
	
	/**
	 * Fire a publish start event.
	 */
	private void firePublishStarted() {
		Trace.trace(Trace.FINEST, "->- Firing publish started event ->-");
	
		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);
			} 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 stop event.
	 *
	 * @param status publishing status
	 */
	private void firePublishFinished(IStatus 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.
	 */
	protected void firePublishStateChange() {
		Trace.trace(Trace.FINEST, "->- Firing publish state change event ->-");
		
		if (notificationManager == null || notificationManager.hasListenerEntries())
			return;
		
		notificationManager.broadcastChange(
			new ServerEvent(ServerEvent.SERVER_CHANGE | ServerEvent.PUBLISH_STATE_CHANGE, this, getServerState(), 
					getServerPublishState(), getServerRestartState()));
	}

	/**
	 * Fire a publish state change event.
	 */
	protected void firePublishStateChange(IModule[] module) {
		Trace.trace(Trace.FINEST, "->- Firing publish state change event: " + module + " ->-");
	
		if (notificationManager == null || notificationManager.hasListenerEntries())
			return;
	
		notificationManager.broadcastChange(
			new ServerEvent(ServerEvent.MODULE_CHANGE | ServerEvent.PUBLISH_STATE_CHANGE, this, module, getModuleState(module), 
				getModulePublishState(module), getModuleRestartState(module)));
	}

	/**
	 * Returns true if the server is in a state that it can
	 * be published to.
	 *
	 * @return boolean
	 */
	public IStatus canPublish() {
		if (getServerType() == null)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorMissingAdapter, null);
		
		// can't publish if the server is starting or stopping
		int state = getServerState();
		if (state == STATE_STARTING || state == STATE_STOPPING)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorPublishStarting, null);
		
		// can't publish if there is no configuration
		if (getServerType().hasServerConfiguration() && configuration == null)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorPublishNoConfiguration, null);
		
		return Status.OK_STATUS;
	}

	/**
	 * Returns true if the server should be published to. This is <code>true</code> when the server
	 * can be published to and the server's publish state or any module's publish state is not
	 * PUBLISH_STATE_NONE. 
	 * 
	 * @return boolean
	 */
	public boolean shouldPublish() {
		if (!canPublish().isOK())
			return false;
		
		if (getServerPublishState() != PUBLISH_STATE_NONE)
			return true;
		
		final boolean[] publish = new boolean[1];
		
		visit(new IModuleVisitor() {
			public boolean visit(IModule[] module) {
				if (getModulePublishState(module) != PUBLISH_STATE_NONE) {
					publish[0] = true;
					return false;
				}
				return true;
			}
		}, null);
		
		return publish[0];
	}

	/**
	 * Returns true if the server should be restarted. This is <code>true</code> when the server
	 * can be restarted and the server's restart state or any module's restart states is not
	 * false. 
	 * 
	 * @return boolean
	 */
	public boolean shouldRestart() {
		if (!canPublish().isOK())
			return false;
		
		if (getServerRestartState())
			return true;
		
		final boolean[] publish = new boolean[1];
		
		visit(new IModuleVisitor() {
			public boolean visit(IModule[] module) {
				if (getModuleRestartState(module)) {
					publish[0] = true;
					return false;
				}
				return true;
			}
		}, null);
		
		return publish[0];
	}

	public ServerPublishInfo getServerPublishInfo() {
		if (publishInfo == null) {
			publishInfo = PublishInfo.getInstance().getServerPublishInfo(this);
		}
		return publishInfo;
	}

	/*
	 * Publish to the server using the progress monitor. The result of the
	 * publish operation is returned as an IStatus.
	 */
	public IStatus publish(final int kind, IProgressMonitor monitor) {
		if (getServerType() == null)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorMissingAdapter, null);

		// check what is out of sync and publish
		if (getServerType().hasServerConfiguration() && configuration == null)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorNoConfiguration, null);
		
		// make sure that the delegate is loaded and the server state is correct
		loadAdapter(ServerBehaviourDelegate.class, monitor);
		
		if (((ServerType)getServerType()).startBeforePublish() && (getServerState() == IServer.STATE_STOPPED)) {
			try {
				synchronousStart(ILaunchManager.RUN_MODE, monitor);
			} catch (CoreException ce) {
				Trace.trace(Trace.SEVERE, "Error starting server", ce);
				return ce.getStatus();
			}
		}
		
		long time = System.currentTimeMillis();
		firePublishStarted();
		IStatus status = doPublish(kind, monitor);
		firePublishFinished(status);
		Trace.trace(Trace.PERFORMANCE, "Server.publish(): <" + (System.currentTimeMillis() - time) + "> " + getServerType().getId());
		return status;
	}

	protected IStatus doPublish(int kind, IProgressMonitor monitor) {
		Trace.trace(Trace.FINEST, "-->-- Publishing to server: " + toString() + " -->--");
		
		stopAutoPublish();
		
		try {
			getServerPublishInfo().startCaching();
			IStatus status = getBehaviourDelegate(monitor).publish(kind, monitor);
			
			final List modules2 = new ArrayList();
			visit(new IModuleVisitor() {
				public boolean visit(IModule[] module) {
					if (getModulePublishState(module) == IServer.PUBLISH_STATE_NONE)
						getServerPublishInfo().fill(module);
					
					modules2.add(module);
					return true;
				}
			}, monitor);
			
			getServerPublishInfo().removeDeletedModulePublishInfo(this, modules2);
			getServerPublishInfo().clearCache();
			getServerPublishInfo().save();
			
			return status;
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error calling delegate publish() " + toString(), e);
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorPublishing, e);
		}
	}

	/**
	 * Returns the publish tasks that have been targetted to this server.
	 * These tasks should be run during publishing and will be initialized
	 * with a task model.
	 * 
	 * @param kind one of the IServer.PUBLISH_XX constants
	 * @param moduleList a list of modules
	 * @param kindList one of the IServer publish change constants
	 * @return a possibly empty array of IOptionalTasks
	 */
	public PublishOperation[] getTasks(int kind, List moduleList, List kindList) {
		List tasks = new ArrayList();
		
		String serverTypeId = getServerType().getId();
		
		IPublishTask[] publishTasks = ServerPlugin.getPublishTasks();
		if (publishTasks != null) {
			List enabledTasks = getEnabledOptionalPublishOperationIds();
			List disabledTasks = getDisabledPreferredPublishOperationIds();
			
			TaskModel taskModel = new TaskModel();
			taskModel.putObject(TaskModel.TASK_SERVER, this);
			
			int size = publishTasks.length;
			for (int i = 0; i < size; i++) {
				IPublishTask task = publishTasks[i];
				if (task.supportsType(serverTypeId)) {
					PublishOperation[] tasks2 = task.getTasks(this, kind, moduleList, kindList);
					if (tasks2 != null) {
						int size2 = tasks2.length;
						for (int j = 0; j < size2; j++) {
							if (tasks2[j].getKind() == PublishOperation.REQUIRED) {
								tasks.add(tasks2[j]);
								tasks2[j].setTaskModel(taskModel);
							} else if (tasks2[j].getKind() == PublishOperation.PREFERRED) {
								String opId = getPublishOperationId(tasks2[j]);
								if (!disabledTasks.contains(opId)) {
									tasks.add(tasks2[j]);
									tasks2[j].setTaskModel(taskModel);
								}
							} else if (tasks2[j].getKind() == PublishOperation.OPTIONAL) {
								String opId = getPublishOperationId(tasks2[j]);
								if (enabledTasks.contains(opId)) {
									tasks.add(tasks2[j]);
									tasks2[j].setTaskModel(taskModel);
								}
							}
						}
					}
				}
			}
		}
		
		Collections.sort(tasks, PUBLISH_OPERATION_COMPARTOR);
		
		return (PublishOperation[]) tasks.toArray(new PublishOperation[tasks.size()]);
	}

	/**
	 * Returns all publish tasks that have been targetted to this server type.
	 * The tasks will not be initialized with a task model. 
	 * 
	 * @param moduleList a list of modules
	 * @return an array of publish operations
	 */
	public PublishOperation[] getAllTasks(List moduleList) {
		String serverTypeId = getServerType().getId();
		if (serverTypeId == null)
			return new PublishOperation[0];
		
		List tasks = new ArrayList();
		
		IPublishTask[] publishTasks = ServerPlugin.getPublishTasks();
		if (publishTasks != null) {
			int size = publishTasks.length;
			for (int i = 0; i < size; i++) {
				IPublishTask task = publishTasks[i];
				if (task.supportsType(serverTypeId)) {
					PublishOperation[] tasks2 = task.getTasks(this, moduleList);
					tasks.addAll(Arrays.asList(tasks2));
				}
			}
		}
		
		Collections.sort(tasks, PUBLISH_OPERATION_COMPARTOR);
		
		return (PublishOperation[])tasks.toArray(new PublishOperation[tasks.size()]);
	}
	
	public String getPublishOperationId(PublishOperation op) {
		return getId()+"|"+op.getLabel();
	}
	
	public List getAllModules() {
		final List moduleList = new ArrayList();
		
		IModuleVisitor visitor = new IModuleVisitor() {
			public boolean visit(IModule[] module) {
				if (!moduleList.contains(module))
					moduleList.add(module);
				return true;
			}
		};
		
		visit(visitor, null);
		
		return moduleList;
	}

	/*
	 * Returns the module resources that have been published.
	 * 
	 * @see ServerBehaviourDelegate.getPublishedResources(IModule[])
	 */
	public IModuleResource[] getResources(IModule[] module) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		return getServerPublishInfo().getResources(module);
	}

	/*
	 * Returns the module resources that have been published.
	 * 
	 * @see ServerBehaviourDelegate.getPublishedResources(IModule[])
	 */
	public IModuleResource[] getPublishedResources(IModule[] module) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		return getServerPublishInfo().getModulePublishInfo(module).getResources();
	}

	/*
	 * Returns the delta of the current module resources that have been
	 * published compared to the current state of the module.
	 * 
	 * @see ServerBehaviourDelegate.getPublishedResourceDelta(IModule[])
	 */
	public IModuleResourceDelta[] getPublishedResourceDelta(IModule[] module) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		return getServerPublishInfo().getDelta(module);
	}

	/*
	 * Returns the delta of the current module resources that have been
	 * published compared to the current state of the module.
	 * 
	 * @see ServerBehaviourDelegate.getPublishedResourceDelta(IModule[])
	 */
	public boolean hasPublishedResourceDelta(IModule[] module) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		return getServerPublishInfo().hasDelta(module);
	}

	/**
	 * @see IServer#getAdapter(Class)
	 */
	public Object getAdapter(Class adapter) {
		if (delegate != null) {
			if (adapter.isInstance(delegate))
				return delegate;
		}
		if (behaviourDelegate != null) {
			if (adapter.isInstance(behaviourDelegate))
				return behaviourDelegate;
		}
		return Platform.getAdapterManager().getAdapter(this, adapter);
	}

	/**
	 * @see IServer#loadAdapter(Class, IProgressMonitor)
	 */
	public Object loadAdapter(Class adapter, IProgressMonitor monitor) {
		getDelegate(monitor);
		if (adapter.isInstance(delegate))
			return delegate;
		
		getBehaviourDelegate(monitor);
		if (adapter.isInstance(behaviourDelegate))
			return behaviourDelegate;
		
		return Platform.getAdapterManager().loadAdapter(this, adapter.getName());
	}

	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 mode2
	 * @return status
	 */
	public IStatus canStart(String mode2) {
		if (getServerType() == null)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorMissingAdapter, null);
		
		int state = getServerState();
		if (state != STATE_STOPPED && state != STATE_UNKNOWN)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.canStartErrorState, null);
		
		if (!getServerType().supportsLaunchMode(mode2))
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorLaunchMode, null);
		
		return Status.OK_STATUS;
	}

	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) {
				// ignore
			}
		}
		
		return null;
	}

	public void setupLaunchConfiguration(ILaunchConfigurationWorkingCopy workingCopy, IProgressMonitor monitor) {
		try {
			getBehaviourDelegate(monitor).setupLaunchConfiguration(workingCopy, monitor);
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error calling delegate setupLaunchConfiguration() " + toString(), e);
		}
	}

	/**
	 * Return the launch configuration for this server. If one does not exist, it
	 * will be created if "create" is true, and otherwise will return <code>null</code>.
	 * Will return <code>null</code> if this server type has no associated launch
	 * configuration type (i.e. the server cannot be started).
	 * 
	 * @param create <code>true</code> if a new launch configuration should be
	 *    created if there are none already
	 * @param monitor a progress monitor, or <code>null</code> if progress
	 *    reporting and cancellation are not desired
	 * @return the launch configuration, or <code>null</code> if there was no
	 *    existing launch configuration and <code>create</code> was false
	 * @throws CoreException
	 */
	public ILaunchConfiguration getLaunchConfiguration(boolean create, IProgressMonitor monitor) throws CoreException {
		if (getServerType() == null)
			return null;
		
		ILaunchConfigurationType launchConfigType = ((ServerType) getServerType()).getLaunchConfigurationType();
		if (launchConfigType == null)
			return null;
		
		ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
		ILaunchConfiguration[] launchConfigs = null;
		try {
			launchConfigs = launchManager.getLaunchConfigurations(launchConfigType);
		} catch (CoreException e) {
			// ignore
		}
		
		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)) {
						final ILaunchConfigurationWorkingCopy wc = launchConfigs[i].getWorkingCopy();
						setupLaunchConfiguration(wc, monitor);
						if (wc.isDirty()) {
							final ILaunchConfiguration[] lc = new ILaunchConfiguration[1];
							Job job = new Job("Saving launch configuration") {
								protected IStatus run(IProgressMonitor monitor2) {
									try {
										lc[0] = wc.doSave();
									} catch (CoreException ce) {
										Trace.trace(Trace.SEVERE, "Error configuring launch", ce);
									}
									return Status.OK_STATUS;
								}
							};
							job.setSystem(true);
							job.schedule();
							try {
								job.join();
							} catch (Exception e) {
								Trace.trace(Trace.SEVERE, "Error configuring launch", e);
							}
							if (job.getState() != Job.NONE) {
								job.cancel();
								lc[0] = wc.doSave();
							}
							
							return lc[0];
						}
						return launchConfigs[i];
					}
				} catch (CoreException e) {
					Trace.trace(Trace.SEVERE, "Error configuring launch", e);
				}
			}
		}
		
		if (!create)
			return null;
		
		// create a new launch configuration
		String launchName = getValidLaunchConfigurationName(getName());
		launchName = launchManager.generateUniqueLaunchConfigurationNameFrom(launchName); 
		ILaunchConfigurationWorkingCopy wc = launchConfigType.newInstance(null, launchName);
		wc.setAttribute(SERVER_ID, getId());
		setupLaunchConfiguration(wc, monitor);
		return wc.doSave();
	}

	protected String getValidLaunchConfigurationName(String s) {
		if (s == null || s.length() == 0)
			return "1";
		int size = INVALID_CHARS.length;
		for (int i = 0; i < size; i++) {
			s = s.replace(INVALID_CHARS[i], '_');
		}
		return s;
	}

	/**
	 * @see IServer#start(String, IProgressMonitor)
	 */
	public void start(String mode2, IProgressMonitor monitor) throws CoreException {
		Trace.trace(Trace.FINEST, "Starting server: " + toString() + ", launchMode: " + mode2);
	
		// make sure that the delegate is loaded and the server state is correct
		loadAdapter(ServerBehaviourDelegate.class, monitor);
		
		try {
			ILaunchConfiguration launchConfig = getLaunchConfiguration(true, monitor);
			ILaunch launch = launchConfig.launch(mode2, monitor); // , true); - causes workspace lock
			Trace.trace(Trace.FINEST, "Launch: " + launch);
		} catch (CoreException e) {
			Trace.trace(Trace.SEVERE, "Error starting server " + toString(), e);
			throw e;
		}
	}

	/**
	 * Clean up any metadata associated with the server, typically in preparation for
	 * deletion.
	 */
	protected void deleteMetadata() {
		deleteLaunchConfigurations();
		ServerPlugin.getInstance().removeTempDirectory(getId());
		PublishInfo.getInstance().removeServerPublishInfo(this);
	}

	/**
	 * Clean up any old launch configurations with the current server's id.
	 */
	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) {
					// ignore
				}
			}
		} catch (Exception e) {
			// ignore
		}
	}

	/**
	 * @see IServer#canRestart(String)
	 */
	public IStatus canRestart(String mode2) {
		if (getServerType() == null)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorMissingAdapter, null);
		
		if (!getServerType().supportsLaunchMode(mode2))
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorLaunchMode, null);

		int state = getServerState();
		if (state == STATE_STARTED)
			return Status.OK_STATUS;
		
		return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorRestartNotStarted, null);
	}

	/**
	 * Returns the current restart state of the server. This
	 * implementation will always return false when the server
	 * is stopped.
	 *
	 * @return boolean
	 */
	public boolean getServerRestartState() {
		if (getServerState() == STATE_STOPPED)
			return false;
		return serverRestartNeeded;
	}

	/**
	 * Sets the server restart state.
	 *
	 * @param state boolean
	 */
	public synchronized void setServerRestartState(boolean state) {
		if (state == serverRestartNeeded)
			return;
		serverRestartNeeded = state;
		fireRestartStateChangeEvent();
	}

	/**
	 * @see IServer#restart(String, IProgressMonitor)
	 */
	public void restart(final String mode2, final IProgressMonitor monitor) {
		if (getServerType() == null || getServerState() == STATE_STOPPED)
			return;
	
		Trace.trace(Trace.FINEST, "Restarting server: " + getName());
	
		try {
			try {
				getBehaviourDelegate(null).restart(mode2);
				return;
			} catch (CoreException ce) {
				Trace.trace(Trace.SEVERE, "Error calling delegate restart() " + toString());
			}
		
			// add listener to start it as soon as it is stopped
			addServerListener(new IServerListener() {
				public void serverChanged(ServerEvent event) {
					int eventKind = event.getKind();
					IServer server = event.getServer();
					if (eventKind == (ServerEvent.SERVER_CHANGE | ServerEvent.STATE_CHANGE)) {
						if (server.getServerState() == STATE_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) {
										// ignore
									}
									ServerType st = (ServerType) getServerType();
									if (st.startBeforePublish()) {
										try {
											Server.this.start(mode2, monitor);
										} catch (Exception e) {
											Trace.trace(Trace.SEVERE, "Error while restarting server", e);
										}
									}
									if (ServerPreferences.getInstance().isAutoPublishing() && shouldPublish()) {
										publish(PUBLISH_INCREMENTAL, null);
									}
									if (getServerState() != IServer.STATE_STARTED) {
										try {
											Server.this.start(mode2, monitor);
										} 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(false);
		} 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 IStatus canStop() {
		if (getServerType() == null)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorMissingAdapter, null);
		
		if (getServerState() == STATE_STOPPED)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorStopAlreadyStopped, null);
		
		if (!getServerType().supportsLaunchMode(getMode()))
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorLaunchMode, null);
		
		return Status.OK_STATUS;
	}

	/**
	 * @see IServer#stop(boolean)
	 */
	public void stop(boolean force) {
		if (getServerState() == STATE_STOPPED)
			return;
		
		Trace.trace(Trace.FINEST, "Stopping server: " + toString());
		
		try {
			getBehaviourDelegate(null).stop(force);
		} catch (Throwable t) {
			Trace.trace(Trace.SEVERE, "Error calling delegate stop() " + toString(), t);
		}
	}

	/**
	 * @see IServer#start(String, IOperationListener)
	 */
	public void start(String mode2, IOperationListener listener2) {
		if (getServerType() == null)
			return;
		
		Trace.trace(Trace.FINEST, "synchronousStart 1");
		final Object mutex = new Object();
		
		// make sure that the delegate is loaded and the server state is correct
		loadAdapter(ServerBehaviourDelegate.class, null);
		
		// add listener to the server
		IServerListener listener = new IServerListener() {
			public void serverChanged(ServerEvent event) {
				int eventKind = event.getKind();
				IServer server = event.getServer();
				if (eventKind == (ServerEvent.SERVER_CHANGE | ServerEvent.STATE_CHANGE)) {
					int state = server.getServerState();
					if (state == IServer.STATE_STARTED || state == IServer.STATE_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();
		
		final int serverTimeout = ((ServerType) getServerType()).getStartTimeout();
		if (serverTimeout > 0) {
			Thread thread = new Thread("Server start timeout") {
				public void run() {
					try {
						Thread.sleep(serverTimeout);
						if (!timer.alreadyDone) {
							// notify waiter
							synchronized (mutex) {
								Trace.trace(Trace.FINEST, "start notify timeout");
								if (!timer.alreadyDone)
									timer.timeout = true;
								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
		IProgressMonitor monitor = new NullProgressMonitor();
		try {
			start(mode2, monitor);
		} catch (CoreException e) {
			removeServerListener(listener);
			timer.alreadyDone = true;
			listener2.done(e.getStatus());
			return;
		}
		if (monitor.isCanceled()) {
			removeServerListener(listener);
			timer.alreadyDone = true;
			listener2.done(Status.CANCEL_STATUS);
			return;
		}
		
		Trace.trace(Trace.FINEST, "synchronousStart 3");
		
		// wait for it! wait for it! ...
		synchronized (mutex) {
			try {
				while (!timer.timeout && !(getServerState() == IServer.STATE_STARTED || getServerState() == IServer.STATE_STOPPED))
					mutex.wait();
			} catch (Exception e) {
				Trace.trace(Trace.SEVERE, "Error waiting for server start", e);
			}
			timer.alreadyDone = true;
		}
		removeServerListener(listener);
		
		if (timer.timeout) {
			listener2.done(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorStartTimeout, new String[] { getName(), (serverTimeout / 1000) + "" }), null));
			stop(false);
			return;
		}
		
		if (getServerState() == IServer.STATE_STOPPED) {
			listener2.done(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorStartFailed, getName()), null));
			return;
		}
		
		Trace.trace(Trace.FINEST, "synchronousStart 4");
		listener2.done(Status.OK_STATUS);
	}

	public void synchronousStart(String mode2, IProgressMonitor monitor) throws CoreException {
		if (getServerType() == null)
			return;
		
		Trace.trace(Trace.FINEST, "synchronousStart 1");
		
		// make sure that the delegate is loaded and the server state is correct
		loadAdapter(ServerBehaviourDelegate.class, monitor);
		
		final boolean[] notified = new boolean[1];
		
		monitor = ProgressUtil.getMonitorFor(monitor);
		
		// add listener to the server
		IServerListener listener = new IServerListener() {
			public void serverChanged(ServerEvent event) {
				int eventKind = event.getKind();
				IServer server = event.getServer();
				if (eventKind == (ServerEvent.SERVER_CHANGE | ServerEvent.STATE_CHANGE)) {
					int state = server.getServerState();
					if (state == IServer.STATE_STARTED || state == IServer.STATE_STOPPED) {
						// notify waiter
						synchronized (notified) {
							try {
								Trace.trace(Trace.FINEST, "synchronousStart notify");
								notified[0] = true;
								notified.notifyAll();
							} catch (Exception e) {
								Trace.trace(Trace.SEVERE, "Error notifying server start", e);
							}
						}
					}
				}
			}
		};
		addServerListener(listener);
		
		final int serverTimeout = ((ServerType) getServerType()).getStartTimeout();
		class Timer {
			boolean timeout;
			boolean alreadyDone;
		}
		final Timer timer = new Timer();
		
		final IProgressMonitor monitor2 = monitor;
		Thread thread = new Thread("Synchronous Server Start") {
			public void run() {
				try {
					int totalTimeout = serverTimeout;
					if (totalTimeout < 0)
						totalTimeout = 1;
					boolean userCancelled = false;
					int retryPeriod = 2500;
					while (!notified[0] && totalTimeout > 0 && !userCancelled && !timer.alreadyDone) {
						Thread.sleep(retryPeriod);
						if (serverTimeout > 0)
							totalTimeout -= retryPeriod;
						if (!notified[0] && !timer.alreadyDone && monitor2.isCanceled()) {
							// user cancelled - set the server state to stopped
							userCancelled = true;
							setServerState(IServer.STATE_STOPPED);
							// notify waiter
							synchronized (notified) {
								Trace.trace(Trace.FINEST, "synchronousStart user cancelled.");
								notified[0] = true;
								notified.notifyAll();
							}
						}
					}
					if (!userCancelled && !timer.alreadyDone && !notified[0]) {
						// notify waiter
						synchronized (notified) {
							Trace.trace(Trace.FINEST, "synchronousStart notify timeout");
							if (!timer.alreadyDone && totalTimeout < 0)
								timer.timeout = true;
							notified[0] = true;
							notified.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(mode2, monitor);
		} catch (CoreException e) {
			removeServerListener(listener);
			timer.alreadyDone = true;
			throw e;
		}
		if (monitor.isCanceled()) {
			removeServerListener(listener);
			timer.alreadyDone = true;
			return;
		}
		
		Trace.trace(Trace.FINEST, "synchronousStart 3");
		
		// wait for it! wait for it! ...
		synchronized (notified) {
			try {
				while (!notified[0] && !monitor.isCanceled() && !timer.timeout
						&& !(getServerState() == IServer.STATE_STARTED || getServerState() == IServer.STATE_STOPPED)) {
					notified.wait();
				}
			} catch (Exception e) {
				Trace.trace(Trace.SEVERE, "Error waiting for server start", e);
			}
			timer.alreadyDone = true;
		}
		removeServerListener(listener);
		
		if (timer.timeout) {
			stop(false);
			throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorStartTimeout, new String[] { getName(), (serverTimeout / 1000) + "" }), null));
		}
		
		if (getServerState() == IServer.STATE_STOPPED)
			throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorStartFailed, getName()), null));
		
		Trace.trace(Trace.FINEST, "synchronousStart 4");
	}

	/*
	 * @see IServer#synchronousRestart(String, IProgressMonitor)
	 */
	public void synchronousRestart(String mode2, IProgressMonitor monitor) throws CoreException {
		synchronousStop(true);
		synchronousStart(mode2, monitor);
	}
	
	/*
	 * @see IServer#restart(String, IOperationListener)
	 */
	public void restart(String mode2, IOperationListener listener) {
		if (getServerType() == null)
			return;
		
		if (getServerState() == STATE_STOPPED)
			return;
	
		Trace.trace(Trace.FINEST, "Restarting server: " + getName());
	
		try {
			final IOperationListener listener2 = listener;
			IServerListener curListener = new IServerListener() {
				public void serverChanged(ServerEvent event) {
					int eventKind = event.getKind();
					IServer server = event.getServer();
					if (eventKind == (ServerEvent.SERVER_CHANGE | ServerEvent.STATE_CHANGE)) {
						if (server.getServerState() == STATE_STARTED) {
							server.removeServerListener(this);
							listener2.done(Status.OK_STATUS);
						}
					}
				}
			};
			try {
				addServerListener(curListener);
				getBehaviourDelegate(null).restart(mode2);
				return;
			} catch (CoreException ce) {
				Trace.trace(Trace.SEVERE, "Error calling delegate restart() " + toString());
				removeServerListener(curListener);
			}
		
			final String mode3 = mode2;
			// add listener to start it as soon as it is stopped
			addServerListener(new IServerListener() {
				public void serverChanged(ServerEvent event) {
					int eventKind = event.getKind();
					IServer server = event.getServer();
					if (eventKind == (ServerEvent.SERVER_CHANGE | ServerEvent.STATE_CHANGE)) {
						if (server.getServerState() == STATE_STOPPED) {
							server.removeServerListener(this);

							// restart in a quarter second (give other listeners a chance
							// to hear the stopped message)
							Thread t = new Thread("Restart thread") {
								public void run() {
									try {
										Thread.sleep(250);
									} catch (Exception e) {
										// ignore
									}
									ServerType st = (ServerType) getServerType();
									if (st.startBeforePublish()) {
										try {
											Server.this.start(mode3, listener2);
										} catch (Exception e) {
											Trace.trace(Trace.SEVERE, "Error while restarting server", e);
										}
									}
									if (ServerPreferences.getInstance().isAutoPublishing() && shouldPublish()) {
										publish(PUBLISH_INCREMENTAL, null);
									}
									if (getServerState() != IServer.STATE_STARTED) {
										try {
											Server.this.start(mode3, listener2);
										} 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(false);
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error restarting server", e);
			listener.done(null);
		}
	}
	
	/*
	 * @see IServer#stop(boolean, IOperationListener)
	 */
	public void stop(boolean force, IOperationListener listener2) {
		if (getServerType() == null)
			return;
		
		if (getServerState() == IServer.STATE_STOPPED)
			return;
		
		final Object mutex = new Object();
	
		// add listener to the server
		IServerListener listener = new IServerListener() {
			public void serverChanged(ServerEvent event) {
				int eventKind = event.getKind();
				IServer server = event.getServer();
				if (eventKind == (ServerEvent.SERVER_CHANGE | ServerEvent.STATE_CHANGE)) {
					int state = server.getServerState();
					if (Server.this == server && state == IServer.STATE_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();
		
		final int serverTimeout = ((ServerType) getServerType()).getStopTimeout();
		if (serverTimeout > 0) {
			Thread thread = new Thread("Server stop timeout") {
				public void run() {
					try {
						Thread.sleep(serverTimeout);
						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(force);
	
		// wait for it! wait for it!
		synchronized (mutex) {
			try {
				while (!timer.timeout && getServerState() != IServer.STATE_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("%errorStartFailed", getName()), null));
		else
			timer.alreadyDone = true;
		
		if (getServerState() == IServer.STATE_STOPPED)
			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorStartFailed", getName()), null));*/
		listener2.done(Status.OK_STATUS);
	}

	/*
	 * @see IServer#synchronousStop()
	 */
	public void synchronousStop(boolean force) {
		if (getServerType() == null)
			return;
		
		if (getServerState() == IServer.STATE_STOPPED)
			return;
		
		final Object mutex = new Object();
	
		// add listener to the server
		IServerListener listener = new IServerListener() {
			public void serverChanged(ServerEvent event) {
				int eventKind = event.getKind();
				IServer server = event.getServer();
				if (eventKind == (ServerEvent.SERVER_CHANGE | ServerEvent.STATE_CHANGE)) {
					int state = server.getServerState();
					if (Server.this == server && state == IServer.STATE_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();
		
		final int serverTimeout = ((ServerType) getServerType()).getStopTimeout();
		if (serverTimeout > 0) {
			Thread thread = new Thread("Synchronous server stop") {
				public void run() {
					try {
						Thread.sleep(serverTimeout);
						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(force);
	
		// wait for it! wait for it!
		synchronized (mutex) {
			try {
				while (!timer.timeout && getServerState() != IServer.STATE_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("%errorStartFailed", getName()), null));
		else
			timer.alreadyDone = true;
		
		if (getServerState() == IServer.STATE_STOPPED)
			throw new CoreException(new Status(IStatus.ERROR, ServerCore.PLUGIN_ID, 0, ServerPlugin.getResource("%errorStartFailed", 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 synchronousRestartModule(final IModule[] module, IProgressMonitor monitor) throws CoreException {
		Trace.trace(Trace.FINEST, "synchronousModuleRestart 1");

		final Object mutex = new Object();
	
		// add listener to the module
		IServerListener listener = new IServerListener() {
			public void serverChanged(ServerEvent event) {
				int eventKind = event.getKind();
				IServer server = event.getServer();
				if (eventKind == (ServerEvent.MODULE_CHANGE | ServerEvent.STATE_CHANGE)) {
					int state = server.getModuleState(module);
					if (state == IServer.STATE_STARTED || state == IServer.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 {
			getBehaviourDelegate(null).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.STATE_STARTED || getModuleState(module) == IServer.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, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorModuleRestartFailed, getName()), null));
		timer.alreadyDone = true;
		
		if (getModuleState(module) == IServer.STATE_STOPPED)
			throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.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) {
		resolve();
	}

	protected void resolve() {
		IServerType oldServerType = serverType;
		String serverTypeId = getAttribute("server-type-id", (String)null);
		if (serverTypeId != null)
			serverType = ServerCore.findServerType(serverTypeId);
		else
			serverType = null;
		if (serverType != null && !serverType.equals(oldServerType))
			serverState = ((ServerType)serverType).getInitialState();
		
		String runtimeId = getAttribute(RUNTIME_ID, (String)null);
		if (runtimeId != null)
			runtime = ServerCore.findRuntime(runtimeId);
		
		String configPath = getAttribute(CONFIGURATION_ID, (String)null);
		configuration = null;
		if (configPath != null)
			configuration = ResourcesPlugin.getWorkspace().getRoot().getFolder(new Path(configPath));
	}

	protected void setInternal(ServerWorkingCopy wc) {
		map = new HashMap(wc.map);
		configuration = wc.configuration;
		runtime = wc.runtime;
		serverSyncState = wc.serverSyncState;
		//restartNeeded = wc.restartNeeded;
		serverType = wc.serverType;
		modules = wc.modules;
		
		// can never modify the following properties via the working copy
		//serverState = wc.serverState;
		delegate = wc.delegate;
		
		if (getServerState() == IServer.STATE_STARTED)
			autoPublish();
	}

	protected void saveState(IMemento memento) {
		if (serverType != null)
			memento.putString("server-type", serverType.getId());
		
		if (configuration != null)
			memento.putString(CONFIGURATION_ID, configuration.getFullPath().toString());
		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(null).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, IProgressMonitor monitor) {
		if (getServerType() == null)
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorMissingAdapter, null);
		
		if ((add == null || add.length == 0) && (remove == null || remove.length == 0))
			throw new IllegalArgumentException("Add and remove cannot both be null/empty");
		
		if (add != null && add.length > 0) {
			int size = add.length;
			for (int i = 0; i < size; i++) {
				IModuleType moduleType = add[i].getModuleType(); 
				if (!ServerUtil.isSupportedModule(getServerType().getRuntimeType().getModuleTypes(), moduleType))
					return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCannotAddModule,
							new Object[] { moduleType.getName(), moduleType.getVersion() }), null);
			}
		}
		
		try {
			return getDelegate(monitor).canModifyModules(add, remove);
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error calling delegate canModifyModules() " + toString(), e);
			return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, "", null);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.wst.server.core.IServer#getModules()
	 */
	public IModule[] getModules() {
		if (modules == null) {
			// convert from attribute
			List list = getAttribute(MODULE_LIST, (List) null);
			if (list == null)
				list = new ArrayList(1);
			
			modules = new ArrayList(list.size() + 1);
			Iterator iterator = list.iterator();
			while (iterator.hasNext()) {
				String moduleId = (String) iterator.next();
				String name = "<unknown>";
				int index = moduleId.indexOf("::");
				if (index > 0) {
					name = moduleId.substring(0, index);
					moduleId = moduleId.substring(index+2);
				}
				
				String moduleTypeId = null;
				String moduleTypeVersion = null;
				index = moduleId.indexOf("::");
				if (index > 0) {
					int index2 = moduleId.indexOf("::", index+1);
					moduleTypeId = moduleId.substring(index+2, index2);
					moduleTypeVersion = moduleId.substring(index2+2);
					moduleId = moduleId.substring(0, index);
				}
				
				IModule module = ServerUtil.getModule(moduleId);
				if (module == null) {
					IModuleType moduleType = null;
					if (moduleTypeId != null)
						moduleType = new ModuleType(moduleTypeId, moduleTypeVersion);
					module = new DeletedModule(moduleId, name, moduleType);
				}
				if (module != null)
					modules.add(module);
			}
		}
		
		IModule[] modules2 = new IModule[modules.size()];
		modules.toArray(modules2);
		return modules2;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.wst.server.core.IServer#getModuleState()
	 */
	public int getModuleState(IModule[] module) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		try {
			Integer in = (Integer) moduleState.get(getKey(module));
			if (in != null)
				return in.intValue();
		} catch (Exception e) {
			// ignore
		}
		return STATE_UNKNOWN;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.wst.server.core.IServer#getModuleState()
	 */
	public int getModulePublishState(IModule[] module) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		try {
			Integer in = (Integer) modulePublishState.get(getKey(module));
			if (in != null)
				return in.intValue();
		} catch (Exception e) {
			// ignore
		}
		return PUBLISH_STATE_UNKNOWN;
	}

	/*
	 * @see IServer#getChildModule(IModule[])
	 */
	public IModule[] getChildModules(IModule[] module, IProgressMonitor monitor) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		try {
			int i = module.length - 1;
			if (module[i].getProject() == null || !module[i].getProject().isAccessible())
				return null;
			
			ServerDelegate sd = getDelegate(monitor);
			if (sd == null)
				return null;
			IModule[] children = sd.getChildModules(module);
			if (children != null && children.length == 1 && children[0].equals(module[module.length - 1]))
				return null;
			return children;
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error calling delegate getChildModules() " + toString(), e);
			return null;
		}
	}

	/*
	 * @see IServer#getRootModules(IModule)
	 */
	public IModule[] getRootModules(IModule module, IProgressMonitor monitor) throws CoreException {
		if (module == null)
			throw new IllegalArgumentException("Module cannot be null");
		try {
			return getDelegate(monitor).getRootModules(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;
		}
	}
	
	/**
	 * Returns whether the given module can be restarted.
	 *
	 * @param module the module
	 * @param monitor
	 * @return <code>true</code> if the given module can be
	 *    restarted, and <code>false</code> otherwise
	 */
	public IStatus canControlModule(IModule[] module, IProgressMonitor monitor) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		try {
			ServerBehaviourDelegate bd = getBehaviourDelegate(monitor);
			if (bd == null)
				return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorRestartModule, null);
			boolean b = bd.canControlModule(module);
			if (b)
				return Status.OK_STATUS;
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error calling delegate canRestartRuntime() " + toString(), e);
		}
		return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorRestartModule, null);
	}

	/**
	 * Check if the given module is in sync on the server. It should
	 * return true if the module should be restarted (is out of
	 * sync) or false if the module does not need to be restarted.
	 *
	 * @param module org.eclipse.wst.server.core.model.IModule
	 * @return boolean
	 */
	public boolean getModuleRestartState(IModule[] module) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		try {
			Boolean b = (Boolean) moduleRestartState.get(getKey(module));
			if (b != null)
				return b.booleanValue();
		} catch (Exception e) {
			// ignore
		}
		return false;
	}

	/*
	 * @see IServer#startModule(IModule[], IOperationListener)
	 */
	public void startModule(IModule[] module, IOperationListener listener) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty or empty");
		try {
			getBehaviourDelegate(null).startModule(module, null);
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error calling delegate restartModule() " + toString(), e);
		}
	}

	/*
	 * @see IServer#stopModule(IModule[], IOperationListener)
	 */
	public void stopModule(IModule[] module, IOperationListener listener) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty or empty");
		try {
			getBehaviourDelegate(null).stopModule(module, null);
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error calling delegate restartModule() " + toString(), e);
		}
	}

	/*
	 * @see IServer#restartModule(IModule[], IOperationListener, IProgressMonitor)
	 */
	public void restartModule(IModule[] module, IOperationListener listener) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		try {
			getBehaviourDelegate(null).stopModule(module, null);
			getBehaviourDelegate(null).startModule(module, null);
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error calling delegate restartModule() " + toString(), e);
		}
	}

	/**
	 * Returns an array of IServerPorts that this server has.
	 * 
	 * @param monitor
	 * @return a possibly empty array of servers ports
	 */
	public ServerPort[] getServerPorts(IProgressMonitor monitor) {
		try {
			return getDelegate(monitor).getServerPorts();
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error calling delegate getServerPorts() " + toString(), e);
			return null;
		}
	}

	/**
	 * Visit all the modules in the server with the given module visitor.
	 * 
	 * @param visitor the visitor
	 * @param monitor a progress monitor, or <code>null</code> if progress
	 *    reporting and cancellation are not desired
	 */
	public void visit(IModuleVisitor visitor, IProgressMonitor monitor) {
		if (visitor == null)
			throw new IllegalArgumentException("Visitor cannot be null");
		IModule[] modules2 = getModules();
		if (modules2 != null) { 
			int size = modules2.length;
			for (int i = 0; i < size; i++) {
				if (!visitModule(new IModule[] { modules2[i] }, visitor, monitor))
					return;
			}
		}
	}

	/**
	 * Returns true to keep visiting, and false to stop.
	 * 
	 * @param monitor a progress monitor, or <code>null</code> if progress
	 *    reporting and cancellation are not desired
	 */
	private boolean visitModule(IModule[] module, IModuleVisitor visitor, IProgressMonitor monitor) {
		if (module == null)
			return true;
		
		if (!visitor.visit(module))
			return false;
		
		IModule[] children = getChildModules(module, monitor);
		if (children != null) {
			int size = children.length;
			for (int i = 0; i < size; i++) {
				IModule[] module2 = new IModule[module.length + 1];
				System.arraycopy(module, 0, module2, 0, module.length);
				module2[module.length] = children[i];
				
				if (!visitModule(module2, visitor, monitor))
					return false;
			}
		}
		
		return true;
	}

	protected String getKey(IModule[] module) {
		StringBuffer sb = new StringBuffer();
		
		if (module != null) {
			int size = module.length;
			for (int i = 0; i < size; i++) {
				if (i != 0)
					sb.append("#");
				sb.append(module[i].getId());
			}
		}
		
		return sb.toString();
	}

	public void setModuleStatus(IModule[] module, IStatus status) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		moduleStatus.put(getKey(module), status);
		//fireServerModuleStateChangeEvent(module);
	}

	public IStatus getModuleStatus(IModule[] module) {
		if (module == null || module.length == 0)
			throw new IllegalArgumentException("Module cannot be null or empty");
		try {
			return (IStatus) moduleStatus.get(getKey(module));
		} catch (Exception e) {
			return null;
		}
	}

	public void setServerStatus(IStatus status) {
		serverStatus = status;
		//fireServerStateChangeEvent();
	}

	public IStatus getServerStatus() {
		return serverStatus;
	}

	/**
	 * Switch the server's location between the workspace and .metadata.
	 * 
	 * @param server a server
	 * @param monitor a progress monitor
	 * @throws CoreException if something goes wrong
	 */
	public static void switchLocation(Server server, IProgressMonitor monitor) throws CoreException {
		IFile file = server.getFile();
		ServerWorkingCopy wc = (ServerWorkingCopy) server.createWorkingCopy();
		server.delete();
		if (file == null) {
			IProject project = ServerType.getServerProject();
			file = ServerUtil.getUnusedServerFile(project, wc);
			wc.setFile(file);
			server.file = file;
		} else {
			wc.setFile(null);
			server.file = null;
		}
		wc.save(true, monitor);
	}

	/**
	 * Returns the current state of the server (see SERVER_XXX constants) after
	 * refreshing the state of the server. The only difference between this method
	 * and the method without a progress monitor is that this method may cause
	 * plugin loading and not return immediately. However, the server will always
	 * be updated and in sync, so the IServer.STATE_UNKNOWN state should never be
	 * returned.
	 * 
	 * @param monitor
	 * @return the server state
	 */
	public int getServerState(IProgressMonitor monitor) {
		loadAdapter(ServerBehaviourDelegate.class, monitor);
		return getServerState();
	}
}