Author: craigmcc
Date: Thu Oct 21 19:56:53 2004
New Revision: 55303
Modified:
struts/trunk/struts-faces/core-library/src/conf/struts-faces.xml
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/ErrorsRenderer.java
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/FormRenderer.java
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/WriteRenderer.java
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/taglib/JavascriptValidatorTag.java
struts/trunk/struts-faces/example1-webapp/src/java/org/apache/struts/webapp/example/SaveRegistrationAction.java
struts/trunk/struts-faces/example1-webapp/src/web/WEB-INF/struts-config.xml
struts/trunk/struts-faces/example1-webapp/src/web/registration.jsp
struts/trunk/struts-faces/example1-webapp/src/web/staticJavascript.jsp
struts/trunk/struts-faces/example1-webapp/src/web/subscription.jsp
struts/trunk/struts-faces/example2-webapp/src/java/org/apache/struts/webapp/example2/SaveRegistrationAction.java
struts/trunk/struts-faces/example2-webapp/src/web/WEB-INF/struts-config.xml
struts/trunk/struts-faces/example2-webapp/src/web/registration.jsp
struts/trunk/struts-faces/example2-webapp/src/web/subscription.jsp
struts/trunk/struts-faces/sysclient-app/src/java/org/apache/struts/faces/sysclient/LogonTestCase.java
Log:
Clean up remaining rendering issues and correct logic errors in the two
sample applications. Everything now works on Tomcat 5.0.28, JSF RI 1.1_01.
Details of changes:
core-library:
------------
* JavascriptValidatorTag.java - Update behavior to match the Struts 1.2.4
mechanisms.
* WriteRenderer.java - Do not emit a <span> around the text if the component
has an automatically assigned id ("_idXXX").
* ErrorsRenderer.java - Change behavior when no "property" attribute is
specified to match the corresponding <html:errors/> tag: render *all*
messages instead of just global ones.
* FormRenderer.java - Create a "name" attribute containing the name of the
form bean, since this is what the Javascript implementing client side
validations expects.
* struts-faces.xml - Update tag library description for "errors" tag
to match the revised behavior.
example1-webapp:
---------------
* SaveRegistration.java - If cancel key was pressed, go back to the
welcome screen instead of the main menu. This avoids an NPE if
you followed the "register" link off the welcome screen.
* subscription.jsp - Add onclick handler on the cancel button to
turn off the client side validation as well.
* registration.jsp - Add onclick handler on the cancel button to
turn off the client side validation as well.
* struts-config.xml - Add forward definition for new cancel behavior.
* staticJavascript.jsp - Use the struts-faces version of the javascript tag.
example2-webapp:
---------------
* Same changes as for example1-webapp.
* Fix the forwarding from registration.jsp (the delete, edit, and create
buttons) to correctly go to the subscription tile.
sysclient-app:
-------------
* Update test cases for new behavior of errors and form renderers.
Modified: struts/trunk/struts-faces/core-library/src/conf/struts-faces.xml
==============================================================================
--- struts/trunk/struts-faces/core-library/src/conf/struts-faces.xml (original)
+++ struts/trunk/struts-faces/core-library/src/conf/struts-faces.xml Thu Oct 21
19:56:53 2004
@@ -387,7 +387,7 @@
<rtexprvalue>false</rtexprvalue>
<description>
Component of the component for which to render errors. If not
- specified, only global messages are rendered.
+ specified, all messages (regardless of property) are displayed.
</description>
</attribute>
Modified:
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/ErrorsRenderer.java
==============================================================================
---
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/ErrorsRenderer.java
(original)
+++
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/ErrorsRenderer.java
Thu Oct 21 19:56:53 2004
@@ -84,6 +84,10 @@
throw new NullPointerException();
}
+ if (log.isDebugEnabled()) {
+ log.debug("encodeEnd() started");
+ }
+
// Look up availability of our predefined resource keys
MessageResources resources = resources(context, component);
if (Beans.isDesignTime() && (resources == null)) {
@@ -112,6 +116,9 @@
Iterator messages = context.getMessages(property);
while (messages.hasNext()) {
FacesMessage message = (FacesMessage) messages.next();
+ if (log.isTraceEnabled()) {
+ log.trace("Processing FacesMessage: " + message.getSummary());
+ }
if (!headerDone) {
if (headerPresent) {
writer.write
@@ -133,10 +140,22 @@
context.getExternalContext().getRequestMap().get
(Globals.ERROR_KEY);
if (errors != null) {
- Iterator reports = errors.get
- ((property == null) ? ActionErrors.GLOBAL_ERROR : property);
+ if (log.isTraceEnabled()) {
+ log.trace("Processing Struts messages for property '" +
+ property + "'");
+ }
+ Iterator reports = null;
+ if (property == null) {
+ reports = errors.get();
+ } else {
+ reports = errors.get(property);
+ }
while (reports.hasNext()) {
ActionMessage report = (ActionMessage) reports.next();
+ if (log.isTraceEnabled()) {
+ log.trace("Processing Struts message key='" +
+ report.getKey() + "'");
+ }
if (!headerDone) {
writer = context.getResponseWriter();
if (headerPresent) {
@@ -164,6 +183,10 @@
}
if (id != null) {
writer.endElement("span");
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("encodeEnd() finished");
}
}
Modified:
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/FormRenderer.java
==============================================================================
---
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/FormRenderer.java
(original)
+++
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/FormRenderer.java
Thu Oct 21 19:56:53 2004
@@ -128,6 +128,9 @@
ResponseWriter writer = context.getResponseWriter();
writer.startElement("form", form);
writer.writeAttribute("id", clientId, "clientId");
+ if (beanName != null) {
+ writer.writeAttribute("name", beanName, null);
+ }
writer.writeAttribute("action", action(context, component), "action");
if (styleClass != null) {
writer.writeAttribute("class", styleClass, "styleClass");
Modified:
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/WriteRenderer.java
==============================================================================
---
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/WriteRenderer.java
(original)
+++
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/renderer/WriteRenderer.java
Thu Oct 21 19:56:53 2004
@@ -19,6 +19,7 @@
import java.io.IOException;
import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@@ -68,10 +69,17 @@
ResponseWriter writer = context.getResponseWriter();
String id = component.getId();
+ if ((id != null) && id.startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) {
+ id = null;
+ }
String style =
(String) component.getAttributes().get("style");
String styleClass =
(String) component.getAttributes().get("styleClass");
+ if (log.isTraceEnabled()) {
+ log.trace("id='" + id + "', style='" + style + "', styleClass='" +
+ styleClass + "'");
+ }
if ((id != null) || (style != null) || (styleClass != null)) {
writer.startElement("span", component);
if (id != null) {
Modified:
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/taglib/JavascriptValidatorTag.java
==============================================================================
---
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/taglib/JavascriptValidatorTag.java
(original)
+++
struts/trunk/struts-faces/core-library/src/java/org/apache/struts/faces/taglib/JavascriptValidatorTag.java
Thu Oct 21 19:56:53 2004
@@ -1,5 +1,7 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * $Id$
+ *
+ * Copyright 2001-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.
@@ -17,6 +19,7 @@
package org.apache.struts.faces.taglib;
import java.io.IOException;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -24,10 +27,12 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.StringTokenizer;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.webapp.UIComponentTag;
+
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
@@ -38,28 +43,70 @@
import org.apache.commons.validator.Form;
import org.apache.commons.validator.ValidatorAction;
import org.apache.commons.validator.ValidatorResources;
-import org.apache.commons.validator.ValidatorUtil;
+import org.apache.commons.validator.util.ValidatorUtils;
import org.apache.commons.validator.Var;
+
import org.apache.struts.Globals;
+import org.apache.struts.action.ActionMapping;
import org.apache.struts.config.ModuleConfig;
import org.apache.struts.faces.component.FormComponent;
+import org.apache.struts.taglib.TagUtils;
import org.apache.struts.util.MessageResources;
-import org.apache.struts.util.RequestUtils;
import org.apache.struts.validator.Resources;
import org.apache.struts.validator.ValidatorPlugIn;
+
/**
* Custom tag that generates JavaScript for client side validation based
* on the validation rules loaded by the <code>ValidatorPlugIn</code>
- * defined in the struts-config.xml file. This is based on the code in
- * the corresponding class of the Struts HTML tag library, modified as needed
- * to reflect differences in the way JavaServer Faces renders field
- * identifiers.
+ * defined in the struts-config.xml file.
*
* @version $Rev$ $Date$
+ * @since Struts 1.1
*/
public class JavascriptValidatorTag extends BodyTagSupport {
+ /**
+ * A Comparator to use when sorting ValidatorAction objects.
+ */
+ private static final Comparator actionComparator = new Comparator() {
+ public int compare(Object o1, Object o2) {
+
+ ValidatorAction va1 = (ValidatorAction) o1;
+ ValidatorAction va2 = (ValidatorAction) o2;
+
+ if ((va1.getDepends() == null || va1.getDepends().length() == 0)
+ && (va2.getDepends() == null || va2.getDepends().length() == 0)) {
+ return 0;
+
+ } else if (
+ (va1.getDepends() != null && va1.getDepends().length() > 0)
+ && (va2.getDepends() == null || va2.getDepends().length() == 0)) {
+ return 1;
+
+ } else if (
+ (va1.getDepends() == null || va1.getDepends().length() == 0)
+ && (va2.getDepends() != null && va2.getDepends().length() > 0)) {
+ return -1;
+
+ } else {
+ return va1.getDependencyList().size() -
va2.getDependencyList().size();
+ }
+ }
+ };
+
+ /**
+ * The start of the HTML comment hiding JavaScript from old browsers.
+ * @since Struts 1.2
+ */
+ protected static final String HTML_BEGIN_COMMENT = "\n<!-- Begin \n";
+
+ /**
+ * The end of the HTML comment hiding JavaScript from old browsers.
+ * @since Struts 1.2
+ */
+ protected static final String HTML_END_COMMENT = "//End --> \n";
+
// ----------------------------------------------------------- Properties
/**
@@ -79,6 +126,15 @@
* <script> </script> around the javascript.
*/
protected String formName = null;
+
+ /**
+ * formName is used for both Javascript and non-javascript validations.
+ * For the javascript validations, there is the possibility that we will
+ * be rewriting the formName (if it is a ValidatorActionForm instead of just
+ * a ValidatorForm) so we need another variable to hold the formName just for
+ * javascript usage.
+ */
+ protected String jsFormName = null;
/**
* The line ending string.
@@ -98,6 +154,13 @@
protected String methodName = null;
/**
+ * Include language attribute in the <script> element. This property is
+ * ignored in XHTML mode.
+ * @since Struts 1.2
+ */
+ protected boolean scriptLanguage = true;
+
+ /**
* The static JavaScript methods will only be printed if this is set to "true".
*/
protected String staticJavascript = "true";
@@ -118,16 +181,12 @@
* The JavaScript methods will enclosed with html comments if this is set to
"true".
*/
protected String htmlComment = "true";
-
+
/**
* Hide JavaScript methods in a CDATA section for XHTML when "true".
*/
protected String cdata = "true";
- private String htmlBeginComment = "\n<!-- Begin \n";
-
- private String htmlEndComment = "//End --> \n";
-
/**
* Gets the key (form name) that will be used
* to retrieve a set of validation rules to be
@@ -149,6 +208,18 @@
}
/**
+ * @return Returns the jsFormName.
+ */
+ public String getJsFormName() {
+ return jsFormName;
+ }
+ /**
+ * @param jsFormName The jsFormName to set.
+ */
+ public void setJsFormName(String jsFormName) {
+ this.jsFormName = jsFormName;
+ }
+ /**
* Gets the current page number of a multi-part form.
* Only field validations with a matching page numer
* will be generated that match the current page number.
@@ -265,242 +336,334 @@
* @exception JspException if a JSP exception has occurred
*/
public int doStartTag() throws JspException {
+
+ JspWriter writer = pageContext.getOut();
+ try {
+ writer.print(this.renderJavascript());
+
+ } catch (IOException e) {
+ throw new JspException(e.getMessage());
+ }
+
+ return EVAL_BODY_TAG;
+
+ }
+
+ /**
+ * Returns fully rendered JavaScript.
+ * @since Struts 1.2
+ */
+ protected String renderJavascript() throws JspException {
StringBuffer results = new StringBuffer();
- ModuleConfig config = RequestUtils.getModuleConfig(pageContext);
+ ModuleConfig config = TagUtils.getInstance().getModuleConfig(pageContext);
ValidatorResources resources =
(ValidatorResources) pageContext.getAttribute(
ValidatorPlugIn.VALIDATOR_KEY + config.getPrefix(),
PageContext.APPLICATION_SCOPE);
- Locale locale = RequestUtils.retrieveUserLocale(this.pageContext, null);
+ Locale locale = TagUtils.getInstance().getUserLocale(this.pageContext, null);
+
+ Form form = resources.getForm(locale, formName);
+
+ if ("true".equalsIgnoreCase(dynamicJavascript) && form == null)
+ {
+ throw new JspException("No form found under '"
+ + formName
+ + "' in locale '"
+ + locale
+ + "'");
+ }
- Form form = resources.get(locale, formName);
if (form != null) {
if ("true".equalsIgnoreCase(dynamicJavascript)) {
- MessageResources messages =
- (MessageResources) pageContext.getAttribute(
- bundle + config.getPrefix(),
- PageContext.APPLICATION_SCOPE);
-
- List lActions = new ArrayList();
- List lActionMethods = new ArrayList();
-
- // Get List of actions for this Form
- for (Iterator i = form.getFields().iterator(); i.hasNext();) {
- Field field = (Field) i.next();
-
- for (Iterator x = field.getDependencies().iterator();
x.hasNext();) {
- Object o = x.next();
-
- if (o != null && !lActionMethods.contains(o)) {
- lActionMethods.add(o);
- }
- }
+ results.append(
+ this.createDynamicJavascript(config, resources, locale,
form));
+ } else if ("true".equalsIgnoreCase(staticJavascript)) {
+ results.append(this.renderStartElement());
+ if ("true".equalsIgnoreCase(htmlComment)) {
+ results.append(HTML_BEGIN_COMMENT);
}
+ }
+ }
- // Create list of ValidatorActions based on lActionMethods
- for (Iterator i = lActionMethods.iterator(); i.hasNext();) {
- String depends = (String) i.next();
- ValidatorAction va = resources.getValidatorAction(depends);
-
- // throw nicer NPE for easier debugging
- if (va == null) {
- throw new NullPointerException(
- "Depends string \""
- + depends
- + "\" was not found in validator-rules.xml.");
- }
-
- String javascript = va.getJavascript();
- if (javascript != null && javascript.length() > 0) {
- lActions.add(va);
- } else {
- i.remove();
+ if ("true".equalsIgnoreCase(staticJavascript)) {
+ results.append(getJavascriptStaticMethods(resources));
+ }
+
+ if (form != null
+ && ("true".equalsIgnoreCase(dynamicJavascript)
+ || "true".equalsIgnoreCase(staticJavascript))) {
+
+ results.append(getJavascriptEnd());
+ }
+
+ return results.toString();
+ }
+
+ /**
+ * Generates the dynamic JavaScript for the form.
+ * @param config
+ * @param resources
+ * @param locale
+ * @param form
+ */
+ private String createDynamicJavascript(
+ ModuleConfig config,
+ ValidatorResources resources,
+ Locale locale,
+ Form form) throws JspException {
+
+ StringBuffer results = new StringBuffer();
+
+ MessageResources messages =
+ (MessageResources) pageContext.getAttribute(
+ bundle + config.getPrefix(),
+ PageContext.APPLICATION_SCOPE);
+
+ List actions = this.createActionList(resources, form);
+
+ final String methods = this.createMethods(actions, this.stopOnError(config));
+
+ String formName = form.getName();
+ jsFormName = formName;
+ if(jsFormName.charAt(0) == '/') {
+ String mappingName =
TagUtils.getInstance().getActionMappingName(jsFormName);
+ ActionMapping mapping = (ActionMapping)
config.findActionConfig(mappingName);
+ if (mapping == null) {
+ JspException e = new
JspException(messages.getMessage("formTag.mapping", mappingName));
+ pageContext.setAttribute(Globals.EXCEPTION_KEY, e,
PageContext.REQUEST_SCOPE);
+ throw e;
}
+ jsFormName = mapping.getAttribute();
}
+
+ results.append(this.getJavascriptBegin(methods));
- Collections.sort(lActions, new Comparator() {
- public int compare(Object o1, Object o2) {
- ValidatorAction va1 = (ValidatorAction) o1;
- ValidatorAction va2 = (ValidatorAction) o2;
-
- if ((va1.getDepends() == null || va1.getDepends().length() ==
0)
- && (va2.getDepends() == null || va2.getDepends().length()
== 0)) {
- return 0;
- } else if (
- (va1.getDepends() != null && va1.getDepends().length() >
0)
- && (va2.getDepends() == null ||
va2.getDepends().length() == 0)) {
- return 1;
- } else if (
- (va1.getDepends() == null || va1.getDepends().length() ==
0)
- && (va2.getDepends() != null &&
va2.getDepends().length() > 0)) {
- return -1;
- } else {
- return va1.getDependencies().size() -
va2.getDependencies().size();
- }
- }
- });
+ for (Iterator i = actions.iterator(); i.hasNext();) {
+ ValidatorAction va = (ValidatorAction) i.next();
+ int jscriptVar = 0;
+ String functionName = null;
- String methods = null;
- for (Iterator i = lActions.iterator(); i.hasNext();) {
- ValidatorAction va = (ValidatorAction) i.next();
- if (methods == null) {
- methods = va.getMethod() + "(form)";
- } else {
- methods += " && " + va.getMethod() + "(form)";
- }
+ if (va.getJsFunctionName() != null
+ && va.getJsFunctionName().length() > 0) {
+ functionName = va.getJsFunctionName();
+ } else {
+ functionName = va.getName();
+ }
+
+
+ results.append(" function " + jsFormName + "_" + functionName + " () {
\n");
+ for (Iterator x = form.getFields().iterator(); x.hasNext();) {
+ Field field = (Field) x.next();
+
+ // Skip indexed fields for now until there is a good way to handle
+ // error messages (and the length of the list (could retrieve from
scope?))
+ if (field.isIndexed()
+ || field.getPage() != page
+ || !field.isDependency(va.getName())) {
+
+ continue;
}
- results.append(getJavascriptBegin(methods));
+ String message = Resources.getMessage(messages, locale, va, field);
- for (Iterator i = lActions.iterator(); i.hasNext();) {
- ValidatorAction va = (ValidatorAction) i.next();
- String jscriptVar = null;
- String functionName = null;
+ message = (message != null) ? message : "";
- if (va.getJsFunctionName() != null &&
va.getJsFunctionName().length() > 0) {
- functionName = va.getJsFunctionName();
+ // prefix variable with 'a' to make it a legal identifier
+ results.append(
+ " this.a"
+ + jscriptVar++
+ + " = new Array(\""
+ + getFormClientId()
+ + ":"
+ + field.getKey()
+ + "\", \""
+ + escapeQuotes(message)
+ + "\", ");
+
+ results.append("new Function (\"varName\", \"");
+
+ Map vars = field.getVars();
+ // Loop through the field's variables.
+ Iterator varsIterator = vars.keySet().iterator();
+ while (varsIterator.hasNext()) {
+ String varName = (String) varsIterator.next();
+ Var var = (Var) vars.get(varName);
+ String varValue = var.getValue();
+ String jsType = var.getJsType();
+
+ // skip requiredif variables field, fieldIndexed, fieldTest,
fieldValue
+ if (varName.startsWith("field")) {
+ continue;
+ }
+
+ if (Var.JSTYPE_INT.equalsIgnoreCase(jsType)) {
+ results.append(
+ "this."
+ + varName
+ + "="
+ + ValidatorUtils.replace(varValue, "\\", "\\\\")
+ + "; ");
+ } else if (Var.JSTYPE_REGEXP.equalsIgnoreCase(jsType)) {
+ results.append(
+ "this."
+ + varName
+ + "=/"
+ + ValidatorUtils.replace(varValue, "\\", "\\\\")
+ + "/; ");
+ } else if (Var.JSTYPE_STRING.equalsIgnoreCase(jsType)) {
+ results.append(
+ "this."
+ + varName
+ + "='"
+ + ValidatorUtils.replace(varValue, "\\", "\\\\")
+ + "'; ");
+ // So everyone using the latest format doesn't need to change
their xml files immediately.
+ } else if ("mask".equalsIgnoreCase(varName)) {
+ results.append(
+ "this."
+ + varName
+ + "=/"
+ + ValidatorUtils.replace(varValue, "\\", "\\\\")
+ + "/; ");
} else {
- functionName = va.getName();
+ results.append(
+ "this."
+ + varName
+ + "='"
+ + ValidatorUtils.replace(varValue, "\\", "\\\\")
+ + "'; ");
}
+ }
- results.append(" function " + functionName + " () { \n");
- for (Iterator x = form.getFields().iterator(); x.hasNext();) {
- Field field = (Field) x.next();
-
- // Skip indexed fields for now until there is a good way to
handle
- // error messages (and the length of the list (could retrieve
from scope?))
- if (field.isIndexed()
- || field.getPage() != page
- || !field.isDependency(va.getName())) {
-
- continue;
- }
-
- String message =
- Resources.getMessage(messages, locale, va, field);
-
- message = (message != null) ? message : "";
+ results.append(" return this[varName];\"));\n");
+ }
+ results.append(" } \n\n");
+ }
- jscriptVar = this.getNextVar(jscriptVar);
+ return results.toString();
+ }
- results.append(
- " this."
- + jscriptVar
- + " = new Array(\""
- + getFormClientId()
- + ":"
- + field.getKey()
- + "\", \""
- + message
- + "\", ");
-
- results.append("new Function (\"varName\", \"");
-
- Map vars = field.getVars();
- // Loop through the field's variables.
- Iterator varsIterator = vars.keySet().iterator();
- while (varsIterator.hasNext()) {
- String varName = (String) varsIterator.next();
- Var var = (Var) vars.get(varName);
- String varValue = var.getValue();
- String jsType = var.getJsType();
-
- // skip requiredif variables field, fieldIndexed,
fieldTest, fieldValue
- if (varName.startsWith("field")) {
- continue;
- }
-
- if (Var.JSTYPE_INT.equalsIgnoreCase(jsType)) {
- results.append(
- "this."
- + varName
- + "="
- + ValidatorUtil.replace(
- varValue,
- "\\",
- "\\\\")
- + "; ");
- } else if (Var.JSTYPE_REGEXP.equalsIgnoreCase(jsType)) {
- results.append(
- "this."
- + varName
- + "=/"
- + ValidatorUtil.replace(
- varValue,
- "\\",
- "\\\\")
- + "/; ");
- } else if (Var.JSTYPE_STRING.equalsIgnoreCase(jsType)) {
- results.append(
- "this."
- + varName
- + "='"
- + ValidatorUtil.replace(
- varValue,
- "\\",
- "\\\\")
- + "'; ");
- // So everyone using the latest format doesn't need
to change their xml files immediately.
- } else if ("mask".equalsIgnoreCase(varName)) {
- results.append(
- "this."
- + varName
- + "=/"
- + ValidatorUtil.replace(
- varValue,
- "\\",
- "\\\\")
- + "/; ");
- } else {
- results.append(
- "this."
- + varName
- + "='"
- + ValidatorUtil.replace(
- varValue,
- "\\",
- "\\\\")
- + "'; ");
- }
- }
+ private String escapeQuotes(String in)
+ {
+ if (in == null || in.indexOf("\"") == -1)
+ {
+ return in;
+ }
+ StringBuffer buffer = new StringBuffer();
+ StringTokenizer tokenizer = new StringTokenizer(in, "\"", true);
- results.append(" return this[varName];\"));\n");
- }
- results.append(" } \n\n");
- }
- } else if ("true".equalsIgnoreCase(staticJavascript)) {
- results.append(this.getStartElement());
- if ("true".equalsIgnoreCase(htmlComment)) {
- results.append(htmlBeginComment);
- }
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+ if (token.equals("\""))
+ {
+ buffer.append("\\");
}
+ buffer.append(token);
}
-
- if ("true".equalsIgnoreCase(staticJavascript)) {
- results.append(getJavascriptStaticMethods(resources));
+
+ return buffer.toString();
+ }
+
+ /**
+ * Determines if validations should stop on an error.
+ * @param config The <code>ModuleConfig</code> used to lookup the
+ * stopOnError setting.
+ * @return <code>true</code> if validations should stop on errors.
+ */
+ private boolean stopOnError(ModuleConfig config) {
+ Object stopOnErrorObj =
+ pageContext.getAttribute(
+ ValidatorPlugIn.STOP_ON_ERROR_KEY + '.' + config.getPrefix(),
+ PageContext.APPLICATION_SCOPE);
+
+ boolean stopOnError = true;
+
+ if (stopOnErrorObj instanceof Boolean) {
+ stopOnError = ((Boolean) stopOnErrorObj).booleanValue();
}
- if (form != null
- && ("true".equalsIgnoreCase(dynamicJavascript)
- || "true".equalsIgnoreCase(staticJavascript))) {
-
- results.append(getJavascriptEnd());
+ return stopOnError;
+ }
+
+ /**
+ * Creates the JavaScript methods list from the given actions.
+ * @param actions A List of ValidatorAction objects.
+ * @param stopOnError If true, behaves like released version of struts 1.1
+ * and stops after first error. If false, evaluates all validations.
+ * @return JavaScript methods.
+ */
+ private String createMethods(List actions, boolean stopOnError) {
+ StringBuffer methods = new StringBuffer();
+ final String methodOperator = stopOnError ? " && " : " & ";
+
+ Iterator iter = actions.iterator();
+ while (iter.hasNext()) {
+ ValidatorAction va = (ValidatorAction) iter.next();
+
+ if (methods.length() > 0) {
+ methods.append(methodOperator);
+ }
+ methods.append(va.getMethod())
+ .append("(form)");
}
+ return methods.toString();
+ }
- JspWriter writer = pageContext.getOut();
- try {
- writer.print(results.toString());
- } catch (IOException e) {
- throw new JspException(e.getMessage());
+ /**
+ * Get List of actions for the given Form.
+ * @param resources
+ * @param form
+ * @return A sorted List of ValidatorAction objects.
+ */
+ private List createActionList(ValidatorResources resources, Form form) {
+
+ List actionMethods = new ArrayList();
+
+ Iterator iterator = form.getFields().iterator();
+ while (iterator.hasNext()) {
+ Field field = (Field) iterator.next();
+
+ for (Iterator x = field.getDependencyList().iterator(); x.hasNext();) {
+ Object o = x.next();
+
+ if (o != null && !actionMethods.contains(o)) {
+ actionMethods.add(o);
+ }
+ }
+ }
+
+ List actions = new ArrayList();
+
+ // Create list of ValidatorActions based on actionMethods
+ iterator = actionMethods.iterator();
+ while (iterator.hasNext()) {
+ String depends = (String) iterator.next();
+ ValidatorAction va = resources.getValidatorAction(depends);
+
+ // throw nicer NPE for easier debugging
+ if (va == null) {
+ throw new NullPointerException(
+ "Depends string \""
+ + depends
+ + "\" was not found in validator-rules.xml.");
+ }
+
+ if (va.getJavascript() != null && va.getJavascript().length() > 0) {
+ actions.add(va);
+ } else {
+ iterator.remove();
+ }
}
- return (EVAL_BODY_TAG);
+ Collections.sort(actions, actionComparator);
+ return actions;
}
/**
@@ -510,6 +673,7 @@
super.release();
bundle = Globals.MESSAGES_KEY;
formName = null;
+ jsFormName = null;
page = 0;
methodName = null;
staticJavascript = "true";
@@ -525,18 +689,19 @@
*/
protected String getJavascriptBegin(String methods) {
StringBuffer sb = new StringBuffer();
- String name =
- formName.substring(0, 1).toUpperCase()
- + formName.substring(1, formName.length());
+ String name = jsFormName.replace('/', '_'); // remove any '/' characters
+ name =
+ jsFormName.substring(0, 1).toUpperCase()
+ + jsFormName.substring(1, jsFormName.length());
+
+ sb.append(this.renderStartElement());
- sb.append(this.getStartElement());
-
if (this.isXhtml() && "true".equalsIgnoreCase(this.cdata)) {
sb.append("<![CDATA[\r\n");
}
-
+
if (!this.isXhtml() && "true".equals(htmlComment)) {
- sb.append(htmlBeginComment);
+ sb.append(HTML_BEGIN_COMMENT);
}
sb.append("\n var bCancel = false; \n\n");
@@ -559,7 +724,10 @@
if (methods == null || methods.length() == 0) {
sb.append(" return true; \n");
} else {
- sb.append(" return " + methods + "; \n");
+ //Making Sure that Bitwise operator works:
+ sb.append(" var formValidationResult;\n");
+ sb.append(" formValidationResult = " + methods + "; \n");
+ sb.append(" return (formValidationResult == 1);\n");
}
sb.append(" } \n\n");
@@ -594,74 +762,28 @@
sb.append("\n");
if (!this.isXhtml() && "true".equals(htmlComment)){
- sb.append(htmlEndComment);
+ sb.append(HTML_END_COMMENT);
}
-
+
if (this.isXhtml() && "true".equalsIgnoreCase(this.cdata)) {
sb.append("]]>\r\n");
}
-
+
sb.append("</script>\n\n");
return sb.toString();
}
/**
- * The value <code>null</code> will be returned at the end of the sequence.
- * ex: "zz" will return <code>null</code>
- */
- private String getNextVar(String input) {
- if (input == null) {
- return "aa";
- }
-
- input = input.toLowerCase();
-
- for (int i = input.length(); i > 0; i--) {
- int pos = i - 1;
-
- char c = input.charAt(pos);
- c++;
-
- if (c <= 'z') {
- if (i == 0) {
- return c + input.substring(pos, input.length());
- } else if (i == input.length()) {
- return input.substring(0, pos) + c;
- } else {
- return input.substring(0, pos) + c + input.substring(pos,
input.length() - 1);
- }
- } else {
- input = replaceChar(input, pos, 'a');
- }
-
- }
-
- return null;
-
- }
-
- /**
- * Replaces a single character in a <code>String</code>
- */
- private String replaceChar(String input, int pos, char c) {
- if (pos == 0) {
- return c + input.substring(pos, input.length());
- } else if (pos == input.length()) {
- return input.substring(0, pos) + c;
- } else {
- return input.substring(0, pos) + c + input.substring(pos, input.length()
- 1);
- }
- }
-
- /**
- * Constructs the beginning <script> element depending on xhtml status.
+ * Constructs the beginning <script> element depending on XHTML
+ * status.
+ * @since Struts 1.2
*/
- private String getStartElement() {
+ protected String renderStartElement() {
StringBuffer start = new StringBuffer("<script type=\"text/javascript\"");
- // there is no language attribute in xhtml
- if (!this.isXhtml()) {
+ // there is no language attribute in XHTML
+ if (!this.isXhtml() && this.scriptLanguage) {
start.append(" language=\"Javascript1.1\"");
}
@@ -672,12 +794,12 @@
start.append("> \n");
return start.toString();
}
-
+
/**
* Returns true if this is an xhtml page.
*/
private boolean isXhtml() {
- return RequestUtils.isXhtml(this.pageContext);
+ return TagUtils.getInstance().isXhtml(this.pageContext);
}
/**
@@ -696,21 +818,39 @@
this.cdata = cdata;
}
+ /**
+ * Gets whether or not the <script> element will include the
+ * language attribute.
+ * @return true if language attribute will be included.
+ * @since Struts 1.2
+ */
+ public boolean getScriptLanguage() {
+ return this.scriptLanguage;
+ }
+
+ /**
+ * Sets whether or not the <script> element will include the
+ * language attribute.
+ * @since Struts 1.2
+ */
+ public void setScriptLanguage(boolean scriptLanguage) {
+ this.scriptLanguage = scriptLanguage;
+ }
+ /**
+ * <p>Cached client identifier of our parent form component.</p>
+ */
private String formClientId = null;
/**
- * <p>Return the <code>clientId</code> of the form component for which
- * we are rendering validation Javascript.</p>
- *
- * @exception IllegalStateException if we are not nested inside a
- * UIComponentTag with a child FormComponent matching our form name
+ * <p>Return the <code>clientId</code> of the [EMAIL PROTECTED] FormComponent}
+ * within which we are nested.</p>
*/
- private String getFormClientId(){
+ private String getFormClientId() {
// Return any cached value
if (formClientId != null) {
- return (formClientId);
+ return formClientId;
}
// Locate our parent tag that is a component tag
@@ -723,7 +863,7 @@
}
if (parent == null) {
throw new IllegalArgumentException
- ("Not nested inside a UIComponentTag");
+ ("Javascript tag is not nested inside a component tag");
}
// Are we nested inside our corresponding form tag?
@@ -733,26 +873,26 @@
if (formName.equals((String)
parentComponent.getAttributes().get("beanName"))) {
formClientId = parentComponent.getClientId
(FacesContext.getCurrentInstance());
- return (formClientId);
+ return formClientId;
}
}
- // Scan the children of this tag's component
- Iterator kids = ((UIComponentTag) parent).
- getComponentInstance().getChildren().iterator();
+ // No, so search the children of this component for a sibling form
+ Iterator kids = parentComponent.getChildren().iterator();
while (kids.hasNext()) {
UIComponent kid = (UIComponent) kids.next();
- if (!(kid instanceof FormComponent)) {
- continue;
- }
- if (formName.equals((String) kid.getAttributes().get("beanName"))) {
- formClientId =
- kid.getClientId(FacesContext.getCurrentInstance());
- return (formClientId);
+ if (kid instanceof FormComponent) {
+ if (formName.equals((String) kid.getAttributes().get("beanName"))) {
+ formClientId = kid.getClientId
+ (FacesContext.getCurrentInstance());
+ return formClientId;
+ }
}
}
+
+ // Rats, could not find a form component that way either
throw new IllegalArgumentException
- ("Cannot find child FormComponent for form '" + formName + "'");
+ ("Cannot find form component for form '" + formName + "'");
}
Modified:
struts/trunk/struts-faces/example1-webapp/src/java/org/apache/struts/webapp/example/SaveRegistrationAction.java
==============================================================================
---
struts/trunk/struts-faces/example1-webapp/src/java/org/apache/struts/webapp/example/SaveRegistrationAction.java
(original)
+++
struts/trunk/struts-faces/example1-webapp/src/java/org/apache/struts/webapp/example/SaveRegistrationAction.java
Thu Oct 21 19:56:53 2004
@@ -117,7 +117,7 @@
"' was cancelled");
}
session.removeAttribute(Constants.SUBSCRIPTION_KEY);
- return (mapping.findForward("success"));
+ return (mapping.findForward("failure"));
}
// Validate the transactional control token
Modified: struts/trunk/struts-faces/example1-webapp/src/web/WEB-INF/struts-config.xml
==============================================================================
--- struts/trunk/struts-faces/example1-webapp/src/web/WEB-INF/struts-config.xml
(original)
+++ struts/trunk/struts-faces/example1-webapp/src/web/WEB-INF/struts-config.xml Thu
Oct 21 19:56:53 2004
@@ -89,6 +89,7 @@
<forward name="registration" path="/registration.faces"/>
<forward name="subscription" path="/subscription.faces"/>
<forward name="success" path="/mainMenu.faces"/>
+ <forward name="failure" path="/index.faces"/>
</global-forwards>
@@ -137,7 +138,8 @@
type="org.apache.struts.webapp.example.SaveRegistrationAction"
name="registrationForm"
scope="request"
- input="registration"/>
+ input="registration">
+ </action>
<!-- Save mail subscription -->
<action path="/saveSubscription"
Modified: struts/trunk/struts-faces/example1-webapp/src/web/registration.jsp
==============================================================================
--- struts/trunk/struts-faces/example1-webapp/src/web/registration.jsp (original)
+++ struts/trunk/struts-faces/example1-webapp/src/web/registration.jsp Thu Oct 21
19:56:53 2004
@@ -178,6 +178,7 @@
<h:commandButton id="cancel"
type="SUBMIT"
styleClass="cancel"
+ onclick="bCancel=true;"
value="#{messages['button.cancel']}"/>
</h:panelGroup>
Modified: struts/trunk/struts-faces/example1-webapp/src/web/staticJavascript.jsp
==============================================================================
--- struts/trunk/struts-faces/example1-webapp/src/web/staticJavascript.jsp
(original)
+++ struts/trunk/struts-faces/example1-webapp/src/web/staticJavascript.jsp Thu
Oct 21 19:56:53 2004
@@ -1,6 +1,7 @@
<%@ page language="java" %>
<%-- set document type to Javascript (addresses a bug in Netscape according to a web
resource --%>
<%@ page contentType="application/x-javascript" %>
+<%@ taglib prefix="s" uri="http://struts.apache.org/tags-faces" %>
<%--
@@ -20,7 +21,4 @@
--%>
-
-<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
-
-<html:javascript dynamicJavascript="false" staticJavascript="true"/>
+<s:javascript dynamicJavascript="false" staticJavascript="true"/>
Modified: struts/trunk/struts-faces/example1-webapp/src/web/subscription.jsp
==============================================================================
--- struts/trunk/struts-faces/example1-webapp/src/web/subscription.jsp (original)
+++ struts/trunk/struts-faces/example1-webapp/src/web/subscription.jsp Thu Oct 21
19:56:53 2004
@@ -195,6 +195,7 @@
<h:commandButton id="cancel"
type="SUBMIT"
styleClass="cancel"
+ onclick="bCancel=true;"
value="#{messages['button.cancel']}"/>
</h:panelGroup>
Modified:
struts/trunk/struts-faces/example2-webapp/src/java/org/apache/struts/webapp/example2/SaveRegistrationAction.java
==============================================================================
---
struts/trunk/struts-faces/example2-webapp/src/java/org/apache/struts/webapp/example2/SaveRegistrationAction.java
(original)
+++
struts/trunk/struts-faces/example2-webapp/src/java/org/apache/struts/webapp/example2/SaveRegistrationAction.java
Thu Oct 21 19:56:53 2004
@@ -115,7 +115,7 @@
"' was cancelled");
}
session.removeAttribute(Constants.SUBSCRIPTION_KEY);
- return (mapping.findForward("success"));
+ return (mapping.findForward("failure"));
}
// Validate the transactional control token
Modified: struts/trunk/struts-faces/example2-webapp/src/web/WEB-INF/struts-config.xml
==============================================================================
--- struts/trunk/struts-faces/example2-webapp/src/web/WEB-INF/struts-config.xml
(original)
+++ struts/trunk/struts-faces/example2-webapp/src/web/WEB-INF/struts-config.xml Thu
Oct 21 19:56:53 2004
@@ -90,6 +90,7 @@
<forward name="registration" path=".registration"/>
<forward name="subscription" path=".subscription"/>
<forward name="success" path=".mainMenu"/>
+ <forward name="failure" path=".welcome"/>
</global-forwards>
@@ -117,7 +118,7 @@
scope="request"
validate="false">
<forward name="failure" path=".mainMenu"/>
- <forward name="success" path=".registration"/>
+ <forward name="success" path=".subscription"/>
</action>
<!-- Process a user logoff -->
Modified: struts/trunk/struts-faces/example2-webapp/src/web/registration.jsp
==============================================================================
--- struts/trunk/struts-faces/example2-webapp/src/web/registration.jsp (original)
+++ struts/trunk/struts-faces/example2-webapp/src/web/registration.jsp Thu Oct 21
19:56:53 2004
@@ -164,6 +164,7 @@
styleClass="command-multiple"
value="Reset"/> <%-- FIXME - i18n --%>
<h:commandButton id="cancel" type="SUBMIT"
+ onclick="bCancel=true;"
styleClass="command-multiple"
value="Cancel"/> <%-- FIXME - i18n --%>
</h:panelGroup>
Modified: struts/trunk/struts-faces/example2-webapp/src/web/subscription.jsp
==============================================================================
--- struts/trunk/struts-faces/example2-webapp/src/web/subscription.jsp (original)
+++ struts/trunk/struts-faces/example2-webapp/src/web/subscription.jsp Thu Oct 21
19:56:53 2004
@@ -181,6 +181,7 @@
value="Reset"/> <%-- FIXME - i18n --%>
<h:commandButton id="cancel"
type="SUBMIT"
+ onclick="bCancel=true;"
styleClass="command-multiple"
value="Cancel"/> <%-- FIXME - i18n --%>
</h:panelGroup>
Modified:
struts/trunk/struts-faces/sysclient-app/src/java/org/apache/struts/faces/sysclient/LogonTestCase.java
==============================================================================
---
struts/trunk/struts-faces/sysclient-app/src/java/org/apache/struts/faces/sysclient/LogonTestCase.java
(original)
+++
struts/trunk/struts-faces/sysclient-app/src/java/org/apache/struts/faces/sysclient/LogonTestCase.java
Thu Oct 21 19:56:53 2004
@@ -131,7 +131,9 @@
span = (HtmlSpan) element("globalErrors");
assertNotNull(span);
- assertEquals("", span.asText());
+ assertEquals("[EH][EP] can not be less than 3 characters.[ES]" +
+ "[EP] is required.[ES][EF]",
+ span.asText());
username = (HtmlTextInput) element("form:username");
assertNotNull(username);
@@ -184,7 +186,7 @@
assertEquals(url + "/logon.faces", action);
assertEquals("", form.getEnctypeAttribute());
assertEquals("post", form.getMethodAttribute());
- assertEquals("", form.getNameAttribute());
+ assertEquals("logonForm", form.getNameAttribute());
assertEquals("", form.getOnResetAttribute());
assertEquals("", form.getOnSubmitAttribute());
assertEquals("", form.getTargetAttribute());
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]