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