1
2
3
4
5
6
7
8
9
10
11 package org.astrogrid.jes.jobscheduler.impl.groovy;
12
13 import org.astrogrid.component.descriptor.ComponentDescriptor;
14 import org.astrogrid.jes.jobscheduler.impl.groovy.GroovyInterpreterFactory.Pickler;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18
19 import com.thoughtworks.xstream.XStream;
20 import com.thoughtworks.xstream.alias.ClassMapper;
21 import com.thoughtworks.xstream.converters.Converter;
22 import com.thoughtworks.xstream.converters.MarshallingContext;
23 import com.thoughtworks.xstream.converters.UnmarshallingContext;
24 import com.thoughtworks.xstream.converters.basic.NullConverter;
25 import com.thoughtworks.xstream.converters.basic.StringConverter;
26 import com.thoughtworks.xstream.converters.collections.MapConverter;
27 import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
28 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
29 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
30 import com.thoughtworks.xstream.io.xml.DomDriver;
31 import com.thoughtworks.xstream.io.xml.XppDomDriver;
32
33 import java.io.Reader;
34 import java.io.Writer;
35 import java.lang.ref.SoftReference;
36 import java.util.ArrayList;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40
41 import junit.framework.Test;
42
43 /*** pickler implementation.
44 * @modified made the reference to xstream a soft reference, so it gets collected if needed. We can always create another one - and the extra memory might just get us through.
45 * @author Noel Winstanley nw@jb.man.ac.uk 28-Jul-2004
46 *
47 */
48 public class XStreamPickler implements Pickler , ComponentDescriptor{
49 /***
50 * Commons Logger for this class
51 */
52 private static final Log logger = LogFactory.getLog(XStreamPickler.class);
53
54
55 /*** made xstream static, for efficiencies sake - don't know how expensive it is to create this object,
56 * but only one instance is ever needed, and is only ever called from the scheduler thread.
57 *
58 * <p>
59 * but then got concerned about keeping a 3rd part object around indefinately- no idea how big it is, or whether it
60 * leaks. Decided to use a 'pooling' pattern - resuse each instance a few times, and then create a new one.
61 * <p>
62 * decided to try without this now - it's only a facade object afterall.
63 */
64
65 private final XStream xstream = createXstream();
66
67
68
69
70 /***
71 * @see org.astrogrid.jes.jobscheduler.impl.groovy.GroovyInterpreterFactory.Pickler#marshallInterpreter(java.io.Writer, org.astrogrid.jes.jobscheduler.impl.groovy.GroovyInterpreter)
72 */
73 public void marshallInterpreter(Writer out, GroovyInterpreter interp) {
74 getXstream().toXML(interp,out);
75 }
76
77 /***
78 * @see org.astrogrid.jes.jobscheduler.impl.groovy.GroovyInterpreterFactory.Pickler#unmarshallInterpreter(java.io.Reader)
79 */
80 public GroovyInterpreter unmarshallInterpreter(Reader in){
81 return (GroovyInterpreter)getXstream().fromXML(in);
82 }
83
84 /***
85 * @see org.astrogrid.jes.jobscheduler.impl.groovy.GroovyInterpreterFactory.Pickler#unmarshallRuleStore(java.io.Reader)
86 */
87 public Map unmarshallRuleStore(Reader reader) {
88 List l = (List )getXstream().fromXML(reader);
89 Map m = new HashMap();
90 for (int i = 0; i < l.size(); i++) {
91 Rule r = (Rule)l.get(i);
92 m.put(r.getName(),r);
93 }
94 return m;
95 }
96
97 final XStream getXstream() {
98
99
100
101
102
103
104
105
106
107 return xstream;
108 }
109 private final XStream createXstream() {
110 XStream x = new XStream(new PureJavaReflectionProvider(),new DomDriver());
111 x.registerConverter(new RuleStoreConvertor(x.getClassMapper(),"class"));
112 x.alias("interpreter",GroovyInterpreter.class);
113 x.alias("rules",ArrayList.class);
114 x.alias("rule",Rule.class);
115 x.alias("state",ActivityStatus.class);
116 x.alias("states",ActivityStatusStore.class);
117 x.alias("vars",Vars.class);
118 return x;
119 }
120
121 /*** subclass of map convertor, for converting rule stores.
122 * and also serialzes the indexScript.
123 * dunno what I'm doing here really - came up with this via reverse-engineering and trial and error.
124 * @author Noel Winstanley nw@jb.man.ac.uk 05-Nov-2004
125 *
126 */
127 protected static class RuleStoreConvertor extends MapConverter {
128
129 public void marshal(Object o, HierarchicalStreamWriter w, MarshallingContext cxt) {
130 RuleStore rs = (RuleStore)o;
131 w.startNode("indexScript");
132 if (rs.indexScript == null) {
133 n.marshal(rs.indexScript,w,cxt);
134 } else {
135 s.marshal(rs.indexScript,w,cxt);
136 }
137 w.endNode();
138 super.marshal(o, w, cxt);
139 }
140 public Object unmarshal(HierarchicalStreamReader r, UnmarshallingContext cxt) {
141 r.moveDown();
142 String index = (String)cxt.convertAnother(r.getValue(),String.class);
143 r.moveUp();
144 RuleStore rs = (RuleStore) super.unmarshal(r, cxt);
145 if (index.trim().length() > 0) {
146 rs.indexScript = index;
147 }
148 return rs;
149 }
150 public boolean canConvert(Class arg0) {
151 return arg0.equals(RuleStore.class) ;
152 }
153 /*** Construct a new RuleStoreConvertor
154 * @param arg0
155 * @param arg1
156 */
157 public RuleStoreConvertor(ClassMapper arg0, String arg1) {
158 super(arg0, arg1);
159 s = new StringConverter();
160 n = new NullConverter();
161 }
162 private final Converter s;
163 private final Converter n;
164 }
165
166 /***
167 * @see org.astrogrid.component.descriptor.ComponentDescriptor#getName()
168 */
169 public String getName() {
170 return "XStream Pickler";
171 }
172
173 /***
174 * @see org.astrogrid.component.descriptor.ComponentDescriptor#getDescription()
175 */
176 public String getDescription() {
177 return "Pickler for interpreter that uses XStream to serialize interpreter state to xml";
178 }
179
180 /***
181 * @see org.astrogrid.component.descriptor.ComponentDescriptor#getInstallationTest()
182 */
183 public Test getInstallationTest() {
184 return null;
185 }
186 }
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243