View Javadoc

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 }