From e9da0a7fceb801b990ec8a1a83efe15bbd698d6c Mon Sep 17 00:00:00 2001 From: jensp Date: Fri, 25 Aug 2017 13:15:54 +0000 Subject: [PATCH] Redirect to URL with language extension for content item view git-svn-id: https://svn.libreccm.org/ccm/trunk@4919 8810af33-2d31-482b-a856-94f89814c4df --- .../arsdigita/cms/ContentSectionServlet.java | 305 ++++++++++++------ .../navigation/PublicationList.java | 2 +- 2 files changed, 202 insertions(+), 105 deletions(-) diff --git a/ccm-cms/src/com/arsdigita/cms/ContentSectionServlet.java b/ccm-cms/src/com/arsdigita/cms/ContentSectionServlet.java index 9007b7e08..37d496b94 100755 --- a/ccm-cms/src/com/arsdigita/cms/ContentSectionServlet.java +++ b/ccm-cms/src/com/arsdigita/cms/ContentSectionServlet.java @@ -69,7 +69,8 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; /* * NOTE: @@ -79,7 +80,7 @@ import org.apache.log4j.Logger; * is CACHE_KEY_DELIMITER. */ -/* + /* * NOTE 2: * In a process of refactoring from legacy compatible to legacy free applications. * TODO: @@ -88,75 +89,92 @@ import org.apache.log4j.Logger; * - Refactor content item UI bebop ApplicationPage or PageFactory instead of * legacy infected sitenode / package dispatchers. */ - /** * Content Section's Application Servlet according CCM core web application - * structure {@see com.arsdigita.web.Application} implements the content - * section UI. - * + * structure { + * + * @see com.arsdigita.web.Application} implements the content section UI. + * * It handles the UI for content items and delegates the UI for sections and * folders to jsp templates. - * + * * @author unknown * @author Sören Bernstein * @author Peter Boy */ public class ContentSectionServlet extends BaseApplicationServlet { - /** Internal logger instance to faciliate debugging. Enable logging output - * by editing /WEB-INF/conf/log4j.properties int hte runtime environment - * and set com.arsdigita.cms.ContentSectionServlet=DEBUG - * by uncommenting or adding the line. */ - private static final Logger s_log = - Logger.getLogger(ContentSectionServlet.class); - /** Stringarray of file name patterns for index files. */ + /** + * Internal logger instance to faciliate debugging. Enable logging output by + * editing /WEB-INF/conf/log4j.properties int hte runtime environment and + * set com.arsdigita.cms.ContentSectionServlet=DEBUG by uncommenting or + * adding the line. + */ + private static final Logger s_log = LogManager.getLogger( + ContentSectionServlet.class); + /** + * Stringarray of file name patterns for index files. + */ // private static final String[] WELCOME_FILES = new String[]{ // "index.jsp", "index.html" // }; // Some literals - - /** Literal for the prefix (in url) for previewing items */ + /** + * Literal for the prefix (in url) for previewing items + */ public static final String PREVIEW = "/preview"; - /** Literal Template files suffix */ + /** + * Literal Template files suffix + */ public static final String FILE_SUFFIX = ".jsp"; - /** Literal of URL Stub for index file name (includes leading slash) */ + /** + * Literal of URL Stub for index file name (includes leading slash) + */ public static final String INDEX_FILE = "/index"; public static final String XML_SUFFIX = ".xml"; public static final String XML_MODE = "xmlMode"; public static final String MEDIA_TYPE = "templateContext"; private static final String CACHE_KEY_DELIMITER = "%"; - public static final String CONTENT_ITEM = - "com.arsdigita.cms.dispatcher.item"; - public static final String CONTENT_SECTION = - "com.arsdigita.cms.dispatcher.section"; + public static final String CONTENT_ITEM + = "com.arsdigita.cms.dispatcher.item"; + public static final String CONTENT_SECTION + = "com.arsdigita.cms.dispatcher.section"; private final ContentItemDispatcher m_disp = new ContentItemDispatcher(); public static Map s_itemResolverCache = Collections - .synchronizedMap(new HashMap()); + .synchronizedMap(new HashMap()); private static Map s_itemURLCacheMap = null; - /** Whether to cache the content items */ + /** + * Whether to cache the content items + */ private static final boolean s_cacheItems = true; // NEW STUFF here used to process the pages in this servlet - /** URL (pathinfo) -> Page object mapping. Based on it (and the http - * request url) the doService method selects a page to display */ + /** + * URL (pathinfo) -> Page object mapping. Based on it (and the http request + * url) the doService method selects a page to display + */ private final Map m_pages = new HashMap(); - /** Path to directory containg ccm-cms template (jsp) files */ + /** + * Path to directory containg ccm-cms template (jsp) files + */ private String m_templatePath; - /** Resolver to actually use to find templates (JSP). JSP may be stored in - * file system or otherwise, depends on resolver. Resolver is retrieved - * from configuration. - * (probably used for other stuff as JSP's as well) */ + /** + * Resolver to actually use to find templates (JSP). JSP may be stored in + * file system or otherwise, depends on resolver. Resolver is retrieved from + * configuration. (probably used for other stuff as JSP's as well) + */ private ApplicationFileResolver m_resolver; - /** * Init method overwrites parents init to pass in optional parameters * {@link com.arsdigita.web.BaseServlet}. If not specified system wide * defaults are used. + * * @param config + * * @throws javax.servlet.ServletException */ @Override @@ -179,17 +197,17 @@ public class ContentSectionServlet extends BaseApplicationServlet { Assert.isTrue(!m_templatePath.endsWith("/"), "template-path must not end with '/'"); - // optional init-param named file-resolver from ~/WEB-INF/web.xml String resolverName = config.getInitParameter("file-resolver"); if (resolverName == null) { m_resolver = Web.getConfig().getApplicationFileResolver(); } else { - m_resolver = (ApplicationFileResolver) Classes.newInstance(resolverName); + m_resolver = (ApplicationFileResolver) Classes.newInstance( + resolverName); } if (s_log.isDebugEnabled()) { - s_log.debug("Template path is " + m_templatePath + - " with resolver " + m_resolver. + s_log.debug("Template path is " + m_templatePath + " with resolver " + + m_resolver. getClass().getName()); } @@ -198,15 +216,14 @@ public class ContentSectionServlet extends BaseApplicationServlet { // addPage("/admin", new MainPage()); // index page at address ~/cs // addPage("/admin/index.jsp", new MainPage()); // addPage("/admin/item.jsp", new MainPage()); - } /** - * Internal service method, adds one pair of Url - Page to the internal - * hash map, used as a cache. - * + * Internal service method, adds one pair of Url - Page to the internal hash + * map, used as a cache. + * * @param pathInfo url stub for a page to display - * @param page Page object to display + * @param page Page object to display */ private void addPage(final String pathInfo, final Page page) { @@ -220,17 +237,18 @@ public class ContentSectionServlet extends BaseApplicationServlet { m_pages.put(pathInfo, page); } - /** - * Implementation of parent's (abstract) doService method checks HTTP request - * to determine whether to handle a content item or other stuff which is - * delegated to jsp templates. - * {@see com.arsdigita.web.BaseApplicationServlet#doService - * (HttpServletRequest, HttpServletResponse, Application)} - * + * Implementation of parent's (abstract) doService method checks HTTP + * request to determine whether to handle a content item or other stuff + * which is delegated to jsp templates. { + * + * @see com.arsdigita.web.BaseApplicationServlet#doService + * (HttpServletRequest, HttpServletResponse, Application)} + * * @param sreq * @param sresp * @param app + * * @throws javax.servlet.ServletException * @throws java.io.IOException */ @@ -238,7 +256,7 @@ public class ContentSectionServlet extends BaseApplicationServlet { protected void doService(HttpServletRequest sreq, HttpServletResponse sresp, Application app) - throws ServletException, IOException { + throws ServletException, IOException { ContentSection section = (ContentSection) app; @@ -265,10 +283,71 @@ public class ContentSectionServlet extends BaseApplicationServlet { String pathInfo = sreq.getPathInfo(); s_log.debug("Path info is: " + pathInfo); - final ContentItem item = getItem(section, pathInfo, itemResolver); + if (CMSConfig.getInstanceOf().getUseLanguageExtension() + && (!pathInfo.endsWith(".jsp") + || !pathInfo.endsWith(".xml"))) { - Assert.exists(pathInfo, "String pathInfo"); - if (pathInfo.length() > 1 && pathInfo.endsWith("/")) { + if (pathInfo.lastIndexOf(".") == -1) { + final String lang; + if (GlobalizationHelper.getSelectedLocale(sreq) == null) { + lang = GlobalizationHelper + .getNegotiatedLocale() + .getLanguage(); + } else { + lang = GlobalizationHelper + .getSelectedLocale(sreq) + .getLanguage(); + } +// try { + final StringBuffer redirectTo = new StringBuffer(); + if (DispatcherHelper.getWebappContext() != null + && !DispatcherHelper.getWebappContext().trim() + .isEmpty()) { + + redirectTo + .append("/") + .append(DispatcherHelper.getWebappContext()); + } + + redirectTo + .append("/ccm") + .append(section.getPath()); + if (pathInfo.endsWith("/")) { + redirectTo + // .append("/") + .append(pathInfo.substring(0, + pathInfo.length() - 1)); + } else { + redirectTo + // .append("/") + .append(pathInfo); + } + redirectTo + .append(".").append(lang); + + sresp.setHeader("Location", redirectTo.toString()); + sresp.sendError(HttpServletResponse.SC_MOVED_PERMANENTLY); +// sreq +// .getRequestDispatcher(redirectTo.toString()) +// .forward(sreq, sresp); + return; +// } catch (ServletException | IOException ex) { +// throw new RuntimeException(ex); +// } + + } else { + final String lang = url.substring(url.lastIndexOf(".")); + GlobalizationHelper.setSelectedLocale(lang); + } + } + + final ContentItem item = getItem(section, pathInfo, sreq, sresp, + itemResolver); + + Assert.exists(pathInfo, + "String pathInfo"); + if (pathInfo.length() + > 1 && pathInfo.endsWith("/")) { /* NOTE: ServletAPI specifies, pathInfo may be empty or will * start with a '/' character. It currently carries a * trailing '/' if a "virtual" page, i.e. not a real jsp, but @@ -276,18 +355,18 @@ public class ContentSectionServlet extends BaseApplicationServlet { * NOT to end with a trailing '/' for legacy free applications. */ pathInfo = pathInfo.substring(0, pathInfo.length() - 1); } - final Page page = (Page) m_pages.get(pathInfo); + final Page page = (Page) m_pages.get(pathInfo); // //////////////////////////////////////////////////////////////////// // Serve the page // //////////////////////////////////////////////////////////////////// /* FIRST try new style servlet based service */ - if (page != null) { + if (page + != null) { // Check user access. // checkUserAccess(sreq, sresp); // done in individual pages ?? - if (page instanceof CMSPage) { // backwards compatibility fix until migration completed final CMSPage cmsPage = (CMSPage) page; @@ -304,8 +383,9 @@ public class ContentSectionServlet extends BaseApplicationServlet { pm.servePage(doc, sreq, sresp); } - /* SECONDLY try if we have to serve an item (old style dispatcher based */ - } else if (item != null) { + /* SECONDLY try if we have to serve an item (old style dispatcher based */ + } else if (item + != null) { /* We have to serve an item here */ String param = sreq.getParameter("transID"); @@ -314,6 +394,7 @@ public class ContentSectionServlet extends BaseApplicationServlet { Session ssn = SessionManager.getSession(); TransactionContext txn = ssn.getTransactionContext(); txn.addTransactionListener(new AbstractTransactionListener() { + @Override public void beforeCommit(TransactionContext txn) { Assert.fail("uncommittable transaction"); @@ -329,7 +410,7 @@ public class ContentSectionServlet extends BaseApplicationServlet { serveItem(sreq, sresp, section, item); - /* OTHERWISE delegate to a JSP in file system */ + /* OTHERWISE delegate to a JSP in file system */ } else { /* We have to deal with a content-section, folder or another bit */ @@ -357,23 +438,24 @@ public class ContentSectionServlet extends BaseApplicationServlet { sresp.sendError(404, requestUri + " not found on this server."); } } + } // END doService - - /** - * + /** + * * @param sreq * @param sresp * @param section * @param item + * * @throws ServletException - * @throws IOException + * @throws IOException */ private void serveItem(HttpServletRequest sreq, HttpServletResponse sresp, ContentSection section, ContentItem item) - throws ServletException, IOException { + throws ServletException, IOException { if (s_log.isInfoEnabled()) { s_log.info("serving content item"); @@ -389,8 +471,7 @@ public class ContentSectionServlet extends BaseApplicationServlet { sreq.setAttribute(CONTENT_ITEM, item); //set the template context - TemplateResolver templateResolver = - m_disp.getTemplateResolver(section); + TemplateResolver templateResolver = m_disp.getTemplateResolver(section); String templateURL = url; if (!templateURL.startsWith("/")) { @@ -414,7 +495,8 @@ public class ContentSectionServlet extends BaseApplicationServlet { Date endDate = cycle.getEndDate(); if (endDate != null) { - int maxAge = (int) ((endDate.getTime() - System.currentTimeMillis()) / 1000l); + int maxAge = (int) ((endDate.getTime() - System + .currentTimeMillis()) / 1000l); if (maxAge < expires) { expires = maxAge; } @@ -443,7 +525,9 @@ public class ContentSectionServlet extends BaseApplicationServlet { * Fetches the content section from the request attributes. * * @param request The HTTP request + * * @return The content section + * * @pre ( request != null ) */ public static ContentSection getContentSection(HttpServletRequest request) { @@ -454,6 +538,7 @@ public class ContentSectionServlet extends BaseApplicationServlet { * Fetches the ItemResolver for a content section. Checks cache first. * * @param section The content section + * * @return The ItemResolver associated with the content section */ public ItemResolver getItemResolver(ContentSection section) { @@ -473,20 +558,16 @@ public class ContentSectionServlet extends BaseApplicationServlet { return ir; } - /** - * - * @param section - * @param url - * @param itemResolver - * @return - */ - public ContentItem getItem(ContentSection section, String url, + public ContentItem getItem(ContentSection section, + String url, + HttpServletRequest request, + HttpServletResponse response, ItemResolver itemResolver) { if (s_log.isDebugEnabled()) { s_log.debug("getting item at url " + url); } - HttpServletRequest request = Web.getRequest(); +// HttpServletRequest request = Web.getRequest(); //first sanitize the url if (url.endsWith(XML_SUFFIX)) { @@ -495,8 +576,10 @@ public class ContentSectionServlet extends BaseApplicationServlet { url = "/" + url.substring(0, url.length() - XML_SUFFIX.length()); } else { request.setAttribute(XML_MODE, Boolean.FALSE); + if (url.endsWith(FILE_SUFFIX)) { - url = "/" + url.substring(0, url.length() - FILE_SUFFIX.length()); + url = "/" + url + .substring(0, url.length() - FILE_SUFFIX.length()); } else if (url.endsWith("/")) { url = "/" + url.substring(0, url.length() - 1); } @@ -526,7 +609,8 @@ public class ContentSectionServlet extends BaseApplicationServlet { item = itemResolver.getItem(section, url, CMSDispatcher.PREVIEW); if (item != null) { - hasPermission = sm.canAccess(request, SecurityManager.PREVIEW_PAGES, item); + hasPermission = sm.canAccess(request, + SecurityManager.PREVIEW_PAGES, item); } } else { if (s_log.isInfoEnabled()) { @@ -536,11 +620,13 @@ public class ContentSectionServlet extends BaseApplicationServlet { //check if this item is in the cache //we only cache live items if (s_log.isDebugEnabled()) { - s_log.debug("Trying to get content item for URL " + url + " from cache"); + s_log.debug("Trying to get content item for URL " + url + + " from cache"); } // Get the negotiated locale - String lang = GlobalizationHelper.getNegotiatedLocale().getLanguage(); + String lang = GlobalizationHelper.getNegotiatedLocale() + .getLanguage(); // XXX why assign a value and afterwards null?? // Effectively it just ignores the cache and forces a fallback to @@ -552,7 +638,7 @@ public class ContentSectionServlet extends BaseApplicationServlet { if (item == null) { if (s_log.isDebugEnabled()) { s_log.debug("Did not find content item in cache, so trying " - + "to retrieve and cache..."); + + "to retrieve and cache..."); } //item not cached, so retreive it and cache it item = itemResolver.getItem(section, url, ContentItem.LIVE); @@ -615,10 +701,12 @@ public class ContentSectionServlet extends BaseApplicationServlet { return item; } - public ContentItem getItem(ContentSection section, String url) { + public ContentItem getItem(ContentSection section, String url, + HttpServletRequest request, + HttpServletResponse response) { ItemResolver itemResolver = getItemResolver(section); - return getItem(section, url, itemResolver); + return getItem(section, url, request, response, itemResolver); } // synchronize access to the item-url cache @@ -632,10 +720,11 @@ public class ContentSectionServlet extends BaseApplicationServlet { /** * Maps the content item to the URL in a cache + * * @param section the content section in which the content item is published - * @param sURL the URL at which the content item s published + * @param sURL the URL at which the content item s published * @param lang - * @param item the content item at the URL + * @param item the content item at the URL */ public static synchronized void itemURLCachePut(ContentSection section, String sURL, @@ -645,8 +734,8 @@ public class ContentSectionServlet extends BaseApplicationServlet { return; } if (s_log.isDebugEnabled()) { - s_log.debug("adding cached entry for url " + sURL + - " and language " + lang); + s_log.debug("adding cached entry for url " + sURL + " and language " + + lang); } itemURLCachePut(section, sURL, lang, item.getID()); @@ -654,58 +743,63 @@ public class ContentSectionServlet extends BaseApplicationServlet { /** * Removes the cache entry for the URL, sURL + * * @param section the content section in which to remove the key - * @param sURL the cache entry key to remove + * @param sURL the cache entry key to remove * @param lang */ public static synchronized void itemURLCacheRemove(ContentSection section, String sURL, String lang) { if (s_log.isDebugEnabled()) { - s_log.debug("removing cached entry for url " + sURL + - "and language " + lang); + s_log.debug("removing cached entry for url " + sURL + + "and language " + lang); } getItemURLCache(section).remove(sURL + CACHE_KEY_DELIMITER + lang); } /** * Fetches the ContentItem published at that URL from the cache. - * + * * @param section the content section in which the content item is published - * @param sURL the URL for the item to fetch - * @param lang + * @param sURL the URL for the item to fetch + * @param lang + * * @return the ContentItem in the cache, or null */ public static ContentItem itemURLCacheGet(ContentSection section, final String sURL, final String lang) { final BigDecimal itemID = (BigDecimal) getItemURLCache(section).get( - sURL + CACHE_KEY_DELIMITER + lang); + sURL + CACHE_KEY_DELIMITER + lang); if (itemID == null) { return null; } else { try { return (ContentItem) DomainObjectFactory.newInstance(new OID( - ContentItem.BASE_DATA_OBJECT_TYPE, itemID)); + ContentItem.BASE_DATA_OBJECT_TYPE, itemID)); } catch (DataObjectNotFoundException donfe) { return null; + } } } - private static synchronized CacheTable getItemURLCache(ContentSection section) { - Assert.exists(section, ContentSection.class); + private static synchronized CacheTable getItemURLCache( + ContentSection section) { + Assert.exists(section, ContentSection.class + ); if (s_itemURLCacheMap == null) { initializeItemURLCache(); } - + if (s_itemURLCacheMap.get(section.getPath()) == null) { - final CacheTable cache = new CacheTable("ContentSectionServletItemURLCache" + - section.getID().toString()); + final CacheTable cache = new CacheTable( + "ContentSectionServletItemURLCache" + section.getID().toString()); s_itemURLCacheMap.put(section.getPath(), cache); } - + return (CacheTable) s_itemURLCacheMap.get(section.getPath()); } @@ -716,8 +810,8 @@ public class ContentSectionServlet extends BaseApplicationServlet { ContentSection section = sections.getContentSection(); String idStr = section.getID().toString(); String path = section.getPath(); - CacheTable itemURLCache = - new CacheTable("ContentSectionServletItemURLCache" + idStr); + CacheTable itemURLCache = new CacheTable( + "ContentSectionServletItemURLCache" + idStr); s_itemURLCacheMap.put(path, itemURLCache); } @@ -725,10 +819,13 @@ public class ContentSectionServlet extends BaseApplicationServlet { /** * Checks that the current user has permission to access the admin pages. + * * @param request * @param section - * @return - **/ + * + * @return + * + */ public static boolean checkAdminAccess(HttpServletRequest request, ContentSection section) { diff --git a/ccm-sci-publications-navigation/src/com/arsdigita/cms/scipublications/navigation/PublicationList.java b/ccm-sci-publications-navigation/src/com/arsdigita/cms/scipublications/navigation/PublicationList.java index d7d49522b..d73278da5 100644 --- a/ccm-sci-publications-navigation/src/com/arsdigita/cms/scipublications/navigation/PublicationList.java +++ b/ccm-sci-publications-navigation/src/com/arsdigita/cms/scipublications/navigation/PublicationList.java @@ -258,7 +258,7 @@ public class PublicationList extends AbstractComponent { final ResultSet mainQueryResult = publicationsQueryStatement .executeQuery(); - final Element listElem = Navigation.newElement("publication-list"); + final Element listElem = Navigation.newElement("sci-publication-list"); final Element paginatorElem = listElem.newChildElement("paginator");