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