CCM NG/ccm-cms: Current progress of porting the UI to CCM NG
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4440 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
4fc5edc59c
commit
7430901acc
|
|
@ -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 <quasi@quasiweb.de>
|
||||
* @author Peter Boy <pboy@barkhof.uni-bremen.de>
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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.</p>
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @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<ContentItem> {
|
||||
|
||||
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<Long> model) {
|
||||
super(type.getContentItemClass(), model);
|
||||
m_typeId = type.getObjectId();
|
||||
typeId = type.getObjectId();
|
||||
}
|
||||
|
||||
public ItemSelectionModel(final ContentTypeInfo type,
|
||||
final SingleSelectionModel<Long> 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 <code>ContentItem</code>
|
||||
*
|
||||
* @param s the current page state
|
||||
* @param state the current page state
|
||||
*
|
||||
* @return the currently selected <code>ContentItem</code>, 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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>This is the default implementation of
|
||||
* {@link com.arsdigita.cms.dispatcher.ItemResolver}.</p>
|
||||
*
|
||||
* <p>The <tt>getItem</tt> method of the default implementation of
|
||||
* <tt>ItemResolver</tt>,
|
||||
* {@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 <tt>cheese</tt>. If no such item
|
||||
* exists, or if there is such an item, but without a live version, even
|
||||
* though one has been requested, <tt>getItem</tt> returns <tt>null</tt>.</p>
|
||||
*
|
||||
* <p>After the CMS Dispatcher received the content item from the
|
||||
* <tt>ItemResolver</tt>, 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 <tt>service</tt> on the page.</p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<ContentType> m_types;
|
||||
private final Map<String, Component> components;
|
||||
private final MapComponentSelectionModel<String> selectionModel;
|
||||
private final List<ContentTypeInfo> 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<String> 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<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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.</p>
|
||||
*
|
||||
* Note that the individual authoring kit steps must provide the following
|
||||
* constructor:
|
||||
*
|
||||
* <blockquote><pre><code>
|
||||
* public TheClass(ItemSelectionModel model, AuthoringKitWizard parent) { ... }
|
||||
* </code></pre></blockquote>
|
||||
*
|
||||
* This constructor will be called when the component is automatically
|
||||
* instantiated by the <code>AuthoringKitWizard</code>.</p>
|
||||
*
|
||||
* @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<AssetStepEntry> s_assets = new
|
||||
ArrayList<AssetStepEntry>();
|
||||
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<AssetStepEntry> 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<AssetStepEntry> 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<AssetStepEntry> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String> 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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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 <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@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<RowData<Long>> getAssignedTasks(final Workflow workflow) {
|
||||
final User user = shiro.getUser();
|
||||
final List<UserTask> tasks = userTaskRepo.getAssignedTasks(user,
|
||||
workflow);
|
||||
|
||||
return tasks
|
||||
.stream()
|
||||
.map(task -> createRowData(task))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
private RowData<Long> createRowData(final UserTask task) {
|
||||
|
||||
|
||||
final RowData<Long> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 <quasi@quasiweb.de>
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
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<UserTask> getTasks(final PageState state) {
|
||||
return (ArrayList<UserTask>) 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 <br />");
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<RowData<Long>> m_iter;
|
||||
// private CmsTask m_task;
|
||||
private RowData<Long> 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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<String, ItemResolver> 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<ItemResolver> clazz;
|
||||
try {
|
||||
clazz = (Class<ItemResolver>) 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());
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
Loading…
Reference in New Issue