You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mb...@apache.org on 2007/03/13 17:28:15 UTC
svn commit: r517757 - in /myfaces/core/branches/jsf12/api/src:
main/java/javax/faces/component/ test/java/javax/faces/component/
Author: mbr
Date: Tue Mar 13 09:28:14 2007
New Revision: 517757
URL: http://svn.apache.org/viewvc?view=rev&rev=517757
Log:
fixed several issues with method binding to method expression adapter
+test
Added:
myfaces/core/branches/jsf12/api/src/test/java/javax/faces/component/_MethodBindingToMethodExpressionTest.java (with props)
Modified:
myfaces/core/branches/jsf12/api/src/main/java/javax/faces/component/_MethodBindingToMethodExpression.java
myfaces/core/branches/jsf12/api/src/main/java/javax/faces/component/_MethodExpressionToMethodBinding.java
Modified: myfaces/core/branches/jsf12/api/src/main/java/javax/faces/component/_MethodBindingToMethodExpression.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/jsf12/api/src/main/java/javax/faces/component/_MethodBindingToMethodExpression.java?view=diff&rev=517757&r1=517756&r2=517757
==============================================================================
--- myfaces/core/branches/jsf12/api/src/main/java/javax/faces/component/_MethodBindingToMethodExpression.java (original)
+++ myfaces/core/branches/jsf12/api/src/main/java/javax/faces/component/_MethodBindingToMethodExpression.java Tue Mar 13 09:28:14 2007
@@ -18,161 +18,259 @@
import javax.el.ELContext;
import javax.el.ELException;
-import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.el.MethodInfo;
import javax.el.MethodNotFoundException;
import javax.el.PropertyNotFoundException;
-import javax.faces.FacesException;
-import javax.faces.FactoryFinder;
-import javax.faces.application.Application;
-import javax.faces.application.ApplicationFactory;
-import javax.faces.component.StateHolder;
import javax.faces.context.FacesContext;
+import javax.faces.el.EvaluationException;
import javax.faces.el.MethodBinding;
/**
* Converts a MethodBinding to a MethodExpression
- *
+ *
+ * TODO: find a way to share the implementation of class with impl.
+ *
* @author Stan Silvert
*/
-class _MethodBindingToMethodExpression extends MethodExpression implements StateHolder {
-
- private static final ExpressionFactory expFactory;
-
- static {
- ApplicationFactory appFactory =
- (ApplicationFactory)FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
- Application application = appFactory.getApplication();
- expFactory = application.getExpressionFactory();
- }
-
+@SuppressWarnings("deprecation")
+class _MethodBindingToMethodExpression extends MethodExpression implements StateHolder
+{
+ private static final Class[] EXPECTED_TYPES = new Class[] { MethodBinding.class, StateHolder.class };
+
private MethodBinding methodBinding;
-
- private MethodExpression methodExpression;
- private boolean paramTypesKnown = false;
-
+
+ private boolean _transientFlag;
+
+ private transient MethodInfo methodInfo;
+
/**
* No-arg constructor used during restoreState
*/
- public _MethodBindingToMethodExpression() {
-
+ protected _MethodBindingToMethodExpression()
+ {
}
-
+
/** Creates a new instance of MethodBindingToMethodExpression */
- public _MethodBindingToMethodExpression(MethodBinding methodBinding) {
+ public _MethodBindingToMethodExpression(MethodBinding methodBinding)
+ {
+ checkNullArgument(methodBinding, "methodBinding");
this.methodBinding = methodBinding;
-
- if (!(methodBinding instanceof StateHolder)) {
- throw new IllegalArgumentException("methodBinding must be an instance of StateHolder");
- }
-
- // We can't determine the expectecParamTypes from the MethodBinding
- // until someone calls invoke.
- // Therefore, we will just create a new one when invoke is called.
- methodExpression = makeMethodExpression(methodBinding, new Class[0]);
}
-
- private MethodExpression makeMethodExpression(MethodBinding methodBinding, Class[] expectedParamTypes) {
- FacesContext facesContext = FacesContext.getCurrentInstance();
-
- String expressionString = methodBinding.getExpressionString();
- if (expressionString == null) expressionString = "null";
- return expFactory.createMethodExpression(facesContext.getELContext(),
- expressionString,
- null,
- expectedParamTypes);
- }
-
+
/**
* Return the wrapped MethodBinding.
*/
- public MethodBinding getMethodBinding() {
+ public MethodBinding getMethodBinding()
+ {
return methodBinding;
}
+
+ void setMethodBinding(MethodBinding methodBinding)
+ {
+ this.methodBinding = methodBinding;
+ }
/**
- * Note: MethodInfo.getParamTypes() may incorrectly return an empty
- * class array if invoke() has not been called.
- *
- * @throws IllegalStateException if expected params types have not been determined.
+ * Note: MethodInfo.getParamTypes() may incorrectly return an empty class array if invoke() has not been called.
+ *
+ * @throws IllegalStateException
+ * if expected params types have not been determined.
*/
- public MethodInfo getMethodInfo(ELContext context)
- throws NullPointerException, PropertyNotFoundException, MethodNotFoundException, ELException {
-
- if (!paramTypesKnown) throw new IllegalStateException("MethodInfo unavailable until invoke is called.");
-
- return methodExpression.getMethodInfo(context);
- }
-
- public Object invoke(ELContext context, Object[] params)
- throws NullPointerException, PropertyNotFoundException, MethodNotFoundException, ELException {
-
- if (!paramTypesKnown) {
- Class[] paramTypes = findParamTypes(params);
- methodExpression = makeMethodExpression(methodBinding, paramTypes);
- paramTypesKnown = true;
+ public MethodInfo getMethodInfo(ELContext context) throws PropertyNotFoundException, MethodNotFoundException,
+ ELException
+ {
+ checkNullArgument(context, "elcontext");
+ checkNullState(methodBinding, "methodBinding");
+
+ if (methodInfo == null)
+ {
+ final FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
+ if (facesContext != null)
+ {
+ methodInfo = invoke(new Invoker<MethodInfo>()
+ {
+ public MethodInfo invoke()
+ {
+ return new MethodInfo(null, methodBinding.getType(facesContext), null);
+ }
+ });
+ }
}
-
- return methodExpression.invoke(context, params);
- }
-
- private Class[] findParamTypes(Object[] params) {
- Class[] paramTypes = new Class[params.length];
- for (int i = 0; i < params.length; i++) {
- paramTypes[i] = params[i].getClass();
- }
-
- return paramTypes;
+ return methodInfo;
}
- public boolean isLiteralText() {
- return methodExpression.isLiteralText();
+ public Object invoke(ELContext context, final Object[] params) throws PropertyNotFoundException,
+ MethodNotFoundException, ELException
+ {
+ checkNullArgument(context, "elcontext");
+ checkNullState(methodBinding, "methodBinding");
+ final FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
+ if (facesContext != null)
+ {
+ return invoke(new Invoker<Object>()
+ {
+ public Object invoke()
+ {
+ return methodBinding.invoke(facesContext, params);
+ }
+ });
+ }
+ return null;
}
- public String getExpressionString() {
- return methodExpression.getExpressionString();
- }
-
- public boolean equals(Object obj) {
- return methodExpression.equals(obj);
- }
-
- public int hashCode() {
- return methodExpression.hashCode();
+ public boolean isLiteralText()
+ {
+ if (methodBinding == null)
+ throw new IllegalStateException("methodBinding is null");
+ String expr = methodBinding.getExpressionString();
+ return !(expr.startsWith("#{") && expr.endsWith("}"));
+ }
+
+ public String getExpressionString()
+ {
+ return methodBinding.getExpressionString();
+ }
+
+ public Object saveState(FacesContext context)
+ {
+ if (!isTransient())
+ {
+ if (methodBinding instanceof StateHolder)
+ {
+ Object[] state = new Object[2];
+ state[0] = methodBinding.getClass().getName();
+ state[1] = ((StateHolder) methodBinding).saveState(context);
+ return state;
+ }
+ else
+ {
+ return methodBinding;
+ }
+ }
+ return null;
}
- public void restoreState(FacesContext context, Object state) {
- Object[] stateArray = (Object[])state;
- try {
- methodBinding = (MethodBinding)Thread.currentThread()
- .getContextClassLoader()
- .loadClass((String)stateArray[0])
- .newInstance();
- } catch (Exception e) {
- throw new FacesException(e);
+ public void restoreState(FacesContext context, Object state)
+ {
+ if (state instanceof MethodBinding)
+ {
+ methodBinding = (MethodBinding) state;
+ methodInfo = null;
+ }
+ else if (state != null)
+ {
+ Object[] values = (Object[]) state;
+ methodBinding = (MethodBinding) newInstance(values[0].toString(), EXPECTED_TYPES);
+ ((StateHolder) methodBinding).restoreState(context, values[1]);
+ methodInfo = null;
}
-
- ((StateHolder)methodBinding).restoreState(context, stateArray[1]);
- paramTypesKnown = ((Boolean)stateArray[2]).booleanValue();
- methodExpression = makeMethodExpression(methodBinding, (Class[])stateArray[3]);
}
- public Object saveState(FacesContext context) {
- Object[] state = new Object[4];
- state[0] = methodBinding.getClass().getName();
- state[1] = ((StateHolder)methodBinding).saveState(context);
- state[2] = Boolean.valueOf(paramTypesKnown);
- state[3] = methodExpression.getMethodInfo(context.getELContext()).getParamTypes();
- return state;
+ public void setTransient(boolean transientFlag)
+ {
+ _transientFlag = transientFlag;
+ }
+
+ public boolean isTransient()
+ {
+ return _transientFlag;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int PRIME = 31;
+ int result = 1;
+ result = PRIME * result + ((methodBinding == null) ? 0 : methodBinding.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final _MethodBindingToMethodExpression other = (_MethodBindingToMethodExpression) obj;
+ if (methodBinding == null)
+ {
+ if (other.methodBinding != null)
+ return false;
+ }
+ else if (!methodBinding.equals(other.methodBinding))
+ return false;
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected Object newInstance(String className, Class[] expectedTypes)
+ {
+ try
+ {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null)
+ {
+ classLoader = getClass().getClassLoader();
+ }
+ Class clazz = classLoader.loadClass(className);
+ for (int i = 0, size = expectedTypes.length; i < size; i++)
+ {
+ if (!expectedTypes[i].isAssignableFrom(clazz))
+ {
+ throw new IllegalStateException("class for name " + className + " does not implement "
+ + expectedTypes[i].getName());
+ }
+ }
+ return clazz.newInstance();
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ catch (InstantiationException e)
+ {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
}
- public void setTransient(boolean newTransientValue) {
- ((StateHolder)methodBinding).setTransient(newTransientValue);
+ private void checkNullState(Object notNullInstance, String instanceName)
+ {
+ if (notNullInstance == null)
+ throw new IllegalStateException(instanceName + " is null");
+ }
+
+ private void checkNullArgument(Object notNullInstance, String instanceName)
+ {
+ if (notNullInstance == null)
+ throw new IllegalArgumentException(instanceName + " is null");
+ }
+
+ private <T> T invoke(Invoker<T> invoker)
+ {
+ try
+ {
+ return invoker.invoke();
+ }
+ catch (javax.faces.el.MethodNotFoundException e)
+ {
+ throw new MethodNotFoundException(e.getMessage(), e);
+ }
+ catch (EvaluationException e)
+ {
+ throw new ELException(e.getMessage(), e);
+ }
}
- public boolean isTransient() {
- return ((StateHolder)methodBinding).isTransient();
+ private interface Invoker<T>
+ {
+ T invoke();
}
-
}
Modified: myfaces/core/branches/jsf12/api/src/main/java/javax/faces/component/_MethodExpressionToMethodBinding.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/jsf12/api/src/main/java/javax/faces/component/_MethodExpressionToMethodBinding.java?view=diff&rev=517757&r1=517756&r2=517757
==============================================================================
--- myfaces/core/branches/jsf12/api/src/main/java/javax/faces/component/_MethodExpressionToMethodBinding.java (original)
+++ myfaces/core/branches/jsf12/api/src/main/java/javax/faces/component/_MethodExpressionToMethodBinding.java Tue Mar 13 09:28:14 2007
@@ -49,6 +49,12 @@
public _MethodExpressionToMethodBinding(MethodExpression methodExpression) {
this.methodExpression = methodExpression;
}
+
+ @Override
+ public String getExpressionString()
+ {
+ return methodExpression.getExpressionString();
+ }
public Class getType(FacesContext facesContext)
throws MethodNotFoundException {
@@ -57,6 +63,8 @@
return methodExpression.getMethodInfo(facesContext.getELContext()).getReturnType();
} catch (javax.el.MethodNotFoundException e) {
throw new javax.faces.el.MethodNotFoundException(e);
+ } catch (ELException e) {
+ throw new EvaluationException(e);
}
}
@@ -75,11 +83,14 @@
// -------- StateHolder methods -------------------------------------------
public void restoreState(FacesContext context, Object state) {
- methodExpression = (MethodExpression)state;
+ if(state != null)
+ methodExpression = (MethodExpression)state;
}
public Object saveState(FacesContext context) {
- return methodExpression;
+ if(!isTransient)
+ return methodExpression;
+ return null;
}
public void setTransient(boolean newTransientValue) {
Added: myfaces/core/branches/jsf12/api/src/test/java/javax/faces/component/_MethodBindingToMethodExpressionTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/jsf12/api/src/test/java/javax/faces/component/_MethodBindingToMethodExpressionTest.java?view=auto&rev=517757
==============================================================================
--- myfaces/core/branches/jsf12/api/src/test/java/javax/faces/component/_MethodBindingToMethodExpressionTest.java (added)
+++ myfaces/core/branches/jsf12/api/src/test/java/javax/faces/component/_MethodBindingToMethodExpressionTest.java Tue Mar 13 09:28:14 2007
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package javax.faces.component;
+
+import static org.easymock.EasyMock.*;
+
+import java.util.Date;
+
+import javax.el.ELException;
+import javax.el.ExpressionFactory;
+import javax.el.MethodInfo;
+import javax.el.MethodNotFoundException;
+import javax.faces.application.Application;
+import javax.faces.context.FacesContext;
+import javax.faces.el.MethodBinding;
+
+import junit.framework.TestCase;
+
+import org.apache.myfaces.Assert;
+import org.apache.myfaces.TestRunner;
+import org.apache.shale.test.el.MockELContext;
+import org.apache.shale.test.mock.MockFacesContext12;
+import org.easymock.classextension.EasyMock;
+import org.easymock.classextension.IMocksControl;
+
+/**
+ * @author Mathias Broekelmann (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+@SuppressWarnings("deprecation")
+public class _MethodBindingToMethodExpressionTest extends TestCase
+{
+
+ private IMocksControl _mocksControl;
+ private MethodBinding _methodBinding;
+ private MockELContext _elContext;
+ private MockFacesContext12 _facesContext;
+ private Application _application;
+ private ExpressionFactory _expressionFactory;
+
+ protected void setUp() throws Exception
+ {
+ _mocksControl = EasyMock.createControl();
+ _facesContext = new MockFacesContext12();
+ _application = _mocksControl.createMock(Application.class);
+ _facesContext.setApplication(_application);
+ _expressionFactory = _mocksControl.createMock(ExpressionFactory.class);
+ _elContext = new MockELContext();
+ _elContext.putContext(FacesContext.class, _facesContext);
+ _methodBinding = _mocksControl.createMock(MethodBinding.class);
+ }
+
+ /**
+ * Test method for {@link javax.faces.component._MethodBindingToMethodExpression#_MethodBindingToMethodExpression()}.
+ */
+ public void test_MethodBindingToMethodExpression()
+ {
+ _MethodBindingToMethodExpression testimpl = new _MethodBindingToMethodExpression();
+ assertNull(testimpl.getMethodBinding());
+ }
+
+ /**
+ * Test method for
+ * {@link javax.faces.component._MethodBindingToMethodExpression#_MethodBindingToMethodExpression(javax.faces.el.MethodBinding)}.
+ */
+ public void test_MethodBindingToMethodExpressionMethodBinding()
+ {
+ Assert.assertException(IllegalArgumentException.class, new TestRunner()
+ {
+ public void run() throws Throwable
+ {
+ new _MethodBindingToMethodExpression(null);
+ }
+ });
+ _MethodBindingToMethodExpression testimpl = new _MethodBindingToMethodExpression(_methodBinding);
+ assertEquals(_methodBinding, testimpl.getMethodBinding());
+ }
+
+ /**
+ * Test method for {@link javax.faces.component._MethodBindingToMethodExpression#isLiteralText()}.
+ */
+ public void testIsLiteralText()
+ {
+ assertIsLiteralText(true, "xxx");
+ assertIsLiteralText(false, "#{xxx}");
+ }
+
+ private void assertIsLiteralText(boolean expected, String expressionString)
+ {
+ _MethodBindingToMethodExpression testimpl = new _MethodBindingToMethodExpression(_methodBinding);
+ expect(_methodBinding.getExpressionString()).andReturn(expressionString);
+ _mocksControl.replay();
+ assertEquals(expected, testimpl.isLiteralText());
+ _mocksControl.reset();
+ }
+
+ /**
+ * Test method for {@link javax.faces.component._MethodBindingToMethodExpression#getMethodInfo(javax.el.ELContext)}.
+ */
+ public void testGetMethodInfoELContext()
+ {
+ _MethodBindingToMethodExpression testimpl = new _MethodBindingToMethodExpression(_methodBinding);
+ Class expectedReturnType = Date.class;
+ expect(_methodBinding.getType(same(_facesContext))).andReturn(expectedReturnType);
+ _mocksControl.replay();
+ MethodInfo methodInfo = testimpl.getMethodInfo(_elContext);
+ assertNotNull(methodInfo);
+ // assertNull(methodInfo.getName());
+ assertEquals(expectedReturnType, methodInfo.getReturnType());
+ // assertNull(methodInfo.getParamTypes());
+ _mocksControl.verify();
+ _mocksControl.reset();
+
+ assertGetMethodInfoException(MethodNotFoundException.class, new javax.faces.el.MethodNotFoundException());
+ assertGetMethodInfoException(ELException.class, new javax.faces.el.EvaluationException());
+ }
+
+ private void assertGetMethodInfoException(Class<? extends Throwable> expected, final Throwable firedFromMBGetType)
+ {
+ final _MethodBindingToMethodExpression testimpl = new _MethodBindingToMethodExpression(_methodBinding);
+ expect(_methodBinding.getType(same(_facesContext))).andThrow(firedFromMBGetType);
+ _mocksControl.replay();
+ Assert.assertException(expected, new TestRunner()
+ {
+ public void run() throws Throwable
+ {
+ testimpl.getMethodInfo(_elContext);
+ }
+ });
+ _mocksControl.verify();
+ _mocksControl.reset();
+ }
+
+ /**
+ * Test method for
+ * {@link javax.faces.component._MethodBindingToMethodExpression#invoke(javax.el.ELContext, java.lang.Object[])}.
+ */
+ public void testInvoke()
+ {
+ _MethodBindingToMethodExpression testimpl = new _MethodBindingToMethodExpression(_methodBinding);
+ Object[] testParams = new Object[] { "test" };
+ Object expectedResult = new StringBuffer();
+ expect(_methodBinding.invoke(same(_facesContext), same(testParams))).andReturn(expectedResult);
+ _mocksControl.replay();
+ assertEquals(expectedResult, testimpl.invoke(_elContext, testParams));
+ _mocksControl.verify();
+ _mocksControl.reset();
+
+ assertInvokeException(MethodNotFoundException.class, new javax.faces.el.MethodNotFoundException());
+ assertInvokeException(ELException.class, new javax.faces.el.EvaluationException());
+ }
+
+ private void assertInvokeException(Class<? extends Throwable> expected, final Throwable firedFromMBInvoke)
+ {
+ final _MethodBindingToMethodExpression testimpl = new _MethodBindingToMethodExpression(_methodBinding);
+ expect(_methodBinding.invoke(same(_facesContext), (Object[]) isNull())).andThrow(firedFromMBInvoke);
+ _mocksControl.replay();
+ Assert.assertException(expected, new TestRunner()
+ {
+ public void run() throws Throwable
+ {
+ testimpl.invoke(_elContext, null);
+ }
+ });
+ _mocksControl.verify();
+ _mocksControl.reset();
+ }
+
+ /**
+ * Test method for {@link javax.faces.component._MethodBindingToMethodExpression#getExpressionString()}.
+ */
+ public void testGetExpressionString()
+ {
+ _MethodBindingToMethodExpression testimpl = new _MethodBindingToMethodExpression(_methodBinding);
+ expect(_methodBinding.getExpressionString()).andReturn("xxx");
+ _mocksControl.replay();
+ assertEquals("xxx", testimpl.getExpressionString());
+ _mocksControl.verify();
+ }
+
+ /**
+ * Test method for
+ * {@link javax.faces.component._MethodBindingToMethodExpression#restoreState(javax.faces.context.FacesContext, java.lang.Object)}.
+ *
+ * @throws Exception
+ */
+ public void testStateHolder() throws Exception
+ {
+ _MethodBindingToMethodExpression testimpl = new _MethodBindingToMethodExpression(_methodBinding);
+ assertFalse(testimpl.isTransient());
+ testimpl.setTransient(true);
+ assertTrue(testimpl.isTransient());
+ assertNull(testimpl.saveState(_facesContext));
+ }
+}
Propchange: myfaces/core/branches/jsf12/api/src/test/java/javax/faces/component/_MethodBindingToMethodExpressionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: myfaces/core/branches/jsf12/api/src/test/java/javax/faces/component/_MethodBindingToMethodExpressionTest.java
------------------------------------------------------------------------------
svn:keywords = URL Author Revision Date