diff --git a/ccm-cms/src/WEB-INF/resources/cms-service-map.xml b/ccm-cms/src/WEB-INF/resources/cms-service-map.xml
index 9f814dd2d..050ccd719 100755
--- a/ccm-cms/src/WEB-INF/resources/cms-service-map.xml
+++ b/ccm-cms/src/WEB-INF/resources/cms-service-map.xml
@@ -1,22 +1,34 @@
- logout/
+ /logout/
com.arsdigita.cms.ui.Logout
+
+ /stream/image/
com.arsdigita.cms.dispatcher.StreamImage
+
+ /download/image/
com.arsdigita.cms.dispatcher.DownloadImage
+
+ /stream/asset/
com.arsdigita.cms.dispatcher.StreamAsset
+
+ /download/asset/
com.arsdigita.cms.dispatcher.DownloadAsset
diff --git a/ccm-cms/src/com/arsdigita/cms/ContentCenterServlet.java b/ccm-cms/src/com/arsdigita/cms/ContentCenterServlet.java
index 085ae6d8f..09e1342fb 100644
--- a/ccm-cms/src/com/arsdigita/cms/ContentCenterServlet.java
+++ b/ccm-cms/src/com/arsdigita/cms/ContentCenterServlet.java
@@ -229,7 +229,7 @@ public class ContentCenterServlet extends BaseApplicationServlet {
sreq = DispatcherHelper.restoreOriginalRequest(sreq);
rd.forward(sreq, sresp);
} else {
- // String requestUri = sreq.getRequestURI();
+
sresp.sendError(404, sreq.getRequestURI() + " not found on this server.");
}
diff --git a/ccm-cms/src/com/arsdigita/cms/ServiceServlet.java b/ccm-cms/src/com/arsdigita/cms/ServiceServlet.java
index 8f819c609..a684a3f3f 100644
--- a/ccm-cms/src/com/arsdigita/cms/ServiceServlet.java
+++ b/ccm-cms/src/com/arsdigita/cms/ServiceServlet.java
@@ -33,7 +33,6 @@ import com.arsdigita.web.Web;
import com.arsdigita.xml.XML;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.RequestDispatcher;
@@ -44,10 +43,23 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.xml.sax.helpers.DefaultHandler;
+// Developer's Note:
+// Class is currently in a transistory state. ServiceServlet itself does process
+// the request following the new legacy free web application model (i.e. as a
+// servlet based on BaseApplicationSerevlet / HTTPServlet).
+// The methods used to invoke the service classes follow the legacy dispatcher
+// model as set up by BaseApplicationServlet (see #makeLegacyContext). They
+// should be refactored to work without LegacyContext, probably as a servlet
+// as well or a legacy free dispatcher / ResourceHandler.
+
/**
* CMS Service application servlet serves all request made for the CMS
* service application.
*
+ * In many cases a service will open a (Web) page, e.g. the download page for
+ * files of a page to provide details or feedback/results of the service. But
+ * a service may also work without any visual output.
+ *
* URLs of the available services are stored in a XML file which is processed
* into a cache of services on a request by request basis (lazy loading).
*
@@ -55,7 +67,7 @@ import org.xml.sax.helpers.DefaultHandler;
* ServiceServlet is associated with a request URL.
*
* The CMS Service determines whether a Page has been registered to
- * the URL and if so passes the request to that page.
+ * the URL and if so passes the request to that serviceResource.
*
* If no Page is registered to the URL, then the CMS Service hands
* the request to the TemplateResolver to find an appropriate JSP file.
@@ -74,18 +86,15 @@ public class ServiceServlet extends BaseApplicationServlet {
* class names). */
private final static String MAP_FILE = "WEB-INF/resources/cms-service-map.xml";
- /** Mapping between a relative URL and the class name of a ResourceHandler.*/
- private static HashMap s_pageClasses = new HashMap();
+ /** Mapping between a relative URL and the class name of a service. */
+ private static HashMap s_serviceClasses = new HashMap();
- /** Instantiated ResourceHandler cache. This allows for lazy loading. */
- private static SimpleCache s_pages = new SimpleCache();
+ /** Instantiated services cache. This allows for lazy loading of the class
+ * (i.e. irs ResourceHandler) for each service. */
+ private static SimpleCache s_services = new SimpleCache();
- /** List of URLs which require a trailing slash. These are required for
- * creating virtual directories, so that relative URLs and redirects
- * work. */
- private ArrayList m_trailingSlashList = new ArrayList();
-
- /** Path to directory containg ccm-cms template files */
+ /** Path to directory containg ccm-cms template files, used in case of fall
+ * back, when no service class is found in s_serviceClasses rsp. MAP_FILE */
private String m_templatePath;
/** Resolvers to find templages (JSP) and other stuff stored in file system.*/
@@ -102,11 +111,7 @@ public class ServiceServlet extends BaseApplicationServlet {
s_log.info("starting doInit method");
}
- /* Initialize List with an empty URL. Later URL's are added which are
- * provided w/o trailing slash rsp. file extension. */
- requireTrailingSlash("");
-
- /* Process mapping file. */
+ /* Process mapping file and fill up s_serviceClasses. */
readFromFile(MAP_FILE);
/** Set Template base path for JSP's */
@@ -141,42 +146,38 @@ public class ServiceServlet extends BaseApplicationServlet {
}
DeveloperSupport.startStage("ServiceServlet.doService");
- Service service = (Service) app;
-
+ /* Developer's Note:
+ * Legacy context, established by BaseApplicationServlet, currently
+ * KernelContext. Not used in ServiceServlet, but required to invoke
+ * the Resource to provide the service by interface definition.
+ * Cuurently (version 6.6.8) not used in any service class.
+ */
RequestContext ctx = DispatcherHelper.getRequestContext();
- String url = ctx.getRemainingURLPart(); // here SiteNodeRequestContext
- String originalUrl = ctx.getOriginalURL();
- String requestUri = sreq.getRequestURI();
- // An empty remaining URL or a URL which doesn't end in trailing slash:
- // probably want to redirect.
- if ( m_trailingSlashList.contains(url) && !originalUrl.endsWith("/") ) {
- DispatcherHelper.sendRedirect(sreq, sresp, originalUrl + "/");
- return;
+ /* Get the service being requested, i.e. the remaining URL following
+ * the servlet address ( ccm/cms-service by default) */
+ String url = sreq.getPathInfo();
+ if (url.length() > 1 && url.endsWith("/")) {
+ /* NOTE: ServletAPI specifies, pathInfo may be empty or will
+ * start with a '/' character. It currently carries a
+ * trailing '/' if a "virtual" serviceResource, i.e. not a real jsp, but
+ * result of a servlet mapping. But Application requires url
+ * NOT to end with a trailing '/' for legacy free applications.
+ * The service classes are currently not real applications, so no
+ * adaptation required here. */
+ // url = url.substring(0, url.length() - 1);
}
- // Check user access.
- // Deprecated and here implemented as a No-OP method!
- /* checkUserAccess(request, response, actx); */
+ // User access can not be checked here, but has to be checked by each
+ // service!
- ResourceHandler page = getResource(url);
+ /* Determine the service requested by url */
+ ResourceHandler serviceResource = getResource(url);
- if (page == null) {
- //Retry without last part
- final String[] tokens = url.split("/");
-
- final StringBuilder altUrlBuilder = new StringBuilder('/');
- for(int i = 0; i < tokens.length - 1; i++) {
- altUrlBuilder.append(tokens[i]);
- altUrlBuilder.append('/');
- }
- page = getResource(altUrlBuilder.toString());
- }
-
- if ( page != null ) {
- // Serve the page.
- page.init();
- page.dispatch(sreq, sresp, ctx);
+ if ( serviceResource != null ) {
+ // Serve the serviceResource.
+ serviceResource.init();
+ serviceResource.dispatch(sreq, sresp, ctx);
} else {
// Fall back on the JSP application dispatcher.
if (s_log.isInfoEnabled()) {
@@ -192,7 +193,7 @@ public class ServiceServlet extends BaseApplicationServlet {
sreq = DispatcherHelper.restoreOriginalRequest(sreq);
rd.forward(sreq,sresp);
} else {
- sresp.sendError(404, requestUri + " not found on this server.");
+ sresp.sendError(404, sreq.getRequestURI() + " not found on this server.");
}
}
@@ -206,20 +207,24 @@ public class ServiceServlet extends BaseApplicationServlet {
/**
- * Fetch a page based on the URL stub.
+ * Determines the Resource (ie class) to serve a requested service based
+ * on its url.
*
+ * Returns a RecourceHandler for the requested service if it could be found,
+ * i.e. a dispatcher class whose dispatch method invokes the service.
+ *
* @param url The URL stub following the site-node URL
* @return A ResourceHandler or null if none exists.
* @pre (url != null)
*/
- protected ResourceHandler getResource(String url) throws ServletException {
+ private ResourceHandler getResource(String url) throws ServletException {
// First check the pages cache for existing pages.
- ResourceHandler page = (ResourceHandler) s_pages.get(url);
+ ResourceHandler page = (ResourceHandler) s_services.get(url);
if ( page == null ) {
- // Next check if the URL maps to a page class.
- String pageClassName = (String) s_pageClasses.get(url);
+ // Next check if the URL maps to a serviceResource class.
+ String pageClassName = (String) s_serviceClasses.get(url);
if ( pageClassName != null ) {
Class pageClass;
@@ -230,7 +235,7 @@ public class ServiceServlet extends BaseApplicationServlet {
throw new ServletException(e);
}
- // Try and instantiate the page.
+ // Try and instantiate the serviceResource.
try {
page = (ResourceHandler) pageClass.newInstance();
} catch (InstantiationException e) {
@@ -242,7 +247,7 @@ public class ServiceServlet extends BaseApplicationServlet {
}
page.init();
- s_pages.put(url, page);
+ s_services.put(url, page);
}
}
return page;
@@ -251,48 +256,24 @@ public class ServiceServlet extends BaseApplicationServlet {
/**
*
- * Initializes URL-to-Page/Dispatcher/Servlet mappings from a file.
+ * Initializes URL-to-Page (class) mappings from a file.
*
* Format of the file is XML:
*
* <dispatcher-configuration>
* <url-mapping
- * <url>my-page</url>
- * OR <page-class>com.arsdigita.Page.class</page-class>
+ * <url>my-serviceResource</url>
+ * OR <serviceResource-class>com.arsdigita.Page</page-class>
* <url-mapping
* </dispatcher-configuration>
*
*/
private void readFromFile(final String file) {
- // XML.parseResource(file, newParseConfigHandler(s_pageClasses));
- XML.parseResource(file, new PageClassConfigHandler(s_pageClasses));
+ XML.parseResource(file, new PageClassConfigHandler(s_serviceClasses));
}
- /**
- * Adds a URL to the list of URLs that are required to have trailing
- * slashes. A request for url will be redirected to url + "/"
- * if the original URL request (what you see in your browser)
- * doesn't include a trailing slash. This is required for
- * creating virtual directories, so that relative URLs and redirects
- * work.
- */
- public void requireTrailingSlash(String url) {
- m_trailingSlashList.add(url);
- }
-
-
- /**
- * Returns a SAX event handler object for setting up a MapDispatcher
- * using an XML config file.
- * @param map A map to configure
- * @return a SAX DefaultHandler object for handling SAX events
- * @pre md.m_map != null
- */
-// protected DefaultHandler newParseConfigHandler(Map map) {
-// return new PageClassConfigHandler(map);
-// }
/**
diff --git a/ccm-cms/src/com/arsdigita/cms/dispatcher/BaseAsset.java b/ccm-cms/src/com/arsdigita/cms/dispatcher/BaseAsset.java
index bfd443133..08cde7bb7 100755
--- a/ccm-cms/src/com/arsdigita/cms/dispatcher/BaseAsset.java
+++ b/ccm-cms/src/com/arsdigita/cms/dispatcher/BaseAsset.java
@@ -52,15 +52,6 @@ class BaseAsset extends ResourceHandlerImpl {
private static final BigDecimalParameter s_assetId = new BigDecimalParameter(ASSET_ID);
private static final OIDParameter s_oid = new OIDParameter(OID_PARAM);
- /*
- * jensp 2011-02-11: No need for static initalizer block here. Moved
- * to variable declaration (see above).
- */
- /*static {
- s_assetId = new BigDecimalParameter(ASSET_ID);
- s_oid = new OIDParameter(OID_PARAM);
- //s_assetId.addParameterListener(new NotNullValidationListener());
- }*/
private final boolean m_download;
private String m_disposition;
@@ -79,7 +70,7 @@ class BaseAsset extends ResourceHandlerImpl {
* Content-Disposition in HTTP.
*/
protected void setFilenameHeader(HttpServletResponse response,
- BinaryAsset asset) {
+ BinaryAsset asset) {
String filename = asset.getName();
if (filename == null) {
filename = s_defaultName;
@@ -95,7 +86,7 @@ class BaseAsset extends ResourceHandlerImpl {
}
private void setHeaders(HttpServletResponse response,
- BinaryAsset asset) {
+ BinaryAsset asset) {
setFilenameHeader(response, asset);
Long contentLength = new Long(asset.getSize());
@@ -121,7 +112,8 @@ class BaseAsset extends ResourceHandlerImpl {
}
private void send(HttpServletResponse response,
- BinaryAsset asset) throws IOException {
+ BinaryAsset asset)
+ throws IOException {
// Stream the blob.
OutputStream out = response.getOutputStream();
try {
@@ -131,11 +123,22 @@ class BaseAsset extends ResourceHandlerImpl {
}
}
+
+ /**
+ *
+ * @param request HTTP request
+ * @param response HTTP response
+ * @param actx (legacy) context, not used in this method but required by
+ * parent implementation's interface
+ * maybe required in future when access privilege is checked.
+ * @throws IOException
+ * @throws ServletException
+ */
@Override
public final void dispatch(HttpServletRequest request,
- HttpServletResponse response,
- RequestContext actx)
- throws IOException, ServletException {
+ HttpServletResponse response,
+ RequestContext actx)
+ throws IOException, ServletException {
// Fetch and validate the asset ID
OID oid = null;
diff --git a/ccm-cms/src/com/arsdigita/cms/dispatcher/BaseImage.java b/ccm-cms/src/com/arsdigita/cms/dispatcher/BaseImage.java
index abbf3788d..94970c533 100755
--- a/ccm-cms/src/com/arsdigita/cms/dispatcher/BaseImage.java
+++ b/ccm-cms/src/com/arsdigita/cms/dispatcher/BaseImage.java
@@ -90,7 +90,7 @@ public class BaseImage extends ResourceHandlerImpl {
}
/**
- * Sets RFC2183 governed Contnet-Disposition header to supply filename to
+ * Sets RFC2183 governed Content-Disposition header to supply filename to
* client. See section 19.5.1 of RFC2616 for interpretation of
* Content-Disposition in HTTP.
*/
diff --git a/ccm-cms/src/com/arsdigita/cms/dispatcher/SimpleCache.java b/ccm-cms/src/com/arsdigita/cms/dispatcher/SimpleCache.java
index 2a75fe5e8..ad4dbfd89 100755
--- a/ccm-cms/src/com/arsdigita/cms/dispatcher/SimpleCache.java
+++ b/ccm-cms/src/com/arsdigita/cms/dispatcher/SimpleCache.java
@@ -53,6 +53,7 @@ public class SimpleCache extends Hashtable{
* @param key The object key
* @return The cached object, null if there is none
*/
+ @Override
public Object get(Object key) {
return super.get(key);
}
@@ -64,6 +65,7 @@ public class SimpleCache extends Hashtable{
* @param value The object to be cached
* @return The cached object
*/
+ @Override
public Object put(Object key, Object value) {
return super.put(key, value);
}
@@ -74,6 +76,7 @@ public class SimpleCache extends Hashtable{
* @param key The object key
* @return The formerly-cached object
*/
+ @Override
public Object remove(Object key) {
return super.remove(key);
}