1 package com.atlassian.maven.plugins.amps;
2
3 import com.atlassian.maven.plugins.amps.product.ProductHandler;
4 import com.atlassian.maven.plugins.amps.product.ProductHandlerFactory;
5 import com.atlassian.maven.plugins.amps.product.studio.StudioProductHandler;
6 import com.atlassian.maven.plugins.amps.util.ArtifactRetriever;
7 import com.atlassian.maven.plugins.amps.util.ProjectUtils;
8 import com.google.common.base.Predicate;
9 import com.google.common.collect.Iterables;
10 import com.google.common.collect.Lists;
11 import com.google.common.collect.Maps;
12 import org.apache.commons.lang.StringUtils;
13 import org.apache.maven.artifact.factory.ArtifactFactory;
14 import org.apache.maven.artifact.repository.ArtifactRepository;
15 import org.apache.maven.artifact.resolver.ArtifactResolver;
16 import org.apache.maven.model.Resource;
17 import org.apache.maven.plugin.MojoExecutionException;
18 import org.apache.maven.plugin.MojoFailureException;
19 import org.apache.maven.project.MavenProject;
20 import org.jfrog.maven.annomojo.annotations.MojoComponent;
21 import org.jfrog.maven.annomojo.annotations.MojoParameter;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.net.HttpURLConnection;
26 import java.net.InetAddress;
27 import java.net.URL;
28 import java.net.UnknownHostException;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Properties;
34 import java.util.concurrent.ExecutionException;
35 import java.util.concurrent.ExecutorService;
36 import java.util.concurrent.Executors;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.TimeoutException;
40
41
42
43
44 public abstract class AbstractProductHandlerMojo extends AbstractProductHandlerAwareMojo {
45
46
47
48 protected static final String DEFAULT_CONTAINER = "tomcat6x";
49 private static final String DEFAULT_SERVER;
50 private static final String DEFAULT_PRODUCT_DATA_VERSION = "LATEST";
51 private static final String DEFAULT_PDK_VERSION = "0.4";
52 private static final String DEFAULT_WEB_CONSOLE_VERSION = "1.2.8";
53 private static final String DEFAULT_FASTDEV_VERSION = "1.9.1";
54 private static final String DEFAULT_DEV_TOOLBOX_VERSION = "1.1";
55 private static final String DEFAULT_PDE_VERSION = "1.2";
56
57
58
59
60 private static final int DEFAULT_PRODUCT_STARTUP_TIMEOUT = 1000 * 60 * 3;
61
62
63
64
65 private static final int DEFAULT_PRODUCT_SHUTDOWN_TIMEOUT = 1000 * 60 * 3;
66
67 static
68 {
69 String localHostName = null;
70 try
71 {
72 localHostName = InetAddress.getLocalHost().getHostName();
73 }
74 catch (UnknownHostException e)
75 {
76 localHostName = "localhost";
77 }
78 DEFAULT_SERVER = localHostName;
79 }
80
81
82
83
84 @MojoParameter(expression = "${container}", defaultValue = DEFAULT_CONTAINER)
85 protected String containerId;
86
87
88
89
90 @MojoParameter(expression = "${http.port}", defaultValue = "0")
91 private int httpPort;
92
93
94
95
96 @MojoParameter(expression = "${context.path}")
97 protected String contextPath;
98
99
100
101
102 @MojoParameter(expression = "${server}")
103 protected String server;
104
105
106
107
108 @MojoParameter(expression = "${product.version}")
109 private String productVersion;
110
111
112
113
114 @MojoParameter(expression = "${jvmargs}")
115 protected String jvmArgs;
116
117
118
119
120 @MojoParameter(expression = "${product.start.timeout}")
121 private int startupTimeout;
122
123
124
125
126 @MojoParameter(expression = "${product.stop.timeout}")
127 private int shutdownTimeout;
128
129
130
131
132
133
134 @MojoParameter
135 @Deprecated
136 protected Properties systemProperties = new Properties();
137
138
139
140
141
142
143 @MojoParameter
144 protected Map<String, Object> systemPropertyVariables = new HashMap<String, Object>();
145
146
147
148
149
150 @MojoParameter
151 protected File log4jProperties;
152
153
154
155
156
157 @Deprecated
158 @MojoParameter(expression = "${test.resources.version}")
159 private String testResourcesVersion;
160
161
162
163
164 @MojoParameter(expression = "${product.data.version}", defaultValue = DEFAULT_PRODUCT_DATA_VERSION)
165 private String productDataVersion;
166
167
168
169
170 @MojoParameter(expression = "${product.data.path}")
171 private String productDataPath;
172
173
174
175
176 @MojoParameter(expression = "${fastdev.enable}", defaultValue = "true")
177 protected boolean enableFastdev;
178
179
180
181
182 @MojoParameter(expression = "${fastdev.version}", defaultValue = DEFAULT_FASTDEV_VERSION)
183 protected String fastdevVersion;
184
185
186
187
188 @MojoParameter(expression = "${devtoolbox.enable}", defaultValue = "true")
189 protected boolean enableDevToolbox;
190
191
192
193
194 @MojoParameter(expression = "${devtoolbox.version}", defaultValue = DEFAULT_DEV_TOOLBOX_VERSION)
195 protected String devToolboxVersion;
196
197
198
199
200 @MojoParameter(expression = "${pde.enable}", defaultValue = "true")
201 protected boolean enablePde;
202
203
204
205
206 @MojoParameter(expression = "${pde.version}", defaultValue = DEFAULT_PDE_VERSION)
207 protected String pdeVersion;
208
209 @MojoParameter
210 private List<ProductArtifact> pluginArtifacts = new ArrayList<ProductArtifact>();
211
212
213
214 @MojoParameter
215 private List<ProductArtifact> libArtifacts = new ArrayList<ProductArtifact>();
216
217
218
219 @MojoParameter
220 private List<ProductArtifact> bundledArtifacts = new ArrayList<ProductArtifact>();
221
222
223
224
225
226 @Deprecated
227 @MojoParameter
228 private String salVersion;
229
230
231
232
233
234 @Deprecated
235 @MojoParameter(defaultValue = DEFAULT_PDK_VERSION)
236 private String pdkVersion;
237
238
239
240
241
242 @Deprecated
243 @MojoParameter
244 private String restVersion;
245
246
247
248
249
250
251 @Deprecated
252 @MojoParameter(defaultValue = DEFAULT_WEB_CONSOLE_VERSION)
253 private String webConsoleVersion;
254
255
256
257
258
259
260
261 @MojoParameter(expression = "${plugins}")
262 private String pluginArtifactsString;
263
264
265
266
267
268 @MojoParameter(expression = "${lib.plugins}")
269 private String libArtifactsString;
270
271
272
273
274
275 @MojoParameter(expression = "${bundled.plugins}")
276 private String bundledArtifactsString;
277
278
279
280
281 @MojoParameter(expression = "${project.build.directory}", required = true)
282 protected File targetDirectory;
283
284
285
286
287 @MojoParameter(expression = "${project.build.finalName}", required = true)
288 protected String finalName;
289
290
291
292
293 @MojoParameter (expression = "${install.plugin}", defaultValue = "true")
294 protected boolean installPlugin;
295
296
297
298
299
300
301
302 @MojoComponent
303 protected ArtifactResolver artifactResolver;
304
305
306
307
308
309
310 @MojoParameter(expression = "${localRepository}")
311 protected ArtifactRepository localRepository;
312
313
314
315
316
317 @MojoParameter(expression = "${project.remoteArtifactRepositories}")
318 protected List repositories;
319
320
321
322
323
324
325
326 @MojoComponent
327 protected ArtifactFactory artifactFactory;
328
329
330
331
332 @MojoParameter
333 protected List<Product> products = new ArrayList<Product>();
334
335
336
337
338
339 private Map<String, Product> productMap;
340
341
342
343
344 @MojoParameter
345 private String output;
346
347
348
349
350 @MojoParameter (expression = "${parallel}", defaultValue = "false")
351 protected boolean parallel;
352
353
354 protected Product createDefaultProductContext() throws MojoExecutionException
355 {
356 Product ctx = new Product();
357 ctx.setId(getProductId());
358 ctx.setContainerId(containerId);
359 ctx.setServer(server);
360 ctx.setContextPath(contextPath);
361 ctx.setJvmArgs(jvmArgs);
362 ctx.setStartupTimeout(startupTimeout);
363 ctx.setShutdownTimeout(shutdownTimeout);
364
365
366
367 Map<String, Object> properties = new HashMap<String, Object>(systemPropertyVariables);
368 properties.put("atlassian.sdk.version", getPluginInformation().getVersion());
369 setDefaultSystemProperty(properties, "atlassian.dev.mode", "true");
370 setDefaultSystemProperty(properties, "java.awt.headless", "true");
371 setDefaultSystemProperty(properties, "plugin.resource.directories", buildResourcesList());
372 setDefaultSystemProperty(properties, "plugin.root.directories", buildRootProperty());
373
374 ctx.setSystemPropertyVariables(properties);
375 ctx.setBundledArtifacts(bundledArtifacts);
376 ctx.setLibArtifacts(libArtifacts);
377 ctx.setPluginArtifacts(pluginArtifacts);
378 ctx.setLog4jProperties(log4jProperties);
379 ctx.setHttpPort(httpPort);
380
381 ctx.setVersion(productVersion);
382 ctx.setDataVersion(productDataVersion);
383 ctx.setDataPath(productDataPath);
384
385
386 ctx.setRestVersion(restVersion);
387 ctx.setSalVersion(salVersion);
388 ctx.setPdkVersion(pdkVersion);
389 ctx.setWebConsoleVersion(webConsoleVersion);
390
391 ctx.setEnableFastdev(enableFastdev);
392 ctx.setFastdevVersion(fastdevVersion);
393
394 ctx.setEnableDevToolbox(enableDevToolbox);
395 ctx.setDevToolboxVersion(devToolboxVersion);
396
397 ctx.setEnablePde(enablePde);
398 ctx.setPdeVersion(pdeVersion);
399
400 ctx.setHttpPort(httpPort);
401 return ctx;
402 }
403
404
405
406
407
408 private String buildResourcesList()
409 {
410
411
412 StringBuilder resourceProp = new StringBuilder();
413 MavenProject mavenProject = getMavenContext().getProject();
414 @SuppressWarnings("unchecked") List<Resource> resList = mavenProject.getResources();
415 for (int i = 0; i < resList.size(); i++) {
416 resourceProp.append(resList.get(i).getDirectory());
417 if (i + 1 != resList.size()) {
418 resourceProp.append(",");
419 }
420 }
421
422 if (ProjectUtils.shouldDeployTestJar(getMavenContext()))
423 {
424 @SuppressWarnings("unchecked") List<Resource> testResList = mavenProject.getTestResources();
425 for (int i = 0; i < testResList.size(); i++) {
426 if (i == 0 && resourceProp.length() > 0)
427 {
428 resourceProp.append(",");
429 }
430 resourceProp.append(testResList.get(i).getDirectory());
431 if (i + 1 != testResList.size()) {
432 resourceProp.append(",");
433 }
434 }
435 }
436 return resourceProp.toString();
437 }
438
439
440
441
442
443
444 private String buildRootProperty()
445 {
446 MavenProject mavenProject = getMavenContext().getProject();
447 return mavenProject.getBasedir().getPath();
448 }
449
450 private static void setDefaultSystemProperty(final Map<String,Object> props, final String key, final String value)
451 {
452 if (!props.containsKey(key))
453 {
454 props.put(key, System.getProperty(key, value));
455 }
456 }
457
458
459
460
461
462
463 protected void setDefaultValues(Product product, ProductHandler handler)
464 {
465 product.setInstanceId(getProductInstanceId(product));
466
467
468 StudioProductHandler.setDefaultValues(getMavenContext(), product);
469
470
471 String dversion = System.getProperty("product.data.version", product.getDataVersion());
472 String pversion = System.getProperty("product.version", product.getVersion());
473 String dpath = System.getProperty("product.data.path", product.getDataPath());
474
475 product.setDataPath(dpath);
476 product.setDataVersion(dversion);
477 product.setVersion(pversion);
478 product.setArtifactRetriever(new ArtifactRetriever(artifactResolver, artifactFactory, localRepository, repositories));
479
480 if (product.getContainerId() == null)
481 {
482 product.setContainerId(DEFAULT_CONTAINER);
483 }
484
485 if (product.getServer() == null)
486 {
487 product.setServer(DEFAULT_SERVER);
488 }
489
490 if (product.getDataVersion() == null)
491 {
492 product.setDataVersion(DEFAULT_PRODUCT_DATA_VERSION);
493 }
494
495 if (product.getPdkVersion() == null)
496 {
497 product.setPdkVersion(DEFAULT_PDK_VERSION);
498 }
499
500 if (product.getWebConsoleVersion() == null)
501 {
502 product.setWebConsoleVersion(DEFAULT_WEB_CONSOLE_VERSION);
503 }
504
505 if (product.isEnableFastdev() == null)
506 {
507 product.setEnableFastdev(true);
508 }
509
510 if (product.getFastdevVersion() == null)
511 {
512 product.setFastdevVersion(DEFAULT_FASTDEV_VERSION);
513 }
514
515 if (product.isEnableDevToolbox() == null)
516 {
517 product.setEnableDevToolbox(true);
518 }
519
520 if (product.getDevToolboxVersion() == null)
521 {
522 product.setDevToolboxVersion(DEFAULT_DEV_TOOLBOX_VERSION);
523 }
524
525 if (product.getPdeVersion() == null)
526 {
527 product.setPdeVersion(DEFAULT_PDE_VERSION);
528 }
529
530 if (product.getOutput() == null)
531 {
532 product.setOutput(output);
533 }
534
535 if (product.getStartupTimeout() <= 0)
536 {
537 product.setStartupTimeout(DEFAULT_PRODUCT_STARTUP_TIMEOUT);
538 }
539
540 if (product.getShutdownTimeout() <= 0)
541 {
542 product.setShutdownTimeout(DEFAULT_PRODUCT_SHUTDOWN_TIMEOUT);
543 }
544
545 if (product.getHttpPort() == 0)
546 {
547 product.setHttpPort(handler.getDefaultHttpPort());
548 }
549
550 if (product.getVersion() == null)
551 {
552 product.setVersion("RELEASE");
553 }
554
555 if (product.getContextPath() == null)
556 {
557 product.setContextPath("/" + handler.getId());
558 }
559 }
560
561 private List<ProductArtifact> stringToArtifactList(String val, List<ProductArtifact> artifacts)
562 {
563 if (val == null || val.trim().length() == 0)
564 {
565 return artifacts;
566 }
567
568 for (String ptn : val.split(","))
569 {
570 String[] items = ptn.split(":");
571 if (items.length < 2 || items.length > 3)
572 {
573 throw new IllegalArgumentException("Invalid artifact pattern: " + ptn);
574 }
575 String groupId = items[0];
576 String artifactId = items[1];
577 String version = (items.length == 3 ? items[2] : "LATEST");
578 artifacts.add(new ProductArtifact(groupId, artifactId, version));
579 }
580 return artifacts;
581 }
582
583 @Override
584 public final void execute() throws MojoExecutionException, MojoFailureException
585 {
586 stringToArtifactList(pluginArtifactsString, pluginArtifacts);
587 stringToArtifactList(libArtifactsString, libArtifacts);
588 stringToArtifactList(bundledArtifactsString, bundledArtifacts);
589 systemPropertyVariables.putAll((Map) systemProperties);
590
591 detectDeprecatedVersionOverrides();
592
593 doExecute();
594 }
595
596 private void detectDeprecatedVersionOverrides()
597 {
598 Properties props = getMavenContext().getProject().getProperties();
599 for (String deprecatedProperty : new String[] {"sal.version", "rest.version", "web.console.version", "pdk.version"})
600 {
601 if (props.containsKey(deprecatedProperty))
602 {
603 getLog().warn("The property '" + deprecatedProperty + "' is no longer usable to override the related bundled plugin." +
604 " Use <pluginArtifacts> or <libArtifacts> to explicitly override bundled plugins and libraries, respectively.");
605 }
606 }
607 }
608
609
610
611
612
613
614
615
616 Map<String, Product> createProductContexts() throws MojoExecutionException
617 {
618 Map<String, Product> productMap = Maps.newHashMap();
619 MavenContext mavenContext = getMavenContext();
620 MavenGoals goals = getMavenGoals();
621
622
623 makeProductsInheritDefaultConfiguration(products, productMap);
624
625 for (Product ctx : Lists.newArrayList(productMap.values()))
626 {
627 ProductHandler handler = ProductHandlerFactory.create(ctx.getId(), mavenContext, goals);
628 setDefaultValues(ctx, handler);
629
630
631 for (String instanceId : StudioProductHandler.getDependantInstances(ctx))
632 {
633 if (!productMap.containsKey(instanceId))
634 {
635 ProductHandler dependantHandler = createProductHandler(instanceId);
636 productMap.put(instanceId, createProductContext(instanceId, instanceId, dependantHandler));
637 }
638 }
639 }
640
641
642 StudioProductHandler studioProductHandler = (StudioProductHandler) ProductHandlerFactory.create(ProductHandlerFactory.STUDIO, mavenContext, goals);
643 studioProductHandler.configureStudioProducts(productMap);
644
645 return productMap;
646 }
647
648
649
650
651 protected Map<String, Product> getProductContexts() throws MojoExecutionException
652 {
653 if (productMap == null)
654 {
655 productMap = createProductContexts();
656 }
657 return productMap;
658 }
659
660
661
662
663
664
665
666
667 void makeProductsInheritDefaultConfiguration(List<Product> products, Map<String, Product> productMap) throws MojoExecutionException
668 {
669 Product defaultProduct = createDefaultProductContext();
670 productMap.put(getProductId(), defaultProduct);
671 if (!products.isEmpty())
672 {
673 for (Product product : products)
674 {
675 Product processedProduct = product.merge(defaultProduct);
676 if (ProductHandlerFactory.STUDIO_CROWD.equals(processedProduct.getId()))
677 {
678
679 processedProduct.getSystemPropertyVariables().put("atlassian.dev.mode", "false");
680 }
681 String instanceId = getProductInstanceId(processedProduct);
682 productMap.put(instanceId, processedProduct);
683 }
684 }
685 }
686
687 private String getProductInstanceId(Product processedProduct)
688 {
689 return processedProduct.getInstanceId() == null ? processedProduct.getId() : processedProduct.getInstanceId();
690 }
691
692
693 private Product createProductContext(String productNickname, String instanceId, ProductHandler handler) throws MojoExecutionException
694 {
695 getLog().info(String.format("Studio (instanceId=%s): No product with name %s is defined in the pom. Using a default product.", instanceId, productNickname));
696 Product product;
697 product = createDefaultProductContext();
698 product.setId(productNickname);
699 product.setInstanceId(instanceId);
700 setDefaultValues(product, handler);
701 if (ProductHandlerFactory.STUDIO_CROWD.equals(product.getId()))
702 {
703
704 product.getSystemPropertyVariables().put("atlassian.dev.mode", "false");
705 }
706 return product;
707 }
708
709
710
711
712
713 protected void stopProducts(List<ProductExecution> productExecutions) throws MojoExecutionException
714 {
715 ExecutorService executor = Executors.newFixedThreadPool(productExecutions.size());
716 try
717 {
718 long before = System.nanoTime();
719 for (final ProductExecution execution : Iterables.reverse(productExecutions))
720 {
721 final Product product = execution.getProduct();
722 final ProductHandler productHandler = execution.getProductHandler();
723
724 Future<?> task = executor.submit(new Runnable()
725 {
726 @Override
727 public void run()
728 {
729 getLog().info(product.getInstanceId() + ": Shutting down");
730 try
731 {
732 productHandler.stop(product);
733 }
734 catch (MojoExecutionException e)
735 {
736 getLog().error("Exception while trying to stop " + product.getInstanceId(), e);
737 }
738 }
739 });
740
741 try
742 {
743 task.get(product.getShutdownTimeout(), TimeUnit.MILLISECONDS);
744 }
745 catch (TimeoutException e)
746 {
747 getLog().info(product.getInstanceId() + " shutdown: Didn't return in time");
748 task.cancel(true);
749 }
750 }
751 long after = System.nanoTime();
752 getLog().info("amps:stop in " + TimeUnit.NANOSECONDS.toSeconds(after - before) + "s");
753 }
754 catch (InterruptedException e1)
755 {
756 Thread.currentThread().interrupt();
757 }
758 catch (ExecutionException e)
759 {
760 throw new MojoExecutionException("Exception while stopping the products", e);
761 }
762
763
764
765 if (parallel)
766 {
767 waitForProducts(productExecutions, false);
768 }
769 }
770
771
772
773
774
775
776 protected void waitForProducts(List<ProductExecution> productExecutions, boolean startingUp) throws MojoExecutionException
777 {
778 for (ProductExecution productExecution : productExecutions)
779 {
780 pingRepeatedly(productExecution.getProduct(), startingUp);
781 }
782 }
783
784
785
786
787
788
789 private void pingRepeatedly(Product product, boolean startingUp) throws MojoExecutionException
790 {
791 if (product.getHttpPort() != 0)
792 {
793 String url = "http://" + product.getServer() + ":" + product.getHttpPort();
794 if (StringUtils.isNotBlank(product.getContextPath()))
795 {
796 url = url + product.getContextPath();
797 }
798
799 int timeout = startingUp ? product.getStartupTimeout() : product.getShutdownTimeout();
800 final long end = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeout);
801 boolean interrupted = false;
802 boolean success = false;
803 String lastMessage = "";
804
805
806 while (!success && !interrupted && System.nanoTime() < end)
807 {
808 HttpURLConnection connection = null;
809 try
810 {
811 URL urlToPing = new URL(url);
812 connection = (HttpURLConnection) urlToPing.openConnection();
813 int response = connection.getResponseCode();
814
815 lastMessage = "Last response code is " + response;
816 if (startingUp)
817 {
818 success = response < 400;
819 }
820 else
821 {
822 success = response >= 400;
823 }
824 }
825 catch (IOException e)
826 {
827 lastMessage = e.getMessage();
828 success = !startingUp;
829 }
830 finally
831 {
832 if (connection != null)
833 {
834 try
835 {
836 connection.getInputStream().close();
837 }
838 catch (IOException e)
839 {
840
841 }
842 }
843 }
844
845 if (!success)
846 {
847 getLog().info("Waiting for " + url + (startingUp ? "" : " to stop"));
848 try
849 {
850 Thread.sleep(1000);
851 }
852 catch (InterruptedException e)
853 {
854 Thread.currentThread().interrupt();
855 interrupted = true;
856 break;
857 }
858 }
859 }
860
861 if (!success)
862 {
863 throw new MojoExecutionException(String.format("The product %s didn't %s after %ds at %s. %s",
864 product.getInstanceId(), startingUp ? "start" : "stop", TimeUnit.MILLISECONDS.toSeconds(timeout), url, lastMessage));
865 }
866 }
867 }
868
869
870
871
872 private Iterable<ProductExecution> getStudioExecutions(final List<ProductExecution> productExecutions)
873 {
874 return Iterables.filter(productExecutions, new Predicate<ProductExecution>(){
875
876 @Override
877 public boolean apply(ProductExecution input)
878 {
879 return input.getProductHandler() instanceof StudioProductHandler;
880 }});
881 }
882
883
884
885
886
887
888
889
890
891
892
893
894 protected List<ProductExecution> includeStudioDependentProducts(final List<ProductExecution> productExecutions, final MavenGoals goals)
895 throws MojoExecutionException
896 {
897
898 Iterable<ProductExecution> studioExecutions = getStudioExecutions(productExecutions);
899 if (Iterables.isEmpty(studioExecutions))
900 {
901 return productExecutions;
902 }
903
904
905 List<ProductExecution> productExecutionsIncludingStudio = Lists.newArrayList(productExecutions);
906 Map<String, Product> allContexts = getProductContexts();
907 for(ProductExecution execution : studioExecutions)
908 {
909 for (String dependantProduct : StudioProductHandler.getDependantInstances(execution.getProduct()))
910 {
911 Product product = allContexts.get(dependantProduct);
912 productExecutionsIncludingStudio.add(toProductExecution(product));
913 }
914 }
915
916 return productExecutionsIncludingStudio;
917 }
918
919 protected ProductExecution toProductExecution(Product product)
920 {
921 return new ProductExecution(product, createProductHandler(product.getId()));
922 }
923
924 protected abstract void doExecute() throws MojoExecutionException, MojoFailureException;
925
926 protected void setParallelMode(List<ProductExecution> executions)
927 {
928
929 for (ProductExecution execution : executions)
930 {
931 Product product = execution.getProduct();
932 if (parallel)
933 {
934 if (product.getSynchronousStartup() == null)
935 {
936 product.setSynchronousStartup(Boolean.FALSE);
937 }
938 }
939 else
940 {
941 product.setSynchronousStartup(Boolean.TRUE);
942 }
943 }
944 }
945 }