You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2011/05/16 23:08:05 UTC

svn commit: r1103891 - in /myfaces/tomahawk/trunk/sandbox/core20: ./ src/main/java/org/apache/myfaces/custom/validatebeanbehavior/

Author: lu4242
Date: Mon May 16 21:08:04 2011
New Revision: 1103891

URL: http://svn.apache.org/viewvc?rev=1103891&view=rev
Log:
TOMAHAWK-1497 New component: ValidateBeanBehavior (thanks to Jan-Kees van Andel for provide this patch)

Added:
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ComponentUtils.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ELContextDecorator.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ExternalSpecifications.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/FacesMessageInterpolatorHolder.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/UIMessagesWrapper.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidateBeanBehavior.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidationPropertyModel.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceResolver.java
    myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceWrapper.java
Modified:
    myfaces/tomahawk/trunk/sandbox/core20/pom.xml

Modified: myfaces/tomahawk/trunk/sandbox/core20/pom.xml
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/pom.xml?rev=1103891&r1=1103890&r2=1103891&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/pom.xml (original)
+++ myfaces/tomahawk/trunk/sandbox/core20/pom.xml Mon May 16 21:08:04 2011
@@ -34,11 +34,13 @@
             <scope>compile</scope>
         </dependency>
 
+        <!-- 
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring</artifactId>
             <scope>compile</scope>
         </dependency>
+         -->
 
         <dependency>
             <groupId>commons-logging</groupId>
@@ -59,16 +61,34 @@
         </dependency>
 
         <dependency>
+            <groupId>javax.validation</groupId>
+            <artifactId>validation-api</artifactId>
+            <version>1.0.0.GA</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.el</groupId>
+            <artifactId>el-api</artifactId>
+            <version>2.1.2-b05</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- 
+        <dependency>
             <groupId>commons-el</groupId>
             <artifactId>commons-el</artifactId>
             <scope>compile</scope>
         </dependency>
+         -->
 
+        <!-- 
         <dependency>
             <groupId>commons-codec</groupId>
             <artifactId>commons-codec</artifactId>
             <scope>compile</scope>
         </dependency>
+         -->
 
         <dependency>
             <groupId>commons-lang</groupId>
@@ -76,18 +96,22 @@
             <scope>compile</scope>
         </dependency>
 
+        <!-- 
         <dependency>
             <groupId>portlet-api</groupId>
             <artifactId>portlet-api</artifactId>
             <version>1.0</version>
             <scope>provided</scope>
         </dependency>
-
+         -->
+         
+        <!-- 
         <dependency>
             <groupId>poi</groupId>
             <artifactId>poi</artifactId>
             <scope>compile</scope>
         </dependency>
+         -->
 
         <!-- provided dependencies -->
 
@@ -111,12 +135,13 @@
             <version>2.5</version>
             <scope>provided</scope>
         </dependency>
-
+<!-- 
         <dependency>
             <groupId>org.freemarker</groupId>
             <artifactId>freemarker</artifactId>
             <scope>compile</scope>
         </dependency>
+         -->
         
         <dependency>
             <groupId>org.apache.myfaces.buildtools</groupId>
@@ -132,10 +157,14 @@
     </dependency>
  -->
  
+     <!-- 
      <dependency>
       <groupId>com.lowagie</groupId>
       <artifactId>itext</artifactId>
-    </dependency> 
+    </dependency>
+     -->
+    
+    
  
         <!-- test dependencies -->
 
@@ -153,27 +182,9 @@
         </dependency>
         
         <dependency>
-            <groupId>org.apache.shale</groupId>
-            <artifactId>shale-test</artifactId>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.apache.myfaces</groupId>
-                    <artifactId>myfaces-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.myfaces</groupId>
-                    <artifactId>myfaces-impl</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>myfaces</groupId>
-                    <artifactId>myfaces-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>myfaces</groupId>
-                    <artifactId>myfaces-impl</artifactId>
-                </exclusion>
-            </exclusions>
+          <groupId>org.apache.myfaces.test</groupId>
+          <artifactId>myfaces-test20</artifactId>
+          <scope>test</scope>
         </dependency>
 
     </dependencies>
@@ -186,9 +197,11 @@
                    <exclude>**/*.vm</exclude>
                 </excludes>
             </resource>
+            <!-- 
             <resource>
                 <directory>target/tomahawk12_resources</directory>
             </resource>
+             -->
         </resources>
         <plugins>
             <plugin>

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ComponentUtils.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ComponentUtils.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ComponentUtils.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ComponentUtils.java Mon May 16 21:08:04 2011
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.validatebeanbehavior;
+
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIForm;
+import javax.faces.component.UIInput;
+import javax.faces.component.UIMessages;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Common component tree utilities.
+ *
+ * @author Jan-Kees van Andel
+ */
+final class ComponentUtils {
+
+    /**
+     * Find and return the parent form for the given component.
+     *
+     * @param component The component.
+     * @return The parent form, never <code>null</code>.
+     * @throws FacesException if no parent form is found.
+     */
+    static UIForm findParentForm(UIComponent component) {
+        while (component.getParent() != null) {
+            component = component.getParent();
+            if (component instanceof UIForm) {
+                return (UIForm) component;
+            }
+        }
+        throw new FacesException("No parent form found");
+    }
+
+    /**
+     * Find and return all UIInput instances in the given form.
+     * <p/>
+     * This method doesn't care about nesting. It looks through the entire form and returns all UIInput components.
+     *
+     * @param form The form to search in.
+     * @return A list with all UIInput components in the form, never <code>null</code>. If nothing is found,
+     *         an empty {java.util.List} is returned.
+     */
+    static List<UIInput> findInputsInForm(UIForm form) {
+        return findInputsInTree(form);
+    }
+
+    /**
+     * Find all UIInput instances that are children of the given component tree.
+     *
+     * @param component The component tree to search in.
+     * @return A list with all UIInput components in the component, never <code>null</code>. If nothing is found,
+     *         an empty {java.util.List} is returned.
+     */
+    private static List<UIInput> findInputsInTree(final UIComponent component) {
+        final List<UIInput> ret = new ArrayList<UIInput>();
+
+        if (component != null) {
+            final List<UIComponent> children = component.getChildren();
+            for (final UIComponent child : children) {
+                if (child instanceof UIInput) {
+                    ret.add((UIInput) child);
+                } else {
+                    ret.addAll(findInputsInTree(child));
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    /**
+     * Find the first UIMessages instance in the given component tree.
+     *
+     * @param component The component tree to search in.
+     * @return The first UIMessages instance, or <code>null</code> if nothing is found.
+     */
+    static UIMessages findMessagesInTree(final UIComponent component) {
+        final List<UIComponent> children = component.getChildren();
+        for (final UIComponent child : children) {
+            if (child instanceof UIMessages) {
+                return (UIMessages) child;
+            } else {
+                final UIMessages messages = findMessagesInTree(child);
+                if (messages != null) {
+                    return messages;
+                }
+            }
+        }
+        return null;
+    }
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ELContextDecorator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ELContextDecorator.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ELContextDecorator.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ELContextDecorator.java Mon May 16 21:08:04 2011
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.validatebeanbehavior;
+
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.FunctionMapper;
+import javax.el.VariableMapper;
+import java.util.Locale;
+
+/**
+ * This ELContext is used to hook into the EL handling, by decorating the
+ * ELResolver chain with a custom ELResolver.
+ *
+ * Note: Copy from MyFaces Core 2.0.
+ *
+ * @author Jan-Kees van Andel
+ */
+final class ELContextDecorator extends ELContext {
+    private final ELContext ctx;
+    private final ELResolver interceptingResolver;
+
+    /**
+     * Only used by ValueExpressionResolver.
+     *
+     * @param elContext            The standard ELContext. All method calls, except getELResolver, are delegated to it.
+     * @param interceptingResolver The ELResolver to be returned by getELResolver.
+     */
+    ELContextDecorator(final ELContext elContext, final ELResolver interceptingResolver) {
+        this.ctx = elContext;
+        this.interceptingResolver = interceptingResolver;
+    }
+
+    /**
+     * This is the important one, it returns the passed ELResolver.
+     *
+     * @return The ELResolver passed into the constructor.
+     */
+    @Override
+    public final ELResolver getELResolver() {
+        return interceptingResolver;
+    }
+
+    // ############################ Standard delegating implementations ############################
+
+    public final FunctionMapper getFunctionMapper() {
+        return ctx.getFunctionMapper();
+    }
+
+    public final VariableMapper getVariableMapper() {
+        return ctx.getVariableMapper();
+    }
+
+    public final void setPropertyResolved(final boolean resolved) {
+        ctx.setPropertyResolved(resolved);
+    }
+
+    public final boolean isPropertyResolved() {
+        return ctx.isPropertyResolved();
+    }
+
+    public final void putContext(final Class key, Object contextObject) {
+        ctx.putContext(key, contextObject);
+    }
+
+    public final Object getContext(final Class key) {
+        return ctx.getContext(key);
+    }
+
+    public final Locale getLocale() {
+        return ctx.getLocale();
+    }
+
+    public final void setLocale(final Locale locale) {
+        ctx.setLocale(locale);
+    }
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ExternalSpecifications.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ExternalSpecifications.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ExternalSpecifications.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ExternalSpecifications.java Mon May 16 21:08:04 2011
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.validatebeanbehavior;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.el.ELContext;
+import javax.validation.Validation;
+import javax.validation.Validator;
+
+/**
+ * <p>
+ * Utility class for determining which specifications are available
+ * in the current process. See JIRA issue: http://issues.apache.org/jira/browse/MYFACES-2386
+ * </p>
+ *
+ * Note: Copy from MyFaces Core 2.0.
+ *
+ * @author Jan-Kees van Andel
+ * @author Jakob Korherr (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ * @since 2.0
+ */
+final class ExternalSpecifications {
+
+    //private static final Log log = LogFactory.getLog(BeanValidator.class);
+    private static final Logger log = Logger.getLogger(ExternalSpecifications.class.getName());
+
+    private static Boolean beanValidationAvailable;
+    private static Boolean unifiedELAvailable;
+
+    /**
+     * Static inner class to prevent NoClassDefFoundErrors when Bean Validation is not available.
+     */
+    private static final class ValidationHolder {
+        static boolean trialErrorValidationInitialization() {
+            try {
+                // Trial-error approach to check for Bean Validation impl existence.
+                // If any Exception occurs here, we assume that Bean Validation is not available.
+                // The cause may be anything, i.e. NoClassDef, config error...
+                final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+
+                return validator != null;
+            } catch (Throwable t) {
+                log.log(Level.FINE, "Error initializing Bean Validation (could be normal)", t);
+                return false;
+            }
+
+        }
+    }
+
+    /**
+     * This method determines if Bean Validation is present.
+     * <p/>
+     * Eager initialization is used for performance. This means Bean Validation binaries
+     * should not be added at runtime after this variable has been set.
+     *
+     * @return true if Bean Validation is available, false otherwise.
+     */
+    static synchronized boolean isBeanValidationAvailable() {
+        if (beanValidationAvailable == null) {
+            try {
+                beanValidationAvailable = (Class.forName("javax.validation.Validation") != null);
+
+                if (beanValidationAvailable) {
+                    beanValidationAvailable = ValidationHolder.trialErrorValidationInitialization();
+                }
+            } catch (Throwable t) {
+                log.log(Level.FINE, "Error loading class (could be normal)", t);
+                beanValidationAvailable = false;
+            }
+
+            log.info("MyFaces Bean Validation support " + (beanValidationAvailable ? "enabled" : "disabled"));
+        }
+        return beanValidationAvailable;
+    }
+
+    /**
+     * This method determines if Unified EL is present.
+     * <p/>
+     * Eager initialization is used for performance. This means Unified EL binaries
+     * should not be added at runtime after this variable has been set.
+     *
+     * @return true if UEL is available, false otherwise.
+     */
+    static synchronized boolean isUnifiedELAvailable() {
+        if (unifiedELAvailable == null) {
+            try {
+                // Check if the UEL classes are available.
+                // If the JSP EL classes are loaded first, UEL will not work
+                // properly, hence it will be disabled.
+                unifiedELAvailable = (
+                        Class.forName("javax.el.ValueReference") != null
+                                && Class.forName("javax.el.ValueExpression")
+                                .getMethod("getValueReference", ELContext.class) != null
+                );
+            } catch (Throwable t) {
+                log.log(Level.FINE, "Error loading class (could be normal)", t);
+                unifiedELAvailable = false;
+            }
+
+            log.info("MyFaces Unified EL support " + (unifiedELAvailable ? "enabled" : "disabled"));
+        }
+        return unifiedELAvailable;
+    }
+
+    /**
+     * this class should not be instantiated.
+     */
+    private ExternalSpecifications() {
+    }
+
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/FacesMessageInterpolatorHolder.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/FacesMessageInterpolatorHolder.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/FacesMessageInterpolatorHolder.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/FacesMessageInterpolatorHolder.java Mon May 16 21:08:04 2011
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.validatebeanbehavior;
+
+import javax.faces.context.FacesContext;
+import javax.validation.MessageInterpolator;
+import javax.validation.ValidatorFactory;
+import java.util.Locale;
+
+/**
+ * Holder class to prevent NoClassDefFoundError in environments without Bean Validation.
+ * <p/>
+ * This is needed, because holder classes are loaded lazily. This means that when it's not
+ * used, it will not be loaded, parsed and initialized. The BeanValidator class is used always,
+ * so the MessageInterpolator references need to be in this separate class.
+ */
+final class FacesMessageInterpolatorHolder {
+
+    // Needs to be volatile.
+    private static volatile FacesMessageInterpolator instance;
+
+    /**
+     * Helper method for initializing the FacesMessageInterpolator.
+     * <p/>
+     * It uses the "Single Check Idiom" as described in Joshua Bloch's Effective Java 2nd Edition.
+     *
+     * @param validatorFactory Used to obtain the MessageInterpolator.
+     * @return The instantiated MessageInterpolator for BeanValidator.
+     */
+    static MessageInterpolator get(final ValidatorFactory validatorFactory) {
+        FacesMessageInterpolatorHolder.FacesMessageInterpolator ret = instance;
+        if (ret == null) {
+            final MessageInterpolator interpolator = validatorFactory.getMessageInterpolator();
+            instance = ret = new FacesMessageInterpolator(interpolator);
+        }
+        return ret;
+    }
+
+    /**
+     * Standard MessageInterpolator, as described in the JSR-314 spec.
+     */
+    private static class FacesMessageInterpolator implements MessageInterpolator {
+        private final MessageInterpolator interpolator;
+
+        FacesMessageInterpolator(final MessageInterpolator interpolator) {
+            this.interpolator = interpolator;
+        }
+
+        public String interpolate(final String s, final Context context) {
+            final Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
+            return interpolator.interpolate(s, context, locale);
+        }
+
+        public String interpolate(final String s, final Context context, final Locale locale) {
+            return interpolator.interpolate(s, context, locale);
+        }
+    }
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/UIMessagesWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/UIMessagesWrapper.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/UIMessagesWrapper.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/UIMessagesWrapper.java Mon May 16 21:08:04 2011
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.validatebeanbehavior;
+
+import java.io.IOException;
+
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
+
+/**
+ * Wrapper component for UIMessages, to make sure there always is a messages placeholder in the DOM.
+ *
+ * @author Jan-Kees van Andel
+ */
+@JSFComponent
+public class UIMessagesWrapper extends UIComponentBase {
+
+    /**
+     * The component type for this component.
+     */
+    public static final String COMPONENT_TYPE = "org.apache.myfaces.custom.validatebeanbehavior.UIMessagesWrapper";
+
+    /**
+     * The component family for this component.
+     */
+    public static final String COMPONENT_FAMILY = "org.apache.myfaces.custom.MessagesWrapper";
+
+    @Override
+    public String getFamily() {
+        return COMPONENT_FAMILY;
+    }
+
+    @Override
+    public void encodeBegin(FacesContext context) throws IOException {
+        super.encodeBegin(context);
+
+        final ResponseWriter writer = context.getResponseWriter();
+        writer.write("<div id=\"");
+        writer.write(getClientId());
+        writer.write("\">");
+    }
+
+    @Override
+    public void encodeEnd(FacesContext context) throws IOException {
+        final ResponseWriter writer = context.getResponseWriter();
+        writer.write("</div>");
+
+        super.encodeEnd(context);
+    }
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidateBeanBehavior.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidateBeanBehavior.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidateBeanBehavior.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidateBeanBehavior.java Mon May 16 21:08:04 2011
@@ -0,0 +1,331 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.validatebeanbehavior;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.el.ValueReference;
+import javax.faces.FacesException;
+import javax.faces.application.ResourceDependency;
+import javax.faces.component.UICommand;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIForm;
+import javax.faces.component.UIInput;
+import javax.faces.component.UIMessages;
+import javax.faces.component.UIViewRoot;
+import javax.faces.component.behavior.ClientBehaviorBase;
+import javax.faces.component.behavior.ClientBehaviorContext;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.DateTimeConverter;
+import javax.servlet.ServletContext;
+import javax.validation.Validation;
+import javax.validation.ValidatorFactory;
+import javax.validation.constraints.Future;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFClientBehavior;
+
+/**
+ * Behavior for Bean Validation validations in JavaScript.
+ * <p/>
+ * This class can be attached to UIComponent instances and validate the entire form.
+ * Any UIMessages instances in the form are looked up and used for positioning error messages.
+ *
+ * @author Jan-Kees van Andel
+ */
+@JSFClientBehavior(
+        name="s:validateBean",
+        id="org.apache.myfaces.custom.ValidateBeanBehavior")
+@ResourceDependency(name = "validateBeanBehavior.js")
+public class ValidateBeanBehavior extends ClientBehaviorBase {
+
+    /** {@inheritDoc} */
+    @Override
+    public String getScript(final ClientBehaviorContext ctx) {
+        final UIComponent component = ctx.getComponent();
+        if (!(component instanceof UICommand)) {
+            throw new FacesException("Unsupported component: " + component + " Only UICommand components are supported");
+        }
+        final UIViewRoot viewRoot = ctx.getFacesContext().getViewRoot();
+
+        UIForm form = ComponentUtils.findParentForm(component);
+        List<UIInput> inputsInForm = ComponentUtils.findInputsInForm(form);
+        UIMessages messages = ComponentUtils.findMessagesInTree(viewRoot);
+
+        return getSubmitHandler(form, inputsInForm, messages);
+    }
+
+    /**
+     * Fetch all necessary metadata and write a JavaScript submit handler to the client.
+     *
+     * @param form The form which must be validated.
+     * @param inputsInForm The input fields in the form.
+     * @param messages The messages to use for displaying error messages.
+     * @return The JavaScript submit handler call.
+     */
+    private String getSubmitHandler(final UIForm form, final List<UIInput> inputsInForm, final UIMessages messages) {
+        final FacesContext fc = FacesContext.getCurrentInstance();
+
+        final String clientId = form.getClientId(fc);
+        final String messagesId = (messages != null) ? "'" + messages.getClientId(fc) + "'": "null";
+        final List<ValidationPropertyModel> validations = new ArrayList<ValidationPropertyModel>();
+
+        for (final UIInput input : inputsInForm) {
+            final PropertyDescriptor propertyDescriptor = getPropertyDescriptor(fc, input);
+            final Set<ConstraintDescriptor<?>> constraints = propertyDescriptor.getConstraintDescriptors();
+            final ValidationPropertyModel model = createValidationModel(input, propertyDescriptor, constraints);
+            validations.add(model);
+        }
+
+        return writeJavaScript(fc, clientId, messagesId, validations);
+    }
+
+    /**
+     * Write the JavaScript submit handler to the client.
+     *
+     * @param fc The FacesContext.
+     * @param clientId The client ID of the form.
+     * @param messagesId The client ID of the messages component.
+     * @param validations The list with field validations.
+     * @return The JavaScript event handler string.
+     */
+    private String writeJavaScript(final FacesContext fc, final String clientId,
+                                   final String messagesId, final List<ValidationPropertyModel> validations) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("return org.jkva.validateBean.validateForm(");
+        sb.append("'").append(clientId).append("', ");
+        sb.append("'").append(messagesId).append("', ");
+        sb.append("[");
+        String sep = "";
+
+        for (final ValidationPropertyModel validationModel : validations) {
+            sb.append(sep);
+            final String validation = writeJavaScriptForField(validationModel, fc);
+            sb.append(validation);
+            sep = ",";
+        }
+
+        sb.append("])");
+        return sb.toString();
+    }
+
+    /**
+     * Write a JSON object with all validation metadata for the given field.
+     *
+     * @param model The validation metadata for a field.
+     * @param fc The FacesContext.
+     * @return The JavaScript event handler string, as a JSON object.
+     */
+    private String writeJavaScriptForField(final ValidationPropertyModel model, final FacesContext fc) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("{");
+        sb.append("fieldId: '").append(model.getComponent().getClientId(fc)).append("'");
+        if (model.isRequired()) {
+            sb.append(",required: true");
+        }
+        sb.append(",type: '").append(model.getType()).append("'");
+        if (model.getMin() != null) {
+            sb.append(",min: true");
+            sb.append(",minValue: ").append(model.getMin()).append("");
+        }
+        if (model.getMax() != null) {
+            sb.append(",max: true");
+            sb.append(",maxValue: ").append(model.getMax()).append("");
+        }
+        if (model.isFutureDate()) {
+            String nowStr = new SimpleDateFormat(model.getDateFormat()).format(new Date());
+            sb.append(",future: true");
+            sb.append(",nowStr: '").append(nowStr).append("'");
+            sb.append(",dateFormat: '").append(model.getDateFormat()).append("'");
+        }
+        sb.append("}");
+
+        return sb.toString();
+    }
+
+    /**
+     * Create the Validation metadata, by inspecting the component, managed bean and {ConstraintDescriptor}s.
+     *
+     * @param component The input component.
+     * @param propertyDescriptor The property descriptor
+     * @param constraints The constraint descriptors.
+     * @return The validation metadata.
+     */
+    private ValidationPropertyModel createValidationModel(final UIComponent component,
+                                                          final PropertyDescriptor propertyDescriptor,
+                                                          final Set<ConstraintDescriptor<?>> constraints) {
+        final ValidationPropertyModel model = new ValidationPropertyModel();
+        model.setComponent(component);
+
+        if (component instanceof UIInput) {
+            model.setRequired(((UIInput) component).isRequired());
+        }
+
+        final Class<?> type = propertyDescriptor.getElementClass();
+        if (type.equals(String.class)) {
+            model.setType("text");
+        } else if (Number.class.isAssignableFrom(type)) {
+            model.setType("numeric");
+        } else if (Date.class.isAssignableFrom(type)
+                || Calendar.class.isAssignableFrom(type)) {
+            model.setType("date");
+        }
+
+        for (final ConstraintDescriptor<?> constraint : constraints) {
+            final Annotation annotation = constraint.getAnnotation();
+            if (annotation instanceof NotNull) {
+                model.setRequired(true);
+            } else if (annotation instanceof Min) {
+                model.setMin(((Min) annotation).value());
+            } else if (annotation instanceof Max) {
+                model.setMax(((Max) annotation).value());
+            } else if (annotation instanceof Future) {
+                model.setFutureDate(true);
+            }
+        }
+
+        final Converter converter = ((UIInput) component).getConverter();
+        if (converter instanceof DateTimeConverter) {
+            model.setDateFormat(((DateTimeConverter) converter).getPattern());
+        }
+
+        return model;
+    }
+
+    // Copied from MyFaces Core 2.0.
+    private PropertyDescriptor getPropertyDescriptor(final FacesContext fc, final UIComponent component) {
+        final ValueReferenceWrapper reference = getValueReference(component, fc);
+
+        if (reference != null) {
+            final Object base = reference.getBase();
+            if (base != null) {
+                final Class<?> valueBaseClass = base.getClass();
+                final String valueProperty = (String) reference.getProperty();
+                if (valueBaseClass != null && valueProperty != null) {
+                    // Initialize Bean Validation.
+                    final ValidatorFactory validatorFactory = createValidatorFactory(fc);
+                    final javax.validation.Validator validator = createValidator(validatorFactory);
+                    final BeanDescriptor beanDescriptor = validator.getConstraintsForClass(valueBaseClass);
+                    if (beanDescriptor.isBeanConstrained()) {
+                        return beanDescriptor.getConstraintsForProperty(valueProperty);
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
+    // Copied from MyFaces Core 2.0.
+    private javax.validation.Validator createValidator(final ValidatorFactory validatorFactory) {
+        return validatorFactory //
+                .usingContext() //
+                .messageInterpolator(FacesMessageInterpolatorHolder.get(validatorFactory)) //
+                .getValidator();
+
+    }
+
+    // Copied from MyFaces Core 2.0.
+    private ValueReferenceWrapper getValueReference(final UIComponent component, final FacesContext context) {
+        final ValueExpression valueExpression = component.getValueExpression("value");
+        final ELContext elCtx = context.getELContext();
+        if (ExternalSpecifications.isUnifiedELAvailable()) {
+            final ValueReference valueReference = getUELValueReference(valueExpression, elCtx);
+            if (valueReference == null) {
+                return null;
+            }
+            return new ValueReferenceWrapper(valueReference.getBase(), valueReference.getProperty());
+        } else {
+            return ValueReferenceResolver.resolve(valueExpression, elCtx);
+        }
+    }
+
+    // Copied from MyFaces Core 2.0.
+    private ValueReference getUELValueReference(final ValueExpression valueExpression, final ELContext elCtx) {
+        final String methodName = "getValueReference";
+        final String methodSignature = valueExpression.getClass().getName() +
+                "." + methodName +
+                "(" + ELContext.class + ")";
+        try {
+            final Method method = valueExpression.getClass().getMethod(methodName, ELContext.class);
+            if (!ValueReference.class.equals(method.getReturnType())
+                    && !ValueReference.class.isAssignableFrom(method.getReturnType())) {
+                throw new NoSuchMethodException(
+                        methodSignature +
+                                "doesn't return " + ValueReference.class +
+                                ", but " + method.getReturnType());
+            }
+            return (ValueReference) method.invoke(valueExpression, elCtx);
+        } catch (NoSuchMethodException e) {
+            throw new FacesException(
+                    "MyFaces indicates Unified EL is available, but method: " +
+                            methodSignature +
+                            " is not available", e);
+        } catch (InvocationTargetException e) {
+            throw new FacesException("Exception invoking " + methodSignature, e);
+        } catch (IllegalAccessException e) {
+            throw new FacesException("Exception invoking " + methodSignature, e);
+        }
+    }
+
+    // Copied from MyFaces Core 2.0.
+    private synchronized ValidatorFactory createValidatorFactory(final FacesContext context) {
+        final Object ctx = context.getExternalContext().getContext();
+        if (ctx instanceof ServletContext) {
+            final ServletContext servletCtx = (ServletContext) ctx;
+            final Object attr = servletCtx.getAttribute(VALIDATOR_FACTORY_KEY);
+            if (attr != null) {
+                return (ValidatorFactory) attr;
+            } else {
+                if (ExternalSpecifications.isBeanValidationAvailable()) {
+                    final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+                    servletCtx.setAttribute(VALIDATOR_FACTORY_KEY, attr);
+                    return factory;
+                } else {
+                    throw new FacesException(
+                            "Bean Validation (API or implementation) is not present, but required for " +
+                                    this.getClass().getSimpleName());
+                }
+            }
+        } else {
+            throw new FacesException("Only Servlet environments are supported for " +
+                    this.getClass().getSimpleName());
+        }
+    }
+
+    // Copied from MyFaces Core 2.0.
+    public static final String VALIDATOR_FACTORY_KEY = "javax.faces.validator.beanValidator.ValidatorFactory";
+}
+

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidationPropertyModel.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidationPropertyModel.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidationPropertyModel.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidationPropertyModel.java Mon May 16 21:08:04 2011
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.validatebeanbehavior;
+
+import javax.faces.component.UIComponent;
+
+/**
+ * This class contains all validation related properties for a single UIInput component.
+ *
+ * @author Jan-Kees van Andel
+ */
+final class ValidationPropertyModel {
+
+    /**
+     * Is this field required?
+     */
+    private boolean required;
+
+    /**
+     * The type of the field, for syntactic validation.
+     */
+    private String type;
+
+    /**
+     * The minimum and maximum value of a number.
+     */
+    private Long min, max;
+
+    /**
+     * A validator that checks if a date is in the future. Today is not considered a future date.
+     */
+    private boolean futureDate;
+
+    /**
+     * The format (SimpleDateFormat pattern) of a date field.
+     */
+    private String dateFormat;
+
+    /**
+     * The corresponding component.
+     */
+    private UIComponent component;
+
+    public boolean isRequired() {
+        return required;
+    }
+
+    public void setRequired(boolean required) {
+        this.required = required;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public Long getMin() {
+        return min;
+    }
+
+    public void setMin(Long min) {
+        this.min = min;
+    }
+
+    public Long getMax() {
+        return max;
+    }
+
+    public void setMax(Long max) {
+        this.max = max;
+    }
+
+    public boolean isFutureDate() {
+        return futureDate;
+    }
+
+    public void setFutureDate(boolean futureDate) {
+        this.futureDate = futureDate;
+    }
+
+    public String getDateFormat() {
+        return dateFormat;
+    }
+
+    public void setDateFormat(String dateFormat) {
+        this.dateFormat = dateFormat;
+    }
+
+    public UIComponent getComponent() {
+        return component;
+    }
+
+    public void setComponent(UIComponent component) {
+        this.component = component;
+    }
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceResolver.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceResolver.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceResolver.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceResolver.java Mon May 16 21:08:04 2011
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.validatebeanbehavior;
+
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.ValueExpression;
+import java.beans.FeatureDescriptor;
+import java.util.Iterator;
+
+/**
+ * This class inspects the EL expression and returns a ValueReferenceWrapper
+ * when Unified EL is not available.
+ *
+ * Note: Copy from MyFaces Core 2.0.
+ */
+final class ValueReferenceResolver extends ELResolver {
+    private final ELResolver resolver;
+
+    /**
+     * This is a simple solution to keep track of the resolved objects,
+     * since ELResolver provides no way to know if the current ELResolver
+     * is the last one in the chain. By assigning (and effectively overwriting)
+     * this field, we know that the value after invoking the chain is always
+     * the last one.
+     * <p/>
+     * This solution also deals with nested objects (like: #{myBean.prop.prop.prop}.
+     */
+    private ValueReferenceWrapper lastObject;
+
+    /**
+     * Constructor is only used internally.
+     *
+     * @param elResolver An ELResolver from the current ELContext.
+     */
+    ValueReferenceResolver(final ELResolver elResolver) {
+        this.resolver = elResolver;
+    }
+
+    /**
+     * This method can be used to extract the ValueReferenceWrapper from the given ValueExpression.
+     *
+     * @param valueExpression The ValueExpression to resolve.
+     * @param elCtx           The ELContext, needed to parse and execute the expression.
+     * @return The ValueReferenceWrapper.
+     */
+    public static ValueReferenceWrapper resolve(final ValueExpression valueExpression, final ELContext elCtx) {
+        final ValueReferenceResolver resolver = new ValueReferenceResolver(elCtx.getELResolver());
+        valueExpression.getValue(new ELContextDecorator(elCtx, resolver));
+        return resolver.lastObject;
+    }
+
+    /**
+     * This method is the only one that matters. It keeps track of the objects in the EL expression.
+     * <p/>
+     * It creates a new ValueReferenceWrapper and assigns it to lastObject.
+     *
+     * @param context  The ELContext.
+     * @param base     The base object, may be null.
+     * @param property The property, may be null.
+     * @return The resolved value
+     */
+    @Override
+    public Object getValue(final ELContext context, final Object base, final Object property) {
+        lastObject = new ValueReferenceWrapper(base, property);
+        return resolver.getValue(context, base, property);
+    }
+
+    // ############################ Standard delegating implementations ############################
+
+    public final Class<?> getType(final ELContext ctx, final Object base, final Object property) {
+        return resolver.getType(ctx, base, property);
+    }
+
+    public final void setValue(final ELContext ctx, final Object base, final Object property, final Object value) {
+        resolver.setValue(ctx, base, property, value);
+    }
+
+    public final boolean isReadOnly(final ELContext ctx, final Object base, final Object property) {
+        return resolver.isReadOnly(ctx, base, property);
+    }
+
+    public final Iterator<FeatureDescriptor> getFeatureDescriptors(final ELContext ctx, final Object base) {
+        return resolver.getFeatureDescriptors(ctx, base);
+    }
+
+    public final Class<?> getCommonPropertyType(final ELContext ctx, final Object base) {
+        return resolver.getCommonPropertyType(ctx, base);
+    }
+
+}

Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceWrapper.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceWrapper.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceWrapper.java Mon May 16 21:08:04 2011
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.validatebeanbehavior;
+
+/**
+ * This class provides access to the object pointed to by the EL expression.
+ * <p/>
+ * It makes the BeanValidator work when Unified EL is not available.
+ *
+ * Note: Copy from MyFaces Core 2.0.
+ */
+final class ValueReferenceWrapper {
+    private final Object base, property;
+
+    /**
+     * Full constructor.
+     *
+     * @param base     The object the reference points to.
+     * @param property The property the reference points to.
+     */
+    public ValueReferenceWrapper(final Object base, final Object property) {
+        this.base = base;
+        this.property = property;
+    }
+
+    /**
+     * The object the reference points to.
+     *
+     * @return base.
+     */
+    public final Object getBase() {
+        return base;
+    }
+
+    /**
+     * The property the reference points to.
+     *
+     * @return property.
+     */
+    public final Object getProperty() {
+        return property;
+    }
+}