1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.beanmerger;
35
36 import java.lang.reflect.InvocationTargetException;
37 import java.lang.reflect.Method;
38 import java.util.ArrayList;
39 import java.util.Collections;
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Set;
43
44 import org.apache.commons.beanutils.MethodUtils;
45 import org.apache.commons.proxy.Invoker;
46 import org.apache.commons.proxy.factory.cglib.CglibProxyFactory;
47
48 import net.sf.cglib.proxy.Enhancer;
49
50
51
52
53
54
55
56 public class ProxyBasedBeanMerger extends BeanMergerBase {
57
58 @Override
59 protected Object mergeBean(List sources) {
60 Set<Class> types = new HashSet<Class>();
61 Class< ? > mostSpecificAssignableClass = sources.get(0).getClass();
62
63 for (Object source : sources) {
64
65
66 Class clazz = source.getClass();
67 while (Enhancer.isEnhanced(clazz)) {
68 clazz = clazz.getSuperclass();
69 }
70
71 Collections.addAll(types, clazz.getInterfaces());
72
73 if (mostSpecificAssignableClass.isAssignableFrom(clazz)) {
74 mostSpecificAssignableClass = clazz;
75 }
76 }
77 types.add(mostSpecificAssignableClass);
78
79 return new CglibProxyFactory().createInvokerProxy(newInvoker(sources), types.toArray(new Class< ? >[types.size()]));
80 }
81
82 protected MergeInvoker newInvoker(List sources) {
83 return new MergeInvoker(this, sources);
84 }
85
86
87
88
89
90
91 protected static final class MergeInvoker implements Invoker {
92
93 private final List sources;
94
95 private BeanMerger merger;
96
97 private MergeInvoker(BeanMerger merger, List sources) {
98 this.merger = merger;
99 this.sources = sources;
100 }
101
102 @Override
103 public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {
104
105 if (arguments.length > 0) {
106 return method.invoke(sources.get(0), arguments);
107 }
108
109 List values = new ArrayList();
110 for (Object obj : sources) {
111 values.add(evaluate(obj, method, arguments));
112 }
113
114 return merger.merge(values);
115 }
116
117 private Object evaluate(Object obj, Method method, Object[] arguments) throws IllegalAccessException, InvocationTargetException {
118
119
120 if (method.getDeclaringClass().isAssignableFrom(obj.getClass())) {
121 return method.invoke(obj, arguments);
122 }
123
124
125 try {
126 return MethodUtils.invokeMethod(obj, method.getName(), arguments);
127 } catch (NoSuchMethodException e) {
128 return null;
129 }
130 }
131 }
132
133 }