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 $Id: $Id 28 * @since 3.4.0 29 */ 30 public abstract class AbstractTestThread implements Runnable { 31 // ~ Instance fields ---------------------------------------------------------------------------- 32 private String name; 33 34 /** Constant <code>DEBUG=true</code> */ 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 super(); 68 } 69 70 /** 71 * <p>Constructor for AbstractTestThread.</p> 72 * 73 * @param registry a {@link org.codehaus.plexus.util.TestThreadManager} object. 74 */ 75 public AbstractTestThread(TestThreadManager registry) { 76 super(); 77 setThreadRegistry(registry); 78 } 79 80 // ~ Methods ------------------------------------------------------------------------------------ 81 82 /** 83 * <p>Getter for the field <code>error</code>.</p> 84 * 85 * @return a {@link java.lang.Throwable} object. 86 */ 87 public Throwable getError() { 88 return error; 89 } 90 91 /** 92 * Resets the test back to it's state before starting. If the test is currently running this method will block until 93 * the test has finished running. Subclasses should call this method if overriding it. 94 */ 95 public void reset() { 96 // shouldn't reset until the test has finished running 97 synchronized (this) { 98 while (isRunning) { 99 try { 100 wait(); 101 } catch (InterruptedException e) { 102 103 } 104 } 105 errorMsg = null; 106 error = null; 107 hasRun = false; 108 passed = false; 109 } 110 } 111 112 /** 113 * Start this TestThread running. If the test is currently running then this method does nothing. 114 */ 115 public final void start() { 116 // shouldn't have multiple threads running this test at the same time 117 synchronized (this) { 118 if (isRunning == false) { 119 isRunning = true; 120 Thread t = new Thread(this); 121 t.start(); 122 } 123 } 124 } 125 126 /** 127 * <p>Getter for the field <code>errorMsg</code>.</p> 128 * 129 * @return a {@link java.lang.String} object. 130 */ 131 public String getErrorMsg() { 132 return errorMsg; 133 } 134 135 /** 136 * <p>hasFailed.</p> 137 * 138 * @return a boolean. 139 */ 140 public boolean hasFailed() { 141 return !passed; 142 } 143 144 /** 145 * DOCUMENT ME! 146 * 147 * @return DOCUMENT ME! 148 */ 149 public boolean hasPassed() { 150 return passed; 151 } 152 153 /** 154 * Don't override this. Calls <code>doRun()</code> 155 * 156 * @see java.lang.Runnable#run() 157 */ 158 public final void run() { 159 if (registry == null) { 160 throw new IllegalArgumentException( 161 "The ThreadRegistry is null. Ensure this is set before running this thread"); 162 } 163 passed = false; 164 try { 165 doRun(); 166 } catch (Throwable t) { 167 error = t; 168 } 169 170 registry.completed(this); 171 hasRun = true; 172 isRunning = false; 173 // notify objects with blocked methods which are waiting 174 // on this test to complete running 175 synchronized (this) { 176 notifyAll(); 177 } 178 } 179 180 /** 181 * Override this to run your custom test 182 * 183 * @throws java.lang.Throwable 184 */ 185 public abstract void doRun() throws Throwable; 186 187 /** 188 * Set the registry this thread should notify when it has completed running 189 * 190 * @param registry a {@link org.codehaus.plexus.util.TestThreadManager} object. 191 */ 192 public void setThreadRegistry(TestThreadManager registry) { 193 194 this.registry = registry; 195 } 196 197 /** 198 * Test if the test has run 199 * 200 * @return a boolean. 201 */ 202 public boolean hasRun() { 203 return hasRun; 204 } 205 206 /** 207 * <p>Setter for the field <code>error</code>.</p> 208 * 209 * @param throwable a {@link java.lang.Throwable} object. 210 */ 211 public void setError(Throwable throwable) { 212 error = throwable; 213 } 214 215 /** 216 * <p>Setter for the field <code>errorMsg</code>.</p> 217 * 218 * @param string a {@link java.lang.String} object. 219 */ 220 public void setErrorMsg(String string) { 221 errorMsg = string; 222 } 223 224 /** 225 * <p>Setter for the field <code>passed</code>.</p> 226 * 227 * @param b a boolean. 228 */ 229 public void setPassed(boolean b) { 230 passed = b; 231 } 232 233 /** 234 * <p>Getter for the field <code>name</code>.</p> 235 * 236 * @return a {@link java.lang.String} object. 237 */ 238 public String getName() { 239 return name; 240 } 241 242 /** 243 * <p>Setter for the field <code>name</code>.</p> 244 * 245 * @param string a {@link java.lang.String} object. 246 */ 247 public void setName(String string) { 248 name = string; 249 } 250 251 private final void debug(String msg) { 252 if (DEBUG) { 253 System.out.println(this + ":" + msg); 254 } 255 } 256 }