View Javadoc

1   /*$Id: XStreamPickler.java,v 1.8 2004/12/03 14:47:41 jdt 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  
32  import java.io.Reader;
33  import java.io.Writer;
34  import java.lang.ref.SoftReference;
35  import java.util.ArrayList;
36  import java.util.HashMap;
37  import java.util.List;
38  import java.util.Map;
39  
40  import junit.framework.Test;
41  
42  /*** pickler implementation.
43   * @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.
44   * @author Noel Winstanley nw@jb.man.ac.uk 28-Jul-2004
45   *
46   */
47  public class XStreamPickler implements Pickler , ComponentDescriptor{
48      /***
49       * Commons Logger for this class
50       */
51      private static final Log logger = LogFactory.getLog(XStreamPickler.class);
52  
53  
54      /*** made xstream static, for efficiencies sake - don't know how expensive it is to create this object,
55       * but only one instance is ever needed, and is only ever called from the scheduler thread.
56       * 
57       * <p>
58       * but then got concerned about keeping a 3rd part object around indefinately- no idea how big it is, or whether it 
59       * leaks. Decided to use a 'pooling' pattern - resuse each instance a few times, and then create a new one.
60       */
61  
62      private  SoftReference xstream = new SoftReference(createXstream());
63      // number of times this xstream has been used.
64      private int useCount = 0;
65      // limit on number of uses.
66      private static final int USE_LIMIT = 500;
67      /***
68       * @see org.astrogrid.jes.jobscheduler.impl.groovy.GroovyInterpreterFactory.Pickler#marshallInterpreter(java.io.Writer, org.astrogrid.jes.jobscheduler.impl.groovy.GroovyInterpreter)
69       */
70      public void marshallInterpreter(Writer out, GroovyInterpreter interp) {
71          getXstream().toXML(interp,out);
72      }
73  
74      /***
75       * @see org.astrogrid.jes.jobscheduler.impl.groovy.GroovyInterpreterFactory.Pickler#unmarshallInterpreter(java.io.Reader)
76       */
77      public GroovyInterpreter unmarshallInterpreter(Reader in){
78          return (GroovyInterpreter)getXstream().fromXML(in);
79      }
80  
81      /***
82       * @see org.astrogrid.jes.jobscheduler.impl.groovy.GroovyInterpreterFactory.Pickler#unmarshallRuleStore(java.io.Reader)
83       */
84      public Map unmarshallRuleStore(Reader reader)  {
85          List l =  (List )getXstream().fromXML(reader);
86          Map m = new HashMap();
87          for (int i = 0; i < l.size(); i++) {
88              Rule r = (Rule)l.get(i);
89              m.put(r.getName(),r);
90          }
91          return m;
92      }
93  
94      XStream getXstream() {
95          XStream x = (XStream)xstream.get();
96          if (useCount++ > USE_LIMIT || x == null) {
97              logger.info("re-creating xstream");
98              useCount = 0;
99              xstream.clear();
100             x = createXstream();
101             xstream = new SoftReference(x);
102         }
103         return x;
104     }
105     private XStream createXstream() {
106         XStream x = new XStream(new PureJavaReflectionProvider(),new DomDriver());
107         x.registerConverter(new RuleStoreConvertor(x.getClassMapper(),"class"));
108         x.alias("interpreter",GroovyInterpreter.class);
109         x.alias("rules",ArrayList.class);
110         x.alias("rule",Rule.class);
111         x.alias("state",ActivityStatus.class);
112         x.alias("states",ActivityStatusStore.class);
113         x.alias("vars",Vars.class);
114         return x;
115     }
116     
117     /*** subclass of map convertor, for converting rule stores.
118      * and also serialzes the indexScript.
119      * dunno what I'm doing here really - came up with this via reverse-engineering and trial and error.
120      * @author Noel Winstanley nw@jb.man.ac.uk 05-Nov-2004
121      *
122      */
123     protected static class RuleStoreConvertor extends MapConverter {
124 
125         public void marshal(Object o, HierarchicalStreamWriter w, MarshallingContext cxt) {
126             RuleStore rs = (RuleStore)o;
127             w.startNode("indexScript");
128             if (rs.indexScript == null) {
129                 n.marshal(rs.indexScript,w,cxt);
130             } else {
131                 s.marshal(rs.indexScript,w,cxt);
132             }
133             w.endNode();            
134             super.marshal(o, w, cxt);
135         }
136         public Object unmarshal(HierarchicalStreamReader r, UnmarshallingContext cxt) {
137             r.moveDown();            
138             String index = (String)cxt.convertAnother(r.getValue(),String.class);          
139             r.moveUp();
140             RuleStore rs = (RuleStore) super.unmarshal(r, cxt);
141             if (index.trim().length() > 0) {
142                 rs.indexScript = index;
143             }
144             return rs;
145         }
146         public boolean canConvert(Class arg0) {
147             return arg0.equals(RuleStore.class) ;
148         }
149         /*** Construct a new RuleStoreConvertor
150          * @param arg0
151          * @param arg1
152          */
153         public RuleStoreConvertor(ClassMapper arg0, String arg1) {
154             super(arg0, arg1);
155             s = new StringConverter();
156             n = new NullConverter();
157         }
158         private final Converter s;
159         private final Converter n;
160     }
161 
162     /***
163      * @see org.astrogrid.component.descriptor.ComponentDescriptor#getName()
164      */
165     public String getName() {
166         return "XStream Pickler";
167     }
168 
169     /***
170      * @see org.astrogrid.component.descriptor.ComponentDescriptor#getDescription()
171      */
172     public String getDescription() {
173         return "Pickler for interpreter that uses XStream to serialize interpreter state to xml";
174     }
175 
176     /***
177      * @see org.astrogrid.component.descriptor.ComponentDescriptor#getInstallationTest()
178      */
179     public Test getInstallationTest() {
180         return null;
181     }
182 }
183 
184 
185 /* 
186 $Log: XStreamPickler.java,v $
187 Revision 1.8  2004/12/03 14:47:41  jdt
188 Merges from workflow-nww-776
189 
190 Revision 1.7.14.1  2004/12/01 21:48:53  nw
191 organized import
192 
193 Revision 1.7  2004/11/05 16:52:42  jdt
194 Merges from branch nww-itn07-scratchspace
195 
196 Revision 1.6.18.1  2004/11/05 16:03:27  nw
197 optimized: caches xstream in a soft reference.
198 added custom serializer for rule store
199 
200 Revision 1.6  2004/09/16 21:43:47  nw
201 made 3rd-party objects only persist for so many calls. - in case they're space leaking.
202 
203 Revision 1.5  2004/09/06 16:47:04  nw
204 javadoc
205 
206 Revision 1.4  2004/08/09 17:32:02  nw
207 updated due to removing RuleStore
208 
209 Revision 1.3  2004/08/05 07:39:37  nw
210 made xstream static for same reasons
211 
212 Revision 1.2  2004/07/30 15:42:34  nw
213 merged in branch nww-itn06-bz#441 (groovy scripting)
214 
215 Revision 1.1.2.3  2004/07/30 14:00:10  nw
216 first working draft
217 
218 Revision 1.1.2.2  2004/07/28 16:24:23  nw
219 finished groovy beans.
220 moved useful tests from old python package.
221 removed python implemntation
222 
223 Revision 1.1.2.1  2004/07/27 23:37:59  nw
224 refactoed framework.
225 experimented with betwixt - can't get it to work.
226 got XStream working in 5 mins.
227 about to remove betwixt code.
228  
229 */