1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package edu.internet2.middleware.grouperClientExt.com.thoughtworks.xstream.converters.reflection;
28
29 import java.io.ObjectInputStream;
30 import java.io.ObjectOutputStream;
31 import java.lang.reflect.InvocationTargetException;
32 import java.lang.reflect.Method;
33 import java.util.Collections;
34 import java.util.HashMap;
35 import java.util.Map;
36
37 import edu.internet2.middleware.grouperClientExt.com.thoughtworks.xstream.converters.ConversionException;
38
39
40
41
42
43
44 public class SerializationMethodInvoker {
45
46 private Map cache = Collections.synchronizedMap(new HashMap());
47 private static final Object NO_METHOD = new Object();
48 private static final Object[] EMPTY_ARGS = new Object[0];
49
50
51
52
53 public Object callReadResolve(Object result) {
54 if (result == null) {
55 return null;
56 } else {
57 Method readResolveMethod = getMethod(result.getClass(), "readResolve", null, true);
58 if (readResolveMethod != null) {
59 try {
60 return readResolveMethod.invoke(result, EMPTY_ARGS);
61 } catch (IllegalAccessException e) {
62 throw new ObjectAccessException("Could not call " + result.getClass().getName() + ".readResolve()", e);
63 } catch (InvocationTargetException e) {
64 throw new ObjectAccessException("Could not call " + result.getClass().getName() + ".readResolve()", e.getTargetException());
65 }
66 } else {
67 return result;
68 }
69 }
70 }
71
72 public Object callWriteReplace(Object object) {
73 if (object == null) {
74 return null;
75 } else {
76 Method writeReplaceMethod = getMethod(object.getClass(), "writeReplace", null, true);
77 if (writeReplaceMethod != null) {
78 try {
79 Object[] EMPTY_ARGS = new Object[0];
80 return writeReplaceMethod.invoke(object, EMPTY_ARGS);
81 } catch (IllegalAccessException e) {
82 throw new ObjectAccessException("Could not call " + object.getClass().getName() + ".writeReplace()", e);
83 } catch (InvocationTargetException e) {
84 throw new ObjectAccessException("Could not call " + object.getClass().getName() + ".writeReplace()", e.getTargetException());
85 }
86 } else {
87 return object;
88 }
89 }
90 }
91
92 public boolean supportsReadObject(Class type, boolean includeBaseClasses) {
93 return getMethod(type, "readObject", new Class[]{ObjectInputStream.class}, includeBaseClasses) != null;
94 }
95
96 public void callReadObject(Class type, Object object, ObjectInputStream stream) {
97 try {
98 Method readObjectMethod = getMethod(type, "readObject", new Class[]{ObjectInputStream.class}, false);
99 readObjectMethod.invoke(object, new Object[]{stream});
100 } catch (IllegalAccessException e) {
101 throw new ConversionException("Could not call " + object.getClass().getName() + ".readObject()", e);
102 } catch (InvocationTargetException e) {
103 throw new ConversionException("Could not call " + object.getClass().getName() + ".readObject()", e.getTargetException());
104 }
105 }
106
107 public boolean supportsWriteObject(Class type, boolean includeBaseClasses) {
108 return getMethod(type, "writeObject", new Class[]{ObjectOutputStream.class}, includeBaseClasses) != null;
109 }
110
111 public void callWriteObject(Class type, Object instance, ObjectOutputStream stream) {
112 try {
113 Method readObjectMethod = getMethod(type, "writeObject", new Class[]{ObjectOutputStream.class}, false);
114 readObjectMethod.invoke(instance, new Object[]{stream});
115 } catch (IllegalAccessException e) {
116 throw new ConversionException("Could not call " + instance.getClass().getName() + ".writeObject()", e);
117 } catch (InvocationTargetException e) {
118 throw new ConversionException("Could not call " + instance.getClass().getName() + ".writeObject()", e.getTargetException());
119 }
120 }
121
122 private Method getMethod(Class type, String name, Class[] parameterTypes, boolean includeBaseclasses) {
123 Object key = type.getName() + "." + name + "." + includeBaseclasses;
124 if (cache.containsKey(key)) {
125 Object result = cache.get(key);
126 return (Method) (result == NO_METHOD ? null : result);
127 }
128 if (includeBaseclasses) {
129 while (type != null) {
130 try {
131 Method result = type.getDeclaredMethod(name, parameterTypes);
132 result.setAccessible(true);
133 cache.put(key, result);
134 return result;
135 } catch (NoSuchMethodException e) {
136 type = type.getSuperclass();
137 }
138 }
139 cache.put(key, NO_METHOD);
140 return null;
141 } else {
142 try {
143 Method result = type.getDeclaredMethod(name, parameterTypes);
144 result.setAccessible(true);
145 cache.put(key, result);
146 return result;
147 } catch (NoSuchMethodException e) {
148 cache.put(key, NO_METHOD);
149 return null;
150 }
151 }
152 }
153
154 }