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