1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.service.impl;
17
18 import com.thoughtworks.xstream.XStream;
19 import com.thoughtworks.xstream.converters.MarshallingContext;
20 import com.thoughtworks.xstream.converters.UnmarshallingContext;
21 import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
22 import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
23 import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
24 import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
25 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
26 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
27 import com.thoughtworks.xstream.mapper.Mapper;
28 import org.apache.ojb.broker.core.proxy.ListProxyDefaultImpl;
29 import org.apache.ojb.broker.core.proxy.ProxyHelper;
30 import org.kuali.rice.krad.document.Document;
31 import org.kuali.rice.krad.service.DocumentSerializerService;
32 import org.kuali.rice.krad.service.PersistenceService;
33 import org.kuali.rice.krad.service.SerializerService;
34 import org.kuali.rice.krad.service.XmlObjectSerializerService;
35 import org.kuali.rice.krad.util.documentserializer.AlwaysTruePropertySerializibilityEvaluator;
36 import org.kuali.rice.krad.util.documentserializer.PropertySerializabilityEvaluator;
37 import org.kuali.rice.krad.util.documentserializer.PropertyType;
38 import org.kuali.rice.krad.util.documentserializer.SerializationState;
39
40 import java.lang.reflect.Field;
41 import java.util.ArrayList;
42 import java.util.Iterator;
43 import java.util.List;
44
45
46
47
48
49
50
51
52 public abstract class SerializerServiceBase implements SerializerService {
53
54
55 protected PersistenceService persistenceService;
56 protected XmlObjectSerializerService xmlObjectSerializerService;
57
58 protected XStream xstream;
59 protected ThreadLocal<SerializationState> serializationStates;
60 protected ThreadLocal<PropertySerializabilityEvaluator> evaluators;
61
62 public SerializerServiceBase() {
63 serializationStates = new ThreadLocal<SerializationState>();
64 evaluators = new ThreadLocal<PropertySerializabilityEvaluator>();
65
66 xstream = new XStream(new ProxyAndStateAwareJavaReflectionProvider());
67 xstream.registerConverter(new ProxyConverter(xstream.getMapper(), xstream.getReflectionProvider() ));
68 xstream.addDefaultImplementation(ArrayList.class, ListProxyDefaultImpl.class);
69
70 }
71
72 public class ProxyConverter extends ReflectionConverter {
73 public ProxyConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
74 super(mapper, reflectionProvider);
75 }
76 public boolean canConvert(Class clazz) {
77 return clazz.getName().contains("CGLIB") || clazz.getName().equals("org.apache.ojb.broker.core.proxy.ListProxyDefaultImpl");
78 }
79
80 public void marshal(Object obj, HierarchicalStreamWriter writer, MarshallingContext context) {
81 if (obj instanceof ListProxyDefaultImpl) {
82 List copiedList = new ArrayList();
83 List proxiedList = (List) obj;
84 for (Iterator iter = proxiedList.iterator(); iter.hasNext();) {
85 copiedList.add(iter.next());
86 }
87 context.convertAnother( copiedList );
88 }
89 else {
90 super.marshal(getPersistenceService().resolveProxy(obj), writer, context);
91 }
92 }
93
94 public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
95 return null;
96 }
97 }
98
99 public class ProxyAndStateAwareJavaReflectionProvider extends PureJavaReflectionProvider {
100 @Override
101 public void visitSerializableFields(Object object, Visitor visitor) {
102 SerializationState state = serializationStates.get();
103 PropertySerializabilityEvaluator evaluator = evaluators.get();
104
105 for (Iterator iterator = fieldDictionary.serializableFieldsFor(object.getClass()); iterator.hasNext();) {
106 Field field = (Field) iterator.next();
107 if (!fieldModifiersSupported(field)) {
108 continue;
109 }
110
111 if (ignoreField(field)) {
112 continue;
113 }
114
115 validateFieldAccess(field);
116
117 initializeField(object, field);
118
119 Object value = null;
120 try {
121 value = field.get(object);
122 } catch (IllegalArgumentException e) {
123 throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
124 } catch (IllegalAccessException e) {
125 throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
126 }
127
128 if (evaluator.isPropertySerializable(state, object, field.getName(), value)) {
129 if (value != null && ProxyHelper.isProxy(value)) {
130
131 value = getPersistenceService().resolveProxy(value);
132 }
133 PropertyType propertyType = evaluator.determinePropertyType(value);
134 state.addSerializedProperty(field.getName(), propertyType);
135 visitor.visit(field.getName(), field.getType(), field.getDeclaringClass(), value);
136 state.removeSerializedProperty();
137 }
138 }
139 }
140
141 protected boolean ignoreField(Field field) {
142 return false;
143 }
144
145 protected void initializeField(Object object, Field field) {
146 }
147 }
148
149 public PersistenceService getPersistenceService() {
150 return this.persistenceService;
151 }
152
153 public void setPersistenceService(PersistenceService persistenceService) {
154 this.persistenceService = persistenceService;
155 }
156
157 public XmlObjectSerializerService getXmlObjectSerializerService() {
158 return this.xmlObjectSerializerService;
159 }
160
161 public void setXmlObjectSerializerService(XmlObjectSerializerService xmlObjectSerializerService) {
162 this.xmlObjectSerializerService = xmlObjectSerializerService;
163 }
164
165 protected SerializationState createNewDocumentSerializationState(Document document) {
166 return new SerializationState();
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 }
183