You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by cz...@apache.org on 2002/12/03 13:31:36 UTC
cvs commit: xml-cocoon2/src/blocks/session-fw/java/org/apache/cocoon/webapps/session/acting SessionFormAction.java
cziegeler 2002/12/03 04:31:35
Modified: src/blocks/session-fw/conf session-act.xmap
src/blocks/session-fw/java/org/apache/cocoon/webapps/session/transformation
SessionPostTransformer.java
Added: src/blocks/session-fw/java/org/apache/cocoon/webapps/session/acting
SessionFormAction.java
Log:
Adding simple validation. Submitted by Guido Casper (gcasper@s-und-n.de)
Revision Changes Path
1.2 +2 -0 xml-cocoon2/src/blocks/session-fw/conf/session-act.xmap
Index: session-act.xmap
===================================================================
RCS file: /home/cvs/xml-cocoon2/src/blocks/session-fw/conf/session-act.xmap,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- session-act.xmap 27 Sep 2002 09:05:11 -0000 1.1
+++ session-act.xmap 3 Dec 2002 12:31:35 -0000 1.2
@@ -6,4 +6,6 @@
<map:action name="session"
src="org.apache.cocoon.webapps.session.acting.SessionAction"/>
+ <map:action name="session-form"
+ src="org.apache.cocoon.webapps.session.acting.SessionFormAction"/>
</xmap>
1.3 +119 -10 xml-cocoon2/src/blocks/session-fw/java/org/apache/cocoon/webapps/session/transformation/SessionPostTransformer.java
Index: SessionPostTransformer.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/src/blocks/session-fw/java/org/apache/cocoon/webapps/session/transformation/SessionPostTransformer.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- SessionPostTransformer.java 8 Oct 2002 14:43:19 -0000 1.2
+++ SessionPostTransformer.java 3 Dec 2002 12:31:35 -0000 1.3
@@ -51,17 +51,28 @@
package org.apache.cocoon.webapps.session.transformation;
import java.io.IOException;
+import java.io.StringBufferInputStream;
import java.util.Map;
+import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceParameters;
+import org.apache.excalibur.source.SourceException;
import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
+import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
+import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.cocoon.environment.Session;
import org.apache.cocoon.webapps.session.SessionConstants;
+import org.apache.cocoon.acting.ValidatorActionResult;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
/**
* This is the session post transformer. It does all the setting and
@@ -105,6 +116,7 @@
public static final String INPUTXML_PATH_ATTRIBUTE = "path";
public static final String INPUTXML_NAME_ATTRIBUTE = "name";
public static final String INPUTXML_TYPE_ATTRIBUTE = "type"; // optional
+ public static final String INPUTXML_VALIDATIONRESULT_ATTRIBUTE = "valresult";
/** The form element */
public static final String FORM_ELEMENT = "form";
@@ -115,6 +127,11 @@
/** The form content element */
public static final String FORM_CONTENT_ELEMENT = "content";
+ /** The form validation rules */
+ public static final String FORM_VALIDATION_ELEMENT = "validate";
+ public static final String FORM_VALIDATION_SOURCE_ATTRIBUTE = "src";
+ public static final String FORM_VALIDATESET_ELEMENT = "validate-set";
+
/** State: no element parsed */
private static final int STATE_OUTSIDE = 0;
/** State: form element */
@@ -126,8 +143,8 @@
/** The current form name */
private String formName;
- /** The unique form number */
- private static int currentFormNumber = 0;
+ /** The validation results */
+ private Map validationResultMap;
public void setupTransforming()
throws ProcessingException, SAXException, IOException {
@@ -202,6 +219,15 @@
"CDATA", attr.getValue(INPUTXML_TYPE_ATTRIBUTE));
}
+ ValidatorActionResult validationResult = null;
+ if (validationResultMap != null && validationResultMap.get(fieldname) != null) {
+ validationResult = (ValidatorActionResult)validationResultMap.get(fieldname);
+ newattr.addAttribute("",
+ INPUTXML_VALIDATIONRESULT_ATTRIBUTE,
+ INPUTXML_VALIDATIONRESULT_ATTRIBUTE,
+ "CDATA", validationResult.toString());
+ }
+
super.startTransformingElement("", name, name, newattr); // remove namespace
this.startRecording();
@@ -224,7 +250,19 @@
// Element form content
} else if (name.equals(FORM_CONTENT_ELEMENT) == true
&& this.state == STATE_FORM) {
- // ignore this
+ // get validation results to be used for inputxml elements
+ validationResultMap = (Map)this.getSessionManager().getSession(true).
+ getAttribute(this.formName + "validation-result");
+
+ // Element form validation rules
+ } else if (name.equals(FORM_VALIDATION_ELEMENT) == true
+ && this.state == STATE_FORM) {
+ this.startRecording();
+ if (attr.getValue(FORM_VALIDATION_SOURCE_ATTRIBUTE) != null) {
+ stack.push(attr.getValue(FORM_VALIDATION_SOURCE_ATTRIBUTE));
+ } else {
+ stack.push("EMPTY");
+ }
} else {
super.startTransformingElement(uri, name, raw, attr);
@@ -310,12 +348,7 @@
&& this.state == STATE_FORM) {
String action = this.endTextRecording();
AttributesImpl a = (AttributesImpl)this.stack.pop();
- // append a unique number to the form
- synchronized (this.getClass()) {
- this.formName = a.getValue("name") + '_' + currentFormNumber;
- currentFormNumber++;
- if (currentFormNumber > 99999) currentFormNumber = 0;
- }
+ this.formName = a.getValue("name");
boolean hasPars = (action.indexOf("?") != -1);
action = this.response.encodeURL(action + (hasPars ? '&' : '?') + SessionConstants.SESSION_FORM_PARAMETER+'='+this.formName);
a.addAttribute("", "action", "action", "CDATA", action);
@@ -328,6 +361,82 @@
} else if (name.equals(FORM_CONTENT_ELEMENT) == true
&& this.state == STATE_FORM) {
// ignore this
+
+ // Element form validation rules
+ } else if (name.equals(FORM_VALIDATION_ELEMENT) == true
+ && this.state == STATE_FORM) {
+ if (this.formName == null) {
+ throw new ProcessingException("The validate element must be contained inside a form.");
+ }
+ DocumentFragment validationDoc = this.endRecording();
+ String source = (String)stack.pop();
+ if (!source.equals("EMPTY")) {
+ // get configuration from external file
+ // referenced by "src" attribute of "validate" element
+
+ Configuration conf = null;
+ Session session = null;
+ try {
+ Source resource = this.resolver.resolveURI(source);
+ SAXConfigurationHandler saxBuilder = new SAXConfigurationHandler();
+ resolver.toSAX(resource, saxBuilder);
+
+ conf = saxBuilder.getConfiguration();
+ session = this.getSessionManager().getSession(true);
+ session.setAttribute(this.formName, conf);
+
+ if (validationDoc != null) {
+ //validationDoc contains "validate-set" element
+ validationDoc.normalize();
+ Node validationNode = validationDoc.getFirstChild();
+ while (validationNode.getNodeType() != Node.ELEMENT_NODE) {
+ validationNode = validationNode.getNextSibling();
+ if (validationNode == null) break;
+ }
+ if (validationNode != null &&
+ validationNode.getNodeType() == Node.ELEMENT_NODE &&
+ validationNode.getNodeName().equals(FORM_VALIDATESET_ELEMENT)) {
+ String validationXML = XMLUtils.serializeNodeToXML(validationNode);
+ DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
+ conf = builder.build(new StringBufferInputStream(validationXML));
+ session.setAttribute(this.formName+"validate-set", conf);
+ }
+ }
+
+ } catch (SourceException se) {
+ throw new ProcessingException("Cannot resolve"+source, se);
+ } catch (ConfigurationException ce) {
+ throw new ProcessingException("Error building Configuration out of validate-set element", ce);
+ }
+
+ } else if (validationDoc != null) {
+ //validationDoc contains the validation rules inline
+ try {
+ validationDoc.normalize();
+ Node validationNode = validationDoc.getFirstChild();
+ while (validationNode.getNodeType() != Node.ELEMENT_NODE) {
+ validationNode = validationNode.getNextSibling();
+ if (validationNode == null) break;
+ }
+ if (validationNode != null &&
+ validationNode.getNodeType() == Node.ELEMENT_NODE &&
+ validationNode.getNodeName().equals("root")) {
+
+ String validationXML = XMLUtils.serializeNodeToXML(validationNode);
+ DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
+ Configuration conf = null;
+ Session session = null;
+ conf = builder.build(new StringBufferInputStream(validationXML));
+ session = this.getSessionManager().getSession(true);
+ session.setAttribute(this.formName, conf);
+ //the constraint-set to validate is the first and single one
+ session.setAttribute(this.formName+"validate-set", conf.getChildren ("constraint-set")[0]);
+
+ }
+ } catch (ConfigurationException ce) {
+ throw new ProcessingException("Error building Configuration out of validation XML", ce);
+ }
+ }
} else {
super.endTransformingElement(uri, name, raw);
1.1 xml-cocoon2/src/blocks/session-fw/java/org/apache/cocoon/webapps/session/acting/SessionFormAction.java
Index: SessionFormAction.java
===================================================================
/*
============================================================================
The Apache Software License, Version 1.1
============================================================================
Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.
4. The names "Apache Cocoon" and "Apache Software Foundation" must not be
used to endorse or promote products derived from this software without
prior written permission. For written permission, please contact
apache@apache.org.
5. Products derived from this software may not be called "Apache", nor may
"Apache" appear in their name, without prior written permission of the
Apache Software Foundation.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This software consists of voluntary contributions made by many individuals
on behalf of the Apache Software Foundation and was originally created by
Stefano Mazzocchi <st...@apache.org>. For more information on the Apache
Software Foundation, please see <http://www.apache.org/>.
*/
package org.apache.cocoon.webapps.session.acting;
import org.apache.cocoon.acting.AbstractValidatorAction;
import org.apache.cocoon.acting.ValidatorActionHelper;
import org.apache.cocoon.acting.ValidatorActionResult;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.Constants;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.webapps.session.SessionConstants;
import org.apache.cocoon.webapps.session.components.SessionManager;
import org.apache.cocoon.util.Tokenizer;
import java.util.HashMap;
import java.util.Map;
/**
* This is the action used to validate Request parameters.
* The validation rules are either embedded within the form
*
* <pre>
* <session:form name="info_form">
* <session:action>next_page</session:action>
* <session:content>
* <session:inputxml name="name" type="text" context="trackdemo" path="/user/name"/>
* </session:content>
* <session:validate>
* <root>
* <parameter name="name" type="string" nullable="no"/>
* <constraint-set name="form_a_set">
* <validate name="name"/>
* </constraint-set>
* </root>
* </session:validate>
* </session:form>
* </pre>
*
* or described via the external xml file referenced
* through the "src" attribute
* (the format is defined in AbstractValidatorAction).
* Then the constraint-set to be used has to be identified
* through the "validate-set" element
*
* <pre>
* <session:form name="info_form>
* <session:action>next_page</session:action>
* <session:content>
* <session:inputxml name="name" type="text" context="trackdemo" path="/user/name"/>
* </session:content>
* <session:validate src="descriptor.xml">
* <validate-set name="form_a_set"/>
* </session:validate>
* </session:form>
* </pre>
*
* Since the validation rules are contained within the form document
* they are read and supplied by the SessionTransformer.
* So this action has to be used in conjunction with the SessionTransformer.
* The "next_page" pipeline might look like this:
*
* <pre>
* <map:match pattern="next_page">
* <map:act type="session-form">
* <map:generate src="next_page.xml"/>
* <map:transform type="session"/>
* <map:transform src="simple2html.xsl"/>
* <map:serialize/>
* </map:act>
* <map:generate src="first_page.xml"/>
* <map:transform type="session"/>
* <map:transform src="simple2html.xsl"/>
* <map:serialize/>
* </map:match>
* </pre>
*
* where "session-form" is configured as SessionFormAction
*
* @author <a href="mailto:gcasper@s-und-n.de">Guido Casper</a>
* @version CVS $Id: SessionFormAction.java,v 1.1 2002/10/09 11:47:33 gcasper Exp $
*/
public class SessionFormAction extends AbstractValidatorAction implements ThreadSafe
{
/**
* Main invocation routine.
*/
public Map act (Redirector redirector, SourceResolver resolver, Map objectModel, String src,
Parameters parameters) throws Exception {
Request req = ObjectModelHelper.getRequest(objectModel);
/* check request validity */
if (req == null) {
if (getLogger().isDebugEnabled())
getLogger().debug ("No request object");
return null;
}
// read global parameter settings
boolean reloadable = Constants.DESCRIPTOR_RELOADABLE_DEFAULT;
if (this.settings.containsKey("reloadable")) {
reloadable = Boolean.valueOf((String) this.settings.get("reloadable")).booleanValue();
}
// read local settings
try {
SessionManager sessionManager = (SessionManager)this.manager.lookup(SessionManager.ROLE);
Session session = sessionManager.getSession(true);
Configuration conf = (Configuration)session.getAttribute(
req.getParameter(SessionConstants.SESSION_FORM_PARAMETER));
String valstr = parameters.getParameter ("validate", (String) settings.get("validate",""));
String valsetstr = parameters.getParameter ("validate-set", (String) settings.get("validate-set",""));
Configuration valConf = (Configuration)session.getAttribute(
req.getParameter(SessionConstants.SESSION_FORM_PARAMETER)+"validate-set");
if (valConf != null) {
valsetstr = valConf.getAttribute("name","");
}
Configuration[] desc = conf.getChildren ("parameter");
Configuration[] csets = conf.getChildren ("constraint-set");
HashMap actionMap = new HashMap ();
HashMap resultMap = new HashMap ();
boolean allOK = true;
/*
* old obsoleted method
*/
if (!"".equals (valstr.trim ())) {
if (getLogger().isDebugEnabled())
getLogger().debug ("Validating parameters "
+ "as specified via 'validate' parameter");
/* get list of params to be validated */
String[] rparams = null;
if (!"*".equals(valstr.trim())) {
rparams = Tokenizer.tokenize (valstr, ",", false);
} else {
// validate _all_ parameters
rparams = new String[desc.length];
for (int i=0; i<desc.length; i++) {
rparams[i] = desc[i].getAttribute("name","");
if ("".equals(rparams[i])) {
if (getLogger().isDebugEnabled())
getLogger().debug ("Wrong syntax of the 'validate' parameter");
return null;
}
}
}
/* perform actual validation */
ValidatorActionHelper result = null;
String name = null;
HashMap params = new HashMap (rparams.length);
/* put required params into hash */
for (int i = 0; i < rparams.length; i ++) {
name = rparams[i];
if (name == null || "".equals (name.trim ())) {
if (getLogger().isDebugEnabled())
getLogger().debug ("Wrong syntax of the 'validate' parameter");
return null;
}
name = name.trim ();
params.put (name, req.getParameter (name));
}
for (int i = 0; i < rparams.length; i ++) {
name = rparams[i].trim ();
result = validateParameter (name, null, desc,
params, true);
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());
}
}
/*
* new set-based method
*/
if (!"".equals (valsetstr.trim ())) {
if (getLogger().isDebugEnabled())
getLogger().debug ("Validating parameters "
+ "from given constraint-set " + valsetstr);
// go over all constraint sets
// untill the requested set is found
// set number will be in j
Configuration cset = null;
String setname = null;
int j = 0;
boolean found = false;
for (j = 0; j < csets.length; j ++) {
setname = csets[j].getAttribute ("name", "");
if (valsetstr.trim().equals (setname.trim ())) {
found = true;
break;
}
}
if (!found) {
if (getLogger().isDebugEnabled())
getLogger().debug ("Given set "
+ valsetstr
+ " does not exist in a description file");
return null;
}
cset = csets[j];
/* get the list of params to be validated */
Configuration[] set = cset.getChildren ("validate");
/* perform actuall validation */
ValidatorActionHelper result = null;
String name = null;
HashMap params = new HashMap (set.length);
if (getLogger().isDebugEnabled())
getLogger().debug ("Given set "
+ valsetstr
+ " contains " + set.length + " rules");
/* put required params into hash */
for (int i = 0; i < set.length; i ++) {
name = set[i].getAttribute ("name", "").trim();
if ("".equals(name)) {
if (getLogger().isDebugEnabled())
getLogger().debug ("Wrong syntax "
+ " of 'validate' children nr. " + i);
return null;
}
Object[] values = req.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);
}
}
String rule = null;
for (int i = 0; i < set.length; i ++) {
name = set[i].getAttribute ("name", null);
rule = set[i].getAttribute("rule",name);
result = validateParameter (name, rule, set[i],
desc, params, true);
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());
}
}
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
req.setAttribute(Constants.XSP_FORMVALIDATOR_PATH, resultMap);
// store validation results in session attribute
// to be used by SessionTransformer
session.setAttribute(req.getParameter(SessionConstants.SESSION_FORM_PARAMETER)+
"validation-result", resultMap);
//return Collections.unmodifiableMap (actionMap);
return actionMap;
} catch (Exception e) {
if (getLogger().isDebugEnabled())
getLogger().debug ("exception: ", e);
}
return null;
}
}
----------------------------------------------------------------------
In case of troubles, e-mail: webmaster@xml.apache.org
To unsubscribe, e-mail: cocoon-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-cvs-help@xml.apache.org