CCM NG: ContentItem Page ported

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4517 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2017-01-13 13:19:02 +00:00
parent c27677b408
commit 652a8744d0
31 changed files with 2093 additions and 1685 deletions

View File

@ -23,16 +23,12 @@ import com.arsdigita.cms.CMS;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.PageLocations;
import com.arsdigita.web.ParameterMap;
import com.arsdigita.web.URL;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
/**

View File

@ -41,12 +41,12 @@ import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.PageLocations;
import com.arsdigita.cms.ui.item.CustomizedPreviewLink;
import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.CMSPage;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.authoring.WizardSelector;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.cms.ui.item.CustomizedPreviewLink;
import com.arsdigita.cms.ui.item.ItemLanguages;
import com.arsdigita.cms.ui.item.Summary;
import com.arsdigita.cms.ui.lifecycle.ItemLifecycleAdminPane;
@ -60,9 +60,7 @@ import com.arsdigita.util.Assert;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.xml.Document;
import com.arsdigita.xml.Element;
import java.io.IOException;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.arsdigita.cms.CMSConfig;
@ -74,6 +72,11 @@ import org.librecms.contentsection.ContentItemVersion;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
import java.io.IOException;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
/**
* Page for administering a content item.
*

View File

@ -39,7 +39,7 @@ import com.arsdigita.cms.dispatcher.CMSPage;
//ToDo NG import com.arsdigita.cms.ui.cse.ContentSoonExpiredPane;
import com.arsdigita.cms.ui.folder.FolderAdminPane;
import com.arsdigita.cms.ui.lifecycle.LifecycleAdminPane;
import com.arsdigita.cms.ui.role.RoleAdminPane;
//import com.arsdigita.cms.ui.role.RoleAdminPane;
import com.arsdigita.cms.ui.type.ContentTypeAdminPane;
import com.arsdigita.cms.ui.workflow.WorkflowAdminPane;
import com.arsdigita.globalization.GlobalizedMessage;
@ -130,7 +130,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
//ToDo NG private BrowsePane m_browsePane;
//ToDo NG private ItemSearch m_searchPane;
//ToDo NG private ImagesPane m_imagesPane;
private RoleAdminPane m_rolePane;
//ToDo NG private RoleAdminPane m_rolePane;
private WorkflowAdminPane m_workflowPane;
private LifecycleAdminPane m_lifecyclePane;
//ToDo NG private CategoryAdminPane m_categoryPane;
@ -157,7 +157,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
//ToDo NG m_browsePane = getBrowsePane();
//ToDo NG m_searchPane = getSearchPane();
//ToDo NG m_imagesPane = getImagesPane();
m_rolePane = getRoleAdminPane();
//ToDo NG m_rolePane = getRoleAdminPane();
m_workflowPane = getWorkflowAdminPane();
m_lifecyclePane = getLifecycleAdminPane();
//ToDo NG m_categoryPane = getCategoryAdminPane();
@ -211,11 +211,12 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
m_typePane,
permissionChecker.isPermitted(
AdminPrivileges.ADMINISTER_CONTENT_TYPES));
m_tabbedPane.setTabVisible(
state,
m_rolePane,
permissionChecker.isPermitted(
AdminPrivileges.ADMINISTER_ROLES));
//ToDo NG
//m_tabbedPane.setTabVisible(
// state,
// m_rolePane,
// permissionChecker.isPermitted(
// AdminPrivileges.ADMINISTER_ROLES));
// csePane: should check permission
m_tabbedPane.setTabVisible(state, m_csePane, true);
// TODO Check for reportPane as well
@ -275,12 +276,13 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
// return m_imagesPane;
// }
protected RoleAdminPane getRoleAdminPane() {
if (m_rolePane == null) {
m_rolePane = new RoleAdminPane();
}
return m_rolePane;
}
// ToDo NG
// protected RoleAdminPane getRoleAdminPane() {
// if (m_rolePane == null) {
// m_rolePane = new RoleAdminPane();
// }
// return m_rolePane;
// }
/**
* Creates, and then caches, the workflow administration pane. Overriding
@ -400,7 +402,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
// ToDo NG tab(pane, "cms.ui.browse", getBrowsePane());
// ToDo NG tab(pane, "cms.ui.search", getSearchPane());
// ToDo NG tab(pane, "cms.ui.images", getImagesPane());
tab(pane, "cms.ui.roles", getRoleAdminPane());
// ToDo NG tab(pane, "cms.ui.roles", getRoleAdminPane());
tab(pane, "cms.ui.workflows", getWorkflowAdminPane());
tab(pane, "cms.ui.lifecycles", getLifecycleAdminPane());
// ToDo NG tab(pane, "cms.ui.categories", getCategoryAdminPane());
@ -448,8 +450,8 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
m_folderPane.reset(state);
//ToDo NG } else if (pane == m_browsePane) {
// m_browsePane.reset(state);
} else if (pane == m_rolePane) {
m_rolePane.reset(state);
// } else if (pane == m_rolePane) {
// m_rolePane.reset(state);
} else if (pane == m_workflowPane) {
m_workflowPane.reset(state);
} else if (pane == m_lifecyclePane) {

View File

@ -39,13 +39,11 @@ import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ContentCenter;
import com.arsdigita.cms.dispatcher.Utilities;
import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.mail.Mail;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.Property;
import com.arsdigita.toolbox.ui.PropertyList;
@ -53,7 +51,6 @@ import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.URL;
import com.arsdigita.web.Web;
import com.arsdigita.xml.Element;
import org.apache.logging.log4j.LogManager;
@ -61,18 +58,15 @@ import org.apache.logging.log4j.Logger;
import org.arsdigita.cms.CMSConfig;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.notification.Notification;
import org.libreccm.security.Party;
import org.libreccm.security.PermissionChecker;
import org.libreccm.security.Shiro;
import org.libreccm.security.User;
import org.libreccm.workflow.Workflow;
import org.libreccm.security.UserRepository;
import org.libreccm.workflow.WorkflowManager;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionConfig;
import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.lifecycle.Lifecycle;
@ -85,6 +79,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Optional;
import javax.mail.MessagingException;
/**
* This class contains the component which displays the information for a
* particular lifecycle, with the ability to edit and delete. This information
@ -304,7 +300,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
WorkflowManager.class);
itemManager.publish(item);
workflowManager.finish(item.getWorkflow());
}
@ -322,10 +318,13 @@ class ItemLifecycleItemPane extends BaseItemPane {
public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
final ContentItem item = selectedItem.getContentItem(state);
final User user = Web.getWebContext().getUser();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Shiro shiro = cdiUtil.findBean(Shiro.class);
final User user = shiro.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.getConfig().isThreadPublishing()) {
final Republisher republisher = new Republisher(item, user);
@ -341,46 +340,30 @@ class ItemLifecycleItemPane extends BaseItemPane {
= new PrintWriter(strWriter);
ex.printStackTrace(writer);
PublishLock.getInstance().setError(item, strWriter
.toString());
// PublishLock.getInstance().setError(item, strWriter
// .toString());
LOGGER.error(String.format(
"An error occurred while "
+ "publishing the item '%s': ",
item.getOID().toString()),
ex);
item.getUuid()), ex);
if ((CMSConfig.getInstanceOf().
getPublicationFailureSender()
if ((CMSConfig.getConfig()
.getPublishingFailureSender()
== null)
&& (CMSConfig.getInstanceOf().
getPublicationFailureReceiver()
&& (CMSConfig.getConfig()
.getPublishingFailureReceiver()
== null)) {
return;
}
final PartyCollection receiverParties = Party
.retrieveAllParties();
Party receiver = null;
receiverParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf()
.getPublicationFailureReceiver());
if (receiverParties.next()) {
receiver = receiverParties.getParty();
}
receiverParties.close();
final PartyCollection senderParties = Party
.retrieveAllParties();
Party sender = null;
senderParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf().
getPublicationFailureReceiver());
if (senderParties.next()) {
sender = senderParties.getParty();
}
senderParties.close();
final UserRepository userRepo = cdiUtil.findBean(
UserRepository.class);
final User receiver = userRepo.findByEmailAddress(
CMSConfig.getConfig()
.getPublishingFailureReceiver());
final User sender = userRepo.findByEmailAddress(
CMSConfig.getConfig()
.getPublishingFailureSender());
if ((sender != null) && (receiver != null)) {
final Writer traceWriter = new StringWriter();
@ -388,21 +371,25 @@ class ItemLifecycleItemPane extends BaseItemPane {
traceWriter);
ex.printStackTrace(printWriter);
final Notification notification
= new Notification(
sender,
receiver,
String.format(
"Failed to publish item '%s'",
item.getOID().toString()),
String.format(
"Publishing item '%s' failed "
+ "with error message: %s.\n\n"
+ "Stacktrace:\n%s",
item.getOID().toString(),
ex.getMessage(),
traceWriter.toString()));
notification.save();
final Mail notification = new Mail(
receiver.getPrimaryEmailAddress()
.getAddress(),
sender.getPrimaryEmailAddress().getAddress(),
String.format(
"Failed to publish item '%s'",
item.getUuid()));
notification.setBody(String.format(
"Publishing item '%s' failed "
+ "with error message: %s.\n\n"
+ "Stacktrace:\n%s",
item.getUuid(),
ex.getMessage(),
traceWriter.toString()));
try {
notification.send();
} catch (MessagingException msgex) {
throw new UncheckedWrapperException(msgex);
}
}
}
@ -420,10 +407,11 @@ class ItemLifecycleItemPane extends BaseItemPane {
*/
} else {
republish(item, false, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) {
if (CMSConfig.getConfig().isUseStreamlinedCreation()) {
throw new RedirectSignal(
URL.there(state.getRequest(),
ContentCenter.getURL()), true);
CmsConstants.CONTENT_CENTER_URL),
true);
}
}
}
@ -435,29 +423,24 @@ class ItemLifecycleItemPane extends BaseItemPane {
*/
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 instance from multiple
* threads. So we have to create a new instance a the data object in
* 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 itemUuid;
private final User user;
private Republisher(final ContentItem item, User user) {
itemOid = item.getOID().toString();
itemUuid = item.getUuid();
this.user = user;
}
@Override
public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory
.newInstance(OID.valueOf(
itemOid));
PublishLock.getInstance().lock(item);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
final ContentItem item = itemRepo.findByUuid(itemUuid).get();
// PublishLock.getInstance().lock(item);
republish(item, false, user);
PublishLock.getInstance().unlock(item);
// PublishLock.getInstance().unlock(item);
}
}
@ -482,13 +465,15 @@ class ItemLifecycleItemPane extends BaseItemPane {
public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState();
final ContentItem item = selectedItem.getContentItem(state);
final User user = Web.getWebContext().getUser();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Shiro shiro = cdiUtil.findBean(Shiro.class);
final User user = shiro.getUser();
/**
* jensp 2011-12-14: Execute is a thread if threaded publishing
* is active.
*/
if (CMSConfig.getInstanceOf().getThreadedPublishing()) {
if (CMSConfig.getConfig().isThreadPublishing()) {
final Republisher republisher = new Republisher(item, user);
final Thread thread = new Thread(republisher);
thread.setUncaughtExceptionHandler(
@ -502,46 +487,29 @@ class ItemLifecycleItemPane extends BaseItemPane {
= new PrintWriter(strWriter);
ex.printStackTrace(writer);
PublishLock.getInstance().setError(item, strWriter
.toString());
// PublishLock.getInstance().setError(item, strWriter
// .toString());
LOGGER.error(String.format(
"An error occurred while "
+ "publishing the item '%s': ",
item.getOID().toString()),
ex);
item.getUuid()), ex);
if ((CMSConfig.getInstanceOf().
getPublicationFailureSender()
== null)
&& (CMSConfig.getInstanceOf().
getPublicationFailureReceiver()
if ((CMSConfig.getConfig().
getPublishingFailureSender() == null)
&& (CMSConfig.getConfig().
getPublishingFailureReceiver()
== null)) {
return;
}
final PartyCollection receiverParties = Party
.retrieveAllParties();
Party receiver = null;
receiverParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf()
.getPublicationFailureReceiver());
if (receiverParties.next()) {
receiver = receiverParties.getParty();
}
receiverParties.close();
final PartyCollection senderParties = Party
.retrieveAllParties();
Party sender = null;
senderParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf().
getPublicationFailureReceiver());
if (senderParties.next()) {
sender = senderParties.getParty();
}
senderParties.close();
final UserRepository userRepo = cdiUtil.findBean(
UserRepository.class);
final User receiver = userRepo.findByEmailAddress(
CMSConfig.getConfig()
.getPublishingFailureReceiver());
final User sender = userRepo.findByEmailAddress(
CMSConfig.getConfig()
.getPublishingFailureSender());
if ((sender != null) && (receiver != null)) {
final Writer traceWriter = new StringWriter();
@ -549,21 +517,25 @@ class ItemLifecycleItemPane extends BaseItemPane {
traceWriter);
ex.printStackTrace(printWriter);
final Notification notification
= new Notification(
sender,
receiver,
String.format(
"Failed to publish item '%s'",
item.getOID().toString()),
String.format(
"Publishing item '%s' failed "
+ "with error message: %s.\n\n"
+ "Stacktrace:\n%s",
item.getOID().toString(),
ex.getMessage(),
traceWriter.toString()));
notification.save();
final Mail notification = new Mail(
receiver.getPrimaryEmailAddress()
.getAddress(),
sender.getPrimaryEmailAddress().getAddress(),
String.format(
"Failed to publish item '%s'",
item.getUuid()));
notification.setBody(String.format(
"Publishing item '%s' failed "
+ "with error message: %s.\n\n"
+ "Stacktrace:\n%s",
item.getUuid(),
ex.getMessage(),
traceWriter.toString()));
try {
notification.send();
} catch (MessagingException msgex) {
throw new UncheckedWrapperException(msgex);
}
}
}
@ -581,10 +553,11 @@ class ItemLifecycleItemPane extends BaseItemPane {
* jensp 2011-12-14 end
*/
republish(item, true, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) {
if (CMSConfig.getConfig().isUseStreamlinedCreation()) {
throw new RedirectSignal(
URL.there(state.getRequest(),
ContentCenter.getURL()), true);
CmsConstants.CONTENT_CENTER_URL),
true);
}
}
}
@ -596,29 +569,23 @@ class ItemLifecycleItemPane extends BaseItemPane {
*/
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 instance from multiple
* threads. So we have to create a new instance a the data object in
* 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 itemUuid;
private final User user;
private Republisher(final ContentItem item, User user) {
itemOid = item.getOID().toString();
itemUuid = item.getUuid();
this.user = user;
}
@Override
public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory
.newInstance(OID.valueOf(
itemOid));
PublishLock.getInstance().lock(item);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
final ContentItem item = itemRepo.findByUuid(itemUuid).get();
// PublishLock.getInstance().lock(item);
republish(item, true, user);
PublishLock.getInstance().unlock(item);
// PublishLock.getInstance().unlock(item);
}
}
@ -678,18 +645,17 @@ class ItemLifecycleItemPane extends BaseItemPane {
final SingleSelect actionSelect = new SingleSelect(
LIFECYCLE_ACTION);
actionSelect.addOption(new Option(REPUBLISH, (String) gz(
"cms.ui.item.lifecycle.republish")
.localize()));
if (!ContentSection.getConfig().hideResetLifecycleLink()) {
actionSelect.addOption(new Option(REPUBLISH_AND_RESET,
(String) gz(
"cms.ui.item.lifecycle.republish_and_reset")
.localize()));
actionSelect.addOption(new Option(
REPUBLISH,
new Label(gz("cms.ui.item.lifecycle.republish"))));
if (!CMSConfig.getConfig().isHideResetLifecycleLink()) {
actionSelect.addOption(new Option(
REPUBLISH_AND_RESET,
new Label(gz("cms.ui.item.lifecycle.republish_and_reset"))));
}
actionSelect.addOption(new Option(UNPUBLISH, (String) gz(
"cms.ui.item.lifecycle.unpublish")
.localize()));
actionSelect.addOption(new Option(
UNPUBLISH,
new Label(gz("cms.ui.item.lifecycle.unpublish"))));
submit = new Submit(gz("cms.ui.item.lifecycle.do"));
notAuthorized = new Label(gz(
@ -705,15 +671,17 @@ class ItemLifecycleItemPane extends BaseItemPane {
}
@Override
public void init(FormSectionEvent fse) throws FormProcessException {
final PageState state = fse.getPageState();
public void init(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
final ContentItem item = selectedItem.getContentItem(state);
final SecurityManager sm = Utilities.getSecurityManager(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
if (sm.canAccess(state.getRequest(),
SecurityManager.PUBLISH,
item)) {
if (permissionChecker.isPermitted(ItemPrivileges.PUBLISH, item)) {
submit.setVisible(state, true);
notAuthorized.setVisible(state, false);
} else {
@ -723,11 +691,14 @@ class ItemLifecycleItemPane extends BaseItemPane {
}
@Override
public void process(final FormSectionEvent fse) throws
FormProcessException {
final PageState state = fse.getPageState();
final FormData data = fse.getFormData();
final User user = Web.getWebContext().getUser();
public void process(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
final FormData data = event.getFormData();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Shiro shiro = cdiUtil.findBean(Shiro.class);
final User user = shiro.getUser();
String selected = (String) data.get(LIFECYCLE_ACTION);
final ContentItem item = selectedItem.getContentItem(state);
@ -737,7 +708,7 @@ class ItemLifecycleItemPane extends BaseItemPane {
* threaded publishing is active.
*/
if (REPUBLISH.equals(selected)) {
if (CMSConfig.getInstanceOf().getThreadedPublishing()) {
if (CMSConfig.getConfig().isThreadPublishing()) {
final RepublishRunner runner = new RepublishRunner(item,
user);
final Thread thread = new Thread(runner);
@ -752,46 +723,30 @@ class ItemLifecycleItemPane extends BaseItemPane {
= new PrintWriter(strWriter);
ex.printStackTrace(writer);
PublishLock.getInstance().setError(item, strWriter
.toString());
// PublishLock.getInstance().setError(item, strWriter
// .toString());
LOGGER.error(String.format(
"An error occurred while "
+ "publishing the item '%s': ",
item.getOID().toString()),
ex);
item.getUuid()), ex);
if ((CMSConfig.getInstanceOf().
getPublicationFailureSender()
if ((CMSConfig.getConfig()
.getPublishingFailureSender()
== null)
&& (CMSConfig.getInstanceOf().
getPublicationFailureReceiver()
&& (CMSConfig.getConfig()
.getPublishingFailureReceiver()
== null)) {
return;
}
final PartyCollection receiverParties = Party
.retrieveAllParties();
Party receiver = null;
receiverParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf()
.getPublicationFailureReceiver());
if (receiverParties.next()) {
receiver = receiverParties.getParty();
}
receiverParties.close();
final PartyCollection senderParties = Party
.retrieveAllParties();
Party sender = null;
senderParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf().
getPublicationFailureReceiver());
if (senderParties.next()) {
sender = senderParties.getParty();
}
senderParties.close();
final UserRepository userRepo = cdiUtil.findBean(
UserRepository.class);
final User receiver = userRepo.findByEmailAddress(
CMSConfig.getConfig()
.getPublishingFailureReceiver());
final User sender = userRepo.findByEmailAddress(
CMSConfig.getConfig()
.getPublishingFailureSender());
if ((sender != null) && (receiver != null)) {
final Writer traceWriter = new StringWriter();
@ -799,21 +754,25 @@ class ItemLifecycleItemPane extends BaseItemPane {
traceWriter);
ex.printStackTrace(printWriter);
final Notification notification
= new Notification(
sender,
receiver,
String.format(
"Failed to publish item '%s'",
item.getOID().toString()),
String.format(
"Publishing item '%s' failed "
+ "with error message: %s.\n\n"
+ "Stacktrace:\n%s",
item.getOID().toString(),
ex.getMessage(),
traceWriter.toString()));
notification.save();
final Mail notification = new Mail(
receiver.getPrimaryEmailAddress()
.getAddress(),
sender.getPrimaryEmailAddress().getAddress(),
String.format(
"Failed to publish item '%s'",
item.getUuid()));
notification.setBody(String.format(
"Publishing item '%s' failed "
+ "with error message: %s.\n\n"
+ "Stacktrace:\n%s",
item.getUuid(),
ex.getMessage(),
traceWriter.toString()));
try {
notification.send();
} catch (MessagingException msgex) {
throw new UncheckedWrapperException(msgex);
}
}
}
@ -829,14 +788,14 @@ class ItemLifecycleItemPane extends BaseItemPane {
} else {
republish(item, false, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) {
if (CMSConfig.getConfig().isUseStreamlinedCreation()) {
throw new RedirectSignal(
URL.there(state.getRequest(),
ContentCenter.getURL()), true);
CmsConstants.CONTENT_CENTER_URL), true);
}
}
} else if (REPUBLISH_AND_RESET.equals(selected)) {
if (CMSConfig.getInstanceOf().getThreadedPublishing()) {
if (CMSConfig.getConfig().isThreadPublishing()) {
final RepublishAndResetRunner runner
= new RepublishAndResetRunner(
item, user);
@ -852,46 +811,30 @@ class ItemLifecycleItemPane extends BaseItemPane {
= new PrintWriter(strWriter);
ex.printStackTrace(writer);
PublishLock.getInstance().setError(item, strWriter
.toString());
// PublishLock.getInstance().setError(item, strWriter
// .toString());
LOGGER.error(String.format(
"An error occurred while "
+ "publishing the item '%s': ",
item.getOID().toString()),
ex);
item.getUuid()), ex);
if ((CMSConfig.getInstanceOf().
getPublicationFailureSender()
if ((CMSConfig.getConfig()
.getPublishingFailureSender()
== null)
&& (CMSConfig.getInstanceOf().
getPublicationFailureReceiver()
&& (CMSConfig.getConfig()
.getPublishingFailureReceiver()
== null)) {
return;
}
final PartyCollection receiverParties = Party
.retrieveAllParties();
Party receiver = null;
receiverParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf()
.getPublicationFailureReceiver());
if (receiverParties.next()) {
receiver = receiverParties.getParty();
}
receiverParties.close();
final PartyCollection senderParties = Party
.retrieveAllParties();
Party sender = null;
senderParties.addEqualsFilter("primaryEmail",
CMSConfig
.getInstanceOf().
getPublicationFailureReceiver());
if (senderParties.next()) {
sender = senderParties.getParty();
}
senderParties.close();
final UserRepository userRepo = cdiUtil.findBean(
UserRepository.class);
final User receiver = userRepo.findByEmailAddress(
CMSConfig.getConfig()
.getPublishingFailureReceiver());
final User sender = userRepo.findByEmailAddress(
CMSConfig.getConfig()
.getPublishingFailureSender());
if ((sender != null) && (receiver != null)) {
final Writer traceWriter = new StringWriter();
@ -899,21 +842,25 @@ class ItemLifecycleItemPane extends BaseItemPane {
traceWriter);
ex.printStackTrace(printWriter);
final Notification notification
= new Notification(
sender,
receiver,
String.format(
"Failed to publish item '%s'",
item.getOID().toString()),
String.format(
"Publishing item '%s' failed "
+ "with error message: %s.\n\n"
+ "Stacktrace:\n%s",
item.getOID().toString(),
ex.getMessage(),
traceWriter.toString()));
notification.save();
final Mail notification = new Mail(
receiver.getPrimaryEmailAddress()
.getAddress(),
sender.getPrimaryEmailAddress().getAddress(),
String.format(
"Failed to publish item '%s'",
item.getUuid()));
notification.setBody(String.format(
"Publishing item '%s' failed "
+ "with error message: %s.\n\n"
+ "Stacktrace:\n%s",
item.getUuid(),
ex.getMessage(),
traceWriter.toString()));
try {
notification.send();
} catch (MessagingException msgex) {
throw new UncheckedWrapperException(msgex);
}
}
}
@ -929,14 +876,16 @@ class ItemLifecycleItemPane extends BaseItemPane {
} else {
republish(item, true, user);
if (ContentSection.getConfig().getUseStreamlinedCreation()) {
if (CMSConfig.getConfig().isUseStreamlinedCreation()) {
throw new RedirectSignal(
URL.there(state.getRequest(),
ContentCenter.getURL()), true);
CmsConstants.CONTENT_CENTER_URL), true);
}
}
} else if (UNPUBLISH.equals(selected)) {
item.unpublish();
final ContentItemManager itemManager = cdiUtil.findBean(
ContentItemManager.class);
itemManager.unpublish(item);
} else {
throw new IllegalArgumentException("Illegal selection");
}
@ -944,72 +893,60 @@ class ItemLifecycleItemPane extends BaseItemPane {
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 instance from multiple
* threads. So we have to create a new instance a the data object in
* 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 itemUuid;
private final User user;
private RepublishRunner(final ContentItem item, User user) {
itemOid = item.getOID().toString();
private RepublishRunner(final ContentItem item,
final User user) {
itemUuid = item.getUuid();
this.user = user;
}
private void doRepublish() {
final ContentItem item = (ContentItem) DomainObjectFactory
.newInstance(OID.valueOf(
itemOid));
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
final ContentItem item = itemRepo.findByUuid(itemUuid).get();
republish(item, false, user);
}
@Override
public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory
.newInstance(OID.valueOf(
itemOid));
PublishLock.getInstance().lock(item);
// PublishLock.getInstance().lock(item);
doRepublish();
PublishLock.getInstance().unlock(item);
// PublishLock.getInstance().unlock(item);
}
}
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 instance from multiple
* threads. So we have to create a new instance a the data object in
* 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 itemUuid;
private final User user;
private RepublishAndResetRunner(final ContentItem item, User user) {
itemOid = item.getOID().toString();
private RepublishAndResetRunner(final ContentItem item,
final User user) {
itemUuid = item.getUuid();
this.user = user;
}
private void doRepublishAndReset() {
final ContentItem item = (ContentItem) DomainObjectFactory
.newInstance(OID.valueOf(
itemOid));
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
final ContentItem item = itemRepo.findByUuid(itemUuid).get();
republish(item, true, user);
}
@Override
public void run() {
final ContentItem item = (ContentItem) DomainObjectFactory
.newInstance(OID.valueOf(
itemOid));
PublishLock.getInstance().lock(item);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
final ContentItem item = itemRepo.findByUuid(itemUuid).get();
// PublishLock.getInstance().lock(item);
doRepublishAndReset();
PublishLock.getInstance().unlock(item);
// PublishLock.getInstance().unlock(item);
}
}

View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.lifecycle;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.globalization.GlobalizedMessage;
import org.arsdigita.cms.CMSConfig;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionConfig;
import org.librecms.lifecycle.Phase;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* @author Xixi D'Moon <xdmoon@arsdigita.com>
* @author Michael Pih
* @author Justin Ross <jross@redhat.com>
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class ItemPhaseTableModelBuilder extends AbstractTableModelBuilder {
private final LifecycleRequestLocal lifecycle;
public ItemPhaseTableModelBuilder(final LifecycleRequestLocal lifecycle) {
this.lifecycle = lifecycle;
}
@Override
public final TableModel makeModel(final Table table,
final PageState state) {
return new Model(lifecycle.getLifecycle(state).getPhases());
}
private static class Model implements TableModel {
private final List<Phase> phases;
private int index = -1;
private Phase phase;
public Model(final List<Phase> phases) {
this.phases = phases;
}
@Override
public final int getColumnCount() {
return 4;
}
@Override
public final boolean nextRow() {
index++;
if (index < phases.size()) {
phase = phases.get(index);
return true;
} else {
return false;
}
}
@Override
public final Object getElementAt(final int column) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final GlobalizationHelper globalizationHelper = cdiUtil
.findBean(GlobalizationHelper.class);
final Locale locale = globalizationHelper.getNegotiatedLocale();
final DateFormat format;
if (CMSConfig.getConfig().isHideTimezone()) {
format = DateFormat.getDateTimeInstance(
DateFormat.FULL, DateFormat.SHORT, locale);
} else {
format = DateFormat.getDateTimeInstance(
DateFormat.FULL, DateFormat.FULL, locale);
}
switch (column) {
case 0:
return phase.getDefinition().getLabel().getValue(locale);
case 1:
return phase.getDefinition().getDescription().getValue(
locale);
case 2:
final Date startDate = phase.getStartDateTime();
return format.format(startDate);
case 3:
final Date endDate = phase.getEndDateTime();
if (endDate == null) {
return lz("cms.ui.lifecycle.forever");
} else {
return format.format(endDate);
}
default:
throw new IllegalArgumentException();
}
}
@Override
public final Object getKeyAt(final int column) {
return phase.getDefinition().getDefinitionId();
}
}
protected final static String lz(final String key) {
final GlobalizedMessage message = new GlobalizedMessage(key,
CmsConstants.CMS_BUNDLE);
return (String) message.localize();
}
}

View File

@ -36,6 +36,7 @@ import org.librecms.lifecycle.PhaseDefinition;
import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.Property;
import com.arsdigita.toolbox.ui.PropertyList;
import com.arsdigita.toolbox.ui.Section;

View File

@ -38,26 +38,27 @@ import java.util.List;
class PhaseTableModelBuilder extends LockableImpl
implements TableModelBuilder {
private final LifecycleDefinitionRequestLocal m_cycle;
private final LifecycleDefinitionRequestLocal cycle;
public PhaseTableModelBuilder
(final LifecycleDefinitionRequestLocal cycle) {
m_cycle = cycle;
this.cycle = cycle;
}
@Override
public final TableModel makeModel(final Table table,
final PageState state) {
return new PhaseTableModel(m_cycle.getLifecycleDefinition(state));
return new PhaseTableModel(cycle.getLifecycleDefinition(state));
}
private static class PhaseTableModel implements TableModel {
private PhaseDefinition m_phase;
private final List<PhaseDefinition> m_phases;
private final List<PhaseDefinition> phases;
private int index = -1;
private PhaseDefinition phase;
public PhaseTableModel(final LifecycleDefinition cycle) {
m_phases = cycle.getPhaseDefinitions();
m_phase = null;
phases = cycle.getPhaseDefinitions();
}
@Override
@ -68,8 +69,8 @@ class PhaseTableModelBuilder extends LockableImpl
@Override
public final boolean nextRow() {
index++;
if (index < m_phases.size()) {
m_phase = m_phases.get(index);
if (index < phases.size()) {
phase = phases.get(index);
return true;
} else {
@ -79,17 +80,17 @@ class PhaseTableModelBuilder extends LockableImpl
@Override
public final Object getElementAt(final int column) {
Assert.exists(m_phase, "PhaseDefinition m_phase");
Assert.exists(phase, "PhaseDefinition m_phase");
switch (column) {
case 0:
return m_phase.getLabel();
return phase.getLabel();
case 1:
return m_phase.getDescription();
return phase.getDescription();
case 2:
return Duration.formatDuration(m_phase.getDefaultDelay());
return Duration.formatDuration(phase.getDefaultDelay());
case 3:
final Long duration = m_phase.getDefaultDuration();
final Long duration = phase.getDefaultDuration();
if (duration == null) {
return lz("cms.ui.lifecycle.forever");
@ -105,11 +106,12 @@ class PhaseTableModelBuilder extends LockableImpl
}
}
@Override
public Object getKeyAt(int columnIndex) {
if (m_phase == null) {
if (phase == null) {
throw new IllegalStateException();
} else {
return m_phase.getDefinitionId();
return phase.getDefinitionId();
}
}
}

View File

@ -0,0 +1,362 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.revision;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.GridPanel;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.RadioGroup;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
import com.arsdigita.bebop.table.DefaultTableColumnModel;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableColumnModel;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.toolbox.ui.NullComponent;
import com.arsdigita.toolbox.ui.Section;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSectionManager;
import java.math.BigInteger;
/**
* Displays the revision history of a {@link ContentItem}
*
* @author unknown
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*
*/
public final class ItemRevisionAdminPane extends BaseItemPane {
private final ContentItemRequestLocal itemRequestLocal;
private final RevisionTable revisionsTable;
private final RevisionRequestLocal fromRequestLocal;
private final RevisionRequestLocal toRequestLocal;
private final LayoutPanel selectPane;
//ToDo
//private final DifferencePane diffPane;
public ItemRevisionAdminPane(final ContentItemRequestLocal itemRequestLocal) {
this.itemRequestLocal = itemRequestLocal;
final RadioGroup fromSelect = new RadioGroup("from");
final RadioGroup toSelect = new RadioGroup("to");
fromRequestLocal = new SelectionRequestLocal(fromSelect);
toRequestLocal = new SelectionRequestLocal(toSelect);
revisionsTable = new RevisionTable(fromSelect, toSelect);
final RevisionForm form = new RevisionForm(fromSelect, toSelect,
revisionsTable);
selectPane = new LayoutPanel();
add(selectPane);
setDefault(selectPane);
selectPane.setBody(new Section(gz("cms.ui.item.revisions"), form));
final ActionLink returnLink = new ActionLink(new Label(gz(
"cms.ui.item.revision.return")));
// Todo
// diffPane = new DifferencePane(itemRequestLocal,
// fromRequestLocal,
// toRequestLocal,
// returnLink);
// add(diffPane);
//
// connect(form, diffPane);
connect(returnLink, selectPane);
}
private class SelectionRequestLocal extends RevisionRequestLocal {
private final RadioGroup group;
SelectionRequestLocal(final RadioGroup group) {
this.group = group;
}
@Override
protected final Object initialValue(final PageState state) {
final Object selected = group.getValue(state);
if (selected == null || selected.toString().equals("")) {
return null;
} else {
final long revisionNumber = Long.parseLong(selected.toString());
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepository = cdiUtil.findBean(
ContentItemRepository.class);
return itemRepository.retrieveRevision(revisionNumber);
}
}
}
private class RevisionForm extends Form {
RevisionForm(final RadioGroup fromSelect,
final RadioGroup toSelect,
final RevisionTable revisions) {
super("revisions", new GridPanel(1));
setMethod("get");
add(fromSelect);
add(toSelect);
// Sets the 'to' revision to the dummy current revision
// and the 'from' revision to the dummy root revision.
fromSelect.setOptionSelected("");
toSelect.setOptionSelected("");
final ActionGroup group = new ActionGroup();
add(group);
group.setSubject(revisions);
group.addAction(new Submit("diff",
gz("cms.ui.item.revision.difference.show")));
}
}
private class RevisionTable extends Table {
// XXX Need to fix the static l18n stuff
private final TableColumn fromCol = new TableColumn(
RevisionTableModelBuilder.FROM, lz("cms.ui.item.revision.from"));
private final TableColumn toCol = new TableColumn(
RevisionTableModelBuilder.TO,
lz("cms.ui.item.revision.to"));
private final TableColumn timestampCol = new TableColumn(
RevisionTableModelBuilder.TIMESTAMP, lz("cms.ui.item.revision"));
private final TableColumn userCol = new TableColumn(
RevisionTableModelBuilder.USER, lz("cms.ui.user"));
private final TableColumn descriptionCol = new TableColumn(
RevisionTableModelBuilder.DESCRIPTION, lz("cms.ui.description"));
private final TableColumn previewCol = new TableColumn(
RevisionTableModelBuilder.PREVIEW, lz("cms.ui.item.revision.view"));
private final TableColumn rollbackCol = new TableColumn(
RevisionTableModelBuilder.ROLLBACK,
lz("cms.ui.item.revision.rollback"));
public RevisionTable(final RadioGroup fromSelect,
final RadioGroup toSelect) {
super(new RevisionTableModelBuilder(itemRequestLocal),
new DefaultTableColumnModel());
final TableColumnModel columns = getColumnModel();
columns.add(fromCol);
columns.add(toCol);
columns.add(timestampCol);
columns.add(userCol);
columns.add(descriptionCol);
columns.add(previewCol);
columns.add(rollbackCol);
fromCol.setCellRenderer(new RadioCellRenderer(fromSelect));
toCol.setCellRenderer(new RadioCellRenderer(toSelect));
timestampCol.setCellRenderer(new DefaultTableCellRenderer(false));
userCol.setCellRenderer(new DefaultTableCellRenderer(false));
descriptionCol.setCellRenderer(new DefaultTableCellRenderer(false));
previewCol.setCellRenderer(new ViewCellRenderer());
rollbackCol.setCellRenderer(new RollbackCellRenderer());
setEmptyView(new Label(gz("cms.ui.item.revision.none")));
addTableActionListener(new RollbackActionListener());
}
class RadioCellRenderer implements TableCellRenderer {
private final RadioGroup group;
RadioCellRenderer(final RadioGroup group) {
this.group = group;
}
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
switch (key.toString()) {
case "first":
if (column == RevisionTableModelBuilder.FROM) {
return new NullComponent();
} else {
final Option option = new Option("", new Text(""));
option.setGroup(group);
return option;
}
case "last":
if (column == RevisionTableModelBuilder.FROM) {
final Option option = new Option("", "");
option.setGroup(group);
return option;
} else {
return new NullComponent();
}
default:
final Option option = new Option(key.toString(),
new Text(""));
option.setGroup(group);
return option;
}
}
}
class ViewCellRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
if (key instanceof String) {
return new NullComponent();
} else {
final BigInteger transID = (BigInteger) key;
final ContentItem item = itemRequestLocal.getContentItem(
state);
final ContentSection section = item.getContentType()
.getContentSection();
final ContentSectionManager sectionManager = CdiUtil
.createCdiUtil().findBean(ContentSectionManager.class);
final ItemResolver itemResolver = sectionManager
.getItemResolver(section);
final StringBuffer url = new StringBuffer(itemResolver
.generateItemURL(state, item, section,
CMSDispatcher.PREVIEW));
// Cheesy code should be fixed
final String sep;
if (url.toString().indexOf('?') == -1) {
sep = "?";
} else {
sep = "&";
}
// TODO: fix this
//url.append(sep).append
// (HistoryCollection.TRANS_ID).append("=");
url.append(sep).append("transID").append("=");
url.append(transID.toString());
final Link link = new Link(new Label(gz(
"cms.ui.item.revision.view")),
url.toString());
link.setTargetFrame(lz("cms.ui.item.revision.view"));
return link;
}
}
}
class RollbackActionListener extends TableActionAdapter {
@Override
public final void cellSelected(final TableActionEvent event) {
final PageState state = event.getPageState();
if (event.getColumn() == RevisionTableModelBuilder.ROLLBACK) {
final ContentItem item = itemRequestLocal.getContentItem(
state);
//Rollback not supported yet
// Versions.rollback(item.getOID(),
// new BigInteger(event.getRowKey()
// .toString()));
//
// item.applyTag(lz("cms.ui.item.revision.rolled_back"));
}
}
}
class RollbackCellRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
if (key instanceof String) {
return new NullComponent();
} else {
return new ControlLink(new Label(gz(
"cms.ui.item.revision.rollback")));
}
}
}
}
}

View File

@ -1,316 +0,0 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.revision;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.GridPanel;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.RadioGroup;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
import com.arsdigita.bebop.table.DefaultTableColumnModel;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableColumnModel;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.toolbox.ui.NullComponent;
import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.versioning.Transaction;
import com.arsdigita.versioning.Versions;
import java.math.BigInteger;
/**
*
* @version $Id: ItemRevisionAdminPane.java 287 2005-02-22 00:29:02Z sskracic $
*/
public final class ItemRevisionAdminPane extends BaseItemPane {
private final ContentItemRequestLocal m_item;
private final RevisionTable m_revisions;
private final TransactionRequestLocal m_from;
private final TransactionRequestLocal m_to;
private final LayoutPanel m_selectPane;
private final DifferencePane m_diffPane;
public ItemRevisionAdminPane(final ContentItemRequestLocal item) {
m_item = item;
final RadioGroup fromSelect = new RadioGroup("from");
final RadioGroup toSelect = new RadioGroup("to");
m_from = new SelectionRequestLocal(fromSelect);
m_to = new SelectionRequestLocal(toSelect);
m_revisions = new RevisionTable(fromSelect, toSelect);
final RevisionForm form = new RevisionForm
(fromSelect, toSelect, m_revisions);
m_selectPane = new LayoutPanel();
add(m_selectPane);
setDefault(m_selectPane);
m_selectPane.setBody
(new Section(gz("cms.ui.item.revisions"), form));
final ActionLink returnLink = new ActionLink
(new Label(gz("cms.ui.item.revision.return")));
m_diffPane = new DifferencePane(m_item, m_from, m_to, returnLink);
add(m_diffPane);
connect(form, m_diffPane);
connect(returnLink, m_selectPane);
}
private class SelectionRequestLocal extends TransactionRequestLocal {
private final RadioGroup m_group;
SelectionRequestLocal(final RadioGroup group) {
m_group = group;
}
protected final Object initialValue(final PageState state) {
final Object id = m_group.getValue(state);
if (id == null || id.toString().equals("")) {
return null;
} else {
return Transaction.retrieve(new BigInteger(id.toString()));
}
}
}
private class RevisionForm extends Form {
RevisionForm(final RadioGroup fromSelect,
final RadioGroup toSelect,
final RevisionTable revisions) {
super("revisions", new GridPanel(1));
setMethod("get");
add(fromSelect);
add(toSelect);
// Sets the 'to' revision to the dummy current revision
// and the 'from' revision to the dummy root revision.
fromSelect.setOptionSelected("");
toSelect.setOptionSelected("");
final ActionGroup group = new ActionGroup();
add(group);
group.setSubject(revisions);
group.addAction
(new Submit("diff",
gz("cms.ui.item.revision.difference.show")));
}
}
private class RevisionTable extends Table {
// XXX Need to fix the static l18n stuff
private TableColumn m_from = new TableColumn
(RevisionTableModelBuilder.FROM, lz("cms.ui.item.revision.from"));
private TableColumn m_to = new TableColumn
(RevisionTableModelBuilder.TO, lz("cms.ui.item.revision.to"));
private TableColumn m_timestamp = new TableColumn
(RevisionTableModelBuilder.TIMESTAMP, lz("cms.ui.item.revision"));
private TableColumn m_user = new TableColumn
(RevisionTableModelBuilder.USER, lz("cms.ui.user"));
private TableColumn m_description = new TableColumn
(RevisionTableModelBuilder.DESCRIPTION, lz("cms.ui.description"));
private TableColumn m_preview = new TableColumn
(RevisionTableModelBuilder.PREVIEW, lz("cms.ui.item.revision.view"));
private TableColumn m_rollback = new TableColumn
(RevisionTableModelBuilder.ROLLBACK,
lz("cms.ui.item.revision.rollback"));
public RevisionTable(final RadioGroup fromSelect,
final RadioGroup toSelect) {
super(new RevisionTableModelBuilder(m_item),
new DefaultTableColumnModel());
final TableColumnModel columns = getColumnModel();
columns.add(m_from);
columns.add(m_to);
columns.add(m_timestamp);
columns.add(m_user);
columns.add(m_description);
columns.add(m_preview);
columns.add(m_rollback);
m_from.setCellRenderer(new RadioCellRenderer(fromSelect));
m_to.setCellRenderer(new RadioCellRenderer(toSelect));
m_timestamp.setCellRenderer(new DefaultTableCellRenderer(false));
m_user.setCellRenderer(new DefaultTableCellRenderer(false));
m_description.setCellRenderer(new DefaultTableCellRenderer(false));
m_preview.setCellRenderer(new ViewCellRenderer());
m_rollback.setCellRenderer(new RollbackCellRenderer());
setEmptyView(new Label(gz("cms.ui.item.revision.none")));
addTableActionListener(new RollbackActionListener());
}
class RadioCellRenderer implements TableCellRenderer {
private final RadioGroup m_group;
RadioCellRenderer(final RadioGroup group) {
m_group = group;
}
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row, final int column) {
if (key.toString().equals("first")) {
if (column == RevisionTableModelBuilder.FROM) {
return new NullComponent();
} else {
final Option option = new Option("", "");
option.setGroup(m_group);
return option;
}
} else if (key.toString().equals("last")) {
if (column == RevisionTableModelBuilder.FROM) {
final Option option = new Option("", "");
option.setGroup(m_group);
return option;
} else {
return new NullComponent();
}
} else {
final Option option = new Option(key.toString(), "");
option.setGroup(m_group);
return option;
}
}
}
class ViewCellRenderer implements TableCellRenderer {
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row, final int column) {
if (key instanceof String) {
return new NullComponent();
} else {
final BigInteger transID = (BigInteger) key;
final ContentItem item = m_item.getContentItem(state);
final ContentSection section = item.getContentSection();
final ItemResolver itemResolver =
section.getItemResolver();
final StringBuffer url = new StringBuffer
(itemResolver.generateItemURL
(state, item, section, CMSDispatcher.PREVIEW));
// Cheesy code should be fixed
final String sep;
if (url.toString().indexOf('?') == -1) {
sep = "?";
} else {
sep = "&";
}
// TODO: fix this
//url.append(sep).append
// (HistoryCollection.TRANS_ID).append("=");
url.append(sep).append("transID").append("=");
url.append(transID.toString());
final Link link = new Link
(new Label(gz("cms.ui.item.revision.view")),
url.toString());
link.setTargetFrame(lz("cms.ui.item.revision.view"));
return link;
}
}
}
class RollbackActionListener extends TableActionAdapter {
public final void cellSelected(final TableActionEvent e) {
final PageState state = e.getPageState();
if (e.getColumn().intValue()
== RevisionTableModelBuilder.ROLLBACK) {
final ContentItem item = m_item.getContentItem(state);
Versions.rollback
(item.getOID(),
new BigInteger(e.getRowKey().toString()));
item.applyTag(lz("cms.ui.item.revision.rolled_back"));
}
}
}
class RollbackCellRenderer implements TableCellRenderer {
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row, final int column) {
if (key instanceof String) {
return new NullComponent();
} else {
return new ControlLink
(new Label(gz("cms.ui.item.revision.rollback")));
}
}
}
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.revision;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.RequestLocal;
import org.libreccm.auditing.CcmRevision;
public abstract class RevisionRequestLocal extends RequestLocal {
public final CcmRevision getRevision(final PageState state) {
final CcmRevision revision = (CcmRevision) get(state);
return revision;
}
}

View File

@ -0,0 +1,164 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.revision;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.globalization.GlobalizedMessage;
import org.libreccm.security.User;
import com.arsdigita.toolbox.ui.FormatStandards;
import org.libreccm.auditing.CcmRevision;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemRepository;
import java.util.List;
/**
* @author Stanislav Freidin &lt;sfreidin@redhat.com&gt;
* @author Justin Ross &lt;jross@redhat.com&gt;
* @version $Id: RevisionTableModelBuilder.java 1942 2009-05-29 07:53:23Z terry
* $
*/
class RevisionTableModelBuilder extends AbstractTableModelBuilder {
static final int FROM = 0;
static final int TO = 1;
static final int TIMESTAMP = 2;
static final int USER = 3;
static final int DESCRIPTION = 4;
static final int PREVIEW = 5;
static final int ROLLBACK = 6;
static final int COLUMNS = 7;
private final ContentItemRequestLocal itemRequestLocal;
RevisionTableModelBuilder(final ContentItemRequestLocal itemRequestLocal) {
this.itemRequestLocal = itemRequestLocal;
}
@Override
public final TableModel makeModel(final Table table,
final PageState state) {
return new Model(itemRequestLocal.getContentItem(state));
}
private static class Model implements TableModel {
private final List<CcmRevision> revisions;
private CcmRevision currentRevision;
private long count = 0;
private long last = 2;
private int index = -1;
public Model(final ContentItem item) {
final ContentItemRepository itemRepository = CdiUtil
.createCdiUtil()
.findBean(ContentItemRepository.class);
revisions = itemRepository.retrieveRevisions(item,
item.getObjectId());
last = revisions.size() + 2;
}
@Override
public final int getColumnCount() {
return COLUMNS;
}
@Override
public final boolean nextRow() {
count++;
index++;
if (count == 1) {
return true;
} else if (count == last) {
return true;
} else if (revisions.size() < index) {
currentRevision = revisions.get(index);
return true;
} else {
return false;
}
}
@Override
public final Object getElementAt(final int column) {
if (count == 1) {
switch (column) {
case TIMESTAMP:
return lz("cms.ui.item.revision.current");
default:
return "";
}
} else if (count == last) {
switch (column) {
case TIMESTAMP:
return lz("cms.ui.item.revision.first");
default:
return "";
}
} else {
switch (column) {
case TIMESTAMP:
return FormatStandards.formatDateTime(
currentRevision.getRevisionDate());
case USER:
return currentRevision.getUserName();
case DESCRIPTION:
return "";
default:
return "";
}
}
}
@Override
public final Object getKeyAt(final int column) {
if (count == 1) {
return "first";
} else if (count == last) {
return "last";
} else {
return currentRevision.getId();
}
}
}
private static GlobalizedMessage gz(final String key) {
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
}
private static String lz(final String key) {
return (String) gz(key).localize();
}
}

View File

@ -44,8 +44,17 @@ public abstract class AbstractAuditedEntityRepository<K, T>
public abstract K getEntityId(final T entity);
/**
* Retrieves an entity at specific revision. The entity will be in the state
* as it was when the revision was created.
*
* @param entity
* @param revision
*
* @return
*/
@SuppressWarnings("unchecked")
public T retrieveRevisionOfEntity(final T entity, final Number revision) {
public T retrieveEntityAtRevision(final T entity, final Number revision) {
final AuditQuery query = auditReader.createQuery()
.forEntitiesAtRevision(getEntityClass(), revision);
query.add(AuditEntity.id().eq(getEntityId(entity)));
@ -104,7 +113,7 @@ public abstract class AbstractAuditedEntityRepository<K, T>
* Retrieves all revisions of the given entity. The list of revisions is
* ordered from the oldest revision to the newest revision.
*
* @param entity The entity.
* @param entity The entity.
* @param objectId The primary key of the entity.
*
* @return A list of all revisions of the provided entity.
@ -122,9 +131,10 @@ public abstract class AbstractAuditedEntityRepository<K, T>
/**
* Retrieves the current revision of an entity.
*
* @param entity The entity.
*
* @param entity The entity.
* @param objectId the primary key the entity.
*
* @return The most current revision of the entity.
*/
public CcmRevision retrieveCurrentRevision(final T entity,
@ -136,4 +146,17 @@ public abstract class AbstractAuditedEntityRepository<K, T>
return auditReader.findRevision(CcmRevision.class, lastRevision);
}
/**
* Retrieves a specific revision object.
*
* @param entity
* @param objectId
* @param revision
*
* @return
*/
public CcmRevision retrieveRevision(final Number revision) {
return auditReader.findRevision(CcmRevision.class, revision);
}
}

View File

@ -64,6 +64,10 @@ import org.libreccm.portation.Portable;
@Table(name = "WORKFLOWS", schema = DB_SCHEMA)
@Inheritance(strategy = InheritanceType.JOINED)
@NamedQueries({
@NamedQuery(
name = "Workflow.findByUuid",
query = "SELECT W FROM Workflow w WHERE w.uuid = :uuid")
,
@NamedQuery(
name = "Workflow.findForObject",
query = "SELECT w FROM Workflow w "

View File

@ -52,22 +52,48 @@ public class WorkflowRepository extends AbstractEntityRepository<Long, Workflow>
workflow.setUuid(UUID.randomUUID().toString());
}
/**
* Find a {@link Workflow} by its UUID.
*
* @param uuid The UUID of the {@link Workflow} to find.
*
* @return An {@link Optional} containing the {@link Workflow} identified by
* the provided UUID.
*/
public Optional<Workflow> findByUuid(final String uuid) {
if (uuid == null || uuid.trim().isEmpty()) {
throw new IllegalArgumentException(
"The UUID of the Workflow to retrieve can't be null or empty.");
}
final TypedQuery<Workflow> query = getEntityManager().createNamedQuery(
"Workflow.findByUuid", Workflow.class);
query.setParameter("uuid", uuid);
try {
return Optional.of(query.getSingleResult());
} catch(NoResultException ex) {
return Optional.empty();
}
}
/**
* Finds the workflow for an given object if the object has workflow.
*
* @param object The object
*
* @return An {@link Optional} containing the workflow assigned to the
* {@code object} if the object has a workflow. Otherwise an empty
* {@link Optional} is returned.
* {@code object} if the object has a workflow. Otherwise an empty
* {@link Optional} is returned.
*/
public Optional<Workflow> findWorkflowForObject(final CcmObject object) {
if (object == null) {
throw new IllegalArgumentException(
"Can't find a workflow for object null.");
"Can't find a workflow for object null.");
}
final TypedQuery<Workflow> query = getEntityManager().createNamedQuery(
"Workflow.findForObject", Workflow.class);
"Workflow.findForObject", Workflow.class);
query.setParameter("object", object);
try {