You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mm...@apache.org on 2006/09/21 22:44:11 UTC

svn commit: r448673 - in /myfaces: shared/trunk/core/src/main/java/org/apache/myfaces/shared/util/ tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/ tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidat...

Author: mmarinschek
Date: Thu Sep 21 13:44:09 2006
New Revision: 448673

URL: http://svn.apache.org/viewvc?view=rev&rev=448673
Log:
fixed TOMAHAWK-50 : custom validator messages (e.g. to prevent equals validator showing password texts)

Added:
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/AttachedListStateWrapper.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/AttachedStateWrapper.java
Modified:
    myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/util/MessageUtils.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/CreditCardValidator.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/ValidateCreditCardTag.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidator/EmailValidator.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidator/ValidateEmailTag.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/equalvalidator/EqualValidator.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/equalvalidator/ValidateEqualTag.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/regexprvalidator/RegExprValidator.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/regexprvalidator/ValidateRegExprTag.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/ValidatorBase.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java
    myfaces/tomahawk/trunk/core/src/main/tld/entities/ext_validator_base_attributes.xml
    myfaces/tomahawk/trunk/examples/simple/src/main/webapp/validate.jsp
    myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/urlvalidator/UrlValidator.java
    myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/urlvalidator/ValidateUrlTag.java
    myfaces/tomahawk/trunk/sandbox/core/src/main/tld/myfaces_sandbox.tld

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/util/MessageUtils.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/util/MessageUtils.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/util/MessageUtils.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/util/MessageUtils.java Thu Sep 21 13:44:09 2006
@@ -247,18 +247,26 @@
      */
     public static FacesMessage getMessage(String bundleBaseName, String messageId, Object params[])
     {
-        Locale locale = null;
+        return getMessage(bundleBaseName, getCurrentLocale(), messageId, params);
+    }
+    
+    /**
+     * 
+     * @return  currently applicable Locale for this request.
+     */
+    public static Locale getCurrentLocale() {
+        Locale locale;
+        
         FacesContext context = FacesContext.getCurrentInstance();
-        if(context != null && context.getViewRoot() != null)
-        {
+        if(context != null && context.getViewRoot() != null) {
             locale = context.getViewRoot().getLocale();
             if(locale == null)
                 locale = Locale.getDefault();
-        } else
-        {
+        } else {
             locale = Locale.getDefault();
         }
-        return getMessage(bundleBaseName, locale, messageId, params);
+        
+        return locale;
     }
 
     /**
@@ -288,7 +296,7 @@
       if (bundleBaseName == null)
       {
           throw new NullPointerException(
-              "Unable to locate ResrouceBundle: bundle is null");
+              "Unable to locate ResourceBundle: bundle is null");
       }
 
       ResourceBundle bundle = ResourceBundle.getBundle(bundleBaseName, locale);
@@ -357,11 +365,7 @@
     {
         if(context == null || messageId == null)
             throw new NullPointerException(" context " + context + " messageId " + messageId);
-        Locale locale = null;
-        if(context != null && context.getViewRoot() != null)
-            locale = context.getViewRoot().getLocale();
-        else
-            locale = Locale.getDefault();
+        Locale locale = getCurrentLocale();
         if(null == locale)
             throw new NullPointerException(" locale " + locale);
         FacesMessage message = getMessage(locale, messageId, params);
@@ -370,6 +374,8 @@
             return message;
         } else
         {
+            // TODO /FIX:  Note that this has fallback behavior to default Locale for message,
+            // but similar behavior above does not.  The methods should probably behave
             locale = Locale.getDefault();
             return getMessage(locale, messageId, params);
         }

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/CreditCardValidator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/CreditCardValidator.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/CreditCardValidator.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/CreditCardValidator.java Thu Sep 21 13:44:09 2006
@@ -15,14 +15,13 @@
  */
 package org.apache.myfaces.custom.creditcardvalidator;
 
+import org.apache.myfaces.validator.ValidatorBase;
+
 import javax.faces.application.FacesMessage;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import javax.faces.validator.ValidatorException;
 
-import org.apache.myfaces.shared_tomahawk.util.MessageUtils;
-import org.apache.myfaces.validator.ValidatorBase;
-
 /**
  * @author mwessendorf (latest modification by $Author$)
  * @version $Revision$ $Date$
@@ -82,10 +81,7 @@
 		initValidator();
 		if (!this.creditCardValidator.isValid(value.toString())){
 			Object[] args = {value.toString()};
-            String message = getMessage();
-            if (null == message)  message = CREDITCARD_MESSAGE_ID;
-
-            throw new ValidatorException(MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, message, args));
+            throw new ValidatorException(getFacesMessage(CREDITCARD_MESSAGE_ID, args));
 		}
 	}
 

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/ValidateCreditCardTag.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/ValidateCreditCardTag.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/ValidateCreditCardTag.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/creditcardvalidator/ValidateCreditCardTag.java Thu Sep 21 13:44:09 2006
@@ -15,13 +15,13 @@
  */
 package org.apache.myfaces.custom.creditcardvalidator;
 
+import org.apache.myfaces.validator.ValidatorBaseTag;
+
 import javax.faces.context.FacesContext;
 import javax.faces.el.ValueBinding;
 import javax.faces.validator.Validator;
 import javax.faces.webapp.UIComponentTag;
 import javax.servlet.jsp.JspException;
-
-import org.apache.myfaces.validator.ValidatorBaseTag;
 
 /**
  * @author mwessendorf (latest modification by $Author$)

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidator/EmailValidator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidator/EmailValidator.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidator/EmailValidator.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidator/EmailValidator.java Thu Sep 21 13:44:09 2006
@@ -21,10 +21,12 @@
 import org.apache.commons.validator.GenericValidator;
 
 import javax.faces.application.FacesMessage;
+import javax.faces.component.StateHolder;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import javax.faces.validator.ValidatorException;
 
+
 /**
  * @author mwessendorf (latest modification by $Author$)
  * @version $Revision$ $Date$
@@ -64,10 +66,7 @@
 			}
 			if (!GenericValidator.isEmail(value.toString())) {
 				Object[] args = {value.toString()};
-                String message = getMessage();
-                if (null == message)  message = EMAIL_MESSAGE_ID;
-
-                throw new ValidatorException(MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, message, args));
+	            throw new ValidatorException(getFacesMessage(EMAIL_MESSAGE_ID, args));
 			}
 
 	}

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidator/ValidateEmailTag.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidator/ValidateEmailTag.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidator/ValidateEmailTag.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/emailvalidator/ValidateEmailTag.java Thu Sep 21 13:44:09 2006
@@ -15,10 +15,10 @@
  */
 package org.apache.myfaces.custom.emailvalidator;
 
+import org.apache.myfaces.validator.ValidatorBaseTag;
+
 import javax.faces.validator.Validator;
 import javax.servlet.jsp.JspException;
-
-import org.apache.myfaces.validator.ValidatorBaseTag;
 
 /**
  * @author mwessendorf (latest modification by $Author$)

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/equalvalidator/EqualValidator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/equalvalidator/EqualValidator.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/equalvalidator/EqualValidator.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/equalvalidator/EqualValidator.java Thu Sep 21 13:44:09 2006
@@ -25,10 +25,12 @@
 import org.apache.myfaces.shared_tomahawk.util.MessageUtils;
 import org.apache.myfaces.validator.ValidatorBase;
 
+
 /**
  * @author mwessendorf (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
+
 public class EqualValidator extends ValidatorBase {
 
 	/**
@@ -48,7 +50,7 @@
 	//the foreign component_id on which the validation is based.
 	private String _for= null;
 
-	// -------------------------------------------------------- ValidatorIF
+  // -------------------------------------------------------- ValidatorIF
 	public void validate(
 		FacesContext facesContext,
 		UIComponent uiComponent,
@@ -78,21 +80,18 @@
 
 		if(foreignEditableValueHolder.getValue()==null || !foreignEditableValueHolder.getValue().toString().equals(value.toString())  )
         {
-            String message = getMessage();
-            if (null == message)  message = EQUAL_MESSAGE_ID;
-
-            throw new ValidatorException(MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, message, args));
+            throw new ValidatorException(getFacesMessage(EQUAL_MESSAGE_ID, args));
         }
 
 	}
 	// -------------------------------------------------------- StateholderIF
 
-    public Object saveState(FacesContext context) {
-        Object values[] = new Object[6];
-        values[0] = super.saveState(context);
-        values[1] = _for;
-        return values;
-    }
+	public Object saveState(FacesContext context) {
+		Object[] state = new Object[2];
+		state[0] = super.saveState(context);
+        state[1] =_for;
+		return state;
+	}
 
     public void restoreState(FacesContext context, Object state) {
         Object values[] = (Object[])state;
@@ -114,5 +113,4 @@
 	public void setFor(String string) {
 		_for = string;
 	}
-
-}
\ No newline at end of file
+}

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/equalvalidator/ValidateEqualTag.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/equalvalidator/ValidateEqualTag.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/equalvalidator/ValidateEqualTag.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/equalvalidator/ValidateEqualTag.java Thu Sep 21 13:44:09 2006
@@ -27,7 +27,9 @@
  * @author mwessendorf (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
+
 public class ValidateEqualTag extends ValidatorBaseTag {
+
   private static final long serialVersionUID = -3249115551944863108L;
   //the foreign component_id on which the validation is based.
 	private String _for = null;

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/regexprvalidator/RegExprValidator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/regexprvalidator/RegExprValidator.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/regexprvalidator/RegExprValidator.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/regexprvalidator/RegExprValidator.java Thu Sep 21 13:44:09 2006
@@ -30,6 +30,7 @@
  * @author mwessendorf (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
+
 public class RegExprValidator extends ValidatorBase {
 	/**
 	 * <p>The standard converter id for this converter.</p>
@@ -54,22 +55,17 @@
 		Object value)
 		throws ValidatorException {
 
-			if (facesContext == null) throw new NullPointerException("facesContext");
-			if (uiComponent == null) throw new NullPointerException("uiComponent");
+		if (facesContext == null) throw new NullPointerException("facesContext");
+		if (uiComponent == null) throw new NullPointerException("uiComponent");
 
-			if (value == null)
+		if (value == null)
 			{
 				return;
 		}
 		Object[] args = {value.toString()};
-		if(!GenericValidator.matchRegexp(value.toString(),"^" + getPattern() + "$")){
-
-            String message = getMessage();
-            if (null == message)  message = REGEXPR_MESSAGE_ID;
-
-            throw new ValidatorException(MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, message, args));
-            }
-
+		if(!GenericValidator.matchRegexp(value.toString(),"^"+getPattern()+"$")){
+			throw new ValidatorException(getFacesMessage(REGEXPR_MESSAGE_ID, args));
+        }
 	}
 
 

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/regexprvalidator/ValidateRegExprTag.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/regexprvalidator/ValidateRegExprTag.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/regexprvalidator/ValidateRegExprTag.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/regexprvalidator/ValidateRegExprTag.java Thu Sep 21 13:44:09 2006
@@ -15,18 +15,19 @@
  */
 package org.apache.myfaces.custom.regexprvalidator;
 
+import org.apache.myfaces.validator.ValidatorBaseTag;
+
 import javax.faces.context.FacesContext;
 import javax.faces.el.ValueBinding;
 import javax.faces.validator.Validator;
 import javax.faces.webapp.UIComponentTag;
 import javax.servlet.jsp.JspException;
 
-import org.apache.myfaces.validator.ValidatorBaseTag;
-
 /**
  * @author mwessendorf (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
+
 public class ValidateRegExprTag extends ValidatorBaseTag {
   private static final long serialVersionUID = -449945949876262076L;
   //the pattern, needed by Commons-Validator.

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/AttachedListStateWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/AttachedListStateWrapper.java?view=auto&rev=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/AttachedListStateWrapper.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/AttachedListStateWrapper.java Thu Sep 21 13:44:09 2006
@@ -0,0 +1,25 @@
+package org.apache.myfaces.validator;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author Manfred Geiler (latest modification by $Author: bdudney $)
+ * @version $Revision: 225333 $ $Date: 2005-07-26 17:49:19 +0200 (Di, 26 Jul 2005) $
+ */
+class AttachedListStateWrapper
+        implements Serializable
+{
+    private static final long serialVersionUID = -3958718149793179776L;
+    private List _wrappedStateList;
+
+    public AttachedListStateWrapper(List wrappedStateList)
+    {
+        _wrappedStateList = wrappedStateList;
+    }
+
+    public List getWrappedStateList()
+    {
+        return _wrappedStateList;
+    }
+}

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/AttachedStateWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/AttachedStateWrapper.java?view=auto&rev=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/AttachedStateWrapper.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/AttachedStateWrapper.java Thu Sep 21 13:44:09 2006
@@ -0,0 +1,39 @@
+package org.apache.myfaces.validator;
+
+import java.io.Serializable;
+
+/**
+ * @author Manfred Geiler (latest modification by $Author: bdudney $)
+ * @version $Revision: 225333 $ $Date: 2005-07-26 17:49:19 +0200 (Di, 26 Jul 2005) $
+ */
+class AttachedStateWrapper
+        implements Serializable
+{
+    private static final long serialVersionUID = 4948301780259917764L;
+    private Class _class;
+    private Object _wrappedStateObject;
+
+    /**
+     * @param clazz null means wrappedStateObject is a List of state objects
+     * @param wrappedStateObject
+     */
+    public AttachedStateWrapper(Class clazz, Object wrappedStateObject)
+    {
+        if (wrappedStateObject != null && !(wrappedStateObject instanceof Serializable))
+        {
+            throw new IllegalArgumentException("Attached state for Object of type " + clazz + " (Class " + wrappedStateObject.getClass().getName() + ") is not serializable");
+        }
+        _class = clazz;
+        _wrappedStateObject = wrappedStateObject;
+    }
+
+    public Class getClazz()
+    {
+        return _class;
+    }
+
+    public Object getWrappedStateObject()
+    {
+        return _wrappedStateObject;
+    }
+}

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/ValidatorBase.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/ValidatorBase.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/ValidatorBase.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/ValidatorBase.java Thu Sep 21 13:44:09 2006
@@ -13,61 +13,123 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.myfaces.validator;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.faces.component.StateHolder;
-import javax.faces.context.FacesContext;
-import javax.faces.el.ValueBinding;
-import javax.faces.validator.Validator;
-
-import org.apache.myfaces.shared_tomahawk.util._ComponentUtils;
 
 /**
  * ValidatorBase provides common attributes and behavior common to all Tomahawk and sandbox validators.
  * Currently this includes:
- *   - getValueBinding(), setValueBinding(), and getFacesContext() methods available in UIComponentBase. 
+ *   - getValueBinding(), setValueBinding(), and getFacesContext() methods available in UIComponentBase.
  *   - a message attribute which can be used to override the message key on a per-validator instance.
- * 
+ *
  * A validator subclass should call getMessage(), and, if not null, use this message key instead.
  * A validator subclass must call super.saveState() and super.restoreState() so that the common attributes are persisted.
- * 
+ *
  * @author mkienenb (latest modification by $Author$)
  * @version $Revision$
+ *//*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
-public abstract class ValidatorBase implements Validator, StateHolder {
 
-    // the message to display when validation fails.
-    protected String _message;
+package org.apache.myfaces.validator;
 
-    //JSF-Field for StateHolder-IF
-    protected boolean _transient = false;
+import java.util.*;
+import java.io.Serializable;
 
-    public String getMessage()
-    {
-        if (_message != null) return _message;
-        ValueBinding vb = getValueBinding("message");
-        return vb != null ? _ComponentUtils.getStringValue(getFacesContext(), vb) : null;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.Validator;
+import javax.faces.el.ValueBinding;
+
+import org.apache.myfaces.shared_tomahawk.util.MessageUtils;
+
+/**
+ * Base validator implementation for Tomahawk validators.
+ *
+ */
+public abstract class ValidatorBase implements StateHolder, Validator {
+
+    private String _summaryMessage = null;
+    private String _detailMessage = null;
+    private boolean _transient = false;
+
+    /**
+     *
+     * @return  The summary message to be displayed
+     */
+    public String getSummaryMessage() {
+        return _summaryMessage;
     }
 
-    public void setMessage(String message)
-    {
-        this._message = message;
+    /**
+     *
+     * @param message   The summary message to be displayed.
+     */
+    public void setSummaryMessage(String message) {
+        _summaryMessage = message;
+    }
+
+    /**
+     *
+     * @return  The message.
+     */
+    public String getMessage() {
+        return getDetailMessage();
+    }
+
+    /**
+     *
+     * @param message  The detail message to be displayed.
+     */
+    public void setMessage(String message) {
+        setDetailMessage(message);
+    }
+
+
+    /**
+     *
+     * @return  The detail message.
+     */
+    public String getDetailMessage() {
+        return _detailMessage;
+    }
+
+    /**
+     *
+     * @param message  The detail message to be displayed.
+     */
+    public void setDetailMessage(String message) {
+        _detailMessage = message;
     }
 
-    // -------------------------------------------------------- StateholderIF
 
+    /**
+     * @param context
+     */
     public Object saveState(FacesContext context) {
-        Object value[] = new Object[1];
-        value[0] = _message;
-        return value;
+        Object[] state = new Object[3];
+        state[0] = _summaryMessage;
+        state[1] = _detailMessage;
+        state[2] = saveValueBindingMap(context);
+        return state;
     }
 
     public void restoreState(FacesContext context, Object state) {
         Object[] values = (Object[]) state;
-         _message = (String) values[0];
+        _summaryMessage = (String) values[0];
+        _detailMessage = (String) values[1];
+        _valueBindingMap = (Map) restoreValueBindingMap(context, values[2]);
     }
 
     public boolean isTransient() {
@@ -78,6 +140,28 @@
         _transient = newTransientValue;
     }
 
+    // Utility methods
+
+    /**
+     * @param defaultMessage The default message we would expect.
+     * @param args Arguments for parsing this message.
+     * @return FacesMessage
+     */
+    protected FacesMessage getFacesMessage(String defaultMessage, Object[] args) {
+        FacesMessage msg;
+
+        if (getSummaryMessage() == null && getDetailMessage() == null)
+        {
+            msg = MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, defaultMessage, args);
+        } else {
+            Locale locale = MessageUtils.getCurrentLocale();
+            String summaryText = MessageUtils.substituteParams(locale, getSummaryMessage(), args);
+            String detailText = MessageUtils.substituteParams(locale, getDetailMessage(), args);
+            msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, summaryText, detailText);
+        }
+        return msg;
+    }
+
     // --------------------- borrowed from UIComponentBase ------------
 
     private Map _valueBindingMap = null;
@@ -106,9 +190,154 @@
         _valueBindingMap.put(name, binding);
     }
 
+    private Object saveValueBindingMap(FacesContext context)
+    {
+        if (_valueBindingMap != null)
+        {
+            int initCapacity = (_valueBindingMap.size() * 4 + 3) / 3;
+            HashMap stateMap = new HashMap(initCapacity);
+            for (Iterator it = _valueBindingMap.entrySet().iterator(); it.hasNext(); )
+            {
+                Map.Entry entry = (Map.Entry)it.next();
+                stateMap.put(entry.getKey(),
+                             saveAttachedState(context, entry.getValue()));
+            }
+            return stateMap;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    private void restoreValueBindingMap(FacesContext context, Object stateObj)
+    {
+        if (stateObj != null)
+        {
+            Map stateMap = (Map)stateObj;
+            int initCapacity = (stateMap.size() * 4 + 3) / 3;
+            _valueBindingMap = new HashMap(initCapacity);
+            for (Iterator it = stateMap.entrySet().iterator(); it.hasNext(); )
+            {
+                Map.Entry entry = (Map.Entry)it.next();
+                _valueBindingMap.put(entry.getKey(),
+                                     restoreAttachedState(context, entry.getValue()));
+            }
+        }
+        else
+        {
+            _valueBindingMap = null;
+        }
+    }
+
+    /**
+     * Serializes objects which are "attached" to this component but which are
+     * not UIComponent children of it. Examples are validator and listener
+     * objects. To be precise, it returns an object which implements
+     * java.io.Serializable, and which when serialized will persist the
+     * state of the provided object.
+     * <p>
+     * If the attachedObject is a List then every object in the list is saved
+     * via a call to this method, and the returned wrapper object contains
+     * a List object.
+     * <p>
+     * If the object implements StateHolder then the object's saveState is
+     * called immediately, and a wrapper is returned which contains both
+     * this saved state and the original class name. However in the case
+     * where the StateHolder.isTransient method returns true, null is
+     * returned instead.
+     * <p>
+     * If the object implements java.io.Serializable then the object is simply
+     * returned immediately; standard java serialization will later be used
+     * to store this object.
+     * <p>
+     * In all other cases, a wrapper is returned which simply stores the type
+     * of the provided object. When deserialized, a default instance of that
+     * type will be recreated.
+     */
+    public static Object saveAttachedState(FacesContext context,
+                                           Object attachedObject)
+    {
+        if (attachedObject == null) return null;
+        if (attachedObject instanceof List)
+        {
+            List lst = new ArrayList(((List)attachedObject).size());
+            for (Iterator it = ((List)attachedObject).iterator(); it.hasNext(); )
+            {
+                lst.add(saveAttachedState(context, it.next()));
+            }
+            return new AttachedListStateWrapper(lst);
+        }
+        else if (attachedObject instanceof StateHolder)
+        {
+            if (((StateHolder)attachedObject).isTransient())
+            {
+                return null;
+            }
+            else
+            {
+                return new AttachedStateWrapper(attachedObject.getClass(),
+                                                 ((StateHolder)attachedObject).saveState(context));
+            }
+        }
+        else if (attachedObject instanceof Serializable)
+        {
+            return attachedObject;
+        }
+        else
+        {
+            return new AttachedStateWrapper(attachedObject.getClass(), null);
+        }
+    }
+
+    public static Object restoreAttachedState(FacesContext context,
+                                              Object stateObj)
+            throws IllegalStateException
+    {
+        if (context == null) throw new NullPointerException("context");
+        if (stateObj == null) return null;
+        if (stateObj instanceof AttachedListStateWrapper)
+        {
+            List lst = ((AttachedListStateWrapper)stateObj).getWrappedStateList();
+            List restoredList = new ArrayList(lst.size());
+            for (Iterator it = lst.iterator(); it.hasNext(); )
+            {
+                restoredList.add(restoreAttachedState(context, it.next()));
+            }
+            return restoredList;
+        }
+        else if (stateObj instanceof AttachedStateWrapper)
+        {
+            Class clazz = ((AttachedStateWrapper)stateObj).getClazz();
+            Object restoredObject;
+            try
+            {
+                restoredObject = clazz.newInstance();
+            }
+            catch (InstantiationException e)
+            {
+                throw new RuntimeException("Could not restore StateHolder of type " + clazz.getName() + " (missing no-args constructor?)", e);
+            }
+            catch (IllegalAccessException e)
+            {
+                throw new RuntimeException(e);
+            }
+            if (restoredObject instanceof StateHolder)
+            {
+                Object wrappedState = ((AttachedStateWrapper)stateObj).getWrappedStateObject();
+                ((StateHolder)restoredObject).restoreState(context, wrappedState);
+            }
+            return restoredObject;
+        }
+        else
+        {
+            return stateObj;
+        }
+    }
+
+
     protected FacesContext getFacesContext()
     {
         return FacesContext.getCurrentInstance();
     }
-
 }

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java Thu Sep 21 13:44:09 2006
@@ -33,27 +33,60 @@
 public class ValidatorBaseTag extends ValidatorTag {
     private static final long serialVersionUID = 4416508071412794682L;
     private String _message = null;
+    private String _detailMessage = null;
+    private String _summaryMessage = null;
 
     public void setMessage(String string) {
         _message = string;
     }
 
+    public void setDetailMessage(String detailMessage)
+    {
+        _detailMessage = detailMessage;
+    }
+
+    public void setSummaryMessage(String summaryMessage)
+    {
+        _summaryMessage = summaryMessage;
+    }
+
     protected Validator createValidator() throws JspException {
 
         ValidatorBase validator = (ValidatorBase)super.createValidator();
 
         FacesContext facesContext = FacesContext.getCurrentInstance();
 
-        if (_message != null)
+        if(_message != null && _detailMessage != null)
+            throw new JspException("you may not set detailMessage and detailMessage together - they serve the same purpose.");
+
+        String detailMessage = _message;
+
+        if(_detailMessage != null)
+            detailMessage = _detailMessage;
+
+        if (detailMessage != null)
+        {
+            if (UIComponentTag.isValueReference(detailMessage))
+            {
+                ValueBinding vb = facesContext.getApplication().createValueBinding(detailMessage);
+                validator.setValueBinding("detailMessage",vb);
+            }
+            else
+            {
+                validator.setDetailMessage(detailMessage);
+            }
+        }
+
+        if (_summaryMessage != null)
         {
-            if (UIComponentTag.isValueReference(_message))
+            if (UIComponentTag.isValueReference(_summaryMessage))
             {
-                ValueBinding vb = facesContext.getApplication().createValueBinding(_message);
-                validator.setMessage(new String(vb.getValue(facesContext).toString()));
+                ValueBinding vb = facesContext.getApplication().createValueBinding(_summaryMessage);
+                validator.setValueBinding("summaryMessage",vb);
             }
             else
             {
-                validator.setMessage(_message);
+                validator.setSummaryMessage(_summaryMessage);
             }
         }
 
@@ -64,5 +97,7 @@
     {
         super.release();
         _message= null;
+        _detailMessage = null;
+        _summaryMessage = null;
     }
 }

Modified: myfaces/tomahawk/trunk/core/src/main/tld/entities/ext_validator_base_attributes.xml
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/tld/entities/ext_validator_base_attributes.xml?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/tld/entities/ext_validator_base_attributes.xml (original)
+++ myfaces/tomahawk/trunk/core/src/main/tld/entities/ext_validator_base_attributes.xml Thu Sep 21 13:44:09 2006
@@ -6,6 +6,25 @@
             <required>false</required>
             <rtexprvalue>false</rtexprvalue>
             <description>
-                alternate validation error message format string
+                alternate validation error detail message format string (use 'message' and 'detailMessage' alternatively)
             </description>
         </attribute>
+        <attribute>
+            <name>detailMessage</name>
+            <required>false</required>
+            <rtexprvalue>false</rtexprvalue>
+            <description>
+                alternate validation error detail message format string (use 'message' and 'detailMessage' alternatively)
+            </description>
+        </attribute>
+        <!--
+        This attribute indicates an alternate validation error summary message format string to display.
+        -->
+        <attribute>
+            <name>summaryMessage</name>
+            <required>false</required>
+            <rtexprvalue>false</rtexprvalue>
+            <description>
+                alternate validation error summary message format string
+            </description>
+        </attribute>
\ No newline at end of file

Modified: myfaces/tomahawk/trunk/examples/simple/src/main/webapp/validate.jsp
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/examples/simple/src/main/webapp/validate.jsp?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/examples/simple/src/main/webapp/validate.jsp (original)
+++ myfaces/tomahawk/trunk/examples/simple/src/main/webapp/validate.jsp Thu Sep 21 13:44:09 2006
@@ -52,19 +52,19 @@
 
                 <h:outputLabel for="email2" value="#{example_messages['validate_email']}2"/>
                 <h:inputText id="email2" value="#{validateForm.email2}" required="true">
-                    <t:validateEmail/>
+                    <t:validateEmail detailMessage="Not a valid email address."/>
                 </h:inputText>
                 <t:message id="emailError2" for="email2" styleClass="error"/>
 
                 <h:outputLabel for="creditCardNumber" value="#{example_messages['validate_credit']}"/>
                 <h:inputText id="creditCardNumber" value="#{validateForm.creditCardNumber}" required="true">
-                    <t:validateCreditCard/>
+                    <t:validateCreditCard detailMessage='#{"{0} is not a valid credit card number."}'/>
                 </h:inputText>
                 <t:message id="creditCardNumberError" for="creditCardNumber" styleClass="error"/>
 
                 <h:outputLabel for="regExprValue" value="#{example_messages['validate_regexp']}"/>
                 <h:inputText id="regExprValue" value="#{validateForm.regExpr}" required="true">
-                    <t:validateRegExpr pattern='\d{5}'/>
+                    <t:validateRegExpr pattern='\d{5}' detailMessage='#{"{0} is not valid in this field." }'/>
                 </h:inputText>
                 <t:message id="regExprValueError" for="regExprValue" styleClass="error"/>
 
@@ -74,7 +74,9 @@
 
                 <h:outputLabel for="equal2" value="#{example_messages['validate_equal']}2"/>
                 <h:inputText id="equal2" value="#{validateForm.equal2}" required="true">
-                    <t:validateEqual for="equal"/>
+                    <t:validateEqual for="equal"
+                                     summaryMessage='#{"Value {0} should equal {1}"}'
+                                     detailMessage='#{"The value of this field, {0}, should equal the value of that other field, {1}"}'/>
                 </h:inputText>
                 <t:message id="equal2Error" for="equal2" styleClass="error"/>
 

Modified: myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/urlvalidator/UrlValidator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/urlvalidator/UrlValidator.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/urlvalidator/UrlValidator.java (original)
+++ myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/urlvalidator/UrlValidator.java Thu Sep 21 13:44:09 2006
@@ -17,6 +17,7 @@
 package org.apache.myfaces.custom.urlvalidator;
 
 import javax.faces.application.FacesMessage;
+import javax.faces.component.StateHolder;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import javax.faces.validator.ValidatorException;
@@ -24,7 +25,6 @@
 import org.apache.commons.validator.GenericValidator;
 import org.apache.myfaces.shared_tomahawk.util.MessageUtils;
 import org.apache.myfaces.validator.ValidatorBase;
-
 /**
  *
  * @author Fabian Frederick
@@ -66,11 +66,8 @@
 			}
 			if (!GenericValidator.isUrl(value.toString())) {
 				Object[] args = {value.toString()};
-                String message = getMessage();
-                if (null == message)  message = URL_MESSAGE_ID;
-
-                throw new ValidatorException(MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, message, args));
-			}
+				throw new ValidatorException(getFacesMessage(URL_MESSAGE_ID, args));
+            }
 
 	}
 

Modified: myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/urlvalidator/ValidateUrlTag.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/urlvalidator/ValidateUrlTag.java?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/urlvalidator/ValidateUrlTag.java (original)
+++ myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/urlvalidator/ValidateUrlTag.java Thu Sep 21 13:44:09 2006
@@ -16,11 +16,11 @@
 
 package org.apache.myfaces.custom.urlvalidator;
 
+import org.apache.myfaces.validator.ValidatorBaseTag;
+
 import javax.faces.validator.Validator;
 import javax.servlet.jsp.JspException;
 
-import org.apache.myfaces.validator.ValidatorBaseTag;
-
 /**
  *
  * @author Fabian Frederick
@@ -34,14 +34,14 @@
 
   public ValidateUrlTag()
     {
-	}
+    }
 
-	protected Validator createValidator() throws JspException
+    protected Validator createValidator() throws JspException
     {
-		setValidatorId(UrlValidator.VALIDATOR_ID);
-	    UrlValidator validator = (UrlValidator)super.createValidator();
-		return validator;
-	}
+        setValidatorId(UrlValidator.VALIDATOR_ID);
+        UrlValidator validator = (UrlValidator)super.createValidator();
+        return validator;
+    }
 
     public void release()
     {

Modified: myfaces/tomahawk/trunk/sandbox/core/src/main/tld/myfaces_sandbox.tld
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core/src/main/tld/myfaces_sandbox.tld?view=diff&rev=448673&r1=448672&r2=448673
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core/src/main/tld/myfaces_sandbox.tld (original)
+++ myfaces/tomahawk/trunk/sandbox/core/src/main/tld/myfaces_sandbox.tld Thu Sep 21 13:44:09 2006
@@ -608,7 +608,6 @@
         &html_anchor_attributes;
     		&user_role_attributes;
 		&ext_forceId_attribute;
-
 		<attribute>
 			<name>resourceRendererClass</name>
 			<required>true</required>
@@ -624,8 +623,7 @@
 				passed by nested f:param elements and/or using session or application scoped beans.
 			</description>
 		</attribute>
-
-	</tag>
+    </tag>
 
 	<!--  effect -->
 	<tag>