This is an automated email from the ASF dual-hosted git repository.

doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git


The following commit(s) were added to refs/heads/master by this push:
     new b5aa814  EMPIREDB-306 previous implmentation did not work as expected 
and didn't work under Mojarra.
b5aa814 is described below

commit b5aa8144f43e99aab2ff9517e2dce3c9bea55d3a
Author: Rainer Döbele <[email protected]>
AuthorDate: Sat Oct 19 19:14:28 2019 +0200

    EMPIREDB-306
    previous implmentation did not work as expected and didn't work under 
Mojarra.
---
 .../org/apache/empire/jsf2/app/FacesUtils.java     |  16 +-
 .../apache/empire/jsf2/components/ControlTag.java  |  11 ++
 .../apache/empire/jsf2/components/InputTag.java    |  12 +-
 .../empire/jsf2/impl/FacesImplementation.java      |   7 +
 .../empire/jsf2/impl/MojarraImplementation.java    |  68 +++++++-
 .../empire/jsf2/impl/MyFacesImplementation.java    |  59 +++++++
 .../empire/jsf2/utils/TagEncodingHelper.java       | 125 +++++++-------
 .../org/apache/empire/commons/ObjectUtils.java     | 182 +++++++++++++++++++++
 pom.xml                                            |   4 +-
 9 files changed, 414 insertions(+), 70 deletions(-)

diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/FacesUtils.java 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/FacesUtils.java
index 50dad0e..e20c6dc 100644
--- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/FacesUtils.java
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/FacesUtils.java
@@ -29,6 +29,7 @@ import javax.el.ValueExpression;
 import javax.faces.application.FacesMessage;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIInput;
+import javax.faces.component.UIViewRoot;
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 import javax.servlet.ServletContext;
@@ -41,6 +42,7 @@ import org.apache.empire.db.DBDatabase;
 import org.apache.empire.exceptions.EmpireException;
 import org.apache.empire.exceptions.InternalException;
 import org.apache.empire.exceptions.ItemNotFoundException;
+import org.apache.empire.jsf2.impl.FacesImplementation;
 import org.apache.empire.jsf2.pages.Page;
 import org.apache.empire.jsf2.pages.PageDefinition;
 import org.apache.empire.jsf2.pages.PageOutcome;
@@ -62,6 +64,11 @@ public class FacesUtils
         return WebApplication.getInstance();
     }
     
+    public static FacesImplementation getFacesImplementation()
+    {
+        return getWebApplication().getFacesImplementation();    
+    }
+    
     public static FacesContext getContext()
     {
         return FacesContext.getCurrentInstance();
@@ -205,9 +212,14 @@ public class FacesUtils
 
     public static Page getPage(final FacesContext fc)
     {
-        Page page = (Page) getManagedBean(fc, "page");
+        UIViewRoot vr = fc.getViewRoot();
+        if (vr==null)
+            throw new ItemNotFoundException("ViewRoot");
+        // find page
+        Page page = (Page)vr.getViewMap().get("page");
         if (page==null)
-            log.error("Page bean {} does not exist!");
+            throw new ItemNotFoundException("page");
+        // ok
         return page; 
     }
 
diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java
 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java
index 7591393..bff104f 100644
--- 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java
+++ 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java
@@ -395,6 +395,17 @@ public class ControlTag extends UIInput implements 
NamingContainer
     }
 
     @Override
+    public String getId()
+    {
+        String compId = super.getId();
+        // Mojarra-Patch since Id might have been set to "null"
+        if ("null".equals(compId))
+            compId =  helper.completeInputTagId(null);
+        // done
+        return compId;
+    }
+
+    @Override
     public void processDecodes(FacesContext context) 
     {
         if (helper.isInsideUIData())
diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java
index 71f6fe2..59fa69e 100644
--- 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java
+++ 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java
@@ -30,7 +30,6 @@ import javax.faces.context.FacesContext;
 import javax.faces.convert.ConverterException;
 import javax.faces.view.AttachedObjectHandler;
 
-import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.Column;
 import org.apache.empire.db.DBRecord;
 import org.apache.empire.db.exceptions.FieldIllegalValueException;
@@ -219,6 +218,17 @@ public class InputTag extends UIInput implements 
NamingContainer
     }
 
     @Override
+    public String getId()
+    {
+        String compId = super.getId();
+        // Mojarra-Patch since Id might have been set to "null"
+        if ("null".equals(compId))
+            compId =  helper.completeInputTagId(null);
+        // done
+        return compId;
+    }
+
+    @Override
     public void processDecodes(FacesContext context) 
     {
         if (helper.isInsideUIData())
diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/FacesImplementation.java
 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/FacesImplementation.java
index 630cb6c..84548f6 100644
--- 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/FacesImplementation.java
+++ 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/FacesImplementation.java
@@ -84,5 +84,12 @@ public interface FacesImplementation
      *  }
         */
        UIComponent getValueParentComponent(final ValueExpression ve);
+
+       /**
+        * Returns the inner value expression
+        * @param ve the original ValueExpression
+        * @return the unwrapped ValueExpression (may be null)
+        */
+       ValueExpression unwrapValueExpression(ValueExpression ve);
        
 }
diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MojarraImplementation.java
 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MojarraImplementation.java
index e0a5562..441f5d8 100644
--- 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MojarraImplementation.java
+++ 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MojarraImplementation.java
@@ -18,27 +18,36 @@
  */
 package org.apache.empire.jsf2.impl;
 
-import java.util.Map;
-
 import javax.el.ValueExpression;
+import javax.el.VariableMapper;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.StringUtils;
 import org.apache.empire.exceptions.ItemExistsException;
-import org.apache.empire.jsf2.app.WebApplication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.sun.faces.application.ApplicationAssociate;
-import com.sun.faces.application.ApplicationFactoryImpl;
-import com.sun.faces.application.InjectionApplicationFactory;
 import com.sun.faces.component.CompositeComponentStackManager;
 import com.sun.faces.facelets.el.ContextualCompositeValueExpression;
+import com.sun.faces.facelets.el.TagValueExpression;
 import com.sun.faces.mgbean.BeanManager;
 import com.sun.faces.mgbean.ManagedBeanInfo;
 
 public class MojarraImplementation implements FacesImplementation 
 {
-       private BeanManager bm;
+    // Logger
+    private static final Logger log = 
LoggerFactory.getLogger(FacesImplementation.class);
 
+    private BeanManager bm;
+    
+    public MojarraImplementation()
+       {
+           log.debug("MojarraImplementation created");
+       }
+               
        /*
        @Override
        public void initApplication(final FacesApplication application)
@@ -71,7 +80,7 @@ public class MojarraImplementation implements 
FacesImplementation
        @Override
        public Object getManagedBean(final String beanName, final FacesContext 
fc)
        {
-               // Find Bean
+           // Find Bean
            if (bm==null)
             bm = 
ApplicationAssociate.getInstance(fc.getExternalContext()).getBeanManager();
                Object mbean = bm.getBeanFromScope(beanName, fc);
@@ -95,4 +104,49 @@ public class MojarraImplementation implements 
FacesImplementation
         return null;
        }
 
+    @Override
+    public ValueExpression unwrapValueExpression(ValueExpression ve)
+    {
+        // unwrap from com.sun.faces.facelets.el.TagValueExpression
+        if (ve instanceof TagValueExpression)
+        {   // cast and getWrapped
+            ve = ((TagValueExpression)ve).getWrapped();
+        }
+        // now unwrap ValueExpressionImpl
+        if (ve!=null)
+        {   // expected: ve = org.apache.el.ValueExpressionImpl
+            if 
(ve.getClass().getName().equals("org.apache.el.ValueExpressionImpl"))
+            {   // get the Node
+                Object node = ObjectUtils.invokeSimplePrivateMethod(ve, 
"getNode");
+                if (node!=null)
+                {   // we have a Node
+                    // now get the Image
+                    String image = 
StringUtils.toString(ObjectUtils.invokeSimpleMethod(node, "getImage"));
+                    if (StringUtils.isNotEmpty(image)) 
+                    {   // find the varMapper
+                        Object varMapper = 
ObjectUtils.getPrivateFieldValue(ve, "varMapper");
+                        if (varMapper!=null)
+                        {   // Resolve variable using mapper
+                            log.debug("Resolving el-variable \"{}\" using 
VariableMapper", image);
+                            VariableMapper vm = (VariableMapper)varMapper;
+                            ve = vm.resolveVariable(image);
+                        } else {
+                            // Variable not provided!
+                            ve = null;
+                        }
+                    } else {
+                        // no image: unwrapping not necessary
+                        // use original ValueExpression!
+                    }
+                }
+            } else {
+                // unexpected
+                log.warn("Unexpected ValueExpression-Implementation: {}", 
ve.getClass().getName());
+                log.warn("ValueExpression unwrapping does not work!");
+            }
+        }
+        // done 
+        return ve;
+    }
+       
 }
diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MyFacesImplementation.java
 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MyFacesImplementation.java
index 2b60a52..be00d29 100644
--- 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MyFacesImplementation.java
+++ 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MyFacesImplementation.java
@@ -20,16 +20,30 @@ package org.apache.empire.jsf2.impl;
 
 import javax.el.ELContext;
 import javax.el.ValueExpression;
+import javax.el.VariableMapper;
 import javax.faces.application.Application;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.StringUtils;
 import org.apache.empire.exceptions.ItemExistsException;
 import org.apache.myfaces.config.RuntimeConfig;
 import org.apache.myfaces.config.impl.digester.elements.ManagedBeanImpl;
+import org.apache.myfaces.view.facelets.el.ContextAwareTagValueExpression;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class MyFacesImplementation implements FacesImplementation 
 {
+    // Logger
+    private static final Logger log = 
LoggerFactory.getLogger(FacesImplementation.class);
+
+    public MyFacesImplementation()
+    {
+        log.debug("MyFacesImplementation created");
+    }
+    
     /*
        @Override
        public void initApplication(FacesApplication application)
@@ -77,4 +91,49 @@ public class MyFacesImplementation implements 
FacesImplementation
                return null;
        }
 
+    @Override
+    public ValueExpression unwrapValueExpression(ValueExpression ve)
+    {
+        // unwrap from 
org.apache.myfaces.view.facelets.el.ContextAwareTagValueExpression
+        if (ve instanceof ContextAwareTagValueExpression)
+        {   // cast and getWrapped
+            ve = ((ContextAwareTagValueExpression)ve).getWrapped();
+        }
+        // now unwrap ValueExpressionImpl
+        if (ve!=null)
+        {   // expected: ve = org.apache.el.ValueExpressionImpl
+            if 
(ve.getClass().getName().equals("org.apache.el.ValueExpressionImpl"))
+            {   // get the Node
+                Object node = ObjectUtils.invokeSimplePrivateMethod(ve, 
"getNode");
+                if (node!=null)
+                {   // we have a Node
+                    // now get the Image
+                    String image = 
StringUtils.toString(ObjectUtils.invokeSimpleMethod(node, "getImage"));
+                    if (StringUtils.isNotEmpty(image)) 
+                    {   // find the varMapper
+                        Object varMapper = 
ObjectUtils.getPrivateFieldValue(ve, "varMapper");
+                        if (varMapper!=null)
+                        {   // Resolve variable using mapper
+                            log.debug("Resolving el-variable \"{}\" using 
VariableMapper", image);
+                            VariableMapper vm = (VariableMapper)varMapper;
+                            ve = vm.resolveVariable(image);
+                        } else {
+                            // Variable not provided!
+                            ve = null;
+                        }
+                    } else {
+                        // no image: unwrapping not necessary
+                        // use original ValueExpression!
+                    }
+                }
+            } else {
+                // unexpected
+                log.warn("Unexpected ValueExpression-Implementation: {}", 
ve.getClass().getName());
+                log.warn("ValueExpression unwrapping does not work!");
+            }
+        }
+        // done 
+        return ve;
+    }
+
 }
diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
index e61712c..b5683a9 100644
--- 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
+++ 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
@@ -23,9 +23,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.util.Iterator;
 import java.util.Locale;
 
-import javax.el.ELContext;
 import javax.el.ValueExpression;
-import javax.el.ValueReference;
 import javax.faces.FacesWrapper;
 import javax.faces.application.FacesMessage;
 import javax.faces.component.NamingContainer;
@@ -203,7 +201,7 @@ public class TagEncodingHelper implements NamingContainer
         /* Value Options */
         protected boolean hasColumn()
         {
-            return (column != null || getColumn() != null);
+            return (column != null || TagEncodingHelper.this.hasColumn());
         }
 
         @Override
@@ -404,7 +402,7 @@ public class TagEncodingHelper implements NamingContainer
     protected RecordTag           recordTag    = null;
     protected UIData              uiDataTag    = null;
     // protected Boolean          tagRequired  = null;
-    protected Boolean             hasValueRef  = null;
+    protected Boolean             hasValueExpr = null;
     protected InputControl        control      = null;
     protected TextResolver        textResolver = null;
     protected Object              mostRecentValue = null;
@@ -455,11 +453,12 @@ public class TagEncodingHelper implements NamingContainer
         else if (id.indexOf(PH_COLUMN_FULL)>=0) 
         {   // column full name including table
             String name= null;
-            Column c = getColumn();
-            if (c instanceof DBColumn)
-                name = ((DBColumn)c).getFullName().replace('.', '_');
-            else if (c!=null)
-                name = c.getName();
+            if (column==null)
+                column = findColumn();
+            if (column instanceof DBColumn)
+                name = ((DBColumn)column).getFullName().replace('.', '_');
+            else if (column!=null)
+                name = column.getName();
             id = id.replace(PH_COLUMN_FULL, String.valueOf(name));
         }
         // done 
@@ -602,21 +601,29 @@ public class TagEncodingHelper implements NamingContainer
     {
         if (column == null)
             column = findColumn();
+        if (column == null)
+        {   // @deprecated: for compatiblity only!
+            column = findColumnFromValue();  
+            if (column!=null)
+                log.warn("Providing the column as the value is deprecated. Use 
column attribute insteam. This might be removed in future versions!");
+        }
         return (column != null);
     }
 
     public Column getColumn()
     {
-        if (column == null)
-            column = findColumn();
-        if (column == null)
+        if (hasColumn())
+            return this.column;
+        else
             throw new InvalidArgumentException("column", column);
-        return column;
     }
     
     public String getColumnName()
     {
-        return ((this.column=findColumn())!=null ? column.getName() : "null");
+        // don't use hasColumn() or getColumn() here!
+        if (column==null)
+            column = findColumn(); 
+        return (column!=null ? column.getName() : "null");
     }
 
     public void setColumn(Column column)
@@ -792,7 +799,7 @@ public class TagEncodingHelper implements NamingContainer
             if (!(record instanceof Record) || ((Record) record).isReadOnly())
                 return true;
         }
-        else if (!hasValueReference())
+        else if (!hasValueExpression())
         { // No Value expression given
             return true;
         }
@@ -850,7 +857,7 @@ public class TagEncodingHelper implements NamingContainer
             return r.isFieldRequired(getColumn());
         }
         // Check Value Attribute
-        if (hasValueReference())
+        if (hasValueExpression())
             return false;
         // Required
         return getColumn().isRequired();
@@ -918,34 +925,39 @@ public class TagEncodingHelper implements NamingContainer
             // done
             return column;
         }
-        // When null, try value
-        if (col == null)
-        { // Try value
-            col = component.getValue();
-            // Column supplied?
-            if (col instanceof Column)
-            {
-                return (Column) col;
-            }
-            // Column expression supplied?
-            if (col instanceof ColumnExpr)
-            { // Use source column instead 
-                Column source = ((ColumnExpr) col).getSourceColumn();
-                if (source != null)
-                    return source;
-                // No source column? --> wrap 
-                return createColumnExprWrapper((ColumnExpr) col);
-            }
-        }
         // No column!
         if (log.isDebugEnabled() && !(component instanceof LinkTag))
             log.warn("No Column provided for value tag!");
         return null;
     }
+
+    /**
+     * Checks whether the value attribute contains a column reference and 
returns it
+     * @return the column
+     */
+    protected Column findColumnFromValue()
+    {   // Try value
+        Object col = component.getValue();
+        // Column supplied?
+        if (col instanceof Column)
+        {
+            return (Column) col;
+        }
+        // Column expression supplied?
+        if (col instanceof ColumnExpr)
+        { // Use source column instead 
+            Column source = ((ColumnExpr) col).getSourceColumn();
+            if (source != null)
+                return source;
+            // No source column? --> wrap 
+            return createColumnExprWrapper((ColumnExpr) col);
+        }
+        return null;
+    }
     
     protected Column createColumnExprWrapper(ColumnExpr colExpr)
     {
-         return new ColumnExprWrapper(colExpr);
+        return new ColumnExprWrapper(colExpr);
     }
     
     protected ColumnExpr unwrapColumnExpr(Column col)
@@ -961,7 +973,7 @@ public class TagEncodingHelper implements NamingContainer
         if (rec != null)
             return rec;
         // Value expression
-        if (hasValueReference())
+        if (hasValueExpression())
         {   // See if the record is in value
             return null;
         }       
@@ -970,39 +982,36 @@ public class TagEncodingHelper implements NamingContainer
         if (rec==null)
         {   // not supplied
             if ((component instanceof ControlTag) && 
!((ControlTag)component).isCustomInput())
-                log.warn("No record supplied for {} and column {}.", 
component.getClass().getSimpleName(), getColumnName());
+                log.warn("No record supplied for {} and column {}.", 
component.getClass().getSimpleName(), getColumnName()); 
         }
         return rec;
     }
     
-    protected boolean hasValueReference()
+    protected boolean hasValueExpression()
     {
         // Find expression
-        if (hasValueRef != null)
-            return hasValueRef.booleanValue();
+        if (hasValueExpr != null)
+            return hasValueExpr.booleanValue();
         // Find expression
-        boolean hasVR = false;
         ValueExpression ve = findValueExpression("value", false);
         if (ve != null)
-        {   // check
-            ELContext elc = FacesContext.getCurrentInstance().getELContext();
-            ValueReference vr = ve.getValueReference(elc);
-            if (vr!=null && log.isDebugEnabled())  
-            {   // log value reference
-                Object base = vr.getBase();
-                Object property = vr.getProperty();
-                String writeable = (ve.isReadOnly(elc) ? "read-only" : 
"updateable");
-                String beanName = (base!=null ? 
base.getClass().getSimpleName() : "{NULL}");
-                log.debug("Tag-ValueExpression for {} on {}.{} is {}. 
Expression is \"{}\".", getColumnName(), beanName, property, writeable, 
ve.getExpressionString());
+        {   // We have a ValueExpression!
+            // Now unwrap for Facelet-Tags to work
+            String originalExpr = ve.getExpressionString(); // 
log.isDebugEnabled() ? ve.getExpressionString() : null;
+            ve = FacesUtils.getFacesImplementation().unwrapValueExpression(ve);
+            if (originalExpr!=null)
+            {   // log result
+                if (ve!=null)
+                    log.info("ValueExpression \"{}\" has been resolved to 
\"{}\" from class {}", originalExpr, ve.getExpressionString(), 
ve.getClass().getName());
+                else 
+                    log.info("ValueExpression \"{}\" has been resolved to 
NULL", originalExpr);
             }
-            // set result
-            hasVR = (vr!=null);
         }
         // store result to avoid multiple detection 
-        hasValueRef = Boolean.valueOf(hasVR);
-        return hasValueRef.booleanValue();
+        hasValueExpr = Boolean.valueOf(ve!=null);
+        return hasValueExpr.booleanValue();
     }
-    
+        
     protected static final String CC_ATTR_EXPR = "#{cc.attrs.";
     
     @SuppressWarnings("unchecked")
@@ -1021,7 +1030,7 @@ public class TagEncodingHelper implements NamingContainer
             if (ve instanceof FacesWrapper<?>)
                 ve = ((FacesWrapper<ValueExpression>)ve).getWrapped();
             // find parent
-            UIComponent valueParent = 
FacesUtils.getWebApplication().getFacesImplementation().getValueParentComponent(ve);
+            UIComponent valueParent = 
FacesUtils.getFacesImplementation().getValueParentComponent(ve);
             if (valueParent!=null)
             {  // use the value parent
                parent = valueParent;
diff --git a/empire-db/src/main/java/org/apache/empire/commons/ObjectUtils.java 
b/empire-db/src/main/java/org/apache/empire/commons/ObjectUtils.java
index 8884c3a..8a6a3c8 100644
--- a/empire-db/src/main/java/org/apache/empire/commons/ObjectUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/commons/ObjectUtils.java
@@ -19,6 +19,9 @@
 package org.apache.empire.commons;
 
 import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.text.SimpleDateFormat;
@@ -29,6 +32,10 @@ import java.util.List;
 import java.util.Locale;
 
 import org.apache.commons.beanutils.MethodUtils;
+import org.apache.empire.exceptions.EmpireException;
+import org.apache.empire.exceptions.InternalException;
+import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.NotSupportedException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -653,5 +660,180 @@ public final class ObjectUtils
         }
         return false;
     }
+
+    /**
+     * Retrieve a field value using reflection
+     * @param clazz the class from which to obtain the field
+     * @param object the object instance from which to obtain the field
+     * @param property the property to obtain 
+     * @param includePrivateFields flag whether or not to include private 
fields
+     * @return the property value
+     */
+    public static synchronized Object getFieldValue(Class<?> clazz, Object 
object, String property, boolean includePrivateFields)
+    {
+        // check arguments
+        if (object==null)
+            throw new InvalidArgumentException("object", object);
+        if (clazz==null || !clazz.isInstance(object))
+            throw new InvalidArgumentException("clazz", clazz);
+        if (StringUtils.isEmpty(property))
+            throw new InvalidArgumentException("property", property);
+        // begin
+        boolean accessible = true; 
+        Field field = null;
+        try
+        { // find and invoke
+            field = (includePrivateFields ? clazz.getDeclaredField(property) : 
clazz.getField(property));
+            accessible = field.isAccessible();
+            if (includePrivateFields && accessible==false)
+                field.setAccessible(true);
+            // invoke
+            return field.get(object);
+        }
+        catch (NoSuchFieldException e)
+        {   // No such Method
+            if (includePrivateFields)
+            {   // try superclass
+                clazz = clazz.getSuperclass();
+                if (clazz!=null && !clazz.equals(java.lang.Object.class))
+                    return getFieldValue(clazz, object, property, true);
+            }
+            // not found
+            return null;
+        }
+        catch (IllegalAccessException e)
+        {   // Invalid Method definition   
+            throw new NotSupportedException(object, property, e);
+        }
+        finally {
+            // restore accessible
+            if (field!=null && accessible==false)
+                field.setAccessible(false);
+        }
+    }
+
+    /**
+     * Retrieve a field value using reflection
+     * The field accessor must be public
+     * @param object the object instance from which to obtain the field
+     * @param property the property to obtain 
+     * @return the property value
+     */
+    public static Object getFieldValue(Object object, String property)
+    {
+        if (object==null)
+            throw new InvalidArgumentException("object", object);
+        // begin
+        return getFieldValue(object.getClass(), object, property, false);
+    }
+
+    /**
+     * Retrieve a field value using reflection 
+     * @param object the object instance from which to obtain the field
+     * @param property the property to obatin 
+     * @return the property value
+     */
+    public static Object getPrivateFieldValue(Object object, String property)
+    {
+        if (object==null)
+            throw new InvalidArgumentException("object", object);
+        // begin
+        return getFieldValue(object.getClass(), object, property, true);
+    }
+    
+    /**
+     * Invoke a simple method (without parameters) on an object using 
reflection
+     * @param clazz the class from which to obtain the field
+     * @param object the object instance on which to invoke the method
+     * @param methodName the name of the method to invoke 
+     * @param includePrivateMethods flag whether or not to include private 
methods
+     * @return the return value of the method
+     */
+    public static synchronized Object invokeSimpleMethod(Class<?> clazz, 
Object object, String methodName, boolean includePrivateMethods)
+    {
+        // check arguments
+        if (object==null)
+            throw new InvalidArgumentException("object", object);
+        if (clazz==null || !clazz.isInstance(object))
+            throw new InvalidArgumentException("clazz", clazz);
+        if (StringUtils.isEmpty(methodName))
+            throw new InvalidArgumentException("methodName", methodName);
+        // begin
+        boolean accessible = true; 
+        Method method = null;
+        try
+        { // find and invoke
+            method = (includePrivateMethods ? 
clazz.getDeclaredMethod(methodName) : clazz.getMethod(methodName));
+            accessible = method.isAccessible();
+            if (includePrivateMethods && accessible==false)
+                method.setAccessible(true);
+            // invoke
+            return method.invoke(object);
+        }
+        catch (NoSuchMethodException e)
+        {   // No such Method
+            if (includePrivateMethods)
+            {   // try superclass
+                clazz = clazz.getSuperclass();
+                if (clazz!=null && !clazz.equals(java.lang.Object.class))
+                    return invokeSimpleMethod(clazz, object, methodName, true);
+            }
+            // not found
+            return null;
+        }
+        catch (SecurityException e)
+        {   // Invalid Method definition   
+            throw new NotSupportedException(object, methodName, e);
+        }
+        catch (IllegalAccessException e)
+        {   // Invalid Method definition   
+            throw new NotSupportedException(object, methodName, e);
+        }
+        catch (IllegalArgumentException e)
+        {   // Invalid Method definition   
+            throw new NotSupportedException(object, methodName, e);
+        }
+        catch (InvocationTargetException e)
+        {   // Error inside Method
+            Throwable cause = e.getCause();
+            if (cause instanceof EmpireException)
+                throw (EmpireException)cause;
+            // wrap    
+            throw new InternalException(cause);
+        }
+        finally {
+            // restore accessible
+            if (method!=null && accessible==false)
+                method.setAccessible(false);
+        }
+    }
+
+    /**
+     * Invoke a simple method (without parameters) on an object using 
reflection
+     * @param object the object instance on which to invoke the method
+     * @param methodName the name of the method to invoke 
+     * @return the return value of the method
+     */
+    public static Object invokeSimpleMethod(Object object, String methodName)
+    {
+        if (object==null)
+            throw new InvalidArgumentException("object", object);
+        // begin
+        return invokeSimpleMethod(object.getClass(), object, methodName, 
false);
+    }
+
+    /**
+     * Invoke a simple method (without parameters) on an object using 
reflection
+     * @param object the object instance on which to invoke the method
+     * @param methodName the name of the method to invoke 
+     * @return the return value of the method
+     */
+    public static Object invokeSimplePrivateMethod(Object object, String 
methodName)
+    {
+        if (object==null)
+            throw new InvalidArgumentException("object", object);
+        // begin
+        return invokeSimpleMethod(object.getClass(), object, methodName, true);
+    }
     
 }
diff --git a/pom.xml b/pom.xml
index 810058c..3ace06c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -352,12 +352,12 @@
                        <dependency>
                                <groupId>com.sun.faces</groupId>
                                <artifactId>jsf-api</artifactId>
-                               <version>2.2.15</version>
+                               <version>2.2.20</version>
                        </dependency>
                        <dependency>
                                <groupId>com.sun.faces</groupId>
                                <artifactId>jsf-impl</artifactId>
-                               <version>2.2.15</version>
+                               <version>2.2.20</version>
                        </dependency>
                        <!-- Apache MyFaces -->
                        <dependency>

Reply via email to