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