diff options
author | avera | 2010-07-14 21:03:13 +0000 |
---|---|---|
committer | avera | 2010-07-14 21:03:13 +0000 |
commit | 95166fb093fd77b758aa3fed4c3e5668effde1ac (patch) | |
tree | 04f8cc993291282c082953bb39d772e74e5ad18a /plugins/org.eclipse.wst.server.core/servercore/org/eclipse | |
parent | b8137ac4b6f6ac90c41e18221006b373b7149a18 (diff) | |
download | webtools.servertools-95166fb093fd77b758aa3fed4c3e5668effde1ac.tar.gz webtools.servertools-95166fb093fd77b758aa3fed4c3e5668effde1ac.tar.xz webtools.servertools-95166fb093fd77b758aa3fed4c3e5668effde1ac.zip |
[319288] Publishers may either cause lock conflicts or duplicate publishes
Diffstat (limited to 'plugins/org.eclipse.wst.server.core/servercore/org/eclipse')
4 files changed, 208 insertions, 46 deletions
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Publisher.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Publisher.java index 9ce878179..f125d754c 100644 --- a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Publisher.java +++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Publisher.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 IBM Corporation and others. + * Copyright (c) 2008, 2010 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 @@ -10,12 +10,14 @@ *******************************************************************************/ package org.eclipse.wst.server.core.internal; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.wst.server.core.IModule; +import org.eclipse.wst.server.core.IServerWorkingCopy; import org.eclipse.wst.server.core.TaskModel; import org.eclipse.wst.server.core.model.PublisherDelegate; /** @@ -24,6 +26,7 @@ import org.eclipse.wst.server.core.model.PublisherDelegate; public class Publisher { private IConfigurationElement element; private PublisherDelegate delegate; + private boolean modifyModules = false; /** * Publisher constructor comment. @@ -78,14 +81,101 @@ public class Publisher { return delegate; } + /** + * Should the original {@link ISchedulingRule} be changed with the new {@link ISchedulingRule}? + * + * @param originalRule + * The original {@link ISchedulingRule} + * @param newRule + * The new {@link ISchedulingRule} + * @return <code>true</code> if the new scheduling rule should be applied; Otherwise <code>false</code>. + */ + private boolean changeSchedulingRule(ISchedulingRule originalRule, ISchedulingRule newRule) { + + boolean changeRule = false; + if ((originalRule == null) && (newRule == null)) { + // no need to change rules if they're both null + changeRule = false; + } + else if((originalRule == null) && (newRule != null)) { + // there is currently no rule and a new not-null rule wants to be added + changeRule = true; + } + else if((originalRule != null) && (newRule == null)) { + // there is currently a rule and a new null rule wants to be applied + changeRule = true; + } + else if((originalRule != null) && (newRule != null)) { + // there is currently a rule and a new not-null rule wants to be applied. + changeRule = !originalRule.equals(newRule); + } + return changeRule; + } + + /** + * rebuild the cache for the modules involved with this task. + */ + private void rebuildModuleCache() { + + // reset the publishing cache for the modules that are part of this task. + Server server = (Server) getDelegate().getTaskModel().getObject(TaskModel.TASK_SERVER); + if (server != null) { + // make sure the right server is used. + if(server.isWorkingCopy()) { + IServerWorkingCopy workingCopy = (IServerWorkingCopy)server; + server = (Server) workingCopy.getOriginal(); + } + final List moduleList = (List)getDelegate().getTaskModel().getObject(TaskModel.TASK_MODULES); + if (moduleList != null) { + final Iterator moduleIterator = moduleList.iterator(); + while (moduleIterator.hasNext()) { + IModule[] module = (IModule[]) moduleIterator.next(); + if (module != null) { + Trace.trace(Trace.FINEST, "rebuilding cache for module: " + module[module.length - 1]); + server.getServerPublishInfo().rebuildCache(module); + } + } + } + } + } + public IStatus execute(int kind, IProgressMonitor monitor, IAdaptable info) throws CoreException { + + Trace.trace(Trace.FINEST, "Task.init " + this); + ISchedulingRule delegatePublisherRule = null; + final ISchedulingRule originalPublisherRule = Job.getJobManager().currentRule(); + IStatus resultStatus = null; + boolean changeSchedulingRules = false; try { - Trace.trace(Trace.FINEST, "Task.init " + this); - return getDelegate().execute(kind, monitor, info); - } catch (Exception e) { + delegatePublisherRule = getDelegate().getRule(); + changeSchedulingRules = this.changeSchedulingRule(originalPublisherRule, delegatePublisherRule); + Trace.trace(Trace.FINEST, "Change the scheduling rule to execute delegate: " + changeSchedulingRules); + if (changeSchedulingRules) { + Trace.trace(Trace.FINEST, "Ending the current scheduling rule " + originalPublisherRule); + Job.getJobManager().endRule(originalPublisherRule); + Trace.trace(Trace.FINEST, "Beginning the new scheduling rule: " + delegatePublisherRule); + Job.getJobManager().beginRule(delegatePublisherRule, monitor); + } + resultStatus = getDelegate().execute(kind, monitor, info); + this.modifyModules = getDelegate().isModifyModules(); + Trace.trace(Trace.FINEST, "The publisher delegate stated that it modified modules: " + this.modifyModules); + if(this.modifyModules) { + this.rebuildModuleCache(); + } + } + catch (Exception e) { Trace.trace(Trace.SEVERE, "Error calling delegate " + toString(), e); - return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, "Error in delegate", e); // TODO + resultStatus = new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, "Error in delegate", e); // TODO } + finally { + if (changeSchedulingRules) { + Trace.trace(Trace.FINEST, "Reseting the scheduling rules... ending: " + delegatePublisherRule); + Job.getJobManager().endRule(delegatePublisherRule); + Trace.trace(Trace.FINEST, "Reseting the scheduling rules... beginning: " + originalPublisherRule); + Job.getJobManager().beginRule(originalPublisherRule, monitor); + } + } + return resultStatus; } public void setTaskModel(TaskModel taskModel) { @@ -97,6 +187,16 @@ public class Publisher { } /** + * Accessor to find out if this publisher modified any modules that are published on the server. + * + * @return <code>true</code> if the publisher modified the contents of any modules that are published on the server. + */ + public boolean isModifyModules() { + + return this.modifyModules; + } + + /** * Return a string representation of this object. * * @return a string diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPublishInfo.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPublishInfo.java index 921000312..eadd3c8fd 100644 --- a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPublishInfo.java +++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/ServerPublishInfo.java @@ -540,4 +540,21 @@ public class ServerPublishInfo { } } } + + /** + * Recreates the cache for the specified {@link IModule}. + * + * @param module The {@link IModule} + */ + public void rebuildCache(IModule[] module) { + + synchronized (modulePublishInfo) { + final String publishInfoKey = this.getKey(module); + ModulePublishInfo mpi = modulePublishInfo.get(publishInfoKey); + if(mpi != null) { + mpi.startCaching(); // clear out the resource list + mpi.fill(module); // rebuild the resource list + } + } + } }
\ No newline at end of file diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/PublisherDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/PublisherDelegate.java index e4b70935e..564b322c0 100644 --- a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/PublisherDelegate.java +++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/PublisherDelegate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 IBM Corporation and others. + * Copyright (c) 2008, 2010 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 @@ -10,10 +10,9 @@ *******************************************************************************/ package org.eclipse.wst.server.core.model; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.wst.server.core.TaskModel; /** * An operation that will be executed during publishing. @@ -91,4 +90,28 @@ public abstract class PublisherDelegate { * @throws CoreException if there was an error while executing the task */ public abstract IStatus execute(int kind, IProgressMonitor monitor, IAdaptable info) throws CoreException; + + /** + * Returns the scheduling rule that is required for executing the publisher delegate. The default is the current + * rule defined on the publishing job. + * + * @return A {@link ISchedulingRule} for the job that defines how this publisher can execute in the publishing job. + * A <code>null</code> value may be returned if the publishing job does not have any rule defined. + * @since 3.2 + */ + public ISchedulingRule getRule() { + + return Job.getJobManager().currentRule(); + } + + /** + * Accessor to find out if this publisher delegate modified any modules that are published on the server. + * + * @return <code>true</code> if the publisher modified the contents of any modules that are published on the server. + * @since 3.2 + */ + public boolean isModifyModules() { + + return false; + } }
\ No newline at end of file diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ServerBehaviourDelegate.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ServerBehaviourDelegate.java index ca4692987..dad47aa3a 100644 --- a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ServerBehaviourDelegate.java +++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/model/ServerBehaviourDelegate.java @@ -863,6 +863,33 @@ public abstract class ServerBehaviourDelegate { multi.addAll(tempMulti); }*/ + private List<Integer> computeDelta(final List<IModule[]> moduleList) { + + final List<Integer> deltaKindList = new ArrayList<Integer>(); + final Iterator<IModule[]> iterator = moduleList.iterator(); + while (iterator.hasNext()) { + IModule[] module = 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)); + } + } + this.addRemovedModules(moduleList, null); + while (deltaKindList.size() < moduleList.size()) { + deltaKindList.add(new Integer(ServerBehaviourDelegate.REMOVED)); + } + return deltaKindList; + } + /** * Publish to the server. * @@ -878,25 +905,7 @@ public abstract class ServerBehaviourDelegate { 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)); + List<Integer> deltaKindList = this.computeDelta(moduleList); PublishOperation[] tasks = getTasks(kind, moduleList, deltaKindList); int size = 2000 + 3500 * moduleList.size() + 500 * tasks.length; @@ -1144,18 +1153,22 @@ public abstract class ServerBehaviourDelegate { } /** - * Execute publishers. + * Execute publishers. If a publisher modified the contents of the module (which is determined by the + * {@link PublisherDelegate}) then the delta list is rebuild. * - * @param kind the publish kind - * @param modules the list of modules - * @param deltaKinds the list of delta kind that maps to the list of modules - * @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 + * @param kind + * the publish kind + * @param modules + * the list of modules. The contents of this {@link List} may change if the publisher modifies code. + * @param deltaKinds + * the list of delta kind that maps to the list of modules. The contents of this {@link List} may change + * if the publisher modifies code. + * @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 * @since 1.1 */ @@ -1176,12 +1189,17 @@ public abstract class ServerBehaviourDelegate { taskModel.putObject(TaskModel.TASK_DELTA_KINDS, deltaKinds); } + boolean publisherModifiedCode = false; for (int i = 0; i < size; i++) { Publisher pub = publishers[i]; monitor.subTask(NLS.bind(Messages.taskPerforming, pub.getName())); try { pub.setTaskModel(taskModel); IStatus pubStatus = pub.execute(kind, ProgressUtil.getSubMonitorFor(monitor, 500), info); + if(!publisherModifiedCode) { + // If a publisher has modified modules then there is no reason to keep checking other publishers. + publisherModifiedCode = pub.isModifyModules(); + } multi.add(pubStatus); } catch (CoreException ce) { Trace.trace(Trace.SEVERE, "Publisher failed", ce); @@ -1192,6 +1210,10 @@ public abstract class ServerBehaviourDelegate { if (monitor.isCanceled()) return multi; } + if (publisherModifiedCode) { + // re-create the delta list as at least one publisher has changed the contents of the published modules. + deltaKinds = this.computeDelta(modules); + } return multi; } |