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  import java.util.Collection;
20  import java.util.Iterator;
21  import java.util.Vector;
22  import java.util.logging.Logger;
23  
24  /**
25   * Manages a number of test threads, which notify this manager when they have completed. Allows TestCases to easily
26   * start and manage multiple test threads.
27   * <p>
28   * Created on 9/06/2003
29   * </p>
30   *
31   * @author <a href="mailto:bert@tuaworks.co.nz">Bert van Brakel</a>
32   * @version $Revision$
33   */
34  public class TestThreadManager
35  {
36      // ~ Instance fields ----------------------------------------------------------------------------
37  
38      /** Test threads which have completed running */
39      private Collection<AbstractTestThread> runThreads = new Vector<AbstractTestThread>();
40  
41      /** Test threads still needing to be run, or are currently running */
42      private Collection<AbstractTestThread> toRunThreads = new Vector<AbstractTestThread>();
43  
44      private Logger logger = null;
45  
46      /** Any test threads which failed */
47      private Vector<AbstractTestThread> failedThreads = new Vector<AbstractTestThread>();
48  
49      /**
50       * The object to notify when all the test threads have completed. Clients use this to lock on (wait) while waiting
51       * for the tests to complete
52       */
53      private Object notify = null;
54  
55      // ~ Constructors -------------------------------------------------------------------------------
56  
57      public TestThreadManager( Object notify )
58      {
59          super();
60          this.notify = notify;
61      }
62  
63      // ~ Methods ------------------------------------------------------------------------------------
64  
65      /**
66       * @return
67       */
68      public Collection<AbstractTestThread> getRunThreads()
69      {
70          return runThreads;
71      }
72  
73      public void runTestThreads()
74      {
75          failedThreads.clear();
76          // use an array as the tests may run very quickly
77          // and modify the toRunThreads vector and hence
78          // cause a Concurrent ModificationException on an
79          // iterator
80          for ( AbstractTestThread toRunThread : toRunThreads )
81          {
82              toRunThread.start();
83          }
84      }
85  
86      public Collection<AbstractTestThread> getFailedTests()
87      {
88          return failedThreads;
89      }
90  
91      /**
92       * Return the object which threads can wait on to be notified when all the test threads have completed running
93       *
94       * @return
95       */
96      public Object getNotifyObject()
97      {
98          return notify;
99      }
100 
101     public boolean hasFailedThreads()
102     {
103         return !failedThreads.isEmpty();
104     }
105 
106     /**
107      * Determine if any threads are still running!
108      *
109      * @return DOCUMENT ME!
110      */
111     public boolean isStillRunningThreads()
112     {
113         return !toRunThreads.isEmpty();
114     }
115 
116     /**
117      * @return
118      */
119     public Collection<AbstractTestThread> getToRunThreads()
120     {
121         return toRunThreads;
122     }
123 
124     /**
125      * DOCUMENT ME!
126      */
127     public void clear()
128     {
129         toRunThreads.clear();
130         runThreads.clear();
131         failedThreads.clear();
132     }
133 
134     /*
135      * (non-Javadoc)
136      * @see java.util.Collection#remove(java.lang.Object)
137      */
138     public synchronized void completed( AbstractTestThread thread )
139     {
140         toRunThreads.remove( thread );
141         runThreads.add( thread );
142         if ( thread.hasFailed() )
143         {
144             failedThreads.add( thread );
145         }
146         // wakeup thread which is waiting for the threads to complete
147         // execution
148         if ( toRunThreads.isEmpty() )
149         {
150             synchronized ( notify )
151             {
152                 notify.notify();
153             }
154         }
155     }
156 
157     /**
158      * Override this to add your own stuff. Called after <code>registerThread(Object)</code>
159      *
160      * @param thread DOCUMENT ME!
161      */
162     public void doRegisterThread( AbstractTestThread thread )
163     {
164     }
165 
166     public final void registerThread( AbstractTestThread thread )
167     {
168         thread.setThreadRegistry( this );
169         if ( toRunThreads.contains( thread ) == false )
170         {
171             toRunThreads.add( thread );
172             doRegisterThread( thread );
173         }
174 
175     }
176 
177     /**
178      * Put all the runThreads back in the que to be run again and clear the failedTest collection
179      */
180     public void reset()
181     {
182         toRunThreads.clear();
183         for ( Object runThread : runThreads )
184         {
185             AbstractTestThread test = (AbstractTestThread) runThread;
186             test.reset();
187             registerThread( test );
188         }
189 
190         runThreads.clear();
191         failedThreads.clear();
192     }
193 }