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.reflection.ObjectAccessException;
21 import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
22 import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
23 import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
24 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
25 import com.thoughtworks.xstream.mapper.Mapper;
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.ojb.broker.core.proxy.ListProxyDefaultImpl;
29 import org.kuali.rice.krad.service.KRADServiceLocator;
30 import org.kuali.rice.krad.service.PersistenceService;
31 import org.kuali.rice.krad.service.XmlObjectSerializerService;
32
33 import java.lang.reflect.Field;
34 import java.util.ArrayList;
35 import java.util.Iterator;
36
37
38
39
40
41
42
43
44 public class XmlObjectSerializerServiceImpl implements XmlObjectSerializerService {
45 private static final Log LOG = LogFactory.getLog(XmlObjectSerializerServiceImpl.class);
46
47 private PersistenceService persistenceService;
48
49 private XStream xstream;
50
51 public XmlObjectSerializerServiceImpl() {
52 xstream = new XStream(new ProxyAwareJavaReflectionProvider());
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 xstream.registerConverter(new ProxyConverter(xstream.getMapper(), xstream.getReflectionProvider() ));
70 xstream.addDefaultImplementation(ArrayList.class, ListProxyDefaultImpl.class);
71 }
72
73
74
75
76 public String toXml(Object object) {
77 if ( LOG.isDebugEnabled() ) {
78 LOG.debug( "toXml(" + object + ") : \n" + xstream.toXML(object) );
79 }
80 return xstream.toXML(object);
81 }
82
83
84
85
86 public Object fromXml(String xml) {
87 if ( LOG.isDebugEnabled() ) {
88 LOG.debug( "fromXml() : \n" + xml );
89 }
90 if ( xml != null ) {
91 xml = xml.replaceAll( "--EnhancerByCGLIB--[0-9a-f]{0,8}", "" );
92 }
93 return xstream.fromXML(xml);
94 }
95
96
97
98
99
100 public class ProxyConverter extends ReflectionConverter {
101 public ProxyConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
102 super(mapper, reflectionProvider);
103 }
104
105 @Override
106
107
108 @SuppressWarnings("unchecked")
109 public boolean canConvert(Class clazz) {
110 return clazz.getName().contains("CGLIB");
111 }
112
113 @Override
114 public void marshal(Object obj, HierarchicalStreamWriter writer, MarshallingContext context) {
115 super.marshal(getPersistenceService().resolveProxy(obj), writer, context);
116 }
117
118
119 }
120
121 public class ProxyAwareJavaReflectionProvider extends PureJavaReflectionProvider {
122
123 public ProxyAwareJavaReflectionProvider() {
124 super();
125 }
126
127
128
129 @Override
130 public void visitSerializableFields(Object object, Visitor visitor) {
131 for (Iterator iterator = fieldDictionary.serializableFieldsFor(object.getClass()); iterator.hasNext();) {
132 Field field = (Field) iterator.next();
133 if (!fieldModifiersSupported(field)) {
134 continue;
135 }
136 validateFieldAccess(field);
137 Object value = null;
138 try {
139 value = field.get(object);
140 if (value != null && getPersistenceService().isProxied(value)) {
141 value = getPersistenceService().resolveProxy(value);
142 }
143 } catch (IllegalArgumentException e) {
144 throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
145 } catch (IllegalAccessException e) {
146 throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
147 }
148 visitor.visit(field.getName(), field.getType(), field.getDeclaringClass(), value);
149 }
150 }
151
152 }
153
154 public PersistenceService getPersistenceService() {
155 if ( persistenceService == null ) {
156 persistenceService = KRADServiceLocator.getPersistenceService();
157 }
158 return persistenceService;
159 }
160
161 }