1 /*************************************************
2 * Copyright (c) Shen Li. All rights reserved. *
3 * http://joyaop.sourceforge.net *
4 * -------------------------------------------- *
5 * Distributable under LGPL license. *
6 * See terms of license at gnu.org. *
7 ************************************************/
8 package net.sf.joyaop.impl;
9
10 import net.sf.cglib.proxy.Callback;
11 import net.sf.cglib.proxy.CallbackFilter;
12 import net.sf.cglib.proxy.Enhancer;
13 import net.sf.cglib.proxy.Factory;
14 import net.sf.joyaop.AspectRuntimeException;
15 import net.sf.joyaop.util.ClassUtils;
16
17 import java.io.IOException;
18 import java.io.ObjectInputStream;
19 import java.io.ObjectOutputStream;
20 import java.io.Serializable;
21 import java.lang.reflect.Field;
22 import java.lang.reflect.Modifier;
23 import java.util.ArrayList;
24 import java.util.Iterator;
25 import java.util.List;
26
27 /***
28 * @author Shen Li
29 */
30 public class SerializableProxy implements Serializable {
31 private static final long serialVersionUID = 0;
32 private Object proxy;
33 private Class[] interfaceClasses;
34 private CallbackFilter callbackFilter;
35
36 public SerializableProxy(Object proxy, Class[] interfaceClasses, CallbackFilter callbackFilter) {
37 this.proxy = proxy;
38 this.interfaceClasses = interfaceClasses;
39 this.callbackFilter = callbackFilter;
40 }
41
42 public Object readResolve() {
43 return proxy;
44 }
45
46 private void writeObject(ObjectOutputStream out) throws IOException {
47 out.writeObject(((Factory) proxy).getCallbacks());
48 out.writeObject(proxy.getClass().getSuperclass());
49 out.writeObject(getSuperClassFields());
50 out.writeObject(interfaceClasses);
51 out.writeObject(callbackFilter);
52 }
53
54 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
55 Callback[] callbacks = (Callback[]) in.readObject();
56 Class superClass = (Class) in.readObject();
57 List fieldValues = (List) in.readObject();
58 Factory factory = ClassUtils.getProxyFactory(superClass);
59 if (factory == null) {
60 Class[] interfaceClasses = (Class[]) in.readObject();
61 CallbackFilter callbackFilter = (CallbackFilter) in.readObject();
62 Enhancer enhancer = new Enhancer();
63 enhancer.setSuperclass(superClass);
64 enhancer.setInterfaces(interfaceClasses);
65 enhancer.setCallbacks(callbacks);
66 enhancer.setCallbackFilter(callbackFilter);
67 enhancer.setClassLoader(ClassUtils.getClassLoader());
68 proxy = enhancer.create();
69 ClassUtils.putProxyFactory(superClass, (Factory) proxy);
70 }
71 proxy = factory.newInstance(callbacks);
72 setSuperClassFields(fieldValues);
73 }
74
75 private List getSuperClassFields() {
76 final List fields = new ArrayList();
77 visitSuperClassFields(new FieldVisitor() {
78 public void visit(Field field) {
79 try {
80 fields.add(field.get(proxy));
81 } catch (IllegalAccessException e) {
82 throw new AspectRuntimeException(e);
83 }
84 }
85 });
86 return fields;
87 }
88
89 private void setSuperClassFields(List fields) {
90 final Iterator i = fields.iterator();
91 visitSuperClassFields(new FieldVisitor() {
92 public void visit(Field field) {
93 try {
94 field.set(proxy, (Object) i.next());
95 } catch (IllegalAccessException e) {
96 throw new AspectRuntimeException(e);
97 }
98 }
99 });
100 }
101
102 private void visitSuperClassFields(FieldVisitor visitor) {
103 Class clazz = proxy.getClass().getSuperclass();
104 while (!clazz.equals(Object.class)) {
105 Field[] fields = clazz.getDeclaredFields();
106 for (int i = 0; i < fields.length; i++) {
107 fields[i].setAccessible(true);
108 int modifiers = fields[i].getModifiers();
109 if (!Modifier.isFinal(modifiers) && !Modifier.isStatic(modifiers)) {
110 visitor.visit(fields[i]);
111 }
112 }
113 clazz = clazz.getSuperclass();
114 }
115 }
116
117 private static interface FieldVisitor {
118 void visit(Field field);
119 }
120 }