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