Skip to content

Commit 511df48

Browse files
committed
Fix for http://code.google.com/p/mybatis/issues/detail?id=379 - allow writing to final fields through reflection
1 parent b3269d6 commit 511df48

File tree

1 file changed

+28
-32
lines changed

1 file changed

+28
-32
lines changed

src/main/java/org/apache/ibatis/reflection/Reflector.java

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ public class Reflector {
1717

1818
private static boolean classCacheEnabled = true;
1919
private static final String[] EMPTY_STRING_ARRAY = new String[0];
20-
private static final Map<Class, Reflector> REFLECTOR_MAP = Collections.synchronizedMap(new HashMap<Class, Reflector>());
20+
private static final Map<Class<?>, Reflector> REFLECTOR_MAP = Collections.synchronizedMap(new HashMap<Class<?>, Reflector>());
2121

22-
private Class type;
22+
private Class<?> type;
2323
private String[] readablePropertyNames = EMPTY_STRING_ARRAY;
2424
private String[] writeablePropertyNames = EMPTY_STRING_ARRAY;
2525
private Map<String, Invoker> setMethods = new HashMap<String, Invoker>();
2626
private Map<String, Invoker> getMethods = new HashMap<String, Invoker>();
27-
private Map<String, Class> setTypes = new HashMap<String, Class>();
28-
private Map<String, Class> getTypes = new HashMap<String, Class>();
29-
private Constructor defaultConstructor;
27+
private Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>();
28+
private Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>();
29+
private Constructor<?> defaultConstructor;
3030

3131
private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>();
3232

33-
private Reflector(Class clazz) {
33+
private Reflector(Class<?> clazz) {
3434
type = clazz;
3535
addDefaultConstructor(clazz);
3636
addGetMethods(clazz);
@@ -46,9 +46,9 @@ private Reflector(Class clazz) {
4646
}
4747
}
4848

49-
private void addDefaultConstructor(Class clazz) {
50-
Constructor[] consts = clazz.getDeclaredConstructors();
51-
for (Constructor constructor : consts) {
49+
private void addDefaultConstructor(Class<?> clazz) {
50+
Constructor<?>[] consts = clazz.getDeclaredConstructors();
51+
for (Constructor<?> constructor : consts) {
5252
if (constructor.getParameterTypes().length == 0) {
5353
if (canAccessPrivateMethods()) {
5454
try {
@@ -64,7 +64,7 @@ private void addDefaultConstructor(Class clazz) {
6464
}
6565
}
6666

67-
private void addGetMethods(Class cls) {
67+
private void addGetMethods(Class<?> cls) {
6868
Method[] methods = getClassMethods(cls);
6969
for (Method method : methods) {
7070
String name = method.getName();
@@ -89,7 +89,7 @@ private void addGetMethod(String name, Method method) {
8989
}
9090
}
9191

92-
private void addSetMethods(Class cls) {
92+
private void addSetMethods(Class<?> cls) {
9393
Map<String, List<Method>> conflictingSetters = new HashMap<String, List<Method>>();
9494
Method[] methods = getClassMethods(cls);
9595
for (Method method : methods) {
@@ -120,7 +120,7 @@ private void resolveSetterConflicts(Map<String, List<Method>> conflictingSetters
120120
if (setters.size() == 1) {
121121
addSetMethod(propName, firstMethod);
122122
} else {
123-
Class expectedType = getTypes.get(propName);
123+
Class<?> expectedType = getTypes.get(propName);
124124
if (expectedType == null) {
125125
throw new ReflectionException("Illegal overloaded setter method with ambiguous type for property "
126126
+ propName + " in class " + firstMethod.getDeclaringClass() + ". This breaks the JavaBeans " +
@@ -154,7 +154,7 @@ private void addSetMethod(String name, Method method) {
154154
}
155155
}
156156

157-
private void addFields(Class clazz) {
157+
private void addFields(Class<?> clazz) {
158158
Field[] fields = clazz.getDeclaredFields();
159159
for (Field field : fields) {
160160
if (canAccessPrivateMethods()) {
@@ -166,9 +166,9 @@ private void addFields(Class clazz) {
166166
}
167167
if (field.isAccessible()) {
168168
if (!setMethods.containsKey(field.getName())) {
169-
if (!Modifier.isFinal(field.getModifiers())) {
170-
addSetField(field);
171-
}
169+
// issue 379 - removed the check for final because JDK 1.5 allows
170+
// modification of final fields through reflection (JSR-133). (JGB)
171+
addSetField(field);
172172
}
173173
if (!getMethods.containsKey(field.getName())) {
174174
addGetField(field);
@@ -207,16 +207,16 @@ private boolean isValidPropertyName(String name) {
207207
* @param cls The class
208208
* @return An array containing all methods in this class
209209
*/
210-
private Method[] getClassMethods(Class cls) {
210+
private Method[] getClassMethods(Class<?> cls) {
211211
HashMap<String, Method> uniqueMethods = new HashMap<String, Method>();
212-
Class currentClass = cls;
212+
Class<?> currentClass = cls;
213213
while (currentClass != null) {
214214
addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
215215

216216
// we also need to look for interface methods -
217217
// because the class may be abstract
218-
Class[] interfaces = currentClass.getInterfaces();
219-
for (Class anInterface : interfaces) {
218+
Class<?>[] interfaces = currentClass.getInterfaces();
219+
for (Class<?> anInterface : interfaces) {
220220
addUniqueMethods(uniqueMethods, anInterface.getMethods());
221221
}
222222

@@ -253,7 +253,7 @@ private void addUniqueMethods(HashMap<String, Method> uniqueMethods, Method[] me
253253
private String getSignature(Method method) {
254254
StringBuffer sb = new StringBuffer();
255255
sb.append(method.getName());
256-
Class[] parameters = method.getParameterTypes();
256+
Class<?>[] parameters = method.getParameterTypes();
257257
for (int i = 0; i < parameters.length; i++) {
258258
if (i == 0) {
259259
sb.append(':');
@@ -282,11 +282,11 @@ private static boolean canAccessPrivateMethods() {
282282
*
283283
* @return The class name
284284
*/
285-
public Class getType() {
285+
public Class<?> getType() {
286286
return type;
287287
}
288288

289-
public Constructor getDefaultConstructor() {
289+
public Constructor<?> getDefaultConstructor() {
290290
if (defaultConstructor != null) {
291291
return defaultConstructor;
292292
} else {
@@ -316,8 +316,8 @@ public Invoker getGetInvoker(String propertyName) {
316316
* @param propertyName - the name of the property
317317
* @return The Class of the propery setter
318318
*/
319-
public Class getSetterType(String propertyName) {
320-
Class clazz = setTypes.get(propertyName);
319+
public Class<?> getSetterType(String propertyName) {
320+
Class<?> clazz = setTypes.get(propertyName);
321321
if (clazz == null) {
322322
throw new ReflectionException("There is no setter for property named '" + propertyName + "' in '" + type + "'");
323323
}
@@ -330,8 +330,8 @@ public Class getSetterType(String propertyName) {
330330
* @param propertyName - the name of the property
331331
* @return The Class of the propery getter
332332
*/
333-
public Class getGetterType(String propertyName) {
334-
Class clazz = getTypes.get(propertyName);
333+
public Class<?> getGetterType(String propertyName) {
334+
Class<?> clazz = getTypes.get(propertyName);
335335
if (clazz == null) {
336336
throw new ReflectionException("There is no getter for property named '" + propertyName + "' in '" + type + "'");
337337
}
@@ -386,7 +386,7 @@ public String findPropertyName(String name) {
386386
* @param clazz The class for which to lookup the method cache.
387387
* @return The method cache for the class
388388
*/
389-
public static Reflector forClass(Class clazz) {
389+
public static Reflector forClass(Class<?> clazz) {
390390
if (classCacheEnabled) {
391391
synchronized (clazz) {
392392
Reflector cached = REFLECTOR_MAP.get(clazz);
@@ -408,8 +408,4 @@ public static void setClassCacheEnabled(boolean classCacheEnabled) {
408408
public static boolean isClassCacheEnabled() {
409409
return classCacheEnabled;
410410
}
411-
412411
}
413-
414-
415-

0 commit comments

Comments
 (0)