CCM NG: TemplatingConfig migrated to new configuration system, WebConfig almost migrated

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3807 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-01-19 19:08:51 +00:00
parent 1a3367bbed
commit 127ff16e59
14 changed files with 1192 additions and 772 deletions

View File

@ -1,157 +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.mail;
import com.arsdigita.runtime.AbstractConfig;
import com.arsdigita.util.parameter.BooleanParameter;
import com.arsdigita.util.parameter.ErrorList;
import com.arsdigita.util.parameter.Parameter;
import com.arsdigita.util.parameter.ParameterError;
import com.arsdigita.util.parameter.StringParameter;
import com.arsdigita.util.parameter.URLParameter;
import com.arsdigita.util.UncheckedWrapperException;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;
/**
* LegacyMailConfig
*
* @author Rafael H. Schloming <rhs@mit.edu>
* @version $Revision: #7 $ $Date: 2004/08/16 $
* @version $Id: LegacyMailConfig.java 1513 2007-03-22 09:09:03Z chrisgilbert23 $
*/
public final class LegacyMailConfig extends AbstractConfig {
private Properties m_props;
private final Parameter m_debug = new BooleanParameter
("waf.mail.debug", Parameter.OPTIONAL, Boolean.FALSE);
private final Parameter m_javamail = new PropertyFileParameter
("waf.mail.javamail.configuration", Parameter.OPTIONAL, null);
/* used by Mail when the user is not logged in. */
private final Parameter m_defaultFrom = new StringParameter
("waf.mail.default_from", Parameter.OPTIONAL, "");
private final Parameter m_sendHTML = new BooleanParameter
("waf.mail.send_html_mail", Parameter.OPTIONAL, Boolean.FALSE);
/**
* Constructor registers the parameter ands loads values from config file.
*
*/
public LegacyMailConfig() {
register(m_javamail);
register(m_debug);
register(m_defaultFrom);
register(m_sendHTML);
loadInfo();
}
public Properties getJavamail() {
if (m_props == null) {
URL propsFile = (URL) get(m_javamail);
if (propsFile == null) {
m_props = new Properties();
m_props.put("mail.transport.protocol", "smtp");
m_props.put("mail.smtp.host", "localhost");
} else {
try {
m_props = PropertyFileParameter.getProperties(propsFile);
} catch (IOException ioe) {
throw new UncheckedWrapperException
("unable to retrieve properties file from "
+ propsFile, ioe);
}
}
}
return m_props;
}
/**
*
* @return
*/
public String getDefaultFrom() {
String from = (String) get(m_defaultFrom);
//TODO: usage of arsdigita.web.Web, not sure if the class will be kept in ccm_ng
// if (null == from)
// from = "notloggedin@" + Web.getConfig().getServer().getName();
return from;
}
/**
*
* @return
*/
public boolean isDebug() {
return get(m_debug).equals(Boolean.TRUE);
}
/**
* determine whether messages with mime type text/html
* should be sent as html emails (with plain text alternative) or
* just sent as translated plain text
* @return
*/
public boolean sendHTMLMessageAsHTMLEmail () {
return ((Boolean)get(m_sendHTML)).booleanValue();
}
/**
*
*/
private static class PropertyFileParameter extends URLParameter {
PropertyFileParameter(String name, int multiplicity, Object defaalt) {
super(name, multiplicity, defaalt);
}
@Override
protected void doValidate(Object value, ErrorList errors) {
super.doValidate(value, errors);
if (!errors.isEmpty()) {
return;
}
try {
getProperties((URL) value);
} catch (IOException ioe) {
errors.add(new ParameterError(this, ioe));
}
}
public static Properties getProperties(URL url) throws IOException {
Properties props = new Properties();
props.load(url.openStream());
return props;
}
}
}

View File

@ -43,15 +43,15 @@ import org.apache.log4j.Logger;
/** /**
* <p> * <p>
* This stylesheet resolver is used by the <code>*PresentationManager</code> * This stylesheet resolver is used by the <code>*PresentationManager</code>
* class to work out which XSLT stylesheet to apply to the current Bebop * class to work out which XSLT stylesheet to apply to the current Bebop XML
* XML output. * output.
* </p> * </p>
* *
* <p> * <p>
* This particular stylesheet resolver uses a flat file containing a list * This particular stylesheet resolver uses a flat file containing a list of
* of stylesheet patterns, one per line. The file is called * stylesheet patterns, one per line. The file is called
* <code>WEB-INF/resources/stylesheet-paths.txt</code>. * <code>WEB-INF/resources/stylesheet-paths.txt</code>. Such a file could look
* Such a file could look like this: * like this:
* </p> * </p>
* *
* <pre> * <pre>
@ -71,57 +71,57 @@ import org.apache.log4j.Logger;
* </p> * </p>
* *
* <p> * <p>
* The patterns, such as <code>::vhost::</code>, are substituted * The patterns, such as <code>::vhost::</code>, are substituted for string
* for string values: * values:
* </p> * </p>
* *
* <table border="1"> * <table border="1">
* <tr> <th> Pattern </th> <th> Meaning </th> <th> Examples </th> </tr> * <tr> <th> Pattern </th> <th> Meaning </th> <th> Examples </th> </tr>
* <tr> * <tr>
* <td> <code>::host::</code> </td> * <td> <code>::host::</code> </td>
* <td> Host name </td> * <td> Host name </td>
* <td> <code>www.aplaws.org</code> </td> * <td> <code>www.aplaws.org</code> </td>
* </tr> * </tr>
* <tr> * <tr>
* <td> <code>::vhost::</code> </td> * <td> <code>::vhost::</code> </td>
* <td> Virtual hostname. </td> * <td> Virtual hostname. </td>
* <td> <code>business.camden.gov.uk</code> </td> * <td> <code>business.camden.gov.uk</code> </td>
* </tr> * </tr>
* <tr> * <tr>
* <td> <code>::webapp::</code> </td> * <td> <code>::webapp::</code> </td>
* <td> Current web application name (ie. context or document root) </td> * <td> Current web application name (ie. context or document root) </td>
* <td> <code>ccm</code> </td> * <td> <code>ccm</code> </td>
* </tr> * </tr>
* <tr> * <tr>
* <td> <code>::application::</code> </td> * <td> <code>::application::</code> </td>
* <td> Current CCM Application name </td> * <td> Current CCM Application name </td>
* <td> <code>navigation</code> </td> * <td> <code>navigation</code> </td>
* </tr> * </tr>
* <tr> * <tr>
* <td> <code>::url::</code> </td> * <td> <code>::url::</code> </td>
* <td> URL stub of the current applications name tree</td> * <td> URL stub of the current applications name tree</td>
* <td> <code>admin</code> </td> * <td> <code>admin</code> </td>
* </tr> * </tr>
* <tr> * <tr>
* <td> <code>::prefix::</code> </td> * <td> <code>::prefix::</code> </td>
* <td> ??</td> * <td> ??</td>
* <td> <code>??</code> </td> * <td> <code>??</code> </td>
* </tr> * </tr>
* <tr> * <tr>
* <td> <code>::outputtype::</code> </td> * <td> <code>::outputtype::</code> </td>
* <td> Output format. </td> * <td> Output format. </td>
* <td> <code>text_html</code> </td> * <td> <code>text_html</code> </td>
* </tr> * </tr>
* <tr> * <tr>
* <td> <code>::locale::</code> </td> * <td> <code>::locale::</code> </td>
* <td> Current locale </td> * <td> Current locale </td>
* <td> <code>fr_FR</code> </td> * <td> <code>fr_FR</code> </td>
* </tr> * </tr>
* <tr>clear * <tr>clear
* *
* <td> <code>::outputtype::</code> </td> * <td> <code>::outputtype::</code> </td>
* <td> Output format. </td> * <td> Output format. </td>
* <td> <code>text_html</code> </td> * <td> <code>text_html</code> </td>
* </tr> * </tr>
* </table> * </table>
* *
@ -141,37 +141,37 @@ import org.apache.log4j.Logger;
* actually exists on disk is returned. * actually exists on disk is returned.
* </p> * </p>
* *
* Developer may customize the process by writing a custom pattern generator * Developer may customize the process by writing a custom pattern generator and
* and add it in a custom integration package Initializer (e.g. ccm-ldn-aplaws) * add it in a custom integration package Initializer (e.g. ccm-ldn-aplaws) by
* by following code: * following code: // Register additional PatternStyleSheetResolver for Web app.
* // Register additional PatternStyleSheetResolver for Web app. * PatternStylesheetResolver.registerPatternGenerator( "[myKey]", new
* PatternStylesheetResolver.registerPatternGenerator( * [My]PatternGenerator() );
* "[myKey]",
* new [My]PatternGenerator()
* );
* *
* *
* @author Richard W.M. Jones * @author Richard W.M. Jones
*/ */
public class PatternStylesheetResolver implements StylesheetResolver { public class PatternStylesheetResolver implements StylesheetResolver {
/** Internal logger instance to faciliate debugging. Enable logging output /**
* by editing /WEB-INF/conf/log4j.properties int the runtime environment * Internal logger instance to faciliate debugging. Enable logging output by
* and set com.arsdigita.templating.PatternStylesheetResolver=DEBUG * editing /WEB-INF/conf/log4j.properties int the runtime environment and
* by uncommenting or adding the line. */ * set com.arsdigita.templating.PatternStylesheetResolver=DEBUG by
private static final Logger s_log = Logger.getLogger * uncommenting or adding the line.
(PatternStylesheetResolver.class); */
private static final Logger s_log = Logger.getLogger(
PatternStylesheetResolver.class);
/** List of registered pattern generators which are queried in turn. */ /**
* List of registered pattern generators which are queried in turn.
*/
private static final HashMap s_generators = new HashMap(); private static final HashMap s_generators = new HashMap();
/** /**
* Registers a new pattern generator for the given key. * Registers a new pattern generator for the given key.
* *
* @param key the key as it appears in the pattern string * @param key the key as it appears in the pattern string
* @param gen a pattern generator for producing values to be * @param gen a pattern generator for producing values to be substituted for
* substituted for <code>key</code> * <code>key</code>
*/ */
public static void registerPatternGenerator(String key, public static void registerPatternGenerator(String key,
PatternGenerator gen) { PatternGenerator gen) {
@ -182,39 +182,38 @@ public class PatternStylesheetResolver implements StylesheetResolver {
* at load time. */ * at load time. */
static { static {
s_log.debug("Static initalizer starting..."); s_log.debug("Static initalizer starting...");
registerPatternGenerator registerPatternGenerator("locale", new LocalePatternGenerator());
("locale", new LocalePatternGenerator()); registerPatternGenerator("url", new URLPatternGenerator());
registerPatternGenerator registerPatternGenerator("application",
("url", new URLPatternGenerator()); new ApplicationPatternGenerator());
registerPatternGenerator registerPatternGenerator("outputtype", new OutputTypePatternGenerator());
("application", new ApplicationPatternGenerator()); registerPatternGenerator("prefix", new PrefixPatternGenerator());
registerPatternGenerator registerPatternGenerator("webapp", new WebAppPatternGenerator());
("outputtype", new OutputTypePatternGenerator()); registerPatternGenerator("host", new HostPatternGenerator());
registerPatternGenerator
("prefix", new PrefixPatternGenerator());
registerPatternGenerator
("webapp", new WebAppPatternGenerator());
registerPatternGenerator
("host", new HostPatternGenerator());
s_log.debug("Static initalizer finished."); s_log.debug("Static initalizer finished.");
} }
/** Complete path to the file specifing stylesheet patterns. Configurable /**
* by configuration option in TemplatingConfig */ * Complete path to the file specifying stylesheet patterns. Configurable by
* configuration option in TemplatingConfig
*/
private String m_path = null; private String m_path = null;
/** A List of Lists each of its lists containing one pattern to resolve /**
* a probably appropriate stylesheet to apply. (i.e. one row of the * A List of Lists each of its lists containing one pattern to resolve a
* file m_path above) */ * probably appropriate stylesheet to apply. (i.e. one row of the file
* m_path above)
*/
private List m_paths = null; private List m_paths = null;
/** /**
* *
* @param request * @param request
*
* @return * @return
*/ */
@Override @Override
public URL resolve(HttpServletRequest request) { public URL resolve(HttpServletRequest request) {
synchronized(this) { synchronized (this) {
if (m_paths == null) { if (m_paths == null) {
loadPaths(Templating.getConfig().getStylesheetPaths()); loadPaths(Templating.getConfig().getStylesheetPaths());
} }
@ -226,7 +225,7 @@ public class PatternStylesheetResolver implements StylesheetResolver {
Iterator it = m_paths.iterator(); Iterator it = m_paths.iterator();
while (it.hasNext()) { while (it.hasNext()) {
List pathList = (List) it.next(); List pathList = (List) it.next();
String[] bits = (String[])pathList.toArray( String[] bits = (String[]) pathList.toArray(
new String[pathList.size()] new String[pathList.size()]
); );
expandPlaceholders(bits, paths, values, request); expandPlaceholders(bits, paths, values, request);
@ -234,7 +233,7 @@ public class PatternStylesheetResolver implements StylesheetResolver {
Iterator files = paths.iterator(); Iterator files = paths.iterator();
while (files.hasNext()) { while (files.hasNext()) {
String[] bits = (String[])files.next(); String[] bits = (String[]) files.next();
String resource = StringUtils.join(bits, ""); String resource = StringUtils.join(bits, "");
// UGLY HACK // UGLY HACK
@ -242,9 +241,9 @@ public class PatternStylesheetResolver implements StylesheetResolver {
// the root webapp) the provided string contains a "//" as there is // the root webapp) the provided string contains a "//" as there is
// a slash before as well as after the placeholder in the pattern // a slash before as well as after the placeholder in the pattern
// string. It's ugly so we'll replace it. // string. It's ugly so we'll replace it.
resource = resource.replace("//","/"); resource = resource.replace("//", "/");
// The hack destroys the http protocol as well so we need another hack // The hack destroys the http protocol as well so we need another hack
resource = resource.replace("http:/","http://"); resource = resource.replace("http:/", "http://");
if (s_log.isInfoEnabled()) { if (s_log.isInfoEnabled()) {
s_log.info("Looking to see if resource " + resource + " exists"); s_log.info("Looking to see if resource " + resource + " exists");
@ -259,11 +258,11 @@ public class PatternStylesheetResolver implements StylesheetResolver {
} }
if (s_log.isInfoEnabled()) { if (s_log.isInfoEnabled()) {
s_log.info("origURL is " + origURL); s_log.info("origURL is " + origURL);
} }
final URL xfrmedURL = (origURL==null) ? null : Templating final URL xfrmedURL = (origURL == null) ? null : Templating
.transformURL(origURL); .transformURL(origURL);
if (s_log.isInfoEnabled()) { if (s_log.isInfoEnabled()) {
s_log.info("Transformed resource is " + xfrmedURL); s_log.info("Transformed resource is " + xfrmedURL);
@ -288,13 +287,13 @@ public class PatternStylesheetResolver implements StylesheetResolver {
} }
// fall through & try next pattern // fall through & try next pattern
} catch (IOException ex) { } catch (IOException ex) {
throw new UncheckedWrapperException("cannot open stream " + throw new UncheckedWrapperException("cannot open stream "
resource, ex); + resource, ex);
} }
} }
throw new RuntimeException("no path to XSL stylesheet found; " + throw new RuntimeException("no path to XSL stylesheet found; "
"try modifying " + m_path); + "try modifying " + m_path);
} }
/** /**
@ -310,31 +309,31 @@ public class PatternStylesheetResolver implements StylesheetResolver {
HttpServletRequest request) { HttpServletRequest request) {
LinkedList queue = new LinkedList(); LinkedList queue = new LinkedList();
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Queue initial entry " + StringUtils.join(inBits, "")); s_log.debug("Queue initial entry " + StringUtils.join(inBits, ""));
} }
queue.add(inBits); queue.add(inBits);
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
String[] bits = (String[])queue.removeFirst(); String[] bits = (String[]) queue.removeFirst();
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Process queue entry " + StringUtils.join(bits, "")); s_log.debug("Process queue entry " + StringUtils.join(bits, ""));
} }
boolean clean = true; boolean clean = true;
for (int i = 0 ; i < bits.length && clean ; i++) { for (int i = 0; i < bits.length && clean; i++) {
if (bits[i].startsWith("::") && bits[i].endsWith("::")) { if (bits[i].startsWith("::") && bits[i].endsWith("::")) {
clean = false; clean = false;
String[] vals = getValues(bits[i] String[] vals = getValues(bits[i]
.substring(2, bits[i].length()-2), .substring(2, bits[i].length() - 2),
values, values,
request); request);
if (vals != null) { if (vals != null) {
for (int k = 0 ; k < vals.length ; k++) { for (int k = 0; k < vals.length; k++) {
String[] newBits = new String[bits.length]; String[] newBits = new String[bits.length];
// In case the pattern for an element is an empty // In case the pattern for an element is an empty
// string (e.g. for the ROOT webapp) the slash before // string (e.g. for the ROOT webapp) the slash before
// as well as after the placeholder are added // as well as after the placeholder are added
// resulting in a "//" which does no harm but is // resulting in a "//" which does no harm but is
// ugly. // ugly.
for (int j = 0 ; j < bits.length ; j++) { for (int j = 0; j < bits.length; j++) {
if (j == i) { if (j == i) {
newBits[j] = vals[k]; newBits[j] = vals[k];
} else { } else {
@ -342,8 +341,8 @@ public class PatternStylesheetResolver implements StylesheetResolver {
} }
} }
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Requeue " + s_log.debug("Requeue " + StringUtils.join(
StringUtils.join(newBits, "")); newBits, ""));
} }
queue.add(newBits); queue.add(newBits);
} }
@ -353,8 +352,8 @@ public class PatternStylesheetResolver implements StylesheetResolver {
if (clean) { if (clean) {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Finished expanding placeholders in " + s_log.debug("Finished expanding placeholders in "
StringUtils.join(bits, "")); + StringUtils.join(bits, ""));
} }
paths.add(bits); paths.add(bits);
} }
@ -366,6 +365,7 @@ public class PatternStylesheetResolver implements StylesheetResolver {
* @param key * @param key
* @param values * @param values
* @param request * @param request
*
* @return * @return
*/ */
private String[] getValues(String key, private String[] getValues(String key,
@ -374,11 +374,11 @@ public class PatternStylesheetResolver implements StylesheetResolver {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Lookup placeholder keys for " + key); s_log.debug("Lookup placeholder keys for " + key);
} }
String[] vals = (String[])values.get(key); String[] vals = (String[]) values.get(key);
if (vals == null) { if (vals == null) {
PatternGenerator gen = (PatternGenerator) s_generators.get(key); PatternGenerator gen = (PatternGenerator) s_generators.get(key);
if (gen == null) { if (gen == null) {
return new String[] {}; return new String[]{};
} }
vals = gen.generateValues(key, request); vals = gen.generateValues(key, request);
values.put(key, vals); values.put(key, vals);
@ -404,8 +404,8 @@ public class PatternStylesheetResolver implements StylesheetResolver {
s_log.debug("stream.available is " + stream.available()); s_log.debug("stream.available is " + stream.available());
m_paths = new ArrayList(); m_paths = new ArrayList();
LineNumberReader file = new LineNumberReader LineNumberReader file = new LineNumberReader(new InputStreamReader(
(new InputStreamReader(stream)); stream));
String line; String line;
int lineNum; int lineNum;
while ((line = file.readLine()) != null) { while ((line = file.readLine()) != null) {
@ -428,7 +428,7 @@ public class PatternStylesheetResolver implements StylesheetResolver {
"cannot read XSLT paths from " + path, ex); "cannot read XSLT paths from " + path, ex);
} catch (Exception e) { } catch (Exception e) {
s_log.debug("loadPaths threw exception " + e); s_log.debug("loadPaths threw exception " + e);
} }
} }

View File

@ -77,38 +77,39 @@ public class Templating {
* Config object containing various parameter * Config object containing various parameter
*/ */
private static final TemplatingConfig s_config = TemplatingConfig private static final TemplatingConfig s_config = TemplatingConfig
.getInstanceOf(); .getConfig();
static { static {
s_log.debug("Static initalizer starting..."); s_log.debug("Static initalizer starting...");
Exceptions.registerUnwrapper( Exceptions.registerUnwrapper(
TransformerException.class, TransformerException.class,
new ExceptionUnwrapper() { new ExceptionUnwrapper() {
@Override @Override
public Throwable unwrap(Throwable t) { public Throwable unwrap(Throwable t) {
TransformerException ex = (TransformerException) t; TransformerException ex = (TransformerException) t;
return ex.getCause(); return ex.getCause();
} }
}); });
// now we initiate the CacheTable here // now we initiate the CacheTable here
// default cache size used to be 50, which is too high I reckon, // default cache size used to be 50, which is too high I reckon,
// each template can eat up to 4 megs // each template can eat up to 4 megs
Integer setting = s_config.getCacheSize(); Integer setting = s_config.getStylesheetCacheSize();
int cacheSize = (setting == null ? 10 : setting.intValue()); int cacheSize = (setting == null ? 10 : setting.intValue());
setting = s_config.getCacheAge(); setting = s_config.getStylesheetCacheAge();
int cacheAge = (setting == null ? 60 * 60 * 24 * 3 : setting.intValue()); int cacheAge = (setting == null ? 60 * 60 * 24 * 3 : setting.intValue());
s_log.debug("Static initalizer finished..."); s_log.debug("Static initalizer finished...");
} }
/** /**
* Gets the <code>TemplatingConfig</code> record. * Gets the <code>LegacyTemplatingConfig</code> record.
* *
* @return The <code>TemplatingConfig</code> of this runtime * @return The <code>LegacyTemplatingConfig</code> of this runtime
*/ */
public static TemplatingConfig getConfig() { public static TemplatingConfig getConfig() {
return s_config; return s_config;
@ -139,7 +140,7 @@ public class Templating {
public static PresentationManager getPresentationManager() { public static PresentationManager getPresentationManager() {
try { try {
return (PresentationManager) BebopConfig.getConfig(). return (PresentationManager) BebopConfig.getConfig().
getPresenterClass().newInstance(); getPresenterClass().newInstance();
} catch (IllegalAccessException | InstantiationException ex) { } catch (IllegalAccessException | InstantiationException ex) {
throw new UncheckedWrapperException(ex); throw new UncheckedWrapperException(ex);
} }
@ -151,8 +152,9 @@ public class Templating {
* was first generated, it will be regenerated first. * was first generated, it will be regenerated first.
* *
* @param source the <code>URL</code> to the top-level template resource * @param source the <code>URL</code> to the top-level template resource
*
* @return an <code>XSLTemplate</code> instance representing * @return an <code>XSLTemplate</code> instance representing
* <code>source</code> * <code>source</code>
*/ */
public static synchronized XSLTemplate getTemplate(final URL source) { public static synchronized XSLTemplate getTemplate(final URL source) {
return getTemplate(source, false, true); return getTemplate(source, false, true);
@ -163,15 +165,18 @@ public class Templating {
* cache, it will be returned. If the template has been modified since it * cache, it will be returned. If the template has been modified since it
* was first generated, it will be regenerated first. * was first generated, it will be regenerated first.
* *
* @param source the <code>URL</code> to the top-level template resource * @param source the <code>URL</code> to the top-level template
* resource
* @param fancyErrors Should this place any xsl errors in the request for * @param fancyErrors Should this place any xsl errors in the request for
* use by another class. If this is true, the the errors are stored for * use by another class. If this is true, the the errors
* later use. * are stored for later use.
* @param useCache Should the templates be pulled from cache, if available? * @param useCache Should the templates be pulled from cache, if
* True means they are pulled from cache. False means they are pulled from * available? True means they are pulled from cache.
* the disk. If this is false the pages are also not placed in the cache. * False means they are pulled from the disk. If this is
* false the pages are also not placed in the cache.
*
* @return an <code>XSLTemplate</code> instance representing * @return an <code>XSLTemplate</code> instance representing
* <code>source</code> * <code>source</code>
*/ */
public static synchronized XSLTemplate getTemplate(final URL source, public static synchronized XSLTemplate getTemplate(final URL source,
boolean fancyErrors, boolean fancyErrors,
@ -188,7 +193,7 @@ public class Templating {
if (template == null) { if (template == null) {
if (s_log.isInfoEnabled()) { if (s_log.isInfoEnabled()) {
s_log.info("The template for URL " + source + " is not " s_log.info("The template for URL " + source + " is not "
+ "cached; creating and caching it now"); + "cached; creating and caching it now");
} }
if (fancyErrors) { if (fancyErrors) {
@ -201,14 +206,14 @@ public class Templating {
} }
} else if (KernelConfig.getConfig().isDebugEnabled() } else if (KernelConfig.getConfig().isDebugEnabled()
&& template.isModified()) { && template.isModified()) {
// XXX referencing Kernel above is a broken dependency. // XXX referencing Kernel above is a broken dependency.
// Debug mode should be captured at a lower level, // Debug mode should be captured at a lower level,
// probably on UtilConfig. // probably on UtilConfig.
if (s_log.isInfoEnabled()) { if (s_log.isInfoEnabled()) {
s_log.info("Template " + template + " has been modified; " s_log.info("Template " + template + " has been modified; "
+ "recreating it from scratch"); + "recreating it from scratch");
} }
if (fancyErrors) { if (fancyErrors) {
@ -228,6 +233,7 @@ public class Templating {
* Resolves and retrieves the template for the given request. * Resolves and retrieves the template for the given request.
* *
* @param sreq The current request object * @param sreq The current request object
*
* @return The resolved <code>XSLTemplate</code> instance * @return The resolved <code>XSLTemplate</code> instance
*/ */
public static XSLTemplate getTemplate(final HttpServletRequest sreq) { public static XSLTemplate getTemplate(final HttpServletRequest sreq) {
@ -237,13 +243,15 @@ public class Templating {
/** /**
* Resolves the template for the given request to an URL. * Resolves the template for the given request to an URL.
* *
* @param sreq The current request object * @param sreq The current request object
* @param fancyErrors Should this place any xsl errors in the request for * @param fancyErrors Should this place any xsl errors in the request for
* use by another class. If this is true, the the errors are stored for * use by another class. If this is true, the the errors
* later use. * are stored for later use.
* @param useCache Should the templates be pulled from cache, if available? * @param useCache Should the templates be pulled from cache, if
* True means they are pulled from cache. False means they are pulled from * available? True means they are pulled from cache.
* the disk. If this is false the pages are also not placed in the cache. * False means they are pulled from the disk. If this is
* false the pages are also not placed in the cache.
*
* @return The resolved <code>XSLTemplate</code> instance * @return The resolved <code>XSLTemplate</code> instance
*/ */
public static XSLTemplate getTemplate(final HttpServletRequest sreq, public static XSLTemplate getTemplate(final HttpServletRequest sreq,
@ -286,6 +294,7 @@ public class Templating {
* Generates a stream containing imports for a number of URLs. * Generates a stream containing imports for a number of URLs.
* *
* @param paths An iterator of <code>java.net.URL</code> objects * @param paths An iterator of <code>java.net.URL</code> objects
*
* @return a virtual XSL file * @return a virtual XSL file
*/ */
public static InputStream multiplexXSLFiles(Iterator paths) { public static InputStream multiplexXSLFiles(Iterator paths) {
@ -298,8 +307,8 @@ public class Templating {
URL path = (URL) paths.next(); URL path = (URL) paths.next();
Element imp = root.newChildElement( Element imp = root.newChildElement(
"xsl:import", "xsl:import",
"http://www.w3.org/1999/XSL/Transform"); "http://www.w3.org/1999/XSL/Transform");
imp.addAttribute("href", path.toString()); imp.addAttribute("href", path.toString());
if (s_log.isInfoEnabled()) { if (s_log.isInfoEnabled()) {
@ -352,8 +361,8 @@ public class Templating {
// Check if the url refers to our own host // Check if the url refers to our own host
if (self.getName().equals(url.getHost()) if (self.getName().equals(url.getHost())
&& ((self.getPort() == url.getPort()) && ((self.getPort() == url.getPort())
|| (url.getPort() == -1 && self.getPort() == 80))) { || (url.getPort() == -1 && self.getPort() == 80))) {
// host part denotes to a local resource, cut off host part. // host part denotes to a local resource, cut off host part.
localPath = url.getPath(); localPath = url.getPath();
isLocal = true; isLocal = true;
@ -391,21 +400,21 @@ public class Templating {
URL newURL = Web.findResource(localPath); //without host part here! URL newURL = Web.findResource(localPath); //without host part here!
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log. s_log.
debug("Transforming resource " + url + " to " debug("Transforming resource " + url + " to "
+ newURL); + newURL);
} }
return newURL; return newURL;
} else { } else {
// A real path to disk // A real path to disk
final String filename = Web.getServletContext() final String filename = Web.getServletContext()
.getRealPath(localPath); .getRealPath(localPath);
File file = new File(filename); File file = new File(filename);
if (file.exists()) { if (file.exists()) {
try { try {
URL newURL = file.toURL(); URL newURL = file.toURL();
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Transforming resource " + url + " to " s_log.debug("Transforming resource " + url + " to "
+ newURL); + newURL);
} }
return newURL; return newURL;
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
@ -413,17 +422,20 @@ public class Templating {
} }
} else if (s_log.isDebugEnabled()) { } else if (s_log.isDebugEnabled()) {
s_log.debug("File " + filename s_log.debug("File " + filename
+ " doesn't exist on disk"); + " doesn't exist on disk");
} }
} }
} else // url is not the (local) running CCM host, no transformation } else // url is not the (local) running CCM host, no transformation
// is done // is done
if (s_log.isDebugEnabled()) { {
if (s_log.isDebugEnabled()) {
s_log.debug("URL " + url + " is not local"); s_log.debug("URL " + url + " is not local");
} }
}
return url; // returns the original, unmodified url here return url; // returns the original, unmodified url here
} }
} }
/** /**
@ -433,7 +445,8 @@ public class Templating {
class LoggingErrorListener implements ErrorListener { class LoggingErrorListener implements ErrorListener {
private static final Logger s_log private static final Logger s_log
= Logger.getLogger(LoggingErrorListener.class); = Logger.getLogger(
LoggingErrorListener.class);
private final ArrayList m_errors; private final ArrayList m_errors;
LoggingErrorListener() { LoggingErrorListener() {
@ -461,9 +474,10 @@ class LoggingErrorListener implements ErrorListener {
private void log(Level level, TransformerException ex) { private void log(Level level, TransformerException ex) {
s_log.log(level, "Transformer " + level + ": " s_log.log(level, "Transformer " + level + ": "
+ ex.getLocationAsString() + ": " + ex. + ex.getLocationAsString() + ": " + ex.
getMessage(), getMessage(),
ex); ex);
m_errors.add(ex); m_errors.add(ex);
} }
} }

View File

@ -1,122 +1,177 @@
/* /*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. * Copyright (C) 2016 LibreCCM Foundation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public
* as published by the Free Software Foundation; either version 2.1 of * License as published by the Free Software Foundation; either
* the License, or (at your option) any later version. * 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, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * 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. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * 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.templating; package com.arsdigita.templating;
import com.arsdigita.runtime.AbstractConfig; import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.util.parameter.Parameter; import com.arsdigita.web.ApplicationFileResolver;
import com.arsdigita.util.parameter.IntegerParameter;
import com.arsdigita.util.parameter.SingletonParameter; import org.libreccm.cdi.utils.CdiUtil;
import com.arsdigita.util.parameter.StringParameter; import org.libreccm.configuration.Configuration;
import org.apache.log4j.Logger; import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.configuration.Setting;
import java.util.Objects;
/** /**
* @author Justin Ross *
* @version $Id$ * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
public final class TemplatingConfig extends AbstractConfig { @Configuration
public final class TemplatingConfig {
/** Internal logger instance to faciliate debugging. Enable logging output @Setting
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment private String stylesheetPaths = "/WEB-INF/resources/stylesheet-paths.txt";
* and set com.arsdigita.templating.TemplatingConfig=DEBUG by uncommenting
* it */
private static final Logger s_log = Logger.getLogger
(TemplatingConfig.class);
/** Singelton config object. */ @Setting
private static TemplatingConfig s_conf; private String stylesheetResolverClass = PatternStylesheetResolver.class
/** .getName();
* Gain a WorkspaceConfig object.
* @Setting
* Singelton pattern, don't instantiate a config object using the private Integer stylesheetCacheSize = 10;
* constructor directly!
* @return @Setting
*/ private Integer stylesheetCacheAge = 3600;
public static synchronized TemplatingConfig getInstanceOf() {
if (s_conf == null) { public static TemplatingConfig getConfig() {
s_conf = new TemplatingConfig(); final CdiUtil cdiUtil = new CdiUtil();
s_conf.load(); final ConfigurationManager confManager = cdiUtil.findBean(
ConfigurationManager.class);
return confManager.findConfiguration(TemplatingConfig.class);
}
public String getStylesheetPaths() {
return stylesheetPaths;
}
public void setStylesheetPaths(final String stylesheetPaths) {
this.stylesheetPaths = stylesheetPaths;
}
public String getStylesheetResolverClass() {
return stylesheetResolverClass;
}
public StylesheetResolver getStylesheetResolver() {
try {
@SuppressWarnings("unchecked")
final Class<StylesheetResolver> clazz
= (Class<StylesheetResolver>) Class
.forName(stylesheetResolverClass);
return clazz.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
throw new UncheckedWrapperException(
"Unable to create configured StylesheetResolver.",
ex);
}
}
public void setStylesheetResolverClass(
final String stylesheetResolverClass) {
try {
final Class<?> clazz = Class.forName(stylesheetResolverClass);
if (!StylesheetResolver.class.isAssignableFrom(clazz)) {
throw new IllegalArgumentException(String.format(
"Provided class \"%s\" is not an "
+ "implementation of the interface \"%s\".",
stylesheetResolverClass,
StylesheetResolver.class.getName()));
}
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(
String.format("Unable to retrieve class \"%s\".",
stylesheetResolverClass),
ex);
} }
return s_conf; this.stylesheetResolverClass = stylesheetResolverClass;
} }
/** Fully qualified path string to file contain the pattern file for public Integer getStylesheetCacheSize() {
{@link com.arsdigita.templating.PatternStylesheetResolver return stylesheetCacheSize;
PatternStylesheetResolver} */
private final Parameter m_paths = new StringParameter
("waf.templating.stylesheet_paths", Parameter.REQUIRED,
"/WEB-INF/resources/stylesheet-paths.txt");
/** Specifies class for the implementation of StylesheetResolver Interface
to resolve a modules stylesheet. */
private final Parameter m_resolver = new SingletonParameter
("waf.templating.stylesheet_resolver", Parameter.REQUIRED,
new PatternStylesheetResolver());
/** Specifies number of stylesheets cached. */
private final Parameter m_cacheSize = new IntegerParameter
("waf.templating.stylesheet_cache_size", Parameter.OPTIONAL,
null);
/** Duration of stylesheet cache in seconds */
private final Parameter m_cacheAge = new IntegerParameter
("waf.templating.stylesheet_cache_age", Parameter.OPTIONAL,
null);
public TemplatingConfig() {
register(m_paths);
register(m_resolver);
register(m_cacheSize);
register(m_cacheAge);
loadInfo();
} }
/** public void setStylesheetCacheSize(final Integer stylesheetCacheSize) {
* Get name and location of stylesheet pattern file. this.stylesheetCacheSize = stylesheetCacheSize;
*
* @return String with fully qualified file name
*/
final String getStylesheetPaths() {
return (String) get(m_paths);
} }
/** public Integer getStylesheetCacheAge() {
* Gets the stylesheet resolver. This value is set via the return stylesheetCacheAge;
* <code>com.arsdigita.templating.stylesheet_resolver</code>
* system property.
* @return
*/
public final StylesheetResolver getStylesheetResolver() {
return (StylesheetResolver) get(m_resolver);
} }
/** Can be null. public void setStylesheetCacheAge(final Integer stylesheetCacheAge) {
* @return */ this.stylesheetCacheAge = stylesheetCacheAge;
public final Integer getCacheSize() {
return (Integer) get(m_cacheSize);
} }
/** Can be null. @Override
* @return */ public int hashCode() {
public final Integer getCacheAge() { int hash = 7;
return (Integer) get(m_cacheAge); hash = 23 * hash + Objects.hashCode(stylesheetPaths);
hash = 23 * hash + Objects.hashCode(stylesheetResolverClass);
hash = 23 * hash + Objects.hashCode(stylesheetCacheSize);
hash = 23 * hash + Objects.hashCode(stylesheetCacheAge);
return hash;
} }
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj instanceof TemplatingConfig) {
return false;
}
final TemplatingConfig other = (TemplatingConfig) obj;
if (!Objects.equals(stylesheetPaths, other.getStylesheetPaths())) {
return false;
}
if (!Objects.equals(stylesheetResolverClass,
other.getStylesheetResolverClass())) {
return false;
}
if (!Objects.equals(stylesheetCacheSize,
other.getStylesheetCacheSize())) {
return false;
}
if (!Objects.equals(stylesheetCacheAge,
other.getStylesheetCacheAge())) {
return false;
}
return true;
}
@Override
public String toString() {
return String.format("%s{ "
+ "stylesheetPaths = \"%s\", "
+ "stylesheetResolverClass = \"%s\", "
+ "stylesheetCacheSize = %d, "
+ "stylesheetCacheAge = %d"
+ " }",
super.toString(),
stylesheetPaths,
stylesheetResolverClass,
stylesheetCacheSize,
stylesheetCacheAge);
}
} }

View File

@ -0,0 +1,319 @@
/*
* Copyright (C) 2015 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 com.arsdigita.web;
import com.arsdigita.runtime.AbstractConfig;
import com.arsdigita.util.parameter.BooleanParameter;
import com.arsdigita.util.parameter.EnumerationParameter;
import com.arsdigita.util.parameter.ErrorList;
import com.arsdigita.util.parameter.Parameter;
import com.arsdigita.util.parameter.ParameterError;
import com.arsdigita.util.parameter.SingletonParameter;
import com.arsdigita.util.parameter.StringArrayParameter;
import com.arsdigita.util.parameter.StringParameter;
import com.arsdigita.util.servlet.HttpHost;
import com.arsdigita.util.servlet.HttpHostParameter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* A record containing server-session scoped configuration properties.
*
* Accessors of this class may return null. Developers should take care to trap
* null return values in their code.
*
* @see com.arsdigita.web.Web
* @author Justin Ross &lt;jross@redhat.com&gt;
* @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class LegacyWebConfig extends AbstractConfig {
private static final Logger LOGGER = LogManager.getLogger(LegacyWebConfig.class);
private static LegacyWebConfig config;
/**
* Returns the singleton configuration record for the content section
* environment.
*
* @return The <code>CMSConfig</code> record; it cannot be null
*/
public static synchronized LegacyWebConfig getInstanceOf() {
if (config == null) {
config = new LegacyWebConfig();
config.load();
}
return config;
}
// /////////////////////////////////////////////////////////////////////////
// Configuration parameter section
// /////////////////////////////////////////////////////////////////////////
/**
* 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_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
* getInstanceOf() instead. (Singleton pattern!)
*
*/
public LegacyWebConfig() {
register(m_scheme);
register(m_server);
register(m_secureServer);
register(m_site);
register(m_host);
register(m_secureRequired);
register(m_secureSwitchBack);
register(m_servlet);
register(m_resolver);
register(m_deactivate_cache_host_notifications);
register(m_dynamic_host_provider);
loadInfo();
}
public final String getDefaultScheme() {
return (String) get(m_scheme);
}
public final HttpHost getServer() {
return (HttpHost) get(m_server);
}
public final HttpHost getSecureServer() {
return (HttpHost) get(m_secureServer);
}
public final boolean isSecureRequired(String uri) {
String[] secured = (String[]) get(m_secureRequired);
if (secured != null) {
for (int i = 0, n = secured.length; i < n; i++) {
if (uri.startsWith(secured[i])) {
return true;
}
}
}
return false;
}
public final boolean isNonSecureSwitchRequired(String uri) {
String[] switchBack = (String[]) get(m_secureSwitchBack);
if (switchBack != null) {
for (int i = 0, n = switchBack.length; i < n; i++) {
if (uri.startsWith(switchBack[i])) {
return true;
}
}
}
return false;
}
public final String getDispatcherServletPath() {
return (String) get(m_servlet);
}
public final ApplicationFileResolver getApplicationFileResolver() {
return (ApplicationFileResolver) get(m_resolver);
}
public final HttpHost getHost() {
return (HttpHost) get(m_host);
}
final void setHost(final HttpHost host) {
set(m_host, host);
}
public final String getSiteName() {
return (String) get(m_site);
}
/**
*
* @return
* @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();
}
private static class DispatcherServletPathParameter
extends StringParameter {
DispatcherServletPathParameter(final String name) {
super(name);
}
@Override
protected void doValidate(final Object value, final ErrorList errors) {
final String string = (String) value;
if (string.endsWith("/")) {
final ParameterError error = new ParameterError(this,
"The value must not end in a '/'");
errors.add(error);
}
}
}
private static class DefaultSchemeParameter extends EnumerationParameter {
DefaultSchemeParameter(final String name,
final int multiplicity,
final Object defaalt) {
super(name, multiplicity, defaalt);
put("http", "http");
put("https", "https");
}
}
protected DynamicHostProvider dhProvider = null;
protected boolean dhProviderInited = false;
public final DynamicHostProvider getDynamicHostProvider() {
if (dhProviderInited == false) {
String classname = (String) get(m_dynamic_host_provider);
if (classname != null) {
try {
Class klass = Class.forName(classname);
dhProvider = (DynamicHostProvider) klass.newInstance();
} catch (Exception e) {
LOGGER.error(
"Could not instantiate DynamicHostProvider using classname : "
+ classname, e);
}
}
dhProviderInited = true;
}
return dhProvider;
}
public final boolean getDeactivateCacheHostNotifications() {
return ((Boolean) get(m_deactivate_cache_host_notifications))
.booleanValue();
}
}

View File

@ -120,7 +120,7 @@ import org.libreccm.web.CcmApplication;
* *
* <p> * <p>
* Those methods not taking an <code>HttpServletRequest</code> use the scheme, * Those methods not taking an <code>HttpServletRequest</code> use the scheme,
* server name, and port defined in <code>WebConfig</code>.</p> * server name, and port defined in <code>LegacyWebConfig</code>.</p>
* *
* <p> * <p>
* All static create methods taking a <code>ParameterMap</code> take null to * All static create methods taking a <code>ParameterMap</code> take null to
@ -136,7 +136,7 @@ import org.libreccm.web.CcmApplication;
* @see com.arsdigita.web.DispatcherServlet * @see com.arsdigita.web.DispatcherServlet
* @see com.arsdigita.web.LoginSignal * @see com.arsdigita.web.LoginSignal
* @see com.arsdigita.web.ReturnSignal * @see com.arsdigita.web.ReturnSignal
* @see com.arsdigita.web.WebConfig * @see com.arsdigita.web.LegacyWebConfig
* @see com.arsdigita.web.Application * @see com.arsdigita.web.Application
* @author Justin Ross * @author Justin Ross
* &lt;<a href="mailto:jross@redhat.com">jross@redhat.com</a>&gt; * &lt;<a href="mailto:jross@redhat.com">jross@redhat.com</a>&gt;
@ -612,7 +612,7 @@ public class URL {
* @return a <code>URL</code> to your server's root path * @return a <code>URL</code> to your server's root path
*/ */
public static final URL root() { public static final URL root() {
final WebConfig config = Web.getConfig(); final LegacyWebConfig config = Web.getConfig();
URL url = new URL(config.getDefaultScheme(), URL url = new URL(config.getDefaultScheme(),
config.getServer().getName(), config.getServer().getName(),
@ -679,7 +679,7 @@ public class URL {
public static final URL there(final HttpServletRequest sreq, public static final URL there(final HttpServletRequest sreq,
final String path, final String path,
final ParameterMap params) { final ParameterMap params) {
final WebConfig config = Web.getConfig(); final LegacyWebConfig config = Web.getConfig();
Assert.exists(sreq, "HttpServletRequest sreq"); Assert.exists(sreq, "HttpServletRequest sreq");
Assert.exists(config, "WebConfig config"); Assert.exists(config, "WebConfig config");
@ -715,7 +715,7 @@ public class URL {
public static final URL dynamicHostThere(final HttpServletRequest sreq, public static final URL dynamicHostThere(final HttpServletRequest sreq,
final String path, final String path,
final ParameterMap params) { final ParameterMap params) {
final WebConfig config = Web.getConfig(); final LegacyWebConfig config = Web.getConfig();
DynamicHostProvider provider = Web.getConfig().getDynamicHostProvider(); DynamicHostProvider provider = Web.getConfig().getDynamicHostProvider();
if (provider == null) { if (provider == null) {
@ -755,7 +755,7 @@ public class URL {
*/ */
public static final URL there(final HttpServletRequest sreq, public static final URL there(final HttpServletRequest sreq,
final String path) { final String path) {
final WebConfig config = Web.getConfig(); final LegacyWebConfig config = Web.getConfig();
Assert.exists(sreq, "HttpServletRequest sreq"); Assert.exists(sreq, "HttpServletRequest sreq");
Assert.exists(config, "WebConfig config"); Assert.exists(config, "WebConfig config");
@ -847,7 +847,7 @@ public class URL {
*/ */
public static final URL there(final String path, public static final URL there(final String path,
final ParameterMap params) { final ParameterMap params) {
final WebConfig config = Web.getConfig(); final LegacyWebConfig config = Web.getConfig();
return new URL(config.getDefaultScheme(), return new URL(config.getDefaultScheme(),
config.getServer().getName(), config.getServer().getName(),
@ -949,7 +949,7 @@ public class URL {
* @return * @return
*/ */
public static String getDispatcherPath() { public static String getDispatcherPath() {
final WebConfig config = Web.getConfig(); final LegacyWebConfig config = Web.getConfig();
final HttpServletRequest req = Web.getRequest(); final HttpServletRequest req = Web.getRequest();
final String context = config.getDispatcherContextPath(); final String context = config.getDispatcherContextPath();

View File

@ -47,7 +47,7 @@ public class Web {
*/ */
private static final Logger s_log = Logger.getLogger(Web.class); private static final Logger s_log = Logger.getLogger(Web.class);
private static final WebConfig s_config = WebConfig.getInstanceOf(); private static final LegacyWebConfig s_config = LegacyWebConfig.getInstanceOf();
private static final ThreadLocal s_request = new InternalRequestLocal(); private static final ThreadLocal s_request = new InternalRequestLocal();
private static final ThreadLocal s_servletContext private static final ThreadLocal s_servletContext
@ -90,9 +90,9 @@ public class Web {
/** /**
* Provide the configuration record for code in the web package. * Provide the configuration record for code in the web package.
* *
* @return A <code>WebConfig</code> configuration record; it cannot be null * @return A <code>LegacyWebConfig</code> configuration record; it cannot be null
*/ */
public static WebConfig getConfig() { public static LegacyWebConfig getConfig() {
return s_config; return s_config;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015 LibreCCM Foundation. * Copyright (C) 2016 LibreCCM Foundation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -18,302 +18,250 @@
*/ */
package com.arsdigita.web; package com.arsdigita.web;
import com.arsdigita.runtime.AbstractConfig; import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.util.parameter.BooleanParameter;
import com.arsdigita.util.parameter.EnumerationParameter;
import com.arsdigita.util.parameter.ErrorList;
import com.arsdigita.util.parameter.Parameter;
import com.arsdigita.util.parameter.ParameterError;
import com.arsdigita.util.parameter.SingletonParameter;
import com.arsdigita.util.parameter.StringArrayParameter;
import com.arsdigita.util.parameter.StringParameter;
import com.arsdigita.util.servlet.HttpHost;
import com.arsdigita.util.servlet.HttpHostParameter;
import org.apache.logging.log4j.LogManager; import org.libreccm.cdi.utils.CdiUtil;
import org.apache.logging.log4j.Logger; import org.libreccm.configuration.Configuration;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.configuration.Setting;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.StringJoiner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.Pattern;
import javax.validation.executable.ExecutableValidator;
/** /**
* A record containing server-session scoped configuration properties.
* *
* Accessors of this class may return null. Developers should take care to trap * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* null return values in their code.
*
* @see com.arsdigita.web.Web
* @author Justin Ross &lt;jross@redhat.com&gt;
* @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
public class WebConfig extends AbstractConfig { @Configuration
public final class WebConfig {
private static final Logger LOGGER = LogManager.getLogger(WebConfig.class); @Setting
private String defaultScheme = "http";
private static WebConfig config; @Setting
private String server;
/** @Setting
* Returns the singleton configuration record for the content section private String secureServer;
* environment.
* @Setting
* @return The <code>CMSConfig</code> record; it cannot be null private String siteName;
*/
public static synchronized WebConfig getInstanceOf() { @Setting
if (config == null) { private String host;
config = new WebConfig();
config.load(); @Setting
} private Set<String> secureRequiredFor = new HashSet<>();
return config;
@Setting
private String dispatcherServletPath = "/ccm";
@Setting
private String resolverClass = DefaultApplicationFileResolver.class
.getName();
@Setting
private Boolean deactiveCacheHostNotifications = false;
@Setting
private String dynamicHostProvider;
public static WebConfig getConfig() {
final CdiUtil cdiUtil = new CdiUtil();
final ConfigurationManager confManager = cdiUtil.findBean(
ConfigurationManager.class);
return confManager.findConfiguration(WebConfig.class);
} }
// ///////////////////////////////////////////////////////////////////////// public String getDefaultScheme() {
// Configuration parameter section return defaultScheme;
// ///////////////////////////////////////////////////////////////////////// }
/**
* 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 void setDefaultScheme(final String defaultScheme) {
public final Object getDefaultValue() { this.defaultScheme = defaultScheme;
final HttpHost host = getServer(); }
if (host == null) {
return null; public String getServer() {
} else { return server;
return host.toString(); }
}
} public void setServer(
@Pattern(regexp = "[\\w-.]*:[0-9]{1,5}") final String server) {
}; final Method method;
/** try {
* Sets the name and port of the machine on which the CCM instance is method = getClass().getMethod("setServer", String.class);
* running. Used to fetch some resources by a local URL avoiding external } catch (NoSuchMethodException ex) {
* internet traffic (and delay). If not specified set to the servers's name throw new UncheckedWrapperException(ex);
* redirecting all traffic to external internet address. }
*/
private final Parameter m_host = new HttpHostParameter("waf.web.host", final Set<ConstraintViolation<WebConfig>> violations
Parameter.OPTIONAL, = validateHostParameter(
null) { method, server);
@Override if (violations.isEmpty()) {
public final Object getDefaultValue() { this.server = server;
return getServer(); } else {
} final StringJoiner joiner = new StringJoiner(", ");
violations.forEach(v -> joiner.add(v.getMessage()));
};
throw new IllegalArgumentException(joiner.toString());
/** }
* List of URLs which accessed by insecure (normal HTTP) connection produce }
* a redirect to a HTTPS equivalent. List is comma separated.
*/ public String getSecureServer() {
private final Parameter m_secureRequired = new StringArrayParameter( return secureServer;
"waf.web.secure_required", Parameter.OPTIONAL, null); }
/**
* List of URLs which accessed by secure (HTTPS) connection produce a public void setSecureServer(
* redirect to a HTTP equivalent. List is comma separated. @Pattern(regexp = "[\\w-.]*:[0-9]{1,5}") final String secureServer) {
*/ final Method method;
private final Parameter m_secureSwitchBack = new StringArrayParameter( try {
"waf.web.secure_switchback", Parameter.OPTIONAL, null); method = getClass().getMethod("setSecureServer", String.class);
} catch (NoSuchMethodException ex) {
/** throw new UncheckedWrapperException(ex);
* Dispatcher servlet path. It's the prefix to the main entry point for any }
* application request (CCMDispatcherServlet). By default /ccm
*/ final Set<ConstraintViolation<WebConfig>> violations
private final Parameter m_servlet = new StringParameter( = validateHostParameter(
"waf.web.dispatcher_servlet_path", Parameter.REQUIRED, "/ccm"); method, secureServer);
/** if (violations.isEmpty()) {
* Specifies by name which implementation of ApplicationFileResolver is used this.secureServer = secureServer;
* to dynamically resolve static files. By default } else {
* DefaultApplicationFileResolver() is used. final StringJoiner joiner = new StringJoiner(", ");
*/ violations.forEach(v -> joiner.add(v.getMessage()));
private final Parameter m_resolver = new SingletonParameter(
"waf.web.application_file_resolver", throw new IllegalArgumentException(joiner.toString());
Parameter.OPTIONAL, }
new DefaultApplicationFileResolver()); }
private final Parameter m_deactivate_cache_host_notifications public String getSiteName() {
= new BooleanParameter( return siteName;
"waf.web.deactivate_cache_host_notifications", }
Parameter.OPTIONAL, Boolean.FALSE);
public void setSiteName(final String siteName) {
private final Parameter m_dynamic_host_provider = new StringParameter( this.siteName = siteName;
"waf.web.dynamic_host_provider", }
Parameter.OPTIONAL, "");
public String getHost() {
/** return host;
* Constructor, but do NOT instantiate this class directly, use }
* getInstanceOf() instead. (Singleton pattern!)
* public void setHost(
*/ @Pattern(regexp = "[\\w-.]*:[0-9]{1,5}") final String host) {
public WebConfig() {
final Method method;
register(m_scheme); try {
register(m_server); method = getClass().getMethod("setHost", String.class);
register(m_secureServer); } catch (NoSuchMethodException ex) {
register(m_site); throw new UncheckedWrapperException(ex);
register(m_host); }
register(m_secureRequired);
register(m_secureSwitchBack); final Set<ConstraintViolation<WebConfig>> violations
register(m_servlet); = validateHostParameter(
register(m_resolver); method, host);
register(m_deactivate_cache_host_notifications);
register(m_dynamic_host_provider); if (violations.isEmpty()) {
this.host = host;
loadInfo(); } else {
} final StringJoiner joiner = new StringJoiner(", ");
violations.forEach(v -> joiner.add(v.getMessage()));
public final String getDefaultScheme() {
return (String) get(m_scheme); throw new IllegalArgumentException(joiner.toString());
} }
}
public final HttpHost getServer() {
return (HttpHost) get(m_server); public Set<String> getSecureRequiredFor() {
} return new HashSet<>(secureRequiredFor);
}
public final HttpHost getSecureServer() {
return (HttpHost) get(m_secureServer); public void setSecureRequiredFor(final Set<String> secureRequiredFor) {
} this.secureRequiredFor = secureRequiredFor;
}
public final boolean isSecureRequired(String uri) {
String[] secured = (String[]) get(m_secureRequired); public String getDispatcherServletPath() {
if (secured != null) { return dispatcherServletPath;
for (int i = 0, n = secured.length; i < n; i++) { }
if (uri.startsWith(secured[i])) {
return true; public void setDispatcherServletPath(final String dispatcherServletPath) {
} this.dispatcherServletPath = dispatcherServletPath;
} }
}
return false; public String getResolverClass() {
} return resolverClass;
}
public final boolean isNonSecureSwitchRequired(String uri) {
String[] switchBack = (String[]) get(m_secureSwitchBack); public ApplicationFileResolver getResolver() {
if (switchBack != null) { try {
for (int i = 0, n = switchBack.length; i < n; i++) { @SuppressWarnings("unchecked")
if (uri.startsWith(switchBack[i])) { final Class<ApplicationFileResolver> clazz
return true; = (Class<ApplicationFileResolver>) Class
} .forName(resolverClass);
} return clazz.newInstance();
} } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
return false; throw new UncheckedWrapperException(
} "Unable to retrieve ApplicationFileResolver", ex);
}
public final String getDispatcherServletPath() { }
return (String) get(m_servlet);
} public void setResolverClass(final String resolverClass) {
try {
public final ApplicationFileResolver getApplicationFileResolver() { final Class<?> clazz = Class.forName(resolverClass);
return (ApplicationFileResolver) get(m_resolver); if (!ApplicationFileResolver.class.isAssignableFrom(clazz)) {
} throw new IllegalArgumentException(
String.format("Provided class \"%s\" is not an "
public final HttpHost getHost() { + "implementation of the interface \"%s\".",
return (HttpHost) get(m_host); resolverClass,
} ApplicationFileResolver.class.getName()));
final void setHost(final HttpHost host) {
set(m_host, host);
}
public final String getSiteName() {
return (String) get(m_site);
}
/**
*
* @return
* @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();
}
private static class DispatcherServletPathParameter
extends StringParameter {
DispatcherServletPathParameter(final String name) {
super(name);
}
@Override
protected void doValidate(final Object value, final ErrorList errors) {
final String string = (String) value;
if (string.endsWith("/")) {
final ParameterError error = new ParameterError(this,
"The value must not end in a '/'");
errors.add(error);
} }
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(
String.format("Unable to retrieve class \"%s\".",
resolverClass),
ex);
} }
this.resolverClass = resolverClass;
} }
private static class DefaultSchemeParameter extends EnumerationParameter { public Boolean getDeactiveCacheHostNotifications() {
return deactiveCacheHostNotifications;
DefaultSchemeParameter(final String name,
final int multiplicity,
final Object defaalt) {
super(name, multiplicity, defaalt);
put("http", "http");
put("https", "https");
}
} }
protected DynamicHostProvider dhProvider = null; public void setDeactiveCacheHostNotifications(
protected boolean dhProviderInited = false; final Boolean deactiveCacheHostNotifications) {
this.deactiveCacheHostNotifications = deactiveCacheHostNotifications;
public final DynamicHostProvider getDynamicHostProvider() {
if (dhProviderInited == false) {
String classname = (String) get(m_dynamic_host_provider);
if (classname != null) {
try {
Class klass = Class.forName(classname);
dhProvider = (DynamicHostProvider) klass.newInstance();
} catch (Exception e) {
LOGGER.error(
"Could not instantiate DynamicHostProvider using classname : "
+ classname, e);
}
}
dhProviderInited = true;
}
return dhProvider;
} }
public final boolean getDeactivateCacheHostNotifications() { public String getDynamicHostProvider() {
return ((Boolean) get(m_deactivate_cache_host_notifications)) return dynamicHostProvider;
.booleanValue(); }
public void setDynamicHostProvider(final String dynamicHostProvider) {
this.dynamicHostProvider = dynamicHostProvider;
}
private Set<ConstraintViolation<WebConfig>> validateHostParameter(
final Method method,
final String parameter) {
final Object[] parameters = new Object[1];
parameters[0] = parameter;
final ValidatorFactory factory = Validation
.buildDefaultValidatorFactory();
final ExecutableValidator validator = factory.getValidator()
.forExecutables();
return validator.validateParameters(this, method, parameters);
} }
} }

View File

@ -1,93 +1,102 @@
/* /*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. * Copyright (C) 2016 LibreCCM Foundation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public
* as published by the Free Software Foundation; either version 2.1 of * License as published by the Free Software Foundation; either
* the License, or (at your option) any later version. * 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, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * 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. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * 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.workflow.simple; package com.arsdigita.workflow.simple;
import com.arsdigita.runtime.AbstractConfig; import org.libreccm.cdi.utils.CdiUtil;
import com.arsdigita.util.parameter.BooleanParameter; import org.libreccm.configuration.Configuration;
import com.arsdigita.util.parameter.Parameter; import org.libreccm.configuration.ConfigurationManager;
import com.arsdigita.util.parameter.StringParameter; import org.libreccm.configuration.Setting;
import java.util.Objects;
/** /**
* WorkflowConfig
* *
* @author Rafael H. Schloming &lt;rhs@mit.edu&gt; * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* @version $Id: WorkflowConfig.java 287 2005-02-22 00:29:02Z sskracic $
*/ */
public final class WorkflowConfig extends AbstractConfig { @Configuration
public final class WorkflowConfig {
/** Private Object to hold one's own instance to return to users. */ @Setting
private static WorkflowConfig s_config; private Boolean simpleAlertsEnabled = true;
/** @Setting
* Returns the singleton configuration record for the workflow private String alertsSender;
* configuration.
*
* @return The <code>ContentSectionConfig</code> record; it cannot be null
*/
public static synchronized WorkflowConfig getInstance() {
if (s_config == null) {
s_config = new WorkflowConfig();
s_config.load();
}
return s_config; public static WorkflowConfig getConfig() {
final CdiUtil cdiUtil = new CdiUtil();
final ConfigurationManager confManager = cdiUtil.findBean(
ConfigurationManager.class);
return confManager.findConfiguration(WorkflowConfig.class);
} }
public Boolean getSimpleAlertsEnabled() {
// ///////////////////////////////////////////////////////////////////////////// return simpleAlertsEnabled;
//
// Set of parameters controlling workflow alerts.
//
// /////////////////////////////////////////////////////////////////////////////
/** Turn on or off workflow alerts. */
private BooleanParameter m_alerts = new BooleanParameter
("waf.workflow.simple.alerts_enabled", Parameter.OPTIONAL,
Boolean.TRUE);
/** Default sender for workflow alerts, e.g. workflow@example.com */
private StringParameter m_sender = new StringParameter
("waf.workflow.simple.alerts_sender", Parameter.OPTIONAL, null);
/**
* Constructor
*/
public WorkflowConfig() {
register(m_alerts);
register(m_sender);
loadInfo();
} }
/** public void setSimpleAlertsEnabled(final Boolean simpleAlertsEnabled) {
* Retrieve whether alerts are to be enabled or not. this.simpleAlertsEnabled = simpleAlertsEnabled;
* @return true if alerts are enabled.
*/
public boolean isAlertsEnabled() {
return get(m_alerts).equals(Boolean.TRUE);
} }
/**
* Retrieve alert senders default mail address.
* @return
*/
public String getAlertsSender() { public String getAlertsSender() {
return (String) get(m_sender); return alertsSender;
}
public void setAlertsSender(final String alertsSender) {
this.alertsSender = alertsSender;
}
@Override
public int hashCode() {
int hash = 5;
hash = 47 * hash + Objects.hashCode(simpleAlertsEnabled);
hash = 47 * hash + Objects.hashCode(alertsSender);
return hash;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj instanceof WorkflowConfig) {
return false;
}
final WorkflowConfig other = (WorkflowConfig) obj;
if (!Objects.equals(alertsSender, other.getAlertsSender())) {
return false;
}
return Objects.equals(simpleAlertsEnabled, other
.getSimpleAlertsEnabled());
}
@Override
public String toString() {
return String.format("%s{ "
+ "simpleAlertsEnabled = %b, "
+ "alertsSender = %s"
+ " }",
super.toString(),
simpleAlertsEnabled,
alertsSender);
} }
} }

View File

@ -0,0 +1,31 @@
# Copyright (C) 2016 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
description = Configuration parameters for the (XSL-) Templating system
stylesheetPaths.label = Stylesheet paths file
stylesheetPaths.description = PatternStylesheetResolver uses this file to match a request to a stylesheet
stylesheetResolverClass.label = Stylesheet resolver class
stylesheetResolverClass.description = Specifies a particular implementation of StylesheetResolver interface
stylesheetCacheSize.label = Stylesheet cache size
stylesheetCacheSize.description = Set the number of stylesheets cached
stylesheetCacheAge.label = Stylesheet cache age
stylesheetCacheAge.description = Set the duration of the stylesheet cache, in seconds

View File

@ -1,16 +0,0 @@
waf.templating.stylesheet_paths.title=Stylesheet paths file
waf.templating.stylesheet_paths.purpose=PatternStylesheetResolver uses this file to match a request to a stylesheet
waf.templating.stylesheet_paths.example=/WEB-INF/resources/stylesheet-paths.txt
waf.templating.stylesheet_paths.format=[string]
waf.templating.stylesheet_resolver.title=Stylesheet resolver class
waf.templating.stylesheet_resolver.purpose=Specifies a particular implementation of StylesheetResolver interface
waf.templating.stylesheet_resolver.example=com.arsdigita.templating.PatternStylesheetResolver
waf.templating.stylesheet_resolver.format=[classname]
waf.templating.stylesheet_cache_size.title=Stylesheet cache size
waf.templating.stylesheet_cache_size.purpose=Set the number of stylesheets cached
waf.templating.stylesheet_cache_size.example=10
waf.templating.stylesheet_cache_size.format=[integer]
waf.templating.stylesheet_cache_age.title=Stylesheet cache age
waf.templating.stylesheet_cache_age.purpose=Set the duration of the stylesheet cache, in seconds
waf.templating.stylesheet_cache_age.example=3600
waf.templating.stylesheet_cache_age.format=[integer]

View File

@ -0,0 +1,25 @@
# Copyright (C) 2016 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
description = Configuration properties for the Workflow system
simpleAlertsEnabled.label = Workflow Alerts Enabled
simpleAlertsEnabled.description = Turn on and off workflow alerts
alertsSender.label = Workflow Alerts Sender
alertsSender.description = Default sender for workflow alerts, eg workflow@example.org

View File

@ -1,8 +0,0 @@
waf.workflow.simple.alerts_enabled.title=Workflow Alerts Enabled
waf.workflow.simple.alerts_enabled.purpose=Turn on and off workflow alerts
waf.workflow.simple.alerts_enabled.example=true
waf.workflow.simple.alerts_enabled.format=true|false
waf.workflow.simple.alerts_sender.title=Workflow Alerts Sender
waf.workflow.simple.alerts_sender.purpose=Default sender for workflow alerts
waf.workflow.simple.alerts_sender.example=workflow@example.com
waf.workflow.simple.alerts_sender.format=[email]

View File

@ -0,0 +1,200 @@
/*
* Copyright (C) 2016 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 com.arsdigita.web;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.libreccm.tests.categories.UnitTest;
import java.util.ArrayList;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Category(UnitTest.class)
public class WebConfigTest {
public WebConfigTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
@Test
public void setValidResolver() {
final WebConfig webConfig = new WebConfig();
webConfig.setResolverClass(DefaultApplicationFileResolver.class
.getName());
assertThat(webConfig.getResolverClass(),
is(equalTo(DefaultApplicationFileResolver.class.getName())));
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidResolver() {
final WebConfig webConfig = new WebConfig();
webConfig.setResolverClass(ArrayList.class.getName());
}
@Test(expected = IllegalArgumentException.class)
public void setNotExistingResolver() {
final WebConfig webConfig = new WebConfig();
webConfig.setResolverClass("org.example.resolvers.NotExisting");
}
@Test
public void setValidHost() {
final WebConfig webConfig = new WebConfig();
webConfig.setHost("zeus.example.org:8080");
assertThat(webConfig.getHost(),
is(equalTo("zeus.example.org:8080")));
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidHostWithSchema() {
final WebConfig webConfig = new WebConfig();
webConfig.setHost("http://zeus.example.org:8080");
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidHostWithoutPort() {
final WebConfig webConfig = new WebConfig();
webConfig.setHost("http://zeus.example.org");
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidHostLongPort() {
final WebConfig webConfig = new WebConfig();
webConfig.setHost("http://zeus.example.org:999999");
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidHostWithPath() {
final WebConfig webConfig = new WebConfig();
webConfig.setHost("http://zeus.example.org:8080/foo");
}
@Test
public void setValidServer() {
final WebConfig webConfig = new WebConfig();
webConfig.setServer("zeus.example.org:8080");
assertThat(webConfig.getServer(),
is(equalTo("zeus.example.org:8080")));
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidServerWithSchema() {
final WebConfig webConfig = new WebConfig();
webConfig.setServer("http://zeus.example.org:8080");
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidServerWithoutPort() {
final WebConfig webConfig = new WebConfig();
webConfig.setServer("http://zeus.example.org");
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidServerLongPort() {
final WebConfig webConfig = new WebConfig();
webConfig.setServer("http://zeus.example.org:999999");
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidServerWithPath() {
final WebConfig webConfig = new WebConfig();
webConfig.setServer("http://zeus.example.org:8080/foo");
}
@Test
public void setValidSecureServer() {
final WebConfig webConfig = new WebConfig();
webConfig.setSecureServer("zeus.example.org:8080");
assertThat(webConfig.getSecureServer(),
is(equalTo("zeus.example.org:8080")));
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidSecureServerWithSchema() {
final WebConfig webConfig = new WebConfig();
webConfig.setSecureServer("http://zeus.example.org:8080");
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidSecureServerWithoutPort() {
final WebConfig webConfig = new WebConfig();
webConfig.setSecureServer("http://zeus.example.org");
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidSecureLongPort() {
final WebConfig webConfig = new WebConfig();
webConfig.setSecureServer("http://zeus.example.org:999999");
}
@Test(expected = IllegalArgumentException.class)
public void setInvalidSecureServerWithPath() {
final WebConfig webConfig = new WebConfig();
webConfig.setSecureServer("http://zeus.example.org:8080/foo");
}
}