diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/AbstractItemResolver.java b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/AbstractItemResolver.java deleted file mode 100755 index 557b313f3..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/AbstractItemResolver.java +++ /dev/null @@ -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 inUrl. - * - * @param inUrl URL, possibly including the template context. - * - * @return inUrl 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; - } - } - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSDispatcher.java b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSDispatcher.java index c2bb8a271..d050b44fa 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSDispatcher.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSDispatcher.java @@ -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; /** *

@@ -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(); - try { - itemResolver = (ItemResolver) Class.forName( - itemResolverClassName).newInstance(); - } catch (ClassNotFoundException | - IllegalAccessException | - InstantiationException ex) { - throw new RuntimeException(ex); - } - s_itemResolverCache.put(name, itemResolver); + + final Class clazz; + try { + clazz = Class.forName(section.getItemResolverClass()); + } catch(ClassNotFoundException ex) { + throw new UncheckedWrapperException(ex); } - return itemResolver; + + return (ItemResolver) CdiUtil.createCdiUtil().findBean(clazz); + } /** diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentPanel.java b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentPanel.java index 3704fd3ed..920538f65 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentPanel.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ContentPanel.java @@ -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(); diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemDispatcher.java b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemDispatcher.java index 5b7959e3b..23eec1e50 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemDispatcher.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemDispatcher.java @@ -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; // } - } diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemResolver.java b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemResolver.java deleted file mode 100755 index 2c77b5a8a..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/ItemResolver.java +++ /dev/null @@ -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; - - -/** - *

- * The 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 - * http://yourserver/cms/cheese:

- * - *

- * The item resolver would be asked to map the URL stub /cheese - * in the content section mounted at /cms to a content item. To this - * end, the dispatcher calls the getItem method, passing in the - * {@link com.arsdigita.cms.ContentSection} and the URL stub for the item within - * the section, /cheese in our example. As a final argument, the - * dispatcher passes either ContentItem.DRAFT or - * ContentItem.LIVE to the ItemResolver, depending on whether - * the returned item should be the live version (for public pages) or the draft - * version (for previewing).

- * - * @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 inUrl. - * - * @param inUrl URL, possibly including the template context. - * @return inUrl with the template context removed - */ - public String stripTemplateFromURL(String inUrl); - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java index 5755de924..5229877fd 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentItemPage.java @@ -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; @@ -93,7 +94,7 @@ public class ContentItemPage extends CMSPage implements ActionListener { * Private Logger instance for debugging purpose. */ private static final Logger LOGGER = LogManager.getLogger( - ContentItemPage.class); + ContentItemPage.class); /** * The URL parameter that must be passed in in order to set the current tab. * This is a KLUDGE right now because the TabbedDialog's current tab is @@ -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 { @@ -172,10 +174,11 @@ public class ContentItemPage extends CMSPage implements ActionListener { public final void prepare(final PrintEvent event) { final Label label = (Label) event.getTarget(); final ContentItem item = itemRequestLocal.getContentItem(event. - getPageState()); + getPageState()); label.setLabel(item.getDisplayName()); } + } /** @@ -197,12 +200,12 @@ public class ContentItemPage extends CMSPage implements ActionListener { // Add the selected item language as parameter final StringParameter selectedLanguage = new StringParameter( - SELECTED_LANGUAGE); + SELECTED_LANGUAGE); selectedLanguage.addParameterListener(new NotNullValidationListener( - SELECTED_LANGUAGE)); + SELECTED_LANGUAGE)); addGlobalStateParam(selectedLanguage); selectedLanguageModel = new ParameterSingleSelectionModel<>( - selectedLanguage); + selectedLanguage); // Add the content type global state parameter final LongParameter contentType = new LongParameter(CONTENT_TYPE); @@ -210,7 +213,7 @@ public class ContentItemPage extends CMSPage implements ActionListener { // Add the streamlined creation global state parameter final StringParameter streamlinedCreation = new StringParameter( - STREAMLINED_CREATION); + STREAMLINED_CREATION); addGlobalStateParam(streamlinedCreation); typeModel = new ACSObjectSelectionModel(ContentType.class.getName(), @@ -219,7 +222,7 @@ public class ContentItemPage extends CMSPage implements ActionListener { // Validate the item ID parameter (caches the validation). getStateModel().addValidationListener( - event -> validateItemID(event.getPageState())); + event -> validateItemID(event.getPageState())); // Add the return url global state parameter returnUrlParameter = new StringParameter(RETURN_URL); @@ -248,7 +251,7 @@ public class ContentItemPage extends CMSPage implements ActionListener { tabbedPane.addTab(new Label(gz("cms.ui.item.summary")), summaryPane); tabbedPane. - addTab(new Label(gz("cms.ui.item.authoring")), wizardPane); + addTab(new Label(gz("cms.ui.item.authoring")), wizardPane); tabbedPane.addTab(new Label(gz("cms.ui.item.languages")), languagesPane); tabbedPane.addTab(new Label(gz("cms.ui.item.workflow")), @@ -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,19 +275,23 @@ 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) { - final Link link = (Link) event.getTarget(); - link.setTarget(getPreviewURL(event. + + @Override + public final void prepare( + final PrintEvent event) { + final Link link = (Link) event.getTarget(); + link.setTarget(getPreviewURL(event. getPageState())); - link.setTargetFrame(Link.NEW_FRAME); - } - }); + link.setTargetFrame(Link.NEW_FRAME); + } + + }); m_previewLink.setIdAttr("preview_link"); add(m_previewLink); @@ -294,21 +302,22 @@ public class ContentItemPage extends CMSPage implements ActionListener { @Override public void validate(final FormSectionEvent event) - throws FormProcessException { + throws FormProcessException { PageState s = event.getPageState(); FormData data = event.getFormData(); final ContentItem item = itemRequestLocal.getContentItem(s); if (item != null - && ContentItemVersion.LIVE == item.getVersion()) { + && ContentItemVersion.LIVE == item.getVersion()) { LOGGER.error(String.format( - "The item %d is live and cannot be edited.", item. - getObjectId())); + "The item %d is live and cannot be edited.", item. + getObjectId())); throw new FormProcessException(new GlobalizedMessage( - "cms.ui.live_item_not_editable", - CmsConstants.CMS_BUNDLE)); + "cms.ui.live_item_not_editable", + CmsConstants.CMS_BUNDLE)); } } + }); } @@ -317,16 +326,17 @@ 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 */ protected void validateItemID(final PageState state) throws - FormProcessException { + FormProcessException { final ContentItem item = itemRequestLocal.getContentItem(state); if (item == null) { throw new FormProcessException(new GlobalizedMessage( - "cms.ui.invalid_item_id", CmsConstants.CMS_BUNDLE)); + "cms.ui.invalid_item_id", CmsConstants.CMS_BUNDLE)); } } @@ -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 @@ -406,8 +419,9 @@ public class ContentItemPage extends CMSPage implements ActionListener { * Construct a URL for displaying a certain item * * @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 + * @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, @@ -419,10 +433,11 @@ public class ContentItemPage extends CMSPage implements ActionListener { /** * Construct a URL for displaying a certain item * - * @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 + * @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 * @param streamlinedCreation Whether to activate Streamlined item authoring + * * @return */ public static String getItemURL(final String nodeURL, @@ -432,25 +447,25 @@ public class ContentItemPage extends CMSPage implements ActionListener { final StringBuilder urlBuilder = new StringBuilder(); urlBuilder - .append(nodeURL) - .append(PageLocations.ITEM_PAGE) - .append("?") - .append(ITEM_ID) - .append("=") - .append(itemId.toString()) - .append("&") - .append(SET_TAB) - .append("=") - .append(tab); + .append(nodeURL) + .append(PageLocations.ITEM_PAGE) + .append("?") + .append(ITEM_ID) + .append("=") + .append(itemId.toString()) + .append("&") + .append(SET_TAB) + .append("=") + .append(tab); if (streamlinedCreation - && CMSConfig.getConfig().isUseStreamlinedCreation()) { + && CMSConfig.getConfig().isUseStreamlinedCreation()) { urlBuilder - .append("&") - .append(STREAMLINED_CREATION) - .append("=") - .append(STREAMLINED_CREATION_ACTIVE); + .append("&") + .append(STREAMLINED_CREATION) + .append("=") + .append(STREAMLINED_CREATION_ACTIVE); } return urlBuilder.toString(); @@ -459,21 +474,23 @@ 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) { final StringBuilder url = new StringBuilder(); url - .append(PageLocations.ITEM_PAGE) - .append("?") - .append(ITEM_ID) - .append("=") - .append(itemId.toString()) - .append("&") - .append(SET_TAB) - .append("=") - .append(tab); + .append(PageLocations.ITEM_PAGE) + .append("?") + .append(ITEM_ID) + .append("=") + .append(itemId.toString()) + .append("&") + .append(SET_TAB) + .append("=") + .append(tab); return url.toString(); } @@ -482,7 +499,8 @@ public class ContentItemPage extends CMSPage implements ActionListener { * Constructs a URL for displaying a certain item. * * @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 */ public static String getItemURL(final ContentItem item, @@ -502,14 +520,15 @@ public class ContentItemPage extends CMSPage implements ActionListener { * Constructs a URL for displaying a certain item. * * @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 */ public static String getItemURL(final long itemId, final int tab) { final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final ContentItemRepository itemRepo = cdiUtil.findBean( - ContentItemRepository.class); + ContentItemRepository.class); final Optional item = itemRepo.findById(itemId); @@ -544,8 +563,8 @@ public class ContentItemPage extends CMSPage implements ActionListener { if (item instanceof CustomizedPreviewLink) { final String previewLink = ((CustomizedPreviewLink) item). - getPreviewUrl( - state); + getPreviewUrl( + state); if ((previewLink == null) || previewLink.isEmpty()) { return getDefaultPreviewLink(state, item); } else { @@ -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, @@ -593,8 +608,8 @@ public class ContentItemPage extends CMSPage implements ActionListener { public static boolean isStreamlinedCreationActive(final PageState state) { return CMSConfig.getConfig().isUseStreamlinedCreation() - && STREAMLINED_CREATION_ACTIVE.equals(state.getRequest(). - getParameter(STREAMLINED_CREATION)); + && STREAMLINED_CREATION_ACTIVE.equals(state.getRequest(). + getParameter(STREAMLINED_CREATION)); } protected TabbedPane getTabbedPane() { @@ -608,8 +623,9 @@ public class ContentItemPage extends CMSPage implements ActionListener { /** * Adds the content type to the output. * - * @param state PageState + * @param state PageState * @param parent Parent document + * * @return page */ @Override @@ -618,12 +634,13 @@ public class ContentItemPage extends CMSPage implements ActionListener { final Element page = super.generateXMLHelper(state, parent); final Element contenttype = page.newChildElement("bebop:contentType", BEBOP_XML_NS); - + contenttype.setText(itemRequestLocal - .getContentItem(state) - .getContentType() - .getLabel().getValue(KernelConfig.getConfig().getDefaultLocale())); + .getContentItem(state) + .getContentType() + .getLabel().getValue(KernelConfig.getConfig().getDefaultLocale())); return page; } + } diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowser.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowser.java index c11f8ae71..e73104fc5 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowser.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowser.java @@ -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; diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/Summary.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/Summary.java index c504b3dbc..31493af89 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/Summary.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/item/Summary.java @@ -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; diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java index 60319cac8..27148b839 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/revision/ItemRevisionAdminPane.java @@ -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; diff --git a/ccm-cms/src/main/java/org/arsdigita/cms/CMSConfig.java b/ccm-cms/src/main/java/org/arsdigita/cms/CMSConfig.java index e4d28b078..bbdccdffe 100644 --- a/ccm-cms/src/main/java/org/arsdigita/cms/CMSConfig.java +++ b/ccm-cms/src/main/java/org/arsdigita/cms/CMSConfig.java @@ -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 defaultItemResolverClassNames = Arrays.asList( new String[]{ - ItemResolver.class.getName() + SimpleItemResolver.class.getName() }); // @Setting diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionManager.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionManager.java index c16d77315..0c5608617 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionManager.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionManager.java @@ -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.*; @@ -83,6 +86,9 @@ public class ContentSectionManager { @Inject private ConfigurationManager confManager; + + @Inject + private Instance itemResolvers; /** * Creates a new content section including the default roles. This operation @@ -448,11 +454,19 @@ public class ContentSectionManager { final Class itemResolverClazz = (Class) Class. forName(section.getItemResolverClass()); - return itemResolverClazz.newInstance(); - } catch (ClassNotFoundException - | IllegalAccessException - | InstantiationException ex) { - throw new RuntimeException(ex); + + final Instance 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); } } diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionServlet.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionServlet.java index 3896b86c4..c00205eae 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionServlet.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionServlet.java @@ -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 itemResolverCache = Collections - .synchronizedMap(new HashMap<>()); +// private static Map 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 @@ -320,8 +322,8 @@ public class ContentSectionServlet extends BaseApplicationServlet { request.setAttribute(CONTENT_SECTION, section); RequestDispatcher rd = m_resolver.resolve(m_templatePath, - request, - response, + request, + response, app); if (rd != null) { if (LOGGER.isDebugEnabled()) { @@ -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 clazz; - try { - clazz = (Class) Class.forName(className); - itemResolver = clazz.newInstance(); - } catch (ClassNotFoundException - | IllegalAccessException - | InstantiationException ex) { - throw new UncheckedWrapperException(ex); - } - - itemResolverCache.put(path, itemResolver); - } - - LOGGER.debug("Using ItemResolver implementation \"{}\"...", - itemResolver.getClass().getName()); - - return itemResolver; + return sectionManager.getItemResolver(section); } public ContentItem getItem(final ContentSection section, diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionSetup.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionSetup.java index fdf0bb751..09112f58a 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionSetup.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSectionSetup.java @@ -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; /** * diff --git a/ccm-cms/src/main/java/org/librecms/dispatcher/ItemResolver.java b/ccm-cms/src/main/java/org/librecms/dispatcher/ItemResolver.java new file mode 100644 index 000000000..e27c994c5 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/dispatcher/ItemResolver.java @@ -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 Jens Pelzetter + * @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 inUrl. + * + * @param inUrl URL, possibly including the template context. + * + * @return inUrl 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; + } + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java b/ccm-cms/src/main/java/org/librecms/dispatcher/MultilingualItemResolver.java old mode 100755 new mode 100644 similarity index 84% rename from ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java rename to ccm-cms/src/main/java/org/librecms/dispatcher/MultilingualItemResolver.java index ea70c4b2d..bac2fb103 --- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/MultilingualItemResolver.java +++ b/ccm-cms/src/main/java/org/librecms/dispatcher/MultilingualItemResolver.java @@ -1,64 +1,70 @@ /* - * 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 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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 - * + * 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}. + * * * 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 Michael Hanisch * @author Jens Pelzetter */ -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 * 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); - // 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 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"); - } + LOGGER.debug("The url is null or parent folder was null " + + "or something else is wrong, so just return " + + "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 item = parentFolder.getObjects().stream() - .map(categorization -> categorization.getCategorizedObject()) - .filter(object -> object.getDisplayName().equals(name)) - .findFirst(); + final Optional 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; } @@ -786,8 +783,8 @@ public class MultilingualItemResolver /** * Finds a language instance of a content item given the bundle, name, and - * lang string. Note: Because there not ContentBundles anymore this method - * simply returns the provided item. + * lang string. Note: Because there not ContentBundles anymore this method + * simply returns the provided item. * * @param lang The lang string from the URL * @param item The content bundle diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/SimpleItemResolver.java b/ccm-cms/src/main/java/org/librecms/dispatcher/SimpleItemResolver.java old mode 100755 new mode 100644 similarity index 75% rename from ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/SimpleItemResolver.java rename to ccm-cms/src/main/java/org/librecms/dispatcher/SimpleItemResolver.java index 2ce01c379..4fa0bc732 --- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/SimpleItemResolver.java +++ b/ccm-cms/src/main/java/org/librecms/dispatcher/SimpleItemResolver.java @@ -1,55 +1,58 @@ /* - * 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 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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 - * + * 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 @@ -62,53 +65,64 @@ import javax.servlet.http.HttpServletRequest; * {@link com.arsdigita.cms.dispatcher.MasterPage} for that item in the current * request. With the content item and the master page in hand, the dispatcher * calls {@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}. + * * * 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. * * * @author Michael Pih (pihman@arsdigita.com) * @author Jens Pelzetter */ -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(); - masterPage.init(); - } + final MasterPage masterPage = new MasterPage(); + masterPage.init(); return masterPage; } diff --git a/ccm-cms/src/main/resources/templates/ccm-cms/content-section/admin/index.jsp b/ccm-cms/src/main/resources/templates/ccm-cms/content-section/admin/index.jsp index c12d4ba89..530ca77bc 100644 --- a/ccm-cms/src/main/resources/templates/ccm-cms/content-section/admin/index.jsp +++ b/ccm-cms/src/main/resources/templates/ccm-cms/content-section/admin/index.jsp @@ -1,17 +1,18 @@ - - + + + + private ContentSectionPage sectionPage = new ContentSectionPage(); - // private HttpServletRequest myRequest = DispatcherHelper.getRequest(); @@ -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); diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/AssetManagerTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/AssetManagerTest.java index 3f7154846..04a7b4af1 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/AssetManagerTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/AssetManagerTest.java @@ -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()) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/AssetRepositoryTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/AssetRepositoryTest.java index 23df66733..c3d237668 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/AssetRepositoryTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/AssetRepositoryTest.java @@ -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()) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/AttachmentListManagerTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/AttachmentListManagerTest.java index d840e24d2..8393bfce6 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/AttachmentListManagerTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/AttachmentListManagerTest.java @@ -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()) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemL10NManagerTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemL10NManagerTest.java index 8064a6379..1215e5046 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemL10NManagerTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemL10NManagerTest.java @@ -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()) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemManagerTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemManagerTest.java index 61ddbd60f..8cafaef36 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemManagerTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemManagerTest.java @@ -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()) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemPermissionTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemPermissionTest.java index 8787acd17..6fec808ac 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemPermissionTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemPermissionTest.java @@ -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()) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemRepositoryTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemRepositoryTest.java index 66686aa65..f52e1459c 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemRepositoryTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemRepositoryTest.java @@ -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()) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/ContentSectionManagerTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/ContentSectionManagerTest.java index 5c56ed6fe..cfe281a27 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/ContentSectionManagerTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/ContentSectionManagerTest.java @@ -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()) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/ContentTypeRepositoryTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/ContentTypeRepositoryTest.java index 7e7f3ca83..e9ce3df09 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/ContentTypeRepositoryTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/ContentTypeRepositoryTest.java @@ -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()) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/FolderManagerTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/FolderManagerTest.java index eab7dc00c..2883e92c0 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/FolderManagerTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/FolderManagerTest.java @@ -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()) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/ItemAttachmentManagerTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/ItemAttachmentManagerTest.java index 9c14a044d..b9bcf279d 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/ItemAttachmentManagerTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/ItemAttachmentManagerTest.java @@ -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()) diff --git a/ccm-core/src/main/java/com/arsdigita/web/CCMDispatcherServlet.java b/ccm-core/src/main/java/com/arsdigita/web/CCMDispatcherServlet.java index 26033a4b4..2dc7ed979 100644 --- a/ccm-core/src/main/java/com/arsdigita/web/CCMDispatcherServlet.java +++ b/ccm-core/src/main/java/com/arsdigita/web/CCMDispatcherServlet.java @@ -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("?");