1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.properties.spi.config.proxy;
17
18 import java.io.Serializable;
19 import java.lang.reflect.Method;
20
21 import de.smartics.properties.api.config.domain.SerializableConfigurationProperties;
22 import de.smartics.properties.api.config.domain.UnknownPropertyException;
23 import de.smartics.properties.api.core.annotations.PropertyMetaDataMethod;
24 import de.smartics.properties.api.core.domain.PropertiesContext;
25 import de.smartics.properties.api.core.domain.PropertyDescriptor;
26 import de.smartics.properties.api.core.domain.PropertyKey;
27 import de.smartics.properties.api.core.domain.PropertyValidationException;
28 import de.smartics.properties.spi.core.metadata.PropertyMetaDataParser;
29 import de.smartics.util.lang.Arg;
30
31
32
33
34
35
36
37
38
39 public final class PropertiesProxyInvocationHandler implements
40 java.lang.reflect.InvocationHandler, Serializable
41 {
42
43
44
45
46
47
48
49 private static final long serialVersionUID = 1L;
50
51
52
53
54
55
56
57
58 private final SerializableConfigurationProperties configurationProperties;
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public PropertiesProxyInvocationHandler(
73 final SerializableConfigurationProperties configurationProperties)
74 throws NullPointerException
75 {
76 this.configurationProperties =
77 Arg.checkNotNull("configurationProperties", configurationProperties);
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 public Object invoke(final Object proxy, final Method method,
99 final Object[] args) throws InvalidArgumentsException
100 {
101 if (proxy == null)
102 {
103 return null;
104 }
105
106 final String methodName = method.getName();
107 if ("equals".equals(methodName))
108 {
109 return handleMethodEquals(proxy, args);
110 }
111
112 checkNoArgs(args);
113
114 if ("toString".equals(methodName))
115 {
116 return handleMethodToString(proxy);
117 }
118 else if ("hashCode".equals(methodName))
119 {
120 return handleMethodHashCode(proxy);
121 }
122
123 return handlePropertyMethod(method);
124 }
125
126 private Object handlePropertyMethod(final Method method)
127 throws UnknownPropertyException, PropertyValidationException,
128 InvalidArgumentsException
129 {
130 final Class<?> declaringClass = method.getDeclaringClass();
131 final PropertiesContext context =
132 configurationProperties.getContext(declaringClass);
133 final PropertyMetaDataParser parser =
134 PropertyMetaDataParser.create(context);
135
136 if (isPropertyKeyMethod(method))
137 {
138 final Method propertyMethod =
139 PropertyMethodNameUtilities.fetchPropertyMethod(method);
140 return parser.readKey(propertyMethod);
141 }
142 else if (isPropertyDescriptorMethod(method))
143 {
144 final Method propertyMethod =
145 PropertyMethodNameUtilities.fetchPropertyMethod(method);
146 return parser.readDescriptor(propertyMethod);
147 }
148 else if (isPropertyMethod(method))
149 {
150 final PropertyKey key = parser.readKey(method);
151 final Object propertyValue =
152 configurationProperties.getPropertyValue(key);
153 return propertyValue;
154 }
155 else
156 {
157 throw new InvalidArgumentsException(
158 "The method '" + method.getName() + "' of interface '"
159 + method.getDeclaringClass().getCanonicalName()
160 + "' is not a property method, not a property key method and "
161 + "not a property descriptor method.");
162 }
163 }
164
165 Object handleMethodEquals(final Object proxy, final Object[] args)
166 {
167 checkOneArg(args);
168 return proxy == args[0];
169 }
170
171 private Object handleMethodHashCode(final Object proxy)
172 throws SecurityException
173 {
174 final Method[] methods = proxy.getClass().getMethods();
175 int hash = proxy.getClass().getCanonicalName().hashCode();
176 for (int i = 0; i < methods.length; i++)
177 {
178 hash = hash * 37 + methods[i].getName().hashCode();
179 }
180 return hash;
181 }
182
183 private Object handleMethodToString(final Object proxy)
184 throws SecurityException
185 {
186 final StringBuilder toStringBuilder =
187 new StringBuilder("Proxy for: ").append(proxy.getClass().getName());
188 final Method[] methods = proxy.getClass().getMethods();
189 for (int i = 0; i < methods.length; i++)
190 {
191 toStringBuilder.append("::").append(methods[i].getName());
192 }
193 return toStringBuilder.toString();
194 }
195
196 private boolean isPropertyKeyMethod(final Method m)
197 {
198 final Class<?> returnType = m.getReturnType();
199 return PropertyKey.class.equals(returnType);
200 }
201
202 private boolean isPropertyDescriptorMethod(final Method m)
203 {
204 final Class<?> returnType = m.getReturnType();
205 return PropertyDescriptor.class.equals(returnType);
206 }
207
208 private boolean isPropertyMethod(final Method m)
209 {
210 return !PropertyMethodNameUtilities.isMethodAnnotatedWithAnnotation(
211 PropertyMetaDataMethod.class, m);
212 }
213
214
215
216
217
218
219 private void checkOneArg(final Object[] args)
220 {
221 if (args == null || args.length != 1)
222 {
223 throw new InvalidArgumentsException("Equals need one parameter.");
224 }
225 }
226
227
228
229
230
231
232
233 private void checkNoArgs(final Object[] args)
234 {
235 if (args != null && args.length > 0)
236 {
237 throw new InvalidArgumentsException(
238 "Only methods without arguments are supported for property methods.");
239 }
240 }
241
242
243
244 }