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.
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.
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.
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 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.
| Method from org.apache.cocoon.acting.AbstractValidatorAction Detail: |
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);
}
|
abstract protected HashMap createMapOfParameters(Map objectModel,
Collection set)
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. |
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;
}
Load the descriptor containing the constraints. |
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;
}
Get list of params to be validated from sitemap parameter and
isolates the parameter names from the comma separated list. |
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;
}
Create an index map to an array of configurations by their name
attribute. An empty array results in an empty map. |
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;
}
Checks the default setting for reloading the descriptor file. |
abstract boolean isStringEncoded()
Are parameters encoded as strings? |
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;
}
Recursively resolve constraint sets that may "include" other constraint
sets and return a collection of all parameters to validate. |
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;
}
Add success indicator to resulting maps and clear actionMap if unsuccessful.
Results are stored as request attributes. |
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. |
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;
}
}
Try to validate given parameter. |
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;
}
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. |
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;
}
}
Validate a single parameter value. |