Workflows werden nun auch bei einem Republish korrekt zurückgesetzt.

git-svn-id: https://svn.libreccm.org/ccm/trunk@2447 8810af33-2d31-482b-a856-94f89814c4df
master
quasi 2013-11-22 09:01:05 +00:00
parent a430009ed2
commit 818b0785cf
1 changed files with 808 additions and 799 deletions

View File

@ -18,17 +18,12 @@
*/ */
package com.arsdigita.cms.ui.lifecycle; package com.arsdigita.cms.ui.lifecycle;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.event.FormSectionEvent;
import java.text.DateFormat;
import org.apache.log4j.Logger;
import com.arsdigita.bebop.ActionLink; import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.BoxPanel; import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Component; import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Form; import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormData; import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.RequestLocal; import com.arsdigita.bebop.RequestLocal;
@ -38,6 +33,7 @@ import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener; import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.FormInitListener; import com.arsdigita.bebop.event.FormInitListener;
import com.arsdigita.bebop.event.FormProcessListener; import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.PrintEvent; import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener; import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.Option; import com.arsdigita.bebop.form.Option;
@ -45,11 +41,10 @@ import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.form.Submit; import com.arsdigita.bebop.form.Submit;
import com.arsdigita.cms.CMS; import com.arsdigita.cms.CMS;
import com.arsdigita.cms.CMSConfig; import com.arsdigita.cms.CMSConfig;
import com.arsdigita.cms.ContentCenter;
import com.arsdigita.cms.ContentItem; import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentPage;
import com.arsdigita.cms.ContentSection; import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.SecurityManager; import com.arsdigita.cms.SecurityManager;
import com.arsdigita.cms.ContentCenter;
import com.arsdigita.cms.dispatcher.Utilities; import com.arsdigita.cms.dispatcher.Utilities;
import com.arsdigita.cms.lifecycle.Lifecycle; import com.arsdigita.cms.lifecycle.Lifecycle;
import com.arsdigita.cms.ui.BaseItemPane; import com.arsdigita.cms.ui.BaseItemPane;
@ -60,6 +55,7 @@ import com.arsdigita.globalization.GlobalizationHelper;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.kernel.Party; import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.PartyCollection; import com.arsdigita.kernel.PartyCollection;
import com.arsdigita.kernel.User;
import com.arsdigita.notification.Notification; import com.arsdigita.notification.Notification;
import com.arsdigita.persistence.OID; import com.arsdigita.persistence.OID;
import com.arsdigita.toolbox.ui.ActionGroup; import com.arsdigita.toolbox.ui.ActionGroup;
@ -75,12 +71,14 @@ import com.arsdigita.xml.Element;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.Writer; import java.io.Writer;
import java.util.Locale; import java.text.DateFormat;
import org.apache.log4j.Logger;
/** /**
* This class contains the component which displays the information for a particular lifecycle, with the ability to edit * This class contains the component which displays the information for a
* and delete. This information also includes the associated phases for this lifecycle, also with the ability to add, * particular lifecycle, with the ability to edit and delete. This information
* edit, and delete. * also includes the associated phases for this lifecycle, also with the ability
* to add, edit, and delete.
* *
* @author Michael Pih * @author Michael Pih
* @author Jack Chung * @author Jack Chung
@ -109,7 +107,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
m_detailPane.add(new SummarySection()); m_detailPane.add(new SummarySection());
final Label lastPublishedLabel = new Label(); final Label lastPublishedLabel = new Label();
lastPublishedLabel.addPrintListener(new PrintListener() { lastPublishedLabel.addPrintListener(new PrintListener() {
@Override
public void prepare(final PrintEvent event) { public void prepare(final PrintEvent event) {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
final ContentItem item = m_item.getContentItem(state). final ContentItem item = m_item.getContentItem(state).
@ -133,7 +131,6 @@ class ItemLifecycleItemPane extends BaseItemPane {
dateStr); dateStr);
label.setLabel(msg); label.setLabel(msg);
} }
}); });
m_detailPane.add(lastPublishedLabel); m_detailPane.add(lastPublishedLabel);
@ -164,6 +161,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
private class Properties extends PropertyList { private class Properties extends PropertyList {
@Override
protected final java.util.List properties(final PageState state) { protected final java.util.List properties(final PageState state) {
final java.util.List props = super.properties(state); final java.util.List props = super.properties(state);
final Lifecycle cycle = m_lifecycle.getLifecycle(state); final Lifecycle cycle = m_lifecycle.getLifecycle(state);
@ -191,7 +189,6 @@ class ItemLifecycleItemPane extends BaseItemPane {
return props; return props;
} }
} }
} }
@ -203,6 +200,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
super(c); super(c);
} }
@Override
public void generateXML(PageState ps, Element parent) { public void generateXML(PageState ps, Element parent) {
Boolean canPublish = (Boolean) m_canPublish.get(ps); Boolean canPublish = (Boolean) m_canPublish.get(ps);
if (null == canPublish) { if (null == canPublish) {
@ -231,7 +229,6 @@ class ItemLifecycleItemPane extends BaseItemPane {
s_log.debug("User cannot publish " + item.getOID()); s_log.debug("User cannot publish " + item.getOID());
} }
} }
} }
private class UnpublishLink extends PublishLink { private class UnpublishLink extends PublishLink {
@ -244,6 +241,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
private class Listener implements ActionListener { private class Listener implements ActionListener {
@Override
public final void actionPerformed(final ActionEvent e) { public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState(); final PageState state = e.getPageState();
final ContentItem item = m_item.getContentItem(state); final ContentItem item = m_item.getContentItem(state);
@ -256,16 +254,14 @@ class ItemLifecycleItemPane extends BaseItemPane {
throw new RedirectSignal(target, true); throw new RedirectSignal(target, true);
} }
} }
} }
private static void republish(ContentItem item, boolean reset) { private static void republish(ContentItem item, boolean reset, User user) {
item.republish(reset); item.republish(reset);
Workflow workflow = Workflow.getObjectWorkflow(item); Workflow workflow = Workflow.getObjectWorkflow(item);
try { try {
ItemLifecycleSelectForm.finish(workflow, item, Web.getContext(). ItemLifecycleSelectForm.finish(workflow, item, user);
getUser());
} catch (TaskException te) { } catch (TaskException te) {
throw new UncheckedWrapperException(te); throw new UncheckedWrapperException(te);
} }
@ -281,18 +277,20 @@ class ItemLifecycleItemPane extends BaseItemPane {
private class Listener implements ActionListener { private class Listener implements ActionListener {
@Override
public final void actionPerformed(final ActionEvent e) { public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState(); final PageState state = e.getPageState();
final ContentItem item = m_item.getContentItem(state); final ContentItem item = m_item.getContentItem(state);
final User user = Web.getContext().getUser();
/* /*
* jensp 2011-12-14: Check is threaded publishing is active. If yes, execute publishing in a thread. * jensp 2011-12-14: Check is threaded publishing is active. If yes, execute publishing in a thread.
*/ */
if (CMSConfig.getInstance().getThreadedPublishing()) { if (CMSConfig.getInstance().getThreadedPublishing()) {
final Republisher republisher = new Republisher(item); final Republisher republisher = new Republisher(item, user);
final Thread thread = new Thread(republisher); final Thread thread = new Thread(republisher);
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread thread, public void uncaughtException(final Thread thread,
final Throwable ex) { final Throwable ex) {
PublishLock.getInstance().setError(item); PublishLock.getInstance().setError(item);
@ -352,7 +350,6 @@ class ItemLifecycleItemPane extends BaseItemPane {
notification.save(); notification.save();
} }
} }
}); });
thread.start(); thread.start();
@ -366,7 +363,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
* jensp 2011-12-14 end * jensp 2011-12-14 end
*/ */
} else { } else {
republish(item, false); republish(item, false, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) { if (ContentSection.getConfig().getUseStreamlinedCreation()) {
throw new RedirectSignal( throw new RedirectSignal(
URL.there(state.getRequest(), URL.there(state.getRequest(),
@ -374,7 +371,6 @@ class ItemLifecycleItemPane extends BaseItemPane {
} }
} }
} }
} }
/** /**
@ -383,24 +379,27 @@ class ItemLifecycleItemPane extends BaseItemPane {
private class Republisher implements Runnable { private class Republisher implements Runnable {
/** /**
* Saves OID of item as a string. This is necessary because it is not possible to access to same data object * Saves OID of item as a string. This is necessary because it is
* instance from multiple threads. So we have to create a new instance a the data object in the run method. * not possible to access to same data object instance from multiple
* To avoid any sort a problems, we store the OID as a string and convert it back to an OID in the run * threads. So we have to create a new instance a the data object in
* method. * the run method. To avoid any sort a problems, we store the OID as
* a string and convert it back to an OID in the run method.
*/ */
private final String itemOid; private final String itemOid;
private final User user;
private Republisher(final ContentItem item) { private Republisher(final ContentItem item, User user) {
itemOid = item.getOID().toString(); itemOid = item.getOID().toString();
this.user = user;
} }
@Override
public void run() { public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid)); final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid));
PublishLock.getInstance().lock(item); PublishLock.getInstance().lock(item);
republish(item, false); republish(item, false, user);
PublishLock.getInstance().unlock(item); PublishLock.getInstance().unlock(item);
} }
} }
} }
@ -418,18 +417,21 @@ class ItemLifecycleItemPane extends BaseItemPane {
private class Listener implements ActionListener { private class Listener implements ActionListener {
@Override
public final void actionPerformed(final ActionEvent e) { public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState(); final PageState state = e.getPageState();
final ContentItem item = m_item.getContentItem(state); final ContentItem item = m_item.getContentItem(state);
final User user = Web.getContext().getUser();
/** /**
* jensp 2011-12-14: Execute is a thread if threaded publishing is active. * jensp 2011-12-14: Execute is a thread if threaded publishing
* is active.
*/ */
if (CMSConfig.getInstance().getThreadedPublishing()) { if (CMSConfig.getInstance().getThreadedPublishing()) {
final Republisher republisher = new Republisher(item); final Republisher republisher = new Republisher(item, user);
final Thread thread = new Thread(republisher); final Thread thread = new Thread(republisher);
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread thread, public void uncaughtException(final Thread thread,
final Throwable ex) { final Throwable ex) {
PublishLock.getInstance().setError(item); PublishLock.getInstance().setError(item);
@ -489,7 +491,6 @@ class ItemLifecycleItemPane extends BaseItemPane {
notification.save(); notification.save();
} }
} }
}); });
thread.start(); thread.start();
@ -503,7 +504,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
/** /**
* jensp 2011-12-14 end * jensp 2011-12-14 end
*/ */
republish(item, true); republish(item, true, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) { if (ContentSection.getConfig().getUseStreamlinedCreation()) {
throw new RedirectSignal( throw new RedirectSignal(
URL.there(state.getRequest(), URL.there(state.getRequest(),
@ -511,7 +512,6 @@ class ItemLifecycleItemPane extends BaseItemPane {
} }
} }
} }
} }
/** /**
@ -520,24 +520,27 @@ class ItemLifecycleItemPane extends BaseItemPane {
private class Republisher implements Runnable { private class Republisher implements Runnable {
/** /**
* Saves OID of item as a string. This is necessary because it is not possible to access to same data object * Saves OID of item as a string. This is necessary because it is
* instance from multiple threads. So we have to create a new instance a the data object in the run method. * not possible to access to same data object instance from multiple
* To avoid any sort a problems, we store the OID as a string and convert it back to an OID in the run * threads. So we have to create a new instance a the data object in
* method. * the run method. To avoid any sort a problems, we store the OID as
* a string and convert it back to an OID in the run method.
*/ */
private final String itemOid; private final String itemOid;
private final User user;
private Republisher(final ContentItem item) { private Republisher(final ContentItem item, User user) {
itemOid = item.getOID().toString(); itemOid = item.getOID().toString();
this.user = user;
} }
@Override
public void run() { public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid)); final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid));
PublishLock.getInstance().lock(item); PublishLock.getInstance().lock(item);
republish(item, true); republish(item, true, user);
PublishLock.getInstance().unlock(item); PublishLock.getInstance().unlock(item);
} }
} }
} }
@ -551,7 +554,6 @@ class ItemLifecycleItemPane extends BaseItemPane {
group.setSubject(new PhaseTable()); group.setSubject(new PhaseTable());
} }
} }
private class PhaseTable extends Table { private class PhaseTable extends Table {
@ -565,11 +567,11 @@ class ItemLifecycleItemPane extends BaseItemPane {
lz("cms.ui.item.lifecycle.end_date") lz("cms.ui.item.lifecycle.end_date")
}); });
} }
} }
/** /**
* New style pane. Uses a select box for the action to avoid wrong clicks on unpublish. * New style pane. Uses a select box for the action to avoid wrong clicks on
* unpublish.
* *
* @author Jens Pelzetter * @author Jens Pelzetter
*/ */
@ -617,6 +619,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
addProcessListener(this); addProcessListener(this);
} }
@Override
public void init(FormSectionEvent fse) throws FormProcessException { public void init(FormSectionEvent fse) throws FormProcessException {
final PageState state = fse.getPageState(); final PageState state = fse.getPageState();
final ContentItem item = m_item.getContentItem(state); final ContentItem item = m_item.getContentItem(state);
@ -634,23 +637,26 @@ class ItemLifecycleItemPane extends BaseItemPane {
} }
} }
@Override
public void process(final FormSectionEvent fse) throws public void process(final FormSectionEvent fse) throws
FormProcessException { FormProcessException {
final PageState state = fse.getPageState(); final PageState state = fse.getPageState();
final FormData data = fse.getFormData(); final FormData data = fse.getFormData();
final User user = Web.getContext().getUser();
String selected = (String) data.get(LIFECYCLE_ACTION); String selected = (String) data.get(LIFECYCLE_ACTION);
final ContentItem item = m_item.getContentItem(state); final ContentItem item = m_item.getContentItem(state);
/** /**
* Republish/Republish and Reset are executed in the thread if threaded publishing is active. * Republish/Republish and Reset are executed in the thread if
* threaded publishing is active.
*/ */
if (REPUBLISH.equals(selected)) { if (REPUBLISH.equals(selected)) {
if (CMSConfig.getInstance().getThreadedPublishing()) { if (CMSConfig.getInstance().getThreadedPublishing()) {
final RepublishRunner runner = new RepublishRunner(item); final RepublishRunner runner = new RepublishRunner(item, user);
final Thread thread = new Thread(runner); final Thread thread = new Thread(runner);
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread thread, public void uncaughtException(final Thread thread,
final Throwable ex) { final Throwable ex) {
PublishLock.getInstance().setError(item); PublishLock.getInstance().setError(item);
@ -710,7 +716,6 @@ class ItemLifecycleItemPane extends BaseItemPane {
notification.save(); notification.save();
} }
} }
}); });
thread.start(); thread.start();
@ -721,7 +726,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
ContentItemPage.PUBLISHING_TAB), ContentItemPage.PUBLISHING_TAB),
true); true);
} else { } else {
republish(item, false); republish(item, false, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) { if (ContentSection.getConfig().getUseStreamlinedCreation()) {
throw new RedirectSignal( throw new RedirectSignal(
@ -732,11 +737,10 @@ class ItemLifecycleItemPane extends BaseItemPane {
} else if (REPUBLISH_AND_RESET.equals(selected)) { } else if (REPUBLISH_AND_RESET.equals(selected)) {
if (CMSConfig.getInstance().getThreadedPublishing()) { if (CMSConfig.getInstance().getThreadedPublishing()) {
final RepublishAndResetRunner runner = final RepublishAndResetRunner runner =
new RepublishAndResetRunner( new RepublishAndResetRunner(item, user);
item);
final Thread thread = new Thread(runner); final Thread thread = new Thread(runner);
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread thread, public void uncaughtException(final Thread thread,
final Throwable ex) { final Throwable ex) {
PublishLock.getInstance().setError(item); PublishLock.getInstance().setError(item);
@ -796,7 +800,6 @@ class ItemLifecycleItemPane extends BaseItemPane {
notification.save(); notification.save();
} }
} }
}); });
thread.start(); thread.start();
@ -807,7 +810,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
ContentItemPage.PUBLISHING_TAB), ContentItemPage.PUBLISHING_TAB),
true); true);
} else { } else {
republish(item, true); republish(item, true, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) { if (ContentSection.getConfig().getUseStreamlinedCreation()) {
throw new RedirectSignal( throw new RedirectSignal(
@ -825,57 +828,63 @@ class ItemLifecycleItemPane extends BaseItemPane {
private class RepublishRunner implements Runnable { private class RepublishRunner implements Runnable {
/** /**
* Saves OID of item as a string. This is necessary because it is not possible to access to same data object * Saves OID of item as a string. This is necessary because it is
* instance from multiple threads. So we have to create a new instance a the data object in the run method. * not possible to access to same data object instance from multiple
* To avoid any sort a problems, we store the OID as a string and convert it back to an OID in the run * threads. So we have to create a new instance a the data object in
* method. * the run method. To avoid any sort a problems, we store the OID as
* a string and convert it back to an OID in the run method.
*/ */
private final String itemOid; private final String itemOid;
private final User user;
private RepublishRunner(final ContentItem item) { private RepublishRunner(final ContentItem item, User user) {
itemOid = item.getOID().toString(); itemOid = item.getOID().toString();
this.user = user;
} }
private void doRepublish() { private void doRepublish() {
final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid)); final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid));
republish(item, false); republish(item, false, user);
} }
@Override
public void run() { public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid)); final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid));
PublishLock.getInstance().lock(item); PublishLock.getInstance().lock(item);
doRepublish(); doRepublish();
PublishLock.getInstance().unlock(item); PublishLock.getInstance().unlock(item);
} }
} }
private class RepublishAndResetRunner implements Runnable { private class RepublishAndResetRunner implements Runnable {
/** /**
* Saves OID of item as a string. This is necessary because it is not possible to access to same data object * Saves OID of item as a string. This is necessary because it is
* instance from multiple threads. So we have to create a new instance a the data object in the run method. * not possible to access to same data object instance from multiple
* To avoid any sort a problems, we store the OID as a string and convert it back to an OID in the run * threads. So we have to create a new instance a the data object in
* method. * the run method. To avoid any sort a problems, we store the OID as
* a string and convert it back to an OID in the run method.
*/ */
private final String itemOid; private final String itemOid;
private final User user;
private RepublishAndResetRunner(final ContentItem item) { private RepublishAndResetRunner(final ContentItem item, User user) {
itemOid = item.getOID().toString(); itemOid = item.getOID().toString();
this.user = user;
} }
private void doRepublishAndReset() { private void doRepublishAndReset() {
final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid)); final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid));
republish(item, true); republish(item, true, user);
} }
@Override
public void run() { public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid)); final ContentItem item = (ContentItem) DomainObjectFactory.newInstance(OID.valueOf(itemOid));
PublishLock.getInstance().lock(item); PublishLock.getInstance().lock(item);
doRepublishAndReset(); doRepublishAndReset();
PublishLock.getInstance().unlock(item); PublishLock.getInstance().unlock(item);
} }
} }
} }
} }