1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.jameleon.util;
20
21 import net.sf.jameleon.Storable;
22
23 import org.apache.log4j.Logger;
24
25 import java.io.File;
26 import java.io.IOException;
27
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.Set;
31 import java.util.Collections;
32
33 /***
34 * A bean that keeps track of a list of <code>Storables</code> and calls the <code>store</code> on each at the appropriate time.
35 * The appropriate times are:
36 * <ol>
37 * <li><b>ON_ERROR_EVENT</b> - When some error occurs.</li>
38 * <li><b>ON_STATE_CHANGE_EVENT</b> - Everytime the object changes state.</li>
39 * <li><b>ON_NO_EVENT</b> - Never store the state.</li>
40 * </ol>
41 * The default event is <b>ON_ERROR_EVENT</b>.
42 * When one of these event occurs, first the <code>storableEvent</code> event is checked to see if the event
43 * is to be recorded. If the event is not to be recorded, then nothing happens. If the event is to be recorded,
44 * then the {@link net.sf.jameleon.Storable#store(java.lang.String,int)} is called for each
45 * {@link net.sf.jameleon.Storable} in the list of registered Storables.
46 */
47 public class StateStorer {
48
49
50 protected static StateStorer stateStorer;
51 /***
52 * When to store the state of the <code>Storables</code>.
53 */
54 protected int storableEvent;
55 /***
56 * A list of storables whose state will be stored at the appropriate time.
57 */
58 protected Set storables;
59 /***
60 * The default event at which to store the state of the object.
61 */
62 public final static String DEFAULT_STORE_DIR = JameleonDefaultValues.RESULTS_DIR;
63 /***
64 * The directory to store the <code>Storables</code>' state to.
65 */
66 protected File storeDir;
67 /***
68 * Only store the state of the object on an unexpected error ( not an assertion error ).
69 */
70 public final static int ON_ERROR_EVENT = 1;
71 /***
72 * Store the state of the object everytime the state itself changes.
73 */
74 public final static int ON_STATE_CHANGE_EVENT = 2;
75 /***
76 * Don't store the state of the object.
77 */
78 public final static int ON_NO_EVENT = 3;
79 /***
80 * Don't store the state of the object.
81 */
82 public final static int ON_COMMAND_EVENT = 4;
83 /***
84 * The default event at which to store the state of the object.
85 */
86 public final static int DEFAULT_EVENT = ON_ERROR_EVENT;
87
88 protected static Logger log = Logger.getLogger(StateStorer.class.getName());
89 protected boolean available = true;
90 /***
91 * Since this is a singleton, a private constructor is in order.
92 * Initializes all values to their defaults.
93 */
94 private StateStorer(){
95 storables = Collections.synchronizedSet(new HashSet());
96 storableEvent = DEFAULT_EVENT;
97 storeDir = new File(DEFAULT_STORE_DIR);
98 }
99
100 public static StateStorer getInstance(){
101 if (stateStorer == null) {
102 stateStorer = new StateStorer();
103 }
104 return stateStorer;
105 }
106
107 public void reset(){
108 getStorables().clear();
109 storableEvent = DEFAULT_EVENT;
110 storeDir = new File(DEFAULT_STORE_DIR);
111 }
112
113 /***
114 * Tests whether the state of a storable is to be stored or not.
115 * @param event - use <code>ON_ERROR</code> for an error or <code>ON_STATE_CHANGE</code> for a simple state change.
116 * @return true if the state
117 */
118 protected boolean isStateStorable(int event){
119 return ( (event == ON_COMMAND_EVENT) || (storableEvent != ON_NO_EVENT && storableEvent >= event) );
120 }
121
122 /***
123 * Records that an <code>event</code> occured. If the event is set as a storable event at runtime,
124 * then thee state of all Storables will be recorded.
125 * @param event - The event type that occured.
126 */
127 public void eventOccured(int event){
128 if (isStateStorable(event)) {
129 storeState(event);
130 }
131 }
132
133 /***
134 * @return the <code>event</code> at which the <code>Storables</code>' state will be stored.
135 */
136 public int getStorableEvent(){
137 return storableEvent;
138 }
139
140 /***
141 * Sets the event at which the state of the storables will be saved.
142 * @param event - the event at which the <code>Storables</code>' state will be stored.
143 * If an invalid <code>event</code> is passed, the <code>storableEvent will not be changed.
144 */
145 public void setStorableEvent(int event){
146 if (ON_ERROR_EVENT == event || ON_STATE_CHANGE_EVENT == event || ON_NO_EVENT == event ) {
147 this.storableEvent = event;
148 }
149 }
150
151 /***
152 * Gets the list of storables to be stored when the appropriate event occurs.
153 * @return The list of storables to be stored when the appropriate event occurs.
154 */
155 public Set getStorables(){
156 return storables;
157 }
158
159 /***
160 * Adds a <code>Storable</code> for which the state will be stored when the appropriate event occurs..
161 * @param s - a <code>Storable</code> object..
162 */
163 public synchronized void addStorable(Storable s){
164 while (!available) {
165 try{
166 wait();
167 } catch (InterruptedException e) { }
168 }
169 available = false;
170 storables.add(s);
171 available = true;
172 notifyAll();
173 }
174
175 /***
176 * Removes a <code>Storable</code> for which the state will be stored when the appropriate event occurs..
177 * @param s - the <code>Storable</code> object to removed from the list of objects
178 */
179 public synchronized void removeStorable(Storable s){
180 while (!available) {
181 try{
182 wait();
183 } catch (InterruptedException e) { }
184 }
185 available = false;
186 storables.remove(s);
187 available = true;
188 notifyAll();
189 }
190
191 protected synchronized void storeState(int event){
192 while (!available) {
193 try{
194 wait();
195 } catch (InterruptedException e) { }
196 }
197 available = false;
198 Iterator it = storables.iterator();
199 while (it.hasNext()) {
200 Storable s = (Storable)it.next();
201 String storeFileS = s.getStoreToFileName(event);
202 if (storeFileS != null) {
203 File storeFile = new File(storeDir, storeFileS);
204 try{
205 s.store(storeFile.getPath(), event);
206 }catch(IOException ioe){
207 log.debug("Unable to write state of storable to file " + JameleonUtility.getStack(ioe));
208 }
209 }
210 }
211 available = true;
212 notifyAll();
213 }
214
215 public File getStoreDir(){
216 return this.storeDir;
217 }
218
219 public void setStoreDir(File dir){
220 this.storeDir = dir;
221 }
222 }