View Javadoc
1   package org.codehaus.plexus.util;
2   
3   /*
4    * Copyright The Codehaus Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  /**
20   * A thread which is registered with a ThreadRegistry and notifies it when it has completed running. Collects any errors
21   * and makes it available for analysis.
22   * <p>
23   * Created on 1/07/2003
24   * </p>
25   *
26   * @author <a href="mailto:bert@tuaworks.co.nz">Bert van Brakel</a>
27   * @version $Revision$
28   */
29  public abstract class AbstractTestThread
30      implements Runnable
31  {
32      // ~ Instance fields ----------------------------------------------------------------------------
33      private String name;
34  
35      public static final boolean DEBUG = true;
36  
37      private boolean isRunning = false;
38  
39      /** Error msg provided by implementing class (of why the test failed) */
40      private String errorMsg = null;
41  
42      /** The registry to notify on completion */
43      private TestThreadManager registry;
44  
45      /**
46       * The error thrown when running the test. Not necessarily a test failure as some tests may test for an exception
47       */
48      private Throwable error;
49  
50      /** If the thread has been run */
51      private boolean hasRun = false;
52  
53      /**
54       * Flag indicating if the test has passed. Some test might require an exception so using the error to determine if
55       * the test has passed is not sufficient.
56       */
57      private boolean passed = false;
58  
59      // ~ Constructors -------------------------------------------------------------------------------
60  
61      /**
62       * Constructor
63       * <p>
64       * Remember to call <code>setThreadRegistry(ThreadRegistry)</code>
65       */
66      public AbstractTestThread()
67      {
68          super();
69      }
70  
71      public AbstractTestThread( TestThreadManager registry )
72      {
73          super();
74          setThreadRegistry( registry );
75      }
76  
77      // ~ Methods ------------------------------------------------------------------------------------
78  
79      /**
80       * @return
81       */
82      public Throwable getError()
83      {
84          return error;
85      }
86  
87      /**
88       * Resets the test back to it's state before starting. If the test is currently running this method will block until
89       * the test has finished running. Subclasses should call this method if overriding it.
90       */
91      public void reset()
92      {
93          // shouldn't reset until the test has finished running
94          synchronized ( this )
95          {
96              while ( isRunning )
97              {
98                  try
99                  {
100                     wait();
101                 }
102                 catch ( InterruptedException e )
103                 {
104 
105                 }
106             }
107             errorMsg = null;
108             error = null;
109             hasRun = false;
110             passed = false;
111         }
112     }
113 
114     /**
115      * Start this TestThread running. If the test is currently running then this method does nothing.
116      */
117     public final void start()
118     {
119         // shouldn't have multiple threads running this test at the same time
120         synchronized ( this )
121         {
122             if ( isRunning == false )
123             {
124                 isRunning = true;
125                 Thread t = new Thread( this );
126                 t.start();
127             }
128         }
129     }
130 
131     /**
132      * @return
133      */
134     public String getErrorMsg()
135     {
136         return errorMsg;
137     }
138 
139     /**
140      * @return
141      */
142     public boolean hasFailed()
143     {
144         return !passed;
145     }
146 
147     /**
148      * DOCUMENT ME!
149      *
150      * @return DOCUMENT ME!
151      */
152     public boolean hasPassed()
153     {
154         return passed;
155     }
156 
157     /**
158      * Don't override this. Calls <code>doRun()</code>
159      *
160      * @see java.lang.Runnable#run()
161      */
162     public final void run()
163     {
164         if ( registry == null )
165         {
166             throw new IllegalArgumentException( "The ThreadRegistry is null. Ensure this is set before running this thread" );
167         }
168         passed = false;
169         try
170         {
171             doRun();
172         }
173         catch ( Throwable t )
174         {
175             error = t;
176         }
177 
178         registry.completed( this );
179         hasRun = true;
180         isRunning = false;
181         // notify objects with blocked methods which are waiting
182         // on this test to complete running
183         synchronized ( this )
184         {
185             notifyAll();
186         }
187     }
188 
189     /**
190      * Override this to run your custom test
191      *
192      * @throws Throwable
193      */
194     public abstract void doRun()
195         throws Throwable;
196 
197     /**
198      * Set the registry this thread should notify when it has completed running
199      *
200      * @param registry
201      */
202     public void setThreadRegistry( TestThreadManager registry )
203 
204     {
205         this.registry = registry;
206     }
207 
208     /**
209      * Test if the test has run
210      *
211      * @return
212      */
213     public boolean hasRun()
214     {
215         return hasRun;
216     }
217 
218     /**
219      * @param throwable
220      */
221     public void setError( Throwable throwable )
222     {
223         error = throwable;
224     }
225 
226     /**
227      * @param string
228      */
229     public void setErrorMsg( String string )
230     {
231         errorMsg = string;
232     }
233 
234     /**
235      * @param b
236      */
237     public void setPassed( boolean b )
238     {
239         passed = b;
240     }
241 
242     /**
243      * @return
244      */
245     public String getName()
246     {
247         return name;
248     }
249 
250     /**
251      * @param string
252      */
253     public void setName( String string )
254     {
255         name = string;
256     }
257 
258     private final void debug( String msg )
259     {
260         if ( DEBUG )
261         {
262             System.out.println( this + ":" + msg );
263         }
264     }
265 }