View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.component;
21  
22  import javax.el.ELContext;
23  import javax.el.ELException;
24  import javax.el.MethodExpression;
25  import javax.el.MethodInfo;
26  import javax.el.MethodNotFoundException;
27  import javax.faces.FacesException;
28  import javax.faces.component.StateHolder;
29  import javax.faces.context.FacesContext;
30  import javax.faces.el.EvaluationException;
31  import javax.faces.el.MethodBinding;
32  
33  /**
34   * @deprecated since 2.0.0
35   */
36  @Deprecated
37  public class MethodBindingToMethodExpression extends MethodExpression implements StateHolder {
38    private MethodBinding methodBinding;
39  
40    private boolean transientFlag;
41  
42    private transient MethodInfo methodInfo;
43  
44    /**
45     * No-arg constructor used during restoreState
46     */
47    public MethodBindingToMethodExpression() {
48    }
49  
50    /**
51     * Creates a new instance of MethodBindingToMethodExpression
52     * @param methodBinding The MethodBinding to wrap.
53     */
54    public MethodBindingToMethodExpression(final MethodBinding methodBinding) {
55      checkNullArgument(methodBinding, "methodBinding");
56      this.methodBinding = methodBinding;
57    }
58  
59    /**
60     * Return the wrapped MethodBinding.
61     * @return the wrapped MethodBinding
62     */
63    public MethodBinding getMethodBinding() {
64      return methodBinding;
65    }
66  
67    void setMethodBinding(final MethodBinding methodBinding) {
68      this.methodBinding = methodBinding;
69    }
70  
71    /**
72     * Note: MethodInfo.getParamTypes() may incorrectly return an empty class array if invoke() has not been called.
73     *
74     * @throws IllegalStateException if expected params types have not been determined.
75     */
76    public MethodInfo getMethodInfo(final ELContext context) throws ELException {
77      checkNullArgument(context, "elcontext");
78      checkNullState(methodBinding, "methodBinding");
79  
80      if (methodInfo == null) {
81        final FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
82        if (facesContext != null) {
83          methodInfo = invoke(new Invoker<MethodInfo>() {
84            public MethodInfo invoke() {
85              return new MethodInfo(null, methodBinding.getType(facesContext), null);
86            }
87          });
88        }
89      }
90      return methodInfo;
91    }
92  
93    public Object invoke(final ELContext context, final Object[] params) throws ELException {
94      checkNullArgument(context, "elcontext");
95      checkNullState(methodBinding, "methodBinding");
96      final FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
97      if (facesContext != null) {
98        return invoke(new Invoker<Object>() {
99          public Object invoke() {
100           return methodBinding.invoke(facesContext, params);
101         }
102       });
103     }
104     return null;
105   }
106 
107   public boolean isLiteralText() {
108     if (methodBinding == null) {
109       throw new IllegalStateException("methodBinding is null");
110     }
111     final String expr = methodBinding.getExpressionString();
112     return !(expr.startsWith("#{") && expr.endsWith("}"));
113   }
114 
115   public String getExpressionString() {
116     return methodBinding.getExpressionString();
117   }
118 
119   public Object saveState(final FacesContext context) {
120     if (!isTransient()) {
121       if (methodBinding instanceof StateHolder) {
122         final Object[] state = new Object[2];
123         state[0] = methodBinding.getClass().getName();
124         state[1] = ((StateHolder) methodBinding).saveState(context);
125         return state;
126       } else {
127         return methodBinding;
128       }
129     }
130     return null;
131   }
132 
133   public void restoreState(final FacesContext context, final Object state) {
134     if (state instanceof MethodBinding) {
135       methodBinding = (MethodBinding) state;
136       methodInfo = null;
137     } else if (state != null) {
138       final Object[] values = (Object[]) state;
139       methodBinding = (MethodBinding) newInstance(values[0].toString());
140       ((StateHolder) methodBinding).restoreState(context, values[1]);
141       methodInfo = null;
142     }
143   }
144 
145   public void setTransient(final boolean transientFlag) {
146     this.transientFlag = transientFlag;
147   }
148 
149   public boolean isTransient() {
150     return transientFlag;
151   }
152 
153   @Override
154   public int hashCode() {
155     final int prime = 31;
156     int result = 1;
157     result = prime * result + ((methodBinding == null) ? 0 : methodBinding.hashCode());
158     return result;
159   }
160 
161   @Override
162   public boolean equals(final Object obj) {
163     if (this == obj) {
164       return true;
165     }
166     if (obj == null) {
167       return false;
168     }
169     if (getClass() != obj.getClass()) {
170       return false;
171     }
172     final MethodBindingToMethodExpression other = (MethodBindingToMethodExpression) obj;
173     if (methodBinding == null) {
174       if (other.methodBinding != null) {
175         return false;
176       }
177     } else if (!methodBinding.equals(other.methodBinding)) {
178       return false;
179     }
180     return true;
181   }
182 
183   private void checkNullState(final Object notNullInstance, final String instanceName) {
184     if (notNullInstance == null) {
185       throw new IllegalStateException(instanceName + " is null");
186     }
187   }
188 
189   private void checkNullArgument(final Object notNullInstance, final String instanceName) {
190     if (notNullInstance == null) {
191       throw new IllegalArgumentException(instanceName + " is null");
192     }
193   }
194 
195   private <T> T invoke(final Invoker<T> invoker) {
196     try {
197       return invoker.invoke();
198     } catch (final javax.faces.el.MethodNotFoundException e) {
199       throw new MethodNotFoundException(e.getMessage(), e);
200     } catch (final EvaluationException e) {
201       throw new ELException(e.getMessage(), e);
202     }
203   }
204 
205   private interface Invoker<T> {
206     T invoke();
207   }
208 
209   private static Object newInstance(final String type) {
210     if (type == null) {
211       throw new NullPointerException("type");
212     }
213     try {
214       try {
215         return Class.forName(type, false, Thread.currentThread().getContextClassLoader()).newInstance();
216       } catch (final ClassNotFoundException e) {
217         // ignore
218         return Class.forName(type, false, MethodBindingToMethodExpression.class.getClassLoader()).newInstance();
219       }
220     } catch (final ClassNotFoundException e) {
221       throw new FacesException(e);
222     } catch (final NoClassDefFoundError e) {
223       throw new FacesException(e);
224     } catch (final InstantiationException e) {
225       throw new FacesException(e);
226     } catch (final IllegalAccessException e) {
227       throw new FacesException(e);
228     }
229   }
230 
231 }