diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ContentSectionServlet.java b/ccm-cms/src/main/java/com/arsdigita/cms/ContentSectionServlet.java
deleted file mode 100755
index d2137b794..000000000
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ContentSectionServlet.java
+++ /dev/null
@@ -1,743 +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;
-
-import com.arsdigita.bebop.Page;
-import com.arsdigita.cms.dispatcher.CMSDispatcher;
-import com.arsdigita.cms.dispatcher.CMSPage;
-import com.arsdigita.cms.dispatcher.ContentItemDispatcher;
-import com.arsdigita.cms.dispatcher.ItemResolver;
-import com.arsdigita.cms.ui.CMSApplicationPage;
-import com.arsdigita.dispatcher.AccessDeniedException;
-import com.arsdigita.dispatcher.DispatcherHelper;
-import com.arsdigita.dispatcher.RequestContext;
-import com.arsdigita.templating.PresentationManager;
-import com.arsdigita.templating.Templating;
-import com.arsdigita.util.Assert;
-import com.arsdigita.util.Classes;
-import com.arsdigita.web.ApplicationFileResolver;
-import com.arsdigita.web.BaseApplicationServlet;
-import com.arsdigita.web.LoginSignal;
-import com.arsdigita.web.Web;
-import com.arsdigita.web.WebConfig;
-import com.arsdigita.xml.Document;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.log4j.Logger;
-import org.arsdigita.cms.CMSConfig;
-import org.libreccm.cdi.utils.CdiUtil;
-import org.libreccm.l10n.GlobalizationHelper;
-import org.libreccm.security.PermissionChecker;
-import org.libreccm.security.Shiro;
-import org.libreccm.web.CcmApplication;
-import org.librecms.contentsection.ContentItem;
-import org.librecms.contentsection.ContentItemManager;
-import org.librecms.contentsection.ContentSection;
-import org.librecms.contentsection.privileges.ItemPrivileges;
-
-/*
- * NOTE:
- * Repaired ItemURLCache to save multilingual items with automatic
- * language negotiation. The cache now uses the remaining url part
- * and the language concatinated as a hash table key. The delimiter
- * is CACHE_KEY_DELIMITER.
- */
-
- /*
- * NOTE 2:
- * In a process of refactoring from legacy compatible to legacy free applications.
- * TODO:
- * - replace url check using RequestContext which resolves to SiteNodeRequest
- * implementation (due to SiteNodeRequest used in BaseApplicationServlet).
- * - Refactor content item UI bebop ApplicationPage or PageFactory instead of
- * legacy infected sitenode / package dispatchers.
- */
-/**
- * Content Section's Application Servlet according CCM core web application
- * structure {
- *
- * @see com.arsdigita.web.Application} implements the content section UI.
- *
- * It handles the UI for content items and delegates the UI for sections and
- * folders to jsp templates.
- *
- * @author unknown
- * @author Sören Bernstein
- * @author Peter Boy
- */
-public class ContentSectionServlet extends BaseApplicationServlet {
-
- /**
- * Internal logger instance to faciliate debugging. Enable logging output by
- * editing /WEB-INF/conf/log4j.properties int hte runtime environment and
- * set com.arsdigita.cms.ContentSectionServlet=DEBUG by uncommenting or
- * adding the line.
- */
- private static final Logger s_log = Logger.getLogger(
- ContentSectionServlet.class);
- /**
- * Stringarray of file name patterns for index files.
- */
-// private static final String[] WELCOME_FILES = new String[]{
-// "index.jsp", "index.html"
-// };
-
- // Some literals
- /**
- * Literal for the prefix (in url) for previewing items
- */
- public static final String PREVIEW = "/preview";
- /**
- * Literal Template files suffix
- */
- public static final String FILE_SUFFIX = ".jsp";
- /**
- * Literal of URL Stub for index file name (includes leading slash)
- */
- public static final String INDEX_FILE = "/index";
- public static final String XML_SUFFIX = ".xml";
- public static final String XML_MODE = "xmlMode";
- public static final String MEDIA_TYPE = "templateContext";
- private static final String CACHE_KEY_DELIMITER = "%";
-
- public static final String CONTENT_ITEM
- = "com.arsdigita.cms.dispatcher.item";
- public static final String CONTENT_SECTION
- = "com.arsdigita.cms.dispatcher.section";
-
- private final ContentItemDispatcher m_disp = new ContentItemDispatcher();
- public static Map s_itemResolverCache = Collections
- .synchronizedMap(new HashMap());
-// private static Map s_itemURLCacheMap = null;
- /**
- * Whether to cache the content items
- */
- private static final boolean s_cacheItems = true;
- // NEW STUFF here used to process the pages in this servlet
- /**
- * URL (pathinfo) -> Page object mapping. Based on it (and the http request
- * url) the doService method selects a page to display
- */
- private final Map m_pages = new HashMap();
- /**
- * Path to directory containg ccm-cms template (jsp) files
- */
- private String m_templatePath;
-
- /**
- * Resolver to actually use to find templates (JSP). JSP may be stored in
- * file system or otherwise, depends on resolver. Resolver is retrieved from
- * configuration. (probably used for other stuff as JSP's as well)
- */
- private ApplicationFileResolver m_resolver;
-
- /**
- * Init method overwrites parents init to pass in optional parameters
- * {@link com.arsdigita.web.BaseServlet}. If not specified system wide
- * defaults are used.
- *
- * @param config
- *
- * @throws javax.servlet.ServletException
- */
- @Override
- public void init(ServletConfig config) throws ServletException {
-
- super.init(config);
-
- // optional init-param named template-path from ~/WEB-INF/web.xml
- // may overwrite configuration parameters
- String templatePath = config.getInitParameter("template-path");
- if (templatePath == null) {
- m_templatePath = CMSConfig.getConfig().getTemplateRootPath();
- } else {
- m_templatePath = config.getInitParameter("template-path");
- }
-
- Assert.exists(m_templatePath, String.class);
- Assert.isTrue(m_templatePath.startsWith("/"),
- "template-path must start with '/'");
- Assert.isTrue(!m_templatePath.endsWith("/"),
- "template-path must not end with '/'");
-
- // optional init-param named file-resolver from ~/WEB-INF/web.xml
- String resolverName = config.getInitParameter("file-resolver");
- if (resolverName == null) {
- m_resolver = WebConfig.getConfig().getResolver();
- } else {
- m_resolver = (ApplicationFileResolver) Classes.newInstance(
- resolverName);
- }
- if (s_log.isDebugEnabled()) {
- s_log.debug("Template path is " + m_templatePath + " with resolver "
- + m_resolver.
- getClass().getName());
- }
-
- //ToDo addPage(CmsConstants.CONTENT_SECTION_PAGE, new ContentSectionPage()); // index page at address ~/cs
- //ToDo addPage(CmsConstants.CONTENT_SECTION_ITEM_PAGE, new ContentSectionPage());
- }
-
- /**
- * Internal service method, adds one pair of Url - Page to the internal hash
- * map, used as a cache.
- *
- * @param pathInfo url stub for a page to display
- * @param page Page object to display
- */
- private void addPage(final String pathInfo, final Page page) {
-
- Assert.exists(pathInfo, String.class);
- Assert.exists(page, Page.class);
- // Current Implementation requires pathInfo to start with a leading '/'
- // SUN Servlet API specifies: "PathInfo *may be empty* or will start
- // with a '/' character."
- Assert.isTrue(pathInfo.startsWith("/"), "path starts not with '/'");
-
- m_pages.put(pathInfo, page);
- }
-
- /**
- * Implementation of parent's (abstract) doService method checks HTTP
- * request to determine whether to handle a content item or other stuff
- * which is delegated to jsp templates. {
- *
- * @see com.arsdigita.web.BaseApplicationServlet#doService
- * (HttpServletRequest, HttpServletResponse, Application)}
- *
- * @param sreq
- * @param sresp
- * @param app
- *
- * @throws javax.servlet.ServletException
- * @throws java.io.IOException
- */
- @Override
- protected void doService(HttpServletRequest sreq,
- HttpServletResponse sresp,
- CcmApplication app)
- throws ServletException, IOException {
-
- ContentSection section = (ContentSection) app;
-
- // ////////////////////////////////////////////////////////////////////
- // Prepare OLD style dispatcher based page service
- // ////////////////////////////////////////////////////////////////////
- /*
- * NOTE:
- * Used to resolve to SiteNodeRequestContext (old style applications)
- * which has been removed.
- * Resolves currently to
- * KernelRequestContext which will be removed as well.
- */
- RequestContext ctx = DispatcherHelper.getRequestContext();
- String url = ctx.getRemainingURLPart(); // here KernelRequestContext now
- if (s_log.isInfoEnabled()) {
- s_log.info("Resolving URL " + url + " and trying as item first.");
- }
- final ItemResolver itemResolver = getItemResolver(section);
-
- // ////////////////////////////////////////////////////////////////////
- // Prepare NEW style servlet based bebob page service
- // ////////////////////////////////////////////////////////////////////
- String pathInfo = sreq.getPathInfo();
-
- final ContentItem item = getItem(section, pathInfo, itemResolver);
-
- Assert.exists(pathInfo, "String pathInfo");
- if (pathInfo.length() > 1 && pathInfo.endsWith("/")) {
- /* NOTE: ServletAPI specifies, pathInfo may be empty or will
- * start with a '/' character. It currently carries a
- * trailing '/' if a "virtual" page, i.e. not a real jsp, but
- * result of a servlet mapping. But Application requires url
- * NOT to end with a trailing '/' for legacy free applications. */
- pathInfo = pathInfo.substring(0, pathInfo.length() - 1);
- }
- final Page page = (Page) m_pages.get(pathInfo);
-
- // ////////////////////////////////////////////////////////////////////
- // Serve the page
- // ////////////////////////////////////////////////////////////////////
- /* FIRST try new style servlet based service */
- if (page != null) {
-
- // Check user access.
- // checkUserAccess(sreq, sresp); // done in individual pages ??
- if (page instanceof CMSPage) {
- // backwards compatibility fix until migration completed
- final CMSPage cmsPage = (CMSPage) page;
- // final RequestContext ctx = DispatcherHelper.getRequestContext();
- cmsPage.init();
- cmsPage.dispatch(sreq, sresp, ctx);
- } else {
- final CMSApplicationPage cmsAppPage = (CMSApplicationPage) page;
- cmsAppPage.init(sreq, sresp, app);
- // Serve the page.
- final Document doc = cmsAppPage.buildDocument(sreq, sresp);
-
- PresentationManager pm = Templating.getPresentationManager();
- pm.servePage(doc, sreq, sresp);
- }
-
- /* SECONDLY try if we have to serve an item (old style dispatcher based */
- } else if (item != null) {
-
- serveItem(sreq, sresp, section, item);
-
- /* OTHERWISE delegate to a JSP in file system */
- } else {
-
- /* We have to deal with a content-section, folder or another bit */
- if (s_log.isInfoEnabled()) {
- s_log.info("NOT serving content item");
- }
-
- /* Store content section in http request to make it available
- * for admin/index.jsp */
- sreq.setAttribute(CONTENT_SECTION, section);
-
- RequestDispatcher rd = m_resolver.resolve(m_templatePath,
- sreq, sresp, app);
- if (rd != null) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Got dispatcher " + rd);
- }
- sreq = DispatcherHelper.restoreOriginalRequest(sreq);
- rd.forward(sreq, sresp);
- } else {
- if (s_log.isDebugEnabled()) {
- s_log.debug("No dispatcher found for" + rd);
- }
- String requestUri = sreq.getRequestURI(); // same as ctx.getRemainingURLPart()
- sresp.sendError(404, requestUri + " not found on this server.");
- }
- }
- } // END doService
-
- /**
- *
- * @param sreq
- * @param sresp
- * @param section
- * @param item
- *
- * @throws ServletException
- * @throws IOException
- */
- private void serveItem(HttpServletRequest sreq,
- HttpServletResponse sresp,
- ContentSection section,
- ContentItem item)
- throws ServletException, IOException {
-
- if (s_log.isInfoEnabled()) {
- s_log.info("serving content item");
- }
-
- RequestContext ctx = DispatcherHelper.getRequestContext();
- String url = ctx.getRemainingURLPart();
-
- final ItemResolver itemResolver = getItemResolver(section);
-
- //set the content item in the request
- sreq.setAttribute(CONTENT_ITEM, item);
-
- //set the template context
- //TemplateResolver templateResolver = m_disp.getTemplateResolver(section);
- String templateURL = url;
- if (!templateURL.startsWith("/")) {
- templateURL = "/" + templateURL;
- }
- if (templateURL.startsWith(PREVIEW)) {
- templateURL = templateURL.substring(PREVIEW.length());
- }
-
- String sTemplateContext = itemResolver.getTemplateFromURL(templateURL);
- if (s_log.isDebugEnabled()) {
- s_log.debug("setting template context to " + sTemplateContext);
- }
- //templateResolver.setTemplateContext(sTemplateContext, sreq);
-
- // Work out how long to cache for....
- // We take minimum(default timeout, lifecycle expiry)
- //ToDo
- /*Lifecycle cycle = item.getLifecycle();
- */
- int expires = DispatcherHelper.getDefaultCacheExpiry();
- /*
- if (cycle != null) {
- Date endDate = cycle.getEndDate();
-
- if (endDate != null) {
- int maxAge = (int) ((endDate.getTime() - System
- .currentTimeMillis()) / 1000l);
- if (maxAge < expires) {
- expires = maxAge;
- }
- }
- }*/
- //ToDo End
-
- // NB, this is not the same as the security check previously
- // We are checking if anyone can access - ie can we allow
- // this page to be publically cached
- final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
- final ContentItemManager contentItemManager = cdiUtil.findBean(
- ContentItemManager.class);
- final PermissionChecker permissionChecker = cdiUtil.findBean(
- PermissionChecker.class);
- if (s_cacheItems && contentItemManager.isLive(item)) {
- if (permissionChecker.isPermitted(
- ItemPrivileges.VIEW_PUBLISHED, item)) {
- DispatcherHelper.cacheForWorld(sresp, expires);
- } else {
- DispatcherHelper.cacheForUser(sresp, expires);
- }
- } else {
- DispatcherHelper.cacheDisable(sresp);
- }
-
- //use ContentItemDispatcher
- m_disp.dispatch(sreq, sresp, ctx);
- }
-
- /**
- * Fetches the content section from the request attributes.
- *
- * @param request The HTTP request
- *
- * @return The content section
- *
- * @pre ( request != null )
- */
- public static ContentSection getContentSection(HttpServletRequest request) {
- return (ContentSection) request.getAttribute(CONTENT_SECTION);
- }
-
- /**
- * Fetches the ItemResolver for a content section. Checks cache first.
- *
- * @param section The content section
- *
- * @return The ItemResolver associated with the content section
- */
- public ItemResolver getItemResolver(ContentSection section) {
-
- String path = section.getPrimaryUrl();
- ItemResolver ir = (ItemResolver) s_itemResolverCache.get(path);
-
- if (ir == null) {
- final String itemResolverClassName = section.getItemResolverClass();
- try {
- ir = (ItemResolver) Class
- .forName(section.getItemResolverClass()).newInstance();
- } catch (ClassNotFoundException |
- IllegalAccessException |
- InstantiationException ex) {
- throw new RuntimeException(ex);
- }
- s_itemResolverCache.put(path, ir);
- }
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("using ItemResolver " + ir.getClass().getName());
- }
-
- return ir;
- }
-
- /**
- *
- * @param section
- * @param url
- * @param itemResolver
- *
- * @return
- */
- public ContentItem getItem(ContentSection section, String url,
- ItemResolver itemResolver) {
-
- if (s_log.isDebugEnabled()) {
- s_log.debug("getting item at url " + url);
- }
- HttpServletRequest request = Web.getRequest();
-
- //first sanitize the url
- if (url.endsWith(XML_SUFFIX)) {
- request.setAttribute(XML_MODE, Boolean.TRUE);
- s_log.debug("StraightXML Requested");
- url = "/" + url.substring(0, url.length() - XML_SUFFIX.length());
- } else {
- request.setAttribute(XML_MODE, Boolean.FALSE);
- if (url.endsWith(FILE_SUFFIX)) {
- url = "/" + url
- .substring(0, url.length() - FILE_SUFFIX.length());
- } else if (url.endsWith("/")) {
- url = "/" + url.substring(0, url.length() - 1);
- }
- }
-
- if (!url.startsWith("/")) {
- url = "/" + url;
- }
-
- ContentItem item;
- // Check if the user has access to view public or preview pages
- final PermissionChecker permissionChecker = CdiUtil.createCdiUtil()
- .findBean(PermissionChecker.class);
- boolean hasPermission = true;
-
- // If the remaining URL starts with "preview/", then try and
- // preview this item. Otherwise look for the live item.
- boolean preview = false;
- if (url.startsWith(PREVIEW)) {
- url = url.substring(PREVIEW.length());
- preview = true;
- }
-
- if (preview) {
- if (s_log.isInfoEnabled()) {
- s_log.info("Trying to get item for PREVIEW");
- }
-
- item = itemResolver.getItem(section, url, CMSDispatcher.PREVIEW);
- if (item != null) {
- hasPermission = permissionChecker.isPermitted(
- ItemPrivileges.PREVIEW, item);
- }
- } else {
- if (s_log.isInfoEnabled()) {
- s_log.info("Trying to get LIVE item");
- }
-
- //check if this item is in the cache
- //we only cache live items
- if (s_log.isDebugEnabled()) {
- s_log.debug("Trying to get content item for URL " + url
- + " from cache");
- }
-
- // Get the negotiated locale
- String lang = CdiUtil.createCdiUtil().findBean(
- GlobalizationHelper.class).getNegotiatedLocale()
- .getLanguage();
-
- // XXX why assign a value and afterwards null??
- // Effectively it just ignores the cache and forces a fallback to
- // itemResover in any case. Maybe otherwise language selection /
- // negotiation doesn't work correctly?
-// item = itemURLCacheGet(section, url, lang);
- item = null;
-
- if (item == null) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Did not find content item in cache, so trying "
- + "to retrieve and cache...");
- }
- //item not cached, so retreive it and cache it
- item = itemResolver.getItem(section, url, "live");
-// itemURLCachePut(section, url, lang, item);
- } else if (s_log.isDebugEnabled()) {
- s_log.debug("Found content item in cache");
- }
-
- //ToDo
-// if (s_log.isDebugEnabled() && item != null) {
-// s_log.debug("Sanity check: item.getPath() is " + item.getPath());
-// }
- if (item != null) {
- if (s_log.isDebugEnabled()) {
- s_log.debug("Content Item is not null");
- }
-
- hasPermission = permissionChecker.isPermitted(
- ItemPrivileges.VIEW_PUBLISHED, item);
-
- if (hasPermission) {
- }
- }
- }
-
- if (item == null && url.endsWith(INDEX_FILE)) {
-
- if (item == null) {
- if (s_log.isInfoEnabled()) {
- s_log.info("no item found");
- }
- }
-
- // look up folder if it's an index
- url = url.substring(0, url.length() - INDEX_FILE.length());
- if (s_log.isInfoEnabled()) {
- s_log.info("Attempting to match folder " + url);
- }
- item = itemResolver.getItem(section, url, "live");
- if (item != null) {
- hasPermission = permissionChecker.isPermitted(
- ItemPrivileges.VIEW_PUBLISHED, item);
- }
- }
-
- if (!hasPermission) {
-
- // first, check if the user is logged-in
- // if he isn't, give him a chance to do so...
- if (!CdiUtil.createCdiUtil().findBean(Shiro.class).getSubject()
- .isAuthenticated()) {
- throw new LoginSignal(request);
- }
-
- throw new AccessDeniedException();
- }
-
- return item;
- }
-
- public ContentItem getItem(ContentSection section, String url) {
- ItemResolver itemResolver = getItemResolver(section);
-
- return getItem(section, url, itemResolver);
- }
-
- // synchronize access to the item-url cache
-// private static synchronized void itemURLCachePut(ContentSection section,
-// String sURL,
-// String lang,
-// Long itemID) {
-//
-// getItemURLCache(section).put(sURL + CACHE_KEY_DELIMITER + lang, itemID);
-// }
- /**
- * Maps the content item to the URL in a cache
- *
- * @param section the content section in which the content item is published
- * @param sURL the URL at which the content item s published
- * @param lang
- * @param item the content item at the URL
- */
-// public static synchronized void itemURLCachePut(ContentSection section,
-// String sURL,
-// String lang,
-// ContentItem item) {
-// if (sURL == null || item == null) {
-// return;
-// }
-// if (s_log.isDebugEnabled()) {
-// s_log.debug("adding cached entry for url " + sURL + " and language "
-// + lang);
-// }
-//
-// itemURLCachePut(section, sURL, lang, item.getObjectId());
-// }
- /**
- * Removes the cache entry for the URL, sURL
- *
- * @param section the content section in which to remove the key
- * @param sURL the cache entry key to remove
- * @param lang
- */
-// public static synchronized void itemURLCacheRemove(ContentSection section,
-// String sURL,
-// String lang) {
-// if (s_log.isDebugEnabled()) {
-// s_log.debug("removing cached entry for url " + sURL
-// + "and language " + lang);
-// }
-// getItemURLCache(section).remove(sURL + CACHE_KEY_DELIMITER + lang);
-// }
- /**
- * Fetches the ContentItem published at that URL from the cache.
- *
- * @param section the content section in which the content item is published
- * @param sURL the URL for the item to fetch
- * @param lang
- *
- * @return the ContentItem in the cache, or null
- */
-// public static ContentItem itemURLCacheGet(ContentSection section,
-// final String sURL,
-// final String lang) {
-// final Long itemID = (Long) getItemURLCache(section).get(
-// sURL + CACHE_KEY_DELIMITER + lang);
-//
-// if (itemID == null) {
-// return null;
-// } else {
-//
-// final ContentItemRepository itemRepo = CdiUtil.createCdiUtil().findBean(ContentItemRepository.class);
-// return itemRepo.findById(itemID);
-//
-// }
-// }
-// private static synchronized CacheTable getItemURLCache(
-// ContentSection section) {
-// Assert.exists(section, ContentSection.class);
-// if (s_itemURLCacheMap == null) {
-// initializeItemURLCache();
-// }
-//
-// if (s_itemURLCacheMap.get(section.getPath()) == null) {
-// final CacheTable cache = new CacheTable(
-// "ContentSectionServletItemURLCache" + section.getID().toString());
-// s_itemURLCacheMap.put(section.getPath(), cache);
-// }
-//
-// return (CacheTable) s_itemURLCacheMap.get(section.getPath());
-// }
-//
-// private static synchronized void initializeItemURLCache() {
-// ContentSectionCollection sections = ContentSection.getAllSections();
-// s_itemURLCacheMap = new HashMap();
-// while (sections.next()) {
-// ContentSection section = sections.getContentSection();
-// String idStr = section.getID().toString();
-// String path = section.getPath();
-// CacheTable itemURLCache = new CacheTable(
-// "ContentSectionServletItemURLCache" + idStr);
-// s_itemURLCacheMap.put(path, itemURLCache);
-//
-// }
-// }
- /**
- * Checks that the current user has permission to access the admin pages.
- *
- * @param request
- * @param section
- *
- * @return
- *
- */
- public static boolean checkAdminAccess(HttpServletRequest request,
- ContentSection section) {
- return CdiUtil.createCdiUtil().findBean(PermissionChecker.class)
- .isPermitted(ItemPrivileges.EDIT,
- section.getRootDocumentsFolder());
- }
-
-}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ItemSelectionModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ItemSelectionModel.java
index 08e2f521c..5b50a0a01 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ItemSelectionModel.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ItemSelectionModel.java
@@ -28,7 +28,7 @@ import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentType;
import org.librecms.contentsection.ContentTypeRepository;
-
+import org.librecms.contenttypes.ContentTypeInfo;
import java.math.BigDecimal;
@@ -44,16 +44,16 @@ import java.math.BigDecimal;
* model will only instantiate items that are of the specified content type, or
* one of it subclasses.
*
+ * @author Jens Pelzetter
* @author Stanislav Freidin (stas@arsdigita.com)
- * @version $Revision$ $DateTime: 2004/08/17 23:15:09 $
* @see com.arsdigita.kernel.ui.ACSObjectSelectionModel
* @see com.arsdigita.bebop.SingleSelectionModel
*/
-public class ItemSelectionModel extends CcmObjectSelectionModel {
+public class ItemSelectionModel extends CcmObjectSelectionModel {
- private Long m_typeId;
+ private Long typeId;
- private static final Logger s_log = Logger.getLogger(
+ private static final Logger LOGGER = Logger.getLogger(
ItemSelectionModel.class);
/**
@@ -65,7 +65,8 @@ public class ItemSelectionModel extends CcmObjectSelectionModel {
* @param parameterName The name of the state parameter which will be used
* to store the item.
*/
- public ItemSelectionModel(ContentType type, String parameterName) {
+ public ItemSelectionModel(final ContentType type,
+ final String parameterName) {
this(type, new LongParameter(parameterName));
}
@@ -77,9 +78,10 @@ public class ItemSelectionModel extends CcmObjectSelectionModel {
* @param parameter The state parameter which should be used by this item
*
*/
- public ItemSelectionModel(ContentType type, LongParameter parameter) {
+ public ItemSelectionModel(final ContentType type,
+ final LongParameter parameter) {
super(type.getContentItemClass(), parameter);
- m_typeId = type.getObjectId();
+ typeId = type.getObjectId();
}
/**
@@ -91,22 +93,35 @@ public class ItemSelectionModel extends CcmObjectSelectionModel {
* {@link BigDecimal} id of the currently selected object
*
*/
- public ItemSelectionModel(ContentType type, SingleSelectionModel model) {
+ public ItemSelectionModel(final ContentType type,
+ final SingleSelectionModel model) {
super(type.getContentItemClass(), model);
- m_typeId = type.getObjectId();
+ typeId = type.getObjectId();
}
+ public ItemSelectionModel(final ContentTypeInfo type,
+ final SingleSelectionModel model) {
+ super(type.getContentItemClass().getName(), model);
+ typeId = null;
+ }
+
+ public ItemSelectionModel(final ContentTypeInfo type,
+ final LongParameter parameter) {
+ super(type.getContentItemClass().getName(), parameter);
+ typeId = null;
+ }
+
/**
* A convenience method that gets the currently selected object and casts it
* to a ContentItem
*
- * @param s the current page state
+ * @param state the current page state
*
* @return the currently selected ContentItem, or null if no
* item was selected.
*/
- public final ContentItem getSelectedItem(PageState s) {
- return (ContentItem) getSelectedObject(s);
+ public final ContentItem getSelectedItem(final PageState state) {
+ return getSelectedObject(state);
}
/**
@@ -119,8 +134,9 @@ public class ItemSelectionModel extends CcmObjectSelectionModel {
ContentType type = null;
- if (m_typeId != null) {
- type = CdiUtil.createCdiUtil().findBean(ContentTypeRepository.class).findById(m_typeId);
+ if (typeId != null) {
+ type = CdiUtil.createCdiUtil().findBean(ContentTypeRepository.class)
+ .findById(typeId);
}
return type;
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSPage.java b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSPage.java
index 99a5c934c..451640591 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSPage.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSPage.java
@@ -24,7 +24,6 @@ import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.page.PageTransformer;
-import com.arsdigita.cms.ContentSectionServlet;
import com.arsdigita.dispatcher.RequestContext;
import com.arsdigita.templating.PresentationManager;
import com.arsdigita.web.Web;
@@ -48,6 +47,7 @@ import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSection;
+import org.librecms.contentsection.ContentSectionServlet;
import org.librecms.contentsection.privileges.ItemPrivileges;
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentItemDispatcher.java b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentItemDispatcher.java
index 60f884113..71c55a6f3 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentItemDispatcher.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentItemDispatcher.java
@@ -18,7 +18,6 @@
*/
package com.arsdigita.cms.dispatcher;
-import com.arsdigita.cms.ContentSectionServlet;
import com.arsdigita.dispatcher.Dispatcher;
import com.arsdigita.dispatcher.DispatcherHelper;
import com.arsdigita.dispatcher.RequestContext;
@@ -80,7 +79,7 @@ public class ContentItemDispatcher implements Dispatcher {
throws IOException, ServletException {
Boolean bXMLMode = (Boolean) request
- .getAttribute(ContentSectionServlet.XML_MODE);
+ .getAttribute("xmlMode");
if (bXMLMode != null && bXMLMode.booleanValue()) {
//if this is XML mode, then use itemXML
m_itemXML.dispatch(request, response, actx);
@@ -119,7 +118,7 @@ public class ContentItemDispatcher implements Dispatcher {
*/
public static ContentItem getContentItem(HttpServletRequest request) {
return (ContentItem) request.getAttribute(
- ContentSectionServlet.CONTENT_ITEM);
+ "com.arsdigita.cms.dispatcher.item");
}
// //synchronize access to the cache
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentPanel.java b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentPanel.java
index 7970f765a..3704fd3ed 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentPanel.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentPanel.java
@@ -21,13 +21,13 @@ package com.arsdigita.cms.dispatcher;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleComponent;
import com.arsdigita.cms.CMS;
-import com.arsdigita.cms.ContentSectionServlet;
import com.arsdigita.dispatcher.DispatcherHelper;
import com.arsdigita.util.Assert;
import com.arsdigita.xml.Element;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
+import org.librecms.contentsection.ContentSectionServlet;
import java.util.logging.Level;
import java.util.logging.Logger;
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemDispatcher.java b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemDispatcher.java
index f73affa4b..5b7959e3b 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemDispatcher.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemDispatcher.java
@@ -18,7 +18,6 @@
*/
package com.arsdigita.cms.dispatcher;
-import com.arsdigita.cms.ContentSectionServlet;
import com.arsdigita.dispatcher.ChainedDispatcher;
import com.arsdigita.dispatcher.DispatcherHelper;
import com.arsdigita.dispatcher.RequestContext;
@@ -39,6 +38,7 @@ import org.libreccm.security.PermissionChecker;
import org.libreccm.security.Shiro;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
+import org.librecms.contentsection.ContentSectionServlet;
import org.librecms.contentsection.privileges.ItemPrivileges;
/**
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/SimpleItemResolver.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/SimpleItemResolver.java.off
new file mode 100755
index 000000000..d9d855e5b
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/SimpleItemResolver.java.off
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2001-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.dispatcher;
+
+
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.cms.CMS;
+import org.librecms.contentsection.ContentItem;
+import org.librecms.contentsection.ContentSection;
+import org.librecms.contentsection.Folder;
+import com.arsdigita.cms.ContentCenter;
+import com.arsdigita.cms.ui.ContentItemPage;
+import com.arsdigita.dispatcher.DispatcherHelper;
+import org.apache.log4j.Logger;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.util.StringTokenizer;
+
+/**
+ * This is the default implementation of
+ * {@link com.arsdigita.cms.dispatcher.ItemResolver}.
+ *
+ * The getItem method of the default implementation of
+ * ItemResolver,
+ * {@link com.arsdigita.cms.dispatcher.SimpleItemResolver}
+ * runs a simple query using the passed in information to retrieve the
+ * content item with a name that matches the URL stub, in our example
+ * it looks for a content item with name cheese. If no such item
+ * exists, or if there is such an item, but without a live version, even
+ * though one has been requested, getItem returns null.
+ *
+ * After the CMS Dispatcher received the content item from the
+ * ItemResolver, it also asks it for the
+ * {@link com.arsdigita.cms.dispatcher.MasterPage} for that item in the
+ * current request. With the content item and the master page in hand,
+ * the dispatcher calls service on the page.
+ *
+ * @author Michael Pih (pihman@arsdigita.com)
+ * @version $Revision: #15 $ $DateTime: 2004/08/17 23:15:09 $
+ * @version $Id: SimpleItemResolver.java 2090 2010-04-17 08:04:14Z pboy $
+ */
+public class SimpleItemResolver extends AbstractItemResolver implements ItemResolver {
+
+ private static final Logger s_log =
+ Logger.getLogger(SimpleItemResolver.class.getName());
+
+ private static final String ADMIN_PREFIX = "admin";
+ private static final String WORKSPACE_PREFIX = ContentCenter.getURL();
+
+ private static MasterPage s_masterP = null;
+
+ public SimpleItemResolver() {}
+
+ /**
+ * Return a content item based on page state (and content section).
+ *
+ * @param section The current content section
+ * @param url The section-relative URL
+ * @param context The LIVE/DRAFT context (*not* the template use context)
+ * @return The content item mapped to the content section and URL, or
+ * null if no such item exists
+ */
+ public ContentItem getItem(ContentSection section, String url,
+ String context) {
+
+ if (s_log.isDebugEnabled()) {
+ s_log.debug("trying to get " + context + " item for url " + url);
+ }
+
+ String itemUrl = stripTemplateFromURL(url);
+
+ // getItem fails if called from a JSP template, because the request URL
+ // gets replaced with the filesystem path to the JSP (when
+ // DispatcherHelper.forwardRequestByPath is called). To fix this, we check
+ // if the item had already been put into the request by the CMSDispatcher
+ // (which it usually has) and return it.
+ ContentItem reqItem = (ContentItem) DispatcherHelper.getRequest().
+ getAttribute("com.arsdigita.cms.dispatcher.item");
+ if (reqItem != null) {
+ s_log.info("found item in the request, returning it");
+ return reqItem;
+ }
+
+ //ContentItem item = getCachedItem(section, itemUrl, context);
+ //if (item != null) {
+ // return item;
+ //}
+
+ Folder rootFolder = section.getRootFolder();
+ if ( rootFolder == null ) {
+ s_log.info("no root folder found, returning null");
+ return null;
+ }
+
+ if ( context.equals(ContentItem.LIVE) ) {
+ rootFolder = (Folder) rootFolder.getLiveVersion();
+ if ( rootFolder == null ) {
+ s_log.info("no LIVE version of root folder found, returning null");
+ return null;
+ }
+ } else if ( context.equals(ContentItem.DRAFT) ) {
+ // Do nothing ?
+ } else {
+ throw new RuntimeException(
+ "getItem: Invalid item resolver context " + context);
+ }
+
+ ContentItem item = getItem(itemUrl, rootFolder);
+ //if (item != null) {
+ // cacheItem(section, itemUrl, context, item);
+ //}
+
+ return item;
+ }
+
+ /**
+ * @param state the current page state
+ * @return the context of the current URL, such as "live" or "admin"
+ */
+ public String getCurrentContext(PageState state) {
+
+ String url = state.getRequest().getRequestURI();
+
+ ContentSection section =
+ CMS.getContext().getContentSection();
+
+ // If this page is associated with a content section, transform
+ // the URL so that it is relative to the content section site node.
+ if ( section != null ) {
+ String sectionURL = section.getURL();
+ if ( url.startsWith(sectionURL) ) {
+ url = url.substring(sectionURL.length());
+ }
+ }
+
+ // remove any template-specific URL components
+ // (will only work if they're first in the URL at this point: verify
+ url = stripTemplateFromURL(url);
+
+ // Determine if we are under the admin UI.
+ if ( url.startsWith(ADMIN_PREFIX) ||
+ url.startsWith(WORKSPACE_PREFIX) ) {
+ return ContentItem.DRAFT;
+ } else {
+ return ContentItem.LIVE;
+ }
+ }
+
+ /**
+ * Return the content item at the specified path, or null
+ * if no such item exists. The path is interpreted as a series
+ * of folders; for example, "/foo/bar/baz" will look for
+ * an item named "baz" in a folder named "bar" in a folder named "foo"
+ * under the specified root folder.
+ *
+ * @param url the URL to the item
+ * @param rootFolder The root folder where the item search will start
+ * @return the item on success, null if no such item exists
+ * @pre rootFolder != null
+ * @pre url != null
+ */
+ public ContentItem getItem(String url, Folder rootFolder) {
+
+ StringTokenizer tokenizer = new StringTokenizer(url, "/");
+ String name = null;
+ Folder oldFolder = null;
+
+ while(rootFolder != null && tokenizer.hasMoreTokens()) {
+ name = tokenizer.nextToken();
+ oldFolder = rootFolder;
+ rootFolder = (Folder)rootFolder.getItem(name, true);
+ }
+
+ if(tokenizer.hasMoreTokens()) {
+ // failure
+ s_log.debug("no more tokens found, returning null");
+ return null;
+ } else {
+ // Get the content item which is the last token
+ if (rootFolder != null ) {
+ ContentItem indexItem = rootFolder.getIndexItem();
+ if (indexItem != null) {
+ s_log.info("returning index item for folder");
+ return indexItem;
+ }
+ }
+ if ( name == null ) {
+ s_log.debug("no name found");
+ return null;
+ }
+ return oldFolder.getItem(name, false);
+ }
+ }
+
+ // Generate the URL for an item in the DRAFT context
+ private String generateDraftURL(BigDecimal itemId, ContentSection section) {
+ return ContentItemPage.getItemURL(section.getFullPath() + "/", itemId,
+ ContentItemPage.AUTHORING_TAB);
+ }
+
+
+ // Generate the URL for an item in the LIVE context with a given template context
+ private String generateLiveURL(ContentItem item, ContentSection section,
+ String templateContext) {
+ String templateURLFrag =
+ (templateContext == null || templateContext.length() == 0) ?
+ "" : TEMPLATE_CONTEXT_PREFIX + templateContext + "/";
+ return section.getPath() + "/" + templateURLFrag + item.getPath();
+ }
+
+
+ // Generate the preview URL for an item in the DRAFT context
+ private String generatePreviewURL(ContentItem item, ContentSection section,
+ String templateContext) {
+ String templateURLFrag =
+ (templateContext == null || templateContext.length() == 0) ?
+ "" : TEMPLATE_CONTEXT_PREFIX + templateContext + "/";
+ StringBuffer url = new StringBuffer();
+ url
+ .append(section.getPath())
+ .append("/" + CMSDispatcher.PREVIEW)
+ .append("/")
+ .append(templateURLFrag)
+ .append(item.getPath());
+ return url.toString();
+ }
+
+ /**
+ * Generates a URL for a content item.
+ *
+ * @param itemId The item ID
+ * @param name The name of the content page
+ * @param state The page state
+ * @param section the content section to which the item belongs
+ * @param context the context of the URL, such as "LIVE" or "DRAFT"
+ * @return The URL of the item
+ * @pre context != null
+ */
+ public String generateItemURL(PageState state, BigDecimal itemId,
+ String name, ContentSection section,
+ String context) {
+ return generateItemURL(state, itemId, name, section, context, null);
+ }
+
+ /**
+ * Generates a URL for a content item.
+ *
+ * @param itemId The item ID
+ * @param name The name of the content page
+ * @param state The page state
+ * @param section the content section to which the item belongs
+ * @param context the context of the URL, such as "live" or "admin"
+ * @param templateContext the context for the URL, such as "public"
+ * @return The URL of the item
+ * @pre context != null
+ */
+ public String generateItemURL(PageState state, BigDecimal itemId,
+ String name, ContentSection section,
+ String context, String templateContext) {
+ if ( ContentItem.DRAFT.equals(context) ) {
+ return generateDraftURL(itemId, section);
+ } else if (ContentItem.LIVE.equals(context)) {
+ ContentItem item = new ContentItem(itemId);
+ return generateLiveURL(item, section, templateContext);
+ } else if (CMSDispatcher.PREVIEW.equals(context)) {
+ ContentItem item = new ContentItem(itemId);
+ return generatePreviewURL(item, section, templateContext);
+ } else {
+ throw new RuntimeException( (String) GlobalizationUtil.globalize("cms.dispatcher.unknown_context").localize() + context);
+ }
+ }
+
+ /**
+ * Generates a URL for a content item.
+ *
+ * @param item The item
+ * @param state The page state
+ * @param section the content section to which the item belongs
+ * @param context the context of the URL, such as "LIVE" or "DRAFT"
+ * @return The URL of the item
+ * @see #getCurrentContext
+ */
+ public String generateItemURL (
+ PageState state, ContentItem item, ContentSection section, String context
+ ) {
+ return generateItemURL(state, item, section, context, null);
+ }
+ /**
+ * Generates a URL for a content item.
+ *
+ * @param item The item
+ * @param state The page state
+ * @param section the content section to which the item belongs
+ * @param context the context of the URL, such as "live" or "admin"
+ * @param templateContext the context for the URL, such as "public"
+ * @return The URL of the item
+ * @see #getCurrentContext
+ */
+ public String generateItemURL (
+ PageState state, ContentItem item, ContentSection section,
+ String context, String templateContext
+ ) {
+ if (ContentItem.LIVE.equals(context)) {
+ return generateLiveURL(item, section, templateContext);
+ } else if (ContentItem.DRAFT.equals(context)) {
+ return generateDraftURL(item.getID(), section);
+ } else if (CMSDispatcher.PREVIEW.equals(context)) {
+ return generatePreviewURL(item, section, templateContext);
+ } else {
+ throw new RuntimeException( (String) GlobalizationUtil.globalize("cms.dispatcher.unknown_context").localize() + context);
+ }
+ }
+
+ /**
+ * Return a master page based on page state (and content section).
+ *
+ * @param item The content item
+ * @param request The HTTP request
+ */
+ public CMSPage getMasterPage(ContentItem item, HttpServletRequest request)
+ throws ServletException {
+
+ if ( s_masterP == null ) {
+ s_masterP = new MasterPage();
+ s_masterP.init();
+ }
+
+ return s_masterP;
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.off
index c05bed15a..2d39a421f 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.off
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java.off
@@ -48,12 +48,8 @@ import com.arsdigita.cms.ui.lifecycle.ItemLifecycleAdminPane;
import com.arsdigita.cms.ui.revision.ItemRevisionAdminPane;
import com.arsdigita.cms.ui.templates.ItemTemplates;
import com.arsdigita.cms.ui.workflow.ItemWorkflowAdminPane;
-import com.arsdigita.cms.util.GlobalizationUtil;
-import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
-import com.arsdigita.persistence.OID;
-import com.arsdigita.ui.DebugPanel;
import com.arsdigita.util.Assert;
import com.arsdigita.xml.Document;
import com.arsdigita.xml.Element;
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitSelector.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitSelector.java
similarity index 58%
rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitSelector.java.off
rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitSelector.java
index 19906bd97..9ca65ca9d 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitSelector.java.off
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitSelector.java
@@ -25,20 +25,24 @@ import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.SingleSelectionModel;
-import org.librecms.contentsection.ContentType;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.xml.Element;
import org.apache.logging.log4j.LogManager;
-import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.Logger;
+import org.libreccm.cdi.utils.CdiUtil;
+import org.librecms.contentsection.ContentType;
+import org.librecms.contenttypes.AuthoringKitInfo;
+import org.librecms.contenttypes.ContentTypeInfo;
+import org.librecms.contenttypes.ContentTypesManager;
import java.util.List;
+import java.util.Objects;
/**
* Selects a component based on content type. Helper class for {@link
@@ -51,9 +55,9 @@ public abstract class AuthoringKitSelector extends SimpleContainer {
private static final Logger LOGGER = LogManager.getLogger(
AuthoringKitSelector.class);
- private Map m_comps;
- private MapComponentSelectionModel m_sel;
- private List m_types;
+ private final Map components;
+ private final MapComponentSelectionModel selectionModel;
+ private final List types;
/**
* Construct a new AuthoringKitSelector. Load all the possible authoring
@@ -64,45 +68,52 @@ public abstract class AuthoringKitSelector extends SimpleContainer {
*
* @pre itemModel != null
*/
- public AuthoringKitSelector(final SingleSelectionModel model) {
+ public AuthoringKitSelector(final SingleSelectionModel model) {
super();
- m_comps = new HashMap();
- m_sel = new MapComponentSelectionModel(model, m_comps);
+ components = new HashMap<>();
+ selectionModel = new MapComponentSelectionModel<>(model, components);
- m_types = ContentType.getAllContentTypes();
- if (m_types.isEmpty()) {
+
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final ContentTypesManager typesManager = cdiUtil.findBean(
+ ContentTypesManager.class);
+ types = typesManager.getAvailableContentTypes();
+
+ if (types.isEmpty()) {
throw new RuntimeException("No Content Types were found.");
}
}
// Overloaded add methods
@Override
- public void add(Component c) {
+ public void add(final Component component) {
throw new UnsupportedOperationException();
}
// Overloaded add methods
@Override
- public void add(Component c, int constraints) {
+ public void add(final Component component, final int constraints) {
throw new UnsupportedOperationException();
}
/**
* Instantiate all the authoring kit wizards. The child class should call
- * this method after it is done with initialization.
+ * this method after it is done with initialisation.
*/
protected void processKit() {
- while (m_types.next()) {
- ContentType type = m_types.getContentType();
- AuthoringKit kit = type.getAuthoringKit();
+ for (final ContentTypeInfo type : types) {
+ final AuthoringKitInfo kit = type.getAuthoringKit();
if (kit != null) {
- Component c = instantiateKitComponent(kit, type);
- if (c != null) {
- super.add(c);
- m_comps.put(type.getID(), c);
- LOGGER.info("Added component " + c + " for "
- + type.getAssociatedObjectType());
+ final Component component = instantiateKitComponent(kit, type);
+ if (component != null) {
+ super.add(component);
+ components.put(type.getContentItemClass().getName(),
+ component);
+ LOGGER.info("Added component {} for {}",
+ Objects.toString(component),
+ type.getContentItemClass().getName());
}
}
}
@@ -115,36 +126,40 @@ public abstract class AuthoringKitSelector extends SimpleContainer {
*
* @param kit for this kit
* @param type for this type
+ *
+ * @return
*/
protected abstract Component instantiateKitComponent(
- AuthoringKit kit, ContentType type);
+ final AuthoringKitInfo kit, final ContentTypeInfo type);
/**
- * @param id The content type id
+ *
+ * @param typeClass
*
* @return The component the given type id
*/
- public Component getComponent(BigDecimal id) {
- return (Component) m_comps.get(id);
+ public Component getComponent(final String typeClass) {
+ return components.get(typeClass);
}
/**
* @return The selection model used by this wizard
*/
- public MapComponentSelectionModel getComponentSelectionModel() {
- return m_sel;
+ public MapComponentSelectionModel getComponentSelectionModel() {
+ return selectionModel;
}
// Choose the right component and run it
- public void generateXML(PageState state, Element parent) {
+ @Override
+ public void generateXML(final PageState state, final Element parent) {
if (isVisible(state)) {
- Component c = m_sel.getComponent(state);
- if (c == null) {
+ final Component component = selectionModel.getComponent(state);
+ if (component == null) {
throw new IllegalStateException("No component for "
- + m_sel
- .getSelectedKey(state));
+ + selectionModel
+ .getSelectedKey(state));
}
- c.generateXML(state, parent);
+ component.generateXML(state, parent);
}
}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitWizard.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitWizard.java.off
new file mode 100755
index 000000000..0424c008f
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/AuthoringKitWizard.java.off
@@ -0,0 +1,684 @@
+/*
+ * Copyright (C) 2001-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.authoring;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.GridPanel;
+import com.arsdigita.bebop.List;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.Resettable;
+import com.arsdigita.bebop.SimpleContainer;
+import com.arsdigita.bebop.SingleSelectionModel;
+import com.arsdigita.bebop.event.ActionEvent;
+import com.arsdigita.bebop.event.ActionListener;
+import com.arsdigita.bebop.event.ChangeEvent;
+import com.arsdigita.bebop.event.ChangeListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.list.ListCellRenderer;
+import org.librecms.contentsection.ContentSection;
+import org.librecms.contentsection.ContentType;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ui.ContentItemPage;
+import com.arsdigita.cms.ui.item.ItemWorkflowRequestLocal;
+import com.arsdigita.cms.ui.workflow.AssignedTaskSection;
+import com.arsdigita.cms.ui.workflow.AssignedTaskTable;
+import com.arsdigita.cms.ui.workflow.TaskFinishForm;
+import com.arsdigita.cms.ui.workflow.TaskRequestLocal;
+import com.arsdigita.cms.ui.workflow.WorkflowRequestLocal;
+import com.arsdigita.cms.util.GlobalizationUtil;
+import com.arsdigita.cms.workflow.CMSTask;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.persistence.metadata.MetadataRoot;
+import com.arsdigita.persistence.metadata.ObjectType;
+import com.arsdigita.toolbox.ui.LayoutPanel;
+import com.arsdigita.toolbox.ui.ModalPanel;
+import com.arsdigita.toolbox.ui.Section;
+import com.arsdigita.util.Assert;
+import com.arsdigita.util.SequentialMap;
+import com.arsdigita.util.UncheckedWrapperException;
+import org.apache.log4j.Logger;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * This class represents a single authoring kit. The wizard accepts a
+ * {@link ContentType} in the constructor; it then extracts
+ * the {@link AuthoringKit} for the content type, and creates the
+ * components for all the steps in the kit.
+ *
+ * Note that the individual authoring kit steps must provide the following
+ * constructor:
+ *
+ *
+ * public TheClass(ItemSelectionModel model, AuthoringKitWizard parent) { ... }
+ *
+ *
+ * This constructor will be called when the component is automatically
+ * instantiated by the AuthoringKitWizard.
+ *
+ * @version $Id: AuthoringKitWizard.java 2140 2011-01-16 12:04:20Z pboy $
+ */
+public class AuthoringKitWizard extends LayoutPanel implements Resettable {
+
+ /** Private Logger instance for this class */
+ private static final Logger s_log = Logger.getLogger(
+ AuthoringKitWizard.class);
+ private static Class[] s_args = new Class[]{
+ ItemSelectionModel.class,
+ AuthoringKitWizard.class
+ };
+ private static Class[] s_userDefinedArgs = new Class[]{
+ ItemSelectionModel.class,
+ AuthoringKitWizard.class,
+ ContentType.class
+ };
+ //private static final ArrayList s_assets = new ArrayList();
+ private static final java.util.List s_assets = new
+ ArrayList();
+ private final Object[] m_vals;
+ private final ContentType m_type;
+ private final AuthoringKit m_kit;
+ private final ItemSelectionModel m_sel;
+ private final WorkflowRequestLocal m_workflow;
+ private final AssignedTaskTable m_tasks;
+ private final SequentialMap m_labels;
+ private final List m_list;
+ private String m_defaultKey;
+ private final GridPanel m_left;
+ private final ModalPanel m_body;
+ private final SimpleContainer m_steps;
+ private final TaskFinishForm m_taskFinishForm;
+ /**
+ * The name of the state parameter that determines whether the
+ * wizard is in item creation mode or item editing mode.
+ */
+ public static final String IS_EDITING = "is_edit";
+ /**
+ * The key for the item creation step.
+ */
+ public static final String CREATION = "_creation_";
+
+ /**
+ * Construct a new AuthoringKitWizard. Add all the steps in the
+ * authoring kit to the wizard.
+ *
+ * @param type The content type of the items that this wizard will
+ * handle
+ *
+ * @param itemModel The item selection model which will supply
+ * this wizard with the content item object
+ */
+ public AuthoringKitWizard(final ContentType type,
+ final ItemSelectionModel model) {
+ if (s_log.isDebugEnabled()) {
+ s_log.debug("Authoring kit wizard for type " + type + " "
+ + "undergoing creation");
+ }
+
+ m_type = type;
+ m_kit = type.getAuthoringKit();
+ m_sel = model;
+ m_vals = new Object[]{m_sel, this};
+ m_workflow = new ItemWorkflowRequestLocal();
+ m_labels = new SequentialMap();
+
+ m_left = new GridPanel(1);
+ setLeft(m_left);
+
+ m_tasks = new AssignedTaskTable(m_workflow);
+
+ m_left.add(new AssignedTaskSection(m_workflow, m_tasks));
+
+ final Section stepSection = new Section(gz("cms.ui.authoring.steps"));
+ m_left.add(stepSection);
+
+ m_list = new List();
+ stepSection.setBody(m_list);
+
+ m_list.setListData(m_labels);
+ m_list.setCellRenderer(new ListCellRenderer() {
+
+ public Component getComponent(
+ List list,
+ PageState state,
+ Object value,
+ String key,
+ int index,
+ boolean isSelected) {
+ Label l = null;
+ if (value instanceof GlobalizedMessage) {
+ l = new Label((GlobalizedMessage) value);
+ } else {
+ l = new Label((String) value);
+ }
+ if (isSelected) {
+ l.setFontWeight(Label.BOLD);
+ return l;
+ }
+ return new ControlLink(l);
+ }
+ });
+
+ m_body = new ModalPanel();
+ setBody(m_body);
+
+ m_steps = new SimpleContainer();
+ m_body.add(m_steps);
+ m_body.setDefault(m_steps);
+
+ final AuthoringStepCollection steps = m_kit.getSteps();
+
+ if (Assert.isEnabled()) {
+ Assert.isTrue(!steps.isEmpty(),
+ "The authoring kit for " + type.getID() + " "
+ + "(java class " + type.getClassName() + ") "
+ + "has no steps.");
+ }
+
+ StepComponent panel = null;
+ while (steps.next()) {
+ final AuthoringStep step = steps.getAuthoringStep();
+ final String key = step.getID().toString();
+
+ if (m_defaultKey == null) {
+ m_defaultKey = key;
+ }
+
+ /**
+ * The "label" and "description" are only here for backwards
+ * compatibility
+ */
+ final String label = step.getLabel();
+ final String labelKey = step.getLabelKey();
+ final String labelBundle = step.getLabelBundle();
+ final String description = step.getDescription();
+ final String descriptionKey = step.getDescription();
+ final String descriptionBundle = step.getDescription();
+ final String str = step.getComponent();
+
+ if (panel != null) {
+ panel.setNextStepKey(step.getID());
+ }
+ panel = new StepComponent(step.getID());
+ m_steps.add(panel);
+ final Component comp;
+
+ if (str.equals("com.arsdigita.cms.ui.authoring."
+ + "SecondaryPageEditDynamic")
+ || str.equals("com.arsdigita.cms.ui.authoring."
+ + "PageEditDynamic")) {
+ comp = instantiateUserDefinedStep(str, m_type);
+ } else {
+ comp = instantiateStep(str);
+ }
+ panel.add(comp);
+ // XXX should be optional
+ if (comp instanceof AuthoringStepComponent) {
+ ((AuthoringStepComponent) comp).addCompletionListener(
+ new StepCompletionListener());
+ }
+
+ GlobalizedMessage gzLabel = null;
+ if (labelKey != null) {
+ if (labelBundle == null) {
+ gzLabel = gz(labelKey);
+ } else {
+ gzLabel = new GlobalizedMessage(labelKey, labelBundle);
+ }
+ }
+ m_labels.put(key,
+ gzLabel == null ? (Object) label : (Object) gzLabel);
+ }
+
+ ObjectType thisType = MetadataRoot.getMetadataRoot().getObjectType(type.
+ getAssociatedObjectType());
+ Collection skipSteps = ContentSection.getConfig().getAssetStepsToSkip(
+ type);
+ Iterator it = skipSteps.iterator();
+ if (s_log.isDebugEnabled()) {
+ while (it.hasNext()) {
+ s_log.debug("skip step " + it.next());
+ }
+ }
+ //Iterator assets = s_assets.iterator();
+ Iterator assets = s_assets.iterator();
+ while (assets.hasNext()) {
+ //Object[] data = (Object[]) assets.next();
+ final AssetStepEntry data = assets.next();
+ //String baseObjectType = (String) data[0];
+ final String baseObjectType = data.getBaseDataObjectType();
+ //Class step = (Class) data[1];
+ Class step = data.getStep();
+ s_log.debug("possibly adding asset step " + step.getName());
+ if (!skipSteps.contains(step.getName())) {
+ //GlobalizedMessage label = (GlobalizedMessage) data[2];
+ GlobalizedMessage label = data.getLabel();
+
+ if (!thisType.isSubtypeOf(baseObjectType)) {
+ continue;
+ }
+
+ if (panel != null) {
+ panel.setNextStepKey(step);
+ }
+ panel = new StepComponent(step);
+ m_steps.add(panel);
+
+ Component comp = instantiateStep(step.getName());
+ if (comp instanceof AuthoringStepComponent) {
+ ((AuthoringStepComponent) comp).addCompletionListener(
+ new StepCompletionListener());
+ }
+ panel.add(comp);
+
+ m_labels.put(step, label);
+ }
+ }
+
+ m_list.addChangeListener(new StepListener());
+
+ m_taskFinishForm = new TaskFinishForm(new TaskSelectionRequestLocal());
+ m_body.add(m_taskFinishForm);
+
+ m_body.connect(m_tasks, 2, m_taskFinishForm);
+ m_body.connect(m_taskFinishForm);
+
+ m_taskFinishForm.addProcessListener(new FormProcessListener() {
+
+ public final void process(final FormSectionEvent e)
+ throws FormProcessException {
+ final PageState state = e.getPageState();
+
+ m_tasks.getRowSelectionModel().clearSelection(state);
+ }
+ });
+ }
+
+ /**
+ *
+ */
+ private final class StepListener implements ChangeListener {
+
+ public final void stateChanged(final ChangeEvent e) {
+ final PageState state = e.getPageState();
+ final String key = m_list.getSelectedKey(state).toString();
+
+ final Iterator iter = m_steps.children();
+
+ while (iter.hasNext()) {
+ final StepComponent step = (StepComponent) iter.next();
+
+ if (step.getStepKey().toString().equals(key)) {
+ step.setVisible(state, true);
+ } else {
+ step.setVisible(state, false);
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ private final class StepCompletionListener implements ActionListener {
+
+ public final void actionPerformed(final ActionEvent e) {
+ final PageState state = e.getPageState();
+ if (ContentItemPage.isStreamlinedCreationActive(state)) {
+ final String key = m_list.getSelectedKey(state).toString();
+
+ final Iterator iter = m_steps.children();
+
+ while (iter.hasNext()) {
+ final StepComponent step = (StepComponent) iter.next();
+ if (step.getStepKey().toString().equals(key)) {
+ Object nextStep = step.getNextStepKey();
+ if (nextStep != null) {
+ m_list.getSelectionModel().setSelectedKey(state,
+ nextStep.
+ toString());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ * @param page
+ */
+ @Override
+ public final void register(final Page page) {
+ super.register(page);
+
+ final Iterator iter = m_steps.children();
+
+ while (iter.hasNext()) {
+ final StepComponent child = (StepComponent) iter.next();
+
+ page.setVisibleDefault(child, false);
+ }
+
+ page.addActionListener(new ActionListener() {
+
+ public final void actionPerformed(final ActionEvent e) {
+ final PageState state = e.getPageState();
+
+ if (state.isVisibleOnPage(AuthoringKitWizard.this)) {
+ final SingleSelectionModel model =
+ m_list.getSelectionModel();
+
+ if (!model.isSelected(state)) {
+ model.setSelectedKey(state, m_defaultKey);
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ *
+ * @param baseObjectType
+ * @param step
+ * @param label
+ * @param description
+ * @param sortKey
+ */
+ public static void registerAssetStep(String baseObjectType,
+ Class step,
+ GlobalizedMessage label,
+ GlobalizedMessage description,
+ int sortKey) {
+ // cg - allow registered steps to be overridden by registering a step with the same label
+ // this is a bit of a hack used specifically for creating a specialised version of image
+ // step. There is no straightforward way of preventing the original image step from being
+ // registered, but I needed the image step to use a different step class if the specialised
+ // image step application was loaded. Solution is to ensure initialiser in new project
+ // runs after original ccm-ldn-image-step initializer and override the registered step here
+ s_log.debug(
+ "registering asset step - label: "
+ + label.localize()
+ + " step class: "
+ + step.getName());
+
+ //Iterator assets = s_assets.iterator();
+ Iterator assets = s_assets.iterator();
+ while (assets.hasNext()) {
+ //Object[] data = (Object[]) assets.next();
+ //String thisObjectType = (String) data[0];
+ //GlobalizedMessage thisLabel = (GlobalizedMessage) data[2];
+
+ final AssetStepEntry data = assets.next();
+ String thisObjectType = data.getBaseDataObjectType();
+ GlobalizedMessage thisLabel = data.getLabel();
+
+ /**
+ * jensp 2011-11-14: The code above was only testing for the same
+ * label, but not for the same object type. I don't think that
+ * this was indented since this made it impossible to attach the
+ * same step to different object types.
+ * The orginal line was
+ * if (thisLabel.localize().equals(label.localize())) {
+ *
+ */
+ if ((thisObjectType.equals(baseObjectType))
+ && (thisLabel.localize().equals(label.localize()))) {
+ s_log.debug(
+ "registering authoring step with same label as previously registered step");
+ s_assets.remove(data);
+ break;
+ }
+ }
+ s_assets.add(new AssetStepEntry(baseObjectType, step, label, description, sortKey));
+ Collections.sort(s_assets);
+ //s_assets.add(new Object[]{baseObjectType, step, label, description});
+ }
+
+ private static class AssetStepEntry implements Comparable {
+ private String baseDataObjectType;
+ private Class step;
+ private GlobalizedMessage label;
+ private GlobalizedMessage description;
+ private Integer sortKey;
+
+ public AssetStepEntry() {
+ super();
+ }
+
+ public AssetStepEntry(final String baseDataObjectType,
+ final Class step,
+ final GlobalizedMessage label,
+ final GlobalizedMessage description,
+ final Integer sortKey) {
+ this.baseDataObjectType = baseDataObjectType;
+ this.step = step;
+ this.label = label;
+ this.description = description;
+ this.sortKey = sortKey;
+ }
+
+ public String getBaseDataObjectType() {
+ return baseDataObjectType;
+ }
+
+ public void setBaseDataObjectType(final String baseDataObjectType) {
+ this.baseDataObjectType = baseDataObjectType;
+ }
+
+ public Class getStep() {
+ return step;
+ }
+
+ public void setStep(final Class step) {
+ this.step = step;
+ }
+
+ public GlobalizedMessage getLabel() {
+ return label;
+ }
+
+ public void setLabel(final GlobalizedMessage label) {
+ this.label = label;
+ }
+
+ public GlobalizedMessage getDescription() {
+ return description;
+ }
+
+ public void setDescription(final GlobalizedMessage description) {
+ this.description = description;
+ }
+
+ public Integer getSortKey() {
+ return sortKey;
+ }
+
+ public void setSortKey(final Integer sortKey) {
+ this.sortKey = sortKey;
+ }
+
+ public int compareTo(final AssetStepEntry other) {
+ if (sortKey == other.getSortKey()) {
+ return step.getName().compareTo(other.getStep().getName());
+ } else {
+ return sortKey.compareTo(other.getSortKey());
+ }
+ }
+ }
+
+ /**
+ * @return The content type handled by this wizard
+ */
+ public ContentType getContentType() {
+ return m_type;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public List getList() {
+ return m_list;
+ }
+
+ /**
+ * @return The authoring kit which is represented by this wizard
+ */
+ public AuthoringKit getAuthoringKit() {
+ return m_kit;
+ }
+
+ /**
+ * @return The ItemSelectionModel used by the steps in this wizard
+ */
+ public ItemSelectionModel getItemSelectionModel() {
+ return m_sel;
+ }
+
+ /**
+ * Instantiate the specified authoring kit step. Will throw a
+ * RuntimeException on failure.
+ *
+ * @param className The Java class name of the step
+ */
+ protected Component instantiateStep(String name) {
+ if (s_log.isDebugEnabled()) {
+ s_log.debug("Instantiating kit wizard '" + name + "' with "
+ + "arguments " + s_args);
+ }
+
+ Object[] vals;
+ try {
+ // Get the creation component
+ Class createClass = Class.forName(name);
+ Constructor constr = createClass.getConstructor(s_args);
+ Component c = (Component) constr.newInstance(m_vals);
+ return c;
+ } catch (Exception e) {
+ Throwable cause = e.getCause(); // JDK1.4
+ if (cause == null) {
+ cause = e;
+ }
+ throw new UncheckedWrapperException(
+ "Failed to instantiate authoring kit component " + m_kit.
+ getCreateComponent() + ": " + e.getMessage(), cause);
+ }
+ }
+
+ /**
+ * Instantiate the specified authoring kit step for a user defined content type.
+ * Will throw a
+ * RuntimeException on failure.
+ *
+ * @param className The Java class name of the step
+ * @param description The step description, which for dynamically generated
+ * steps will be the object type which originally defined the step.
+ */
+ protected Component instantiateUserDefinedStep(String name,
+ ContentType originatingType) {
+ Object[] vals;
+ try {
+ // Get the creation component
+ Class createClass = Class.forName(name);
+ Constructor constr = createClass.getConstructor(s_userDefinedArgs);
+ Object[] userDefinedVals =
+ new Object[]{m_sel, this, originatingType};
+ Component c = (Component) constr.newInstance(userDefinedVals);
+ return c;
+ } catch (ClassNotFoundException cnfe) {
+ throw new UncheckedWrapperException(cnfe);
+ } catch (NoSuchMethodException nsme) {
+ throw new UncheckedWrapperException(nsme);
+ } catch (InstantiationException ie) {
+ throw new UncheckedWrapperException(ie);
+ } catch (IllegalAccessException iae) {
+ throw new UncheckedWrapperException(iae);
+ } catch (InvocationTargetException ite) {
+ throw new UncheckedWrapperException(ite);
+ }
+ }
+
+// /**
+// * Tell the parent page to redirect back to its return URL
+// *
+// * @param state The page state
+// */
+// public static void redirectBack(PageState state) {
+// ((ContentItemPage)state.getPage()).redirectBack(state);
+// }
+ /**
+ * Reset the state of this wizard
+ */
+ public final void reset(PageState state) {
+ m_list.setSelectedKey(state, m_defaultKey);
+ }
+
+ private final class StepComponent extends SimpleContainer {
+
+ private final Object m_key;
+ private Object m_nextKey;
+
+
+ public StepComponent(Object key) {
+ m_key = key;
+ }
+
+ public Object getStepKey() {
+ return m_key;
+ }
+
+ public Object getNextStepKey() {
+ return m_nextKey;
+ }
+
+ public void setNextStepKey(Object nextKey) {
+ m_nextKey = nextKey;
+ }
+ }
+
+ private final class TaskSelectionRequestLocal extends TaskRequestLocal {
+
+ protected final Object initialValue(final PageState state) {
+ final String id = m_tasks.getRowSelectionModel().getSelectedKey(
+ state).toString();
+
+ return new CMSTask(new BigDecimal(id));
+ }
+ }
+
+ protected final static GlobalizedMessage gz(final String key) {
+ return GlobalizationUtil.globalize(key);
+ }
+
+ protected final static String lz(final String key) {
+ return (String) gz(key).localize();
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java.off
index 0c6b267c1..64d0db1ef 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java.off
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/WizardSelector.java.off
@@ -25,12 +25,21 @@ import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.parameters.BigDecimalParameter;
+import com.arsdigita.bebop.parameters.LongParameter;
+import com.arsdigita.bebop.parameters.StringParameter;
+
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentType;
+
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.xml.Element;
+import oracle.jrockit.jfr.events.ContentTypeImpl;
+import org.librecms.contenttypes.AuthoringKit;
+import org.librecms.contenttypes.AuthoringKitInfo;
+import org.librecms.contenttypes.ContentTypeInfo;
+
import java.math.BigDecimal;
@@ -49,7 +58,7 @@ import java.math.BigDecimal;
public class WizardSelector extends AuthoringKitSelector
implements Resettable {
- private ItemSelectionModel m_itemSel;
+ private ItemSelectionModel itemSelectionModel;
/**
* Construct a new WizardSelector. Load all the possible authoring kits
@@ -63,45 +72,48 @@ public class WizardSelector extends AuthoringKitSelector
*
* @pre itemModel != null
*/
- public WizardSelector(ItemSelectionModel model,
- SingleSelectionModel typeModel) {
+ public WizardSelector(final ItemSelectionModel model,
+ final SingleSelectionModel typeModel) {
super(typeModel);
- m_itemSel = model;
+ itemSelectionModel = model;
super.processKit();
}
/**
* Get the wizard for the given kit.
+ * @param kit
+ * @param type
+ * @return
*/
- public Component instantiateKitComponent(AuthoringKit kit,
- ContentType type) {
+ public Component instantiateKitComponent(final AuthoringKitInfo kit,
+ final ContentTypeInfo type) {
- ItemSelectionModel itemModel = new
+ final ItemSelectionModel itemModel = new
ItemSelectionModel(type,
- (BigDecimalParameter)m_itemSel.getStateParameter());
+ (LongParameter)itemSelectionModel.getStateParameter());
- AuthoringKitWizard w = new AuthoringKitWizard(type, itemModel);
- return w;
+ final AuthoringKitWizard wizard = new AuthoringKitWizard(type, itemModel);
+ return wizard;
}
/**
* @return The item selection model used by this wizard
*/
public ItemSelectionModel getSelectionModel() {
- return m_itemSel;
+ return itemSelectionModel;
}
// Determine the current wizard
private Component getCurrentWizard(PageState state) {
// Get the current item and extract its content type
- if(!m_itemSel.isSelected(state))
+ if(!itemSelectionModel.isSelected(state))
throw new RuntimeException( (String) GlobalizationUtil.globalize(
"cms.ui.authoring.missing_item_id")
.localize());
ContentItem item =
- (ContentItem)m_itemSel.getSelectedObject(state);
+ (ContentItem)itemSelectionModel.getSelectedObject(state);
ContentType type = item.getContentType();
BigDecimal typeId;
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/ContentSectionContainer.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/ContentSectionContainer.java
index 3ea1ae711..ae73dea83 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/ContentSectionContainer.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/contentcenter/ContentSectionContainer.java
@@ -34,12 +34,13 @@ import com.arsdigita.bebop.table.TableColumnModel;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.bebop.table.TableModelBuilder;
import com.arsdigita.cms.ui.CMSContainer;
-import com.arsdigita.ui.admin.GlobalizationUtil;
+import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.util.LockableImpl;
import org.libreccm.categorization.Category;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.PermissionChecker;
+import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionRepository;
import org.librecms.contentsection.privileges.ItemPrivileges;
@@ -298,8 +299,8 @@ public class ContentSectionContainer extends CMSContainer {
// depending on configuration of the location column!
Integer colNo = 0;
- Label emptyView = new Label(GlobalizationUtil
- .globalize("cms.ui.contentcenter.section"));
+ Label emptyView = new Label(new GlobalizedMessage(
+ "cms.ui.contentcenter.section", CmsConstants.CMS_BUNDLE));
emptyView.setFontWeight(Label.ITALIC);
setEmptyView(emptyView);
@@ -309,18 +310,18 @@ public class ContentSectionContainer extends CMSContainer {
TableColumnModel columnModel = getColumnModel();
// prepare column headers
- Label sectionHead = new Label(GlobalizationUtil
- .globalize("cms.ui.contentcenter.section"));
- sectionHead.setHint(GlobalizationUtil
- .globalize("cms.ui.contentcenter.section_hint"));
- Label locationHead = new Label(GlobalizationUtil
- .globalize("cms.ui.contentcenter.location"));
- locationHead.setHint(GlobalizationUtil
- .globalize("cms.ui.contentcenter.location_hint"));
- Label actionHead = new Label(GlobalizationUtil
- .globalize("cms.ui.contentcenter.action"));
- actionHead.setHint(GlobalizationUtil
- .globalize("cms.ui.contentcenter.action_hint"));
+ Label sectionHead = new Label(new GlobalizedMessage(
+ "cms.ui.contentcenter.section", CmsConstants.CMS_BUNDLE));
+ sectionHead.setHint(new GlobalizedMessage(
+ "cms.ui.contentcenter.section_hint", CmsConstants.CMS_BUNDLE));
+ Label locationHead = new Label(new GlobalizedMessage(
+ "cms.ui.contentcenter.location", CmsConstants.CMS_BUNDLE));
+ locationHead.setHint(new GlobalizedMessage(
+ "cms.ui.contentcenter.location_hint", CmsConstants.CMS_BUNDLE));
+ Label actionHead = new Label(new GlobalizedMessage(
+ "cms.ui.contentcenter.action", CmsConstants.CMS_BUNDLE));
+ actionHead.setHint(new GlobalizedMessage(
+ "cms.ui.contentcenter.action_hint", CmsConstants.CMS_BUNDLE));
//TableColumn contentSectionColumn = new TableColumn(colNo, COLUMN_SECTION);
TableColumn contentSectionColumn = new TableColumn(
@@ -606,7 +607,7 @@ public class ContentSectionContainer extends CMSContainer {
section.getRootDocumentsFolder())) {
return new Link(section.getLabel(),
- generateURL(section.getPrimaryUrl() + "/"));
+ generateURL(section.getPrimaryUrl()));
} else {
//return new Label(section.getName(), false);
// return null; // Produces a NPE although it shouldn't and
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemWorkflowRequestLocal.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemWorkflowRequestLocal.java
new file mode 100755
index 000000000..a7d3ad7e2
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/ItemWorkflowRequestLocal.java
@@ -0,0 +1,39 @@
+/*
+ * 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.item;
+
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.cms.CMS;
+
+import org.librecms.contentsection.ContentItem;
+
+import com.arsdigita.cms.ui.workflow.WorkflowRequestLocal;
+
+import org.libreccm.workflow.Workflow;
+
+public class ItemWorkflowRequestLocal extends WorkflowRequestLocal {
+
+
+ @Override
+ protected final Object initialValue(final PageState state) {
+ final ContentItem item = CMS.getContext().getContentItem();
+
+ return item.getWorkflow();
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskController.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskController.java
new file mode 100644
index 000000000..25f60747f
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskController.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 LibreCCM Foundation.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package com.arsdigita.cms.ui.workflow;
+
+import com.arsdigita.bebop.table.RowData;
+import com.arsdigita.kernel.KernelConfig;
+
+import org.libreccm.configuration.ConfigurationManager;
+import org.libreccm.security.Shiro;
+import org.libreccm.security.User;
+import org.libreccm.workflow.UserTask;
+import org.libreccm.workflow.UserTaskRepository;
+import org.libreccm.workflow.Workflow;
+import org.libreccm.workflow.WorkflowManager;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+
+/**
+ * Controller for the assigned task components.
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+public class AssignedTaskController {
+
+ @Inject
+ private WorkflowManager workflowManager;
+
+ @Inject
+ private UserTaskRepository userTaskRepo;
+
+ @Inject
+ private Shiro shiro;
+
+ @Inject
+ private ConfigurationManager confManager;
+
+ private Locale defaultLocale;
+
+ @PostConstruct
+ private void init() {
+ final KernelConfig kernelConfig = confManager.findConfiguration(
+ KernelConfig.class);
+ defaultLocale = kernelConfig.getDefaultLocale();
+ }
+
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public List> getAssignedTasks(final Workflow workflow) {
+ final User user = shiro.getUser();
+ final List tasks = userTaskRepo.getAssignedTasks(user,
+ workflow);
+
+ return tasks
+ .stream()
+ .map(task -> createRowData(task))
+ .collect(Collectors.toList());
+
+ }
+
+ private RowData createRowData(final UserTask task) {
+
+
+ final RowData rowData = new RowData<>(3);
+
+ rowData.setRowKey(task.getTaskId());
+
+ // Change when Workflow forms provide fields to enter localised label.
+ rowData.setColData(0, task.getLabel().getValue(defaultLocale));
+
+ if (task.isLocked()) {
+ rowData.setColData(1, task.getLockingUser().getName());
+ } else {
+ rowData.setColData(1,"");
+ }
+
+ rowData.setColData(2, "");
+
+
+ return rowData;
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskSection.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskSection.java
new file mode 100755
index 000000000..3ffe736ef
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskSection.java
@@ -0,0 +1,269 @@
+/*
+ * 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.workflow;
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.RequestLocal;
+import com.arsdigita.bebop.event.ActionEvent;
+import com.arsdigita.bebop.event.ActionListener;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.toolbox.ui.ActionGroup;
+import com.arsdigita.toolbox.ui.Section;
+import com.arsdigita.web.Web;
+
+import org.libreccm.workflow.Workflow;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.log4j.Logger;
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.security.Shiro;
+import org.libreccm.workflow.Task;
+import org.libreccm.workflow.UserTask;
+import org.libreccm.workflow.UserTaskRepository;
+import org.libreccm.workflow.WorkflowConstants;
+import org.libreccm.workflow.WorkflowManager;
+import org.libreccm.workflow.WorkflowRepository;
+import org.librecms.CmsConstants;
+import org.librecms.workflow.CmsTask;
+import org.librecms.workflow.CmsTaskType;
+
+import java.util.List;
+
+/**
+ * @author unknown
+ * @author Sören Bernstein
+ * @author Jens Pelzetter
+ */
+public final class AssignedTaskSection extends Section {
+
+ private final WorkflowRequestLocal m_workflow;
+ private final WorkflowFacade m_facade;
+
+ public AssignedTaskSection(final WorkflowRequestLocal workflow,
+ final Component subject) {
+ super(gz("cms.ui.workflow.task.assigned"));
+
+ m_workflow = workflow;
+ m_facade = new WorkflowFacade(m_workflow);
+
+ final ActionGroup group = new ActionGroup();
+ setBody(group);
+
+ group.setSubject(subject);
+ group.addAction(new RestartLink());
+ //jensp 2014-06-06 Removed this two links because the funcationality they provide should
+ //be accessible from this place.
+ //group.addAction(new LockLink());
+ //group.addAction(new UnlockLink());
+ }
+
+ @Override
+ public final boolean isVisible(final PageState state) {
+ return m_workflow.getWorkflow(state) != null;
+ }
+
+ private class RestartLink extends ActionLink {
+
+ RestartLink() {
+ super(new Label(gz("cms.ui.workflow.restart_stopped_workflow")));
+
+ setClassAttr("restartWorkflowLink");
+ addActionListener(new Listener());
+ }
+
+ @Override
+ public final boolean isVisible(final PageState state) {
+ return m_facade.workflowState(state, WorkflowConstants.INIT)
+ || m_facade.workflowState(state, WorkflowConstants.STOPPED);
+ }
+
+ private class Listener implements ActionListener {
+
+ @Override
+ public final void actionPerformed(final ActionEvent event) {
+ m_facade.restartWorkflow(event.getPageState());
+ }
+
+ }
+
+ }
+
+ private class LockLink extends ActionLink {
+
+ LockLink() {
+ super(new Label(gz("cms.ui.workflow.task.assigned.lock_all")));
+
+ addActionListener(new Listener());
+ }
+
+ @Override
+ public final boolean isVisible(final PageState state) {
+ return m_facade.workflowState(state, WorkflowConstants.STARTED)
+ && m_facade.tasksExist(state)
+ && !m_facade.tasksLocked(state);
+ }
+
+ private class Listener implements ActionListener {
+
+ @Override
+ public final void actionPerformed(final ActionEvent event) {
+ m_facade.lockTasks(event.getPageState());
+ }
+
+ }
+
+ }
+
+ private class UnlockLink extends ActionLink {
+
+ UnlockLink() {
+ super(new Label(gz("cms.ui.workflow.task.assigned.unlock_all")));
+
+ addActionListener(new UnlockLink.Listener());
+ }
+
+ @Override
+ public final boolean isVisible(final PageState state) {
+ return m_facade.workflowState(state, WorkflowConstants.STARTED)
+ && m_facade.tasksExist(state)
+ && m_facade.tasksLocked(state);
+ }
+
+ private class Listener implements ActionListener {
+
+ @Override
+ public final void actionPerformed(final ActionEvent event) {
+ m_facade.unlockTasks(event.getPageState());
+ }
+
+ }
+
+ }
+
+ private class WorkflowFacade {
+
+ private final WorkflowRequestLocal m_flow;
+ private final TaskListRequestLocal m_tasks;
+
+ WorkflowFacade(final WorkflowRequestLocal flow) {
+ m_flow = flow;
+ m_tasks = new TaskListRequestLocal();
+ }
+
+ private class TaskListRequestLocal extends RequestLocal {
+
+ @Override
+ protected final Object initialValue(final PageState state) {
+ final Workflow workflow = m_flow.getWorkflow(state);
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final UserTaskRepository userTaskRepo = cdiUtil.findBean(
+ UserTaskRepository.class);
+ final Shiro shiro = cdiUtil.findBean(Shiro.class);
+ return userTaskRepo.findEnabledTasksForWorkflow(shiro.getUser(),
+ workflow);
+ }
+
+ @SuppressWarnings("unchecked")
+ final List getTasks(final PageState state) {
+ return (ArrayList) get(state);
+ }
+
+ }
+
+ final void restartWorkflow(final PageState state) {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final WorkflowManager workflowManager = cdiUtil.findBean(
+ WorkflowManager.class);
+ final Workflow workflow = m_flow.getWorkflow(state);
+ workflowManager.start(workflow);
+
+ // Lock tasks if not locked
+ if (!tasksLocked(state)) {
+ lockTasks(state);
+ }
+ }
+
+ final void lockTasks(final PageState state) {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final WorkflowManager workflowManager = cdiUtil.findBean(WorkflowManager.class);
+
+ for(final UserTask task : m_tasks.getTasks(state)) {
+ if (relevant(task) && !task.isLocked()) {
+ workflowManager.lockTask(task);
+ }
+ }
+ }
+
+ final void unlockTasks(final PageState state) {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final WorkflowManager workflowManager = cdiUtil.findBean(WorkflowManager.class);
+
+ for(final UserTask task : m_tasks.getTasks(state)) {
+ if (relevant(task) && task.isLocked()) {
+ workflowManager.unlockTask(task);
+ }
+ }
+ }
+
+ final boolean tasksLocked(final PageState state) {
+ for(final UserTask task : m_tasks.getTasks(state)) {
+ if (relevant(task) && !task.isLocked()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ final boolean workflowState(final PageState state, int processState) {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final WorkflowManager workflowManager = cdiUtil.findBean(WorkflowManager.class);
+ final Workflow workflow = m_flow.getWorkflow(state);
+
+ return workflowManager.getState(workflow) == processState;
+ }
+
+ final boolean tasksExist(final PageState state) {
+ return !m_tasks.getTasks(state).isEmpty();
+ }
+
+ private boolean relevant(final UserTask task) {
+ return true;
+
+// ToDo
+// return task.getTaskType().getID().equals(CMSTaskType.AUTHOR)
+// || task.getTaskType().getID().equals(CMSTaskType.EDIT);
+ }
+
+ }
+
+ protected final static GlobalizedMessage gz(final String key) {
+ return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
+ }
+
+ protected final static String lz(final String key) {
+ return (String) gz(key).localize();
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskTable.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskTable.java
new file mode 100755
index 000000000..848793dbc
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskTable.java
@@ -0,0 +1,139 @@
+/*
+ * 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.workflow;
+
+import com.arsdigita.bebop.BoxPanel;
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.Label;
+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.table.DefaultTableCellRenderer;
+import com.arsdigita.bebop.table.TableCellRenderer;
+
+import org.librecms.workflow.CmsTask;
+
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.web.Web;
+
+import java.math.BigDecimal;
+
+import org.apache.log4j.Logger;
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.security.Shiro;
+import org.libreccm.security.User;
+import org.libreccm.workflow.UserTask;
+import org.libreccm.workflow.UserTaskRepository;
+import org.libreccm.workflow.WorkflowManager;
+import org.librecms.CmsConstants;
+import org.librecms.workflow.CmsTaskTypeRepository;
+
+public final class AssignedTaskTable extends Table {
+
+ public AssignedTaskTable(final WorkflowRequestLocal workflow) {
+
+ super(new AssignedTaskTableModelBuilder(workflow),
+ new String[]{lz("cms.ui.name"), "", ""});
+
+ // XXX The string array and setHeader(null) are a product of
+ // messed up Table behavior.
+ setEmptyView(new Label(gz("cms.ui.workflow.task.assigned.none")));
+
+ addTableActionListener(new LockListener());
+
+ getColumn(1).setCellRenderer(new CellRenderer());
+ getColumn(2).setCellRenderer(new DefaultTableCellRenderer(true));
+ }
+
+ private static class LockListener extends TableActionAdapter {
+
+ @Override
+ public final void cellSelected(final TableActionEvent event) {
+ final int column = event.getColumn();
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final UserTaskRepository userTaskRepo = cdiUtil.findBean(
+ UserTaskRepository.class);
+ final WorkflowManager workflowManager = cdiUtil.findBean(WorkflowManager.class);
+ final Shiro shiro = cdiUtil.findBean(Shiro.class);
+
+ if (column == 1) {
+ final UserTask task = userTaskRepo.findById((Long) event
+ .getRowKey());
+ final User currentUser = shiro.getUser();
+ final User lockingUser = task.getLockingUser();
+ if (task.isLocked()
+ && lockingUser != null
+ && lockingUser.equals(currentUser)) {
+ workflowManager.unlockTask(task);
+ } else {
+ workflowManager.lockTask(task);
+ }
+ }
+ }
+
+ }
+
+ private class CellRenderer implements TableCellRenderer {
+
+ @Override
+ public final Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ // SF patch [ 1587168 ] Show locking user
+ BoxPanel p = new BoxPanel();
+ User lockingUser = (User) value;
+ if (lockingUser != null) {
+ final StringBuilder sb = new StringBuilder("Locked by
");
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final Shiro shiro = cdiUtil.findBean(Shiro.class);
+ if (lockingUser.equals(shiro.getUser())) {
+ sb.append("you");
+ p.add(new ControlLink(new Label(
+ gz("cms.ui.workflow.task.unlock"))));
+ } else {
+ sb.append(lockingUser.getName());
+ p.add(new ControlLink(new Label(
+ gz("cms.ui.workflow.task.takeover"))));
+ }
+ p.add(new Label(sb.toString(), false));
+ } else {
+ p.add(new ControlLink(
+ new Label(gz("cms.ui.workflow.task.lock"))));
+ }
+ return p;
+ }
+
+ }
+
+ protected final static GlobalizedMessage gz(final String key) {
+ return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
+ }
+
+ protected final static String lz(final String key) {
+ return (String) gz(key).localize();
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskTableModelBuilder.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskTableModelBuilder.java
new file mode 100755
index 000000000..60425e78d
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/AssignedTaskTableModelBuilder.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
+ *
+ * The contents of this file are subject to the CCM Public
+ * License (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the
+ * License at http://www.redhat.com/licenses/ccmpl.html.
+ *
+ * Software distributed under the License is distributed on an
+ * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
+ * or implied. See the License for the specific language
+ * governing rights and limitations under the License.
+ *
+ */
+package com.arsdigita.cms.ui.workflow;
+
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.table.AbstractTableModelBuilder;
+import com.arsdigita.bebop.table.RowData;
+import com.arsdigita.bebop.table.TableModel;
+
+
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.util.Assert;
+
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.workflow.Workflow;
+import org.libreccm.workflow.WorkflowConstants;
+import org.libreccm.workflow.WorkflowManager;
+import org.librecms.CmsConstants;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ *
+ *
+ */
+class AssignedTaskTableModelBuilder extends AbstractTableModelBuilder {
+
+ private final WorkflowRequestLocal m_workflow;
+
+ public AssignedTaskTableModelBuilder(final WorkflowRequestLocal workflow) {
+ m_workflow = workflow;
+ }
+
+ @Override
+ public TableModel makeModel(final Table table, final PageState state) {
+ return new Model(m_workflow.getWorkflow(state));
+ }
+
+ private static class Model implements TableModel {
+
+ private final Iterator> m_iter;
+// private CmsTask m_task;
+ private RowData rowData;
+
+ Model(final Workflow workflow) {
+ Assert.exists(workflow, Workflow.class);
+
+ final CdiUtil cdiUtil= CdiUtil.createCdiUtil();
+ final WorkflowManager workflowManager = cdiUtil.findBean(WorkflowManager.class);
+
+ if (workflowManager.getState(workflow) == WorkflowConstants.STARTED) {
+ final AssignedTaskController controller = cdiUtil.findBean(
+ AssignedTaskController.class);
+ m_iter = controller.getAssignedTasks(workflow).iterator();
+ } else {
+ m_iter = Collections.emptyIterator();
+ }
+ }
+
+ @Override
+ public final int getColumnCount() {
+ return 3;
+ }
+
+ @Override
+ public final boolean nextRow() {
+ if (m_iter.hasNext()) {
+ rowData = m_iter.next();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public final Object getKeyAt(final int column) {
+ return rowData.getRowKey();
+ }
+
+ @Override
+ public final Object getElementAt(final int column) {
+ switch (column) {
+ case 0:
+ return rowData.getColData(0);
+ case 1:
+ return rowData.getColData(1);
+ case 2:
+ return rowData.getColData(2);
+ default:
+ throw new IllegalArgumentException(String.format(
+ "Illegal column index %d. Valid column index: 0, 1, 2",
+ column));
+ }
+ }
+ }
+
+ protected final static GlobalizedMessage gz(final String key) {
+ return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
+ }
+
+ protected final static String lz(final String key) {
+ return (String) gz(key).localize();
+ }
+}
diff --git a/ccm-cms/src/main/java/org/librecms/Cms.java b/ccm-cms/src/main/java/org/librecms/Cms.java
index c58cc31cf..3ac2e9384 100644
--- a/ccm-cms/src/main/java/org/librecms/Cms.java
+++ b/ccm-cms/src/main/java/org/librecms/Cms.java
@@ -47,7 +47,8 @@ import java.util.Properties;
instanceForm = ApplicationInstanceForm.class,
settingsPane = SettingsPane.class,
descBundle = CmsConstants.CONTENT_SECTION_DESC_BUNDLE,
- creator = ContentSectionCreator.class
+ creator = ContentSectionCreator.class,
+ servletPath = "/templates/servlet/content-section"
)
}
)
diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionServlet.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionServlet.java
index d40e0329b..f3041abb4 100644
--- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionServlet.java
+++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionServlet.java
@@ -19,21 +19,50 @@
package org.librecms.contentsection;
import com.arsdigita.bebop.Page;
+import com.arsdigita.cms.dispatcher.CMSPage;
+import com.arsdigita.cms.dispatcher.ContentItemDispatcher;
+import com.arsdigita.cms.dispatcher.ItemResolver;
+import com.arsdigita.cms.ui.CMSApplicationPage;
+import com.arsdigita.dispatcher.AccessDeniedException;
+import com.arsdigita.dispatcher.DispatcherHelper;
+import com.arsdigita.dispatcher.RequestContext;
+import com.arsdigita.templating.PresentationManager;
+import com.arsdigita.templating.Templating;
+import com.arsdigita.util.Assert;
+import com.arsdigita.util.Classes;
+import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.ApplicationFileResolver;
import com.arsdigita.web.BaseApplicationServlet;
+import com.arsdigita.web.LoginSignal;
+import com.arsdigita.web.Web;
+import com.arsdigita.web.WebConfig;
+import com.arsdigita.xml.Document;
+
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.l10n.GlobalizationHelper;
+import org.libreccm.security.PermissionChecker;
+import org.libreccm.security.Shiro;
import org.libreccm.web.CcmApplication;
import org.librecms.CmsConstants;
+import org.librecms.contentsection.privileges.ItemPrivileges;
+import org.librecms.lifecycle.Lifecycle;
+
+import java.util.Date;
+
+import javax.servlet.RequestDispatcher;
/*
* This servlet will maybe removed. Our current plan is to integrate the navigation
@@ -77,7 +106,7 @@ public class ContentSectionServlet extends BaseApplicationServlet {
private static final long serialVersionUID = 8061725145564728637L;
private static final Logger LOGGER = LogManager.getLogger(
- ContentSectionServlet.class);
+ ContentSectionServlet.class);
/**
* Literal for the prefix (in url) for previewing items
@@ -97,18 +126,18 @@ public class ContentSectionServlet extends BaseApplicationServlet {
private static final String CACHE_KEY_DELIMITER = "%";
public static final String CONTENT_ITEM
- = "com.arsdigita.cms.dispatcher.item";
+ = "com.arsdigita.cms.dispatcher.item";
public static final String CONTENT_SECTION
- = "com.arsdigita.cms.dispatcher.section";
+ = "com.arsdigita.cms.dispatcher.section";
- //ToDo: private final ContentItemDispatcher m_disp = new ContentItemDispatcher();
- public static Map s_itemResolverCache = Collections
- .synchronizedMap(new HashMap());
+ private final ContentItemDispatcher m_disp = new ContentItemDispatcher();
+ private static Map itemResolverCache = Collections
+ .synchronizedMap(new HashMap<>());
private static Map s_itemURLCacheMap = null;
/**
* Whether to cache the content items
*/
- private static final boolean s_cacheItems = true;
+// private static final boolean s_cacheItems = true;
// NEW STUFF here used to process the pages in this servlet
/**
* URL (pathinfo) -> Page object mapping. Based on it (and the http request
@@ -133,6 +162,7 @@ public class ContentSectionServlet extends BaseApplicationServlet {
* defaults are used.
*
* @param config
+ *
* @throws javax.servlet.ServletException
*/
@Override
@@ -154,12 +184,12 @@ public class ContentSectionServlet extends BaseApplicationServlet {
String resolverName = config.getInitParameter("file-resolver");
//ToDo
-// if (resolverName == null) {
-// m_resolver = Web.getConfig().getApplicationFileResolver();
-// } else {
-// m_resolver = (ApplicationFileResolver) Classes.newInstance(
-// resolverName);
-// }
+ if (resolverName == null) {
+ m_resolver = WebConfig.getConfig().getResolver();
+ } else {
+ m_resolver = (ApplicationFileResolver) Classes.newInstance(
+ resolverName);
+ }
LOGGER.debug("Template path is {} with resolver {}",
m_templatePath,
m_resolver.getClass().getName());
@@ -176,7 +206,7 @@ public class ContentSectionServlet extends BaseApplicationServlet {
* map, used as a cache.
*
* @param pathInfo url stub for a page to display
- * @param page Page object to display
+ * @param page Page object to display
*/
private void addPage(final String pathInfo, final Page page) {
m_pages.put(pathInfo, page);
@@ -185,8 +215,7 @@ public class ContentSectionServlet extends BaseApplicationServlet {
/**
* Implementation of parent's (abstract) doService method checks HTTP
* request to determine whether to handle a content item or other stuff
- * which is delegated to jsp templates.
- * {
+ * which is delegated to jsp templates. {
*
* @see com.arsdigita.web.BaseApplicationServlet#doService
* (HttpServletRequest, HttpServletResponse, Application)}
@@ -194,6 +223,7 @@ public class ContentSectionServlet extends BaseApplicationServlet {
* @param request
* @param response
* @param app
+ *
* @throws javax.servlet.ServletException
* @throws java.io.IOException
*/
@@ -201,10 +231,433 @@ public class ContentSectionServlet extends BaseApplicationServlet {
protected void doService(final HttpServletRequest request,
final HttpServletResponse response,
final CcmApplication app)
- throws ServletException, IOException {
+ throws ServletException, IOException {
+
+ if (!(app instanceof ContentSection)) {
+ throw new IllegalArgumentException(
+ "The provided application instance is not a content section.");
+ }
+
+ final ContentSection section = (ContentSection) app;
+
+ final RequestContext ctx = DispatcherHelper.getRequestContext();
+ final String url = ctx.getRemainingURLPart();
+ LOGGER.info("Resolving URL {} and trying as item first.");
+ final ItemResolver itemResolver = getItemResolver(section);
+
+ String pathInfo = request.getPathInfo();
+
+ final ContentItem item = getItem(section, pathInfo, itemResolver);
+
+ Assert.exists(pathInfo, "String pathInfo");
+ if (pathInfo.length() > 1 && pathInfo.endsWith("/")) {
+ /* NOTE: ServletAPI specifies, pathInfo may be empty or will
+ * start with a '/' character. It currently carries a
+ * trailing '/' if a "virtual" page, i.e. not a real jsp, but
+ * result of a servlet mapping. But Application requires url
+ * NOT to end with a trailing '/' for legacy free applications. */
+ pathInfo = pathInfo.substring(0, pathInfo.length() - 1);
+ }
+ final Page page = (Page) m_pages.get(pathInfo);
+ // ////////////////////////////////////////////////////////////////////
+ // Serve the page
+ // ////////////////////////////////////////////////////////////////////
+ /* FIRST try new style servlet based service */
+ if (page != null) {
+
+ // Check user access.
+ // checkUserAccess(request, response); // done in individual pages ??
+ if (page instanceof CMSPage) {
+ // backwards compatibility fix until migration completed
+ final CMSPage cmsPage = (CMSPage) page;
+ // final RequestContext ctx = DispatcherHelper.getRequestContext();
+ cmsPage.init();
+ cmsPage.dispatch(request, response, ctx);
+ } else {
+ final CMSApplicationPage cmsAppPage = (CMSApplicationPage) page;
+ cmsAppPage.init(request, response, app);
+ // Serve the page.
+ final Document doc = cmsAppPage.buildDocument(request, response);
+
+ final PresentationManager pm = Templating
+ .getPresentationManager();
+ pm.servePage(doc, request, response);
+ }
+
+ /* SECONDLY try if we have to serve an item (old style dispatcher based */
+ } else if (item != null) {
+
+ /* We have to serve an item here */
+ String param = request.getParameter("transID");
+
+ serveItem(request, response, section, item);
+
+ /* OTHERWISE delegate to a JSP in file system */
+ } else {
+ /* We have to deal with a content-section, folder or another bit */
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("NOT serving content item");
+ }
+
+ /* Store content section in http request to make it available
+ * for admin/index.jsp */
+ request.setAttribute(CONTENT_SECTION, section);
+
+ RequestDispatcher rd = m_resolver.resolve(m_templatePath,
+ request, response, app);
+ if (rd != null) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Got dispatcher " + rd);
+ }
+ rd.forward(DispatcherHelper.restoreOriginalRequest(request),
+ response);
+ } else {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("No dispatcher found for" + rd);
+ }
+ String requestUri = request.getRequestURI(); // same as ctx.getRemainingURLPart()
+ response.sendError(404, requestUri
+ + " not found on this server.");
+ }
+ }
- //ToDo
- throw new UnsupportedOperationException();
}
+ private void serveItem(final HttpServletRequest request,
+ final HttpServletResponse response,
+ final ContentSection section,
+ final ContentItem item)
+ throws ServletException, IOException {
+
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("serving content item");
+ }
+
+ RequestContext ctx = DispatcherHelper.getRequestContext();
+ String url = ctx.getRemainingURLPart();
+
+ final ItemResolver itemResolver = getItemResolver(section);
+
+ //set the content item in the request
+ request.setAttribute(CONTENT_ITEM, item);
+
+ //set the template context
+// ToDo
+// final TemplateResolver templateResolver = m_disp.getTemplateResolver(
+// section);
+//
+// String templateURL = url;
+// if (!templateURL.startsWith("/")) {
+// templateURL = "/" + templateURL;
+// }
+// if (templateURL.startsWith(PREVIEW)) {
+// templateURL = templateURL.substring(PREVIEW.length());
+// }
+//
+// final String sTemplateContext = itemResolver.getTemplateFromURL(
+// templateURL);
+// LOGGER.debug("setting template context to {}", sTemplateContext);
+//
+// templateResolver.setTemplateContext(sTemplateContext, request);
+// ToDo End
+
+ // Work out how long to cache for....
+ // We take minimum(default timeout, lifecycle expiry)
+ Lifecycle cycle = item.getLifecycle();
+ int expires = DispatcherHelper.getDefaultCacheExpiry();
+ if (cycle != null) {
+ Date endDate = cycle.getEndDateTime();
+
+ if (endDate != null) {
+ int maxAge = (int) ((endDate.getTime() - System
+ .currentTimeMillis()) / 1000l);
+ if (maxAge < expires) {
+ expires = maxAge;
+ }
+ }
+ }
+
+ //use ContentItemDispatcher
+ m_disp.dispatch(request, response, ctx);
+ }
+
+ /**
+ * Fetches the content section from the request attributes.
+ *
+ * @param request The HTTP request
+ *
+ * @return The content section
+ *
+ * @pre ( request != null )
+ */
+ public static ContentSection getContentSection(HttpServletRequest request) {
+ return (ContentSection) request.getAttribute(CONTENT_SECTION);
+ }
+
+ @SuppressWarnings("unchecked")
+ public ItemResolver getItemResolver(final ContentSection section) {
+
+ final String path = section.getPrimaryUrl();
+ final ItemResolver itemResolver;
+ if (itemResolverCache.containsKey(path)) {
+ itemResolver = itemResolverCache.get(path);
+ } else {
+ final String className = section.getItemResolverClass();
+ final Class clazz;
+ try {
+ clazz = (Class) Class.forName(className);
+ itemResolver = clazz.newInstance();
+ } catch (ClassNotFoundException
+ | IllegalAccessException
+ | InstantiationException ex) {
+ throw new UncheckedWrapperException(ex);
+ }
+
+ itemResolverCache.put(path, itemResolver);
+ }
+
+ LOGGER.debug("Using ItemResolver implementation \"{}\"...",
+ itemResolver.getClass().getName());
+
+ return itemResolver;
+ }
+
+ public ContentItem getItem(final ContentSection section,
+ final String url,
+ final ItemResolver itemResolver) {
+
+ LOGGER.debug("getting item at url {}", url);
+ final HttpServletRequest request = Web.getRequest();
+
+ //first sanitize the url
+ String itemUrl = url;
+ if (url.endsWith(XML_SUFFIX)) {
+ request.setAttribute(XML_MODE, Boolean.TRUE);
+ LOGGER.debug("StraightXML Requested");
+ itemUrl = String.format(
+ "/%s",
+ url.substring(0, url.length() - XML_SUFFIX.length()));
+ itemUrl = "/" + url.substring(0, url.length() - XML_SUFFIX.length());
+ } else {
+ request.setAttribute(XML_MODE, Boolean.FALSE);
+ if (url.endsWith(FILE_SUFFIX)) {
+ itemUrl = String.format(
+ "/%s",
+ url.substring(0, url.length() - FILE_SUFFIX.length()));
+ } else if (url.endsWith("/")) {
+ itemUrl = String.format("/%s",
+ url.substring(0, url.length() - 1));
+ }
+ }
+
+ if (!itemUrl.startsWith("/")) {
+ itemUrl = String.format("/%s", itemUrl);
+ }
+
+ ContentItem item;
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final PermissionChecker permissionChecker = cdiUtil.findBean(
+ PermissionChecker.class);
+ final ContentItemManager itemManager = cdiUtil.findBean(
+ ContentItemManager.class);
+ // Check if the user has access to view public or preview pages
+ boolean hasPermission = true;
+
+ // If the remaining URL starts with "preview/", then try and
+ // preview this item. Otherwise look for the live item.
+ boolean preview = false;
+ if (itemUrl.startsWith(PREVIEW)) {
+ itemUrl = itemUrl.substring(PREVIEW.length());
+ preview = true;
+ }
+
+ if (preview) {
+ LOGGER.info("Trying to get item for PREVIEW");
+
+ item = itemResolver.getItem(section,
+ itemUrl,
+ ContentItemVersion.DRAFT.toString());
+ if (item != null) {
+ hasPermission = permissionChecker.isPermitted(
+ ItemPrivileges.PREVIEW, item);
+ }
+ } else {
+ LOGGER.info("Trying to get LIVE item");
+
+ //check if this item is in the cache
+ //we only cache live items
+ LOGGER.debug("Trying to get content item for URL {}from cache",
+ itemUrl);
+
+ // Get the negotiated locale
+ final GlobalizationHelper globalizationHelper = cdiUtil.findBean(
+ GlobalizationHelper.class);
+ final String lang = globalizationHelper.getNegotiatedLocale()
+ .getLanguage();
+
+ // XXX why assign a value and afterwards null??
+ // Effectively it just ignores the cache and forces a fallback to
+ // itemResover in any case. Maybe otherwise language selection /
+ // negotiation doesn't work correctly?
+ item = null;
+
+ if (item == null) {
+ LOGGER.debug("Did not find content item in cache, so trying "
+ + "to retrieve and cache...");
+ //item not cached, so retreive it and cache it
+ item = itemResolver.getItem(section,
+ itemUrl,
+ ContentItemVersion.LIVE.toString());
+
+ if (LOGGER.isDebugEnabled() && item != null) {
+ LOGGER.debug("Sanity check: item.getPath() is {}",
+ itemManager.getItemPath(item));
+ }
+
+ if (item != null) {
+ LOGGER.debug("Content Item is not null");
+
+ hasPermission = permissionChecker.isPermitted(
+ ItemPrivileges.VIEW_PUBLISHED, item);
+ }
+ }
+
+ }
+
+ if (item == null && itemUrl.endsWith(INDEX_FILE)) {
+
+ if (item == null) {
+ LOGGER.info("no item found");
+ }
+
+ // look up folder if it's an index
+ itemUrl = itemUrl.substring(0, itemUrl.length() - INDEX_FILE
+ .length());
+ LOGGER.info("Attempting to match folder " + itemUrl);
+
+ item = itemResolver.getItem(section,
+ itemUrl,
+ ContentItemVersion.LIVE.toString());
+ if (item != null) {
+ hasPermission = permissionChecker.isPermitted(
+ ItemPrivileges.VIEW_PUBLISHED, item);
+ }
+ }
+
+ if (!hasPermission) {
+
+ // first, check if the user is logged-in
+ // if he isn't, give him a chance to do so...
+ final Shiro shiro = cdiUtil.findBean(Shiro.class);
+
+ if (shiro.getSubject().isAuthenticated()) {
+ throw new LoginSignal(request);
+ }
+
+ throw new AccessDeniedException();
+ }
+
+ return item;
+ }
+
+ public ContentItem getItem(final ContentSection section, final String url) {
+ final ItemResolver itemResolver = getItemResolver(section);
+
+ return getItem(section, url, itemResolver);
+ }
+
+ // synchronize access to the item-url cache
+// private static synchronized void itemURLCachePut(
+// final ContentSection section,
+// final String sURL,
+// final String lang,
+// final Long itemID) {
+//
+// getItemURLCache(section).put(String.format(
+// "%s" + CACHE_KEY_DELIMITER + "%s", sURL, lang), itemID);
+// }
+//
+// /**
+// * Maps the content item to the URL in a cache
+// *
+// * @param section the content section in which the content item is published
+// * @param url the URL at which the content item s published
+// * @param lang
+// * @param item the content item at the URL
+// */
+// public static synchronized void itemURLCachePut(
+// final ContentSection section,
+// final String url,
+// final String lang,
+// final ContentItem item) {
+//
+// if (url == null || item == null) {
+// return;
+// }
+// LOGGER.debug("adding cached entry for url {} and language {}",
+// url,
+// lang);
+//
+// itemURLCachePut(section, url, lang, item.getObjectId());
+// }
+//
+// /**
+// * Removes the cache entry for the URL, sURL
+// *
+// * @param section the content section in which to remove the key
+// * @param url the cache entry key to remove
+// * @param lang
+// */
+// public static synchronized void itemURLCacheRemove(
+// final ContentSection section,
+// final String url,
+// final String lang) {
+//
+// LOGGER.debug("removing cached entry for url {} and language {} ",
+// url,
+// lang);
+//
+// getItemURLCache(section).remove(url + CACHE_KEY_DELIMITER + lang);
+// }
+//
+// /**
+// * Fetches the ContentItem published at that URL from the cache.
+// *
+// * @param section the content section in which the content item is published
+// * @param url the URL for the item to fetch
+// * @param lang
+// * @return the ContentItem in the cache, or null
+// */
+// public static ContentItem itemURLCacheGet(final ContentSection section,
+// final String url,
+// final String lang) {
+// final Long itemID = (Long) getItemURLCache(section).get(
+// url + CACHE_KEY_DELIMITER + lang);
+//
+// if (itemID == null) {
+// return null;
+// } else {
+// final ContentItemRepository itemRepo = CdiUtil.createCdiUtil().findBean(ContentItemRepository.class);
+// try {
+// return itemRepo.findById(itemID);
+// } catch(NoResultException ex) {
+// return null;
+// }
+// }
+// }
+//
+// private static synchronized CacheTable getItemURLCache(ContentSection section) {
+// Assert.exists(section, ContentSection.class);
+// if (s_itemURLCacheMap == null) {
+// initializeItemURLCache();
+// }
+//
+// if (s_itemURLCacheMap.get(section.getPath()) == null) {
+// final CacheTable cache = new CacheTable("ContentSectionServletItemURLCache" +
+// section.getID().toString());
+// s_itemURLCacheMap.put(section.getPath(), cache);
+// }
+//
+// return (CacheTable) s_itemURLCacheMap.get(section.getPath());
+// }
}
diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionSetup.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionSetup.java
index 939911d61..b826c5494 100644
--- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionSetup.java
+++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionSetup.java
@@ -20,7 +20,6 @@ package org.librecms.contentsection;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.libreccm.categorization.Category;
import org.libreccm.modules.InstallEvent;
import org.libreccm.security.Role;
import org.libreccm.web.AbstractCcmApplicationSetup;
@@ -28,8 +27,8 @@ import org.librecms.CmsConstants;
import java.util.UUID;
-import static org.librecms.CmsConstants.*;
import static org.librecms.contentsection.ContentSection.*;
+
import org.librecms.contentsection.privileges.AdminPrivileges;
import org.librecms.contentsection.privileges.AssetPrivileges;
import org.librecms.contentsection.privileges.ItemPrivileges;
@@ -96,12 +95,14 @@ public class ContentSectionSetup extends AbstractCcmApplicationSetup {
rootFolder.setUuid(UUID.randomUUID().toString());
rootFolder.setUniqueId(rootFolder.getUuid());
rootFolder.setName(String.format("%s_" + ROOT, sectionName));
+ rootFolder.setType(FolderType.DOCUMENTS_FOLDER);
rootFolder.setSection(section);
final Folder rootAssetFolder = new Folder();
rootAssetFolder.setName(String.format("%s_" + ASSETS, sectionName));
rootAssetFolder.setUuid(UUID.randomUUID().toString());
rootAssetFolder.setUniqueId(rootAssetFolder.getUuid());
+ rootAssetFolder.setType(FolderType.ASSETS_FOLDER);
rootAssetFolder.setSection(section);
section.setRootDocumentFolder(rootFolder);
diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_8__update_assets_and_attachments.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_8__update_assets_and_attachments.sql
index 3a36f52c2..5222abee8 100644
--- a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_8__update_assets_and_attachments.sql
+++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_8__update_assets_and_attachments.sql
@@ -152,6 +152,9 @@ alter table CCM_CMS.BINARY_ASSETS_AUD
drop table if exists CCM_CMS.AttachmentList_ItemAttachment_AUD;
+alter table CCM_CMS.ATTACHMENTS_AUD
+ add column ATTACHMENT_LIST_ID bigint;
+
alter table CCM_CMS.AUDIO_ASSETS
alter column ASSET_ID RENAME TO OBJECT_ID;
@@ -246,6 +249,12 @@ alter table CCM_CMS.NOTE_TEXTS
alter table CCM_CMS.SIDE_NOTE_TEXTS
alter column ASSET_ID RENAME TO SIDE_NOTE_ID;
+alter table CCM_CMS.NOTE_TEXTS_AUD
+ rename to SIDE_NOTE_TEXTS_AUD;
+
+alter table CCM_CMS.SIDE_NOTE_TEXTS_AUD
+ alter column ASSET_ID RENAME TO SIDE_NOTE_ID;
+
create table CCM_CMS.SIDE_NOTE_TITLES (
SIDE_NOTE_ID bigint not null,
LOCALIZED_VALUE longvarchar,
diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_8__update_assets_and_attachments.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_8__update_assets_and_attachments.sql
index 033726bc5..eb1df07ef 100644
--- a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_8__update_assets_and_attachments.sql
+++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_8__update_assets_and_attachments.sql
@@ -152,6 +152,9 @@ alter table CCM_CMS.BINARY_ASSETS_AUD
drop table if exists CCM_CMS.AttachmentList_ItemAttachment_AUD;
+alter table CCM_CMS.ATTACHMENTS_AUD
+ add column ATTACHMENT_LIST_ID int8;
+
alter table CCM_CMS.AUDIO_ASSETS
rename column ASSET_ID to OBJECT_ID;
@@ -244,6 +247,12 @@ alter table CCM_CMS.NOTE_TEXTS
alter table CCM_CMS.SIDE_NOTE_TEXTS
rename column ASSET_ID to SIDE_NOTE_ID;
+alter table CCM_CMS.NOTE_TEXTS_AUD
+ rename to SIDE_NOTE_TEXTS_AUD;
+
+alter table CCM_CMS.SIDE_NOTE_TEXTS_AUD
+ rename column ASSET_ID TO SIDE_NOTE_ID;
+
create table CCM_CMS.SIDE_NOTE_TITLES (
SIDE_NOTE_ID int8 not null,
LOCALIZED_VALUE text,
diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties
index 30f792792..27f9fa354 100644
--- a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties
+++ b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties
@@ -1,4 +1,18 @@
contentsection.ui.admin.app_note=The properties for a Content Section are managed a special application:
contentsection.ui.admin.link_app=Go to Content Section application
-cms.ui.role.insufficient_privileges=The user is not permitted to administrate roles.
\ No newline at end of file
+cms.ui.role.insufficient_privileges=The user is not permitted to administrate roles.
+cms.ui.change_password=Change password
+cms.ui.sign_out=Sign out
+cms.ui.content_center=Content Center
+cms.ui.contentcenter.mainpage.taskssections=Tasks/Sections
+cms.ui.contentcenter.section=Content Section
+cms.ui.contentcenter.action=Action
+cms.ui.workflow.task.view_locked=View your locked tasks
+cms.ui.workflow.task.view_unlocked=View unlocked tasks
+cms.ui.workflow.task.view_all=View all tasks
+cms.ui.my_workspace=My Portal
+cms.ui.admin_center=Admin Center
+cms.ui.contentcenter.section_hint=All documents are organized in one or more contect sections. Each content section may have its own system of permission and its own administrators, independent from each other. Select a section where you will edit a document or create a new one.
+cms.ui.contentcenter.location=Location
+cms.ui.contentcenter.location_hint=In Legacy mode links to public pages.
diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties
index a39f49e80..53ca6579b 100644
--- a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties
+++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties
@@ -1,4 +1,18 @@
contentsection.ui.admin.app_note=Die Verwaltung von Content Sections erfolgt \u00fcber eine eigene Application:
contentsection.ui.admin.link_app=Zur Content Section Applikation
-cms.ui.role.insufficient_privileges=Der Benutzer ist nicht privilegiert Rollen zu administrieren.
\ No newline at end of file
+cms.ui.role.insufficient_privileges=Der Benutzer ist nicht privilegiert Rollen zu administrieren.
+cms.ui.change_password=Passwort \u00e4ndern
+cms.ui.sign_out=Abmelden
+cms.ui.content_center=Content Center
+cms.ui.contentcenter.mainpage.taskssections=Aufgaben/Content Sections
+cms.ui.contentcenter.section=Content Section
+cms.ui.contentcenter.action=Aktion
+cms.ui.workflow.task.view_locked=Reservierte Aufgaben anzeigen
+cms.ui.workflow.task.view_unlocked=Freigegebene Aufgaben anzeigen
+cms.ui.workflow.task.view_all=Alle Aufgaben anzeigen
+cms.ui.my_workspace=Mein Portal
+cms.ui.admin_center=Admin Center
+cms.ui.contentcenter.section_hint=All documents are organized in one or more contect sections. Each content section may have its own system of permission and its own administrators, independent from each other. Select a section where you will edit a document or create a new one.
+cms.ui.contentcenter.location=Ort
+cms.ui.contentcenter.location_hint=In Legacy mode links to public pages.
diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties
new file mode 100644
index 000000000..70bc7507f
--- /dev/null
+++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties
@@ -0,0 +1,18 @@
+
+contentsection.ui.admin.app_note=The properties for a Content Section are managed a special application:
+contentsection.ui.admin.link_app=Go to Content Section application
+cms.ui.role.insufficient_privileges=The user is not permitted to administrate roles.
+cms.ui.change_password=Change password
+cms.ui.sign_out=Sign out
+cms.ui.content_center=Centre de contenu
+cms.ui.contentcenter.mainpage.taskssections=Tasks/Sections
+cms.ui.contentcenter.section=Content Section
+cms.ui.contentcenter.action=Action
+cms.ui.workflow.task.view_locked=View your locked tasks
+cms.ui.workflow.task.view_unlocked=View unlocked tasks
+cms.ui.workflow.task.view_all=View all tasks
+cms.ui.my_workspace=Mon espace de travail
+cms.ui.admin_center=Admin Center
+cms.ui.contentcenter.section_hint=All documents are organized in one or more contect sections. Each content section may have its own system of permission and its own administrators, independent from each other. Select a section where you will edit a document or create a new one.
+cms.ui.contentcenter.location=Location
+cms.ui.contentcenter.location_hint=In Legacy mode links to public pages.