blob: 307389e5769e9c8e5c346c7660a9b601398be35b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - Initial API and implementation
*******************************************************************************/
package org.eclipse.wst.server.core.model;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.*;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerWorkingCopy;
import org.eclipse.wst.server.core.TaskModel;
import org.eclipse.wst.server.core.internal.*;
/**
* A server delegate provides the implementation for various
* generic and server-type-specific operations for a specific type of server.
* A server delegate is specified by the
* <code>class</code> attribute of a <code>serverTypes</code> extension.
* <p>
* When the server instance needs to be given a delegate, the delegate class
* specified for the server type is instantiated with a 0-argument constructor
* and primed with <code>delegate.initialize(((IServerState)server)</code>,
* which it is expected to hang on to. Later, when
* <code>delegate.dispose()</code> is called as the server instance is
* being discarded, the delegate is expected to let go of the server instance.
* </p>
* <p>
* Server delegates may keep state in instance fields, but that state is
* transient and will not be persisted across workbench sessions.
* </p>
* <p>
* This abstract class is intended to be extended only by clients
* to extend the <code>serverTypes</code> extension point.
* </p>
*
* @see IServer
* @see IServerWorkingCopy
* @since 1.0
*/
public abstract class ServerBehaviourDelegate {
private Server server;
/**
* Publish kind constant (value 0) for no change.
*
* @see #publishModule(int, int, IModule[], IProgressMonitor)
*/
public static final int NO_CHANGE = 0;
/**
* Publish kind constant (value 1) for added resources.
*
* @see #publishModule(int, int, IModule[], IProgressMonitor)
*/
public static final int ADDED = 1;
/**
* Publish kind constant (value 2) for changed resources.
*
* @see #publishModule(int, int, IModule[], IProgressMonitor)
*/
public static final int CHANGED = 2;
/**
* Publish kind constant (value 3) for removed resources.
*
* @see #publishModule(int, int, IModule[], IProgressMonitor)
*/
public static final int REMOVED = 3;
/**
* Delegates must have a public 0-arg constructor.
*/
public ServerBehaviourDelegate() {
// do nothing
}
/**
* Initializes this server delegate with its life-long server instance.
* <p>
* This method is called by the server core framework.
* Clients should never call this method.
* </p>
*
* @param newServer the server instance
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
*/
final void initialize(Server newServer, IProgressMonitor monitor) {
server = newServer;
initialize(monitor);
}
/**
* Initializes this server delegate. This method gives delegates a chance
* to do their own initialization.
* <p>
* If the server state is initially unknown, this method should attempt
* to connect to the server and update the state. On servers where the
* state may change, this is also an excellent place to create a background
* thread that will constantly ping the server (or have a listener) to
* update the server state as changes occur.
* </p>
* <p>
* This method is called by the server core framework.
* Clients should never call this method.
* </p>
*
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
*/
protected void initialize(IProgressMonitor monitor) {
// do nothing
}
/**
* Returns the server that this server delegate corresponds to.
*
* @return the server
*/
public final IServer getServer() {
return server;
}
/**
* Sets the current state of this server.
*
* @param state the current state of the server, one of the state
* constants defined by {@link IServer}
* @see IServer#getServerState()
*/
protected final void setServerState(int state) {
server.setServerState(state);
}
/**
* Sets the ILaunchManager mode that the server is running in. The server
* implementation will automatically return <code>null</code> to clients
* when the server is stopped, so you only need to update the mode when
* it changes.
*
* @param mode the mode in which a server is running, one of the mode constants
* defined by {@link ILaunchManager}
*/
protected final void setMode(String mode) {
server.setMode(mode);
}
/**
* Sets the server restart state.
*
* @param state <code>true</code> if the server needs to be restarted,
* and <code>false</code> otherwise
*/
protected final void setServerRestartState(boolean state) {
server.setServerRestartState(state);
}
/**
* Sets the server publish state.
*
* @param state the current publish state of the server, one of the
* publish constants defined by {@link IServer}
*/
protected final void setServerPublishState(int state) {
server.setServerPublishState(state);
}
/**
* Hook to fire an event when a module state changes.
*
* @param module the module
* @param state the current state of the module, one of the state
* constants defined by {@link IServer}
*/
protected final void setModuleState(IModule[] module, int state) {
server.setModuleState(module, state);
}
/**
* Sets the module publish state.
*
* @param module the module
* @param state the current publish state of the module, one of the
* publish constants defined by {@link IServer}
*/
protected final void setModulePublishState(IModule[] module, int state) {
server.setModulePublishState(module, state);
}
/**
* Sets the module restart state.
*
* @param module the module
* @param state <code>true</code> if the module needs to be restarted,
* and <code>false</code> otherwise
*/
protected final void setModuleRestartState(IModule[] module, boolean state) {
server.setModuleRestartState(module, state);
}
/**
* Sets the server's external modules.
*
* @param modules the root external module
*/
protected final void setExternalModules(IModule[] modules) {
server.setExternalModules(modules);
}
/**
* Creates an external module instance with the given static information. An external module is a unit of "content"
* that is already published to the server, and that doesn't exist in the workspace
*
* @param id the module id
* @param name the module name
* @param type the module type id
* @param version the module version id
* @param moduleDelegate the ModuleDelegate which will act as a helper of the module
* @return a module instance
*/
protected final IModule createExternalModule(String id, String name, String type, String version, ModuleDelegate moduleDelegate) {
IModule module = new ExternalModule(id, name, type, version, moduleDelegate);
setModulePublishState(new IModule [] {module}, IServer.PUBLISH_STATE_NONE);
return module;
}
/**
* Disposes of this server delegate.
* <p>
* This method is called by the web server core framework.
* Clients should never call this method.
* </p>
* <p>
* Implementations are expected to let go of the delegate's reference
* to the server, deregister listeners, etc.
* </p>
*/
public void dispose() {
// do nothing
}
/**
* Methods called to notify that publishing is about to begin.
* This allows the server to open a connection to the server
* or get any global information ready.
* <p>
* This method is called by the server core framework,
* in response to a call to <code>IServer.publish()</code>.
* Clients should never call this method.
* </p>
*
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @throws CoreException if there is a problem starting the publish
*/
protected void publishStart(IProgressMonitor monitor) throws CoreException {
// do nothing
}
/**
* Publish the server.
* <p>
* This method is called by the server core framework,
* in response to a call to <code>IServer.publish()</code>.
* Clients should never call this method.
* </p>
*
* @param kind one of the IServer.PUBLISH_XX constants. Valid values are
* <ul>
* <li><code>PUBLISH_FULL</code>- indicates a full publish.</li>
* <li><code>PUBLISH_INCREMENTAL</code>- indicates a incremental publish.
* <li><code>PUBLISH_AUTO</code>- indicates an automatic incremental publish.</li>
* <li><code>PUBLISH_CLEAN</code>- indicates a clean request. Clean throws
* out all state and cleans up the module on the server before doing a
* full publish.
* </ul>
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @throws CoreException if there is a problem publishing the server
*/
protected void publishServer(int kind, IProgressMonitor monitor) throws CoreException {
// do nothing
}
/**
* Publish a single module to the server.
* <p>
* This method is called by the server core framework,
* in response to a call to <code>IServer.publish()</code>.
* Clients should never call this method directly.
* </p>
* <p>
* If the deltaKind is IServer.REMOVED, the module may have been completely
* deleted and does not exist anymore. In this case, a dummy module (with the
* correct id) will be passed to this method.
* </p>
* <p>
* It is recommended that clients implementing this method be responsible for
* setting the module state.
* </p>
*
* @param kind one of the IServer.PUBLISH_XX constants. Valid values are:
* <ul>
* <li><code>PUBLISH_FULL</code>- indicates a full publish.</li>
* <li><code>PUBLISH_INCREMENTAL</code>- indicates a incremental publish.
* <li><code>PUBLISH_AUTO</code>- indicates an automatic incremental publish.</li>
* <li><code>PUBLISH_CLEAN</code>- indicates a clean request. Clean throws
* out all state and cleans up the module on the server before doing a
* full publish.
* </ul>
* @param module the module to publish
* @param deltaKind one of the IServer publish change constants. Valid values are:
* <ul>
* <li><code>ADDED</code>- indicates the module has just been added to the server
* and this is the first publish.
* <li><code>NO_CHANGE</code>- indicates that nothing has changed in the module
* since the last publish.</li>
* <li><code>CHANGED</code>- indicates that the module has been changed since
* the last publish. Call <code>getPublishedResourceDelta()</code> for
* details of the change.
* <li><code>REMOVED</code>- indicates the module has been removed and should be
* removed/cleaned up from the server.
* </ul>
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @throws CoreException if there is a problem publishing the module
*/
protected void publishModule(int kind, int deltaKind, IModule[] module, IProgressMonitor monitor) throws CoreException {
// by default, assume the module has published successfully.
// this will update the publish state and delta correctly
setModulePublishState(module, IServer.PUBLISH_STATE_NONE);
}
/**
* Methods called to notify that publishing has finished.
* The server can close any open connections to the server
* and do any cleanup operations.
* <p>
* This method is called by the server core framework,
* in response to a call to <code>IServer.publish()</code>.
* Clients should never call this method.
* </p>
*
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @throws CoreException if there is a problem stopping the publish
*/
protected void publishFinish(IProgressMonitor monitor) throws CoreException {
// do nothing
}
/**
* Configure the given launch configuration to start this server. This method is called whenever
* the server is started to ensure that the launch configuration is accurate and up to date.
* This method should not blindly update the launch configuration in cases where the user has
* access to change the launch configuration by hand.
*
* @param workingCopy a launch configuration working copy
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @throws CoreException if there is an error setting up the configuration
*/
public void setupLaunchConfiguration(ILaunchConfigurationWorkingCopy workingCopy, IProgressMonitor monitor) throws CoreException {
// do nothing
}
/**
* Restart this server. The server should use the server
* listener to notify progress. It must use the same debug
* flags as was originally passed into the start() method.
*
* This method is used if there is a quick/better way to restart
* the server. If it throws a CoreException, the normal stop/start
* actions will be used.
*
* @param launchMode the mode to restart in, one of the mode constants
* defined by {@link ILaunchManager}
* @throws CoreException if there was a problem restarting
*/
public void restart(String launchMode) throws CoreException {
throw new CoreException(new Status(IStatus.WARNING, ServerPlugin.PLUGIN_ID, 0, "Restart not supported", null));
}
/**
* Returns whether the given module can be restarted.
* <p>
* [issue: It's unclear whether this operations is guaranteed to be fast
* or whether it could involve communication with any actual
* server. If it is not fast, the method should take a progress
* monitor.]
* </p>
*
* @param module the module
* @return <code>true</code> if the given module can be
* restarted, and <code>false</code> otherwise
*/
public boolean canControlModule(IModule[] module) {
return false;
}
/**
* Starts the given module on the server. See the specification of
* {@link IServer#startModule(IModule[], IServer.IOperationListener)}
* for further details.
* <p>
* The implementation should update the module sync state and fire
* an event for the module.
* </p>
* <p>
* This method will throw an exception if the module does not exist on
* the server.
* </p>
* <p>
* [issue: Since this method is asynchronous, is there
* any need for the progress monitor?]
* </p>
*
* @param module the module to be started
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @exception CoreException if an error occurs while trying to restart the module
*/
public void startModule(IModule[] module, IProgressMonitor monitor) throws CoreException {
// do nothing
}
/**
* Stops the given module on the server. See the specification of
* {@link IServer#stopModule(IModule[], IServer.IOperationListener)}
* for further details.
* <p>
* The implementation should update the module sync state and fire
* an event for the module.
* </p>
* <p>
* This method will throw an exception if the module does not exist on
* the server.
* </p>
* <p>
* [issue: Since this method is asynchronous, is there
* any need for the progress monitor?]
* </p>
*
* @param module the module to be stopped
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @exception CoreException if an error occurs while trying to restart the module
*/
public void stopModule(IModule[] module, IProgressMonitor monitor) throws CoreException {
// do nothing
}
/**
* Restarts the given module on the server. See the specification of
* {@link IServer#restartModule(IModule[], IServer.IOperationListener)}
* for further details.
* <p>
* The implementation should update the module sync state and fire
* an event for the module.
* </p>
* <p>
* This method will throw an exception if the module does not exist on
* the server.
* </p>
* <p>
* [issue: Since this method is asynchronous, is there
* any need for the progress monitor?]
* </p>
*
* @param module the module to be stopped
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @exception CoreException if an error occurs while trying to restart the module
*/
public void restartModule(IModule[] module, IProgressMonitor monitor) throws CoreException {
stopModule(module, monitor);
startModule(module, monitor);
}
/**
* Shuts down and stops this server. The server should return from this method
* quickly and use the server listener to notify shutdown progress.
* <p>
* If force is <code>false</code>, it will attempt to stop the server
* normally/gracefully. If force is <code>true</code>, then the server
* process will be terminated any way that it can.
* </p>
* <p>
* [issue: There is no way to communicate failure to the
* client. Given that this operation can go awry, there probably
* should be a mechanism that allows failing async operations
* to be diagnosed.]
* </p>
* @param force <code>true</code> to kill the server, or <code>false</code>
* to stop normally
*/
public abstract void stop(boolean force);
/**
* Returns the current module resources.
*
* @param module the module
* @return an array containing the module's resources
*/
protected IModuleResource[] getResources(IModule[] module) {
return server.getResources(module);
}
/**
* Returns the module resources that have been published to the server.
*
* <p>
* If the module has just been added to the server, an empty list will
* be returned. If the module has never existed on the server, a CoreException
* will be thrown.
* </p>
*
* @param module the module
* @return an array containing the published module resource
*/
protected IModuleResource[] getPublishedResources(IModule[] module) {
return server.getPublishedResources(module);
}
/**
* Returns the delta of the current module resources that have been
* published compared to the current state of the module.
*
* @param module the module
* @return an array containing the publish resource delta
*/
protected IModuleResourceDelta[] getPublishedResourceDelta(IModule[] module) {
return server.getPublishedResourceDelta(module);
}
/**
* Returns a temporary directory that the requester can use
* throughout it's lifecycle. This is primary to be used by
* servers for working directories, server specific
* files, etc.
* <p>
* This method directory will return the same directory on
* each use of the workbench. 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 may want to request the temp directory on
* startup if it wants to store files there. In any case, the
* server should have a backup plan to refill the directory
* in case it has been deleted since last use.</p>
*
* @return a temporary directory
*/
protected IPath getTempDirectory() {
return server.getTempDirectory();
}
/**
* Set a global status on the server.
*
* @param status the status
*/
protected final void setServerStatus(IStatus status) {
server.setServerStatus(status);
}
/**
* Set a status on a specific module.
*
* @param module the module
* @param status the status
*/
protected final void setModuleStatus(IModule[] module, IStatus status) {
server.setModuleStatus(module, status);
}
/**
* Publish to the server.
*
* @param kind the publish kind
* @param modules
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @param info
* @throws CoreException
*/
public void publish(int kind, List<IModule[]> modules, IProgressMonitor monitor, IAdaptable info) throws CoreException {
info2 = info;
IStatus status = publish(kind, monitor);
if (status != null && status.getSeverity() != IStatus.OK && status.getSeverity() != IStatus.CANCEL)
throw new CoreException(status);
}
private IAdaptable info2;
/*public void publish2(int kind, List<IModule[]> modules, IProgressMonitor monitor, IAdaptable info) throws CoreException {
Trace.trace(Trace.FINEST, "-->-- Publishing to server: " + toString() + " -->--");
if (getServer().getServerType().hasRuntime() && getServer().getRuntime() == null)
throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorPublishNoRuntime, null));
final List<IModule[]> moduleList = getAllModules();
addRemovedModules(moduleList, null);
PublishOperation[] tasks = getTasks(kind, moduleList, null);
int size = 2000 + 3500 * moduleList.size() + 500 * tasks.length;
monitor = ProgressUtil.getMonitorFor(monitor);
monitor.beginTask(NLS.bind(Messages.publishing, getServer().getName()), size);
MultiStatus tempMulti = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, "", null);
if (monitor.isCanceled())
return;
try {
Trace.trace(Trace.FINEST, "Starting publish");
publishStart(ProgressUtil.getSubMonitorFor(monitor, 1000));
if (monitor.isCanceled())
return;
// execute publishers
executePublishers(kind, modules, monitor, info);
if (monitor.isCanceled())
return;
// publish the server
publishServer(kind, ProgressUtil.getSubMonitorFor(monitor, 1000));
if (monitor.isCanceled())
return;
// publish modules
IspublishModules(kind, moduleList, monitor);
if (monitor.isCanceled())
return;
monitor.done();
} catch (CoreException ce) {
Trace.trace(Trace.INFO, "CoreException publishing to " + toString(), ce);
throw ce;
} catch (Exception e) {
Trace.trace(Trace.SEVERE, "Error publishing to " + toString(), e);
tempMulti.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorPublishing, e));
} finally {
// end the publishing
try {
publishFinish(ProgressUtil.getSubMonitorFor(monitor, 500));
} catch (CoreException ce) {
Trace.trace(Trace.INFO, "CoreException publishing to " + toString(), ce);
tempMulti.add(ce.getStatus());
} catch (Exception e) {
Trace.trace(Trace.SEVERE, "Error stopping publish to " + toString(), e);
tempMulti.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorPublishing, e));
}
}
Trace.trace(Trace.FINEST, "--<-- Done publishing --<--");
if (tempMulti.getChildren().length == 1)
throw new CoreException(tempMulti.getChildren()[0]);
MultiStatus multi = null;
if (tempMulti.getSeverity() == IStatus.OK)
return;
else if (tempMulti.getSeverity() == IStatus.INFO)
multi = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, Messages.publishingStatusInfo, null);
else if (tempMulti.getSeverity() == IStatus.WARNING)
multi = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, Messages.publishingStatusWarning, null);
else if (tempMulti.getSeverity() == IStatus.ERROR)
multi = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, Messages.publishingStatusError, null);
if (multi != null)
multi.addAll(tempMulti);
}*/
/**
* Publish to the server.
*
* @param kind the publish kind
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @return the publish status
*/
public IStatus publish(int kind, IProgressMonitor monitor) {
Trace.trace(Trace.FINEST, "-->-- Publishing to server: " + toString() + " -->--");
if (getServer().getServerType().hasRuntime() && getServer().getRuntime() == null)
return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorPublishNoRuntime, null);
final List<IModule[]> moduleList = getAllModules();
final List<Integer> deltaKindList = new ArrayList<Integer>();
Iterator iterator = moduleList.iterator();
while (iterator.hasNext()) {
IModule[] module = (IModule[]) iterator.next();
if (hasBeenPublished(module)) {
IModule m = module[module.length - 1];
if ((m.getProject() != null && !m.getProject().isAccessible())
|| getPublishedResourceDelta(module).length == 0)
deltaKindList.add(new Integer(ServerBehaviourDelegate.NO_CHANGE));
else
deltaKindList.add(new Integer(ServerBehaviourDelegate.CHANGED));
} else
deltaKindList.add(new Integer(ServerBehaviourDelegate.ADDED));
}
addRemovedModules(moduleList, null);
while (deltaKindList.size() < moduleList.size())
deltaKindList.add(new Integer(ServerBehaviourDelegate.REMOVED));
PublishOperation[] tasks = getTasks(kind, moduleList, deltaKindList);
int size = 2000 + 3500 * moduleList.size() + 500 * tasks.length;
monitor = ProgressUtil.getMonitorFor(monitor);
monitor.beginTask(NLS.bind(Messages.publishing, getServer().getName()), size);
MultiStatus tempMulti = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, "", null);
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
try {
Trace.trace(Trace.FINEST, "Starting publish");
publishStart(ProgressUtil.getSubMonitorFor(monitor, 1000));
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
// execute tasks
MultiStatus taskStatus = performTasks(tasks, monitor);
if (taskStatus != null && !taskStatus.isOK())
tempMulti.addAll(taskStatus);
executePublishers(kind, moduleList, monitor, info2);
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
// publish the server
publishServer(kind, ProgressUtil.getSubMonitorFor(monitor, 1000));
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
// publish modules
publishModules(kind, moduleList, deltaKindList, tempMulti, monitor);
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
monitor.done();
} catch (CoreException ce) {
Trace.trace(Trace.INFO, "CoreException publishing to " + toString(), ce);
return ce.getStatus();
} catch (Exception e) {
Trace.trace(Trace.SEVERE, "Error publishing to " + toString(), e);
tempMulti.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorPublishing, e));
} finally {
// end the publishing
try {
publishFinish(ProgressUtil.getSubMonitorFor(monitor, 500));
} catch (CoreException ce) {
Trace.trace(Trace.INFO, "CoreException publishing to " + toString(), ce);
tempMulti.add(ce.getStatus());
} catch (Exception e) {
Trace.trace(Trace.SEVERE, "Error stopping publish to " + toString(), e);
tempMulti.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorPublishing, e));
}
}
Trace.trace(Trace.FINEST, "--<-- Done publishing --<--");
if (tempMulti.getChildren().length == 1)
return tempMulti.getChildren()[0];
MultiStatus multi = null;
if (tempMulti.getSeverity() == IStatus.OK)
return Status.OK_STATUS;
else if (tempMulti.getSeverity() == IStatus.INFO)
multi = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, Messages.publishingStatusInfo, null);
else if (tempMulti.getSeverity() == IStatus.WARNING)
multi = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, Messages.publishingStatusWarning, null);
else if (tempMulti.getSeverity() == IStatus.ERROR)
multi = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, Messages.publishingStatusError, null);
if (multi != null)
multi.addAll(tempMulti);
return multi;
}
/*private void printModule(IModuleResource[] res, String ind) {
int size = res.length;
for (int i = 0; i < size; i++) {
if (res[i] instanceof IModuleFolder) {
IModuleFolder f = (IModuleFolder) res[i];
printModule(f.members(), ind + " ");
} else {
Trace.trace(Trace.INFO, ind + res[i].getName());
}
}
}*/
/**
* Publish a single module.
*
* @param kind a publish kind
* @param module a module
* @param deltaKind the delta kind
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @return the status
*/
protected IStatus publishModule(int kind, IModule[] module, int deltaKind, IProgressMonitor monitor) {
Trace.trace(Trace.FINEST, "Publishing module: " + module);
int size = module.length;
IModule m = module[size - 1];
monitor.beginTask(NLS.bind(Messages.publishingModule, m.getName()), 1000);
try {
publishModule(kind, deltaKind, module, monitor);
return Status.OK_STATUS;
} catch (CoreException ce) {
return ce.getStatus();
} catch (Exception e) {
return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, Messages.errorPublishing, e);
} finally {
monitor.done();
Trace.trace(Trace.FINEST, "Done publishing: " + module);
}
}
/**
* Returns <code>true</code> if the given module has been published, and
* <code>false</code> otherwise.
*
* @param module a module
* @return <code>true</code> if the given module has been published, and
* <code>false</code> otherwise
*/
protected boolean hasBeenPublished(IModule[] module) {
return server.getServerPublishInfo().hasModulePublishInfo(module);
}
/**
* Adds removed modules.
*
* @param moduleList a list of modules
* @param kindList deprecated, should be null
*/
protected void addRemovedModules(List<IModule[]> moduleList, List<Integer> kindList) {
server.getServerPublishInfo().addRemovedModules(moduleList);
}
/**
* Update the stored publish info for the given module.
*
* @deprecated should never need to be called directly. Will be removed
* in a future version of WTP
* @param deltaKind a publish delta kind
* @param module a module
*/
protected void updatePublishInfo(int deltaKind, IModule[] module) {
// TODO remove
}
/**
* Publishes the given modules. Returns true if the publishing
* should continue, or false if publishing has failed or is canceled.
*
* Uses 500 ticks plus 3500 ticks per module
*
* @param kind the publish kind
* @param modules a list of modules
* @param deltaKind a list of delta kinds
* @param multi a multistatus to add the status to
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
*/
protected void publishModules(int kind, List modules, List deltaKind2, MultiStatus multi, IProgressMonitor monitor) {
if (modules == null)
return;
int size = modules.size();
if (size == 0)
return;
// publish modules
for (int i = 0; i < size; i++) {
if (monitor.isCanceled())
return;
// skip closed projects
IModule[] module = (IModule[]) modules.get(i);
IModule m = module[module.length - 1];
if (m.getProject() != null && !m.getProject().isAccessible())
continue;
int kind2 = kind;
if (getServer().getModulePublishState(module) == IServer.PUBLISH_STATE_UNKNOWN)
kind2 = IServer.PUBLISH_FULL;
/*int deltaKind = ServerBehaviourDelegate.ADDED;
if (hasBeenPublished(module)) {
if (getPublishedResourceDelta(module).length == 0)
deltaKind = ServerBehaviourDelegate.NO_CHANGE;
else
deltaKind = ServerBehaviourDelegate.CHANGED;
} // TODO REMOVED*/
IStatus status = publishModule(kind2, module, ((Integer)deltaKind2.get(i)).intValue(), ProgressUtil.getSubMonitorFor(monitor, 3000));
if (status != null && !status.isOK())
multi.add(status);
}
}
/**
* Returns the publish tasks that have been targeted to this server.
* These tasks should be run during publishing.
*
* @param kind one of the IServer.PUBLISH_XX constants
* @param moduleList a list of modules
* @param kindList list of one of the IServer publish change constants
* @return a possibly empty array of IOptionalTasks
*/
protected final PublishOperation[] getTasks(int kind, List moduleList, List kindList) {
return server.getTasks(kind, moduleList, kindList);
}
/**
* Execute publishers.
*
* @param kind the publish kind
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @param info the IAdaptable (or <code>null</code>) provided by the
* caller in order to supply UI information for prompting the
* user if necessary. When this parameter is not <code>null</code>,
* it should minimally contain an adapter for the
* org.eclipse.swt.widgets.Shell.class
* @throws CoreException
*/
protected void executePublishers(int kind, List<IModule[]> modules, IProgressMonitor monitor, IAdaptable info) throws CoreException {
Publisher[] publishers = ((Server)getServer()).getEnabledPublishers();
int size = publishers.length;
Trace.trace(Trace.FINEST, "Executing publishers: " + size);
if (size == 0)
return;
TaskModel taskModel = new TaskModel();
taskModel.putObject(TaskModel.TASK_SERVER, getServer());
taskModel.putObject(TaskModel.TASK_MODULES, modules);
for (int i = 0; i < size; i++) {
Publisher pub = publishers[i];
monitor.subTask(NLS.bind(Messages.taskPerforming, pub.getName()));
try {
pub.setTaskModel(taskModel);
pub.execute(kind, ProgressUtil.getSubMonitorFor(monitor, 500), info);
} catch (CoreException ce) {
Trace.trace(Trace.SEVERE, "Publisher failed", ce);
throw ce;
}
// return early if the monitor has been canceled
if (monitor.isCanceled())
return;
}
}
/**
* Returns all the modules that are on the server, including root
* modules and all their children.
*
* @return a list of IModule[]s
*/
protected final List<IModule[]> getAllModules() {
return server.getAllModules();
}
/**
* Perform (execute) all the given tasks.
*
* @param tasks an array of tasks
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @return the status
*/
protected MultiStatus performTasks(PublishOperation[] tasks, IProgressMonitor monitor) {
int size = tasks.length;
Trace.trace(Trace.FINEST, "Performing tasks: " + size);
if (size == 0)
return null;
MultiStatus multi = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, Messages.taskPerforming, null);
for (int i = 0; i < size; i++) {
PublishOperation task = tasks[i];
monitor.subTask(NLS.bind(Messages.taskPerforming, task.toString()));
try {
task.execute(ProgressUtil.getSubMonitorFor(monitor, 500), null);
} catch (CoreException ce) {
Trace.trace(Trace.SEVERE, "Task failed", ce);
multi.add(ce.getStatus());
}
// return early if the monitor has been canceled
if (monitor.isCanceled())
return multi;
}
return multi;
}
/**
* Called when resources change within the workspace.
* This gives the server an opportunity to update the server or module
* restart state.
*/
public void handleResourceChange() {
// do nothing
}
}