1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.morph.wrap.support;
17
18 import java.lang.reflect.InvocationTargetException;
19 import java.lang.reflect.Method;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25
26 import net.sf.composite.util.CompositeUtils;
27 import net.sf.composite.util.ObjectUtils;
28 import net.sf.morph.Defaults;
29 import net.sf.morph.reflect.BeanReflector;
30 import net.sf.morph.reflect.ContainerReflector;
31 import net.sf.morph.reflect.GrowableContainerReflector;
32 import net.sf.morph.reflect.IndexedContainerReflector;
33 import net.sf.morph.reflect.Reflector;
34 import net.sf.morph.reflect.SizableReflector;
35 import net.sf.morph.util.BidirectionalMap;
36 import net.sf.morph.wrap.Bean;
37 import net.sf.morph.wrap.Container;
38 import net.sf.morph.wrap.GrowableContainer;
39 import net.sf.morph.wrap.IndexedContainer;
40 import net.sf.morph.wrap.MutableIndexedContainer;
41 import net.sf.morph.wrap.Sizable;
42
43 /**
44 * Default WrapperInvocationHandler implementation.
45 * @author Matt Sgarlata
46 * @since Jan 16, 2005
47 */
48 public class DefaultWrapperInvocationHandler implements WrapperInvocationHandler {
49
50 private static final Map DEFAULT_REFLECTOR_WRAPPER_MAP;
51
52 static {
53 DEFAULT_REFLECTOR_WRAPPER_MAP = new BidirectionalMap(6);
54 DEFAULT_REFLECTOR_WRAPPER_MAP.put(BeanReflector.class, Bean.class);
55 DEFAULT_REFLECTOR_WRAPPER_MAP.put(ContainerReflector.class, Container.class);
56 DEFAULT_REFLECTOR_WRAPPER_MAP.put(GrowableContainerReflector.class, GrowableContainer.class);
57 DEFAULT_REFLECTOR_WRAPPER_MAP.put(IndexedContainerReflector.class, IndexedContainer.class);
58 DEFAULT_REFLECTOR_WRAPPER_MAP.put(MutableIndexedContainer.class, MutableIndexedContainer.class);
59 DEFAULT_REFLECTOR_WRAPPER_MAP.put(SizableReflector.class, Sizable.class);
60 }
61
62 private Map reflectorWrapperMap;
63 private Reflector reflector;
64 private Object wrapped;
65
66 /**
67 * Create a new DefaultWrapperInvocationHandler.
68 * @param wrapped object
69 */
70 public DefaultWrapperInvocationHandler(Object wrapped) {
71 super();
72 this.wrapped = wrapped;
73 }
74
75 /**
76 * Create a new DefaultWrapperInvocationHandler.
77 * @param wrapped object
78 * @param reflector to use
79 */
80 public DefaultWrapperInvocationHandler(Object wrapped, Reflector reflector) {
81 this(wrapped);
82 this.reflector = reflector;
83 }
84
85 /**
86 * {@inheritDoc}
87 */
88 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
89
90 try {
91
92 Class declaringClass = method.getDeclaringClass();
93 if (declaringClass.equals(getWrapped().getClass())) {
94 return method.invoke(getWrapped(), args);
95 }
96 Class wrapperClass = method.getDeclaringClass();
97 Class reflectorClass = (Class) getBiDirectionalReflectorWrapperMap().getKey(wrapperClass);
98 if (reflectorClass == null) {
99 throw new IllegalArgumentException(
100 "Cannot invoke method "
101 + method
102 + " because it is not declared in one of the recognized wrapper classes, which are: "
103 + ObjectUtils
104 .getObjectDescription(getReflectorWrapperMap()
105 .values()));
106 }
107
108 Reflector reflector = (Reflector) CompositeUtils.specialize(getReflector(), reflectorClass);
109
110 int wrapperNumArgs = method.getParameterTypes().length;
111 int reflectorNumArgs = wrapperNumArgs + 1;
112
113 Class[] reflectorParameterTypes = new Class[reflectorNumArgs];
114 reflectorParameterTypes[0] = Object.class;
115 if (method.getParameterTypes() != null) {
116 System.arraycopy(method.getParameterTypes(), 0,
117 reflectorParameterTypes, 1, wrapperNumArgs);
118 }
119
120 Object[] reflectorArgs = new Object[reflectorNumArgs];
121 reflectorArgs[0] = getWrapped();
122 if (args != null) {
123 System.arraycopy(args, 0, reflectorArgs, 1, wrapperNumArgs);
124 }
125
126 Method reflectorMethod = reflector.getClass().getMethod(method.getName(), reflectorParameterTypes);
127
128 return reflectorMethod.invoke(reflector, reflectorArgs);
129 }
130
131
132 catch (InvocationTargetException e) {
133 throw e.getTargetException();
134 }
135
136 }
137
138 /**
139 * {@inheritDoc}
140 */
141 public Class[] getInterfaces(Object object) {
142 Class[] baseInterfaces = object.getClass().getInterfaces();
143 List interfaces;
144 if (baseInterfaces == null) {
145 interfaces = new ArrayList();
146 }
147 else {
148
149 interfaces = new ArrayList(Arrays.asList(baseInterfaces));
150 }
151 Map reflectorWrapperMap = getReflectorWrapperMap();
152 Iterator reflectorClasses = reflectorWrapperMap.keySet().iterator();
153 while (reflectorClasses.hasNext()) {
154 Class reflectorClass = (Class) reflectorClasses.next();
155 Class wrapperClass = (Class) reflectorWrapperMap.get(reflectorClass);
156 if (CompositeUtils.isSpecializable(getReflector(), reflectorClass)) {
157 interfaces.add(wrapperClass);
158 }
159 }
160 return (Class[]) interfaces.toArray(new Class[interfaces.size()]);
161 }
162
163 /**
164 * Get the bidirectional reflector map.
165 * @return BidirectionalMap
166 */
167 protected BidirectionalMap getBiDirectionalReflectorWrapperMap() {
168 return (BidirectionalMap) getReflectorWrapperMap();
169 }
170
171 /**
172 * Get the reflectorWrapperMap.
173 * @return Map
174 */
175 public Map getReflectorWrapperMap() {
176 if (reflectorWrapperMap == null) {
177 setReflectorWrapperMap(DEFAULT_REFLECTOR_WRAPPER_MAP);
178 }
179 return reflectorWrapperMap;
180 }
181
182 /**
183 * Set the reflectorWrapperMap.
184 * @param reflectorWrapperMap to set
185 */
186 public void setReflectorWrapperMap(Map reflectorWrapperMap) {
187 this.reflectorWrapperMap = BidirectionalMap.getInstance(reflectorWrapperMap);
188 }
189
190 /**
191 * Get the reflector.
192 * @return Reflector
193 */
194 public synchronized Reflector getReflector() {
195 if (reflector == null) {
196 setReflector(Defaults.createReflector());
197 }
198 return reflector;
199 }
200
201 /**
202 * Set the reflector.
203 * @param reflector to set
204 */
205 public synchronized void setReflector(Reflector reflector) {
206 this.reflector = reflector;
207 }
208
209 /**
210 * Get the wrapped object.
211 * @return Object
212 */
213 public Object getWrapped() {
214 return wrapped;
215 }
216
217 /**
218 * Set the wrapped object.
219 * @param wrapped object to set
220 */
221 public void setWrapped(Object wrapped) {
222 this.wrapped = wrapped;
223 }
224 }