2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shale.test.mock;
19  
20  import java.lang.reflect.InvocationTargetException;
21  import java.lang.reflect.Method;
22  
23  import javax.faces.application.Application;
24  import javax.faces.component.StateHolder;
25  import javax.faces.component.UIComponentBase;
26  import javax.faces.context.FacesContext;
27  import javax.faces.el.EvaluationException;
28  import javax.faces.el.MethodBinding;
29  import javax.faces.el.MethodNotFoundException;
30  import javax.faces.el.ReferenceSyntaxException;
31  import javax.faces.el.ValueBinding;
32  
33  /***
34   * <p>Mock implementation of <code>MethodBinding</code>.</p>
35   *
36   * <p>This implementation is subject to the following restrictions:</p>
37   * <ul>
38   * <li>The portion of the method reference expression before the final
39   *     "." must conform to the limitations of {@link MockValueBinding}.</li>
40   * <li>The name of the method to be executed cannot be delimited by "[]".</li>
41   * </ul>
42   */
43  
44  public class MockMethodBinding extends MethodBinding implements StateHolder {
45  
46  
47      // ------------------------------------------------------------ Constructors
48  
49      /***
50       * <p>Construct a default instance.</p>
51       */
52      public MockMethodBinding() {
53      }
54  
55  
56      /***
57       * <p>Construct a configured instance.</p>
58       *
59       * @param application Application instance for this application
60       * @param ref Method binding expression to be parsed
61       * @param args Signature of this method
62       */
63      public MockMethodBinding(Application application, String ref,
64                               Class[] args) {
65  
66          this.application = application;
67          this.args = args;
68          if (ref.startsWith("#{") && ref.endsWith("}")) {
69              ref = ref.substring(2, ref.length() - 1);
70          }
71          this.ref = ref;
72          int period = ref.lastIndexOf(".");
73          if (period < 0) {
74              throw new ReferenceSyntaxException(ref);
75          }
76          vb = application.createValueBinding(ref.substring(0, period));
77          name = ref.substring(period + 1);
78          if (name.length() < 1) {
79              throw new ReferenceSyntaxException(ref);
80          }
81  
82      }
83  
84  
85      // ------------------------------------------------------ Instance Variables
86  
87  
88      private Application application;
89      private Class args[];
90      private String name;
91      private String ref;
92      private ValueBinding vb;
93  
94  
95      // --------------------------------------------------- MethodBinding Methods
96  
97  
98      /*** {@inheritDoc} */
99      public Object invoke(FacesContext context, Object[] params)
100         throws EvaluationException, MethodNotFoundException {
101 
102         if (context == null) {
103             throw new NullPointerException();
104         }
105         Object base = vb.getValue(context);
106         if (base == null) {
107             throw new EvaluationException("Cannot find object via expression \""
108                                           + vb.getExpressionString() + "\"");
109         }
110         Method method = method(base);
111         try {
112             return (method.invoke(base, params));
113         } catch (IllegalAccessException e) {
114             throw new EvaluationException(e);
115         } catch (InvocationTargetException e) {
116             throw new EvaluationException(e.getTargetException());
117         }
118 
119     }
120 
121 
122     /*** {@inheritDoc} */
123     public Class getType(FacesContext context) {
124 
125         Object base = vb.getValue(context);
126         Method method = method(base);
127         Class returnType = method.getReturnType();
128         if ("void".equals(returnType.getName())) {
129             return (null);
130         } else {
131             return (returnType);
132         }
133 
134     }
135 
136     /*** {@inheritDoc} */
137     public String getExpressionString() {
138         return "#{" + ref + "}";
139     }
140 
141     // ----------------------------------------------------- StateHolder Methods
142 
143 
144     /*** {@inheritDoc} */
145     public Object saveState(FacesContext context) {
146         Object values[] = new Object[4];
147         values[0] = name;
148         values[1] = ref;
149         values[2] = UIComponentBase.saveAttachedState(context, vb);
150         values[3] = args;
151         return (values);
152     }
153 
154 
155     /*** {@inheritDoc} */
156     public void restoreState(FacesContext context, Object state) {
157         Object values[] = (Object[]) state;
158         name = (String) values[0];
159         ref = (String) values[1];
160         vb = (ValueBinding) UIComponentBase.restoreAttachedState(context, 
161                                                                  values[2]);
162         args = (Class []) values[3];
163     }
164 
165 
166     /***
167      * <p>Flag indicating this is a transient instance.</p>
168      */
169     private boolean transientFlag = false;
170 
171 
172     /*** {@inheritDoc} */
173     public boolean isTransient() {
174         return (this.transientFlag);
175     }
176 
177 
178     /*** {@inheritDoc} */
179     public void setTransient(boolean transientFlag) {
180         this.transientFlag = transientFlag;
181     }
182 
183     /*** {@inheritDoc} */
184     public int hashCode() {
185         if (ref == null) {
186             return 0;
187         } else {
188             return ref.hashCode();
189         }
190     }
191 
192     /*** {@inheritDoc} */
193     public boolean equals(Object otherObj) {
194         MockMethodBinding other = null;
195 
196         if (!(otherObj instanceof MockMethodBinding)) {
197             return false;
198         }
199         other = (MockMethodBinding) otherObj;
200         // test object reference equality
201         if (this.ref != other.ref) {
202             // test object equality
203             if (null != this.ref && null != other.ref) {
204                 if (!this.ref.equals(other.ref)) {
205                     return false;
206                 }
207             }
208             return false;
209         }
210         // no need to test name, since it flows from ref.
211         // test our args array
212         if (this.args != other.args) {
213             if (this.args.length != other.args.length) {
214                 return false;
215             }
216             for (int i = 0, len = this.args.length; i < len; i++) {
217                 if (this.args[i] != other.args[i]) {
218                     if (!this.ref.equals(other.ref)) {
219                         return false;
220                     }
221                 }
222             }
223         }
224         return true;
225     }
226 
227 
228     // --------------------------------------------------------- Private Methods
229 
230 
231     /***
232      * <p>Return the <code>Method</code> to be called.</p>
233      *
234      * @param base Base object from which to extract the method reference
235      */
236     Method method(Object base) {
237 
238         Class clazz = base.getClass();
239         try {
240             return (clazz.getMethod(name, args));
241         } catch (NoSuchMethodException e) {
242             throw new MethodNotFoundException(ref + ": " + e.getMessage());
243         }
244 
245     }
246 
247 
248 
249 }