View Javadoc

1   /*$Id: XStreamPickler.java,v 1.9 2005/04/25 12:13:54 clq2 Exp $
2    * Created on 28-Jul-2004
3    *
4    * Copyright (C) AstroGrid. All rights reserved.
5    *
6    * This software is published under the terms of the AstroGrid 
7    * Software License version 1.2, a copy of which has been included 
8    * with this distribution in the LICENSE.txt file.  
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      // number of times this xstream has been used.
67      //private int useCount = 0;
68      // limit on number of uses.
69      //private static final int USE_LIMIT = 500;
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          /*XStream x = (XStream)xstream.get();
99          if (useCount++ > USE_LIMIT || x == null) {
100             logger.info("re-creating xstream");
101             useCount = 0;
102             xstream.clear();
103             x = createXstream();
104             xstream = new SoftReference(x);
105         }
106         return x;*/
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 $Log: XStreamPickler.java,v $
191 Revision 1.9  2005/04/25 12:13:54  clq2
192 jes-nww-776-again
193 
194 Revision 1.8.42.2  2005/04/12 17:08:15  nw
195 caching to improve performance
196 
197 Revision 1.8.42.1  2005/04/11 16:31:14  nw
198 updated version of xstream.
199 added caching to job factory
200 
201 Revision 1.8  2004/12/03 14:47:41  jdt
202 Merges from workflow-nww-776
203 
204 Revision 1.7.14.1  2004/12/01 21:48:53  nw
205 organized import
206 
207 Revision 1.7  2004/11/05 16:52:42  jdt
208 Merges from branch nww-itn07-scratchspace
209 
210 Revision 1.6.18.1  2004/11/05 16:03:27  nw
211 optimized: caches xstream in a soft reference.
212 added custom serializer for rule store
213 
214 Revision 1.6  2004/09/16 21:43:47  nw
215 made 3rd-party objects only persist for so many calls. - in case they're space leaking.
216 
217 Revision 1.5  2004/09/06 16:47:04  nw
218 javadoc
219 
220 Revision 1.4  2004/08/09 17:32:02  nw
221 updated due to removing RuleStore
222 
223 Revision 1.3  2004/08/05 07:39:37  nw
224 made xstream static for same reasons
225 
226 Revision 1.2  2004/07/30 15:42:34  nw
227 merged in branch nww-itn06-bz#441 (groovy scripting)
228 
229 Revision 1.1.2.3  2004/07/30 14:00:10  nw
230 first working draft
231 
232 Revision 1.1.2.2  2004/07/28 16:24:23  nw
233 finished groovy beans.
234 moved useful tests from old python package.
235 removed python implemntation
236 
237 Revision 1.1.2.1  2004/07/27 23:37:59  nw
238 refactoed framework.
239 experimented with betwixt - can't get it to work.
240 got XStream working in 5 mins.
241 about to remove betwixt code.
242  
243 */