[seam-commits] Seam SVN: r10644 - in modules/trunk: el and 8 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Mon Apr 27 00:13:09 EDT 2009


Author: shane.bryzak at jboss.com
Date: 2009-04-27 00:13:09 -0400 (Mon, 27 Apr 2009)
New Revision: 10644

Added:
   modules/trunk/el/
   modules/trunk/el/pom.xml
   modules/trunk/el/src/
   modules/trunk/el/src/main/
   modules/trunk/el/src/main/java/
   modules/trunk/el/src/main/java/org/
   modules/trunk/el/src/main/java/org/jboss/
   modules/trunk/el/src/main/java/org/jboss/seam/
   modules/trunk/el/src/main/java/org/jboss/seam/el/
   modules/trunk/el/src/main/java/org/jboss/seam/el/EL.java
   modules/trunk/el/src/main/java/org/jboss/seam/el/Expressions.java
   modules/trunk/el/src/main/java/org/jboss/seam/el/JBossELReferenceCache.java
   modules/trunk/el/src/main/java/org/jboss/seam/el/OptionalParameterMethodExpression.java
   modules/trunk/el/src/main/java/org/jboss/seam/el/SeamELResolver.java
   modules/trunk/el/src/main/java/org/jboss/seam/el/SeamExpressionFactory.java
   modules/trunk/el/src/main/java/org/jboss/seam/el/SeamFunctionMapper.java
Modified:
   modules/trunk/version-matrix/pom.xml
Log:
initial import of el module

Added: modules/trunk/el/pom.xml
===================================================================
--- modules/trunk/el/pom.xml	                        (rev 0)
+++ modules/trunk/el/pom.xml	2009-04-27 04:13:09 UTC (rev 10644)
@@ -0,0 +1,36 @@
+<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">   
+   <parent>
+      <artifactId>seam-parent</artifactId>
+      <groupId>org.jboss.seam</groupId>      
+      <version>3.0.0-SNAPSHOT</version>
+   </parent>    
+  
+   <modelVersion>4.0.0</modelVersion>   
+   <groupId>org.jboss.seam</groupId>
+   <artifactId>seam-el</artifactId>
+   <packaging>jar</packaging>
+   <version>3.0.0-SNAPSHOT</version>
+   <name>Seam EL</name>
+         
+   <dependencies>
+      <dependency>
+         <groupId>org.jboss.webbeans</groupId>
+         <artifactId>jsr299-api</artifactId>
+      </dependency>              
+      <dependency>
+         <groupId>org.jboss.webbeans</groupId>
+         <artifactId>webbeans-logging</artifactId>
+      </dependency>
+      <dependency>
+         <groupId>javax.el</groupId>
+         <artifactId>el-api</artifactId>
+      </dependency>   
+      <dependency>
+         <groupId>org.jboss.el</groupId>
+         <artifactId>jboss-el</artifactId>
+      </dependency>      
+   </dependencies>
+
+</project>

Added: modules/trunk/el/src/main/java/org/jboss/seam/el/EL.java
===================================================================
--- modules/trunk/el/src/main/java/org/jboss/seam/el/EL.java	                        (rev 0)
+++ modules/trunk/el/src/main/java/org/jboss/seam/el/EL.java	2009-04-27 04:13:09 UTC (rev 10644)
@@ -0,0 +1,143 @@
+package org.jboss.seam.el;
+
+import java.util.Locale;
+
+import javax.el.ArrayELResolver;
+import javax.el.BeanELResolver;
+import javax.el.CompositeELResolver;
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.ExpressionFactory;
+import javax.el.FunctionMapper;
+import javax.el.ListELResolver;
+import javax.el.MapELResolver;
+import javax.el.ResourceBundleELResolver;
+import javax.el.VariableMapper;
+
+import org.jboss.el.ExpressionFactoryImpl;
+import org.jboss.el.lang.FunctionMapperImpl;
+import org.jboss.el.lang.VariableMapperImpl;
+
+/**
+ * An instance of JBoss EL.
+ * 
+ * @author Gavin King
+ *
+ */
+public class EL
+{
+   public static final ELResolver EL_RESOLVER = createELResolver();
+   //ELContext instances should not be shared between threads
+   //public static final ELContext EL_CONTEXT = createELContext( EL_RESOLVER, new FunctionMapperImpl() );
+   
+   public static final ExpressionFactory EXPRESSION_FACTORY = new ExpressionFactoryImpl();
+   
+   private static ELResolver createELResolver()
+   {
+      CompositeELResolver resolver = new CompositeELResolver();
+      resolver.add( new SeamELResolver() );
+      resolver.add( new MapELResolver() );
+      resolver.add( new ListELResolver() );
+      resolver.add( new ArrayELResolver() );
+      resolver.add( new ResourceBundleELResolver() );
+      resolver.add( new BeanELResolver() );
+      return resolver;
+   }
+
+   public static ELContext createELContext() {
+       return createELContext( EL_RESOLVER, new FunctionMapperImpl() );
+   }
+   
+   public static ELContext createELContext(final ELResolver resolver, final FunctionMapper functionMapper)
+   {
+      return new ELContext()
+      {
+         final VariableMapperImpl variableMapper = new VariableMapperImpl();
+
+         @Override
+         public ELResolver getELResolver()
+         {
+            return resolver;
+         }
+
+         @Override
+         public FunctionMapper getFunctionMapper()
+         {
+            return functionMapper;
+         }
+
+         @Override
+         public VariableMapper getVariableMapper()
+         {
+            return variableMapper;
+         }
+         
+      };
+   }
+   
+   public static ELContext createELContext(final ELContext context, final ELResolver resolver)
+   {
+      return new ELContext()
+      {
+
+         @Override
+         public Locale getLocale()
+         {
+            return context.getLocale();
+         }
+         
+         @Override
+         public void setPropertyResolved(boolean value)
+         {
+            super.setPropertyResolved(value);
+            context.setPropertyResolved(value);
+         }
+         
+         /*@Override
+         public boolean isPropertyResolved()
+         {
+            return super.isPropertyResolved();
+         }*/
+         
+         @Override
+         public void putContext(Class clazz, Object object)
+         {
+            super.putContext(clazz, object);
+            context.putContext(clazz, object);
+         }
+         
+         @Override
+         public Object getContext(Class clazz)
+         {
+            return context.getContext(clazz);
+         }
+         
+         @Override
+         public void setLocale(Locale locale)
+         {
+            super.setLocale(locale);
+            context.setLocale(locale);
+         }
+         
+         @Override
+         public ELResolver getELResolver()
+         {
+            return resolver;
+         }
+
+         @Override
+         public FunctionMapper getFunctionMapper()
+         {
+            return context.getFunctionMapper();
+         }
+
+         @Override
+         public VariableMapper getVariableMapper()
+         {
+            return context.getVariableMapper();
+         }
+         
+      };
+   }
+   
+}

Added: modules/trunk/el/src/main/java/org/jboss/seam/el/Expressions.java
===================================================================
--- modules/trunk/el/src/main/java/org/jboss/seam/el/Expressions.java	                        (rev 0)
+++ modules/trunk/el/src/main/java/org/jboss/seam/el/Expressions.java	2009-04-27 04:13:09 UTC (rev 10644)
@@ -0,0 +1,220 @@
+package org.jboss.seam.el;
+
+import java.io.Serializable;
+
+import javax.context.ApplicationScoped;
+import javax.el.ELContext;
+import javax.el.ExpressionFactory;
+
+import org.jboss.seam.el.EL;
+import org.jboss.seam.el.SeamExpressionFactory;
+
+/**
+ * Factory for EL method and value expressions.
+ * 
+ * This default implementation uses JBoss EL.
+ * 
+ * @author Gavin King
+ */
+ at ApplicationScoped
+public class Expressions implements Serializable
+{
+   private static final long serialVersionUID = 7420955152664486125L;
+
+   /**
+    * Get the JBoss EL ExpressionFactory
+    */
+   public ExpressionFactory getExpressionFactory()
+   {
+      return SeamExpressionFactory.INSTANCE;
+   }
+   
+   /**
+    * Get an appropriate ELContext. If there is an active JSF request,
+    * use JSF's ELContext. Otherwise, use one that we create.
+    */
+   public ELContext getELContext() {
+       return EL.createELContext();
+   }
+
+   /**
+    * Create a value expression.
+    * 
+    * @param expression a JBoss EL value expression
+    */
+   public ValueExpression<Object> createValueExpression(String expression)
+   {
+      return createValueExpression(expression, Object.class);
+   }
+   
+   /**
+    * Create a method expression.
+    * 
+    * @param expression a JBoss EL method expression
+    */
+   public MethodExpression<Object> createMethodExpression(String expression)
+   {
+      return createMethodExpression(expression, Object.class);
+   }
+   
+   /**
+    * Create a value expression.
+    * 
+    * @param expression a JBoss EL value expression
+    * @param type the type of the value 
+    */
+   public <T> ValueExpression<T> createValueExpression(final String expression, final Class<T> type)
+   {
+      
+      return new ValueExpression<T>()
+      {
+         private javax.el.ValueExpression facesValueExpression;
+         private javax.el.ValueExpression seamValueExpression;
+         
+         public javax.el.ValueExpression toUnifiedValueExpression()
+         {
+            if ( isFacesContextActive() )
+            {
+               if (facesValueExpression==null)
+               {
+                  facesValueExpression = createExpression();
+               }
+               return facesValueExpression;
+            }
+            else
+            {
+               if (seamValueExpression==null)
+               {
+                  seamValueExpression = createExpression();
+               }
+               return seamValueExpression;
+            }
+         }
+         
+         private javax.el.ValueExpression createExpression()
+         {
+            return getExpressionFactory().createValueExpression( getELContext(), expression, type );
+         }
+         
+         public T getValue()
+         {
+            return (T) toUnifiedValueExpression().getValue( getELContext() );
+         }        
+
+        public void setValue(T value)
+         {
+            toUnifiedValueExpression().setValue( getELContext(), value );
+         }
+         
+         public String getExpressionString()
+         {
+            return expression;
+         }
+         
+         public Class<T> getType()
+         {
+            // QUESTION shouldn't we use the type provided in the constructor?
+            return (Class<T>) toUnifiedValueExpression().getType( getELContext() );
+         }
+         
+      };
+   }
+   
+   /**
+    * Create a method expression.
+    * 
+    * @param expression a JBoss EL method expression
+    * @param type the method return type
+    * @param argTypes the method parameter types
+    */
+   public <T> MethodExpression<T> createMethodExpression(final String expression, final Class<T> type, final Class... argTypes)
+   {
+      return new MethodExpression<T>()
+      {
+         private javax.el.MethodExpression facesMethodExpression;
+         private javax.el.MethodExpression seamMethodExpression;
+         
+         public javax.el.MethodExpression toUnifiedMethodExpression()
+         {
+            if ( isFacesContextActive() )
+            {
+               if (facesMethodExpression==null)
+               {
+                  facesMethodExpression = createExpression();
+               }
+               return facesMethodExpression;
+            }
+            else
+            {
+               if (seamMethodExpression==null)
+               {
+                  seamMethodExpression = createExpression();
+               }
+               return seamMethodExpression;
+            }
+         }
+         
+         private javax.el.MethodExpression createExpression()
+         {
+            return getExpressionFactory().createMethodExpression( getELContext(), expression, type, argTypes );
+         }
+         
+         public T invoke(Object... args)
+         {
+            return (T) toUnifiedMethodExpression().invoke( getELContext(), args );
+         }
+         
+         public String getExpressionString()
+         {
+            return expression;
+         }
+         
+      };
+   }
+   
+   /**
+    * A value expression - an EL expression that evaluates to
+    * an attribute getter or get/set pair. This interface
+    * is just a genericized version of the Unified EL ValueExpression
+    * interface.
+    * 
+    * @author Gavin King
+    *
+    * @param <T> the type of the value
+    */
+   public static interface ValueExpression<T> extends Serializable
+   {
+      public T getValue();
+      public void setValue(T value);
+      public String getExpressionString();
+      public Class<T> getType();
+      /**
+       * @return the underlying Unified EL ValueExpression
+       */
+      public javax.el.ValueExpression toUnifiedValueExpression();
+   }
+   
+   /**
+    * A method expression - an EL expression that evaluates to
+    * a method. This interface is just a genericized version of 
+    * the Unified EL ValueExpression interface.
+    * 
+    * @author Gavin King
+    *
+    * @param <T> the method return type
+    */
+   public static interface MethodExpression<T> extends Serializable
+   {
+      public T invoke(Object... args);
+      public String getExpressionString();
+      /**
+       * @return the underlying Unified EL MethodExpression
+       */
+      public javax.el.MethodExpression toUnifiedMethodExpression();
+   }
+   
+   protected boolean isFacesContextActive()
+   {
+      return false;
+   }
+}

Added: modules/trunk/el/src/main/java/org/jboss/seam/el/JBossELReferenceCache.java
===================================================================
--- modules/trunk/el/src/main/java/org/jboss/seam/el/JBossELReferenceCache.java	                        (rev 0)
+++ modules/trunk/el/src/main/java/org/jboss/seam/el/JBossELReferenceCache.java	2009-04-27 04:13:09 UTC (rev 10644)
@@ -0,0 +1,23 @@
+package org.jboss.seam.el;
+
+import javax.annotation.PreDestroy;
+import javax.context.ApplicationScoped;
+import javax.inject.Initializer;
+
+import org.jboss.el.util.ReflectionUtil;
+
+ at ApplicationScoped
+public class JBossELReferenceCache 
+{
+   @Initializer
+   public void start() 
+   {
+      ReflectionUtil.startup();
+   }
+    
+   @PreDestroy
+   public void stop() 
+   {
+      ReflectionUtil.shutdown();
+   }
+}

Added: modules/trunk/el/src/main/java/org/jboss/seam/el/OptionalParameterMethodExpression.java
===================================================================
--- modules/trunk/el/src/main/java/org/jboss/seam/el/OptionalParameterMethodExpression.java	                        (rev 0)
+++ modules/trunk/el/src/main/java/org/jboss/seam/el/OptionalParameterMethodExpression.java	2009-04-27 04:13:09 UTC (rev 10644)
@@ -0,0 +1,80 @@
+/**
+ * 
+ */
+package org.jboss.seam.el;
+
+import javax.el.ELContext;
+import javax.el.MethodExpression;
+import javax.el.MethodInfo;
+import javax.el.MethodNotFoundException;
+
+/**
+ * 
+ * @author Gavin King
+ *
+ */
+class OptionalParameterMethodExpression extends MethodExpression
+{
+    
+    private MethodExpression withParam;
+    private MethodExpression withNoParam;
+    
+   public OptionalParameterMethodExpression(MethodExpression withParam, MethodExpression withNoParam)
+   {
+      this.withParam = withParam;
+      this.withNoParam = withNoParam;
+   }
+
+   @Override
+   public MethodInfo getMethodInfo(ELContext ctx)
+   {
+      return withParam.getMethodInfo(ctx);
+   }
+
+   @Override
+   public Object invoke(ELContext ctx, Object[] args)
+   {
+      try
+      {
+         return withParam.invoke(ctx, args);
+      }
+      catch (MethodNotFoundException mnfe)
+      {
+         try
+         {
+            return withNoParam.invoke(ctx, new Object[0]);
+         }
+         catch (MethodNotFoundException mnfe2)
+         {
+            throw mnfe;
+         }
+      }
+   }
+
+   @Override
+   public String getExpressionString()
+   {
+      return withParam.getExpressionString();
+   }
+
+   @Override
+   public boolean isLiteralText()
+   {
+      return withParam.isLiteralText();
+   }
+
+   @Override
+   public boolean equals(Object object)
+   {
+      if ( !(object instanceof OptionalParameterMethodExpression) ) return false;
+      OptionalParameterMethodExpression other = (OptionalParameterMethodExpression) object;
+      return withParam.equals(other.withParam);
+   }
+
+   @Override
+   public int hashCode()
+   {
+      return withParam.hashCode();
+   }
+    
+ }
\ No newline at end of file

Added: modules/trunk/el/src/main/java/org/jboss/seam/el/SeamELResolver.java
===================================================================
--- modules/trunk/el/src/main/java/org/jboss/seam/el/SeamELResolver.java	                        (rev 0)
+++ modules/trunk/el/src/main/java/org/jboss/seam/el/SeamELResolver.java	2009-04-27 04:13:09 UTC (rev 10644)
@@ -0,0 +1,189 @@
+package org.jboss.seam.el;
+
+import org.jboss.seam.util.JSF;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.el.ELContext;
+import javax.el.ELResolver;
+
+import org.jboss.seam.Namespace;
+import org.jboss.seam.contexts.Context;
+import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.core.Init;
+
+/**
+ * Resolves Seam components and namespaces. Also
+ * allows the use of #{dataModel.size}, #{dataModel.empty},
+ * #{collection.size}, #{map.size}, #{map.values}, #{map.keySet},
+ * and #{map.entrySet}. Also allows #{sessionContext['name']}.
+ * 
+ * @author Gavin King
+ *
+ */
+public class SeamELResolver extends ELResolver
+{
+
+   @Override
+   public Class getCommonPropertyType(ELContext context, Object base)
+   {
+      return null;
+   }
+
+   @Override
+   public Iterator getFeatureDescriptors(ELContext context, Object base)
+   {
+      return null;
+   }
+
+   @Override
+   public Class getType(ELContext context, Object base, Object property)
+   {
+      return null;
+   }
+
+   @Override
+   public Object getValue(ELContext context, Object base, Object property) 
+   {
+        if (base == null) {
+            return resolveBase(context, property);
+            
+        } else if (base instanceof Namespace) {
+            return resolveInNamespace(context, (Namespace) base, property);
+            
+        } else if (JSF.DATA_MODEL.isInstance(base)) {
+            return resolveInDataModel(context,  base, property);
+            
+        } else if (base instanceof Collection) {
+            return resolveInCollection(context, (Collection) base, property);
+            
+        } else if (base instanceof Map) {
+            return resolveInMap(context, (Map) base, property);
+            
+        } else if (base instanceof Context) {
+            return resolveInContextObject(context, (Context) base, property);
+            
+        } else {
+            return null;
+        }
+    }
+
+   private Object resolveInContextObject(ELContext context, Context seamContext, Object property)
+   {
+        if (seamContext.isSet((String) property)) {
+            context.setPropertyResolved(true);
+            return seamContext.get((String) property);
+        } else {
+            return null;
+        }
+    }
+
+   private Object resolveInMap(ELContext context, Map map, Object property) {       
+        try {
+            if (map.containsKey(property)) {
+                return null;
+            }
+        } catch (UnsupportedOperationException e) {
+            // eat it
+        }
+        
+        if ("size".equals(property)) {
+            context.setPropertyResolved(true);
+            return map.size();
+            
+        } else if ("values".equals(property)) {
+            context.setPropertyResolved(true);
+            return map.values();
+        
+        } else if ("keySet".equals(property)) {
+            context.setPropertyResolved(true);
+            return map.keySet();
+        
+        } else if ("entrySet".equals(property)) {
+            context.setPropertyResolved(true);
+            return map.entrySet();
+        
+        } else {
+            return null;
+        }
+    }
+
+   private Object resolveInCollection(ELContext context, Collection collection, Object property)
+   {
+        if ("size".equals(property)) {
+            context.setPropertyResolved(true);
+            return collection.size();
+        } else {
+            return null;
+        }
+    }
+
+   private Object resolveInDataModel(ELContext context, Object base, Object property)
+   {
+        if ("size".equals(property)) {
+            context.setPropertyResolved(true);
+            return JSF.getRowCount(base);
+        } else if ("empty".equals(property)) {
+            context.setPropertyResolved(true);
+            return JSF.getRowCount(base) == 0;
+        } else {
+            return null;
+        }
+    }
+
+   private Object resolveBase(ELContext context, Object property)
+   {
+      if (!Contexts.isApplicationContextActive()) {
+            // if no Seam contexts, bypass straight through to JSF
+            return null;
+        }
+
+        String key = (String) property;
+        Init init = Init.instance();
+
+        // look for a component in the root namespace
+        Object result = init.getRootNamespace().getComponentInstance(key);
+        if (result != null) {
+            context.setPropertyResolved(true);
+            return result;
+        } else {
+            // look for a component in the imported namespaces
+            for (Namespace ns : init.getGlobalImports()) {
+                result = ns.getComponentInstance(key);
+                if (result != null) {
+                    context.setPropertyResolved(true);
+                    return result;
+                }
+            }
+        }
+
+        // look for a namespace
+        Namespace namespace = init.getRootNamespace().getChild(key);
+        if (namespace != null) {
+            context.setPropertyResolved(true);
+        }
+        return namespace;
+    }
+
+    private Object resolveInNamespace(ELContext context, Namespace namespace, Object property) {
+        Object result = namespace.get((String) property);
+        // JBSEAM-3077 if the result is null, it means that there is no component instance bound to this qualified name
+        context.setPropertyResolved(true);
+        return result;
+    }
+
+    @Override
+    public boolean isReadOnly(ELContext context, Object base, Object property) 
+    {
+        return base != null
+                && (JSF.DATA_MODEL.isInstance(base) || (base instanceof Collection) || (base instanceof Map));
+    }
+
+    @Override
+    public void setValue(ELContext context, Object base, Object property, Object value) 
+    {
+    }
+
+}

Added: modules/trunk/el/src/main/java/org/jboss/seam/el/SeamExpressionFactory.java
===================================================================
--- modules/trunk/el/src/main/java/org/jboss/seam/el/SeamExpressionFactory.java	                        (rev 0)
+++ modules/trunk/el/src/main/java/org/jboss/seam/el/SeamExpressionFactory.java	2009-04-27 04:13:09 UTC (rev 10644)
@@ -0,0 +1,101 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.el;
+
+import javax.el.ELContext;
+import javax.el.ExpressionFactory;
+import javax.el.MethodExpression;
+import javax.el.ValueExpression;
+
+import org.jboss.el.lang.EvaluationContext;
+import org.jboss.seam.util.JSF;
+
+/**
+ * Allows JSF action listener methods to not declare the
+ * totally useless ActionEvent parameter if they don't
+ * want to. 
+ *
+ * @author Gavin King
+ */
+public class SeamExpressionFactory extends ExpressionFactory 
+{
+   public static final ExpressionFactory INSTANCE = new SeamExpressionFactory(EL.EXPRESSION_FACTORY);
+   
+    private static final Class[] NO_CLASSES = {};
+    
+    private final ExpressionFactory expressionFactory;
+    
+    SeamExpressionFactory(ExpressionFactory expressionFactory) 
+    {
+       this.expressionFactory = expressionFactory;
+    }
+    
+    /**
+     * Wrap the base ELContext, adding Seam's FunctionMapper.
+     * 
+     * Thus, any expressions with s:hasRole, s:hasPermission 
+     * must be evaluated either via Facelets/JSP (since they
+     * are declared in the tld/taglib.xml or via the 
+     * Expressions component.
+     * 
+     * @param context the JSF ELContext
+     */
+    private static EvaluationContext decorateELContext(ELContext context)
+    {
+       return new EvaluationContext( context, new SeamFunctionMapper( context.getFunctionMapper() ), context.getVariableMapper() );
+    }
+    
+    @Override
+    public Object coerceToType(Object obj, Class targetType) 
+    {
+        return expressionFactory.coerceToType(obj, targetType);
+    }
+
+    @Override
+    public MethodExpression createMethodExpression(ELContext elContext, String expression, Class returnType, Class[] paramTypes) 
+    {
+        if ( paramTypes.length==1 && JSF.FACES_EVENT.isAssignableFrom( paramTypes[0] ) )
+        {
+         return new OptionalParameterMethodExpression(
+                 expressionFactory.createMethodExpression( decorateELContext(elContext), expression, returnType, paramTypes ),
+                 expressionFactory.createMethodExpression( decorateELContext(elContext), expression, returnType, NO_CLASSES )
+              );
+        }
+        else
+        {
+           return expressionFactory.createMethodExpression( decorateELContext(elContext), expression, returnType, paramTypes );
+        }
+    }
+    
+    @Override
+    public ValueExpression createValueExpression(Object instance, Class expectedType) 
+    {
+        return expressionFactory.createValueExpression(instance, expectedType);
+    }
+
+    @Override
+    public ValueExpression createValueExpression(ELContext elContext, String expression, Class expectedType) 
+    {   
+        return expressionFactory.createValueExpression( decorateELContext(elContext), expression, expectedType );
+    }
+    
+}
\ No newline at end of file

Added: modules/trunk/el/src/main/java/org/jboss/seam/el/SeamFunctionMapper.java
===================================================================
--- modules/trunk/el/src/main/java/org/jboss/seam/el/SeamFunctionMapper.java	                        (rev 0)
+++ modules/trunk/el/src/main/java/org/jboss/seam/el/SeamFunctionMapper.java	2009-04-27 04:13:09 UTC (rev 10644)
@@ -0,0 +1,114 @@
+package org.jboss.seam.el;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.el.FunctionMapper;
+
+import org.jboss.el.lang.ExtendedFunctionMapper;
+import org.jboss.webbeans.log.LogProvider;
+import org.jboss.webbeans.log.Logging;
+import org.jboss.seam.security.SecurityFunctions;
+
+/**
+ * Resolves Seam Security EL functions, s:hasRole() and s:hasPermission()
+ * by decorating a delegate Unified EL FunctionMapper
+ *  
+ * @author Shane Bryzak
+ */
+public class SeamFunctionMapper extends ExtendedFunctionMapper
+{
+   private static Map<String,List<Method>> methodCache = new HashMap<String,List<Method>>();
+   
+   private static final LogProvider log = Logging.getLogProvider(SeamFunctionMapper.class);
+
+   private FunctionMapper functionMapper;
+   
+   public SeamFunctionMapper(FunctionMapper functionMapper)
+   {
+      this.functionMapper = functionMapper;
+   }
+   
+   static 
+   {
+      cacheMethod("hasPermission", SecurityFunctions.class, "hasPermission", 
+               new Class[] {String.class, String.class, Object.class});
+      cacheMethod("hasPermission", SecurityFunctions.class, "hasPermission",
+               new Class[] {Object.class, String.class});
+      cacheMethod("hasRole", SecurityFunctions.class, "hasRole",
+               new Class[] { String.class });      
+   }
+
+   @Override 
+   public Method resolveFunction(String prefix, String localName) 
+   {
+      if ( "s".equals(prefix) )
+      {
+         List<Method> methods = methodCache.get(localName);
+         return methods != null ? methods.get(0) : null;
+      }
+      else if (functionMapper != null)
+      {
+         return functionMapper.resolveFunction(prefix, localName);
+      }
+      else
+      {
+         return null;
+      }
+   }  
+   
+   @Override 
+   public Method resolveFunction(String prefix, String localName, int paramCount) 
+   {
+      if ( "s".equals(prefix) )
+      {
+         List<Method> methods = methodCache.get(localName);
+         if (methods != null)
+         {
+            for (Method m : methods)
+            {
+               if (m.getParameterTypes().length == paramCount) return m;
+            }
+         }
+         
+         return null;
+      }
+      else if (functionMapper != null)
+      {
+         return functionMapper.resolveFunction(prefix, localName);
+      }
+      else
+      {
+         return null;
+      }
+   }    
+   
+   private static void cacheMethod(String localName, Class cls, String name, Class[] params)
+   {
+      try
+      {
+         Method m = cls.getMethod(name, params);
+
+         List<Method> methods;
+         if (methodCache.containsKey(localName))
+         {
+            methods = methodCache.get(localName);
+         }
+         else
+         {
+            methods = new ArrayList<Method>();
+            methodCache.put(localName, methods);
+         }
+         
+         methods.add(m);         
+      }
+      catch (NoSuchMethodException ex)
+      {
+         log.warn(String.format("Method %s.%s could not be cached", cls.getName(), name));
+      }
+   }
+   
+}

Modified: modules/trunk/version-matrix/pom.xml
===================================================================
--- modules/trunk/version-matrix/pom.xml	2009-04-25 19:53:01 UTC (rev 10643)
+++ modules/trunk/version-matrix/pom.xml	2009-04-27 04:13:09 UTC (rev 10644)
@@ -132,7 +132,7 @@
          <dependency>
             <groupId>org.jboss.el</groupId>
             <artifactId>jboss-el</artifactId>
-            <version>1.0_02.CR2</version>
+            <version>1.0_02.CR4</version>
          </dependency>
 
          <dependency>
@@ -154,6 +154,12 @@
          </dependency>
          
          <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate</artifactId>
+            <version>3.2.4.sp1</version>
+         </dependency>
+         
+         <dependency>
             <groupId>org.jboss.webbeans</groupId>
             <artifactId>jsr299-api</artifactId>
             <version>1.0.0-SNAPSHOT</version>                           




More information about the seam-commits mailing list