carbidecpp22devenv/plugins/org.eclipse.test.source_3.5.0.r20080925/src/org.junit4_4.5.0.v20090423/junitsrc/org/junit/runners/model/RunnerBuilder.java
changeset 636 3ef299ba838f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/carbidecpp22devenv/plugins/org.eclipse.test.source_3.5.0.r20080925/src/org.junit4_4.5.0.v20090423/junitsrc/org/junit/runners/model/RunnerBuilder.java	Fri Dec 04 11:49:54 2009 -0600
@@ -0,0 +1,99 @@
+package org.junit.runners.model;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.internal.runners.ErrorReportingRunner;
+import org.junit.runner.Runner;
+
+/**
+ * A RunnerBuilder is a strategy for constructing runners for classes. 
+ * 
+ * Only writers of custom runners should use <code>RunnerBuilder</code>s.  A custom runner class with a constructor taking
+ * a <code>RunnerBuilder</code> parameter will be passed the instance of <code>RunnerBuilder</code> used to build that runner itself.  
+ * For example,
+ * imagine a custom runner that builds suites based on a list of classes in a text file:
+ * 
+ * <pre>
+ * \@RunWith(TextFileSuite.class)
+ * \@SuiteSpecFile("mysuite.txt")
+ * class MySuite {}
+ * </pre>
+ * 
+ * The implementation of TextFileSuite might include:
+ * 
+ * <pre>
+ * public TextFileSuite(Class testClass, RunnerBuilder builder) {
+ *   // ...
+ *   for (String className : readClassNames())
+ *     addRunner(builder.runnerForClass(Class.forName(className)));
+ *   // ...
+ * }
+ * </pre>
+ * 
+ * @see org.junit.runners.Suite
+ */
+public abstract class RunnerBuilder {
+	private final Set<Class<?>> parents= new HashSet<Class<?>>();
+
+	/**
+	 * Override to calculate the correct runner for a test class at runtime.
+	 * 
+	 * @param testClass class to be run
+	 * @return a Runner
+	 * @throws Throwable if a runner cannot be constructed
+	 */
+	public abstract Runner runnerForClass(Class<?> testClass) throws Throwable;
+
+	/**
+	 * Always returns a runner, even if it is just one that prints an error instead of running tests.
+	 * @param testClass class to be run
+	 * @return a Runner
+	 */
+	public Runner safeRunnerForClass(Class<?> testClass) {
+		try {
+			return runnerForClass(testClass);
+		} catch (Throwable e) {
+			return new ErrorReportingRunner(testClass, e);
+		}
+	}
+
+	Class<?> addParent(Class<?> parent) throws InitializationError {
+		if (!parents.add(parent))
+			throw new InitializationError(String.format("class '%s' (possibly indirectly) contains itself as a SuiteClass", parent.getName()));
+		return parent;
+	}
+
+	void removeParent(Class<?> klass) {
+		parents.remove(klass);
+	}
+
+	/**
+	 * Constructs and returns a list of Runners, one for each child class in
+	 * {@code children}.  Care is taken to avoid infinite recursion:
+	 * this builder will throw an exception if it is requested for another
+	 * runner for {@code parent} before this call completes.
+	 */
+	public List<Runner> runners(Class<?> parent, Class<?>[] children)
+			throws InitializationError {
+		addParent(parent);
+
+		try {
+			return runners(children);
+		} finally {
+			removeParent(parent);
+		}
+	}
+	
+	private List<Runner> runners(Class<?>[] children) {
+		ArrayList<Runner> runners= new ArrayList<Runner>();
+		for (Class<?> each : children) {
+			Runner childRunner= safeRunnerForClass(each);
+			if (childRunner != null)
+				runners.add(childRunner);
+		}
+		return runners;
+	}
+}