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.Arguments;
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 Arguments.checkNotNull("configurationProperties", configurationProperties);
77
78 this.configurationProperties = configurationProperties;
79 }
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 public Object invoke(final Object proxy, final Method method,
100 final Object[] args) throws InvalidArgumentsException
101 {
102 if (proxy == null)
103 {
104 return null;
105 }
106
107 final String methodName = method.getName();
108 if ("equals".equals(methodName))
109 {
110 return handleMethodEquals(proxy, args);
111 }
112
113 checkNoArgs(args);
114
115 if ("toString".equals(methodName))
116 {
117 return handleMethodToString(proxy);
118 }
119 else if ("hashCode".equals(methodName))
120 {
121 return handleMethodHashCode(proxy);
122 }
123
124 return handlePropertyMethod(method);
125 }
126
127 private Object handlePropertyMethod(final Method method)
128 throws UnknownPropertyException, PropertyValidationException,
129 InvalidArgumentsException
130 {
131 final Class<?> declaringClass = method.getDeclaringClass();
132 final PropertiesContext context =
133 configurationProperties.getContext(declaringClass);
134 final PropertyMetaDataParser parser =
135 PropertyMetaDataParser.create(context);
136
137 if (isPropertyKeyMethod(method))
138 {
139 final Method propertyMethod =
140 PropertyMethodNameUtilities.fetchPropertyMethod(method);
141 return parser.readKey(propertyMethod);
142 }
143 else if (isPropertyDescriptorMethod(method))
144 {
145 final Method propertyMethod =
146 PropertyMethodNameUtilities.fetchPropertyMethod(method);
147 return parser.readDescriptor(propertyMethod);
148 }
149 else if (isPropertyMethod(method))
150 {
151 final PropertyKey key = parser.readKey(method);
152 return configurationProperties.getPropertyValue(key);
153 }
154 else
155 {
156 throw new InvalidArgumentsException(
157 "The method '" + method.getName() + "' of interface '"
158 + method.getDeclaringClass().getCanonicalName()
159 + "' is not a property method, not a property key method and "
160 + "not a property descriptor method.");
161 }
162 }
163
164 Object handleMethodEquals(final Object proxy, final Object[] args)
165 {
166 checkOneArg(args);
167 return proxy == args[0];
168 }
169
170 private Object handleMethodHashCode(final Object proxy)
171 throws SecurityException
172 {
173 final Method[] methods = proxy.getClass().getMethods();
174 int hash = proxy.getClass().getCanonicalName().hashCode();
175 for (int i = 0; i < methods.length; i++)
176 {
177 hash = hash * 37 + methods[i].getName().hashCode();
178 }
179 return hash;
180 }
181
182 private Object handleMethodToString(final Object proxy)
183 throws SecurityException
184 {
185 final StringBuilder toStringBuilder =
186 new StringBuilder("Proxy for: ").append(proxy.getClass().getName());
187 final Method[] methods = proxy.getClass().getMethods();
188 for (int i = 0; i < methods.length; i++)
189 {
190 toStringBuilder.append("::").append(methods[i].getName());
191 }
192 return toStringBuilder.toString();
193 }
194
195 private boolean isPropertyKeyMethod(final Method m)
196 {
197 final Class<?> returnType = m.getReturnType();
198 return PropertyKey.class.equals(returnType);
199 }
200
201 private boolean isPropertyDescriptorMethod(final Method m)
202 {
203 final Class<?> returnType = m.getReturnType();
204 return PropertyDescriptor.class.equals(returnType);
205 }
206
207 private boolean isPropertyMethod(final Method m)
208 {
209 return !PropertyMethodNameUtilities.isMethodAnnotatedWithAnnotation(
210 PropertyMetaDataMethod.class, m);
211 }
212
213
214
215
216
217
218 private void checkOneArg(final Object[] args)
219 {
220 if (args == null || args.length != 1)
221 {
222 throw new InvalidArgumentsException("Equals need one parameter.");
223 }
224 }
225
226
227
228
229
230
231
232 private void checkNoArgs(final Object[] args)
233 {
234 if (args != null && args.length > 0)
235 {
236 throw new InvalidArgumentsException(
237 "Only methods without arguments are supported for property methods.");
238 }
239 }
240
241
242
243 }