001: /*
002: * Copyright 2006 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package javax.faces.component;
018:
019: import javax.el.ELContext;
020: import javax.el.ELException;
021: import javax.el.MethodExpression;
022: import javax.el.MethodInfo;
023: import javax.el.MethodNotFoundException;
024: import javax.el.PropertyNotFoundException;
025: import javax.faces.context.FacesContext;
026: import javax.faces.el.EvaluationException;
027: import javax.faces.el.MethodBinding;
028:
029: /**
030: * Converts a MethodBinding to a MethodExpression
031: *
032: * TODO: find a way to share the implementation of class with impl.
033: *
034: * @author Stan Silvert
035: */
036: @SuppressWarnings("deprecation")
037: class _MethodBindingToMethodExpression extends MethodExpression
038: implements StateHolder {
039: private static final Class[] EXPECTED_TYPES = new Class[] {
040: MethodBinding.class, StateHolder.class };
041:
042: private MethodBinding methodBinding;
043:
044: private boolean _transientFlag;
045:
046: private transient MethodInfo methodInfo;
047:
048: /**
049: * No-arg constructor used during restoreState
050: */
051: protected _MethodBindingToMethodExpression() {
052: }
053:
054: /** Creates a new instance of MethodBindingToMethodExpression */
055: public _MethodBindingToMethodExpression(MethodBinding methodBinding) {
056: checkNullArgument(methodBinding, "methodBinding");
057: this .methodBinding = methodBinding;
058: }
059:
060: /**
061: * Return the wrapped MethodBinding.
062: */
063: public MethodBinding getMethodBinding() {
064: return methodBinding;
065: }
066:
067: void setMethodBinding(MethodBinding methodBinding) {
068: this .methodBinding = methodBinding;
069: }
070:
071: /**
072: * Note: MethodInfo.getParamTypes() may incorrectly return an empty class array if invoke() has not been called.
073: *
074: * @throws IllegalStateException
075: * if expected params types have not been determined.
076: */
077: public MethodInfo getMethodInfo(ELContext context)
078: throws PropertyNotFoundException, MethodNotFoundException,
079: ELException {
080: checkNullArgument(context, "elcontext");
081: checkNullState(methodBinding, "methodBinding");
082:
083: if (methodInfo == null) {
084: final FacesContext facesContext = (FacesContext) context
085: .getContext(FacesContext.class);
086: if (facesContext != null) {
087: methodInfo = invoke(new Invoker<MethodInfo>() {
088: public MethodInfo invoke() {
089: return new MethodInfo(null, methodBinding
090: .getType(facesContext), null);
091: }
092: });
093: }
094: }
095: return methodInfo;
096: }
097:
098: public Object invoke(ELContext context, final Object[] params)
099: throws PropertyNotFoundException, MethodNotFoundException,
100: ELException {
101: checkNullArgument(context, "elcontext");
102: checkNullState(methodBinding, "methodBinding");
103: final FacesContext facesContext = (FacesContext) context
104: .getContext(FacesContext.class);
105: if (facesContext != null) {
106: return invoke(new Invoker<Object>() {
107: public Object invoke() {
108: return methodBinding.invoke(facesContext, params);
109: }
110: });
111: }
112: return null;
113: }
114:
115: public boolean isLiteralText() {
116: if (methodBinding == null)
117: throw new IllegalStateException("methodBinding is null");
118: String expr = methodBinding.getExpressionString();
119: return !(expr.startsWith("#{") && expr.endsWith("}"));
120: }
121:
122: public String getExpressionString() {
123: return methodBinding.getExpressionString();
124: }
125:
126: public Object saveState(FacesContext context) {
127: if (!isTransient()) {
128: if (methodBinding instanceof StateHolder) {
129: Object[] state = new Object[2];
130: state[0] = methodBinding.getClass().getName();
131: state[1] = ((StateHolder) methodBinding)
132: .saveState(context);
133: return state;
134: } else {
135: return methodBinding;
136: }
137: }
138: return null;
139: }
140:
141: public void restoreState(FacesContext context, Object state) {
142: if (state instanceof MethodBinding) {
143: methodBinding = (MethodBinding) state;
144: methodInfo = null;
145: } else if (state != null) {
146: Object[] values = (Object[]) state;
147: methodBinding = (MethodBinding) _ClassUtils.newInstance(
148: values[0].toString(), EXPECTED_TYPES);
149: ((StateHolder) methodBinding).restoreState(context,
150: values[1]);
151: methodInfo = null;
152: }
153: }
154:
155: public void setTransient(boolean transientFlag) {
156: _transientFlag = transientFlag;
157: }
158:
159: public boolean isTransient() {
160: return _transientFlag;
161: }
162:
163: @Override
164: public int hashCode() {
165: final int PRIME = 31;
166: int result = 1;
167: result = PRIME
168: * result
169: + ((methodBinding == null) ? 0 : methodBinding
170: .hashCode());
171: return result;
172: }
173:
174: @Override
175: public boolean equals(Object obj) {
176: if (this == obj)
177: return true;
178: if (obj == null)
179: return false;
180: if (getClass() != obj.getClass())
181: return false;
182: final _MethodBindingToMethodExpression other = (_MethodBindingToMethodExpression) obj;
183: if (methodBinding == null) {
184: if (other.methodBinding != null)
185: return false;
186: } else if (!methodBinding.equals(other.methodBinding))
187: return false;
188: return true;
189: }
190:
191: private void checkNullState(Object notNullInstance,
192: String instanceName) {
193: if (notNullInstance == null)
194: throw new IllegalStateException(instanceName + " is null");
195: }
196:
197: private void checkNullArgument(Object notNullInstance,
198: String instanceName) {
199: if (notNullInstance == null)
200: throw new IllegalArgumentException(instanceName
201: + " is null");
202: }
203:
204: private <T> T invoke(Invoker<T> invoker) {
205: try {
206: return invoker.invoke();
207: } catch (javax.faces.el.MethodNotFoundException e) {
208: throw new MethodNotFoundException(e.getMessage(), e);
209: } catch (EvaluationException e) {
210: throw new ELException(e.getMessage(), e);
211: }
212: }
213:
214: private interface Invoker<T> {
215: T invoke();
216: }
217: }
|