View Javadoc
1   /*
2    * Copyright 2004-2005, 2007-2008 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package net.sf.morph.reflect.reflectors;
17  
18  import java.util.Iterator;
19  import java.util.LinkedList;
20  import java.util.List;
21  import java.util.Set;
22  
23  import net.sf.composite.SpecializableComposite;
24  import net.sf.composite.StrictlyTypedComposite;
25  import net.sf.composite.util.ObjectUtils;
26  import net.sf.morph.reflect.BeanReflector;
27  import net.sf.morph.reflect.CompositeReflector;
28  import net.sf.morph.reflect.ContainerReflector;
29  import net.sf.morph.reflect.DecoratedReflector;
30  import net.sf.morph.reflect.GrowableContainerReflector;
31  import net.sf.morph.reflect.IndexedContainerReflector;
32  import net.sf.morph.reflect.InstantiatingReflector;
33  import net.sf.morph.reflect.MutableIndexedContainerReflector;
34  import net.sf.morph.reflect.ReflectionException;
35  import net.sf.morph.reflect.Reflector;
36  import net.sf.morph.reflect.SizableReflector;
37  import net.sf.morph.util.ClassUtils;
38  import net.sf.morph.util.ContainerUtils;
39  import net.sf.morph.util.ReflectorUtils;
40  
41  /**
42   * Reflector that can be used to combine multiple bean reflectors.  By default,
43   * a new instance of this reflector will include all reflectors defined in
44   * Morph except the MapReflector (the MapBeanReflector is used
45   * instead).
46   *
47   * @author Matt Sgarlata
48   * @since Dec 13, 2004
49   */
50  public class SimpleDelegatingReflector extends BaseCompositeReflector implements
51  		DecoratedReflector, StrictlyTypedComposite, SpecializableComposite,
52  		BeanReflector, ContainerReflector, GrowableContainerReflector,
53  		IndexedContainerReflector, InstantiatingReflector,
54  		MutableIndexedContainerReflector, CompositeReflector, Cloneable {
55  
56  	/**
57  	 * Construct a new SimpleDelegatingReflector.
58  	 */
59  	public SimpleDelegatingReflector() {
60  		this(null, true);
61  	}
62  
63  	/**
64  	 * Construct a new SimpleDelegatingReflector.
65  	 * @param components
66  	 */
67  	public SimpleDelegatingReflector(Reflector[] components) {
68  		this(components, false);
69  	}
70  
71  	/**
72  	 * Construct a new SimpleDelegatingReflector.
73  	 * @param components
74  	 * @param appendDefaultComponents if true, the components returned from createDefaultComponents() will be added.
75  	 */
76  	public SimpleDelegatingReflector(Reflector[] components, boolean appendDefaultComponents) {
77  		if (appendDefaultComponents) {
78  			Reflector[] defaultComponents = createDefaultComponents();
79  			if (ObjectUtils.isEmpty(components)) {
80  				components = defaultComponents;
81  			}
82  			else {
83  				//use getComponentType() in case a subclass tightens from Reflector;
84  				Reflector[] newComponents = (Reflector[]) ClassUtils.createArray(
85  						getComponentType(), components.length + defaultComponents.length);
86  				System.arraycopy(components, 0, newComponents, 0, components.length);
87  				System.arraycopy(defaultComponents, 0, newComponents, components.length, defaultComponents.length);
88  				components = newComponents;
89  			}
90  		}
91  		setComponents(components);
92  	}
93  
94  	protected Reflector[] createDefaultComponents() {
95  		List componentList = new LinkedList();
96  
97  		// container reflectors
98  		componentList.add(new ListReflector());
99  		componentList.add(new SortedSetReflector());
100 		componentList.add(new SetReflector());
101 		componentList.add(new StringTokenizerReflector());
102 		componentList.add(new ResetableIteratorWrapperReflector());
103 		componentList.add(new EnumerationReflector());
104 		componentList.add(new IteratorReflector());
105 		// have to do this to avoid an infinite loop 
106 		componentList.add(new ArrayReflector(this));
107 		componentList.add(new CollectionReflector());
108 
109 		// result set reflector acts as a container and as a bean reflector
110 		componentList.add(new ResultSetReflector());
111 
112 		// the context reflector must be preferred over the map reflector,
113 		// because all contexts are maps
114 		componentList.add(new ContextReflector());
115 
116 		// a map reflector can act both as a container reflector and as a
117 		// bean reflector
118 		componentList.add(new MapReflector());
119 
120 		// bean reflectors
121 		if (ClassUtils.isServletApiPresent()) {
122 			componentList.add(new ServletRequestReflector());
123 			componentList.add(new HttpSessionAttributeReflector());
124 			componentList.add(new ServletContextAttributeReflector());
125 		}
126 		if (ClassUtils.isJspApiPresent()) {
127 			componentList.add(new PageContextAttributeReflector());
128 		}
129 		if (ClassUtils.isBeanUtilsPresent()) {
130 			componentList.add(new DynaBeanReflector());
131 		}
132 		componentList.add(new SimpleInstantiatingReflector());
133 		componentList.add(new ObjectReflector());
134 
135 		return (Reflector[]) componentList.toArray(new Reflector[componentList.size()]);
136 	}
137 
138 // internal state initialization/validation
139 
140 	protected void initializeImpl() throws Exception {
141 		super.initializeImpl();
142 		getComponentValidator().validate(this);
143 	}
144 
145 	protected Class[] getReflectableClassesImpl() {
146 		Set set = ContainerUtils.createOrderedSet();
147 		Object[] reflectors = getComponents();
148 		for (int i = 0; i < reflectors.length; i++) {
149 			Class[] reflectableClasses = ((Reflector) reflectors[i]).getReflectableClasses();
150 			for (int j = 0; j < reflectableClasses.length; j++) {
151 				set.add(reflectableClasses[j]);
152 			}
153 		}
154 		return (Class[]) set.toArray(new Class[set.size()]);
155 	}
156 
157 // bean reflectors
158 
159 	protected Object getImpl(Object bean, String propertyName) throws Exception {
160 		return getBeanReflector(bean).get(bean, propertyName);
161 	}
162 
163 	protected String[] getPropertyNamesImpl(Object bean) throws Exception {
164 		return getBeanReflector(bean).getPropertyNames(bean);
165 	}
166 
167 	protected Class getTypeImpl(Object bean, String propertyName)
168 		throws Exception {
169 		return getBeanReflector(bean).getType(bean, propertyName);
170 	}
171 
172 	protected boolean isReadableImpl(Object bean, String propertyName)
173 		throws Exception {
174 		return getBeanReflector(bean).isReadable(bean, propertyName);
175 	}
176 
177 	protected boolean isWriteableImpl(Object bean, String propertyName)
178 		throws Exception {
179 		return getBeanReflector(bean).isWriteable(bean, propertyName);
180 	}
181 
182 	protected void setImpl(Object bean, String propertyName, Object value)
183 		throws Exception {
184 		getBeanReflector(bean).set(bean, propertyName, value);
185 	}
186 
187 // container reflectors
188 
189 	protected Iterator getIteratorImpl(Object container) throws Exception {
190 		return getContainerReflector(container).getIterator(container);
191 	}
192 
193 	protected Class getContainedTypeImpl(Class clazz) throws Exception {
194 		return getContainerReflectorForClass(clazz).getContainedType(clazz);
195 	}
196 
197 // sizable reflectors
198 
199 	protected int getSizeImpl(Object container) throws Exception {
200 		return getSizableReflector(container).getSize(container);
201 	}
202 
203 // growable reflectors
204 
205 	protected boolean addImpl(Object container, Object value) throws Exception {
206 		return getGrowableContainerReflector(container).add(container, value);
207 	}
208 
209 // indexed reflectors
210 
211 	protected Object getImpl(Object container, int index) throws Exception {
212 		return getIndexedContainerReflector(container).get(container, index);
213 	}
214 
215 // mutable indexed reflectors
216 
217 	protected Object setImpl(Object container, int index, Object propertyValue)
218 		throws Exception {
219 		return getMutableIndexedContainerReflector(container).set(container, index, propertyValue);
220 	}
221 
222 	protected Object newInstanceImpl(Class clazz, Object parameters) throws Exception {
223 		InstantiatingReflector reflector = getInstantiatingReflectorForClass(clazz);
224 		return reflector.newInstance(clazz, parameters);
225 	}
226 
227 	public boolean isReflectableImpl(Class reflectedType, Class reflectorType)
228 			throws ReflectionException {
229 		return safeGetReflector(reflectorType, reflectedType) != null;
230 	}
231 
232 	protected Reflector getReflector(Class reflectorType, Class reflectedType) {
233 		Reflector result = safeGetReflector(reflectorType, reflectedType);
234 		if (result == null) {
235 			throw new ReflectionException("Could not find a "
236 					+ ClassUtils.getUnqualifiedClassName(reflectorType)
237 					+ " that can reflect "
238 					+ ObjectUtils.getObjectDescription(reflectedType));
239 		}
240 		return result;
241 	}
242 
243 	private Reflector safeGetReflector(Class reflectorType, Class reflectedType) {
244 		for (int i = 0; i < getComponents().length; i++) {
245 			Reflector component = (Reflector) getComponents()[i];
246 			if (ReflectorUtils.isReflectable(component, reflectedType, reflectorType)) {
247 				if (log.isTraceEnabled()) {
248 					log.trace("Using "
249 						+ component.getClass().getName()
250 						+ " to reflect "
251 						+ ObjectUtils.getObjectDescription(reflectedType));
252 				}
253 				return component;
254 			}
255 		}
256 		return null;
257 	}
258 
259 	protected BeanReflector getBeanReflector(Object bean) {
260 		return (BeanReflector) getReflector(BeanReflector.class, bean.getClass());
261 	}
262 
263 	protected ContainerReflector getContainerReflector(Object bean) {
264 		return (ContainerReflector) getReflector(ContainerReflector.class, bean.getClass());
265 	}
266 
267 	protected ContainerReflector getContainerReflectorForClass(Class reflectedClass) {
268 		return (ContainerReflector) getReflector(ContainerReflector.class, reflectedClass);
269 	}
270 
271 	protected GrowableContainerReflector getGrowableContainerReflector(Object bean) {
272 		return (GrowableContainerReflector) getReflector(GrowableContainerReflector.class, bean.getClass());
273 	}
274 
275 	protected SizableReflector getSizableReflector(Object bean) {
276 		return (SizableReflector) getReflector(SizableReflector.class, bean.getClass());
277 	}
278 
279 	protected IndexedContainerReflector getIndexedContainerReflector(Object bean) {
280 		return (IndexedContainerReflector) getReflector(IndexedContainerReflector.class, bean.getClass());
281 	}
282 
283 	protected MutableIndexedContainerReflector getMutableIndexedContainerReflector(Object bean) {
284 		return (MutableIndexedContainerReflector) getReflector(MutableIndexedContainerReflector.class, bean.getClass());
285 	}
286 
287 	protected InstantiatingReflector getInstantiatingReflectorForClass(Class clazz) {
288 		return (InstantiatingReflector) getReflector(InstantiatingReflector.class, clazz);
289 	}
290 
291 	// workaround for problem w/constructor using JDK 1.4.2_06 on WinXP SP2
292 	public Object[] getComponents() {
293 		if (super.getComponents() == null) {
294 			setComponents(createDefaultComponents());
295 		}
296 		return super.getComponents();
297 	}
298 
299 }