Author: tschneider
Date: Fri Nov  9 18:47:29 2007
New Revision: 593725

URL: http://svn.apache.org/viewvc?rev=593725&view=rev
Log:
adding juel plugin as uel plugin

Added:
    struts/sandbox/trunk/struts2-uel-plugin/
    struts/sandbox/trunk/struts2-uel-plugin/pom.xml
    struts/sandbox/trunk/struts2-uel-plugin/src/
    struts/sandbox/trunk/struts2-uel-plugin/src/main/
    struts/sandbox/trunk/struts2-uel-plugin/src/main/java/
    struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/
    struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/
    struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/CompoundRootELContext.java
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelReflectionContextFactory.java
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelReflectionProvider.java
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelValueStack.java
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelValueStackFactory.java
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/contextlistener/
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/contextlistener/UelServletContextListener.java
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/CompoundRootELResolver.java
    
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/XWorkBeanELResolver.java
    struts/sandbox/trunk/struts2-uel-plugin/src/main/resources/
    struts/sandbox/trunk/struts2-uel-plugin/src/main/resources/struts-plugin.xml
    struts/sandbox/trunk/struts2-uel-plugin/src/test/
    struts/sandbox/trunk/struts2-uel-plugin/src/test/java/
    struts/sandbox/trunk/struts2-uel-plugin/src/test/java/org/
    struts/sandbox/trunk/struts2-uel-plugin/src/test/java/org/apache/
    struts/sandbox/trunk/struts2-uel-plugin/src/test/java/org/apache/struts2/
    
struts/sandbox/trunk/struts2-uel-plugin/src/test/java/org/apache/struts2/uelplugin/
    
struts/sandbox/trunk/struts2-uel-plugin/src/test/java/org/apache/struts2/uelplugin/UelTest.java

Added: struts/sandbox/trunk/struts2-uel-plugin/pom.xml
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/pom.xml?rev=593725&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-uel-plugin/pom.xml (added)
+++ struts/sandbox/trunk/struts2-uel-plugin/pom.xml Fri Nov  9 18:47:29 2007
@@ -0,0 +1,82 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+       <modelVersion>4.0.0</modelVersion>
+       <groupId>org.apache.struts2juel</groupId>
+       <artifactId>struts2-uel-plugin</artifactId>
+       <packaging>jar</packaging>
+       <name>Struts 2 Unified EL Plugin</name>
+       <version>1.0.0-SNAPSHOT</version>
+       <build>
+               <plugins>
+                       <plugin>
+                               <artifactId>maven-compiler-plugin</artifactId>
+                               <configuration>
+                                       <source>1.5</source>
+                                       <target>1.5</target>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+       <scm>
+               <connection>
+                       
scm:svn:https://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-uel-plugin
+               </connection>
+               <developerConnection>
+                       
scm:svn:https://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-uel-plugin
+               </developerConnection>
+               
<url>http://https://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-uel-plugin</url>
+       </scm>
+       <dependencies>
+               <dependency>
+                       <groupId>org.apache.struts</groupId>
+                       <artifactId>struts2-core</artifactId>
+                       <version>2.1.1-SNAPSHOT</version>
+                       <exclusions>
+                               <exclusion>
+                                       <groupId>javax.servlet</groupId>
+                                       <artifactId>servlet-api</artifactId>
+                               </exclusion>
+                       </exclusions>
+               </dependency>
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <version>4.4</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>de.odysseus.juel</groupId>
+                       <artifactId>juel</artifactId>
+                       <version>2.1.0</version>
+                       <scope>provided</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.mortbay.jetty</groupId>
+                       <artifactId>jsp-2.1</artifactId>
+                       <version>6.1.3</version>
+                       <scope>provided</scope>
+               </dependency>
+               <dependency>
+                       <groupId>commons-beanutils</groupId>
+                       <artifactId>commons-beanutils</artifactId>
+                       <version>20030211.134440</version>
+               </dependency>
+               <dependency>
+                       <groupId>commons-collections</groupId>
+                       <artifactId>commons-collections</artifactId>
+                       <version>20040616</version>
+               </dependency>
+               <dependency>
+                       <groupId>commons-logging</groupId>
+                       <artifactId>commons-logging</artifactId>
+                       <version>1.1</version>
+                       <exclusions>
+                               <exclusion>
+                                       <groupId>javax.servlet</groupId>
+                                       <artifactId>servlet-api</artifactId>
+                               </exclusion>
+                       </exclusions>
+               </dependency>
+       </dependencies>
+</project>
\ No newline at end of file

Added: 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/CompoundRootELContext.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/CompoundRootELContext.java?rev=593725&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/CompoundRootELContext.java
 (added)
+++ 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/CompoundRootELContext.java
 Fri Nov  9 18:47:29 2007
@@ -0,0 +1,51 @@
+package org.apache.struts2.uelplugin;
+
+import javax.el.ArrayELResolver;
+import javax.el.CompositeELResolver;
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.FunctionMapper;
+import javax.el.ListELResolver;
+import javax.el.MapELResolver;
+import javax.el.ResourceBundleELResolver;
+import javax.el.VariableMapper;
+
+import org.apache.struts2.uelplugin.elresolvers.CompoundRootELResolver;
+import org.apache.struts2.uelplugin.elresolvers.XWorkBeanELResolver;
+
+
+/**
+ * An implementation of SimpleContext that knows about the ValueStack's
+ * CompoundRoot.
+ */
+public class CompoundRootELContext extends ELContext {
+       private ELResolver DEFAULT_RESOLVER_READ_WRITE;
+
+       public CompoundRootELContext() {
+               DEFAULT_RESOLVER_READ_WRITE = new CompositeELResolver() {
+                       {
+                               add(new CompoundRootELResolver());
+                               add(new ArrayELResolver(false));
+                               add(new ListELResolver(false));
+                               add(new MapELResolver(false));
+                               add(new ResourceBundleELResolver());
+                               add(new XWorkBeanELResolver());
+                       }
+               };
+       }
+
+       @Override
+       public VariableMapper getVariableMapper() {
+               return null;
+       }
+
+       @Override
+       public ELResolver getELResolver() {
+               return DEFAULT_RESOLVER_READ_WRITE;
+       }
+
+       @Override
+       public FunctionMapper getFunctionMapper() {
+               return null;
+       }
+}

Added: 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelReflectionContextFactory.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelReflectionContextFactory.java?rev=593725&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelReflectionContextFactory.java
 (added)
+++ 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelReflectionContextFactory.java
 Fri Nov  9 18:47:29 2007
@@ -0,0 +1,15 @@
+package org.apache.struts2.uelplugin;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.opensymphony.xwork2.util.reflection.ReflectionContextFactory;
+
+/**
+ * ReflectionContextFactory for Unified EL.
+ */
+public class UelReflectionContextFactory implements ReflectionContextFactory {
+    public Map createDefaultContext(Object root) {
+        return new HashMap();
+    }
+}

Added: 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelReflectionProvider.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelReflectionProvider.java?rev=593725&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelReflectionProvider.java
 (added)
+++ 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelReflectionProvider.java
 Fri Nov  9 18:47:29 2007
@@ -0,0 +1,58 @@
+package org.apache.struts2.uelplugin;
+
+import java.util.Map;
+
+import javax.el.ELContext;
+import javax.el.ExpressionFactory;
+import javax.el.ValueExpression;
+
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.ognl.OgnlReflectionProvider;
+import com.opensymphony.xwork2.util.CompoundRoot;
+import com.opensymphony.xwork2.util.reflection.ReflectionException;
+
+/**
+ * A OgnlReflectionProvider based on Unified EL.
+ */
+public class UelReflectionProvider extends OgnlReflectionProvider {
+       private ExpressionFactory factory;
+       private XWorkConverter xworkConverter;
+
+       @Inject
+       public void setXWorkConverter(XWorkConverter conv) {
+               this.xworkConverter = conv;
+       }
+
+       public void initExpressionFactory() {
+               if (factory == null) {
+                       factory = ExpressionFactory.newInstance();
+               }
+       }
+       
+    @Override
+    public Object getValue(String expr, Map context, Object root) throws 
ReflectionException {
+       initExpressionFactory();
+        CompoundRoot compoundRoot = new CompoundRoot();
+        compoundRoot.add(root);
+        ELContext elContext = new CompoundRootELContext();
+        elContext.putContext(XWorkConverter.class, xworkConverter);
+        // parse our expression
+        ValueExpression valueExpr = factory.createValueExpression(elContext,
+            expr, String.class);
+        return (String) valueExpr.getValue(elContext);
+    }
+
+    @Override
+    public void setValue(String expr, Map context, Object root, Object value) 
throws ReflectionException {
+       initExpressionFactory();
+        CompoundRoot compoundRoot = new CompoundRoot();
+        compoundRoot.add(root);
+        ELContext elContext = new CompoundRootELContext();
+        elContext.putContext(XWorkConverter.class, xworkConverter);
+        // parse our expression
+        ValueExpression valueExpr = factory.createValueExpression(elContext,
+            expr, String.class);
+        valueExpr.setValue(elContext, value);
+    }
+}

Added: 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelValueStack.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelValueStack.java?rev=593725&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelValueStack.java
 (added)
+++ 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelValueStack.java
 Fri Nov  9 18:47:29 2007
@@ -0,0 +1,168 @@
+package org.apache.struts2.uelplugin;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.ExpressionFactory;
+import javax.el.PropertyNotFoundException;
+import javax.el.ValueExpression;
+
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import com.opensymphony.xwork2.util.CompoundRoot;
+import com.opensymphony.xwork2.util.ValueStack;
+
+/**
+ * A ValueStack that uses Unified EL as the underlying Expression Language.
+ */
+public class UelValueStack implements ValueStack {
+       private CompoundRoot root = new CompoundRoot();
+       private transient Map context;
+       private Class defaultType;
+       private Map overrides;
+       private XWorkConverter xworkConverter;
+
+       private ExpressionFactory factory;
+
+       private ELContext elContext;
+
+       public UelValueStack(ExpressionFactory factory,
+                       XWorkConverter xworkConverter) {
+               this(factory, xworkConverter, new CompoundRoot());
+       }
+
+       public UelValueStack(ExpressionFactory factory,
+                       XWorkConverter xworkConverter, ValueStack vs) {
+               this(factory, xworkConverter, new CompoundRoot(vs.getRoot()));
+       }
+
+       public UelValueStack(ExpressionFactory factory,
+                       XWorkConverter xworkConverter, CompoundRoot root) {
+               this.xworkConverter = xworkConverter;
+               this.factory = factory;
+               setRoot(new CompoundRoot());
+       }
+
+       public String findString(String expr) {
+               return (String) findValue(expr, String.class);
+       }
+
+       public Object findValue(String expr) {
+               return findValue(expr, Object.class);
+       }
+
+       public Object findValue(String expr, Class asType) {
+               try {
+                       if (expr != null && expr.startsWith("#") && 
!expr.startsWith("#{")) {
+                               int firstDot = expr.indexOf('.');
+                               String key = expr.substring(1, firstDot);
+                               String value = expr.substring(firstDot + 1);
+                               Map map = (Map) context.get(key);
+                               return map.get(value);
+                       }
+                       if ((overrides != null) && overrides.containsKey(expr)) 
{
+                               expr = (String) overrides.get(expr);
+                       }
+                       if (expr != null && expr.startsWith("%{")) {
+                               // replace %{ with ${
+                               expr = "#" + expr.substring(1);
+                       }
+                       if (expr != null && !expr.startsWith("${")
+                                       && !expr.startsWith("#{")) {
+                               expr = "#{" + expr + "}";
+                       }
+               elContext.putContext(XWorkConverter.class, xworkConverter);
+               elContext.putContext(CompoundRoot.class, root);
+                       // parse our expression
+                       ValueExpression valueExpr = 
factory.createValueExpression(
+                                       elContext, expr, Object.class);
+                       Object retVal = valueExpr.getValue(elContext);
+                       if (!Object.class.equals(asType)) {
+                               retVal = xworkConverter.convertValue(null, 
retVal, asType);
+                       }
+                       return retVal;
+               } catch (PropertyNotFoundException e) {
+                       // property not found
+                       return null;
+               } catch (ELException e) {
+                       // fail silently so we don't mess things up
+                       return null;
+               }
+       }
+
+       public Map getContext() {
+               return context;
+       }
+
+       public Map getExprOverrides() {
+               return overrides;
+       }
+
+       public CompoundRoot getRoot() {
+               return root;
+       }
+
+       public Object peek() {
+               return root.peek();
+       }
+
+       public Object pop() {
+               return root.pop();
+       }
+
+       public void push(Object o) {
+               root.push(o);
+       }
+
+       public void setDefaultType(Class defaultType) {
+               this.defaultType = defaultType;
+       }
+
+       public void setExprOverrides(Map overrides) {
+               if (this.overrides == null) {
+                       this.overrides = overrides;
+               } else {
+                       this.overrides.putAll(overrides);
+               }
+       }
+
+       public void set(String key, Object o) {
+               overrides.put(key, o);
+       }
+
+       public void setValue(String expr, Object value) {
+               setValue(expr, value, false);
+       }
+
+       public void setValue(String expr, Object value,
+                       boolean throwExceptionOnFailure) {
+               try {
+                       if (expr != null && !expr.startsWith("${")
+                                       && !expr.startsWith("#{")) {
+                               expr = "#{" + expr + "}";
+                       }
+               elContext.putContext(XWorkConverter.class, xworkConverter);
+               elContext.putContext(CompoundRoot.class, root);
+                       // parse our expression
+                       ValueExpression valueExpr = 
factory.createValueExpression(
+                                       elContext, expr, Object.class);
+                       valueExpr.setValue(elContext, value);
+               } catch (ELException e) {
+                       if (throwExceptionOnFailure) {
+                               throw e;
+                       }
+               }
+       }
+
+       public int size() {
+               return root.size();
+       }
+
+       protected void setRoot(CompoundRoot root) {
+               this.context = new TreeMap();
+               context.put(VALUE_STACK, this);
+               this.root = root;
+               elContext = new CompoundRootELContext();
+       }
+}

Added: 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelValueStackFactory.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelValueStackFactory.java?rev=593725&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelValueStackFactory.java
 (added)
+++ 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/UelValueStackFactory.java
 Fri Nov  9 18:47:29 2007
@@ -0,0 +1,38 @@
+package org.apache.struts2.uelplugin;
+
+import javax.el.ExpressionFactory;
+
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+
+/**
+ * Creates JuelValueStacks.
+ */
+public class UelValueStackFactory implements ValueStackFactory {
+       private ExpressionFactory factory;
+
+       private XWorkConverter xworkConverter;
+
+       @Inject
+       public void setXWorkConverter(XWorkConverter conv) {
+               this.xworkConverter = conv;
+       }
+
+       public void initExpressionFactory() {
+               if (factory == null) {
+                       factory = ExpressionFactory.newInstance();
+               }
+       }
+
+       public ValueStack createValueStack() {
+               initExpressionFactory();
+               return new UelValueStack(factory, xworkConverter);
+       }
+
+       public ValueStack createValueStack(ValueStack stack) {
+               initExpressionFactory();
+               return new UelValueStack(factory, xworkConverter, stack);
+       }
+}

Added: 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/contextlistener/UelServletContextListener.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/contextlistener/UelServletContextListener.java?rev=593725&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/contextlistener/UelServletContextListener.java
 (added)
+++ 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/contextlistener/UelServletContextListener.java
 Fri Nov  9 18:47:29 2007
@@ -0,0 +1,30 @@
+package org.apache.struts2.uelplugin.contextlistener;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.jsp.JspApplicationContext;
+import javax.servlet.jsp.JspFactory;
+
+import org.apache.struts2.uelplugin.elresolvers.CompoundRootELResolver;
+import org.apache.struts2.uelplugin.elresolvers.XWorkBeanELResolver;
+
+
+/**
+ * Responsible for registering the ELResolvers.
+ */
+public class UelServletContextListener implements ServletContextListener {
+
+       public void contextInitialized(ServletContextEvent contextEvent) {
+               ServletContext servletContext = 
contextEvent.getServletContext();
+               JspApplicationContext jspApplicationContext = JspFactory
+                               
.getDefaultFactory().getJspApplicationContext(servletContext);
+               jspApplicationContext.addELResolver(new 
CompoundRootELResolver());
+               jspApplicationContext.addELResolver(new XWorkBeanELResolver());
+               contextEvent.getServletContext().log(
+                               "CompoundRootELResolver and XWorkBeanELResolver 
registered");
+       }
+
+       public void contextDestroyed(ServletContextEvent contextEvent) {
+       }
+}

Added: 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/CompoundRootELResolver.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/CompoundRootELResolver.java?rev=593725&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/CompoundRootELResolver.java
 (added)
+++ 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/CompoundRootELResolver.java
 Fri Nov  9 18:47:29 2007
@@ -0,0 +1,203 @@
+package org.apache.struts2.uelplugin.elresolvers;
+
+import java.beans.BeanInfo;
+import java.beans.FeatureDescriptor;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.el.ELContext;
+import javax.el.ELResolver;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.beanutils.PropertyUtils;
+
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import com.opensymphony.xwork2.util.CompoundRoot;
+
+/**
+ * An ELResolver that is capable of resolving properties against the
+ * CompoundRoot if available in the ELContext.
+ */
+public class CompoundRootELResolver extends ELResolver {
+
+       @Override
+       public Class<?> getCommonPropertyType(ELContext context, Object base) {
+               if (base == null) {
+                       return null;
+               }
+
+               return String.class;
+       }
+
+       @Override
+       public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext 
context,
+                       Object base) {
+               // only resolve at the root of the context
+               if (base != null) {
+                       return null;
+               }
+
+               CompoundRoot root = (CompoundRoot) context
+                               .getContext(CompoundRoot.class);
+               if (root == null) {
+                       return null;
+               }
+
+               ArrayList<FeatureDescriptor> list = new 
ArrayList<FeatureDescriptor>();
+               if (root.size() > 0) {
+                       FeatureDescriptor descriptor = new FeatureDescriptor();
+                       descriptor.setValue("type", root.get(0).getClass());
+                       descriptor.setValue("resolvableAtDesignTime", 
Boolean.FALSE);
+                       list.add(descriptor);
+               }
+
+               for (Object bean : root) {
+                       BeanInfo info = null;
+                       try {
+                               info = 
Introspector.getBeanInfo(base.getClass());
+                       } catch (Exception ex) {
+                       }
+                       if (info != null) {
+                               for (PropertyDescriptor pd : 
info.getPropertyDescriptors()) {
+                                       pd.setValue("type", 
pd.getPropertyType());
+                                       pd.setValue("resolvableAtDesignTime", 
Boolean.FALSE);
+                                       list.add(pd);
+                               }
+                       }
+               }
+               return list.iterator();
+       }
+
+       @Override
+       public Class<?> getType(ELContext context, Object base, Object 
property) {
+               // only resolve at the root of the context
+               if (base != null) {
+                       return null;
+               }
+
+               CompoundRoot root = (CompoundRoot) context
+                               .getContext(CompoundRoot.class);
+               if (root == null) {
+                       return null;
+               }
+               String propertyName = (String) property;
+               Object bean = findObjectForProperty(root, propertyName);
+               if (bean == null) {
+                       return null;
+               }
+               try {
+                       Class type = determineType(bean, propertyName);
+                       context.setPropertyResolved(true);
+                       return type;
+               } catch (IllegalAccessException e) {
+                       throw new RuntimeException(e);
+               } catch (InvocationTargetException e) {
+                       throw new RuntimeException(e);
+               } catch (NoSuchMethodException e) {
+                       throw new RuntimeException(e);
+               }
+       }
+
+       @Override
+       public Object getValue(ELContext context, Object base, Object property) 
{
+               if (context == null) {
+                       throw new NullPointerException();
+               }
+               // only resolve at the root of the context
+               if (base != null) {
+                       return null;
+               }
+
+               CompoundRoot root = (CompoundRoot) context
+                               .getContext(CompoundRoot.class);
+               if (root == null) {
+                       return null;
+               }
+               String propertyName = (String) property;
+               if ("top".equals(propertyName) && root.size() > 0) {
+                       return root.get(0);
+               }
+               try {
+                       Object bean = findObjectForProperty(root, propertyName);
+                       if (bean != null) {
+                               Object retVal = PropertyUtils.getProperty(bean, 
propertyName); 
+                               context.setPropertyResolved(true);
+                               return retVal;
+                       }
+               } catch (IllegalAccessException e) {
+                       throw new RuntimeException(e);
+               } catch (InvocationTargetException e) {
+                       throw new RuntimeException(e);
+               } catch (NoSuchMethodException e) {
+                       throw new RuntimeException(e);
+               }
+               return null;
+       }
+
+       @Override
+       public boolean isReadOnly(ELContext context, Object base, Object 
property) {
+               if (context == null) {
+                       throw new NullPointerException();
+               }
+
+               return false;
+       }
+
+       @Override
+       public void setValue(ELContext context, Object base, Object property,
+                       Object value) {
+               if (context == null) {
+                       throw new NullPointerException();
+               }
+               // only resolve at the root of the context
+               if (base != null) {
+                       return;
+               }
+
+               CompoundRoot root = (CompoundRoot) context
+                               .getContext(CompoundRoot.class);
+               String propertyName = (String) property;
+               try {
+                       if (base == null && property != null && root != null) {
+                               Object bean = findObjectForProperty(root, 
propertyName);
+                               if (bean != null) {
+                                       XWorkConverter converter = 
(XWorkConverter) context
+                                                       
.getContext(XWorkConverter.class);
+                                       if (converter != null && root != null) {
+                                               Class propType = 
determineType(bean, propertyName);
+                                               value = 
converter.convertValue(null, value, propType);
+                                       }
+                                       BeanUtils.setProperty(bean, 
propertyName, value);
+                                       context.setPropertyResolved(true);
+                               }
+                       }
+               } catch (IllegalAccessException e) {
+                       throw new RuntimeException(e);
+               } catch (InvocationTargetException e) {
+                       throw new RuntimeException(e);
+               } catch (NoSuchMethodException e) {
+                       throw new RuntimeException(e);
+               }
+       }
+
+       protected Class<?> determineType(Object bean, String property)
+                       throws IllegalAccessException, 
InvocationTargetException, NoSuchMethodException {
+               return PropertyUtils.getPropertyType(bean, property);
+       }
+
+       protected Object findObjectForProperty(CompoundRoot root, String 
propertyName) {
+               if ("top".equals(propertyName) && root.size() > 0) {
+                       return root.get(0);
+               }
+               for (int i = 0; i < root.size(); i++) {
+                       if (PropertyUtils.isReadable(root.get(i), propertyName)
+                                       || 
PropertyUtils.isWriteable(root.get(i), propertyName)) {
+                               return root.get(i);
+                       }
+               }
+               return null;
+       }
+}

Added: 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/XWorkBeanELResolver.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/XWorkBeanELResolver.java?rev=593725&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/XWorkBeanELResolver.java
 (added)
+++ 
struts/sandbox/trunk/struts2-uel-plugin/src/main/java/org/apache/struts2/uelplugin/elresolvers/XWorkBeanELResolver.java
 Fri Nov  9 18:47:29 2007
@@ -0,0 +1,57 @@
+package org.apache.struts2.uelplugin.elresolvers;
+
+import java.lang.reflect.InvocationTargetException;
+
+import javax.el.BeanELResolver;
+import javax.el.ELContext;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+
+public class XWorkBeanELResolver extends BeanELResolver {
+
+       public XWorkBeanELResolver() {
+               super(false);
+       }
+
+       /**
+        * Re-implement this to always return Object. We don't want unified EL 
to do
+        * type conversion, we do that in the setter using xwork type conversion
+        * framework.
+        */
+       @Override
+       public Class<?> getType(ELContext context, Object base, Object 
property) {
+               if (context == null) {
+                       throw new NullPointerException();
+               }
+
+               if (base == null || property == null) {
+                       return null;
+               }
+
+               context.setPropertyResolved(true);
+               return Object.class;
+       }
+
+       @Override
+       public void setValue(ELContext context, Object base, Object property,
+                       Object value) {
+               XWorkConverter converter = (XWorkConverter) context
+                               .getContext(XWorkConverter.class);
+               try {
+                       if (converter != null && base != null) {
+                               Class propType = 
PropertyUtils.getPropertyType(base, property
+                                               .toString());
+                               value = converter.convertValue(null, value, 
propType);
+                       }
+                       super.setValue(context, base, property, value);
+               } catch (IllegalAccessException e) {
+                       throw new RuntimeException(e);
+               } catch (InvocationTargetException e) {
+                       throw new RuntimeException(e);
+               } catch (NoSuchMethodException e) {
+                       throw new RuntimeException(e);
+               }
+       }
+}

Added: 
struts/sandbox/trunk/struts2-uel-plugin/src/main/resources/struts-plugin.xml
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/src/main/resources/struts-plugin.xml?rev=593725&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-uel-plugin/src/main/resources/struts-plugin.xml 
(added)
+++ 
struts/sandbox/trunk/struts2-uel-plugin/src/main/resources/struts-plugin.xml 
Fri Nov  9 18:47:29 2007
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!DOCTYPE struts PUBLIC
+    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+    "http://struts.apache.org/dtds/struts-2.0.dtd";>
+    
+<struts>
+       <bean type="com.opensymphony.xwork2.util.ValueStackFactory" name="uel" 
class=" org.apache.struts2.uelplugin.UelValueStackFactory" />
+       <bean type="com.opensymphony.xwork2.util.reflection.ReflectionProvider" 
name="uel" class="org.apache.struts2.uelplugin.UelReflectionProvider" />        
+       <bean 
type="com.opensymphony.xwork2.util.reflection.ReflectionContextFactory" 
name="uel" class=" org.apache.struts2.uelplugin.UelReflectionContextFactory" />
+
+    <constant name="struts.valueStackFactory" value="uel" />
+    <constant name="struts.reflectionProvider" value="uel" />
+    <constant name="struts.reflectionContextFactory" value="uel" />
+</struts>
\ No newline at end of file

Added: 
struts/sandbox/trunk/struts2-uel-plugin/src/test/java/org/apache/struts2/uelplugin/UelTest.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-uel-plugin/src/test/java/org/apache/struts2/uelplugin/UelTest.java?rev=593725&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-uel-plugin/src/test/java/org/apache/struts2/uelplugin/UelTest.java
 (added)
+++ 
struts/sandbox/trunk/struts2-uel-plugin/src/test/java/org/apache/struts2/uelplugin/UelTest.java
 Fri Nov  9 18:47:29 2007
@@ -0,0 +1,217 @@
+package org.apache.struts2.uelplugin;
+
+import java.lang.reflect.InvocationTargetException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.el.ExpressionFactory;
+
+import org.apache.struts2.uelplugin.UelValueStack;
+import org.apache.struts2.util.StrutsTypeConverter;
+
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import com.opensymphony.xwork2.util.CompoundRoot;
+
+public class UelTest extends XWorkTestCase {
+       private ExpressionFactory factory = ExpressionFactory.newInstance();
+       private XWorkConverter converter;
+       private DateFormat format = DateFormat.getDateInstance();
+
+       private class DateConverter extends StrutsTypeConverter {
+
+               @Override
+               public Object convertFromString(Map context, String[] values,
+                               Class toClass) {
+                       try {
+                               return format.parseObject(values[0]);
+                       } catch (ParseException e) {
+                               return null;
+                       }
+               }
+
+               @Override
+               public String convertToString(Map context, Object o) {
+                       return format.format(o);
+               }
+
+       }
+
+       protected void setUp() throws Exception {
+               super.setUp();
+
+               converter = container.getInstance(XWorkConverter.class);
+               converter.registerConverter("java.util.Date", new 
DateConverter());
+       }
+
+       public void testBasicFind() throws IllegalAccessException,
+                       InvocationTargetException, NoSuchMethodException {
+               CompoundRoot root = new CompoundRoot();
+               TestObject obj = new TestObject();
+               root.add(obj);
+               UelValueStack stack = new UelValueStack(factory, converter);
+               stack.setRoot(root);
+               stack.setValue("${value}", "Hello World");
+               String value = stack.findString("${value}");
+               assertEquals("Hello World", value);
+
+               stack.setValue("${age}", "56");
+               String age = stack.findString("${age}");
+               assertEquals("56", age);
+       }
+
+       public void testSetStringArray() throws IllegalAccessException,
+                       InvocationTargetException, NoSuchMethodException {
+               CompoundRoot root = new CompoundRoot();
+               TestObject obj = new TestObject();
+               root.add(obj);
+               UelValueStack stack = new UelValueStack(factory, converter);
+               stack.setRoot(root);
+               stack.setValue("${value}", new String[] { "Hello World" });
+               String value = stack.findString("${value}");
+               assertEquals("Hello World", value);
+
+               stack.setValue("${age}", new String[] { "67" });
+               assertEquals(new Integer(67), stack.findValue("${age}"));
+       }
+
+       public void testDeferredFind() throws IllegalAccessException,
+                       InvocationTargetException, NoSuchMethodException {
+               CompoundRoot root = new CompoundRoot();
+               TestObject obj = new TestObject();
+               root.add(obj);
+
+               UelValueStack stack = new UelValueStack(factory, converter);
+               stack.setRoot(root);
+               stack.setValue("#{value}", "Hello World");
+               String value = stack.findString("#{value}");
+               assertEquals("Hello World", value);
+
+               stack.setValue("#{age}", "56");
+               String age = stack.findString("#{age}");
+               assertEquals("56", age);
+
+               stack.setValue("#{date}", new Date());
+               assertEquals(stack.findString("#{date}"), 
format.format(obj.getDate()));
+       }
+
+       public void testMap() throws IllegalAccessException,
+                       InvocationTargetException, NoSuchMethodException {
+               CompoundRoot root = new CompoundRoot();
+               HashMap map = new HashMap();
+               map.put("nameValue", "Musachy");
+               TestObject obj = new TestObject();
+               obj.setParameters(map);
+               root.add(obj);
+
+               UelValueStack stack = new UelValueStack(factory, converter);
+               stack.setRoot(root);
+               String value = (String) stack.findValue("parameters.nameValue",
+                               String.class);
+               assertEquals("Musachy", value);
+       }
+
+       public void test2LevelSet() throws IllegalAccessException,
+                       InvocationTargetException, NoSuchMethodException {
+               CompoundRoot root = new CompoundRoot();
+               TestObject obj = new TestObject();
+               TestObject nestedObj = new TestObject();
+               obj.setInner(nestedObj);
+               root.add(obj);
+               UelValueStack stack = new UelValueStack(factory, converter);
+               stack.setRoot(root);
+               stack.setValue("${inner.age}", "66");
+               assertEquals(66, obj.getInner().getAge());
+       }
+
+       public void testTypeConversion() throws IllegalAccessException,
+                       InvocationTargetException, NoSuchMethodException {
+
+               CompoundRoot root = new CompoundRoot();
+               TestObject obj = new TestObject();
+               TestObject inner = new TestObject();
+               obj.setInner(inner);
+               root.add(obj);
+               UelValueStack stack = new UelValueStack(factory, converter);
+               stack.setRoot(root);
+
+               stack.setValue("${age}", "22");
+               assertEquals(stack.findValue("${age}"), obj.getAge());
+
+               stack.setValue("${inner.value}", "George");
+               assertEquals(stack.findValue("${inner.value}"), obj.getInner()
+                               .getValue());
+
+               stack.setValue("${inner.age}", "44");
+               assertEquals(stack.findValue("${inner.age}"), 
obj.getInner().getAge());
+
+               stack.setValue("${date}", new Date());
+               assertEquals(stack.findString("${date}"), 
format.format(obj.getDate()));
+       }
+
+       public void testNotFound() throws IllegalAccessException,
+                       InvocationTargetException, NoSuchMethodException {
+               CompoundRoot root = new CompoundRoot();
+               TestObject obj = new TestObject();
+               root.add(obj);
+               UelValueStack stack = new UelValueStack(factory, converter);
+               stack.setRoot(root);
+               stack.setValue("${value}", "Hello World");
+               String value = stack.findString("${VALUENOTHERE}");
+               assertNull(value);
+
+               value = stack.findString("VALUENOTHERE");
+               assertNull(value);
+       }
+
+       public class TestObject {
+               private String value;
+               private int age;
+               private Date date;
+               private TestObject inner;
+               private Map parameters;
+
+               public String getValue() {
+                       return value;
+               }
+
+               public void setValue(String value) {
+                       this.value = value;
+               }
+
+               public int getAge() {
+                       return age;
+               }
+
+               public void setAge(int age) {
+                       this.age = age;
+               }
+
+               public Date getDate() {
+                       return date;
+               }
+
+               public void setDate(Date date) {
+                       this.date = date;
+               }
+
+               public TestObject getInner() {
+                       return inner;
+               }
+
+               public void setInner(TestObject inner) {
+                       this.inner = inner;
+               }
+
+               public Map getParameters() {
+                       return parameters;
+               }
+
+               public void setParameters(Map parameters) {
+                       this.parameters = parameters;
+               }
+       }
+}


Reply via email to