TestThreadManager.java

package org.codehaus.plexus.util;

/*
 * Copyright The Codehaus Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.Collection;
import java.util.Vector;

/**
 * Manages a number of test threads, which notify this manager when they have completed. Allows TestCases to easily
 * start and manage multiple test threads.
 * <p>
 * Created on 9/06/2003
 * </p>
 *
 * @author <a href="mailto:bert@tuaworks.co.nz">Bert van Brakel</a>
 * @since 3.4.0
 */
public class TestThreadManager {

    /** Test threads which have completed running */
    private Collection<AbstractTestThread> runThreads = new Vector<AbstractTestThread>();

    /** Test threads still needing to be run, or are currently running */
    private Collection<AbstractTestThread> toRunThreads = new Vector<AbstractTestThread>();

    /** Any test threads which failed */
    private Vector<AbstractTestThread> failedThreads = new Vector<AbstractTestThread>();

    /**
     * The object to notify when all the test threads have completed. Clients use this to lock on (wait) while waiting
     * for the tests to complete
     */
    private Object notify = null;

    public TestThreadManager(Object notify) {
        super();
        this.notify = notify;
    }

    public Collection<AbstractTestThread> getRunThreads() {
        return runThreads;
    }

    public void runTestThreads() {
        failedThreads.clear();
        // use an array as the tests may run very quickly
        // and modify the toRunThreads vector and hence
        // cause a Concurrent ModificationException on an
        // iterator
        for (AbstractTestThread toRunThread : toRunThreads) {
            toRunThread.start();
        }
    }

    public Collection<AbstractTestThread> getFailedTests() {
        return failedThreads;
    }

    /**
     * Return the object which threads can wait on to be notified when all the test threads have completed running
     *
     * @return a {@link java.lang.Object} object.
     */
    public Object getNotifyObject() {
        return notify;
    }

    public boolean hasFailedThreads() {
        return !failedThreads.isEmpty();
    }

    public boolean isStillRunningThreads() {
        return !toRunThreads.isEmpty();
    }

    public Collection<AbstractTestThread> getToRunThreads() {
        return toRunThreads;
    }

    public void clear() {
        toRunThreads.clear();
        runThreads.clear();
        failedThreads.clear();
    }

    public synchronized void completed(AbstractTestThread thread) {
        toRunThreads.remove(thread);
        runThreads.add(thread);
        if (thread.hasFailed()) {
            failedThreads.add(thread);
        }
        // wakeup thread which is waiting for the threads to complete
        // execution
        if (toRunThreads.isEmpty()) {
            synchronized (notify) {
                notify.notify();
            }
        }
    }

    /**
     * Override this to add your own stuff. Called after <code>registerThread(Object)</code>
     *
     * @param thread DOCUMENT ME!
     */
    public void doRegisterThread(AbstractTestThread thread) {}

    public final void registerThread(AbstractTestThread thread) {
        thread.setThreadRegistry(this);
        if (toRunThreads.contains(thread) == false) {
            toRunThreads.add(thread);
            doRegisterThread(thread);
        }
    }

    /**
     * Put all the runThreads back in the que to be run again and clear the failedTest collection
     */
    public void reset() {
        toRunThreads.clear();
        for (AbstractTestThread runThread : runThreads) {
            runThread.reset();
            registerThread(runThread);
        }

        runThreads.clear();
        failedThreads.clear();
    }
}