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.ExecutorService; |
9 | |
import java.util.concurrent.ThreadPoolExecutor; |
10 | |
|
11 | |
import org.apache.commons.lang.StringUtils; |
12 | |
import org.apache.commons.lang.builder.ToStringBuilder; |
13 | |
import org.apache.commons.lang.builder.ToStringStyle; |
14 | |
import org.jbehave.core.ConfigurableEmbedder; |
15 | |
import org.jbehave.core.Embeddable; |
16 | |
import org.jbehave.core.configuration.Configuration; |
17 | |
import org.jbehave.core.configuration.MostUsefulConfiguration; |
18 | |
import org.jbehave.core.embedder.executors.FixedThreadExecutors; |
19 | |
import org.jbehave.core.failures.BatchFailures; |
20 | |
import org.jbehave.core.failures.FailingUponPendingStep; |
21 | |
import org.jbehave.core.junit.AnnotatedEmbedderRunner; |
22 | |
import org.jbehave.core.junit.AnnotatedEmbedderUtils; |
23 | |
import org.jbehave.core.model.Story; |
24 | |
import org.jbehave.core.model.StoryMaps; |
25 | |
import org.jbehave.core.reporters.ReportsCount; |
26 | |
import org.jbehave.core.reporters.StepdocReporter; |
27 | |
import org.jbehave.core.reporters.StoryReporterBuilder; |
28 | |
import org.jbehave.core.reporters.ViewGenerator; |
29 | |
import org.jbehave.core.steps.CandidateSteps; |
30 | |
import org.jbehave.core.steps.InjectableStepsFactory; |
31 | |
import org.jbehave.core.steps.ProvidedStepsFactory; |
32 | |
import org.jbehave.core.steps.StepFinder; |
33 | |
import org.jbehave.core.steps.Stepdoc; |
34 | |
|
35 | |
|
36 | |
|
37 | |
|
38 | |
|
39 | |
|
40 | |
public class Embedder { |
41 | |
|
42 | |
private StoryMapper storyMapper; |
43 | |
private StoryRunner storyRunner; |
44 | |
private EmbedderMonitor embedderMonitor; |
45 | 74 | private EmbedderClassLoader classLoader = new EmbedderClassLoader(this.getClass().getClassLoader()); |
46 | 74 | private EmbedderControls embedderControls = new EmbedderControls(); |
47 | 74 | private EmbedderFailureStrategy embedderFailureStrategy = new ThrowingRunningStoriesFailed(); |
48 | 74 | private Configuration configuration = new MostUsefulConfiguration(); |
49 | 74 | private List<CandidateSteps> candidateSteps = new ArrayList<CandidateSteps>(); |
50 | |
private InjectableStepsFactory stepsFactory; |
51 | 74 | private List<String> metaFilters = Arrays.asList(); |
52 | 74 | private Properties systemProperties = new Properties(); |
53 | |
private ExecutorService executorService; |
54 | |
private boolean executorServiceCreated; |
55 | |
private StoryManager storyManager; |
56 | |
|
57 | |
public Embedder() { |
58 | 41 | this(new StoryMapper(), new StoryRunner(), new PrintStreamEmbedderMonitor()); |
59 | 41 | } |
60 | |
|
61 | 74 | public Embedder(StoryMapper storyMapper, StoryRunner storyRunner, EmbedderMonitor embedderMonitor) { |
62 | 74 | this.storyMapper = storyMapper; |
63 | 74 | this.storyRunner = storyRunner; |
64 | 74 | this.embedderMonitor = embedderMonitor; |
65 | 74 | } |
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 | StoryManager storyManager = storyManager(); |
79 | 1 | for (String storyPath : storyPaths) { |
80 | 2 | Story story = storyManager.storyOfPath(storyPath); |
81 | 2 | embedderMonitor.mappingStory(storyPath, metaFilters); |
82 | 2 | storyMapper.map(story, new MetaFilter("")); |
83 | 2 | for (String filter : metaFilters) { |
84 | 0 | storyMapper.map(story, new MetaFilter(filter)); |
85 | |
} |
86 | 2 | } |
87 | |
|
88 | 1 | generateMapsView(storyMapper.getStoryMaps()); |
89 | |
|
90 | 1 | } |
91 | |
|
92 | |
private void generateMapsView(StoryMaps storyMaps) { |
93 | 1 | Configuration configuration = configuration(); |
94 | 1 | StoryReporterBuilder builder = configuration.storyReporterBuilder(); |
95 | 1 | File outputDirectory = builder.outputDirectory(); |
96 | 1 | Properties viewResources = builder.viewResources(); |
97 | 1 | ViewGenerator viewGenerator = configuration.viewGenerator(); |
98 | |
try { |
99 | 1 | embedderMonitor.generatingMapsView(outputDirectory, storyMaps, viewResources); |
100 | 1 | viewGenerator.generateMapsView(outputDirectory, storyMaps, viewResources); |
101 | 0 | } catch (RuntimeException e) { |
102 | 0 | embedderMonitor.mapsViewGenerationFailed(outputDirectory, storyMaps, viewResources, e); |
103 | 0 | throw new ViewGenerationFailed(outputDirectory, storyMaps, viewResources, e); |
104 | 1 | } |
105 | 1 | } |
106 | |
|
107 | |
public void runAsEmbeddables(List<String> classNames) { |
108 | 11 | EmbedderControls embedderControls = embedderControls(); |
109 | 11 | embedderMonitor.usingControls(embedderControls); |
110 | |
|
111 | 11 | if (embedderControls.skip()) { |
112 | 1 | embedderMonitor.embeddablesSkipped(classNames); |
113 | 1 | return; |
114 | |
} |
115 | |
|
116 | 10 | BatchFailures failures = new BatchFailures(embedderControls.verboseFailures()); |
117 | 10 | for (Embeddable embeddable : embeddables(classNames, classLoader())) { |
118 | 16 | String name = embeddable.getClass().getName(); |
119 | |
try { |
120 | 16 | embedderMonitor.runningEmbeddable(name); |
121 | 16 | embeddable.useEmbedder(this); |
122 | 16 | embeddable.run(); |
123 | 5 | } catch (Throwable e) { |
124 | 5 | if (embedderControls.batch()) { |
125 | |
|
126 | 2 | failures.put(name, e); |
127 | |
} else { |
128 | 3 | if (ignoreFailure(embedderControls)) { |
129 | 1 | embedderMonitor.embeddableFailed(name, e); |
130 | |
} else { |
131 | 2 | throw new RunningEmbeddablesFailed(name, e); |
132 | |
} |
133 | |
} |
134 | 11 | } |
135 | 14 | } |
136 | |
|
137 | 8 | if (embedderControls.batch() && failures.size() > 0) { |
138 | 2 | if (ignoreFailure(embedderControls)) { |
139 | 1 | embedderMonitor.batchFailed(failures); |
140 | |
} else { |
141 | 1 | throw new RunningEmbeddablesFailed(failures); |
142 | |
} |
143 | |
} |
144 | |
|
145 | 7 | } |
146 | |
|
147 | |
private boolean ignoreFailure(EmbedderControls embedderControls) { |
148 | 5 | boolean ignore = embedderControls.ignoreFailureInStories(); |
149 | 5 | if (embedderControls.generateViewAfterStories()) { |
150 | 5 | ignore = ignore && embedderControls.ignoreFailureInView(); |
151 | |
} |
152 | 5 | return ignore; |
153 | |
} |
154 | |
|
155 | |
private List<Embeddable> embeddables(List<String> classNames, EmbedderClassLoader classLoader) { |
156 | 10 | List<Embeddable> embeddables = new ArrayList<Embeddable>(); |
157 | 10 | for (String className : classNames) { |
158 | 18 | if (!classLoader.isAbstract(className)) { |
159 | 17 | embeddables.add(classLoader.newInstance(Embeddable.class, className)); |
160 | |
} |
161 | |
} |
162 | 10 | return embeddables; |
163 | |
} |
164 | |
|
165 | |
public void runStoriesWithAnnotatedEmbedderRunner(List<String> classNames) { |
166 | 4 | EmbedderClassLoader classLoader = classLoader(); |
167 | 4 | for (String className : classNames) { |
168 | 4 | embedderMonitor.runningWithAnnotatedEmbedderRunner(className); |
169 | 4 | AnnotatedEmbedderRunner runner = AnnotatedEmbedderUtils.annotatedEmbedderRunner(className, classLoader); |
170 | |
try { |
171 | 3 | Object annotatedInstance = runner.createTest(); |
172 | 3 | if (annotatedInstance instanceof Embeddable) { |
173 | 2 | ((Embeddable) annotatedInstance).run(); |
174 | |
} else { |
175 | 1 | embedderMonitor.annotatedInstanceNotOfType(annotatedInstance, Embeddable.class); |
176 | |
} |
177 | 1 | } catch (Throwable e) { |
178 | 1 | throw new AnnotatedEmbedderRunFailed(runner, e); |
179 | 2 | } |
180 | 2 | } |
181 | 2 | } |
182 | |
|
183 | |
public void runStoriesAsPaths(List<String> storyPaths) { |
184 | |
|
185 | 12 | processSystemProperties(); |
186 | |
|
187 | 12 | embedderMonitor.usingControls(embedderControls); |
188 | |
|
189 | 12 | if (embedderControls.skip()) { |
190 | 1 | embedderMonitor.storiesSkipped(storyPaths); |
191 | 1 | return; |
192 | |
} |
193 | |
|
194 | |
try { |
195 | |
|
196 | |
|
197 | 11 | StoryManager storyManager = createStoryManager(); |
198 | 11 | MetaFilter filter = metaFilter(); |
199 | 11 | BatchFailures failures = new BatchFailures(embedderControls.verboseFailures()); |
200 | |
|
201 | |
|
202 | 11 | storyManager.runStories(storyPaths, filter, failures); |
203 | |
|
204 | |
|
205 | 11 | handleFailures(failures); |
206 | |
|
207 | |
} finally { |
208 | |
|
209 | |
|
210 | |
|
211 | 11 | if (embedderControls.generateViewAfterStories()) { |
212 | 10 | generateReportsView(); |
213 | |
} |
214 | 11 | shutdownExecutorService(); |
215 | |
|
216 | 6 | } |
217 | 6 | } |
218 | |
|
219 | |
private void handleFailures(BatchFailures failures) { |
220 | 11 | if (failures.size() > 0) { |
221 | 5 | if (embedderControls.ignoreFailureInStories()) { |
222 | 0 | embedderMonitor.batchFailed(failures); |
223 | |
} else { |
224 | 5 | embedderFailureStrategy.handleFailures(failures); |
225 | |
} |
226 | |
} |
227 | 6 | } |
228 | |
|
229 | |
public void generateReportsView() { |
230 | 10 | StoryReporterBuilder builder = configuration().storyReporterBuilder(); |
231 | 10 | File outputDirectory = builder.outputDirectory(); |
232 | 10 | List<String> formatNames = builder.formatNames(true); |
233 | 10 | generateReportsView(outputDirectory, formatNames, builder.viewResources()); |
234 | 10 | } |
235 | |
|
236 | |
public void generateReportsView(File outputDirectory, List<String> formats, Properties viewResources) { |
237 | |
|
238 | 19 | if (embedderControls.skip()) { |
239 | 1 | embedderMonitor.reportsViewNotGenerated(); |
240 | 1 | return; |
241 | |
} |
242 | 18 | ViewGenerator viewGenerator = configuration().viewGenerator(); |
243 | |
try { |
244 | 18 | embedderMonitor.generatingReportsView(outputDirectory, formats, viewResources); |
245 | 18 | viewGenerator.generateReportsView(outputDirectory, formats, viewResources); |
246 | 1 | } catch (RuntimeException e) { |
247 | 1 | embedderMonitor.reportsViewGenerationFailed(outputDirectory, formats, viewResources, e); |
248 | 1 | throw new ViewGenerationFailed(outputDirectory, formats, viewResources, e); |
249 | 17 | } |
250 | 17 | ReportsCount count = viewGenerator.getReportsCount(); |
251 | 17 | embedderMonitor.reportsViewGenerated(count); |
252 | 17 | handleFailures(count); |
253 | |
|
254 | 13 | } |
255 | |
|
256 | |
private void handleFailures(ReportsCount count) { |
257 | 17 | boolean failed = count.failed(); |
258 | 17 | if (configuration().pendingStepStrategy() instanceof FailingUponPendingStep) { |
259 | 1 | failed = failed || count.pending(); |
260 | |
} |
261 | 17 | if (failed) { |
262 | 6 | if (embedderControls.ignoreFailureInView()) { |
263 | 1 | embedderMonitor.reportsViewFailures(count); |
264 | |
} else { |
265 | 5 | embedderFailureStrategy.handleFailures(count); |
266 | |
} |
267 | |
} |
268 | 13 | } |
269 | |
|
270 | |
public void generateCrossReference() { |
271 | 2 | StoryReporterBuilder builder = configuration().storyReporterBuilder(); |
272 | 2 | if (builder.hasCrossReference()) { |
273 | 1 | builder.crossReference().outputToFiles(builder); |
274 | |
} |
275 | 2 | } |
276 | |
|
277 | |
public void reportStepdocs() { |
278 | 1 | reportStepdocs(configuration(), candidateSteps()); |
279 | 1 | } |
280 | |
|
281 | |
public void reportStepdocsAsEmbeddables(List<String> classNames) { |
282 | 0 | EmbedderControls embedderControls = embedderControls(); |
283 | 0 | if (embedderControls.skip()) { |
284 | 0 | embedderMonitor.embeddablesSkipped(classNames); |
285 | 0 | return; |
286 | |
} |
287 | |
|
288 | 0 | for (Embeddable embeddable : embeddables(classNames, classLoader())) { |
289 | 0 | if (embeddable instanceof ConfigurableEmbedder) { |
290 | 0 | ConfigurableEmbedder configurableEmbedder = (ConfigurableEmbedder) embeddable; |
291 | 0 | List<CandidateSteps> steps = configurableEmbedder.candidateSteps(); |
292 | 0 | if (steps.isEmpty()) { |
293 | 0 | steps = configurableEmbedder.stepsFactory().createCandidateSteps(); |
294 | |
} |
295 | 0 | reportStepdocs(configurableEmbedder.configuration(), steps); |
296 | 0 | } else { |
297 | 0 | embedderMonitor.embeddableNotConfigurable(embeddable.getClass().getName()); |
298 | |
} |
299 | |
} |
300 | 0 | } |
301 | |
|
302 | |
public void reportStepdocs(Configuration configuration, List<CandidateSteps> candidateSteps) { |
303 | 1 | StepFinder finder = configuration.stepFinder(); |
304 | 1 | StepdocReporter reporter = configuration.stepdocReporter(); |
305 | 1 | List<Object> stepsInstances = finder.stepsInstances(candidateSteps); |
306 | 1 | reporter.stepdocs(finder.stepdocs(candidateSteps), stepsInstances); |
307 | 1 | } |
308 | |
|
309 | |
public void reportMatchingStepdocs(String stepAsString) { |
310 | 3 | Configuration configuration = configuration(); |
311 | 3 | List<CandidateSteps> candidateSteps = candidateSteps(); |
312 | 3 | StepFinder finder = configuration.stepFinder(); |
313 | 3 | StepdocReporter reporter = configuration.stepdocReporter(); |
314 | 3 | List<Stepdoc> matching = finder.findMatching(stepAsString, candidateSteps); |
315 | 3 | List<Object> stepsInstances = finder.stepsInstances(candidateSteps); |
316 | 3 | reporter.stepdocsMatching(stepAsString, matching, stepsInstances); |
317 | 3 | } |
318 | |
|
319 | |
public void processSystemProperties() { |
320 | 15 | Properties properties = systemProperties(); |
321 | 15 | embedderMonitor.processingSystemProperties(properties); |
322 | 15 | if (!properties.isEmpty()) { |
323 | 1 | for (Object key : properties.keySet()) { |
324 | 2 | String name = (String) key; |
325 | 2 | String value = properties.getProperty(name); |
326 | 2 | System.setProperty(name, value); |
327 | 2 | embedderMonitor.systemPropertySet(name, value); |
328 | 2 | } |
329 | |
} |
330 | 15 | } |
331 | |
|
332 | |
public EmbedderClassLoader classLoader() { |
333 | 14 | return classLoader; |
334 | |
} |
335 | |
|
336 | |
public Configuration configuration() { |
337 | 102 | configureThreads(configuration, embedderControls.threads()); |
338 | 102 | return configuration; |
339 | |
} |
340 | |
|
341 | |
public List<CandidateSteps> candidateSteps() { |
342 | 15 | return candidateSteps; |
343 | |
} |
344 | |
|
345 | |
public InjectableStepsFactory stepsFactory() { |
346 | 23 | if (stepsFactory == null) { |
347 | 12 | stepsFactory = new ProvidedStepsFactory(candidateSteps); |
348 | |
} |
349 | 23 | return stepsFactory; |
350 | |
} |
351 | |
|
352 | |
public EmbedderControls embedderControls() { |
353 | 36 | return embedderControls; |
354 | |
} |
355 | |
|
356 | |
public EmbedderMonitor embedderMonitor() { |
357 | 14 | return embedderMonitor; |
358 | |
} |
359 | |
|
360 | |
public EmbedderFailureStrategy embedderFailureStrategy() { |
361 | 0 | return embedderFailureStrategy; |
362 | |
} |
363 | |
|
364 | |
public boolean hasExecutorService() { |
365 | 1 | return executorService != null; |
366 | |
} |
367 | |
|
368 | |
public ExecutorService executorService() { |
369 | 12 | if (executorService == null) { |
370 | 12 | executorService = createExecutorService(); |
371 | 12 | executorServiceCreated = true; |
372 | |
} |
373 | 12 | return executorService; |
374 | |
} |
375 | |
|
376 | |
|
377 | |
|
378 | |
|
379 | |
|
380 | |
|
381 | |
|
382 | |
private ExecutorService createExecutorService() { |
383 | 12 | return new FixedThreadExecutors().create(embedderControls); |
384 | |
} |
385 | |
|
386 | |
|
387 | |
|
388 | |
|
389 | |
|
390 | |
|
391 | |
|
392 | |
protected void shutdownExecutorService() { |
393 | 11 | if (executorServiceCreated) { |
394 | 11 | executorService.shutdownNow(); |
395 | 11 | executorService = null; |
396 | 11 | executorServiceCreated = false; |
397 | |
} |
398 | 11 | } |
399 | |
|
400 | |
public StoryManager storyManager() { |
401 | 1 | if (storyManager == null) { |
402 | 1 | storyManager = createStoryManager(); |
403 | |
} |
404 | 1 | return storyManager; |
405 | |
} |
406 | |
|
407 | |
private StoryManager createStoryManager() { |
408 | 12 | return new StoryManager(configuration(), embedderControls(), embedderMonitor(), executorService(), |
409 | |
stepsFactory(), storyRunner()); |
410 | |
} |
411 | |
|
412 | |
private void configureThreads(Configuration configuration, int threads) { |
413 | 102 | StoryReporterBuilder reporterBuilder = configuration.storyReporterBuilder(); |
414 | 102 | reporterBuilder.withMultiThreading(threads > 1); |
415 | 102 | configuration.useStoryReporterBuilder(reporterBuilder); |
416 | 102 | } |
417 | |
|
418 | |
public List<String> metaFilters() { |
419 | 4 | return metaFilters; |
420 | |
} |
421 | |
|
422 | |
public MetaFilter metaFilter() { |
423 | 11 | return new MetaFilter(StringUtils.join(metaFilters, " "), embedderMonitor); |
424 | |
} |
425 | |
|
426 | |
public StoryRunner storyRunner() { |
427 | 14 | return storyRunner; |
428 | |
} |
429 | |
|
430 | |
public Properties systemProperties() { |
431 | 18 | return systemProperties; |
432 | |
} |
433 | |
|
434 | |
public void useClassLoader(EmbedderClassLoader classLoader) { |
435 | 14 | this.classLoader = classLoader; |
436 | 14 | } |
437 | |
|
438 | |
public void useConfiguration(Configuration configuration) { |
439 | 17 | this.configuration = configuration; |
440 | 17 | } |
441 | |
|
442 | |
public void useCandidateSteps(List<CandidateSteps> candidateSteps) { |
443 | 10 | this.candidateSteps = candidateSteps; |
444 | 10 | } |
445 | |
|
446 | |
public void useStepsFactory(InjectableStepsFactory stepsFactory) { |
447 | 10 | this.stepsFactory = stepsFactory; |
448 | 10 | } |
449 | |
|
450 | |
public void useEmbedderControls(EmbedderControls embedderControls) { |
451 | 33 | this.embedderControls = embedderControls; |
452 | 33 | } |
453 | |
|
454 | |
public void useEmbedderFailureStrategy(EmbedderFailureStrategy failureStategy) { |
455 | 1 | this.embedderFailureStrategy = failureStategy; |
456 | 1 | } |
457 | |
|
458 | |
public void useEmbedderMonitor(EmbedderMonitor embedderMonitor) { |
459 | 1 | this.embedderMonitor = embedderMonitor; |
460 | 1 | } |
461 | |
|
462 | |
public void useExecutorService(ExecutorService executorService) { |
463 | 0 | this.executorService = executorService; |
464 | 0 | embedderMonitor.usingExecutorService(executorService); |
465 | 0 | } |
466 | |
|
467 | |
public void useMetaFilters(List<String> metaFilters) { |
468 | 4 | this.metaFilters = metaFilters; |
469 | 4 | } |
470 | |
|
471 | |
public void useStoryRunner(StoryRunner storyRunner) { |
472 | 1 | this.storyRunner = storyRunner; |
473 | 1 | } |
474 | |
|
475 | |
public void useSystemProperties(Properties systemProperties) { |
476 | 2 | this.systemProperties = systemProperties; |
477 | 2 | } |
478 | |
|
479 | |
@Override |
480 | |
public String toString() { |
481 | 1 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); |
482 | |
} |
483 | |
|
484 | |
public static interface EmbedderFailureStrategy { |
485 | |
|
486 | |
void handleFailures(BatchFailures failures); |
487 | |
|
488 | |
void handleFailures(ReportsCount count); |
489 | |
|
490 | |
} |
491 | |
|
492 | 74 | public static class ThrowingRunningStoriesFailed implements EmbedderFailureStrategy { |
493 | |
|
494 | |
public void handleFailures(BatchFailures failures) { |
495 | 5 | throw new RunningStoriesFailed(failures); |
496 | |
} |
497 | |
|
498 | |
public void handleFailures(ReportsCount count) { |
499 | 4 | throw new RunningStoriesFailed(count); |
500 | |
} |
501 | |
|
502 | |
} |
503 | |
|
504 | |
@SuppressWarnings("serial") |
505 | |
public static class AnnotatedEmbedderRunFailed extends RuntimeException { |
506 | |
|
507 | |
public AnnotatedEmbedderRunFailed(AnnotatedEmbedderRunner runner, Throwable cause) { |
508 | 1 | super("Annotated embedder run failed with runner " + runner.toString(), cause); |
509 | 1 | } |
510 | |
|
511 | |
} |
512 | |
|
513 | |
@SuppressWarnings("serial") |
514 | |
public static class RunningEmbeddablesFailed extends RuntimeException { |
515 | |
|
516 | |
public RunningEmbeddablesFailed(String name, Throwable failure) { |
517 | 2 | super("Failure in running embeddable: " + name, failure); |
518 | 2 | } |
519 | |
|
520 | |
public RunningEmbeddablesFailed(BatchFailures failures) { |
521 | 1 | super("Failures in running embeddables: " + failures); |
522 | 1 | } |
523 | |
|
524 | |
} |
525 | |
|
526 | |
@SuppressWarnings("serial") |
527 | |
public static class RunningStoriesFailed extends RuntimeException { |
528 | |
|
529 | |
public RunningStoriesFailed(ReportsCount reportsCount) { |
530 | 4 | super("Failures in running stories: " + reportsCount); |
531 | 4 | } |
532 | |
|
533 | |
public RunningStoriesFailed(BatchFailures failures) { |
534 | 5 | super("Failures in running stories: " + failures); |
535 | 5 | } |
536 | |
|
537 | |
} |
538 | |
|
539 | |
@SuppressWarnings("serial") |
540 | |
public static class ViewGenerationFailed extends RuntimeException { |
541 | |
public ViewGenerationFailed(File outputDirectory, List<String> formats, Properties viewResources, |
542 | |
RuntimeException cause) { |
543 | 1 | super("View generation failed to " + outputDirectory + " for formats " + formats + " and resources " |
544 | |
+ viewResources, cause); |
545 | 1 | } |
546 | |
|
547 | |
public ViewGenerationFailed(File outputDirectory, StoryMaps storyMaps, Properties viewResources, |
548 | |
RuntimeException cause) { |
549 | 0 | super("View generation failed to " + outputDirectory + " for story maps " + storyMaps + " for resources " |
550 | |
+ viewResources, cause); |
551 | 0 | } |
552 | |
} |
553 | |
|
554 | |
} |