Added documentation, enhanced formatting.

git-svn-id: https://svn.libreccm.org/ccm/trunk@2581 8810af33-2d31-482b-a856-94f89814c4df
master
pb 2014-03-24 01:59:58 +00:00
parent 5c97a3058a
commit 38313c1e5f
7 changed files with 250 additions and 169 deletions

View File

@ -103,27 +103,35 @@ import org.apache.log4j.Logger;
*/
public class ContentSectionServlet extends BaseApplicationServlet {
/** Creates a s_logging category with name = full name of class */
/** 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. */
// private static final String[] WELCOME_FILES = new String[]{
// "index.jsp", "index.html"
// };
/** The context (in url) for previewing items */
// Some literals
/** Literal for the prefix (in url) for previewing items */
public static final String PREVIEW = "/preview";
/** Template files */
/** Literal Template files suffix */
public static final String FILE_SUFFIX = ".jsp";
/** Literal of URL Stub for index file name (includes leading slash) */
public static final String INDEX_FILE = "/index";
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 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";
private final ContentItemDispatcher m_disp = new ContentItemDispatcher();
public static Map s_itemResolverCache = Collections
.synchronizedMap(new HashMap());
@ -143,10 +151,11 @@ public class ContentSectionServlet extends BaseApplicationServlet {
* (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.
* {@link com.arsdigita.web.BaseServlet}. If not specified system wide
* defaults are used.
* @param config
* @throws javax.servlet.ServletException
*/
@ -192,6 +201,26 @@ public class ContentSectionServlet extends BaseApplicationServlet {
}
/**
* 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
*/
private void addPage(final String pathInfo, final Page page) {
Assert.exists(pathInfo, String.class);
Assert.exists(page, Page.class);
// Current Implementation requires pathInfo to start with a leading '/'
// SUN Servlet API specifies: "PathInfo *may be empty* or will start
// with a '/' character."
Assert.isTrue(pathInfo.startsWith("/"), "path starts not with '/'");
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
@ -329,6 +358,7 @@ public class ContentSectionServlet extends BaseApplicationServlet {
}
} // END doService
/**
*
* @param sreq
@ -342,8 +372,8 @@ public class ContentSectionServlet extends BaseApplicationServlet {
HttpServletResponse sresp,
ContentSection section,
ContentItem item)
throws ServletException, IOException {
//this is a content item, so use ContentItemDispatcher
throws ServletException, IOException {
if (s_log.isInfoEnabled()) {
s_log.info("serving content item");
}
@ -360,6 +390,7 @@ public class ContentSectionServlet extends BaseApplicationServlet {
//set the template context
TemplateResolver templateResolver =
m_disp.getTemplateResolver(section);
String templateURL = url;
if (!templateURL.startsWith("/")) {
templateURL = "/" + templateURL;
@ -407,25 +438,6 @@ public class ContentSectionServlet extends BaseApplicationServlet {
m_disp.dispatch(sreq, sresp, ctx);
}
/**
* 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
*/
private void addPage(final String pathInfo, final Page page) {
Assert.exists(pathInfo, String.class);
Assert.exists(page, Page.class);
// Current Implementation requires pathInfo to start with a leading '/'
// SUN Servlet API specifies: "PathInfo *may be empty* or will start
// with a '/' character."
Assert.isTrue(pathInfo.startsWith("/"), "path starts not with '/'");
m_pages.put(pathInfo, page);
}
/**
* Fetches the content section from the request attributes.
*
@ -530,6 +542,9 @@ public class ContentSectionServlet extends BaseApplicationServlet {
String lang = GlobalizationHelper.getNegotiatedLocale().getLanguage();
// XXX why assign a value and afterwards null??
// Effectively it just ignores the cache and forces a fallback to
// itemResover in any case. Maybe otherwise language selection /
// negotiation doesn't work correctly?
item = itemURLCacheGet(section, url, lang);
item = null;

View File

@ -222,6 +222,7 @@ public class UserLoginForm extends Form
* @param event
* @throws FormProcessException
*/
@Override
public void init(FormSectionEvent event)
throws FormProcessException {
s_log.info("In init");
@ -255,6 +256,7 @@ public class UserLoginForm extends Form
* @param event
* @throws FormProcessException
*/
@Override
public void validate(FormSectionEvent event)
throws FormProcessException {
@ -312,6 +314,7 @@ public class UserLoginForm extends Form
* override this method or just one of the specific case handlers
* (onLoginSuccess, onBadPassword, onAccountNotFound, onLoginException).
*
* @param event
* @throws FormProcessException if there is an unexpected login error
**/
protected void loginUser(FormSectionEvent event)
@ -350,6 +353,8 @@ public class UserLoginForm extends Form
/**
* Executed when login succeeds. Default implementation does nothing.
* @param event
* @throws com.arsdigita.bebop.FormProcessException
**/
protected void onLoginSuccess(FormSectionEvent event)
throws FormProcessException {
@ -373,6 +378,9 @@ public class UserLoginForm extends Form
* autoLoginOn is set to false and the user doesn't exist.
* Default implementation marks password parameter with an error
* message.
* @param event
* @param e
* @throws com.arsdigita.bebop.FormProcessException
**/
protected void onLoginFail(FormSectionEvent event,
LoginException e)

View File

@ -23,9 +23,26 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.RequestDispatcher;
/**
* Interface specifies standard API tools to resolve an URL to a accessible
* resource, stored in file system, database of any other suitable location.
* The URL may include virtual resources, e.g. files stored in the database
* instead of the file system. The URL may include other "virtual" parts with
* must be mapped to an appropriate real path.
*/
public interface ApplicationFileResolver {
/**
*
* @param templatePath
* @param sreq
* @param sresp
* @param app
* @return
*/
RequestDispatcher resolve(String templatePath,
HttpServletRequest sreq,
HttpServletResponse sresp,
Application app);
}

View File

@ -42,7 +42,9 @@ import org.apache.log4j.Logger;
// NOTE
// Combines and replaces the classes DispatcherServlet and BaseDispatcher
// Combines and replaces the previous classes DispatcherServlet and BaseDispatcher
// Most of their code and their separation are abundant as old style applications
// are no longer supported.
/**
@ -378,7 +380,7 @@ public class CCMDispatcherServlet extends BaseServlet {
/**
*
* Private class.
*/
private static class ApplicationSpec {
private final BigDecimal m_id;

View File

@ -25,6 +25,12 @@ import javax.servlet.RequestDispatcher;
import org.apache.log4j.Logger;
/**
* The default implementation deals with templates files belonging to a specific
* application, e.g. cms. Because of the modular structure of CCM all file
* resources of an application are stored below that application's module
* directory. The directory structure itself is application specific.
*/
public class DefaultApplicationFileResolver implements ApplicationFileResolver {
/** Internal logger instance to faciliate debugging. Enable logging output
@ -34,13 +40,24 @@ public class DefaultApplicationFileResolver implements ApplicationFileResolver {
private static final Logger s_log = Logger.getLogger
(DefaultApplicationFileResolver.class);
/** List of alternative greeting files. Typical vales are index.jsp and
* index.html */
private static final String[] WELCOME_FILES = new String[] {
"index.jsp", "index.html"
};
/**
* Determines from the passsed in information a suitable RequestDispatcher.
* Implementation of the interface' single method.
* Determines from the passsed in request URL a suitable template file in
* the templates subdirectory. It returns an identified template wrapped
* in a RequestDispatcher enabling it to be executed (forwarded). The
* request will typically something like
* <pre>/[appCtx]/[webappInstance]/[webappInstInternalDir]/[template.jsp]</pre>
* For the content section "info" administration page installed in the
* ROOT context (i.e. [appCtx] is empty) in would be
* <pre>/info/admin/index.jsp</pre>
* The actual template is actual stored in the file system at
* <pre>/templates/ccm-cms/content-section/admin/index.jsp</pre> and the
* content-section to be administrated has to be passed in as parameter.
*
* @param templatePath
* @param sreq
@ -55,17 +72,24 @@ public class DefaultApplicationFileResolver implements ApplicationFileResolver {
Application app) {
String contextPath = app.getContextPath(); // constant from Application!
String pathInfo = sreq.getPathInfo();
if (s_log.isDebugEnabled()) {
String pathInfo = sreq.getPathInfo(); // effectively provides an url
if (s_log.isDebugEnabled()) { // with application part stripped
s_log.debug("Resolving resource for " + pathInfo);
}
String node = app.getPath();
// determine the URL the application INSTANCE is really installed at
// will replace the application part stripped above
String node = app.getPath();
do {
// First check the complete path for the instance. Parameter
// templatePath denotes the template directory for the application
// TYPE.
String path = templatePath + node + pathInfo;
// Just in case of a directory the list of welcome files have to be
// probed.
if (path.endsWith("/")) {
for (String welcomeFile : WELCOME_FILES) { //1.5 enhanced for-loop
if (s_log.isDebugEnabled()) {
@ -95,9 +119,15 @@ public class DefaultApplicationFileResolver implements ApplicationFileResolver {
return rd;
}
}
// If nothing has been found at the complete path, probe variations
// of the node part by clipping element-wise
if ("".equals(node)) {
// if node is already empty we can't clip anything - fallthrough
node = null;
} else {
// clipp the last part of node retaining the first / in case
// of multiple parts or clip at all (in case of a single part)
int index = node.lastIndexOf("/", node.length() - 2);
node = node.substring(0, index);
}
@ -106,7 +136,7 @@ public class DefaultApplicationFileResolver implements ApplicationFileResolver {
if (s_log.isDebugEnabled()) {
s_log.debug("No dispatcher found");
}
// fallthrough, no success - returning null
return null;
}

View File

@ -62,33 +62,91 @@ public final class WebConfig extends AbstractConfig {
*
* @return The <code>CMSConfig</code> record; it cannot be null
*/
public static synchronized WebConfig getInstanceOf() {
if (s_config == null) {
s_config = new WebConfig();
s_config.load();
}
public static synchronized WebConfig getInstanceOf() {
if (s_config == null) {
s_config = new WebConfig();
s_config.load();
}
return s_config;
}
return s_config;
}
// /////////////////////////////////////////////////////////////////////////
// Configuration parameter section
// /////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Configuration parameter section
// /////////////////////////////////////////////////////////////////////////
private final Parameter m_scheme;
private final Parameter m_server;
private final Parameter m_secureServer;
private final Parameter m_host;
private final Parameter m_site;
// private final Parameter m_context;
private final Parameter m_servlet;
private final Parameter m_policy;
private final Parameter m_resolver;
private final Parameter m_dynamic_host_provider;
private final Parameter m_deactivate_cache_host_notifications;
private final Parameter m_secureRequired;
private final Parameter m_secureSwitchBack;
/** Determines what HTTP scheme prefix is used by default to generate URLs
* (either http od https) */
private final Parameter m_scheme = new DefaultSchemeParameter
("waf.web.default_scheme",
Parameter.REQUIRED, "http");
/** Sets the name and port that users of a site will see in URLs generated
* by CCM for the site. This is a required parameter during installation,
* e.g. example.com:80 */
private final Parameter m_server = new HttpHostParameter
("waf.web.server");
/** Name and port that users of a site will see in secure URLs generated
* by CCM for the site. As an example: example.com:443 */
private final Parameter m_secureServer = new HttpHostParameter
("waf.web.secure_server",
Parameter.OPTIONAL, null);
/** The name of your website, for use in page footers for example. It's
* not necessarily the URL but rather a title, e.g. "House of HTML".
* If not specified set to the server's URL. */
private final Parameter m_site= new StringParameter
("waf.web.site_name",
Parameter.OPTIONAL, null) { @Override
public final Object getDefaultValue() {
final HttpHost host = getServer();
if (host == null) {
return null;
} else {
return host.toString();
}
}
};
/** Sets the name and port of the machine on which the CCM instance is
* running. Used to fetch some resources by a local URL avoiding external
* internet traffic (and delay). If not specified set to the servers's
* name redirecting all traffic to external internet address. */
private final Parameter m_host = new HttpHostParameter
("waf.web.host",
Parameter.OPTIONAL, null) { @Override
public final Object getDefaultValue() {
return getServer();
}
};
/** List of URLs which accessed by insecure (normal HTTP) connection
* produce a redirect to a HTTPS equivalent. List is comma separated. */
private final Parameter m_secureRequired = new StringArrayParameter
("waf.web.secure_required", Parameter.OPTIONAL, null);
/** List of URLs which accessed by secure (HTTPS) connection produce a
* redirect to a HTTP equivalent. List is comma separated. */
private final Parameter m_secureSwitchBack = new StringArrayParameter
("waf.web.secure_switchback", Parameter.OPTIONAL, null);
/** Dispatcher servlet path. It's the prefix to the main entry point for
* any application request (CCMDispatcherServlet). By default /ccm */
private final Parameter m_servlet = new StringParameter
("waf.web.dispatcher_servlet_path", Parameter.REQUIRED, "/ccm");
/** Specifies by name which implementation of ApplicationFileResolver is
* used to dynamically resolve static files. By default
* DefaultApplicationFileResolver() is used. */
private final Parameter m_resolver = new SingletonParameter
("waf.web.application_file_resolver",
Parameter.OPTIONAL,
new DefaultApplicationFileResolver());
private final Parameter m_default_cache_policy = new CachePolicyParameter
("waf.web.cache_policy",
Parameter.OPTIONAL, null);
private final Parameter m_deactivate_cache_host_notifications = new BooleanParameter
("waf.web.deactivate_cache_host_notifications",
Parameter.OPTIONAL, Boolean.FALSE);
private final Parameter m_dynamic_host_provider = new StringParameter
("waf.web.dynamic_host_provider",
Parameter.OPTIONAL, "");
/**
* Constructor, but do NOT instantiate this class directly, use
@ -96,80 +154,19 @@ public final class WebConfig extends AbstractConfig {
*
*/
public WebConfig() {
m_scheme = new DefaultSchemeParameter
("waf.web.default_scheme", Parameter.REQUIRED, "http");
m_server = new HttpHostParameter("waf.web.server");
m_secureServer = new HttpHostParameter
("waf.web.secure_server", Parameter.OPTIONAL, null);
m_host = new HttpHostParameter
("waf.web.host", Parameter.OPTIONAL, null) {
@Override
public final Object getDefaultValue() {
return getServer();
}
};
m_site = new StringParameter
("waf.web.site_name", Parameter.OPTIONAL, null) {
@Override
public final Object getDefaultValue() {
final HttpHost host = getServer();
if (host == null) {
return null;
} else {
return host.toString();
}
}
};
// NO LONGER configured by configuration option but determined at runtime
// by CCMDispatcherServlet itself.
// // dispatcherContextPath option in old Initializer, set to ""
// m_context = new StringParameter
// ("waf.web.dispatcher_context_path", Parameter.REQUIRED, "");
// dispatcherServletPath option in old Initializer, set to "/ccm"
m_servlet = new StringParameter
("waf.web.dispatcher_servlet_path", Parameter.REQUIRED, "/ccm");
m_policy = new CachePolicyParameter
("waf.web.cache_policy", Parameter.OPTIONAL, null);
m_resolver = new SingletonParameter
("waf.web.application_file_resolver",
Parameter.OPTIONAL,
new DefaultApplicationFileResolver());
m_secureRequired = new StringArrayParameter(
"waf.web.secure_required", Parameter.OPTIONAL, null);
m_secureSwitchBack = new StringArrayParameter (
"waf.web.secure_switchback", Parameter.OPTIONAL, null);
m_dynamic_host_provider = new StringParameter
("waf.web.dynamic_host_provider", Parameter.OPTIONAL, "");
m_deactivate_cache_host_notifications = new BooleanParameter
("waf.web.deactivate_cache_host_notifications", Parameter.OPTIONAL, Boolean.FALSE);
register(m_scheme);
register(m_server);
register(m_secureServer);
register(m_host);
register(m_site);
// register(m_context);
register(m_servlet);
register(m_policy);
register(m_resolver);
register(m_dynamic_host_provider);
register(m_deactivate_cache_host_notifications);
register(m_host);
register(m_secureRequired);
register(m_secureSwitchBack);
register(m_servlet);
register(m_resolver);
register(m_default_cache_policy);
register(m_deactivate_cache_host_notifications);
register(m_dynamic_host_provider);
loadInfo();
}
@ -228,6 +225,11 @@ public final class WebConfig extends AbstractConfig {
* @deprecated use Web.getContextPath() instead. The installation context
* must no longer manually configured
*/
// NO LONGER configured by configuration option but determined at runtime
// by CCMDispatcherServlet itself.
// // dispatcherContextPath option in old Initializer, set to ""
// m_context = new StringParameter
// ("waf.web.dispatcher_context_path", Parameter.REQUIRED, "");
public final String getDispatcherContextPath() {
// return (String) get(m_context);
return CCMDispatcherServlet.getContextPath();
@ -251,7 +253,7 @@ public final class WebConfig extends AbstractConfig {
* @return
*/
public final CachePolicy getCachePolicy() {
return (CachePolicy) get(m_policy);
return (CachePolicy) get(m_default_cache_policy);
}
private static class DispatcherServletPathParameter

View File

@ -1,52 +1,59 @@
waf.web.application_file_resolver.title=Application file resolver class
waf.web.application_file_resolver.purpose=Determines the implementation of ApplicationFileResolver used to dynamically resolve static files
waf.web.application_file_resolver.example=com.arsdigita.web.DefaultApplicationFileResolver
waf.web.application_file_resolver.format=[classname]
waf.web.cache_policy.title=Default HTTP-header caching policy
waf.web.cache_policy.purpose=Sets the default policy for controlling browser-side caching via HTTP cache headers
waf.web.cache_policy.example=world
waf.web.cache_policy.format=none|disable|user|world
waf.web.default_scheme.title=Default scheme
waf.web.default_scheme.purpose=Determines what HTTP scheme prefix is used to generate URLs
waf.web.default_scheme.example=http
waf.web.default_scheme.format=http|https
waf.web.dispatcher_context_path.title=Dispatcher context path
waf.web.dispatcher_context_path.purpose=Sets the context path to the WAF dispatcher servlet
waf.web.dispatcher_context_path.example=/
waf.web.dispatcher_context_path.format=[url]
waf.web.dispatcher_servlet_path.title=Dispatcher servlet path
waf.web.dispatcher_servlet_path.purpose=Sets the servlet path to the WAF dispatcher servlet
waf.web.dispatcher_servlet_path.example=/ccm
waf.web.dispatcher_servlet_path.format=[url]
waf.web.host.title=Virtual host
waf.web.host.purpose=Sets the hostname and port of the machine on which the CCM instance is running
waf.web.host.example=frontend1.example.com:8080
waf.web.host.format=[hostname]:[port]
waf.web.server.title=Server virtual host
waf.web.server.purpose=Sets the hostname and port that users of a site will see in URLs generated by WAF
waf.web.server.title=Server
waf.web.server.purpose=Sets the name and port that users of a site will see in URLs generated by WAF
waf.web.server.example=example.com:80
waf.web.server.format=[server hostname]:[port number]
waf.web.secure_server.title=Secure server virtual host
waf.web.secure_server.purpose=Sets the hostname and port that users of a site will see in secure URLs generated by WAF
waf.web.secure_server.title=Secure server
waf.web.secure_server.purpose=Sets the name and port that users of a site will see in secure URLs generated by WAF
waf.web.secure_server.example=example.com:443
waf.web.secure_server.format=[server hostname]:[port number]
waf.web.secure_required.title=List of URLs where HTTPS is required
waf.web.secure_required.purpose=List of URLs which accessed by insecure (normal HTTP) connection produce a redirect to a HTTPS equivalent
waf.web.secure_required.example=/ccm/register/,/ccm/admin/
waf.web.secure_required.format=url1,url2,...
waf.web.secure_switchback.title=List of URLs that switch back to unsecure
waf.web.secure_switchback.purpose=List of URLs which accessed by secure (HTTPS) connection produce a redirect to a HTTP equivalent
waf.web.secure_switchback.example=/ccm/register/logout
waf.web.secure_switchback.format=url1,url2,...
waf.web.site_name.title=Site name
waf.web.site_name.purpose=The name of your website, for use in page footers for example
waf.web.site_name.example=Joe's House of HTML
waf.web.site_name.format=[string]
waf.web.dynamic_host_provider.title=Dynamic Host Provider
waf.web.dynamic_host_provider.purpose=Class name of the DynamicHostProvider to use
waf.web.dynamic_host_provider.example=com.arsdigita.web.ServerDynamicHostProvider
waf.web.dynamic_host_provider.format=[string]
web.host.title=CCM host
waf.web.host.purpose=Sets the name and port of the machine on which the CCM instance is running
waf.web.host.example=frontend1.example.com:8080
waf.web.host.format=[hostname]:[port]
waf.web.secure_required.title=List of URLs where HTTPS is required
waf.web.secure_required.purpose=List of URLs which accessed by insecure (normal HTTP) connection produce a redirect to a HTTPS equivalent
waf.web.secure_required.example=/ccm/register/,/ccm/admin/
waf.web.secure_required.format=url1,url2,...
waf.web.secure_switchback.title=List of URLs that switch back to unsecure
waf.web.secure_switchback.purpose=List of URLs which accessed by secure (HTTPS) connection produce a redirect to a HTTP equivalent
waf.web.secure_switchback.example=/ccm/register/logout
waf.web.secure_switchback.format=url1,url2,...
waf.web.dispatcher_servlet_path.title=Dispatcher servlet path
waf.web.dispatcher_servlet_path.purpose=Sets the servlet path to the WAF dispatcher servlet
waf.web.dispatcher_servlet_path.example=/ccm
waf.web.dispatcher_servlet_path.format=[url]
waf.web.application_file_resolver.title=Application file resolver class
waf.web.application_file_resolver.purpose=Determines the implementation of ApplicationFileResolver used to dynamically resolve static files
waf.web.application_file_resolver.example=com.arsdigita.web.DefaultApplicationFileResolver
waf.web.application_file_resolver.format=[classname]
waf.web.cache_policy.title=Default HTTP-header caching policy
waf.web.cache_policy.purpose=Sets the default policy for controlling browser-side caching via HTTP cache headers
waf.web.cache_policy.example=world
waf.web.cache_policy.format=none|disable|user|world
waf.web.deactivate_cache_host_notifications.title=Deactivate Host Notification for Caches
waf.web.deactivate_cache_host_notifications.purpose=Whether Hosts should be notificed when a Cache needs to be cleared
waf.web.deactivate_cache_host_notifications.example=true
waf.web.deactivate_cache_host_notifications.format=[boolean]
waf.web.dynamic_host_provider.title=Dynamic Host Provider
waf.web.dynamic_host_provider.purpose=Class name of the DynamicHostProvider to use
waf.web.dynamic_host_provider.example=com.arsdigita.web.ServerDynamicHostProvider
waf.web.dynamic_host_provider.format=[string]