| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to you under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.myfaces.test.mock; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| |
| import javax.faces.application.Application; |
| import javax.faces.component.StateHolder; |
| import javax.faces.component.UIComponentBase; |
| import javax.faces.context.FacesContext; |
| import javax.faces.el.EvaluationException; |
| import javax.faces.el.MethodBinding; |
| import javax.faces.el.MethodNotFoundException; |
| import javax.faces.el.ReferenceSyntaxException; |
| import javax.faces.el.ValueBinding; |
| |
| /** |
| * <p>Mock implementation of <code>MethodBinding</code>.</p> |
| * |
| * <p>This implementation is subject to the following restrictions:</p> |
| * <ul> |
| * <li>The portion of the method reference expression before the final |
| * "." must conform to the limitations of {@link MockValueBinding}.</li> |
| * <li>The name of the method to be executed cannot be delimited by "[]".</li> |
| * </ul> |
| */ |
| |
| public class MockMethodBinding extends MethodBinding implements StateHolder { |
| |
| |
| // ------------------------------------------------------------ Constructors |
| |
| /** |
| * <p>Construct a default instance.</p> |
| */ |
| public MockMethodBinding() { |
| } |
| |
| |
| /** |
| * <p>Construct a configured instance.</p> |
| * |
| * @param application Application instance for this application |
| * @param ref Method binding expression to be parsed |
| * @param args Signature of this method |
| */ |
| public MockMethodBinding(Application application, String ref, |
| Class[] args) { |
| |
| this.application = application; |
| this.args = args; |
| if (ref.startsWith("#{") && ref.endsWith("}")) { |
| ref = ref.substring(2, ref.length() - 1); |
| } |
| this.ref = ref; |
| int period = ref.lastIndexOf("."); |
| if (period < 0) { |
| throw new ReferenceSyntaxException(ref); |
| } |
| vb = application.createValueBinding(ref.substring(0, period)); |
| name = ref.substring(period + 1); |
| if (name.length() < 1) { |
| throw new ReferenceSyntaxException(ref); |
| } |
| |
| } |
| |
| |
| // ------------------------------------------------------ Instance Variables |
| |
| |
| private Application application; |
| private Class args[]; |
| private String name; |
| private String ref; |
| private ValueBinding vb; |
| |
| |
| // --------------------------------------------------- MethodBinding Methods |
| |
| |
| /** {@inheritDoc} */ |
| public Object invoke(FacesContext context, Object[] params) |
| throws EvaluationException, MethodNotFoundException { |
| |
| if (context == null) { |
| throw new NullPointerException(); |
| } |
| Object base = vb.getValue(context); |
| if (base == null) { |
| throw new EvaluationException("Cannot find object via expression \"" |
| + vb.getExpressionString() + "\""); |
| } |
| Method method = method(base); |
| try { |
| return (method.invoke(base, params)); |
| } catch (IllegalAccessException e) { |
| throw new EvaluationException(e); |
| } catch (InvocationTargetException e) { |
| throw new EvaluationException(e.getTargetException()); |
| } |
| |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public Class getType(FacesContext context) { |
| |
| Object base = vb.getValue(context); |
| Method method = method(base); |
| Class returnType = method.getReturnType(); |
| if ("void".equals(returnType.getName())) { |
| return (null); |
| } else { |
| return (returnType); |
| } |
| |
| } |
| |
| /** {@inheritDoc} */ |
| public String getExpressionString() { |
| return "#{" + ref + "}"; |
| } |
| |
| // ----------------------------------------------------- StateHolder Methods |
| |
| |
| /** {@inheritDoc} */ |
| public Object saveState(FacesContext context) { |
| Object values[] = new Object[4]; |
| values[0] = name; |
| values[1] = ref; |
| values[2] = UIComponentBase.saveAttachedState(context, vb); |
| values[3] = args; |
| return (values); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void restoreState(FacesContext context, Object state) { |
| Object values[] = (Object[]) state; |
| name = (String) values[0]; |
| ref = (String) values[1]; |
| vb = (ValueBinding) UIComponentBase.restoreAttachedState(context, |
| values[2]); |
| args = (Class []) values[3]; |
| } |
| |
| |
| /** |
| * <p>Flag indicating this is a transient instance.</p> |
| */ |
| private boolean transientFlag = false; |
| |
| |
| /** {@inheritDoc} */ |
| public boolean isTransient() { |
| return (this.transientFlag); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void setTransient(boolean transientFlag) { |
| this.transientFlag = transientFlag; |
| } |
| |
| /** {@inheritDoc} */ |
| public int hashCode() { |
| if (ref == null) { |
| return 0; |
| } else { |
| return ref.hashCode(); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public boolean equals(Object otherObj) { |
| MockMethodBinding other = null; |
| |
| if (!(otherObj instanceof MockMethodBinding)) { |
| return false; |
| } |
| other = (MockMethodBinding) otherObj; |
| // test object reference equality |
| if (this.ref != other.ref) { |
| // test object equality |
| if (null != this.ref && null != other.ref) { |
| if (!this.ref.equals(other.ref)) { |
| return false; |
| } |
| } |
| return false; |
| } |
| // no need to test name, since it flows from ref. |
| // test our args array |
| if (this.args != other.args) { |
| if (this.args.length != other.args.length) { |
| return false; |
| } |
| for (int i = 0, len = this.args.length; i < len; i++) { |
| if (this.args[i] != other.args[i]) { |
| if (!this.ref.equals(other.ref)) { |
| return false; |
| } |
| } |
| } |
| } |
| return true; |
| } |
| |
| |
| // --------------------------------------------------------- Private Methods |
| |
| |
| /** |
| * <p>Return the <code>Method</code> to be called.</p> |
| * |
| * @param base Base object from which to extract the method reference |
| */ |
| Method method(Object base) { |
| |
| Class clazz = base.getClass(); |
| try { |
| return (clazz.getMethod(name, args)); |
| } catch (NoSuchMethodException e) { |
| throw new MethodNotFoundException(ref + ": " + e.getMessage()); |
| } |
| |
| } |
| |
| |
| |
| } |