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