View Javadoc

1   /*
2       Jameleon - An automation testing tool..
3       Copyright (C) 2003 Christian W. Hargraves (engrean@hotmail.com)
4       
5       This library is free software; you can redistribute it and/or
6       modify it under the terms of the GNU Lesser General Public
7       License as published by the Free Software Foundation; either
8       version 2.1 of the License, or (at your option) any later version.
9   
10      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13      Lesser General Public License for more details.
14  
15      You should have received a copy of the GNU Lesser General Public
16      License along with this library; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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 }