CCM NG/ccm-cms: Several things for the dispatching prodecure.

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4547 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2017-02-01 14:03:46 +00:00
parent 647f182943
commit fe4cf824f8
29 changed files with 664 additions and 694 deletions

View File

@ -1,137 +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.dispatcher;
import com.arsdigita.bebop.PageState;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.util.StringTokenizer;
/**
* @author bche
*/
public abstract class AbstractItemResolver implements ItemResolver {
protected static final String TEMPLATE_CONTEXT_PREFIX = "tem_";
@Override
public abstract ContentItem getItem(
ContentSection section,
String url,
String context);
@Override
public abstract String getCurrentContext(PageState state);
@Override
public abstract String generateItemURL(
PageState state,
Long itemId,
String name,
ContentSection section,
String context);
@Override
public abstract String generateItemURL(PageState state,
Long itemId,
String name,
ContentSection section,
String context,
String templateContext);
@Override
public abstract String generateItemURL(PageState state,
ContentItem item,
ContentSection section,
String context);
@Override
public abstract String generateItemURL(PageState state,
ContentItem item,
ContentSection section,
String context,
String templateContext);
@Override
public abstract CMSPage getMasterPage(ContentItem item,
HttpServletRequest request)
throws ServletException;
/**
* Finds the template context from the URL and returns it, if it is there.
* Otherwise, returns null.
*
* @param inUrl the URL from which to get the template context
*
* @return the template context, or null if there is no template context
*/
@Override
public String getTemplateFromURL(final String inUrl) {
String tempUrl;
String url;
if (inUrl.startsWith("/")) {
tempUrl = inUrl.substring(1);
} else {
tempUrl = inUrl;
}
String templateContext = null;
StringTokenizer tokenizer = new StringTokenizer(tempUrl, "/");
if (tokenizer.hasMoreTokens()) {
templateContext = tokenizer.nextToken();
}
if (templateContext != null && templateContext.startsWith(
TEMPLATE_CONTEXT_PREFIX)) {
return templateContext.substring(TEMPLATE_CONTEXT_PREFIX.length());
} else {
return null;
}
}
/**
* Removes the template context from the <code>inUrl</code>.
*
* @param inUrl URL, possibly including the template context.
*
* @return <code>inUrl</code> with the template context removed
*/
@Override
public String stripTemplateFromURL(final String inUrl) {
String sTemplateContext = getTemplateFromURL(inUrl);
if (sTemplateContext != null) {
//there is a template context, so strip it
int iTemplateLength = TEMPLATE_CONTEXT_PREFIX.length()
+ sTemplateContext.length() + 1;
String sStripped = inUrl.substring(iTemplateLength, inUrl.length());
return sStripped;
} else {
return inUrl;
}
}
}

View File

@ -24,6 +24,7 @@ import com.arsdigita.dispatcher.DispatcherHelper;
import com.arsdigita.dispatcher.JSPApplicationDispatcher; import com.arsdigita.dispatcher.JSPApplicationDispatcher;
import com.arsdigita.dispatcher.RedirectException; import com.arsdigita.dispatcher.RedirectException;
import com.arsdigita.dispatcher.RequestContext; import com.arsdigita.dispatcher.RequestContext;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.LoginSignal; import com.arsdigita.web.LoginSignal;
import com.arsdigita.web.URL; import com.arsdigita.web.URL;
@ -45,8 +46,10 @@ import org.libreccm.security.User;
import org.librecms.CmsConstants; import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionManager;
import org.librecms.contentsection.ContentSectionRepository; import org.librecms.contentsection.ContentSectionRepository;
import org.librecms.contentsection.privileges.ItemPrivileges; import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.dispatcher.ItemResolver;
/** /**
* <p> * <p>
@ -139,7 +142,7 @@ public class CMSDispatcher implements Dispatcher, ChainedDispatcher {
// Content section cache // Content section cache
private static HashMap s_pageResolverCache = new HashMap(); private static HashMap s_pageResolverCache = new HashMap();
private static HashMap s_itemResolverCache = new HashMap(); // private static HashMap s_itemResolverCache = new HashMap();
private static HashMap s_xmlGeneratorCache = new HashMap(); private static HashMap s_xmlGeneratorCache = new HashMap();
private boolean m_adminPagesOnly = false; private boolean m_adminPagesOnly = false;
@ -489,17 +492,17 @@ public class CMSDispatcher implements Dispatcher, ChainedDispatcher {
* @param context The use context * @param context The use context
* *
* @return The item associated with the URL, or null if no such item exists * @return The item associated with the URL, or null if no such item exists
* @throws javax.servlet.ServletException
*/ */
protected ContentItem getContentItem(ContentSection section, String url, protected ContentItem getContentItem(ContentSection section, String url,
String context) String context)
throws ServletException { throws ServletException {
ItemResolver itemResolver = CMSDispatcher.getItemResolver(section); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentSectionManager sectionManager = cdiUtil.findBean(ContentSectionManager.class);
final ItemResolver itemResolver = sectionManager.getItemResolver(section);
ContentItem item = null; return itemResolver.getItem(section, url, context);
item = itemResolver.getItem(section, url, context);
return item;
} }
/** /**
@ -584,21 +587,16 @@ public class CMSDispatcher implements Dispatcher, ChainedDispatcher {
* @return The ItemResolver associated with the content section * @return The ItemResolver associated with the content section
*/ */
public static ItemResolver getItemResolver(ContentSection section) { public static ItemResolver getItemResolver(ContentSection section) {
String name = section.getLabel();
ItemResolver itemResolver = (ItemResolver) s_itemResolverCache.get(name); final Class<?> clazz;
if (itemResolver == null) {
final String itemResolverClassName = section.getItemResolverClass();
try { try {
itemResolver = (ItemResolver) Class.forName( clazz = Class.forName(section.getItemResolverClass());
itemResolverClassName).newInstance(); } catch(ClassNotFoundException ex) {
} catch (ClassNotFoundException | throw new UncheckedWrapperException(ex);
IllegalAccessException |
InstantiationException ex) {
throw new RuntimeException(ex);
} }
s_itemResolverCache.put(name, itemResolver);
} return (ItemResolver) CdiUtil.createCdiUtil().findBean(clazz);
return itemResolver;
} }
/** /**

View File

@ -28,6 +28,7 @@ import com.arsdigita.xml.Element;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionServlet; import org.librecms.contentsection.ContentSectionServlet;
import org.librecms.dispatcher.ItemResolver;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -116,7 +117,7 @@ public class ContentPanel extends SimpleComponent {
ContentSectionServlet.PREVIEW); ContentSectionServlet.PREVIEW);
} }
pathInfo.newChildElement("cms:templatePrefix", CMS.CMS_XML_NS).setText( pathInfo.newChildElement("cms:templatePrefix", CMS.CMS_XML_NS).setText(
"/" + AbstractItemResolver.TEMPLATE_CONTEXT_PREFIX); "/" + ItemResolver.TEMPLATE_CONTEXT_PREFIX);
if (CMS.getContext().hasContentItem()) { if (CMS.getContext().hasContentItem()) {
ContentItem item = CMS.getContext().getContentItem(); ContentItem item = CMS.getContext().getContentItem();

View File

@ -21,6 +21,7 @@ package com.arsdigita.cms.dispatcher;
import com.arsdigita.dispatcher.ChainedDispatcher; import com.arsdigita.dispatcher.ChainedDispatcher;
import com.arsdigita.dispatcher.DispatcherHelper; import com.arsdigita.dispatcher.DispatcherHelper;
import com.arsdigita.dispatcher.RequestContext; import com.arsdigita.dispatcher.RequestContext;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.LoginSignal; import com.arsdigita.web.LoginSignal;
import java.io.IOException; import java.io.IOException;
@ -38,8 +39,10 @@ import org.libreccm.security.PermissionChecker;
import org.libreccm.security.Shiro; import org.libreccm.security.Shiro;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionManager;
import org.librecms.contentsection.ContentSectionServlet; import org.librecms.contentsection.ContentSectionServlet;
import org.librecms.contentsection.privileges.ItemPrivileges; import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.dispatcher.ItemResolver;
/** /**
* Dispatches to the JSP or Servlet for rendering a content item. * Dispatches to the JSP or Servlet for rendering a content item.
@ -167,9 +170,7 @@ public class ItemDispatcher implements ChainedDispatcher {
// This part assumes the template is JSP. // This part assumes the template is JSP.
// final String templateURL = getTemplateURL(section, item, request, // final String templateURL = getTemplateURL(section, item, request,
// actx); // actx);
// s_log.debug("TEMPLATE " + templateURL); // s_log.debug("TEMPLATE " + templateURL);
DispatcherHelper.setRequestContext(request, actx); DispatcherHelper.setRequestContext(request, actx);
DispatcherHelper.forwardRequestByPath(null, request, DispatcherHelper.forwardRequestByPath(null, request,
response); response);
@ -235,7 +236,7 @@ public class ItemDispatcher implements ChainedDispatcher {
} }
/** /**
* Fetches the ItemResolver for a content section. Checks cache first. * Fetches the ItemResolver for a content section.
* *
* @param section The content section * @param section The content section
* *
@ -243,22 +244,11 @@ public class ItemDispatcher implements ChainedDispatcher {
*/ */
public ItemResolver getItemResolver(ContentSection section) { public ItemResolver getItemResolver(ContentSection section) {
String name = section.getLabel(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
ItemResolver ir = (ItemResolver) s_itemResolverCache.get(name); final ContentSectionManager sectionManager = cdiUtil.findBean(
ContentSectionManager.class);
if (ir == null) { return sectionManager.getItemResolver(section);
try {
ir = (ItemResolver) Class
.forName(section.getItemResolverClass()).newInstance();
s_itemResolverCache.put(name, ir);
} catch (ClassNotFoundException |
IllegalAccessException |
InstantiationException ex) {
throw new RuntimeException(ex);
}
}
return ir;
} }
/** /**
@ -281,7 +271,6 @@ public class ItemDispatcher implements ChainedDispatcher {
// //
// return ir; // return ir;
// } // }
/** /**
* Fetches the URL of a template for an item. The returned URL is relative * Fetches the URL of a template for an item. The returned URL is relative
* to the webapp context. * to the webapp context.
@ -297,5 +286,4 @@ public class ItemDispatcher implements ChainedDispatcher {
// //
// return templateURL; // return templateURL;
// } // }
} }

View File

@ -1,182 +0,0 @@
/*
* 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 org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
/**
* <p>
* The <tt>ItemResolver</tt> is responsible for mapping a URL in a particular
* content section to a content item.</p>
*
* <p>
* As an example, here is the item resolution process for a request to
* <tt>http://yourserver/cms/cheese</tt>:</p>
*
* <p>
* The item resolver would be asked to map the URL stub <tt>/cheese</tt>
* in the content section mounted at <tt>/cms</tt> to a content item. To this
* end, the dispatcher calls the <tt>getItem</tt> method, passing in the
* {@link com.arsdigita.cms.ContentSection} and the URL stub for the item within
* the section, <tt>/cheese</tt> in our example. As a final argument, the
* dispatcher passes either <tt>ContentItem.DRAFT</tt> or
* <tt>ContentItem.LIVE</tt> to the <tt>ItemResolver</tt>, depending on whether
* the returned item should be the live version (for public pages) or the draft
* version (for previewing).</p>
*
* @author Michael Pih (pihman@arsdigita.com)
* @author Stanislav Freidin (sfreidin@arsdigita.com)
* @version $Revision$ $DateTime: 2004/08/17 23:15:09 $
* @version $Id$
*/
public interface ItemResolver {
/**
* Return a content item based on section, url, and use context.
*
* @param section The current content section
* @param url The section-relative URL
* @param context The use context
* @return The content item, or null if no such item exists
*/
public ContentItem getItem(ContentSection section,
String url,
String context);
/**
* Fetches the current context based on the page state.
*
* @param state the current page state
* @return the context of the current URL, such as "live" or "admin"
*/
public String getCurrentContext(PageState state);
/**
* 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"
* @return The URL of the item
* @see #getCurrentContext
*/
public String generateItemURL(PageState state,
Long itemId,
String name,
ContentSection section,
String context);
/**
* 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
* @see #getCurrentContext
*/
public String generateItemURL(PageState state,
Long itemId,
String name,
ContentSection section,
String context,
String templateContext
);
/**
* 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"
* @return The URL of the item
* @see #getCurrentContext
*/
public String generateItemURL(PageState state,
ContentItem item,
ContentSection section,
String 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 "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);
/**
* Return a master page based on page state (and content section).
*
* @param item The content item
* @param request The HTTP request
* @return The master page
*/
public CMSPage getMasterPage(ContentItem item, HttpServletRequest request)
throws ServletException;
/*
* Having to stick the following methods, getTemplateFromURL, and
* stripTemplateFromURL in the ItemResolver interface is somewhat ugly.
* But, the relationship between ItemResolver and TemplateResolver needs
* to be cleaned up to fix this. As it is, ItemResolver parses URL's for
* template contexts, and TemplateResolver sets the actual template contexts
* in the request.
*/
/**
* Finds the template context from the URL and returns it, if it is there.
* Otherwise, returns null.
*
* @param inUrl the URL from which to get the template context
* @return the template context, or null if there is no template context
*/
public String getTemplateFromURL(String inUrl);
/**
* Removes the template context from the <code>inUrl</code>.
*
* @param inUrl URL, possibly including the template context.
* @return <code>inUrl</code> with the template context removed
*/
public String stripTemplateFromURL(String inUrl);
}

View File

@ -43,7 +43,6 @@ import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.PageLocations; import com.arsdigita.cms.PageLocations;
import com.arsdigita.cms.dispatcher.CMSDispatcher; import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.CMSPage; import com.arsdigita.cms.dispatcher.CMSPage;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.authoring.WizardSelector; import com.arsdigita.cms.ui.authoring.WizardSelector;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal; import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.cms.ui.item.CustomizedPreviewLink; import com.arsdigita.cms.ui.item.CustomizedPreviewLink;
@ -70,7 +69,9 @@ import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentItemVersion; import org.librecms.contentsection.ContentItemVersion;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionManager;
import org.librecms.contentsection.ContentType; import org.librecms.contentsection.ContentType;
import org.librecms.dispatcher.ItemResolver;
import java.io.IOException; import java.io.IOException;
import java.util.Optional; import java.util.Optional;
@ -164,6 +165,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
protected final Object initialValue(final PageState state) { protected final Object initialValue(final PageState state) {
return CMS.getContext().getContentItem(); return CMS.getContext().getContentItem();
} }
} }
private class TitlePrinter implements PrintListener { private class TitlePrinter implements PrintListener {
@ -176,6 +178,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
label.setLabel(item.getDisplayName()); label.setLabel(item.getDisplayName());
} }
} }
/** /**
@ -261,6 +264,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
templatesPane); templatesPane);
tabbedPane.addActionListener(new ActionListener() { tabbedPane.addActionListener(new ActionListener() {
@Override @Override
public final void actionPerformed(final ActionEvent event) { public final void actionPerformed(final ActionEvent event) {
@ -271,18 +275,22 @@ public class ContentItemPage extends CMSPage implements ActionListener {
((Resettable) pane).reset(state); ((Resettable) pane).reset(state);
} }
} }
}); });
// Build the preview link. // Build the preview link.
m_previewLink = new Link(new Label(gz("cms.ui.preview")), m_previewLink = new Link(new Label(gz("cms.ui.preview")),
new PrintListener() { new PrintListener() {
@Override @Override
public final void prepare(final PrintEvent event) { public final void prepare(
final PrintEvent event) {
final Link link = (Link) event.getTarget(); final Link link = (Link) event.getTarget();
link.setTarget(getPreviewURL(event. link.setTarget(getPreviewURL(event.
getPageState())); getPageState()));
link.setTargetFrame(Link.NEW_FRAME); link.setTargetFrame(Link.NEW_FRAME);
} }
}); });
m_previewLink.setIdAttr("preview_link"); m_previewLink.setIdAttr("preview_link");
add(m_previewLink); add(m_previewLink);
@ -309,6 +317,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
CmsConstants.CMS_BUNDLE)); CmsConstants.CMS_BUNDLE));
} }
} }
}); });
} }
@ -317,6 +326,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* com.arsdigita.cms.ContentItem}. * com.arsdigita.cms.ContentItem}.
* *
* @param state The page state * @param state The page state
*
* @pre state != null * @pre state != null
* @exception FormProcessException if the item_id is not valid * @exception FormProcessException if the item_id is not valid
*/ */
@ -336,6 +346,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* @deprecated use com.arsdigita.cms.CMS.getContext().getContentSection() * @deprecated use com.arsdigita.cms.CMS.getContext().getContentSection()
* instead * instead
* @param request The HTTP request * @param request The HTTP request
*
* @return The current content section * @return The current content section
*/ */
@Override @Override
@ -352,6 +363,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* *
* @deprecated Use the ItemSelectionModel * @deprecated Use the ItemSelectionModel
* @param state The page state * @param state The page state
*
* @return The current content item, null if there is none * @return The current content item, null if there is none
*/ */
@Override @Override
@ -361,6 +373,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
/** /**
* Set the current tab, if necessary * Set the current tab, if necessary
*
* @param event * @param event
*/ */
@Override @Override
@ -408,6 +421,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* @param nodeURL The URL where this page is mounted * @param nodeURL The URL where this page is mounted
* @param itemId The id of the item to display * @param itemId The id of the item to display
* @param tab The index of the tab to display * @param tab The index of the tab to display
*
* @return * @return
*/ */
public static String getItemURL(final String nodeURL, public static String getItemURL(final String nodeURL,
@ -423,6 +437,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* @param itemId The id of the item to display * @param itemId The id of the item to display
* @param tab The index of the tab to display * @param tab The index of the tab to display
* @param streamlinedCreation Whether to activate Streamlined item authoring * @param streamlinedCreation Whether to activate Streamlined item authoring
*
* @return * @return
*/ */
public static String getItemURL(final String nodeURL, public static String getItemURL(final String nodeURL,
@ -459,7 +474,9 @@ public class ContentItemPage extends CMSPage implements ActionListener {
/** /**
* @param itemId * @param itemId
* @param tab * @param tab
*
* @return * @return
*
* @deprecated Use getItemURL instead * @deprecated Use getItemURL instead
*/ */
public static String getRelativeItemURL(final Long itemId, final int tab) { public static String getRelativeItemURL(final Long itemId, final int tab) {
@ -483,6 +500,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* *
* @param item the ContentItem object to display * @param item the ContentItem object to display
* @param tab The index of the tab to display * @param tab The index of the tab to display
*
* @return * @return
*/ */
public static String getItemURL(final ContentItem item, public static String getItemURL(final ContentItem item,
@ -503,6 +521,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* *
* @param itemId the id of the ContentItem object to display * @param itemId the id of the ContentItem object to display
* @param tab The index of the tab to display * @param tab The index of the tab to display
*
* @return * @return
*/ */
public static String getItemURL(final long itemId, public static String getItemURL(final long itemId,
@ -560,21 +579,17 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* *
* @param state * @param state
* @param item * @param item
*
* @return * @return
*/ */
private String getDefaultPreviewLink(final PageState state, private String getDefaultPreviewLink(final PageState state,
final ContentItem item) { final ContentItem item) {
final ContentSection section = CMS.getContext().getContentSection(); final ContentSection section = CMS.getContext().getContentSection();
final ItemResolver itemResolver; final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
try { final ContentSectionManager sectionManager = cdiUtil.findBean(
final Class<?> itemResolverClass = Class.forName(section. ContentSectionManager.class);
getItemResolverClass()); final ItemResolver itemResolver = sectionManager
itemResolver = (ItemResolver) itemResolverClass.newInstance(); .getItemResolver(section);
} catch (ClassNotFoundException
| IllegalAccessException
| InstantiationException ex) {
throw new UncheckedWrapperException(ex);
}
// Pass in the "Live" context since we need it for the preview // Pass in the "Live" context since we need it for the preview
return itemResolver.generateItemURL(state, return itemResolver.generateItemURL(state,
@ -610,6 +625,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* *
* @param state PageState * @param state PageState
* @param parent Parent document * @param parent Parent document
*
* @return page * @return page
*/ */
@Override @Override
@ -626,4 +642,5 @@ public class ContentItemPage extends CMSPage implements ActionListener {
return page; return page;
} }
} }

View File

@ -42,8 +42,7 @@ import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn; import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableHeader; import com.arsdigita.bebop.table.TableHeader;
import com.arsdigita.bebop.table.TableModel; import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.cms.*; import com.arsdigita.cms.CMS;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.kernel.KernelConfig; import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.toolbox.ui.FormatStandards; import com.arsdigita.toolbox.ui.FormatStandards;
@ -77,6 +76,7 @@ import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionManager; import org.librecms.contentsection.ContentSectionManager;
import org.librecms.contentsection.privileges.ItemPrivileges; import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.dispatcher.ItemResolver;
import java.util.Date; import java.util.Date;

View File

@ -33,7 +33,6 @@ import org.librecms.contentsection.ContentSection;
import com.arsdigita.cms.ItemSelectionModel; import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.dispatcher.CMSDispatcher; import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.ItemResolver;
import org.librecms.lifecycle.Lifecycle; import org.librecms.lifecycle.Lifecycle;
@ -61,6 +60,7 @@ import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.security.Shiro; import org.libreccm.security.Shiro;
import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSectionManager; import org.librecms.contentsection.ContentSectionManager;
import org.librecms.dispatcher.ItemResolver;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.Date; import java.util.Date;

View File

@ -43,7 +43,6 @@ import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import com.arsdigita.cms.dispatcher.CMSDispatcher; import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.BaseItemPane; import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal; import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.toolbox.ui.ActionGroup; import com.arsdigita.toolbox.ui.ActionGroup;
@ -52,9 +51,9 @@ import com.arsdigita.toolbox.ui.NullComponent;
import com.arsdigita.toolbox.ui.Section; import com.arsdigita.toolbox.ui.Section;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSectionManager; import org.librecms.contentsection.ContentSectionManager;
import org.librecms.dispatcher.ItemResolver;
import java.math.BigInteger; import java.math.BigInteger;

View File

@ -18,13 +18,14 @@
*/ */
package org.arsdigita.cms; package org.arsdigita.cms;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.util.UncheckedWrapperException;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.configuration.Configuration; import org.libreccm.configuration.Configuration;
import org.libreccm.configuration.ConfigurationManager; import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.configuration.Setting; import org.libreccm.configuration.Setting;
import org.librecms.dispatcher.ItemResolver;
import org.librecms.dispatcher.SimpleItemResolver;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -292,7 +293,7 @@ public class CMSConfig {
@Setting @Setting
private List<String> defaultItemResolverClassNames = Arrays.asList( private List<String> defaultItemResolverClassNames = Arrays.asList(
new String[]{ new String[]{
ItemResolver.class.getName() SimpleItemResolver.class.getName()
}); });
// @Setting // @Setting

View File

@ -18,10 +18,9 @@
*/ */
package org.librecms.contentsection; package org.librecms.contentsection;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.kernel.KernelConfig; import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.util.UncheckedWrapperException;
import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryRepository; import org.libreccm.categorization.CategoryRepository;
import org.libreccm.configuration.ConfigurationManager; import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.core.CoreConstants; import org.libreccm.core.CoreConstants;
@ -51,7 +50,11 @@ import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.lifecycle.LifecycleDefinition; import org.librecms.lifecycle.LifecycleDefinition;
import java.util.Optional; import java.util.Optional;
import org.librecms.contentsection.privileges.TypePrivileges; import org.librecms.contentsection.privileges.TypePrivileges;
import org.librecms.dispatcher.ItemResolver;
import javax.enterprise.inject.Instance;
import static org.librecms.contentsection.ContentSection.*; import static org.librecms.contentsection.ContentSection.*;
@ -84,6 +87,9 @@ public class ContentSectionManager {
@Inject @Inject
private ConfigurationManager confManager; private ConfigurationManager confManager;
@Inject
private Instance<ItemResolver> itemResolvers;
/** /**
* Creates a new content section including the default roles. This operation * Creates a new content section including the default roles. This operation
* requries {@code admin} privileges. * requries {@code admin} privileges.
@ -448,11 +454,19 @@ public class ContentSectionManager {
final Class<ItemResolver> itemResolverClazz final Class<ItemResolver> itemResolverClazz
= (Class<ItemResolver>) Class. = (Class<ItemResolver>) Class.
forName(section.getItemResolverClass()); forName(section.getItemResolverClass());
return itemResolverClazz.newInstance();
} catch (ClassNotFoundException final Instance<ItemResolver> instance = itemResolvers.select(
| IllegalAccessException itemResolverClazz);
| InstantiationException ex) {
throw new RuntimeException(ex); if (instance.isUnsatisfied()) {
throw new UncheckedWrapperException(String.format(
"No ItemResolver \"{}\" found.",
itemResolverClazz.getName()));
} else {
return instance.get();
}
} catch (ClassNotFoundException ex) {
throw new UncheckedWrapperException(ex);
} }
} }

View File

@ -21,7 +21,6 @@ package org.librecms.contentsection;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
import com.arsdigita.cms.dispatcher.CMSPage; import com.arsdigita.cms.dispatcher.CMSPage;
import com.arsdigita.cms.dispatcher.ContentItemDispatcher; import com.arsdigita.cms.dispatcher.ContentItemDispatcher;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.CMSApplicationPage; import com.arsdigita.cms.ui.CMSApplicationPage;
import com.arsdigita.dispatcher.AccessDeniedException; import com.arsdigita.dispatcher.AccessDeniedException;
import com.arsdigita.dispatcher.DispatcherHelper; import com.arsdigita.dispatcher.DispatcherHelper;
@ -30,7 +29,6 @@ import com.arsdigita.templating.PresentationManager;
import com.arsdigita.templating.Templating; import com.arsdigita.templating.Templating;
import com.arsdigita.util.Assert; import com.arsdigita.util.Assert;
import com.arsdigita.util.Classes; import com.arsdigita.util.Classes;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.ApplicationFileResolver; import com.arsdigita.web.ApplicationFileResolver;
import com.arsdigita.web.BaseApplicationServlet; import com.arsdigita.web.BaseApplicationServlet;
import com.arsdigita.web.LoginSignal; import com.arsdigita.web.LoginSignal;
@ -39,7 +37,6 @@ import com.arsdigita.web.WebConfig;
import com.arsdigita.xml.Document; import com.arsdigita.xml.Document;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -59,10 +56,12 @@ import org.libreccm.security.Shiro;
import org.libreccm.web.CcmApplication; import org.libreccm.web.CcmApplication;
import org.librecms.CmsConstants; import org.librecms.CmsConstants;
import org.librecms.contentsection.privileges.ItemPrivileges; import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.dispatcher.ItemResolver;
import org.librecms.lifecycle.Lifecycle; import org.librecms.lifecycle.Lifecycle;
import java.util.Date; import java.util.Date;
import javax.inject.Inject;
import javax.servlet.RequestDispatcher; import javax.servlet.RequestDispatcher;
/* /*
@ -136,8 +135,8 @@ public class ContentSectionServlet extends BaseApplicationServlet {
= "com.arsdigita.cms.dispatcher.section"; = "com.arsdigita.cms.dispatcher.section";
private final ContentItemDispatcher m_disp = new ContentItemDispatcher(); private final ContentItemDispatcher m_disp = new ContentItemDispatcher();
private static Map<String, ItemResolver> itemResolverCache = Collections // private static Map<String, ItemResolver> itemResolverCache = Collections
.synchronizedMap(new HashMap<>()); // .synchronizedMap(new HashMap<>());
private static Map s_itemURLCacheMap = null; private static Map s_itemURLCacheMap = null;
/** /**
* Whether to cache the content items * Whether to cache the content items
@ -161,6 +160,9 @@ public class ContentSectionServlet extends BaseApplicationServlet {
*/ */
private ApplicationFileResolver m_resolver; private ApplicationFileResolver m_resolver;
@Inject
private ContentSectionManager sectionManager;
/** /**
* Init method overwrites parents init to pass in optional parameters * Init method overwrites parents init to pass in optional parameters
* {@link com.arsdigita.web.BaseServlet}. If not specified system wide * {@link com.arsdigita.web.BaseServlet}. If not specified system wide
@ -411,32 +413,23 @@ public class ContentSectionServlet extends BaseApplicationServlet {
return (ContentSection) request.getAttribute(CONTENT_SECTION); return (ContentSection) request.getAttribute(CONTENT_SECTION);
} }
public static boolean checkAdminAccess(final HttpServletRequest request,
final ContentSection section) {
final PermissionChecker permissionChecker = CdiUtil.createCdiUtil()
.findBean(PermissionChecker.class);
return permissionChecker.isPermitted(ItemPrivileges.PREVIEW,
section)
|| permissionChecker.isPermitted(ItemPrivileges.EDIT,
section)
|| permissionChecker.isPermitted(ItemPrivileges.APPROVE,
section);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public ItemResolver getItemResolver(final ContentSection section) { public ItemResolver getItemResolver(final ContentSection section) {
final String path = section.getPrimaryUrl(); return sectionManager.getItemResolver(section);
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, public ContentItem getItem(final ContentSection section,

View File

@ -18,8 +18,6 @@
*/ */
package org.librecms.contentsection; package org.librecms.contentsection;
import com.arsdigita.cms.dispatcher.MultilingualItemResolver;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.libreccm.modules.InstallEvent; import org.libreccm.modules.InstallEvent;
@ -34,6 +32,7 @@ import static org.librecms.contentsection.ContentSection.*;
import org.librecms.contentsection.privileges.AdminPrivileges; import org.librecms.contentsection.privileges.AdminPrivileges;
import org.librecms.contentsection.privileges.AssetPrivileges; import org.librecms.contentsection.privileges.AssetPrivileges;
import org.librecms.contentsection.privileges.ItemPrivileges; import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.dispatcher.MultilingualItemResolver;
/** /**
* *

View File

@ -0,0 +1,243 @@
/*
* Copyright (C) 2017 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 org.librecms.dispatcher;
import com.arsdigita.bebop.PageState;
import com.arsdigita.cms.dispatcher.CMSPage;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemVersion;
import org.librecms.contentsection.ContentSection;
import java.util.StringTokenizer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
/**
* The {@code ItemResolver} is responsible for mapping a URL in a particular
* content section to a content item.
*
*
* As an example, here is the item resolution process for a request to
* {@code http://yourserver/cms/cheese}:
*
* The item resolver would be asked to map the URL stub {@code /cheese} in the
* content section mounted at {@code /cms} to a content item. To this end, the
* dispatcher calls the {@link #getItem} method, passing in the
* {@link com.arsdigita.cms.ContentSection} and the URL stub for the item within
* the section, {@code /cheese} in our example. As a final argument, the
* dispatcher passes either {@link ContentItemVersion#DRAFT} or
* {@link ContentItemVersion#LIVE} to the {@code ItemResolver}, depending on
* whether the returned item should be the live version (for pages) or the draft
* version (for previewing).
*
* Originally these interface was located in the
* {@code org.arsdigita.cms.dispatcher} package but has been moved here when its
* implementations had been refactored to CDI beans. Also the default
* implementations of the {@link #getTemplateFromURL(java.lang.String)} and
* {@link #stripTemplateFromURL(java.lang.String)} from the old
* {@code AbstractItemResolver} class have been moved here which is now possible
* thanks to the default methods in interfaces introduced in Java 8. The
* class {@code AbstractItemResolver} has been removed completely.
*
* @author Michael Pih (pihman@arsdigita.com)
* @author Stanislav Freidin (sfreidin@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* @version $Revision$ $DateTime: 2004/08/17 23:15:09 $
* @version $Id$
*/
public interface ItemResolver {
public static final String TEMPLATE_CONTEXT_PREFIX = "tem_";
/**
* Return a content item based on section, url, and use context.
*
* @param section The current content section
* @param url The section-relative URL
* @param context The use context
*
* @return The content item, or null if no such item exists
*/
ContentItem getItem(ContentSection section,
String url,
String context);
/**
* Fetches the current context based on the page state.
*
* @param state the current page state
*
* @return the context of the current URL, such as "live" or "admin"
*/
String getCurrentContext(PageState state);
/**
* 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"
*
* @return The URL of the item
*
* @see #getCurrentContext
*/
String generateItemURL(PageState state,
Long itemId,
String name,
ContentSection section,
String context);
/**
* 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
*
* @see #getCurrentContext
*/
String generateItemURL(PageState state,
Long itemId,
String name,
ContentSection section,
String context,
String templateContext
);
/**
* 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"
*
* @return The URL of the item
*
* @see #getCurrentContext
*/
String generateItemURL(PageState state,
ContentItem item,
ContentSection section,
String 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 "admin"
* @param templateContext the context for the URL, such as "public"
*
* @return The URL of the item
*
* @see #getCurrentContext
*/
String generateItemURL(PageState state,
ContentItem item,
ContentSection section,
String context,
String templateContext);
/**
* Return a master page based on page state (and content section).
*
* @param item The content item
* @param request The HTTP request
*
* @return The master page
*
* @throws javax.servlet.ServletException
*/
CMSPage getMasterPage(ContentItem item, HttpServletRequest request)
throws ServletException;
/*
* Having to stick the following methods, getTemplateFromURL, and
* stripTemplateFromURL in the ItemResolver interface is somewhat ugly.
* But, the relationship between ItemResolver and TemplateResolver needs
* to be cleaned up to fix this. As it is, ItemResolver parses URL's for
* template contexts, and TemplateResolver sets the actual template contexts
* in the request.
*/
/**
* Finds the template context from the URL and returns it, if it is there.
* Otherwise, returns null.
*
* @param inUrl the URL from which to get the template context
*
* @return the template context, or null if there is no template context
*/
default String getTemplateFromURL(final String inUrl) {
final String tempUrl;
if (inUrl.startsWith("/")) {
tempUrl = inUrl.substring(1);
} else {
tempUrl = inUrl;
}
final StringTokenizer tokenizer = new StringTokenizer(tempUrl, "/");
final String templateContext;
if (tokenizer.hasMoreTokens()) {
templateContext = tokenizer.nextToken();
} else {
templateContext = null;
}
if (templateContext != null && templateContext.startsWith(
TEMPLATE_CONTEXT_PREFIX)) {
return templateContext.substring(TEMPLATE_CONTEXT_PREFIX.length());
} else {
return null;
}
}
/**
* Removes the template context from the <code>inUrl</code>.
*
* @param inUrl URL, possibly including the template context.
*
* @return <code>inUrl</code> with the template context removed
*/
default String stripTemplateFromURL(final String inUrl) {
final String sTemplateContext = getTemplateFromURL(inUrl);
if (sTemplateContext != null) {
//there is a template context, so strip it
final int iTemplateLength = TEMPLATE_CONTEXT_PREFIX.length()
+ sTemplateContext.length() + 1;
return inUrl.substring(iTemplateLength, inUrl.length());
} else {
return inUrl;
}
}
}

View File

@ -1,10 +1,10 @@
/* /*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. * Copyright (C) 2017 LibreCCM Foundation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public
* as published by the Free Software Foundation; either version 2.1 of * License as published by the Free Software Foundation; either
* the License, or (at your option) any later version. * 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, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -13,52 +13,58 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* * MA 02110-1301 USA
*/ */
package com.arsdigita.cms.dispatcher; package org.librecms.dispatcher;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.cms.CMS; import com.arsdigita.cms.CMS;
import com.arsdigita.cms.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.CMSPage;
import com.arsdigita.cms.dispatcher.MasterPage;
import com.arsdigita.cms.ui.ContentItemPage; import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.kernel.KernelConfig; import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.util.Assert; import com.arsdigita.util.Assert;
import org.apache.logging.log4j.Logger;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Objects;
import java.util.StringTokenizer;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.libreccm.cdi.utils.CdiUtil; import org.apache.logging.log4j.Logger;
import org.libreccm.core.CcmObject; import org.libreccm.core.CcmObject;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.CmsConstants; import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager; import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentItemVersion; import org.librecms.contentsection.ContentItemVersion;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.Folder; import org.librecms.contentsection.Folder;
import org.librecms.contentsection.FolderManager; import org.librecms.contentsection.FolderManager;
import org.librecms.util.LanguageUtil; import org.librecms.contentsection.FolderRepository;
import java.math.BigDecimal; import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.StringTokenizer;
import static javax.naming.ldap.SortControl.*; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
/** /**
* Resolves items to URLs and URLs to items for multiple language variants. * Resolves items to URLs and URLs to items for multiple language variants.
* *
* For version 7.0.0 this call has been moved from the
* {@code com.arsdigita.cms.dispatcher} package to the
* {@code org.librecms.dispatcher} package and refactored to an CDI bean. This
* was necessary to avoid several problems when accessing the entity beans for
* {@link Category} and {@link ContentItem}, primarily the infamous
* {@code LazyInitializationException}. Also several checks for null parameters
* were added to avoid {@code NullPointerExcpetions}.
*
* <strong> * <strong>
* AS of version 7.0.0 this class not longer part of the public API. It is left * AS of version 7.0.0 this class not longer part of the public API. It is left
* here to keep the changes to the UI classes as minimal as possible. For new * here to keep the changes to the UI classes as minimal as possible. For new
@ -73,13 +79,12 @@ import static javax.naming.ldap.SortControl.*;
* @author <a href="mailto:mhanisch@redhat.com">Michael Hanisch</a> * @author <a href="mailto:mhanisch@redhat.com">Michael Hanisch</a>
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
public class MultilingualItemResolver @RequestScoped
extends AbstractItemResolver implements ItemResolver { public class MultilingualItemResolver implements ItemResolver {
private static final Logger LOGGER = LogManager.getLogger( private static final Logger LOGGER = LogManager.getLogger(
MultilingualItemResolver.class); MultilingualItemResolver.class);
private static MasterPage s_masterP = null;
private static final String ADMIN_PREFIX = "admin"; private static final String ADMIN_PREFIX = "admin";
/** /**
@ -92,9 +97,17 @@ public class MultilingualItemResolver
*/ */
protected static final String SEPARATOR = "&"; protected static final String SEPARATOR = "&";
public MultilingualItemResolver() { @Inject
LOGGER.debug("Undergoing creation"); private FolderRepository folderRepo;
}
@Inject
private FolderManager folderManager;
@Inject
private ContentItemRepository itemRepo;
@Inject
private ContentItemManager itemManager;
/** /**
* Returns a content item based on section, url, and use context. * Returns a content item based on section, url, and use context.
@ -108,25 +121,32 @@ public class MultilingualItemResolver
* *
* @return The content item, or null if no such item exists * @return The content item, or null if no such item exists
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@Override @Override
public ContentItem getItem(final ContentSection section, public ContentItem getItem(final ContentSection section,
final String itemUrl, final String itemUrl,
final String context) { final String context) {
if (section == null) {
throw new IllegalArgumentException(
"Can't get item from section null.");
}
if (itemUrl == null) {
throw new IllegalArgumentException("Can't get item for URL null.");
}
if (context == null) {
throw new IllegalArgumentException(
"Can't get item for context null.");
}
LOGGER.debug("Resolving the item in content section \"{}\" at URL " LOGGER.debug("Resolving the item in content section \"{}\" at URL "
+ "\"{}\" for context \"{}\"...", + "\"{}\" for context \"{}\"...",
section.getLabel(), section.getLabel(),
itemUrl, itemUrl,
context); context);
Assert.exists(section, "ContentSection section");
Assert.exists(itemUrl, "String url");
Assert.exists(context, "String context");
final Folder rootFolder = section.getRootDocumentsFolder(); final Folder rootFolder = section.getRootDocumentsFolder();
String url = stripTemplateFromURL(itemUrl); String url = stripTemplateFromURL(itemUrl);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
if (rootFolder == null) { if (rootFolder == null) {
// nothing to do, if root folder is null // nothing to do, if root folder is null
LOGGER.debug("The root folder is null; returning no item"); LOGGER.debug("The root folder is null; returning no item");
@ -139,8 +159,6 @@ public class MultilingualItemResolver
LOGGER.debug("The root folder has a live version; recursing"); LOGGER.debug("The root folder has a live version; recursing");
final FolderManager folderManager = cdiUtil.findBean(
FolderManager.class);
final String prefix = String.join( final String prefix = String.join(
"", "",
section.getPrimaryUrl(), section.getPrimaryUrl(),
@ -229,6 +247,7 @@ public class MultilingualItemResolver
* *
* ToDo: Refactor to use the {@link ContentItemVersion} directly. * ToDo: Refactor to use the {@link ContentItemVersion} directly.
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@Override @Override
public String getCurrentContext(final PageState state) { public String getCurrentContext(final PageState state) {
LOGGER.debug("Getting the current context"); LOGGER.debug("Getting the current context");
@ -276,6 +295,7 @@ public class MultilingualItemResolver
* *
* @see #getCurrentContext * @see #getCurrentContext
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@Override @Override
public String generateItemURL(final PageState state, public String generateItemURL(final PageState state,
final Long itemId, final Long itemId,
@ -299,6 +319,7 @@ public class MultilingualItemResolver
* *
* @see #getCurrentContext * @see #getCurrentContext
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@Override @Override
public String generateItemURL(final PageState state, public String generateItemURL(final PageState state,
final Long itemId, final Long itemId,
@ -306,20 +327,25 @@ public class MultilingualItemResolver
final ContentSection section, final ContentSection section,
final String context, final String context,
final String templateContext) { final String templateContext) {
if (LOGGER.isDebugEnabled()) { if (itemId == null) {
LOGGER.debug("Generating an item URL for item id " + itemId throw new IllegalArgumentException(
+ ", section " + section + ", and context '" "Can't generate item URL for item id null.");
+ context }
+ "' with name '" + name + "'"); if (context == null) {
throw new IllegalArgumentException(
"Can't generate item URL for context null.");
}
if (section == null) {
throw new IllegalArgumentException(
"Can't generate item URL for section null.");
} }
Assert.exists(itemId, "BigDecimal itemId"); LOGGER.debug("Generating an item URL for item id {}, section \"{}\" "
Assert.exists(context, "String context"); + "and context \"{}\" with name \"{}\"...",
Assert.exists(section, "ContentSection section"); itemId,
section.getLabel(),
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); context,
final ContentItemRepository itemRepo = cdiUtil.findBean( name);
ContentItemRepository.class);
if (ContentItemVersion.DRAFT.toString().equals(context)) { if (ContentItemVersion.DRAFT.toString().equals(context)) {
// No template context here. // No template context here.
@ -349,6 +375,7 @@ public class MultilingualItemResolver
* *
* @see #getCurrentContext * @see #getCurrentContext
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@Override @Override
public String generateItemURL(final PageState state, public String generateItemURL(final PageState state,
final ContentItem item, final ContentItem item,
@ -370,16 +397,20 @@ public class MultilingualItemResolver
* *
* @see #getCurrentContext * @see #getCurrentContext
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@Override @Override
public String generateItemURL(final PageState state, public String generateItemURL(final PageState state,
final ContentItem item, final ContentItem item,
final ContentSection section, final ContentSection section,
final String context, final String context,
final String templateContext) { final String templateContext) {
if (LOGGER.isDebugEnabled()) { if (item == null) {
LOGGER.debug("Generating an item URL for item " + item throw new IllegalArgumentException(
+ ", section " "Can't generate URL for item null.");
+ section + ", and context " + context); }
if (context == null) {
throw new IllegalArgumentException(
"Can't generate URL for context null.");
} }
final ContentSection contentSection; final ContentSection contentSection;
@ -389,6 +420,12 @@ public class MultilingualItemResolver
contentSection = section; contentSection = section;
} }
LOGGER.debug("Generating an item URL for item \"{}\", section \"{}\" "
+ "and context \"{}\".",
item.getDisplayName(),
contentSection.getLabel(),
context);
if (ContentItemVersion.DRAFT.toString().equals(context)) { if (ContentItemVersion.DRAFT.toString().equals(context)) {
return generateDraftURL(section, item.getObjectId()); return generateDraftURL(section, item.getObjectId());
} else if (CMSDispatcher.PREVIEW.equals(context)) { } else if (CMSDispatcher.PREVIEW.equals(context)) {
@ -401,35 +438,19 @@ public class MultilingualItemResolver
} }
} }
/** @Transactional(Transactional.TxType.REQUIRED)
* Returns a master page based on page state (and content section).
*
* @param item The content item
* @param request The HTTP request
*
* @return The master page
*
* @throws javax.servlet.ServletException
*/
@Override @Override
public CMSPage getMasterPage(final ContentItem item, public CMSPage getMasterPage(final ContentItem item,
final HttpServletRequest request) final HttpServletRequest request)
throws ServletException { throws ServletException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Getting the master page for item " + item);
}
// taken from SimpleItemResolver LOGGER.debug("Getting the master page for item {}",
if (s_masterP == null) { item.getDisplayName());
s_masterP = new MasterPage();
s_masterP.init();
}
if (LOGGER.isDebugEnabled()) { final MasterPage masterPage = new MasterPage();
LOGGER.debug("Returning master page " + s_masterP); masterPage.init();
}
return s_masterP; return masterPage;
} }
/** /**
@ -512,9 +533,6 @@ public class MultilingualItemResolver
.append("/"); .append("/");
} }
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemManager itemManager = cdiUtil.findBean(
ContentItemManager.class);
url.append(itemManager.getItemPath(item)); url.append(itemManager.getItemPath(item));
return url.toString(); return url.toString();
@ -561,9 +579,6 @@ public class MultilingualItemResolver
.append("/"); .append("/");
} }
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemManager itemManager = cdiUtil.findBean(
ContentItemManager.class);
url.append(itemManager.getItemPath(item)); url.append(itemManager.getItemPath(item));
return url.toString(); return url.toString();
@ -581,19 +596,10 @@ public class MultilingualItemResolver
* <code>url</code> * <code>url</code>
*/ */
protected ContentItem getItemFromDraftURL(final String url) { protected ContentItem getItemFromDraftURL(final String url) {
if (LOGGER.isDebugEnabled()) { LOGGER.debug("Looking up the item from draft URL ", url);
LOGGER.debug("Looking up the item from draft URL " + url);
}
int pos = url.indexOf(ITEM_ID); int pos = url.indexOf(ITEM_ID);
// XXX this is wrong: here we abort on not finding the
// parameter; below we return null.
if (Assert.isEnabled()) {
Assert.isTrue(pos >= 0,
"Draft URL must contain parameter " + ITEM_ID);
}
String item_id = url.substring(pos); // item_id == ITEM_ID=.... ? String item_id = url.substring(pos); // item_id == ITEM_ID=.... ?
pos = item_id.indexOf("="); // should be exactly after the ITEM_ID string pos = item_id.indexOf("="); // should be exactly after the ITEM_ID string
@ -612,13 +618,7 @@ public class MultilingualItemResolver
int i = item_id.indexOf(SEPARATOR); int i = item_id.indexOf(SEPARATOR);
item_id = item_id.substring(pos, Math.min(i, item_id.length() - 1)); item_id = item_id.substring(pos, Math.min(i, item_id.length() - 1));
if (LOGGER.isDebugEnabled()) { LOGGER.debug("Looking up item using item ID {}", item_id);
LOGGER.debug("Looking up item using item ID " + item_id);
}
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
final Optional<ContentItem> item = itemRepo.findById(Long.parseLong( final Optional<ContentItem> item = itemRepo.findById(Long.parseLong(
item_id)); item_id));
@ -642,21 +642,20 @@ public class MultilingualItemResolver
*/ */
protected ContentItem getItemFromLiveURL(final String url, protected ContentItem getItemFromLiveURL(final String url,
final Folder parentFolder) { final Folder parentFolder) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Resolving the item for live URL " + url
+ " and parent folder " + parentFolder);
}
if (parentFolder == null || url == null || url.equals("")) { if (parentFolder == null || url == null || url.equals("")) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("The url is null or parent folder was null " LOGGER.debug("The url is null or parent folder was null "
+ "or something else is wrong, so just return " + "or something else is wrong, so just return "
+ "null"); + "null.");
}
return null; return null;
} }
LOGGER.debug("Resolving the item for live URL {}"
+ " and parent folder {}...",
url,
parentFolder.getName());
int len = url.length(); int len = url.length();
int index = url.indexOf('/'); int index = url.indexOf('/');
@ -674,13 +673,11 @@ public class MultilingualItemResolver
final String[] nameAndLang = getNameAndLangFromURLFrag(url); final String[] nameAndLang = getNameAndLangFromURLFrag(url);
final String name = nameAndLang[0]; final String name = nameAndLang[0];
final Optional<CcmObject> item = parentFolder.getObjects().stream() final Optional<ContentItem> item = itemRepo.findByNameInFolder(
.map(categorization -> categorization.getCategorizedObject()) parentFolder, name);
.filter(object -> object.getDisplayName().equals(name))
.findFirst();
if (item.isPresent() && item.get() instanceof ContentItem) { if (item.isPresent()) {
return (ContentItem) item.get(); return item.get();
} else { } else {
return null; return null;
} }

View File

@ -1,10 +1,10 @@
/* /*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. * Copyright (C) 2017 LibreCCM Foundation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public
* as published by the Free Software Foundation; either version 2.1 of * License as published by the Free Software Foundation; either
* the License, or (at your option) any later version. * 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, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -13,43 +13,46 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* * MA 02110-1301 USA
*/ */
package com.arsdigita.cms.dispatcher; package org.librecms.dispatcher;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.cms.CMS; import com.arsdigita.cms.CMS;
import com.arsdigita.cms.dispatcher.CMSDispatcher;
import org.librecms.contentsection.ContentItem; import com.arsdigita.cms.dispatcher.CMSPage;
import org.librecms.contentsection.ContentSection; import com.arsdigita.cms.dispatcher.MasterPage;
import org.librecms.contentsection.Folder;
import com.arsdigita.cms.ui.ContentItemPage; import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.dispatcher.DispatcherHelper; import com.arsdigita.dispatcher.DispatcherHelper;
import com.arsdigita.web.URL; import com.arsdigita.web.URL;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.categorization.Category;
import org.libreccm.core.CcmObject; import org.libreccm.core.CcmObject;
import org.librecms.CmsConstants; import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager; import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentItemVersion; import org.librecms.contentsection.ContentItemVersion;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.Folder;
import java.util.Optional; import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
/** /**
* This is the default implementation of * This is the default implementation of
* {@link com.arsdigita.cms.dispatcher.ItemResolver}. * {@link com.arsdigita.cms.dispatcher.ItemResolver}.
* *
* The {@link #getItem(java.lang.String, org.librecms.contentsection.Folder) } * The {@link #getItem(java.lang.String, org.librecms.contentsection.Folder) }
* method of the default implementation of {@link ItemResolver}, * method of the default implementation of null {@link ItemResolver},
* {@link com.arsdigita.cms.dispatcher.SimpleItemResolver} runs a simple query * {@link com.arsdigita.cms.dispatcher.SimpleItemResolver} runs a simple query
* using the passed in information to retrieve the content item with a name that * 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 * matches the URL stub, in our example it looks for a content item with name
@ -63,52 +66,63 @@ import javax.servlet.http.HttpServletRequest;
* request. With the content item and the master page in hand, the dispatcher * request. With the content item and the master page in hand, the dispatcher
* calls {@code service} on the page. * calls {@code service} on the page.
* *
* For version 7.0.0 this call has been moved from the
* {@code com.arsdigita.cms.dispatcher} package to the
* {@code org.librecms.dispatcher} package and refactored to an CDI bean. This
* was necessary to avoid several problems when accessing the entity beans for
* {@link Category} and {@link ContentItem}, primarily the infamous
* {@code LazyInitializationException}. Also several checks for null parameters
* were added to avoid {@code NullPointerExcpetions}.
*
* <strong> * <strong>
* AS of version 7.0.0 this class not longer part of the public API. It is left * AS of version 7.0.0 this class not longer part of the public API. It is left
* here to keep the changes to the UI classes as minimal as possible. For new * here to keep the changes to the UI classes as minimal as possible. For new
* code other methods, for example from the {@link ContentItemManager} or * code other methods, for example from the {@link ContentItemManager} or the
* the {@link ContentItemRepository} should be used. Because this class is no * {@link ContentItemRepository} should be used. Because this class is no longer
* longer part of the public API the will might be removed or changed in future * part of the public API the will might be removed or changed in future
* releases without prior warning. * releases without prior warning.
* </strong> * </strong>
* *
* @author Michael Pih (pihman@arsdigita.com) * @author Michael Pih (pihman@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
public class SimpleItemResolver @RequestScoped
extends AbstractItemResolver public class SimpleItemResolver implements ItemResolver {
implements ItemResolver {
private static final Logger LOGGER = LogManager.getLogger( private static final Logger LOGGER = LogManager.getLogger(
SimpleItemResolver.class.getName()); SimpleItemResolver.class);
private static final String ADMIN_PREFIX = "admin"; private static final String ADMIN_PREFIX = "admin";
private static final String WORKSPACE_PREFIX private static final String WORKSPACE_PREFIX
= CmsConstants.CONTENT_CENTER_URL; = CmsConstants.CONTENT_CENTER_URL;
private static MasterPage masterPage = null; @Inject
private ContentItemRepository itemRepo;
@Inject
private ContentItemManager itemManager;
public SimpleItemResolver() { @Transactional(Transactional.TxType.REQUIRED)
}
/**
* 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
*/
@Override @Override
public ContentItem getItem(final ContentSection section, public ContentItem getItem(final ContentSection section,
final String url, final String url,
final String context) { final String context) {
if (section == null) {
if (LOGGER.isDebugEnabled()) { throw new IllegalArgumentException(
LOGGER.debug("trying to get " + context + " item for url " + url); "Can't get an item for ContentSection null.");
} }
if (url == null) {
throw new IllegalArgumentException("Can't get an item for URL null.");
}
if (context == null) {
throw new IllegalArgumentException(
"Can't get an item for context null.");
}
LOGGER.debug(
"Trying to get {} item for url \"{}\" from content section \"{}\"...",
context,
url,
section.getLabel());
final String itemUrl = stripTemplateFromURL(url); final String itemUrl = stripTemplateFromURL(url);
@ -120,27 +134,28 @@ public class SimpleItemResolver
ContentItem reqItem = (ContentItem) DispatcherHelper.getRequest(). ContentItem reqItem = (ContentItem) DispatcherHelper.getRequest().
getAttribute("com.arsdigita.cms.dispatcher.item"); getAttribute("com.arsdigita.cms.dispatcher.item");
if (reqItem != null) { if (reqItem != null) {
LOGGER.info("found item in the request, returning it"); LOGGER.info("Found item in the request, returning it.");
return reqItem; return reqItem;
} }
final Folder rootFolder = section.getRootDocumentsFolder(); final Folder rootFolder = section.getRootDocumentsFolder();
if (rootFolder == null) { if (rootFolder == null) {
LOGGER.info("no root folder found, returning null"); LOGGER.info("No root folder found, returning null.");
return null; return null;
} }
return getItem(itemUrl, rootFolder); return getItem(itemUrl, rootFolder);
} }
/** @Transactional(Transactional.TxType.REQUIRED)
* @param state the current page state
*
* @return the context of the current URL, such as "live" or "admin"
*/
@Override @Override
public String getCurrentContext(final PageState state) { public String getCurrentContext(final PageState state) {
if (state == null) {
throw new IllegalArgumentException(
"Can't get current context from PageState null.");
}
String url = state.getRequest().getRequestURI(); String url = state.getRequest().getRequestURI();
final ContentSection section = CMS.getContext().getContentSection(); final ContentSection section = CMS.getContext().getContentSection();
@ -168,17 +183,29 @@ public class SimpleItemResolver
/** /**
* Return the content item at the specified path, or null if no such item * 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, * exists.
* "/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. * The path is interpreted as a series of folders; for example,
* {@code /foo/bar/baz} will look for an item named @code{baz} in a folder
* named * @code{bar} * in a folder named {@code foo} under the specified
* root folder.
* *
* @param url the URL to the item * @param url the URL to the item
* @param rootFolder The root folder where the item search will start * @param rootFolder The root folder where the item search will start
* *
* @return the item on success, null if no such item exists * @return the item on success, null if no such item exists
*/ */
@Transactional(Transactional.TxType.REQUIRED)
public ContentItem getItem(final String url, final Folder rootFolder) { public ContentItem getItem(final String url, final Folder rootFolder) {
if (url == null) {
throw new IllegalArgumentException("Can't get item for URL null.");
}
if (rootFolder == null) {
throw new IllegalArgumentException(
"Can't get item from rootFolder null.");
}
final String[] tokens = url.split("/"); final String[] tokens = url.split("/");
Folder currentFolder = rootFolder; Folder currentFolder = rootFolder;
@ -227,6 +254,15 @@ public class SimpleItemResolver
*/ */
private String generateDraftURL(final Long itemId, private String generateDraftURL(final Long itemId,
final ContentSection section) { final ContentSection section) {
if (itemId == null) {
throw new IllegalArgumentException(
"Can't generat draft URL for itemId null.");
}
if (itemId == null) {
throw new IllegalArgumentException(
"Can't generat draft URL for content section null.");
}
return ContentItemPage.getItemURL( return ContentItemPage.getItemURL(
String.format("%s%s/", String.format("%s%s/",
URL.getDispatcherPath(), URL.getDispatcherPath(),
@ -250,6 +286,15 @@ public class SimpleItemResolver
final ContentSection section, final ContentSection section,
final String templateContext) { final String templateContext) {
if (item == null) {
throw new IllegalArgumentException(
"Can't generate live URL for item null.");
}
if (section == null) {
throw new IllegalArgumentException(
"Can't generate live URL for content section null.");
}
final String templateUrlFrag; final String templateUrlFrag;
if (templateContext == null || templateContext.isEmpty()) { if (templateContext == null || templateContext.isEmpty()) {
templateUrlFrag = ""; templateUrlFrag = "";
@ -258,10 +303,6 @@ public class SimpleItemResolver
templateContext); templateContext);
} }
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemManager itemManager = cdiUtil.findBean(
ContentItemManager.class);
return String.format("%s/%s%s", return String.format("%s/%s%s",
section.getPrimaryUrl(), section.getPrimaryUrl(),
templateUrlFrag, templateUrlFrag,
@ -280,6 +321,15 @@ public class SimpleItemResolver
private String generatePreviewURL(final ContentItem item, private String generatePreviewURL(final ContentItem item,
final ContentSection section, final ContentSection section,
final String templateContext) { final String templateContext) {
if (item == null) {
throw new IllegalArgumentException(
"Can't generate draft URL for item null.");
}
if (section == null) {
throw new IllegalArgumentException(
"Can't generate draft URL for content section null.");
}
final String templateUrlFrag; final String templateUrlFrag;
if (templateContext == null || templateContext.isEmpty()) { if (templateContext == null || templateContext.isEmpty()) {
templateUrlFrag = ""; templateUrlFrag = "";
@ -287,9 +337,6 @@ public class SimpleItemResolver
templateUrlFrag = String.format(TEMPLATE_CONTEXT_PREFIX + "%s/", templateUrlFrag = String.format(TEMPLATE_CONTEXT_PREFIX + "%s/",
templateContext); templateContext);
} }
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemManager itemManager = cdiUtil.findBean(
ContentItemManager.class);
final StringBuilder url = new StringBuilder(); final StringBuilder url = new StringBuilder();
url url
@ -314,6 +361,7 @@ public class SimpleItemResolver
* *
* @return The URL of the item * @return The URL of the item
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@Override @Override
public String generateItemURL(final PageState state, public String generateItemURL(final PageState state,
final Long itemId, final Long itemId,
@ -335,6 +383,7 @@ public class SimpleItemResolver
* *
* @return The URL of the item * @return The URL of the item
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@Override @Override
public String generateItemURL(final PageState state, public String generateItemURL(final PageState state,
final Long itemId, final Long itemId,
@ -342,9 +391,6 @@ public class SimpleItemResolver
final ContentSection section, final ContentSection section,
final String context, final String context,
final String templateContext) { final String templateContext) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
if (ContentItemVersion.DRAFT.toString().equals(context)) { if (ContentItemVersion.DRAFT.toString().equals(context)) {
return generateDraftURL(itemId, section); return generateDraftURL(itemId, section);
@ -372,6 +418,7 @@ public class SimpleItemResolver
* *
* @see #getCurrentContext * @see #getCurrentContext
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@Override @Override
public String generateItemURL(final PageState state, public String generateItemURL(final PageState state,
final ContentItem item, final ContentItem item,
@ -393,6 +440,7 @@ public class SimpleItemResolver
* *
* @see #getCurrentContext * @see #getCurrentContext
*/ */
@Transactional(Transactional.TxType.REQUIRED)
@Override @Override
public String generateItemURL(final PageState state, public String generateItemURL(final PageState state,
final ContentItem item, final ContentItem item,
@ -412,23 +460,14 @@ public class SimpleItemResolver
} }
} }
/** @Transactional(Transactional.TxType.REQUIRED)
* Return a master page based on page state (and content section).
*
* @param item The content item
* @param request The HTTP request
*
* @throws javax.servlet.ServletException
*/
@Override @Override
public CMSPage getMasterPage(final ContentItem item, public CMSPage getMasterPage(final ContentItem item,
final HttpServletRequest request) final HttpServletRequest request)
throws ServletException { throws ServletException {
if (masterPage == null) { final MasterPage masterPage = new MasterPage();
masterPage = new MasterPage();
masterPage.init(); masterPage.init();
}
return masterPage; return masterPage;
} }

View File

@ -1,17 +1,18 @@
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2"> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2">
<jsp:directive.page import="com.arsdigita.cms.ui.ContentSectionPage"/> <jsp:directive.page import="com.arsdigita.cms.ui.ContentSectionPage"/>
<jsp:directive.page import="org.librecms.ContentSection"/> <jsp:directive.page import="org.librecms.contentsection.ContentSection"/>
<jsp:directive.page import="org.librecms.ContentSectionServlet"/> <jsp:directive.page import="org.librecms.contentsection.ContentSectionServlet"/>
<jsp:directive.page import="com.arsdigita.cms.dispatcher.Utilities"/> <jsp:directive.page import="com.arsdigita.cms.dispatcher.Utilities"/>
<jsp:directive.page import="com.arsdigita.dispatcher.*"/> <jsp:directive.page import="com.arsdigita.dispatcher.*"/>
<jsp:directive.page import="com.arsdigita.web.LoginSignal"/> <jsp:directive.page import="com.arsdigita.web.LoginSignal"/>
<jsp:directive.page import="com.arsdigita.web.Web"/> <jsp:directive.page import="com.arsdigita.web.Web"/>
<jsp:directive.page import="java.util.Date"/> <jsp:directive.page import="java.util.Date"/>
<jsp:directive.page import="org.libreccm.cdi.utils.CdiUtil"/>
<jsp:directive.page import="org.libreccm.security.Shiro"/>
<jsp:declaration> <jsp:declaration>
private ContentSectionPage sectionPage = new ContentSectionPage(); private ContentSectionPage sectionPage = new ContentSectionPage();
// private HttpServletRequest myRequest = DispatcherHelper.getRequest();
</jsp:declaration> </jsp:declaration>
<jsp:scriptlet> <jsp:scriptlet>
@ -21,13 +22,13 @@
ContentSection section = ContentSectionServlet.getContentSection(myRequest); ContentSection section = ContentSectionServlet.getContentSection(myRequest);
if (Web.getWebContext().getUser() == null) { //if (Web.getWebContext().getUser() == null) {
if (!CdiUtil.createCdiUtil().findBean(Shiro.class).getSubject().isAuthenticated()) {
throw new LoginSignal(myRequest); throw new LoginSignal(myRequest);
} else if (! ContentSectionServlet.checkAdminAccess(myRequest, section)) { } else if (! ContentSectionServlet.checkAdminAccess(myRequest, section)) {
throw new com.arsdigita.cms.dispatcher.AccessDeniedException(); throw new com.arsdigita.dispatcher.AccessDeniedException();
} }
RequestContext context = DispatcherHelper.getRequestContext(myRequest); RequestContext context = DispatcherHelper.getRequestContext(myRequest);
sectionPage.init(); sectionPage.init();
sectionPage.dispatch(myRequest, response, context); sectionPage.dispatch(myRequest, response, context);

View File

@ -141,7 +141,7 @@ public class AssetManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class) com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass( .addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class) com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
.addClass(com.arsdigita.cms.dispatcher.ItemResolver.class) .addClass(org.librecms.dispatcher.ItemResolver.class)
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage()) .addPackage(org.librecms.Cms.class.getPackage())

View File

@ -136,7 +136,7 @@ public class AssetRepositoryTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class) com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass( .addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class) com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
.addClass(com.arsdigita.cms.dispatcher.ItemResolver.class) .addClass(org.librecms.dispatcher.ItemResolver.class)
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage()) .addPackage(org.librecms.Cms.class.getPackage())

View File

@ -132,7 +132,7 @@ public class AttachmentListManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class) com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass( .addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class) com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
.addClass(com.arsdigita.cms.dispatcher.ItemResolver.class) .addClass(org.librecms.dispatcher.ItemResolver.class)
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage()) .addPackage(org.librecms.Cms.class.getPackage())

View File

@ -134,7 +134,7 @@ public class ContentItemL10NManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class) com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass( .addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class) com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
.addClass(com.arsdigita.cms.dispatcher.ItemResolver.class) .addClass(org.librecms.dispatcher.ItemResolver.class)
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage()) .addPackage(org.librecms.Cms.class.getPackage())

View File

@ -154,7 +154,7 @@ public class ContentItemManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class) com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass( .addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class) com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
.addClass(com.arsdigita.cms.dispatcher.ItemResolver.class) .addClass(org.librecms.dispatcher.ItemResolver.class)
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage()) .addPackage(org.librecms.Cms.class.getPackage())

View File

@ -136,8 +136,8 @@ public class ContentItemPermissionTest {
addClass( addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class). com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class).
addClass( addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class). com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
addClass(com.arsdigita.cms.dispatcher.ItemResolver.class) .addClass(org.librecms.dispatcher.ItemResolver.class)
.addClass(org.libreccm.portation.Portable.class) .addClass(org.libreccm.portation.Portable.class)
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())

View File

@ -127,7 +127,7 @@ public class ContentItemRepositoryTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class) com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass( .addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class) com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
.addClass(com.arsdigita.cms.dispatcher.ItemResolver.class) .addClass(org.librecms.dispatcher.ItemResolver.class)
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage()) .addPackage(org.librecms.Cms.class.getPackage())

View File

@ -163,8 +163,7 @@ public class ContentSectionManagerTest {
.addClass(org.libreccm.modules.Module.class) .addClass(org.libreccm.modules.Module.class)
.addClass(org.libreccm.modules.RequiredModule.class) .addClass(org.libreccm.modules.RequiredModule.class)
.addClass(org.libreccm.portation.Marshals.class) .addClass(org.libreccm.portation.Marshals.class)
.addPackage(com.arsdigita.cms.dispatcher.ItemResolver.class. .addPackage(org.librecms.dispatcher.ItemResolver.class.getPackage())
getPackage())
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage()) .addPackage(org.librecms.Cms.class.getPackage())

View File

@ -133,7 +133,7 @@ public class ContentTypeRepositoryTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class) com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass( .addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class) com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
.addClass(com.arsdigita.cms.dispatcher.ItemResolver.class) .addClass(org.librecms.dispatcher.ItemResolver.class)
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage()) .addPackage(org.librecms.Cms.class.getPackage())

View File

@ -124,8 +124,7 @@ public class FolderManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class) com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass( .addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class) com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
.addPackage(com.arsdigita.cms.dispatcher.ItemResolver.class. .addPackage(org.librecms.dispatcher.ItemResolver.class.getPackage())
getPackage())
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage()) .addPackage(org.librecms.Cms.class.getPackage())

View File

@ -139,7 +139,7 @@ public class ItemAttachmentManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class) com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass( .addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class) com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
.addClass(com.arsdigita.cms.dispatcher.ItemResolver.class) .addClass(org.librecms.dispatcher.ItemResolver.class)
.addPackage(com.arsdigita.util.Lockable.class.getPackage()) .addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) .addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage()) .addPackage(org.librecms.Cms.class.getPackage())

View File

@ -501,7 +501,8 @@ public class CCMDispatcherServlet extends BaseServlet {
if (path.length() > (m_instanceURI.length() + 1)) { if (path.length() > (m_instanceURI.length() + 1)) {
target.append(path.substring(m_instanceURI.length())); target.append(path.substring(m_instanceURI.length()));
} }
if (target.charAt(target.length() - 1) != '/') { if (target.charAt(target.length() - 1) != '/'
&& !path.contains(".")) {
target.append('/'); target.append('/');
} }
target.append("?"); target.append("?");