1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.ini4j.spi;
17
18 import java.beans.Introspector;
19 import java.beans.PropertyChangeListener;
20 import java.beans.PropertyChangeSupport;
21 import java.beans.PropertyVetoException;
22 import java.beans.VetoableChangeListener;
23 import java.beans.VetoableChangeSupport;
24
25 import java.lang.reflect.Array;
26 import java.lang.reflect.InvocationHandler;
27 import java.lang.reflect.Method;
28
29 public abstract class AbstractBeanInvocationHandler implements InvocationHandler
30 {
31 private static final String PROPERTY_CHANGE_LISTENER = "PropertyChangeListener";
32 private static final String VETOABLE_CHANGE_LISTENER = "VetoableChangeListener";
33 private static final String ADD_PREFIX = "add";
34 private static final String READ_PREFIX = "get";
35 private static final String REMOVE_PREFIX = "remove";
36 private static final String READ_BOOLEAN_PREFIX = "is";
37 private static final String WRITE_PREFIX = "set";
38 private static final String HAS_PREFIX = "has";
39
40 private static enum Prefix
41 {
42 READ(READ_PREFIX),
43 READ_BOOLEAN(READ_BOOLEAN_PREFIX),
44 WRITE(WRITE_PREFIX),
45 ADD_CHANGE(ADD_PREFIX + PROPERTY_CHANGE_LISTENER),
46 ADD_VETO(ADD_PREFIX + VETOABLE_CHANGE_LISTENER),
47 REMOVE_CHANGE(REMOVE_PREFIX + PROPERTY_CHANGE_LISTENER),
48 REMOVE_VETO(REMOVE_PREFIX + VETOABLE_CHANGE_LISTENER),
49 HAS(HAS_PREFIX);
50 private int _len;
51 private String _value;
52
53 private Prefix(String value)
54 {
55 _value = value;
56 _len = value.length();
57 }
58
59 public static Prefix parse(String str)
60 {
61 Prefix ret = null;
62
63 for (Prefix p : values())
64 {
65 if (str.startsWith(p.getValue()))
66 {
67 ret = p;
68
69 break;
70 }
71 }
72
73 return ret;
74 }
75
76 public String getTail(String input)
77 {
78 return Introspector.decapitalize(input.substring(_len));
79 }
80
81 public String getValue()
82 {
83 return _value;
84 }
85 }
86
87 private PropertyChangeSupport _pcSupport;
88 private Object _proxy;
89 private VetoableChangeSupport _vcSupport;
90
91 @Override public Object invoke(Object proxy, Method method, Object[] args) throws PropertyVetoException
92 {
93 Object ret = null;
94 Prefix prefix = Prefix.parse(method.getName());
95
96 if (prefix != null)
97 {
98 String tail = prefix.getTail(method.getName());
99
100 updateProxy(proxy);
101 switch (prefix)
102 {
103
104 case READ:
105 ret = getProperty(prefix.getTail(method.getName()), method.getReturnType());
106 break;
107
108 case READ_BOOLEAN:
109 ret = getProperty(prefix.getTail(method.getName()), method.getReturnType());
110 break;
111
112 case WRITE:
113 setProperty(tail, args[0], method.getParameterTypes()[0]);
114 break;
115
116 case HAS:
117 ret = Boolean.valueOf(hasProperty(prefix.getTail(method.getName())));
118 break;
119
120 case ADD_CHANGE:
121 addPropertyChangeListener((String) args[0], (PropertyChangeListener) args[1]);
122 break;
123
124 case ADD_VETO:
125 addVetoableChangeListener((String) args[0], (VetoableChangeListener) args[1]);
126 break;
127
128 case REMOVE_CHANGE:
129 removePropertyChangeListener((String) args[0], (PropertyChangeListener) args[1]);
130 break;
131
132 case REMOVE_VETO:
133 removeVetoableChangeListener((String) args[0], (VetoableChangeListener) args[1]);
134 break;
135
136 default:
137 break;
138 }
139 }
140
141 return ret;
142 }
143
144 protected abstract Object getPropertySpi(String property, Class<?> clazz);
145
146 protected abstract void setPropertySpi(String property, Object value, Class<?> clazz);
147
148 protected abstract boolean hasPropertySpi(String property);
149
150 protected synchronized Object getProperty(String property, Class<?> clazz)
151 {
152 Object o;
153
154 try
155 {
156 o = getPropertySpi(property, clazz);
157 if (o == null)
158 {
159 o = zero(clazz);
160 }
161 else if (clazz.isArray() && (o instanceof String[]) && !clazz.equals(String[].class))
162 {
163 String[] str = (String[]) o;
164
165 o = Array.newInstance(clazz.getComponentType(), str.length);
166 for (int i = 0; i < str.length; i++)
167 {
168 Array.set(o, i, parse(str[i], clazz.getComponentType()));
169 }
170 }
171 else if ((o instanceof String) && !clazz.equals(String.class))
172 {
173 o = parse((String) o, clazz);
174 }
175 }
176 catch (Exception x)
177 {
178 o = zero(clazz);
179 }
180
181 return o;
182 }
183
184 protected synchronized void setProperty(String property, Object value, Class<?> clazz) throws PropertyVetoException
185 {
186 boolean pc = (_pcSupport != null) && _pcSupport.hasListeners(property);
187 boolean vc = (_vcSupport != null) && _vcSupport.hasListeners(property);
188 Object oldVal = null;
189 Object newVal = ((value != null) && clazz.equals(String.class) && !(value instanceof String)) ? value.toString() : value;
190
191 if (pc || vc)
192 {
193 oldVal = getProperty(property, clazz);
194 }
195
196 if (vc)
197 {
198 fireVetoableChange(property, oldVal, value);
199 }
200
201 setPropertySpi(property, newVal, clazz);
202 if (pc)
203 {
204 firePropertyChange(property, oldVal, value);
205 }
206 }
207
208 protected synchronized Object getProxy()
209 {
210 return _proxy;
211 }
212
213 protected synchronized void addPropertyChangeListener(String property, PropertyChangeListener listener)
214 {
215 if (_pcSupport == null)
216 {
217 _pcSupport = new PropertyChangeSupport(_proxy);
218 }
219
220 _pcSupport.addPropertyChangeListener(property, listener);
221 }
222
223 protected synchronized void addVetoableChangeListener(String property, VetoableChangeListener listener)
224 {
225 if (_vcSupport == null)
226 {
227 _vcSupport = new VetoableChangeSupport(_proxy);
228 }
229
230 _vcSupport.addVetoableChangeListener(property, listener);
231 }
232
233 protected synchronized void firePropertyChange(String property, Object oldValue, Object newValue)
234 {
235 if (_pcSupport != null)
236 {
237 _pcSupport.firePropertyChange(property, oldValue, newValue);
238 }
239 }
240
241 protected synchronized void fireVetoableChange(String property, Object oldValue, Object newValue) throws PropertyVetoException
242 {
243 if (_vcSupport != null)
244 {
245 _vcSupport.fireVetoableChange(property, oldValue, newValue);
246 }
247 }
248
249 protected synchronized boolean hasProperty(String property)
250 {
251 boolean ret;
252
253 try
254 {
255 ret = hasPropertySpi(property);
256 }
257 catch (Exception x)
258 {
259 ret = false;
260 }
261
262 return ret;
263 }
264
265 protected Object parse(String value, Class<?> clazz) throws IllegalArgumentException
266 {
267 return BeanTool.getInstance().parse(value, clazz);
268 }
269
270 protected synchronized void removePropertyChangeListener(String property, PropertyChangeListener listener)
271 {
272 if (_pcSupport != null)
273 {
274 _pcSupport.removePropertyChangeListener(property, listener);
275 }
276 }
277
278 protected synchronized void removeVetoableChangeListener(String property, VetoableChangeListener listener)
279 {
280 if (_vcSupport != null)
281 {
282 _vcSupport.removeVetoableChangeListener(property, listener);
283 }
284 }
285
286 protected Object zero(Class<?> clazz)
287 {
288 return BeanTool.getInstance().zero(clazz);
289 }
290
291 private synchronized void updateProxy(Object value)
292 {
293 if (_proxy == null)
294 {
295 _proxy = value;
296 }
297 }
298 }