Coverage Report - org.jbehave.core.embedder.Embedder
 
Classes in this File Line Coverage Branch Coverage Complexity
Embedder
83%
213/254
80%
68/84
2.147
Embedder$AnnotatedEmbedderRunFailed
100%
2/2
N/A
2.147
Embedder$EnqueuedStory
92%
23/25
100%
4/4
2.147
Embedder$NonThreadingExecutorService
26%
5/19
N/A
2.147
Embedder$NonThreadingExecutorService$1
50%
3/6
N/A
2.147
Embedder$RunningEmbeddablesFailed
100%
4/4
N/A
2.147
Embedder$RunningStoriesFailed
75%
6/8
N/A
2.147
Embedder$ThrowableStory
83%
5/6
N/A
2.147
Embedder$ViewGenerationFailed
50%
2/4
N/A
2.147
 
 1  
 package org.jbehave.core.embedder;
 2  
 
 3  
 import java.io.File;
 4  
 import java.util.ArrayList;
 5  
 import java.util.Arrays;
 6  
 import java.util.Collection;
 7  
 import java.util.List;
 8  
 import java.util.Properties;
 9  
 import java.util.concurrent.Callable;
 10  
 import java.util.concurrent.CancellationException;
 11  
 import java.util.concurrent.ExecutionException;
 12  
 import java.util.concurrent.ExecutorService;
 13  
 import java.util.concurrent.Executors;
 14  
 import java.util.concurrent.Future;
 15  
 import java.util.concurrent.ThreadPoolExecutor;
 16  
 import java.util.concurrent.TimeUnit;
 17  
 import java.util.concurrent.TimeoutException;
 18  
 
 19  
 import org.apache.commons.lang.StringUtils;
 20  
 import org.apache.commons.lang.builder.ToStringBuilder;
 21  
 import org.apache.commons.lang.builder.ToStringStyle;
 22  
 import org.jbehave.core.ConfigurableEmbedder;
 23  
 import org.jbehave.core.Embeddable;
 24  
 import org.jbehave.core.configuration.Configuration;
 25  
 import org.jbehave.core.configuration.MostUsefulConfiguration;
 26  
 import org.jbehave.core.embedder.StoryRunner.State;
 27  
 import org.jbehave.core.failures.BatchFailures;
 28  
 import org.jbehave.core.junit.AnnotatedEmbedderRunner;
 29  
 import org.jbehave.core.junit.AnnotatedEmbedderUtils;
 30  
 import org.jbehave.core.model.Story;
 31  
 import org.jbehave.core.model.StoryMaps;
 32  
 import org.jbehave.core.reporters.ReportsCount;
 33  
 import org.jbehave.core.reporters.StepdocReporter;
 34  
 import org.jbehave.core.reporters.StoryReporterBuilder;
 35  
 import org.jbehave.core.reporters.ViewGenerator;
 36  
 import org.jbehave.core.steps.CandidateSteps;
 37  
 import org.jbehave.core.steps.InjectableStepsFactory;
 38  
 import org.jbehave.core.steps.ProvidedStepsFactory;
 39  
 import org.jbehave.core.steps.StepCollector.Stage;
 40  
 import org.jbehave.core.steps.StepFinder;
 41  
 import org.jbehave.core.steps.Stepdoc;
 42  
 
 43  
 /**
 44  
  * Represents an entry point to all of JBehave's functionality that is
 45  
  * embeddable into other launchers, such as IDEs or CLIs.
 46  
  */
 47  
 public class Embedder {
 48  
 
 49  81
     private Configuration configuration = new MostUsefulConfiguration();
 50  81
     private List<CandidateSteps> candidateSteps = new ArrayList<CandidateSteps>();
 51  
     private InjectableStepsFactory stepsFactory;
 52  81
     private EmbedderClassLoader classLoader = new EmbedderClassLoader(this.getClass().getClassLoader());
 53  81
     private EmbedderControls embedderControls = new EmbedderControls();
 54  81
     private List<String> metaFilters = Arrays.asList();
 55  81
     private Properties systemProperties = new Properties();
 56  
     private StoryMapper storyMapper;
 57  
     private StoryRunner storyRunner;
 58  
     private EmbedderMonitor embedderMonitor;
 59  
     private ExecutorService executorService;
 60  
 
 61  
     public Embedder() {
 62  53
         this(new StoryMapper(), new StoryRunner(), new PrintStreamEmbedderMonitor());
 63  53
     }
 64  
 
 65  81
     public Embedder(StoryMapper storyMapper, StoryRunner storyRunner, EmbedderMonitor embedderMonitor) {
 66  81
         this.storyMapper = storyMapper;
 67  81
         this.storyRunner = storyRunner;
 68  81
         this.embedderMonitor = embedderMonitor;
 69  81
     }
 70  
 
 71  
     public void mapStoriesAsPaths(List<String> storyPaths) {
 72  1
         EmbedderControls embedderControls = embedderControls();
 73  1
         if (embedderControls.skip()) {
 74  0
             embedderMonitor.storiesSkipped(storyPaths);
 75  0
             return;
 76  
         }
 77  
 
 78  1
         processSystemProperties();
 79  
 
 80  1
         for (String storyPath : storyPaths) {
 81  2
             Story story = storyRunner.storyOfPath(configuration, storyPath);
 82  2
             embedderMonitor.mappingStory(storyPath, metaFilters);
 83  2
             storyMapper.map(story, new MetaFilter(""));
 84  2
             for (String filter : metaFilters) {
 85  0
                 storyMapper.map(story, new MetaFilter(filter));
 86  
             }
 87  2
         }
 88  
 
 89  1
         generateMapsView(storyMapper.getStoryMaps());
 90  
 
 91  1
     }
 92  
 
 93  
     private void generateMapsView(StoryMaps storyMaps) {
 94  1
         Configuration configuration = configuration();
 95  1
         StoryReporterBuilder builder = configuration.storyReporterBuilder();
 96  1
         File outputDirectory = builder.outputDirectory();
 97  1
         Properties viewResources = builder.viewResources();
 98  1
         ViewGenerator viewGenerator = configuration.viewGenerator();
 99  
         try {
 100  1
             embedderMonitor.generatingMapsView(outputDirectory, storyMaps, viewResources);
 101  1
             viewGenerator.generateMapsView(outputDirectory, storyMaps, viewResources);
 102  0
         } catch (RuntimeException e) {
 103  0
             embedderMonitor.mapsViewGenerationFailed(outputDirectory, storyMaps, viewResources, e);
 104  0
             throw new ViewGenerationFailed(outputDirectory, storyMaps, viewResources, e);
 105  1
         }
 106  1
     }
 107  
 
 108  
     public void runAsEmbeddables(List<String> classNames) {
 109  10
         EmbedderControls embedderControls = embedderControls();
 110  10
         if (embedderControls.skip()) {
 111  1
             embedderMonitor.embeddablesSkipped(classNames);
 112  1
             return;
 113  
         }
 114  
 
 115  9
         BatchFailures batchFailures = new BatchFailures();
 116  9
         for (Embeddable embeddable : embeddables(classNames, classLoader())) {
 117  15
             String name = embeddable.getClass().getName();
 118  
             try {
 119  15
                 embedderMonitor.runningEmbeddable(name);
 120  15
                 embeddable.useEmbedder(this);
 121  15
                 embeddable.run();
 122  4
             } catch (Throwable e) {
 123  4
                 if (embedderControls.batch()) {
 124  
                     // collect and postpone decision to throw exception
 125  2
                     batchFailures.put(name, e);
 126  
                 } else {
 127  2
                     if (embedderControls.ignoreFailureInStories()) {
 128  1
                         embedderMonitor.embeddableFailed(name, e);
 129  
                     } else {
 130  1
                         throw new RunningEmbeddablesFailed(name, e);
 131  
                     }
 132  
                 }
 133  11
             }
 134  14
         }
 135  
 
 136  8
         if (embedderControls.batch() && batchFailures.size() > 0) {
 137  2
             if (embedderControls.ignoreFailureInStories()) {
 138  1
                 embedderMonitor.batchFailed(batchFailures);
 139  
             } else {
 140  1
                 throw new RunningEmbeddablesFailed(batchFailures);
 141  
             }
 142  
         }
 143  
 
 144  7
     }
 145  
 
 146  
     private List<Embeddable> embeddables(List<String> classNames, EmbedderClassLoader classLoader) {
 147  9
         List<Embeddable> embeddables = new ArrayList<Embeddable>();
 148  9
         for (String className : classNames) {
 149  17
             if (!classLoader.isAbstract(className)) {
 150  16
                 embeddables.add(classLoader.newInstance(Embeddable.class, className));
 151  
             }
 152  
         }
 153  9
         return embeddables;
 154  
     }
 155  
 
 156  
     public void runStoriesWithAnnotatedEmbedderRunner(List<String> classNames) {
 157  4
         EmbedderClassLoader classLoader = classLoader();
 158  4
         for (String className :  classNames) {
 159  4
             embedderMonitor.runningWithAnnotatedEmbedderRunner(className);
 160  4
             AnnotatedEmbedderRunner runner = AnnotatedEmbedderUtils.annotatedEmbedderRunner(className, classLoader);
 161  
             try {
 162  3
                 Object annotatedInstance = runner.createTest();
 163  3
                 if (annotatedInstance instanceof Embeddable) {
 164  2
                     ((Embeddable) annotatedInstance).run();
 165  
                 } else {
 166  1
                     embedderMonitor.annotatedInstanceNotOfType(annotatedInstance, Embeddable.class);
 167  
                 }
 168  1
             } catch (Throwable e) {
 169  1
                 throw new AnnotatedEmbedderRunFailed(runner, e);
 170  2
             }
 171  2
         }
 172  2
     }
 173  
     
 174  
     public void runStoriesAsPaths(List<String> storyPaths) {
 175  
 
 176  19
         processSystemProperties();
 177  
 
 178  19
         final EmbedderControls embedderControls = embedderControls();
 179  19
         if (embedderControls.skip()) {
 180  1
             embedderMonitor.storiesSkipped(storyPaths);
 181  1
             return;
 182  
         }
 183  
 
 184  18
         Configuration configuration = configuration();        
 185  18
         InjectableStepsFactory stepsFactory = stepsFactory();
 186  18
         List<CandidateSteps> candidateSteps = stepsFactory.createCandidateSteps();
 187  
         
 188  18
         State beforeStories = storyRunner.runBeforeOrAfterStories(configuration, candidateSteps, Stage.BEFORE);
 189  
 
 190  18
         BatchFailures batchFailures = new BatchFailures();
 191  18
         configureReporterBuilder(configuration);
 192  18
         MetaFilter filter = new MetaFilter(StringUtils.join(metaFilters, " "), embedderMonitor);
 193  
 
 194  18
         List<Future<ThrowableStory>> futures = new ArrayList<Future<ThrowableStory>>();
 195  
 
 196  18
         for (String storyPath : storyPaths) {
 197  26
             enqueueStory(batchFailures, filter, futures, storyPath, storyRunner.storyOfPath(configuration, storyPath), beforeStories);
 198  
         }
 199  
 
 200  18
         waitUntilAllDone(futures);
 201  
 
 202  18
         checkForFailures(futures);
 203  
 
 204  17
         State afterStories = storyRunner.runBeforeOrAfterStories(configuration, candidateSteps, Stage.AFTER);
 205  
 
 206  17
         if ( storyRunner.failed(afterStories) ){
 207  0
             if (embedderControls.ignoreFailureInStories()){
 208  0
                 embedderMonitor.beforeOrAfterStoriesFailed();
 209  
             } else {
 210  0
                 throw new RunningStoriesFailed();
 211  
             }
 212  
         }
 213  
 
 214  17
         if (embedderControls.batch() && batchFailures.size() > 0) {
 215  2
             if (embedderControls.ignoreFailureInStories()) {
 216  1
                 embedderMonitor.batchFailed(batchFailures);
 217  
             } else {
 218  1
                 throw new RunningStoriesFailed(batchFailures);
 219  
             }
 220  
         }
 221  
 
 222  16
         if (embedderControls.generateViewAfterStories()) {
 223  13
             generateReportsView();
 224  
         }
 225  
         
 226  16
     }
 227  
 
 228  
     public Future<ThrowableStory> enqueueStory(BatchFailures batchFailures, MetaFilter filter,
 229  
             List<Future<ThrowableStory>> futures, String storyPath, Story story) {
 230  0
         return enqueueStory(batchFailures, filter, futures, storyPath, story, null);
 231  
     }
 232  
 
 233  
     private Future<ThrowableStory> enqueueStory(BatchFailures batchFailures, MetaFilter filter,
 234  
             List<Future<ThrowableStory>> futures, String storyPath, Story story, State beforeStories) {
 235  26
         EnqueuedStory enqueuedStory = enqueuedStory(embedderControls, configuration, stepsFactory, batchFailures,
 236  
                 filter, storyPath, story, beforeStories);
 237  26
         return submit(futures, enqueuedStory);
 238  
     }
 239  
 
 240  
     private synchronized Future<ThrowableStory> submit(List<Future<ThrowableStory>> futures, EnqueuedStory enqueuedStory) {
 241  26
         if (executorService == null) {
 242  15
             executorService = createExecutorService();
 243  
         }
 244  26
         Future<ThrowableStory> submit = executorService.submit(enqueuedStory);
 245  26
         futures.add(submit);
 246  26
         return submit;
 247  
     }
 248  
 
 249  
     protected EnqueuedStory enqueuedStory(EmbedderControls embedderControls, Configuration configuration,
 250  
             InjectableStepsFactory stepsFactory, BatchFailures batchFailures, MetaFilter filter, String storyPath,
 251  
             Story story, State beforeStories) {
 252  26
         return new EnqueuedStory(storyPath, configuration, stepsFactory, story, filter, embedderControls,
 253  
                 batchFailures, embedderMonitor, storyRunner, beforeStories);
 254  
     }
 255  
 
 256  
     /**
 257  
      * Creates a {@link ThreadPoolExecutor} using the number of threads defined
 258  
      * in the {@link EmbedderControls#threads()}
 259  
      * 
 260  
      * @return An ExecutorService
 261  
      */
 262  
     protected ExecutorService createExecutorService() {
 263  15
         int threads = embedderControls.threads();
 264  15
         embedderMonitor.usingThreads(threads);
 265  15
         if (threads == 1) {
 266  
             // this is necessary for situations where people use the
 267  
             // PerStoriesWebDriverSteps class.
 268  15
             return new NonThreadingExecutorService();
 269  
         } else {
 270  0
             return Executors.newFixedThreadPool(threads);
 271  
         }
 272  
     }
 273  
 
 274  
     private void waitUntilAllDone(List<Future<ThrowableStory>> futures) {
 275  
 
 276  18
         long start = System.currentTimeMillis();
 277  18
         boolean allDone = false;
 278  36
         while (!allDone) {
 279  18
             allDone = true;
 280  18
             for (Future<ThrowableStory> future : futures) {
 281  26
                 if (!future.isDone()) {
 282  0
                     allDone = false;
 283  0
                     long durationInSecs = (System.currentTimeMillis() - start)/1000;
 284  0
                     if ( durationInSecs > embedderControls.storyTimeoutInSecs()) {
 285  0
                         Story story = null;
 286  
                         try {
 287  0
                             story = future.get().getStory();
 288  0
                         } catch (Throwable e) {
 289  0
                         }
 290  0
                         embedderMonitor.storyTimeout(durationInSecs, story);
 291  0
                         future.cancel(true);
 292  
                     }
 293  
                     try {
 294  0
                         Thread.sleep(100);
 295  0
                     } catch (InterruptedException e) {
 296  0
                     }
 297  0
                     break;
 298  
                 }
 299  
             }
 300  
         }
 301  18
     }
 302  
 
 303  
     private void checkForFailures(List<Future<ThrowableStory>> futures) {
 304  
         try {
 305  18
             BatchFailures failures = new BatchFailures();
 306  18
             for (Future<ThrowableStory> future : futures) {
 307  
                 try {
 308  26
                     ThrowableStory throwableStory = future.get();
 309  26
                     if (throwableStory.throwable != null) {
 310  2
                         failures.put(future.toString(), throwableStory.throwable);
 311  
                     }
 312  0
                 } catch (CancellationException e) {
 313  0
                     failures.put(future.toString(), e);
 314  52
                 }
 315  
             }
 316  18
             if (failures.size() > 0) {
 317  1
                 throw new RunningStoriesFailed(failures);
 318  
             }
 319  0
         } catch (InterruptedException e) {
 320  0
             throw new RuntimeException(e);
 321  0
         } catch (ExecutionException e) {
 322  0
             throw new RuntimeException(e);
 323  17
         }
 324  17
     }
 325  
 
 326  
     private void configureReporterBuilder(Configuration configuration) {
 327  18
         StoryReporterBuilder reporterBuilder = configuration.storyReporterBuilder();
 328  18
         reporterBuilder.withMultiThreading(embedderControls.threads() > 1);
 329  18
         configuration.useStoryReporterBuilder(reporterBuilder);
 330  18
     }
 331  
 
 332  
     public void generateReportsView() {
 333  13
         StoryReporterBuilder builder = configuration().storyReporterBuilder();
 334  13
         File outputDirectory = builder.outputDirectory();
 335  13
         List<String> formatNames = builder.formatNames(true);
 336  13
         generateReportsView(outputDirectory, formatNames, builder.viewResources());
 337  13
     }
 338  
 
 339  
     public void generateReportsView(File outputDirectory, List<String> formats, Properties viewResources) {
 340  19
         EmbedderControls embedderControls = embedderControls();
 341  
 
 342  19
         if (embedderControls.skip()) {
 343  1
             embedderMonitor.reportsViewNotGenerated();
 344  1
             return;
 345  
         }
 346  18
         ViewGenerator viewGenerator = configuration().viewGenerator();
 347  
         try {
 348  18
             embedderMonitor.generatingReportsView(outputDirectory, formats, viewResources);
 349  18
             viewGenerator.generateReportsView(outputDirectory, formats, viewResources);
 350  1
         } catch (RuntimeException e) {
 351  1
             embedderMonitor.reportsViewGenerationFailed(outputDirectory, formats, viewResources, e);
 352  1
             throw new ViewGenerationFailed(outputDirectory, formats, viewResources, e);
 353  17
         }
 354  17
         ReportsCount count = viewGenerator.getReportsCount();
 355  17
         embedderMonitor.reportsViewGenerated(count);
 356  17
         if (!embedderControls.ignoreFailureInView() && count.failed() ) {
 357  2
             throw new RunningStoriesFailed(count);
 358  
         }
 359  
 
 360  15
     }
 361  
 
 362  
     public void generateCrossReference() {
 363  11
         StoryReporterBuilder builder = configuration().storyReporterBuilder();
 364  11
         if (builder.hasCrossReference()){
 365  1
             builder.crossReference().outputToFiles(builder);
 366  
         }
 367  11
     }
 368  
 
 369  
     public void reportStepdocs() {
 370  1
         reportStepdocs(configuration(), candidateSteps());
 371  1
     }
 372  
 
 373  
     public void reportStepdocsAsEmbeddables(List<String> classNames) {
 374  0
         EmbedderControls embedderControls = embedderControls();
 375  0
         if (embedderControls.skip()) {
 376  0
             embedderMonitor.embeddablesSkipped(classNames);
 377  0
             return;
 378  
         }
 379  
 
 380  0
         for (Embeddable embeddable : embeddables(classNames, classLoader())) {
 381  0
             if (embeddable instanceof ConfigurableEmbedder) {
 382  0
                 ConfigurableEmbedder configurableEmbedder = (ConfigurableEmbedder) embeddable;
 383  0
                 reportStepdocs(configurableEmbedder.configuration(), configurableEmbedder.candidateSteps());
 384  0
             } else {
 385  0
                 embedderMonitor.embeddableNotConfigurable(embeddable.getClass().getName());
 386  
             }
 387  
         }
 388  0
     }
 389  
 
 390  
     public void reportStepdocs(Configuration configuration, List<CandidateSteps> candidateSteps) {
 391  1
         StepFinder finder = configuration.stepFinder();
 392  1
         StepdocReporter reporter = configuration.stepdocReporter();
 393  1
         List<Object> stepsInstances = finder.stepsInstances(candidateSteps);
 394  1
         reporter.stepdocs(finder.stepdocs(candidateSteps), stepsInstances);
 395  1
     }
 396  
 
 397  
     public void reportMatchingStepdocs(String stepAsString) {
 398  3
         Configuration configuration = configuration();
 399  3
         List<CandidateSteps> candidateSteps = candidateSteps();
 400  3
         StepFinder finder = configuration.stepFinder();
 401  3
         StepdocReporter reporter = configuration.stepdocReporter();
 402  3
         List<Stepdoc> matching = finder.findMatching(stepAsString, candidateSteps);
 403  3
         List<Object> stepsInstances = finder.stepsInstances(candidateSteps);
 404  3
         reporter.stepdocsMatching(stepAsString, matching, stepsInstances);
 405  3
     }
 406  
 
 407  
     public void processSystemProperties() {
 408  22
         Properties properties = systemProperties();
 409  22
         embedderMonitor.processingSystemProperties(properties);
 410  22
         if (!properties.isEmpty()) {
 411  1
             for (Object key : properties.keySet()) {
 412  2
                 String name = (String) key;
 413  2
                 String value = properties.getProperty(name);
 414  2
                 System.setProperty(name, value);
 415  2
                 embedderMonitor.systemPropertySet(name, value);
 416  2
             }
 417  
         }
 418  22
     }
 419  
 
 420  
     public EmbedderClassLoader classLoader() {
 421  13
         return classLoader;
 422  
     }
 423  
 
 424  
     public Configuration configuration() {
 425  108
         return configuration;
 426  
     }
 427  
 
 428  
     public List<CandidateSteps> candidateSteps() {
 429  15
         return candidateSteps;
 430  
     }
 431  
 
 432  
     public InjectableStepsFactory stepsFactory() {
 433  29
         if ( stepsFactory == null ){
 434  19
             stepsFactory = new ProvidedStepsFactory(candidateSteps);            
 435  
         }
 436  29
         return stepsFactory;
 437  
     }
 438  
 
 439  
     public EmbedderControls embedderControls() {
 440  60
         return embedderControls;
 441  
     }
 442  
 
 443  
     public EmbedderMonitor embedderMonitor() {
 444  2
         return embedderMonitor;
 445  
     }
 446  
 
 447  
     public List<String> metaFilters() {
 448  4
         return metaFilters;
 449  
     }
 450  
 
 451  
     public StoryRunner storyRunner() {
 452  2
         return storyRunner;
 453  
     }
 454  
 
 455  
     public Properties systemProperties() {
 456  25
         return systemProperties;
 457  
     }
 458  
 
 459  
     public void useClassLoader(EmbedderClassLoader classLoader) {
 460  14
         this.classLoader = classLoader;
 461  14
     }
 462  
 
 463  
     public void useConfiguration(Configuration configuration) {
 464  26
         this.configuration = configuration;
 465  26
     }
 466  
 
 467  
     public void useCandidateSteps(List<CandidateSteps> candidateSteps) {
 468  19
         this.candidateSteps = candidateSteps;
 469  19
     }
 470  
 
 471  
     public void useStepsFactory(InjectableStepsFactory stepsFactory) {
 472  19
         this.stepsFactory = stepsFactory;        
 473  19
     }
 474  
 
 475  
     public void useEmbedderControls(EmbedderControls embedderControls) {
 476  28
         this.embedderControls = embedderControls;
 477  28
     }
 478  
 
 479  
     public void useEmbedderMonitor(EmbedderMonitor embedderMonitor) {
 480  1
         this.embedderMonitor = embedderMonitor;
 481  1
     }
 482  
 
 483  
     public void useMetaFilters(List<String> metaFilters) {
 484  4
         this.metaFilters = metaFilters;
 485  4
     }
 486  
 
 487  
     public void useStoryRunner(StoryRunner storyRunner) {
 488  1
         this.storyRunner = storyRunner;
 489  1
     }
 490  
 
 491  
     public void useSystemProperties(Properties systemProperties) {
 492  2
         this.systemProperties = systemProperties;
 493  2
     }
 494  
 
 495  
     @Override
 496  
     public String toString() {
 497  1
         return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
 498  
     }
 499  
 
 500  
     @SuppressWarnings("serial")
 501  
     public static class AnnotatedEmbedderRunFailed extends RuntimeException {
 502  
 
 503  
         public AnnotatedEmbedderRunFailed(AnnotatedEmbedderRunner runner, Throwable cause) {
 504  1
             super("Annotated embedder run failed with runner " + runner.toString(), cause);
 505  1
         }
 506  
 
 507  
     }
 508  
 
 509  
     @SuppressWarnings("serial")
 510  
     public static class RunningEmbeddablesFailed extends RuntimeException {
 511  
 
 512  
         public RunningEmbeddablesFailed(String name, Throwable cause) {
 513  1
             super("Failures in running embeddable " + name, cause);
 514  1
         }
 515  
 
 516  
         public RunningEmbeddablesFailed(BatchFailures batchFailures) {
 517  1
             super("Failures in running embeddables in batch: " + batchFailures);
 518  1
         }
 519  
 
 520  
     }
 521  
 
 522  
     @SuppressWarnings("serial")
 523  
     public static class RunningStoriesFailed extends RuntimeException {
 524  
 
 525  
         public RunningStoriesFailed(ReportsCount count) {
 526  2
             super("Failures in running stories: " + count);
 527  2
         }
 528  
 
 529  
         public RunningStoriesFailed(BatchFailures failures) {
 530  2
             super("Failures in running stories in batch: " + failures);
 531  2
         }
 532  
 
 533  
         public RunningStoriesFailed(String name, Throwable cause) {
 534  2
             super("Failures in running stories " + name, cause);
 535  2
         }
 536  
 
 537  
         public RunningStoriesFailed() {
 538  0
             super("Failures in running before or after stories steps");
 539  0
         }
 540  
     }
 541  
 
 542  
     @SuppressWarnings("serial")
 543  
     public static class ViewGenerationFailed extends RuntimeException {
 544  
         public ViewGenerationFailed(File outputDirectory, List<String> formats, Properties viewResources,
 545  
                 RuntimeException cause) {
 546  1
             super("View generation failed to " + outputDirectory + " for formats " + formats + " and resources "
 547  
                     + viewResources, cause);
 548  1
         }
 549  
 
 550  
         public ViewGenerationFailed(File outputDirectory, StoryMaps storyMaps, Properties viewResources,
 551  
                 RuntimeException cause) {
 552  0
             super("View generation failed to " + outputDirectory + " for story maps " + storyMaps + " for resources "
 553  
                     + viewResources, cause);
 554  0
         }
 555  
     }
 556  
 
 557  
     /**
 558  
      * Non-threading ExecutorService for situations where thread count = 1
 559  
      */
 560  15
     public static class NonThreadingExecutorService implements ExecutorService {
 561  
         public void shutdown() {
 562  0
             throw new UnsupportedOperationException();
 563  
         }
 564  
 
 565  
         public List<Runnable> shutdownNow() {
 566  0
             throw new UnsupportedOperationException();
 567  
         }
 568  
 
 569  
         public boolean isShutdown() {
 570  0
             throw new UnsupportedOperationException();
 571  
         }
 572  
 
 573  
         public boolean isTerminated() {
 574  0
             throw new UnsupportedOperationException();
 575  
         }
 576  
 
 577  
         public boolean awaitTermination(long l, TimeUnit timeUnit) throws InterruptedException {
 578  0
             throw new UnsupportedOperationException();
 579  
         }
 580  
 
 581  
         public <T> Future<T> submit(Callable<T> callable) {
 582  26
             final Object[] rc = new Object[1];
 583  
             try {
 584  26
                 rc[0] = callable.call();
 585  0
             } catch (Exception e) {
 586  0
                 rc[0] = e;
 587  26
             }
 588  26
             return new Future<T>() {
 589  
 
 590  
                 public boolean cancel(boolean b) {
 591  0
                     throw new UnsupportedOperationException();
 592  
                 }
 593  
 
 594  
                 public boolean isCancelled() {
 595  0
                     throw new UnsupportedOperationException();
 596  
                 }
 597  
 
 598  
                 public boolean isDone() {
 599  26
                     return true;
 600  
                 }
 601  
 
 602  
                 @SuppressWarnings("unchecked")
 603  
                 public T get() throws InterruptedException, ExecutionException {
 604  26
                     return (T) rc[0];
 605  
                 }
 606  
 
 607  
                 public T get(long l, TimeUnit timeUnit) throws InterruptedException, ExecutionException,
 608  
                         TimeoutException {
 609  0
                     return get();
 610  
                 }
 611  
             };
 612  
         }
 613  
 
 614  
         public <T> Future<T> submit(Runnable runnable, T t) {
 615  0
             throw new UnsupportedOperationException();
 616  
         }
 617  
 
 618  
         public Future<?> submit(Runnable runnable) {
 619  0
             throw new UnsupportedOperationException();
 620  
         }
 621  
 
 622  
         public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> callables) throws InterruptedException {
 623  0
             throw new UnsupportedOperationException();
 624  
         }
 625  
 
 626  
         public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> callables, long l, TimeUnit timeUnit)
 627  
                 throws InterruptedException {
 628  0
             throw new UnsupportedOperationException();
 629  
         }
 630  
 
 631  
         public <T> T invokeAny(Collection<? extends Callable<T>> callables) throws InterruptedException,
 632  
                 ExecutionException {
 633  0
             throw new UnsupportedOperationException();
 634  
         }
 635  
 
 636  
         public <T> T invokeAny(Collection<? extends Callable<T>> callables, long l, TimeUnit timeUnit)
 637  
                 throws InterruptedException, ExecutionException, TimeoutException {
 638  0
             throw new UnsupportedOperationException();
 639  
         }
 640  
 
 641  
         public void execute(Runnable runnable) {
 642  0
             throw new UnsupportedOperationException();
 643  
         }
 644  
     }
 645  
 
 646  26
     public static class EnqueuedStory implements Callable<ThrowableStory> {
 647  
         private final String storyPath;
 648  
         private final Configuration configuration;
 649  
         private final InjectableStepsFactory stepsFactory;
 650  
         private final Story story;
 651  
         private final MetaFilter filter;
 652  
         private final EmbedderControls embedderControls;
 653  
         private final BatchFailures batchFailures;
 654  
         private final EmbedderMonitor embedderMonitor;
 655  
         private final StoryRunner storyRunner;
 656  
         private final State beforeStories;
 657  
 
 658  
         public EnqueuedStory(String storyPath, Configuration configuration, List<CandidateSteps> candidateSteps,
 659  
                 Story story, MetaFilter filter, EmbedderControls embedderControls, BatchFailures batchFailures,
 660  
                 EmbedderMonitor embedderMonitor, StoryRunner storyRunner, State beforeStories) {
 661  0
             this(storyPath, configuration, new ProvidedStepsFactory(candidateSteps), story, filter, embedderControls, batchFailures, embedderMonitor, storyRunner, beforeStories);
 662  0
         }
 663  
 
 664  
         public EnqueuedStory(String storyPath, Configuration configuration, InjectableStepsFactory stepsFactory,
 665  
                 Story story, MetaFilter filter, EmbedderControls embedderControls, BatchFailures batchFailures,
 666  26
                 EmbedderMonitor embedderMonitor, StoryRunner storyRunner, State beforeStories) {
 667  26
             this.storyPath = storyPath;
 668  26
             this.configuration = configuration;
 669  26
             this.stepsFactory = stepsFactory;
 670  26
             this.story = story;
 671  26
             this.filter = filter;
 672  26
             this.embedderControls = embedderControls;
 673  26
             this.batchFailures = batchFailures;
 674  26
             this.embedderMonitor = embedderMonitor;
 675  26
             this.storyRunner = storyRunner;
 676  26
             this.beforeStories = beforeStories;
 677  26
         }
 678  
 
 679  
         public ThrowableStory call() throws Exception {
 680  
             try {
 681  26
                 embedderMonitor.runningStory(storyPath);
 682  26
                 storyRunner.run(configuration, stepsFactory, story, filter, beforeStories);
 683  8
             } catch (Throwable e) {
 684  8
                 if (embedderControls.batch()) {
 685  
                     // collect and postpone decision to throw exception
 686  4
                     batchFailures.put(storyPath, e);
 687  
                 } else {
 688  4
                     if (embedderControls.ignoreFailureInStories()) {
 689  2
                         embedderMonitor.storyFailed(storyPath, e);
 690  
                     } else {
 691  2
                         return new ThrowableStory(new RunningStoriesFailed(storyPath, e), story);
 692  
                     }
 693  
                 }
 694  18
             }
 695  24
             return new ThrowableStory(null, story);
 696  
         }
 697  
     }
 698  
     
 699  28
     public static class ThrowableStory {
 700  
         private Throwable throwable;
 701  
         private Story story;
 702  
 
 703  26
         public ThrowableStory(Throwable throwable, Story story) {
 704  26
             this.throwable = throwable;
 705  26
             this.story = story;
 706  26
         }
 707  
 
 708  
         public Story getStory() {
 709  0
             return story;
 710  
         }
 711  
     }
 712  
 
 713  
 }