001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.faces.el;
023:
024: import org.apache.log4j.Logger;
025: import org.jboss.portal.common.reflect.Modifier;
026: import org.jboss.portal.faces.el.decorator.BeanDecorator;
027: import org.jboss.portal.faces.el.dynamic.DynamicBean;
028:
029: import javax.faces.el.EvaluationException;
030: import javax.faces.el.PropertyNotFoundException;
031: import javax.faces.el.PropertyResolver;
032: import java.lang.reflect.Field;
033: import java.util.HashMap;
034: import java.util.Map;
035:
036: /**
037: * A property resolver that provide fine grained configuration of the resolution mechanism.
038: *
039: * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
040: * @version $Revision: 8784 $
041: */
042: public class DelegatingPropertyResolver extends PropertyResolver {
043:
044: /** . */
045: private static final Logger log = Logger
046: .getLogger(DelegatingPropertyResolver.class);
047:
048: /** . */
049: private final PropertyResolver delegate;
050:
051: /** . */
052: private volatile Map decoratorMap = new HashMap();
053:
054: public DelegatingPropertyResolver(PropertyResolver delegate) {
055: this .delegate = delegate;
056: }
057:
058: public DelegatingPropertyResolver() {
059: this (null);
060: }
061:
062: public Class getType(Object base, Object property)
063: throws EvaluationException, PropertyNotFoundException {
064: // See if the object can handle itself the property
065: if (base instanceof DynamicBean) {
066: DynamicBean dynamicBean = (DynamicBean) base;
067: Class type = dynamicBean.getType(property);
068: if (type != null) {
069: return type;
070: }
071: }
072:
073: //
074: GetTypeBeanAction beanAction = new GetTypeBeanAction(base,
075: property);
076: if (resolveAction(base.getClass(), beanAction)) {
077: return beanAction.type;
078: }
079:
080: //
081: if (property instanceof String) {
082: try {
083: Field f = base.getClass().getField((String) property);
084: if (Modifier.isReadableProperty(f)) {
085: return f.getType();
086: }
087: } catch (NoSuchFieldException ignore) {
088: }
089: }
090:
091: //
092: if (delegate != null) {
093: return delegate.getType(base, property);
094: }
095:
096: //
097: throw createPNFE(base, property);
098: }
099:
100: public boolean isReadOnly(Object base, Object property)
101: throws EvaluationException, PropertyNotFoundException {
102: //
103: if (delegate != null) {
104: return delegate.isReadOnly(base, property);
105: }
106:
107: //
108: throw createPNFE(base, property);
109: }
110:
111: public Object getValue(final Object base, final Object property)
112: throws EvaluationException, PropertyNotFoundException {
113: // See if the object can handle itself the property
114: if (base instanceof DynamicBean) {
115: DynamicBean dynamicBean = (DynamicBean) base;
116: PropertyValue value = dynamicBean.getValue(property);
117: if (value != null) {
118: return value.getObject();
119: }
120: }
121:
122: //
123: GetValueBeanAction beanAction = new GetValueBeanAction(base,
124: property);
125: if (resolveAction(base.getClass(), beanAction)) {
126: return beanAction.value.getObject();
127: }
128:
129: //
130: if (property instanceof String) {
131: try {
132: Field f = base.getClass().getField((String) property);
133: if (Modifier.isReadableProperty(f)) {
134: return f.get(base);
135: }
136: } catch (NoSuchFieldException ignore) {
137: } catch (IllegalAccessException e) {
138: log.error("Was not able to read the field " + property
139: + " of object " + base + " with class "
140: + base.getClass().getName());
141: }
142: }
143:
144: //
145: if (delegate != null) {
146: return delegate.getValue(base, property);
147: }
148:
149: //
150: throw createPNFE(base, property);
151: }
152:
153: public void setValue(Object base, Object property, Object value)
154: throws EvaluationException, PropertyNotFoundException {
155: // See if the object can handle itself the property
156: if (base instanceof DynamicBean) {
157: DynamicBean dynamic = (DynamicBean) base;
158: if (dynamic.setValue(property, value)) {
159: return;
160: }
161: }
162:
163: //
164: SetValueBeanAction beanAction = new SetValueBeanAction(base,
165: property, value);
166: if (resolveAction(base.getClass(), beanAction)) {
167: return;
168: }
169:
170: //
171: if (property instanceof String) {
172: try {
173: Field f = base.getClass().getField((String) property);
174: if (Modifier.isWritableProperty(f)) {
175: f.set(base, value);
176: return;
177: }
178: } catch (NoSuchFieldException ignore) {
179: } catch (IllegalAccessException e) {
180: log.error("Was not able to write the field " + property
181: + " of object " + base + " with class "
182: + base.getClass().getName());
183: }
184: }
185:
186: //
187: if (delegate != null) {
188: delegate.setValue(base, property, value);
189: return;
190: }
191:
192: //
193: throw createPNFE(base, property);
194: }
195:
196: public Class getType(Object base, int index)
197: throws EvaluationException, PropertyNotFoundException {
198: if (delegate != null) {
199: return delegate.getType(base, index);
200: }
201:
202: //
203: throw createPNFE(base, index);
204: }
205:
206: public boolean isReadOnly(Object base, int index)
207: throws EvaluationException, PropertyNotFoundException {
208: //
209: if (delegate != null) {
210: return delegate.isReadOnly(base, index);
211: }
212:
213: //
214: throw createPNFE(base, index);
215: }
216:
217: public Object getValue(Object base, int index)
218: throws EvaluationException, PropertyNotFoundException {
219: //
220: if (delegate != null) {
221: return delegate.getValue(base, index);
222: }
223:
224: //
225: throw createPNFE(base, index);
226: }
227:
228: public void setValue(Object base, int index, Object value)
229: throws EvaluationException, PropertyNotFoundException {
230: //
231: if (delegate != null) {
232: delegate.setValue(base, index, value);
233: }
234:
235: //
236: throw createPNFE(base, index);
237: }
238:
239: public final synchronized void registerDecorator(Class clazz,
240: BeanDecorator decorator) {
241: if (clazz == null) {
242: throw new IllegalArgumentException();
243: }
244: if (decorator == null) {
245: throw new IllegalArgumentException();
246: }
247: Map copy = new HashMap(decoratorMap);
248: copy.put(clazz.getName(), decorator);
249: decoratorMap = copy;
250: log.debug("Added bean decorator " + clazz.getName()
251: + " in resolver map");
252: }
253:
254: private static interface BeanAction {
255: boolean execute(BeanDecorator decorator);
256: }
257:
258: private abstract static class AbstractBeanAction implements
259: BeanAction {
260:
261: /** . */
262: protected final Object base;
263:
264: /** . */
265: protected final Object property;
266:
267: public AbstractBeanAction(Object base, Object property) {
268: this .base = base;
269: this .property = property;
270: }
271: }
272:
273: private static class GetTypeBeanAction extends AbstractBeanAction {
274:
275: /** . */
276: private Class type;
277:
278: public GetTypeBeanAction(Object base, Object property) {
279: super (base, property);
280: }
281:
282: public boolean execute(BeanDecorator decorator) {
283: type = decorator.getType(base, property);
284: return type != null;
285: }
286: }
287:
288: private static class GetValueBeanAction extends AbstractBeanAction {
289:
290: /** . */
291: private PropertyValue value;
292:
293: public GetValueBeanAction(Object base, Object property) {
294: super (base, property);
295: }
296:
297: public boolean execute(BeanDecorator decorator) {
298: value = decorator.getValue(base, property);
299: return value != null;
300: }
301: }
302:
303: private static class SetValueBeanAction extends AbstractBeanAction {
304:
305: /** . */
306: private Object value;
307:
308: public SetValueBeanAction(Object base, Object property,
309: Object value) {
310: super (base, property);
311: this .value = value;
312: }
313:
314: public boolean execute(BeanDecorator decorator) {
315: return decorator.setValue(base, property, value);
316: }
317: }
318:
319: private boolean resolveAction(Class clazz, BeanAction action) {
320: BeanDecorator decorator = (BeanDecorator) decoratorMap
321: .get(clazz.getName());
322: if (decorator != null) {
323: if (action.execute(decorator)) {
324: return true;
325: }
326: }
327: Class[] itfs = clazz.getInterfaces();
328: for (int i = 0; i < itfs.length; i++) {
329: Class itf = clazz.getInterfaces()[i];
330: if (resolveAction(itf, action)) {
331: return true;
332: }
333: }
334: Class super Class = clazz.getSuperclass();
335: if (super Class != null) {
336: if (resolveAction(super Class, action)) {
337: return true;
338: }
339: }
340:
341: return false;
342: }
343:
344: private PropertyNotFoundException createPNFE(Object base, int index) {
345: return createPNFE(base, "[" + index + "]");
346: }
347:
348: private PropertyNotFoundException createPNFE(Object base,
349: Object propertyName) {
350: return new PropertyNotFoundException("Property " + propertyName
351: + " on object " + base + " was not found");
352: }
353: }
|