/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.cocoon.Constants; 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. * * <h3>Variant 1</h3> * <pre> * <map:act type="validator"> * <parameter name="descriptor" value="context://descriptor.xml"> * <parameter name="validate" value="username,password"> * </map:act> * </pre> * * <p>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 <code>*</code>, * all parameters in the file will be validated.</p> * * <h3>Variant 2</h3> * <pre> * <map:act type="validator"> * <parameter name="descriptor" value="context://descriptor.xml"> * <parameter name="constraint-set" value="is-logged-in"> * </map:act> * </pre> * * <p>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.</p> * * <p>For even more powerful validation, constraints can be grouped * and used independently of the parameter name. If a validate element * has a <code>rule</code> attribute, it uses the parameter with that * name as a rule template and validates the parameter from the * <code>name</code> attribute with that rule.</p> * * <p>This action returns null when validation fails, otherwise it * provides all validated parameters to the sitemap via {name} * expression.</p> * * <p>In addition a request attribute * <code>org.apache.cocoon.acting.FormValidatorAction.results</code> * contains the validation results in both cases and make it available * to XSPs. 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.</p> * * <pre> * <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> * </pre> * * <h3>The types recognized by validator and their attributes</h3> * <table border="1"> * <tr> * <td><b>string</b></td><td>nullable="yes|no" default="str"</td> * </tr> * <tr> * <td><b>long</b></td><td>nullable="yes|no" default="123123"</td> * </tr> * <tr> * <td><b>double</b></td><td>nullable="yes|no" default="0.5"</td> * </tr> * </table> * * <p>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).</p> * * <h3>Constraints</h3> * <table border="1"> * <tr> * <td>matches-regex</td><td>POSIX regular expression</td> * </tr> * <tr> * <td>min-len</td><td>positive integer</td> * </tr> * <tr> * <td>max-len</td><td>positive integer</td> * </tr> * <tr> * <td>min</td><td>Double / Long</td> * </tr> * <tr> * <td>max</td><td>Double / Long</td> * </tr> * </table> * * <p>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.</p> * * <p>Values in parameter arrays are validated individually and the * worst error is reported back.</p> * * <h3>The attributes recognized in "constraint-set"</h3> * <table> * <tr> * <td>equals-to-param</td><td>parameter name</td> * </tr> * <tr> * <td>equals-to</td><td>string constant</td> * </tr> * </table> * @author <a href="mailto:Martin.Man@seznam.cz">Martin Man</a> * @author <a href="mailto:haul@apache.org">Christian Haul</a> * @version CVS $Id$ */ public abstract class AbstractValidatorAction extends AbstractComplementaryConfigurableAction { /** * 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 boolean */ 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.getStatementLocation(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 <code>Long</code> but long and * thus won't take <code>null</code> as parameter value for * default. * * @param conf Configuration * @param name Parameter's name * @param dflt Default value * @return Parameter's value in <code>configuration</code> or * <code>dflt</code> if parameter is not set or couldn't be * converted to a <code>Long</code> * @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 <code>float</code>. * * @param conf Configuration * @param name Parameter's name * @param dflt Default value * @return Parameter's value in <code>configuration</code> or * <code>dflt</code> if parameter is not set or couldn't be * converted to a <code>Double</code> * @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 = Constants.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( Constants.XSP_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; } }