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

View File

@ -28,6 +28,7 @@ import com.arsdigita.xml.Element;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionServlet;
import org.librecms.dispatcher.ItemResolver;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -116,7 +117,7 @@ public class ContentPanel extends SimpleComponent {
ContentSectionServlet.PREVIEW);
}
pathInfo.newChildElement("cms:templatePrefix", CMS.CMS_XML_NS).setText(
"/" + AbstractItemResolver.TEMPLATE_CONTEXT_PREFIX);
"/" + ItemResolver.TEMPLATE_CONTEXT_PREFIX);
if (CMS.getContext().hasContentItem()) {
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.DispatcherHelper;
import com.arsdigita.dispatcher.RequestContext;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.LoginSignal;
import java.io.IOException;
@ -38,8 +39,10 @@ import org.libreccm.security.PermissionChecker;
import org.libreccm.security.Shiro;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionManager;
import org.librecms.contentsection.ContentSectionServlet;
import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.dispatcher.ItemResolver;
/**
* 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.
// final String templateURL = getTemplateURL(section, item, request,
// actx);
// s_log.debug("TEMPLATE " + templateURL);
DispatcherHelper.setRequestContext(request, actx);
DispatcherHelper.forwardRequestByPath(null, request,
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
*
@ -243,22 +244,11 @@ public class ItemDispatcher implements ChainedDispatcher {
*/
public ItemResolver getItemResolver(ContentSection section) {
String name = section.getLabel();
ItemResolver ir = (ItemResolver) s_itemResolverCache.get(name);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentSectionManager sectionManager = cdiUtil.findBean(
ContentSectionManager.class);
if (ir == null) {
try {
ir = (ItemResolver) Class
.forName(section.getItemResolverClass()).newInstance();
s_itemResolverCache.put(name, ir);
} catch (ClassNotFoundException |
IllegalAccessException |
InstantiationException ex) {
throw new RuntimeException(ex);
}
}
return ir;
return sectionManager.getItemResolver(section);
}
/**
@ -281,7 +271,6 @@ public class ItemDispatcher implements ChainedDispatcher {
//
// return ir;
// }
/**
* Fetches the URL of a template for an item. The returned URL is relative
* to the webapp context.
@ -297,5 +286,4 @@ public class ItemDispatcher implements ChainedDispatcher {
//
// 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.dispatcher.CMSDispatcher;
import com.arsdigita.cms.dispatcher.CMSPage;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.authoring.WizardSelector;
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
import com.arsdigita.cms.ui.item.CustomizedPreviewLink;
@ -70,7 +69,9 @@ import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentItemVersion;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionManager;
import org.librecms.contentsection.ContentType;
import org.librecms.dispatcher.ItemResolver;
import java.io.IOException;
import java.util.Optional;
@ -164,6 +165,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
protected final Object initialValue(final PageState state) {
return CMS.getContext().getContentItem();
}
}
private class TitlePrinter implements PrintListener {
@ -176,6 +178,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
label.setLabel(item.getDisplayName());
}
}
/**
@ -261,6 +264,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
templatesPane);
tabbedPane.addActionListener(new ActionListener() {
@Override
public final void actionPerformed(final ActionEvent event) {
@ -271,18 +275,22 @@ public class ContentItemPage extends CMSPage implements ActionListener {
((Resettable) pane).reset(state);
}
}
});
// Build the preview link.
m_previewLink = new Link(new Label(gz("cms.ui.preview")),
new PrintListener() {
@Override
public final void prepare(final PrintEvent event) {
public final void prepare(
final PrintEvent event) {
final Link link = (Link) event.getTarget();
link.setTarget(getPreviewURL(event.
getPageState()));
link.setTargetFrame(Link.NEW_FRAME);
}
});
m_previewLink.setIdAttr("preview_link");
add(m_previewLink);
@ -309,6 +317,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
CmsConstants.CMS_BUNDLE));
}
}
});
}
@ -317,6 +326,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* com.arsdigita.cms.ContentItem}.
*
* @param state The page state
*
* @pre state != null
* @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()
* instead
* @param request The HTTP request
*
* @return The current content section
*/
@Override
@ -352,6 +363,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
*
* @deprecated Use the ItemSelectionModel
* @param state The page state
*
* @return The current content item, null if there is none
*/
@Override
@ -361,6 +373,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
/**
* Set the current tab, if necessary
*
* @param event
*/
@Override
@ -408,6 +421,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
* @param nodeURL The URL where this page is mounted
* @param itemId The id of the item to display
* @param tab The index of the tab to display
*
* @return
*/
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 tab The index of the tab to display
* @param streamlinedCreation Whether to activate Streamlined item authoring
*
* @return
*/
public static String getItemURL(final String nodeURL,
@ -459,7 +474,9 @@ public class ContentItemPage extends CMSPage implements ActionListener {
/**
* @param itemId
* @param tab
*
* @return
*
* @deprecated Use getItemURL instead
*/
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 tab The index of the tab to display
*
* @return
*/
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 tab The index of the tab to display
*
* @return
*/
public static String getItemURL(final long itemId,
@ -560,21 +579,17 @@ public class ContentItemPage extends CMSPage implements ActionListener {
*
* @param state
* @param item
*
* @return
*/
private String getDefaultPreviewLink(final PageState state,
final ContentItem item) {
final ContentSection section = CMS.getContext().getContentSection();
final ItemResolver itemResolver;
try {
final Class<?> itemResolverClass = Class.forName(section.
getItemResolverClass());
itemResolver = (ItemResolver) itemResolverClass.newInstance();
} catch (ClassNotFoundException
| IllegalAccessException
| InstantiationException ex) {
throw new UncheckedWrapperException(ex);
}
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentSectionManager sectionManager = cdiUtil.findBean(
ContentSectionManager.class);
final ItemResolver itemResolver = sectionManager
.getItemResolver(section);
// Pass in the "Live" context since we need it for the preview
return itemResolver.generateItemURL(state,
@ -610,6 +625,7 @@ public class ContentItemPage extends CMSPage implements ActionListener {
*
* @param state PageState
* @param parent Parent document
*
* @return page
*/
@Override
@ -626,4 +642,5 @@ public class ContentItemPage extends CMSPage implements ActionListener {
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.TableHeader;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.cms.*;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.CMS;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.toolbox.ui.FormatStandards;
@ -77,6 +76,7 @@ import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionManager;
import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.dispatcher.ItemResolver;
import java.util.Date;

View File

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

View File

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

View File

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

View File

@ -18,10 +18,9 @@
*/
package org.librecms.contentsection;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.util.UncheckedWrapperException;
import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryRepository;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.core.CoreConstants;
@ -51,7 +50,11 @@ import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.lifecycle.LifecycleDefinition;
import java.util.Optional;
import org.librecms.contentsection.privileges.TypePrivileges;
import org.librecms.dispatcher.ItemResolver;
import javax.enterprise.inject.Instance;
import static org.librecms.contentsection.ContentSection.*;
@ -84,6 +87,9 @@ public class ContentSectionManager {
@Inject
private ConfigurationManager confManager;
@Inject
private Instance<ItemResolver> itemResolvers;
/**
* Creates a new content section including the default roles. This operation
* requries {@code admin} privileges.
@ -448,11 +454,19 @@ public class ContentSectionManager {
final Class<ItemResolver> itemResolverClazz
= (Class<ItemResolver>) Class.
forName(section.getItemResolverClass());
return itemResolverClazz.newInstance();
} catch (ClassNotFoundException
| IllegalAccessException
| InstantiationException ex) {
throw new RuntimeException(ex);
final Instance<ItemResolver> instance = itemResolvers.select(
itemResolverClazz);
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.cms.dispatcher.CMSPage;
import com.arsdigita.cms.dispatcher.ContentItemDispatcher;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.ui.CMSApplicationPage;
import com.arsdigita.dispatcher.AccessDeniedException;
import com.arsdigita.dispatcher.DispatcherHelper;
@ -30,7 +29,6 @@ import com.arsdigita.templating.PresentationManager;
import com.arsdigita.templating.Templating;
import com.arsdigita.util.Assert;
import com.arsdigita.util.Classes;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.ApplicationFileResolver;
import com.arsdigita.web.BaseApplicationServlet;
import com.arsdigita.web.LoginSignal;
@ -39,7 +37,6 @@ import com.arsdigita.web.WebConfig;
import com.arsdigita.xml.Document;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -59,10 +56,12 @@ import org.libreccm.security.Shiro;
import org.libreccm.web.CcmApplication;
import org.librecms.CmsConstants;
import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.dispatcher.ItemResolver;
import org.librecms.lifecycle.Lifecycle;
import java.util.Date;
import javax.inject.Inject;
import javax.servlet.RequestDispatcher;
/*
@ -136,8 +135,8 @@ public class ContentSectionServlet extends BaseApplicationServlet {
= "com.arsdigita.cms.dispatcher.section";
private final ContentItemDispatcher m_disp = new ContentItemDispatcher();
private static Map<String, ItemResolver> itemResolverCache = Collections
.synchronizedMap(new HashMap<>());
// private static Map<String, ItemResolver> itemResolverCache = Collections
// .synchronizedMap(new HashMap<>());
private static Map s_itemURLCacheMap = null;
/**
* Whether to cache the content items
@ -161,6 +160,9 @@ public class ContentSectionServlet extends BaseApplicationServlet {
*/
private ApplicationFileResolver m_resolver;
@Inject
private ContentSectionManager sectionManager;
/**
* Init method overwrites parents init to pass in optional parameters
* {@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);
}
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")
public ItemResolver getItemResolver(final ContentSection section) {
final String path = section.getPrimaryUrl();
final ItemResolver itemResolver;
if (itemResolverCache.containsKey(path)) {
itemResolver = itemResolverCache.get(path);
} else {
final String className = section.getItemResolverClass();
final Class<ItemResolver> clazz;
try {
clazz = (Class<ItemResolver>) Class.forName(className);
itemResolver = clazz.newInstance();
} catch (ClassNotFoundException
| IllegalAccessException
| InstantiationException ex) {
throw new UncheckedWrapperException(ex);
}
itemResolverCache.put(path, itemResolver);
}
LOGGER.debug("Using ItemResolver implementation \"{}\"...",
itemResolver.getClass().getName());
return itemResolver;
return sectionManager.getItemResolver(section);
}
public ContentItem getItem(final ContentSection section,

View File

@ -18,8 +18,6 @@
*/
package org.librecms.contentsection;
import com.arsdigita.cms.dispatcher.MultilingualItemResolver;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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.AssetPrivileges;
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
* 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.
* 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
@ -13,52 +13,58 @@
*
* 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
*
* 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.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.kernel.KernelConfig;
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.libreccm.cdi.utils.CdiUtil;
import org.apache.logging.log4j.Logger;
import org.libreccm.core.CcmObject;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentItemVersion;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.Folder;
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.Objects;
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.
*
* 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>
* 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
@ -73,13 +79,12 @@ import static javax.naming.ldap.SortControl.*;
* @author <a href="mailto:mhanisch@redhat.com">Michael Hanisch</a>
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class MultilingualItemResolver
extends AbstractItemResolver implements ItemResolver {
@RequestScoped
public class MultilingualItemResolver implements ItemResolver {
private static final Logger LOGGER = LogManager.getLogger(
MultilingualItemResolver.class);
private static MasterPage s_masterP = null;
private static final String ADMIN_PREFIX = "admin";
/**
@ -92,9 +97,17 @@ public class MultilingualItemResolver
*/
protected static final String SEPARATOR = "&";
public MultilingualItemResolver() {
LOGGER.debug("Undergoing creation");
}
@Inject
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.
@ -108,25 +121,32 @@ public class MultilingualItemResolver
*
* @return The content item, or null if no such item exists
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public ContentItem getItem(final ContentSection section,
final String itemUrl,
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 "
+ "\"{}\" for context \"{}\"...",
section.getLabel(),
itemUrl,
context);
Assert.exists(section, "ContentSection section");
Assert.exists(itemUrl, "String url");
Assert.exists(context, "String context");
final Folder rootFolder = section.getRootDocumentsFolder();
String url = stripTemplateFromURL(itemUrl);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
if (rootFolder == null) {
// nothing to do, if root folder is null
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");
final FolderManager folderManager = cdiUtil.findBean(
FolderManager.class);
final String prefix = String.join(
"",
section.getPrimaryUrl(),
@ -229,6 +247,7 @@ public class MultilingualItemResolver
*
* ToDo: Refactor to use the {@link ContentItemVersion} directly.
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String getCurrentContext(final PageState state) {
LOGGER.debug("Getting the current context");
@ -276,6 +295,7 @@ public class MultilingualItemResolver
*
* @see #getCurrentContext
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String generateItemURL(final PageState state,
final Long itemId,
@ -299,6 +319,7 @@ public class MultilingualItemResolver
*
* @see #getCurrentContext
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String generateItemURL(final PageState state,
final Long itemId,
@ -306,20 +327,25 @@ public class MultilingualItemResolver
final ContentSection section,
final String context,
final String templateContext) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Generating an item URL for item id " + itemId
+ ", section " + section + ", and context '"
+ context
+ "' with name '" + name + "'");
if (itemId == null) {
throw new IllegalArgumentException(
"Can't generate item URL for item id null.");
}
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");
Assert.exists(context, "String context");
Assert.exists(section, "ContentSection section");
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
LOGGER.debug("Generating an item URL for item id {}, section \"{}\" "
+ "and context \"{}\" with name \"{}\"...",
itemId,
section.getLabel(),
context,
name);
if (ContentItemVersion.DRAFT.toString().equals(context)) {
// No template context here.
@ -349,6 +375,7 @@ public class MultilingualItemResolver
*
* @see #getCurrentContext
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String generateItemURL(final PageState state,
final ContentItem item,
@ -370,16 +397,20 @@ public class MultilingualItemResolver
*
* @see #getCurrentContext
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String generateItemURL(final PageState state,
final ContentItem item,
final ContentSection section,
final String context,
final String templateContext) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Generating an item URL for item " + item
+ ", section "
+ section + ", and context " + context);
if (item == null) {
throw new IllegalArgumentException(
"Can't generate URL for item null.");
}
if (context == null) {
throw new IllegalArgumentException(
"Can't generate URL for context null.");
}
final ContentSection contentSection;
@ -389,6 +420,12 @@ public class MultilingualItemResolver
contentSection = section;
}
LOGGER.debug("Generating an item URL for item \"{}\", section \"{}\" "
+ "and context \"{}\".",
item.getDisplayName(),
contentSection.getLabel(),
context);
if (ContentItemVersion.DRAFT.toString().equals(context)) {
return generateDraftURL(section, item.getObjectId());
} else if (CMSDispatcher.PREVIEW.equals(context)) {
@ -401,35 +438,19 @@ public class MultilingualItemResolver
}
}
/**
* 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
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public CMSPage getMasterPage(final ContentItem item,
final HttpServletRequest request)
throws ServletException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Getting the master page for item " + item);
}
// taken from SimpleItemResolver
if (s_masterP == null) {
s_masterP = new MasterPage();
s_masterP.init();
}
LOGGER.debug("Getting the master page for item {}",
item.getDisplayName());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Returning master page " + s_masterP);
}
final MasterPage masterPage = new MasterPage();
masterPage.init();
return s_masterP;
return masterPage;
}
/**
@ -512,9 +533,6 @@ public class MultilingualItemResolver
.append("/");
}
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemManager itemManager = cdiUtil.findBean(
ContentItemManager.class);
url.append(itemManager.getItemPath(item));
return url.toString();
@ -561,9 +579,6 @@ public class MultilingualItemResolver
.append("/");
}
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemManager itemManager = cdiUtil.findBean(
ContentItemManager.class);
url.append(itemManager.getItemPath(item));
return url.toString();
@ -581,19 +596,10 @@ public class MultilingualItemResolver
* <code>url</code>
*/
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);
// 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=.... ?
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);
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);
}
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
LOGGER.debug("Looking up item using item ID {}", item_id);
final Optional<ContentItem> item = itemRepo.findById(Long.parseLong(
item_id));
@ -642,21 +642,20 @@ public class MultilingualItemResolver
*/
protected ContentItem getItemFromLiveURL(final String url,
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 (LOGGER.isDebugEnabled()) {
LOGGER.debug("The url is null or parent folder was null "
+ "or something else is wrong, so just return "
+ "null");
}
+ "null.");
return null;
}
LOGGER.debug("Resolving the item for live URL {}"
+ " and parent folder {}...",
url,
parentFolder.getName());
int len = url.length();
int index = url.indexOf('/');
@ -674,13 +673,11 @@ public class MultilingualItemResolver
final String[] nameAndLang = getNameAndLangFromURLFrag(url);
final String name = nameAndLang[0];
final Optional<CcmObject> item = parentFolder.getObjects().stream()
.map(categorization -> categorization.getCategorizedObject())
.filter(object -> object.getDisplayName().equals(name))
.findFirst();
final Optional<ContentItem> item = itemRepo.findByNameInFolder(
parentFolder, name);
if (item.isPresent() && item.get() instanceof ContentItem) {
return (ContentItem) item.get();
if (item.isPresent()) {
return item.get();
} else {
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
* 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.
* 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
@ -13,43 +13,46 @@
*
* 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
*
* 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.cms.CMS;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.Folder;
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.dispatcher.DispatcherHelper;
import com.arsdigita.web.URL;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.categorization.Category;
import org.libreccm.core.CcmObject;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentItemVersion;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.Folder;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
/**
* This is the default implementation of
* {@link com.arsdigita.cms.dispatcher.ItemResolver}.
*
* 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
* 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
@ -63,52 +66,63 @@ import javax.servlet.http.HttpServletRequest;
* request. With the content item and the master page in hand, the dispatcher
* 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>
* 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
* code other methods, for example from the {@link ContentItemManager} or
* the {@link ContentItemRepository} should be used. Because this class is no
* longer part of the public API the will might be removed or changed in future
* code other methods, for example from the {@link ContentItemManager} or the
* {@link ContentItemRepository} should be used. Because this class is no longer
* part of the public API the will might be removed or changed in future
* releases without prior warning.
* </strong>
*
* @author Michael Pih (pihman@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class SimpleItemResolver
extends AbstractItemResolver
implements ItemResolver {
@RequestScoped
public class SimpleItemResolver implements ItemResolver {
private static final Logger LOGGER = LogManager.getLogger(
SimpleItemResolver.class.getName());
SimpleItemResolver.class);
private static final String ADMIN_PREFIX = "admin";
private static final String WORKSPACE_PREFIX
= CmsConstants.CONTENT_CENTER_URL;
private static MasterPage masterPage = null;
@Inject
private ContentItemRepository itemRepo;
@Inject
private ContentItemManager itemManager;
public SimpleItemResolver() {
}
/**
* Return a content item based on page state (and content section).
*
* @param section The current content section
* @param url The section-relative URL
* @param context The LIVE/DRAFT context (*not* the template use context)
*
* @return The content item mapped to the content section and URL, or null
* if no such item exists
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public ContentItem getItem(final ContentSection section,
final String url,
final String context) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("trying to get " + context + " item for url " + url);
if (section == null) {
throw new IllegalArgumentException(
"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);
@ -120,27 +134,28 @@ public class SimpleItemResolver
ContentItem reqItem = (ContentItem) DispatcherHelper.getRequest().
getAttribute("com.arsdigita.cms.dispatcher.item");
if (reqItem != null) {
LOGGER.info("found item in the request, returning it");
LOGGER.info("Found item in the request, returning it.");
return reqItem;
}
final Folder rootFolder = section.getRootDocumentsFolder();
if (rootFolder == null) {
LOGGER.info("no root folder found, returning null");
LOGGER.info("No root folder found, returning null.");
return null;
}
return getItem(itemUrl, rootFolder);
}
/**
* @param state the current page state
*
* @return the context of the current URL, such as "live" or "admin"
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
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();
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
* exists. The path is interpreted as a series of folders; for example,
* "/foo/bar/baz" will look for an item named "baz" in a folder named "bar"
* in a folder named "foo" under the specified root folder.
* exists.
*
* 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 rootFolder The root folder where the item search will start
*
* @return the item on success, null if no such item exists
*/
@Transactional(Transactional.TxType.REQUIRED)
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("/");
Folder currentFolder = rootFolder;
@ -227,6 +254,15 @@ public class SimpleItemResolver
*/
private String generateDraftURL(final Long itemId,
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(
String.format("%s%s/",
URL.getDispatcherPath(),
@ -250,6 +286,15 @@ public class SimpleItemResolver
final ContentSection section,
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;
if (templateContext == null || templateContext.isEmpty()) {
templateUrlFrag = "";
@ -258,10 +303,6 @@ public class SimpleItemResolver
templateContext);
}
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemManager itemManager = cdiUtil.findBean(
ContentItemManager.class);
return String.format("%s/%s%s",
section.getPrimaryUrl(),
templateUrlFrag,
@ -280,6 +321,15 @@ public class SimpleItemResolver
private String generatePreviewURL(final ContentItem item,
final ContentSection section,
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;
if (templateContext == null || templateContext.isEmpty()) {
templateUrlFrag = "";
@ -287,9 +337,6 @@ public class SimpleItemResolver
templateUrlFrag = String.format(TEMPLATE_CONTEXT_PREFIX + "%s/",
templateContext);
}
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemManager itemManager = cdiUtil.findBean(
ContentItemManager.class);
final StringBuilder url = new StringBuilder();
url
@ -314,6 +361,7 @@ public class SimpleItemResolver
*
* @return The URL of the item
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String generateItemURL(final PageState state,
final Long itemId,
@ -335,6 +383,7 @@ public class SimpleItemResolver
*
* @return The URL of the item
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String generateItemURL(final PageState state,
final Long itemId,
@ -342,9 +391,6 @@ public class SimpleItemResolver
final ContentSection section,
final String context,
final String templateContext) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
if (ContentItemVersion.DRAFT.toString().equals(context)) {
return generateDraftURL(itemId, section);
@ -372,6 +418,7 @@ public class SimpleItemResolver
*
* @see #getCurrentContext
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String generateItemURL(final PageState state,
final ContentItem item,
@ -393,6 +440,7 @@ public class SimpleItemResolver
*
* @see #getCurrentContext
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String generateItemURL(final PageState state,
final ContentItem item,
@ -412,23 +460,14 @@ public class SimpleItemResolver
}
}
/**
* 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
*/
@Transactional(Transactional.TxType.REQUIRED)
@Override
public CMSPage getMasterPage(final ContentItem item,
final HttpServletRequest request)
throws ServletException {
if (masterPage == null) {
masterPage = new MasterPage();
final MasterPage masterPage = new MasterPage();
masterPage.init();
}
return masterPage;
}

View File

@ -1,17 +1,18 @@
<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="org.librecms.ContentSection"/>
<jsp:directive.page import="org.librecms.ContentSectionServlet"/>
<jsp:directive.page import="org.librecms.contentsection.ContentSection"/>
<jsp:directive.page import="org.librecms.contentsection.ContentSectionServlet"/>
<jsp:directive.page import="com.arsdigita.cms.dispatcher.Utilities"/>
<jsp:directive.page import="com.arsdigita.dispatcher.*"/>
<jsp:directive.page import="com.arsdigita.web.LoginSignal"/>
<jsp:directive.page import="com.arsdigita.web.Web"/>
<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>
private ContentSectionPage sectionPage = new ContentSectionPage();
// private HttpServletRequest myRequest = DispatcherHelper.getRequest();
</jsp:declaration>
<jsp:scriptlet>
@ -21,13 +22,13 @@
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);
} else if (! ContentSectionServlet.checkAdminAccess(myRequest, section)) {
throw new com.arsdigita.cms.dispatcher.AccessDeniedException();
throw new com.arsdigita.dispatcher.AccessDeniedException();
}
RequestContext context = DispatcherHelper.getRequestContext(myRequest);
sectionPage.init();
sectionPage.dispatch(myRequest, response, context);

View File

@ -141,7 +141,7 @@ public class AssetManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass(
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.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage())

View File

@ -136,7 +136,7 @@ public class AssetRepositoryTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass(
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.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage())

View File

@ -132,7 +132,7 @@ public class AttachmentListManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass(
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.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage())

View File

@ -134,7 +134,7 @@ public class ContentItemL10NManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass(
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.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage())

View File

@ -154,7 +154,7 @@ public class ContentItemManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass(
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.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage())

View File

@ -136,8 +136,8 @@ public class ContentItemPermissionTest {
addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class).
addClass(
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class).
addClass(com.arsdigita.cms.dispatcher.ItemResolver.class)
com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class)
.addClass(org.librecms.dispatcher.ItemResolver.class)
.addClass(org.libreccm.portation.Portable.class)
.addPackage(com.arsdigita.util.Lockable.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)
.addClass(
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.web.BaseServlet.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.RequiredModule.class)
.addClass(org.libreccm.portation.Marshals.class)
.addPackage(com.arsdigita.cms.dispatcher.ItemResolver.class.
getPackage())
.addPackage(org.librecms.dispatcher.ItemResolver.class.getPackage())
.addPackage(com.arsdigita.util.Lockable.class.getPackage())
.addPackage(com.arsdigita.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage())

View File

@ -133,7 +133,7 @@ public class ContentTypeRepositoryTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass(
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.web.BaseServlet.class.getPackage())
.addPackage(org.librecms.Cms.class.getPackage())

View File

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

View File

@ -139,7 +139,7 @@ public class ItemAttachmentManagerTest {
com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class)
.addClass(
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.web.BaseServlet.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)) {
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("?");