Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 17222 invoked from network); 3 Nov 2005 14:41:04 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 3 Nov 2005 14:41:04 -0000 Received: (qmail 27875 invoked by uid 500); 3 Nov 2005 14:36:59 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 26517 invoked by uid 500); 3 Nov 2005 14:36:09 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 26001 invoked by uid 99); 3 Nov 2005 14:35:07 -0000 X-ASF-Spam-Status: No, hits=0.6 required=10.0 tests=NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Thu, 03 Nov 2005 06:34:17 -0800 Received: (qmail 11260 invoked by uid 65534); 3 Nov 2005 14:33:56 -0000 Message-ID: <20051103143356.11248.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r330548 [8/132] - in /cocoon/whiteboard/maven2/cocoon-flat-layout: ./ cocoon-ajax-block/ cocoon-ajax-block/api/ cocoon-ajax-block/api/src/ cocoon-ajax-block/api/src/main/ cocoon-ajax-block/api/src/main/java/ cocoon-ajax-block/api/src/main/r... Date: Thu, 03 Nov 2005 14:00:48 -0000 To: cvs@cocoon.apache.org From: jheymans@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/AbstractValidatorAction.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/AbstractValidatorAction.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/AbstractValidatorAction.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/AbstractValidatorAction.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,1075 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.configuration.Configurable; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.parameters.Parameters; + +import org.apache.cocoon.ProcessingException; +import org.apache.cocoon.environment.SourceResolver; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.sitemap.SitemapParameters; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; + +import org.apache.regexp.RE; +import org.apache.regexp.RESyntaxException; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +/** + * Abstract implementation of action that needs to perform validation of + * parameters (from session, from request, etc.). All `validator' actions + * share the same description xml file. In such file every parameter is + * described via its name, type and its constraints. One large description + * file can be used among all validator actions, because each action should + * explicitely specify which parameters to validate - through a sitemap + * parameter. + * + *

Variant 1

+ *
+ * <map:act type="validator">
+ *         <parameter name="descriptor" value="context://descriptor.xml">
+ *         <parameter name="validate" value="username,password">
+ * </map:act>
+ * 
+ * + *

The list of parameters to be validated is specified as a comma + * separated list of their names. descriptor.xml can therefore be used + * among many various actions. If the list contains only of *, + * all parameters in the file will be validated.

+ * + *

Variant 2

+ *
+ * <map:act type="validator">
+ *         <parameter name="descriptor" value="context://descriptor.xml">
+ *         <parameter name="constraint-set" value="is-logged-in">
+ * </map:act>
+ * 
+ * + *

The parameter "constraint-set" tells to take a given + * "constraint-set" from description file and test all parameters + * against given criteria. This variant is more powerful, more aspect + * oriented and more flexibile than the previous one, because it + * allows comparsion constructs, etc. See AbstractValidatorAction + * documentation.

+ * + *

For even more powerful validation, constraints can be grouped + * and used independently of the parameter name. If a validate element + * has a rule attribute, it uses the parameter with that + * name as a rule template and validates the parameter from the + * name attribute with that rule.

+ * + *

This action returns null when validation fails, otherwise it + * provides all validated parameters to the sitemap via {name} + * expression.

+ * + *

In addition a request attribute + * org.apache.cocoon.acting.FormValidatorAction.results + * contains the validation results in both cases and make it available + * to other components. The special parameter "*" contains either the validation + * result "OK", if all parameters were validated successfully, or + * "ERROR" otherwise. Mind you that redirections create new request + * objects and thus the result is not available for the target + * page.

+ * + *
+ * <root>
+ *         <parameter name="username" type="string" nullable="no"/>
+ *         <parameter name="role" type="string" nullable="no"/>
+ *         <parameter name="oldpassword" type="string" nullable="no"/>
+ *         <parameter name="newpassword" type="string" nullable="no"/>
+ *         <parameter name="renewpassword" type="string" nullable="no"/>
+ *         <parameter name="id" type="long" nullable="no"/>
+ *         <parameter name="sallary" type="double" nullable="no"/>
+ *         <parameter name="theme" type="string" nullable="yes" default="dflt"/>
+ *         <constraint-set name="is-logged-in">
+ *                 <validate name="username"/>
+ *                 <validate name="role"/>
+ *         </constraint-set>
+ *
+ *         <constraint-set name="is-in-admin-role">
+ *                 <validate name="username"/>
+ *                 <validate name="role" equals-to="admin"/>
+ *         </constraint-set>
+ *
+ *         <constraint-set name="new-passwords-match">
+ *                 <validate name="oldpassword"/>
+ *                 <validate name="newpassword"/>
+ *                 <validate name="renewpassword"
+ *                         equals-to-param="newpass"/>
+ *         </constraint-set>
+ *
+ *         <constraint-set name="all">
+ *                 <include name="is-logged-in"/>
+ *                 <include name="is-in-admin-role"/>
+ *                 <include name="new-passwords-match"/>
+ *         </constraint-set>
+ * </root>
+ * 
+ * + *

The types recognized by validator and their attributes

+ * + * + * + * + * + * + * + * + * + * + *
stringnullable="yes|no" default="str"
longnullable="yes|no" default="123123"
doublenullable="yes|no" default="0.5"
+ * + *

Default value takes place only when specified parameter is + * nullable and really is null or empty. Long numbers may be specified + * in decimal, hex or octal values as accepted by java.Lang.decode + * (String s).

+ * + *

Constraints

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
matches-regexPOSIX regular expression
min-lenpositive integer
max-lenpositive integer
minDouble / Long
maxDouble / Long
+ * + *

Constraints can be defined globally for a parameter and can be + * overridden by redefinition in a constraint-set. Thus if e.g. a + * database field can take at maximum 200 character, this property can + * be set globally.

+ * + *

Values in parameter arrays are validated individually and the + * worst error is reported back.

+ * + *

The attributes recognized in "constraint-set"

+ * + * + * + * + * + * + * + *
equals-to-paramparameter name
equals-tostring constant
+ * @author Martin Man + * @author Christian Haul + * @version CVS $Id: AbstractValidatorAction.java 307316 2005-10-08 17:20:59Z cziegeler $ + */ +public abstract class AbstractValidatorAction + extends AbstractComplementaryConfigurableAction + implements Configurable { + + /** + * This is the name of the request attribute containing the result + */ + public static final String FORMVALIDATOR_PATH = "org.apache.cocoon.acting.FormValidatorAction.results"; + + /** + * Reads parameter values for all parameters that are contained in the active + * constraint list. If a parameter has multiple values, all are stored in the + * resulting map. + * + * @param objectModel the object model + * @param set a collection of parameter names + * @return HashMap + */ + abstract protected HashMap createMapOfParameters(Map objectModel, Collection set); + + /** + * Are parameters encoded as strings? + * @return + */ + abstract boolean isStringEncoded(); + + /* + * main method + */ + public Map act(Redirector redirector, + SourceResolver resolver, + Map objectModel, + String src, + Parameters parameters) throws Exception { + + Configuration conf = this.getDescriptor(resolver, objectModel, parameters); + if (conf == null) + return null; + + String valStr = + parameters.getParameter("validate", (String)settings.get("validate", "")).trim(); + String valSetStr = + parameters.getParameter("validate-set", (String)settings.get("validate-set", "")).trim(); + String constraintSetStr = + parameters.getParameter("constraint-set", (String)settings.get("constraint-set", "")).trim(); + if (!"".equals(valSetStr)) { + if (getLogger().isInfoEnabled()) { + getLogger().info("Using sitemap parameter 'validate-set' for specifying " + + "the constraint-set for the ValidatorActions is deprecated in " + + "favor of 'constraint-set' due to consistency in the naming."); + } + if ("".equals(constraintSetStr)) { + constraintSetStr = valSetStr; + } + } + Map desc = this.indexConfiguration(conf.getChildren("parameter")); + + Map actionMap = new HashMap(); + Map resultMap = new HashMap(); + Collection params = null; + boolean allOK = false; + + if (!"".equals(valStr)) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Validating parameters as specified via 'validate' parameter"); + } + params = this.getSetOfParameterNamesFromSitemap(valStr, desc); + } else if (!"".equals(constraintSetStr)) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Validating parameters from given constraint-set " + constraintSetStr); + } + Map csets = this.indexConfiguration(conf.getChildren("constraint-set")); + params = this.resolveConstraints(constraintSetStr, csets); + } + + if (params == null) { + throw new ProcessingException("Neither a constraint-set nor parameters in the sitemap " + + "were specified for validating at " + + SitemapParameters.getLocation(parameters)); + } + HashMap values = this.createMapOfParameters(objectModel, params); + allOK = this.validateSetOfParameters(desc, actionMap, resultMap, params, values, this.isStringEncoded()); + + return this.setResult(objectModel, actionMap, resultMap, allOK); + } + + /** + * Try to validate given parameter. + * @param name The name of the parameter to validate. + * @param constraints Configuration of all constraints for this + * parameter as taken from the description XML file. + * @param conf Configuration of all parameters as taken from the + * description XML file. + * @param params The map of parameters. + * @param isString Indicates wheter given param to validate is + * string (as taken from HTTP request for example) or wheteher it + * should be regular instance of java.lang.Double, java.lang.Long, + * etc. + * @return The validated parameter. + */ + public ValidatorActionHelper validateParameter( + String name, + Configuration constraints, + Map conf, + Map params, + boolean isString) { + + return validateParameter(name, name, constraints, conf, params, isString); + } + + /** + * Try to validate given parameter. + * @param name The actual name of the parameter to validate. + * @param rule The name of the parameter element that contains the + * rule that should be used for validation. + * @param constraints Configuration of all constraints for this + * parameter as taken from the description XML file. + * @param conf Configuration of all parameters as taken from the + * description XML file. + * @param params The map of parameters. + * @param isString Indicates wheter given param to validate is + * string (as taken from HTTP request for example) or wheteher it + * should be regular instance of java.lang.Double, java.lang.Long, + * etc. + * @return The validated parameter. + */ + public ValidatorActionHelper validateParameter( + String name, + String rule, + Configuration constraints, + Map conf, + Map params, + boolean isString) { + String type = null; + + if (getLogger().isDebugEnabled()) + getLogger().debug("Validating parameter: " + name + " using rule: " + rule); + + /* try to find matching param description in conf tree */ + try { + Configuration theConf = (Configuration) conf.get(rule); + type = theConf.getAttribute("type"); + + return validateValue(name, constraints, theConf, params, isString, type); + + } catch (Exception e) { + if (getLogger().isDebugEnabled()) + getLogger().debug("No type specified for parameter " + name); + return null; + } + } + + /** + * Validate a single parameter value. + * + * @param name String holding the name of the parameter + * @param constraints Configuration holding the constraint set configuration for the parameter + * @param conf Configuration holding the parameter configuration + * @param params Map of parameter values to be validated + * @param isString boolean indicating if the value is string encoded + * @param type string holding the name of the datatype to validate value + * @return ValidatorActionHelper + */ + protected ValidatorActionHelper validateValue( + String name, + Configuration constraints, + Configuration conf, + Map params, + boolean isString, + String type) { + Object value = params.get(name); + + if (value != null && value.getClass().isArray()) { + Object[] values = (Object[]) value; + ValidatorActionHelper vaH = null; + ValidatorActionResult vaR = ValidatorActionResult.OK; + for (int j = 0; j < values.length; j++) { + value = values[j]; + if ("string".equals(type)) { + vaH = validateString(name, constraints, conf, params, value); + } else if ("long".equals(type)) { + vaH = validateLong(name, constraints, conf, params, isString, value); + } else if ("double".equals(type)) { + vaH = validateDouble(name, constraints, conf, params, isString, value); + } else { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "Unknown type " + type + " specified for parameter " + name); + return null; + } + vaR = (vaR.getPos() < vaH.getResult().getPos() ? vaH.getResult() : vaR); + } + return new ValidatorActionHelper(vaH.getObject(), vaR); + } else { + if ("string".equals(type)) { + return validateString(name, constraints, conf, params, value); + } else if ("long".equals(type)) { + return validateLong(name, constraints, conf, params, isString, value); + } else if ("double".equals(type)) { + return validateDouble(name, constraints, conf, params, isString, value); + } else { + if (getLogger().isDebugEnabled()) + getLogger().debug("Unknown type " + type + " specified for parameter " + name); + } + return null; + } + } + + /** + * Validates nullability and default value for given parameter. If given + * constraints are not null they are validated as well. + */ + private ValidatorActionHelper validateString( + String name, + Configuration constraints, + Configuration conf, + Map params, + Object param) { + + String value = null; + String dflt = getDefault(conf, constraints); + boolean nullable = getNullable(conf, constraints); + + if (getLogger().isDebugEnabled()) + getLogger().debug("Validating string parameter " + name); + try { + value = getStringValue(param); + } catch (Exception e) { + // ClassCastException + return new ValidatorActionHelper(value, ValidatorActionResult.ERROR); + } + if (value == null) { + if (getLogger().isDebugEnabled()) + getLogger().debug("String parameter " + name + " is null"); + if (!nullable) { + return new ValidatorActionHelper(value, ValidatorActionResult.ISNULL); + } else { + return new ValidatorActionHelper(dflt); + } + } + if (constraints != null) { + String eq = constraints.getAttribute("equals-to", ""); + eq = conf.getAttribute("equals-to", eq); + + String eqp = constraints.getAttribute("equals-to-param", ""); + eqp = conf.getAttribute("equals-to-param", eqp); + + String regex = conf.getAttribute("matches-regex", ""); + regex = constraints.getAttribute("matches-regex", regex); + + String oneOf = conf.getAttribute("one-of", ""); + oneOf = constraints.getAttribute("one-of", oneOf); + + Long minlen = getAttributeAsLong(conf, "min-len", null); + minlen = getAttributeAsLong(constraints, "min-len", minlen); + + Long maxlen = getAttributeAsLong(conf, "max-len", null); + maxlen = getAttributeAsLong(constraints, "max-len", maxlen); + + // Validate whether param is equal to constant + if (!"".equals(eq)) { + if (getLogger().isDebugEnabled()) + getLogger().debug("String parameter " + name + " should be equal to " + eq); + if (!value.equals(eq)) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + } + + // Validate whether param is equal to another param + // FIXME: take default value of param being compared with into + // account? + if (!"".equals(eqp)) { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "String parameter " + name + " should be equal to " + params.get(eqp)); + if (!value.equals(params.get(eqp))) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + } + + // Validate whether param length is at least of minimum length + if (minlen != null) { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "String parameter " + + name + + " should be at least " + + minlen + + " characters long"); + if (value.length() < minlen.longValue()) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is shorter (" + value.length() + ")"); + return new ValidatorActionHelper(value, ValidatorActionResult.TOOSMALL); + } + } + + // Validate whether param length is at most of maximum length + if (maxlen != null) { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "String parameter " + + name + + " should be at most " + + maxlen + + " characters long"); + + if (value.length() > maxlen.longValue()) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is longer (" + value.length() + ")"); + return new ValidatorActionHelper(value, ValidatorActionResult.TOOLARGE); + } + } + + // Validate wheter param matches regular expression + if (!"".equals(regex)) { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "String parameter " + name + " should match regexp \"" + regex + "\""); + try { + RE r = new RE(regex); + if (!r.match(value)) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it does not match"); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + } catch (RESyntaxException rese) { + if (getLogger().isDebugEnabled()) + getLogger().error("String parameter " + name + " regex error ", rese); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + } + + // Validates against a set of possibilities + if (!"".equals(oneOf)) { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "String parameter " + name + " should be one of \"" + oneOf + "\""); + if (!oneOf.startsWith("|")) + oneOf = "|" + oneOf; + if (!oneOf.endsWith("|")) + oneOf = oneOf + "|"; + if (value.indexOf("|") != -1) { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "String parameter " + name + "contains \"|\" - can't validate that."); + return new ValidatorActionHelper(value, ValidatorActionResult.ERROR); + } + if (oneOf.indexOf("|" + value + "|") == -1) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + return new ValidatorActionHelper(value, ValidatorActionResult.OK); + + } + + } + return new ValidatorActionHelper(value); + } + + /** + * Validates nullability and default value for given parameter. If given + * constraints are not null they are validated as well. + */ + private ValidatorActionHelper validateLong( + String name, + Configuration constraints, + Configuration conf, + Map params, + boolean is_string, + Object param) { + + boolean nullable = getNullable(conf, constraints); + Long value = null; + Long dflt = getLongValue(getDefault(conf, constraints), true); + + if (getLogger().isDebugEnabled()) + getLogger().debug( + "Validating long parameter " + name + " (encoded in a string: " + is_string + ")"); + try { + value = getLongValue(param, is_string); + } catch (Exception e) { + // Unable to parse long + return new ValidatorActionHelper(value, ValidatorActionResult.ERROR); + } + if (value == null) { + if (getLogger().isDebugEnabled()) + getLogger().debug("Long parameter " + name + " is null"); + if (!nullable) { + return new ValidatorActionHelper(value, ValidatorActionResult.ISNULL); + } else { + return new ValidatorActionHelper(dflt); + } + } + if (constraints != null) { + Long eq = getAttributeAsLong(constraints, "equals-to", null); + String eqp = constraints.getAttribute("equals-to-param", ""); + + Long min = getAttributeAsLong(conf, "min", null); + min = getAttributeAsLong(constraints, "min", min); + + Long max = getAttributeAsLong(conf, "max", null); + max = getAttributeAsLong(constraints, "max", max); + + // Validate whether param is equal to constant + if (eq != null) { + if (getLogger().isDebugEnabled()) + getLogger().debug("Long parameter " + name + " should be equal to " + eq); + + if (!value.equals(eq)) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + } + + // Validate whether param is equal to another param + // FIXME: take default value of param being compared with into + // account? + if (!"".equals(eqp)) { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "Long parameter " + name + " should be equal to " + params.get(eqp)); + // Request parameter is stored as string. + // Need to convert it beforehand. + try { + Long _eqp = new Long(Long.parseLong((String) params.get(eqp))); + if (!value.equals(_eqp)) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + } catch (NumberFormatException nfe) { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "Long parameter " + name + ": " + eqp + " is no long", + nfe); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + } + + // Validate wheter param is at least min + if (min != null) { + if (getLogger().isDebugEnabled()) + getLogger().debug("Long parameter " + name + " should be at least " + min); + + if (min.compareTo(value) > 0) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.TOOSMALL); + } + } + + // Validate wheter param is at most max + if (max != null) { + if (getLogger().isDebugEnabled()) + getLogger().debug("Long parameter " + name + " should be at most " + max); + if (max.compareTo(value) < 0) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.TOOLARGE); + } + } + } + return new ValidatorActionHelper(value); + } + + /** + * Validates nullability and default value for given parameter. If given + * constraints are not null they are validated as well. + */ + private ValidatorActionHelper validateDouble( + String name, + Configuration constraints, + Configuration conf, + Map params, + boolean is_string, + Object param) { + + boolean nullable = getNullable(conf, constraints); + Double value = null; + Double dflt = getDoubleValue(getDefault(conf, constraints), true); + + if (getLogger().isDebugEnabled()) + getLogger().debug( + "Validating double parameter " + + name + + " (encoded in a string: " + + is_string + + ")"); + try { + value = getDoubleValue(param, is_string); + } catch (Exception e) { + // Unable to parse double + return new ValidatorActionHelper(value, ValidatorActionResult.ERROR); + } + if (value == null) { + if (getLogger().isDebugEnabled()) + getLogger().debug("double parameter " + name + " is null"); + if (!nullable) { + return new ValidatorActionHelper(value, ValidatorActionResult.ISNULL); + } else { + return new ValidatorActionHelper(dflt); + } + } + if (constraints != null) { + Double eq = getAttributeAsDouble(constraints, "equals-to", null); + String eqp = constraints.getAttribute("equals-to-param", ""); + + Double min = getAttributeAsDouble(conf, "min", null); + min = getAttributeAsDouble(constraints, "min", min); + + Double max = getAttributeAsDouble(conf, "max", null); + max = getAttributeAsDouble(constraints, "max", max); + + // Validate whether param is equal to constant + if (eq != null) { + if (getLogger().isDebugEnabled()) + getLogger().debug("Double parameter " + name + " should be equal to " + eq); + + if (!value.equals(eq)) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + } + + // Validate whether param is equal to another param + // FIXME: take default value of param being compared with into + // account? + if (!"".equals(eqp)) { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "Double parameter " + name + " should be equal to " + params.get(eqp)); + // Request parameter is stored as string. + // Need to convert it beforehand. + try { + Double _eqp = new Double(Double.parseDouble((String) params.get(eqp))); + if (!value.equals(_eqp)) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + } catch (NumberFormatException nfe) { + if (getLogger().isDebugEnabled()) + getLogger().debug( + "Double parameter " + name + ": " + eqp + " is no double", + nfe); + return new ValidatorActionHelper(value, ValidatorActionResult.NOMATCH); + } + } + + // Validate wheter param is at least min + if (min != null) { + if (getLogger().isDebugEnabled()) + getLogger().debug("Double parameter " + name + " should be at least " + min); + if (0 > value.compareTo(min)) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.TOOSMALL); + } + } + + // Validate wheter param is at most max + if (max != null) { + if (getLogger().isDebugEnabled()) + getLogger().debug("Double parameter " + name + " should be at most " + max); + if (0 < value.compareTo(max)) { + if (getLogger().isDebugEnabled()) + getLogger().debug("and it is not"); + return new ValidatorActionHelper(value, ValidatorActionResult.TOOLARGE); + } + } + } + return new ValidatorActionHelper(value); + } + + /** + * Returns the parsed Double value. + */ + private Double getDoubleValue(Object param, boolean is_string) + throws ClassCastException, NumberFormatException { + + /* convert param to double */ + if (is_string) { + String tmp = getStringValue(param); + if (tmp == null) { + return null; + } + return new Double(tmp); + } else { + return (Double) param; + } + } + + /** + * Returns the parsed Long value. + */ + private Long getLongValue(Object param, boolean is_string) + throws ClassCastException, NumberFormatException { + + /* convert param to long */ + if (is_string) { + String tmp = getStringValue(param); + if (tmp == null) { + return null; + } + return Long.decode(tmp); + } else { + return (Long) param; + } + } + + /** + * Returns string + * @throws ClassCastException if param is not a String object + */ + private String getStringValue(Object param) throws ClassCastException { + + /* convert param to string */ + String value = (String) param; + if (value != null && "".equals(value.trim())) { + value = null; + } + return value; + } + + /** + * Returns the value of 'nullable' attribute from given configuration or + * from given constraints, value present in constraints takes precedence, + * false when attribute is not present in either of them. + */ + private boolean getNullable(Configuration conf, Configuration cons) { + /* check nullability */ + try { + String tmp = cons.getAttribute("nullable"); + return BooleanUtils.toBoolean(tmp); + } catch (Exception e) { + String tmp = "no"; + if (conf != null) { + tmp = conf.getAttribute("nullable", "no"); + } + return BooleanUtils.toBoolean(tmp); + } + } + + /** + * Returns the default value from given configuration or constraints. + * Value present in constraints takes precedence, null is returned when no + * default attribute is present in eiher of them. + */ + private String getDefault(Configuration conf, Configuration cons) { + String dflt = ""; + try { + dflt = cons.getAttribute("default"); + } catch (Exception e) { + if (conf != null) + dflt = conf.getAttribute("default", ""); + } + if ("".equals(dflt.trim())) { + dflt = null; + } + return dflt; + } + + /** + * Replacement for Avalon's Configuration.getAttributeAsLong + * because that one doesn't take Long but long and + * thus won't take null as parameter value for + * default. + * + * @param conf Configuration + * @param name Parameter's name + * @param dflt Default value + * @return Parameter's value in configuration or + * dflt if parameter is not set or couldn't be + * converted to a Long + * @throws NumberFormatException if conversion fails + */ + private Long getAttributeAsLong(Configuration conf, String name, Long dflt) + throws NumberFormatException { + try { + return new Long(conf.getAttribute(name)); + } catch (ConfigurationException e) { + return dflt; + } + } + + /** + * Addition to Avalon's Configuration.getAttributeAsFloat + * because that one does only deal with float. + * + * @param conf Configuration + * @param name Parameter's name + * @param dflt Default value + * @return Parameter's value in configuration or + * dflt if parameter is not set or couldn't be + * converted to a Double + * @throws NumberFormatException if conversion fails + */ + private Double getAttributeAsDouble(Configuration conf, String name, Double dflt) + throws NumberFormatException { + try { + return new Double(conf.getAttribute(name)); + } catch (ConfigurationException e) { + return dflt; + } + } + + /** + * Create an index map to an array of configurations by their name + * attribute. An empty array results in an empty map. + * + * @param descriptor + * @return index map or empty map + */ + protected Map indexConfiguration(Configuration[] descriptor) { + if (descriptor == null) + return new HashMap(); + Map result = new HashMap((descriptor.length > 0) ? descriptor.length * 2 : 5); + for (int i = descriptor.length - 1; i >= 0; i--) { + String name = descriptor[i].getAttribute("name", ""); + result.put(name, descriptor[i]); + } + return result; + } + + /** + * Recursively resolve constraint sets that may "include" other constraint + * sets and return a collection of all parameters to validate. + * + * @param valsetstr + * @param consets + * @return collection of all parameters to validate + */ + protected Collection resolveConstraints(String valsetstr, Map consets) { + /* get the list of params to be validated */ + Vector rules = new Vector(); + Configuration[] set = ((Configuration) consets.get(valsetstr)).getChildren("validate"); + for (int j = 0; j < set.length; j++) { + rules.add(set[j]); + } + set = ((Configuration) consets.get(valsetstr)).getChildren("include"); + for (int j = 0; j < set.length; j++) { + Collection tmp = resolveConstraints(set[j].getAttribute("name", ""), consets); + rules.addAll(tmp); + } + return rules; + } + + /** + * Checks the default setting for reloading the descriptor file. + * @return boolean + */ + protected boolean isDescriptorReloadable() { + // read global parameter settings + boolean reloadable = DESCRIPTOR_RELOADABLE_DEFAULT; + if (this.settings.containsKey("reloadable")) { + reloadable = Boolean.valueOf((String) this.settings.get("reloadable")).booleanValue(); + } + return reloadable; + } + + /** + * Get list of params to be validated from sitemap parameter and + * isolates the parameter names from the comma separated list. + * + */ + protected Collection getSetOfParameterNamesFromSitemap(String valstr, Map desc) { + String[] rparams = null; + Set set = new HashSet(20); + if (!"*".equals(valstr.trim())) { + rparams = StringUtils.split(valstr, ","); + if (rparams != null) { + for (int i = rparams.length - 1; i >= 0; i--) { + set.add(desc.get(rparams[i])); + } + } + } else { + // validate _all_ parameters + set = desc.entrySet(); + } + return set; + } + + /** + * Validate all parameters in the set with the constraints contained in + * desc and the values from params. Validation details are in resultMap and + * successful validated parameters in resultMap. + * + * @param desc + * @param actionMap + * @param resultMap + * @param set + * @param params + * @param isString + * @return boolean all parameters ok or not + */ + protected boolean validateSetOfParameters( + Map desc, + Map actionMap, + Map resultMap, + Collection set, + Map params, + boolean isString) { + + boolean allOK = true; + ValidatorActionHelper result; + String name; + String rule = null; + for (Iterator i = set.iterator(); i.hasNext();) { + Configuration constr = (Configuration) i.next(); + name = constr.getAttribute("name", null); + rule = constr.getAttribute("rule", name); + result = validateParameter(name, rule, constr, desc, params, isString); + if (!result.isOK()) { + if (getLogger().isDebugEnabled()) + getLogger().debug("Validation failed for parameter " + name); + allOK = false; + } + actionMap.put(name, result.getObject()); + resultMap.put(name, result.getResult()); + } + return allOK; + } + + /** + * Add success indicator to resulting maps and clear actionMap if unsuccessful. + * Results are stored as request attributes. + * + * @param objectModel the object model + * @param actionMap a Map containing validated parameters + * @param resultMap a Map containing validation results + * @param allOK a boolean indicating if all validations were successful + * @return actionMap if allOK or null otherwise + */ + protected Map setResult(Map objectModel, Map actionMap, Map resultMap, boolean allOK) { + if (!allOK) { + // if any validation failed return an empty map + actionMap = null; + resultMap.put("*", ValidatorActionResult.ERROR); + if (getLogger().isDebugEnabled()) + getLogger().debug("All form params validated. An error occurred."); + } else { + resultMap.put("*", ValidatorActionResult.OK); + if (getLogger().isDebugEnabled()) + getLogger().debug("All form params successfully validated"); + } + // store validation results in request attribute + ObjectModelHelper.getRequest(objectModel).setAttribute( + FORMVALIDATOR_PATH, + resultMap); + //return Collections.unmodifiableMap (actionMap); + return actionMap; + } + + /** + * Load the descriptor containing the constraints. + * @param resolver + * @param parameters + * @return a Configuration containing the constraints or null if a problem occurred. + */ + protected Configuration getDescriptor( + SourceResolver resolver, + Map objectModel, + Parameters parameters) { + Configuration conf = null; + try { + conf = + this.getConfiguration( + parameters.getParameter("descriptor", (String) this.settings.get("descriptor")), + resolver, + parameters.getParameterAsBoolean("reloadable", isDescriptorReloadable())); + } catch (ConfigurationException e) { + if (this.getLogger().isWarnEnabled()) + this.getLogger().warn("Exception reading descriptor: ", e); + } + return conf; + } + +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/AbstractValidatorAction.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/Action.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/Action.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/Action.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/Action.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.SourceResolver; + +import java.util.Map; + +/** + * + * @author Giacomo Pati + * @version CVS $Id: Action.java 55383 2004-10-23 15:10:46Z cziegeler $ + */ +public interface Action { + + String ROLE = Action.class.getName(); + + /** + * Controls the processing against some values of the + * Dictionary objectModel and returns a + * Map object with values used in subsequent + * sitemap substitution patterns. + * + * NOTE: This interface is designed so that implentations can be ThreadSafe. + * When an action is ThreadSafe, only one instance serves all requests : this + * reduces memory usage and avoids pooling. + * + * @param resolver The SourceResolver in charge + * @param objectModel The Map with object of the + * calling environment which can be used + * to select values this controller may need + * (ie Request, Response). + * @param source A source String to the Action + * @param parameters The Parameters for this invocation + * @return Map The returned Map object with + * sitemap substitution values which can be used + * in subsequent elements attributes like src= + * using a xpath like expression: src="mydir/{myval}/foo" + * If the return value is null the processing inside + * the element of the sitemap will + * be skipped. + * @exception Exception Indicates something is totally wrong + */ + Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) + throws Exception; +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/Action.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ClearCacheAction.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ClearCacheAction.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ClearCacheAction.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ClearCacheAction.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.caching.Cache; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.SourceResolver; + +import java.util.Map; + +/** + * Simple action which ensures the cache is cleared of all + * cached results + * + * @author Michael Melhem + * @version CVS $Id: ClearCacheAction.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public class ClearCacheAction extends ServiceableAction implements ThreadSafe { + + public Map act(Redirector redirector, + SourceResolver resolver, + Map objectModel, + String src, + Parameters par + ) throws Exception { + final String cacheRole = par.getParameter("cache-role", Cache.ROLE); + Cache cache = null; + + try { + cache = (Cache)this.manager.lookup(cacheRole); + cache.clear(); + return EMPTY_MAP; + } catch (Exception ex) { + if (this.getLogger().isDebugEnabled()) { + getLogger().debug("Exception while trying to clear Cache with role " + cacheRole, ex); + } + return null; + } finally { + this.manager.release( cache ); + } + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ClearCacheAction.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ClearPersistentStoreAction.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ClearPersistentStoreAction.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ClearPersistentStoreAction.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ClearPersistentStoreAction.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.SourceResolver; +import org.apache.excalibur.store.Store; + +import java.util.Map; + +/** + * Simple action which ensures the persistent store is cleared. + * + * @author Gerhard Froehlich + * @version CVS $Id: ClearPersistentStoreAction.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public class ClearPersistentStoreAction extends ServiceableAction implements ThreadSafe { + + public Map act(Redirector redirector, + SourceResolver resolver, + Map objectModel, + String src, + Parameters par + ) throws Exception { + if ( this.manager.hasService( Store.PERSISTENT_STORE) ) { + final Store store_persistent = (Store)this.manager.lookup(Store.ROLE); + + try { + store_persistent.clear(); + return EMPTY_MAP; + } catch (Exception ex) { + getLogger().debug("Exception while trying to Clearing the Store", ex); + return null; + } finally { + this.manager.release( store_persistent ); + } + } else { + getLogger().info("Unable to clear persistent store as no persistent store is configured."); + return null; + } + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ClearPersistentStoreAction.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ConfigurableServiceableAction.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ConfigurableServiceableAction.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ConfigurableServiceableAction.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ConfigurableServiceableAction.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; + +/** + * The ConfigurableServiceableAction will allow any Action + * that extends this to access SitemapComponents. + * + * Basically a copy of {@link ServiceableAction} that inherits from + * {@link AbstractConfigurableAction}. + * + * @author Giacomo Pati + * @author Christian Haul + * @version CVS $Id: ConfigurableServiceableAction.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public abstract class ConfigurableServiceableAction + extends AbstractConfigurableAction implements Serviceable { + + /** The service manager instance */ + protected ServiceManager manager; + + /* (non-Javadoc) + * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) + */ + public void service(ServiceManager manager) throws ServiceException { + this.manager = manager; + } + +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ConfigurableServiceableAction.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ConfigurationHelper.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ConfigurationHelper.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ConfigurationHelper.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ConfigurationHelper.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,27 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.configuration.Configuration; + +/** + * + * @version CVS $Id: ConfigurationHelper.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public class ConfigurationHelper { + public long lastModified = 0; + public Configuration configuration = null; +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/ConfigurationHelper.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/CopySourceAction.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/CopySourceAction.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/CopySourceAction.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/CopySourceAction.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,108 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.components.source.impl.PartSource; +import org.apache.cocoon.environment.Redirector; +import org.apache.excalibur.source.ModifiableSource; +import org.apache.excalibur.source.Source; +import org.apache.excalibur.source.SourceResolver; +import org.apache.excalibur.source.TraversableSource; + +/** + * The CopySourceAction copies the content of it's "src" attribute to its "dest" parameter. + * The destination must of course resolve to a WriteableSource + *

+ * Example : + *

+ *   <map:act type="copy-source" src="cocoon://pipeline.xml">
+ *     <map:parameter name="dest" value="context://WEB-INF/data/file.xml"/>
+ *     .../...
+ *   </map:act>
+ *
+ * + * @author Sylvain Wallez + * @version CVS $Id: CopySourceAction.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public class CopySourceAction extends ServiceableAction implements ThreadSafe +{ + + private SourceResolver resolver; + + public void service(ServiceManager manager) throws ServiceException { + super.service(manager); + this.resolver = (SourceResolver)manager.lookup(SourceResolver.ROLE); + } + + public Map act(Redirector redirector, org.apache.cocoon.environment.SourceResolver oldResolver, Map objectModel, String source, Parameters par) + throws Exception { + + // Get source and destination Sources + Source src = resolver.resolveURI(source); + Source dest = resolver.resolveURI(par.getParameter("dest")); + + // Check that dest is writeable + if (! (dest instanceof ModifiableSource)) { + throw new IllegalArgumentException("Non-writeable URI : " + dest.getURI()); + } + + if (dest instanceof TraversableSource) { + TraversableSource trDest = (TraversableSource) dest; + if (trDest.isCollection()) { + if (src instanceof TraversableSource) { + dest = trDest.getChild(((TraversableSource)src).getName()); + } else if (src instanceof PartSource){ + // FIXME : quick hack to store "upload://xxx" sources into directories + // it would be better for the PartSource to be Traversable, or to + // create a new "NamedSource" interface + dest = trDest.getChild(((PartSource)src).getPart().getFileName()); + } + } + } + + ModifiableSource wdest = (ModifiableSource)dest; + + // Get streams + InputStream is = src.getInputStream(); + OutputStream os = wdest.getOutputStream(); + + // And transfer all content. + try { + byte[] buffer = new byte[1024]; + int len; + while ((len = is.read(buffer, 0, buffer.length)) > 0) { + os.write(buffer, 0, len); + } + os.close(); + } catch(Exception e) { + if (wdest.canCancel(os)) { + wdest.cancel(os); + } + } finally { + is.close(); + } + // Success ! + return EMPTY_MAP; + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/CopySourceAction.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/FormValidatorAction.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/FormValidatorAction.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/FormValidatorAction.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/FormValidatorAction.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,84 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.thread.ThreadSafe; + +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Request; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * This is the action used to validate Request parameters. + * The parameters are described via the external xml + * file (its format is defined in AbstractValidatorAction). + * @see org.apache.cocoon.acting.AbstractValidatorAction + * + * @author Martin Man + * @author Christian Haul + * @version CVS $Id: FormValidatorAction.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public class FormValidatorAction extends AbstractValidatorAction implements ThreadSafe { + + /** + * Reads parameter values from request parameters for all parameters + * that are contained in the active constraint list. If a parameter + * has multiple values, all are stored in the resulting map. + * + * @param objectModel the object model + * @param set a collection of parameter names + * @return HashMap of required parameters + */ + protected HashMap createMapOfParameters(Map objectModel, Collection set) { + String name; + HashMap params = new HashMap(set.size()); + // put required params into hash + Request request = ObjectModelHelper.getRequest(objectModel); + for (Iterator i = set.iterator(); i.hasNext();) { + name = ((Configuration) i.next()).getAttribute("name", "").trim(); + Object[] values = request.getParameterValues(name); + if (values != null) { + switch (values.length) { + case 0 : + params.put(name, null); + break; + case 1 : + params.put(name, values[0]); + break; + default : + params.put(name, values); + } + } else { + params.put(name, values); + } + } + return params; + } + + /* (non-Javadoc) + * @see org.apache.cocoon.acting.AbstractValidatorAction#isStringEncoded() + */ + boolean isStringEncoded() { + return true; + } + + +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/FormValidatorAction.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HelloAction.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HelloAction.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HelloAction.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HelloAction.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.Request; +import org.apache.cocoon.environment.Session; +import org.apache.cocoon.environment.SourceResolver; + +import java.util.Map; + +/** + * A simple Action that tracks if a Session object + * has been created or not. + * + * @author Giacomo Pati + * @version CVS $Id: HelloAction.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public class HelloAction extends ServiceableAction implements ThreadSafe { + + /** + * A simple Action that logs if the Session object + * has been created + */ + public Map act (Redirector redirector, SourceResolver resolver, Map objectModel, String src, Parameters par) throws Exception { + Request request = ObjectModelHelper.getRequest(objectModel); + if (request != null) { + Session session = request.getSession (false); + + if (session != null) { + if (session.isNew()) { + getLogger().debug("Session is new"); + } else { + getLogger().debug("Session is old"); + } + } else { + getLogger().debug("A session object was not created"); + } + } + + return null; + } +} + + + Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HelloAction.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HttpCacheAction.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HttpCacheAction.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HttpCacheAction.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HttpCacheAction.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,150 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.Response; +import org.apache.cocoon.environment.SourceResolver; +import org.apache.commons.lang.time.DateUtils; +import org.apache.commons.lang.time.FastDateFormat; + +import java.util.Calendar; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * This action adds the Last-Modified, Expires and + * Cache-Control HTTP headers to the response. + * + *

+ * This action will add the Last-Modified header to the response + * with the time in which the request was executed, and an Expires + * header at a specified time difference. Additionally, it will provide an + * extra Cache-Control indicating the maximum age of the request + * as a delta between the expiration and last modification dates. + *

+ *

+ * This is useful (for example) when Cocoon is proxyied by a Web Server such + * as Apache HTTPD running mod_cache, to indicate for each request how long + * the output should be cached for. + *

+ *

+ * To configure the difference between Last-Modified and + * Expires this Action can be configured specifying + * days, hours, minutes, and seconds in this way: + *

+ *
+ * <map:action>s
+ *   <map:action name="xyz" src="org.apache.cocoon.acting.HttpCacheAction>"
+ *     <days>1</day>s
+ *     <hours>2</hour>s
+ *     <minutes>3</minute>s
+ *     <seconds>4</second>s
+ *   </map:actio>n
+ * </map:action>s
+ * 
+ *

+ * Using this example configuration, the Expires header will + * specify a date one day, two hours, three minutes and four seconds after + * the time of the request (which will be in Last-Modified). + *

+ *

+ * Note that if any of the parameters mentioned above is zero or + * less than zero this action will modify the behaviour of the + * resulting Cache-Control header to emit the keyword + * no-cache. + *

+ *

+ * This action will also return the three headers it added as sitemap + * parameters called last-modified, expires and + * cache-control (all lowercase). + *

+ * + * @author Pier Fumagalli + * @version CVS $Id: HttpCacheAction.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public class HttpCacheAction extends AbstractConfigurableAction implements ThreadSafe { + + private FastDateFormat formatter = null; + int days = 0; + int hours = 0; + int minutes = 0; + int seconds = 0; + + public void configure(Configuration configuration) + throws ConfigurationException { + super.configure(configuration); + + // RFC-822 Date with a GMT based time zone + this.formatter = FastDateFormat.getInstance("EEE, dd MMM yyyy kk:mm:ss zzz", DateUtils.UTC_TIME_ZONE); + this.days = configuration.getChild("days").getValueAsInteger(0); + this.hours = configuration.getChild("hours").getValueAsInteger(0); + this.minutes = configuration.getChild("minutes").getValueAsInteger(0); + this.seconds = configuration.getChild("seconds").getValueAsInteger(0); + } + + public Map act(Redirector redirector, SourceResolver resolver, + Map objectModel, String source, Parameters parameters) + throws Exception { + Response response = ObjectModelHelper.getResponse(objectModel); + Calendar calendar = Calendar.getInstance(DateUtils.UTC_TIME_ZONE); + Map values = new HashMap(3); + + /* Get the current time and output as the last modified header */ + String value = this.formatter.format(calendar); + long maxage = calendar.getTime().getTime(); + response.setHeader("Last-Modified", value); + values.put("last-modified", value); + + /* Advance the time as much as required */ + calendar.add(Calendar.DATE, this.days); + calendar.add(Calendar.HOUR, this.hours); + calendar.add(Calendar.MINUTE, this.minutes); + calendar.add(Calendar.SECOND, this.seconds); + + /* Recalculate time and age to see what changed */ + maxage = calendar.getTime().getTime() - maxage; + + /* If we got more than one second everything is quite normal */ + if (maxage > 1000) { + value = this.formatter.format(calendar); + response.setHeader("Expires", value); + values.put("expires", value); + + value = "max-age=" + Long.toString(maxage / 1000l); + response.setHeader("Cache-Control", value); + values.put("cache-control", value); + + /* If we got less than one second (even negatives) no cache */ + } else { + /* We still hold the old value from Last-Modified here */ + response.setHeader("Expires", value); + values.put("expires", value); + + response.setHeader("Cache-Control", "no-cache"); + values.put("cache-control", "no-cache"); + } + + /* Return the headers */ + return(Collections.unmodifiableMap(values)); + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HttpCacheAction.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HttpHeaderAction.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HttpHeaderAction.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HttpHeaderAction.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HttpHeaderAction.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,75 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.Response; +import org.apache.cocoon.environment.SourceResolver; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * This action adds HTTP headers to the response. + * + * @author Donald Ball + * @version CVS $Id: HttpHeaderAction.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public class HttpHeaderAction +extends AbstractConfigurableAction +implements ThreadSafe { + + /** + * Stores keys of global configuration. + */ + private Object[] defaults = {}; + + public void configure(Configuration conf) throws ConfigurationException { + super.configure(conf); + this.defaults = super.settings.keySet().toArray(); + } + + public Map act(Redirector redirector, SourceResolver resolver, + Map objectModel, String source, Parameters parameters) + throws Exception { + final Map results = new HashMap(); + + final Response response = ObjectModelHelper.getResponse(objectModel); + + // Process local configuration parameters + final String[] names = parameters.getNames(); + for (int i = 0; i < names.length; i++) { + response.setHeader(names[i],parameters.getParameter(names[i])); + results.put(names[i], parameters.getParameter(names[i])); + } + + // Process global defaults, that are not overridden + for (int i = 0; i < defaults.length; i++) { + if (!results.containsKey(this.defaults[i])) { + response.setHeader((String) this.defaults[i], (String) this.settings.get(defaults[i])); + results.put(this.defaults[i], this.settings.get(defaults[i])); + } + } + + return Collections.unmodifiableMap(results); + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/HttpHeaderAction.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/InputModuleAction.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/InputModuleAction.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/InputModuleAction.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/InputModuleAction.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,129 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.acting; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.thread.ThreadSafe; + +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.SourceResolver; +import org.apache.cocoon.components.modules.input.InputModuleHelper; + +import org.apache.commons.lang.BooleanUtils; + +import java.util.HashMap; +import java.util.Map; + +/** + * Simple helper action to allow passing sitemap variables to InputModules. + * Sitemap evaluation of input modules using the curly bracket syntax e.g. + * {defaults:skin} suffers from the fact that it is not + * possible to use a sitemap variable as part of the invocation like + * {defaults:{1})}. This action takes three parameters, the name + * of the input module, the attribute name, and whether to call getAttribute() or + * getAttributeValues(). Thus the above becomes + *
+ *   <map:act type="inputmodule">
+ *     <map:parameter name="module" value="defaults"/>
+ *     <map:parameter name="attribute" value="{1}"/>
+ *     <map:parameter name="single-value" value="false"/>
+ * 
+ *     <!-- do something with the result: "{1}" -->
+ * 
+ *   </map:act>
+ * 
+ * The action invokes the + * {@link org.apache.cocoon.components.modules.input.InputModule#getAttributeValues(String, Configuration, Map) getAttributeValues()} + * method and returns all results numbered from "0". If no result exists, + * "null" is returned and the nested block is skipped. + * The name of the input module to use may be preconfigured when + * declaring the action in your sitemap: + *
+ *     <map:action name="inputmodule" 
+ *                    src="org.apache.cocoon.acting.InputModuleAction" 
+ *                    logger="sitemap.action.inputmodule">
+ *        <module>defaults</module>
+ *        <single-value>false</single-value>
+ *     </map:action>
+ * 
+ * + * + * @see org.apache.cocoon.components.modules.input.InputModule + * + * @author Christian Haul + * @version CVS $Id: InputModuleAction.java 123777 2004-12-31 09:18:04Z antonio $ + */ +public class InputModuleAction extends ConfigurableServiceableAction implements ThreadSafe { + + /* (non-Javadoc) + * @see org.apache.cocoon.acting.Action#act(org.apache.cocoon.environment.Redirector, org.apache.cocoon.environment.SourceResolver, java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters) + */ + public Map act(Redirector redirector, SourceResolver resolver, + Map objectModel, String source, Parameters parameters) + throws Exception { + + HashMap map = null; + Configuration conf = null; + String module = parameters.getParameter("module", (String) this.settings.get("module")); + String attrib = + parameters.getParameter("attribute", (String) this.settings.get("attribute")); + boolean single = + parameters.getParameterAsBoolean( + "single-value", + ((Boolean) this.settings.get("single-value")).booleanValue()); + + if (module != null && attrib != null) { + InputModuleHelper mhelper = new InputModuleHelper(); + mhelper.setup(manager); + Object[] result = null; + if (!single) { + result = mhelper.getAttributeValues(objectModel, conf, module, attrib, null); + } else { + Object tmp = mhelper.getAttribute(objectModel, conf, module, attrib, null); + if (tmp != null){ + result = new Object[1]; + result[0] = tmp; + } + } + mhelper.releaseAll(); + + if (result != null && result.length != 0) { + map = new HashMap(); + for (int i = 0; i < result.length; i++) { + map.put(Integer.toString(i), result[i]); + } + } + } else { + if (getLogger().isErrorEnabled()) { + getLogger().error( + "Parameter is missing: module=" + module + " attribute=" + attrib); + } + } + return map; + } + + /* (non-Javadoc) + * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration) + */ + public void configure(Configuration conf) throws ConfigurationException { + super.configure(conf); + String tmp = (String) this.settings.get("single-value", "false"); + this.settings.put("single-value", BooleanUtils.toBooleanObject(tmp)); + } + +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/acting/InputModuleAction.java ------------------------------------------------------------------------------ svn:eol-style = native