1 package org.codehaus.mojo.appassembler;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 import java.io.File;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.StringTokenizer;
37
38 import org.apache.maven.artifact.Artifact;
39 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
40 import org.apache.maven.plugin.MojoExecutionException;
41 import org.apache.maven.plugin.MojoFailureException;
42 import org.apache.maven.plugins.annotations.LifecyclePhase;
43 import org.apache.maven.plugins.annotations.Mojo;
44 import org.apache.maven.plugins.annotations.Parameter;
45 import org.apache.maven.plugins.annotations.ResolutionScope;
46 import org.codehaus.mojo.appassembler.daemon.DaemonGenerationRequest;
47 import org.codehaus.mojo.appassembler.daemon.DaemonGeneratorException;
48 import org.codehaus.mojo.appassembler.daemon.script.Platform;
49 import org.codehaus.mojo.appassembler.model.Classpath;
50 import org.codehaus.mojo.appassembler.model.Dependency;
51 import org.codehaus.mojo.appassembler.model.Directory;
52 import org.codehaus.mojo.appassembler.model.JvmSettings;
53 import org.codehaus.mojo.appassembler.util.DependencyFactory;
54 import org.codehaus.plexus.util.StringUtils;
55
56
57
58
59
60
61
62
63
64 @Mojo( name = "assemble", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true )
65 public class AssembleMojo
66 extends AbstractScriptGeneratorMojo
67 {
68
69
70
71
72
73
74
75 @Parameter( property = "assembleDirectory", defaultValue = "${project.build.directory}/appassembler", required = true )
76 private File assembleDirectory;
77
78
79
80
81
82
83
84
85
86
87
88
89
90 @Parameter
91 protected Map<String, String> binFileExtensions;
92
93
94
95
96
97
98 @Parameter( defaultValue = "bin" )
99 private String binFolder;
100
101
102
103
104
105
106
107
108
109
110
111 @Parameter
112 private String extraJvmArguments;
113
114
115
116
117
118 @Parameter( defaultValue = "true" )
119 private boolean includeConfigurationDirectoryInClasspath;
120
121
122
123
124
125 @Parameter
126 private Set<String> platforms;
127
128
129
130
131 @Parameter( required = true )
132 private Set<Program> programs;
133
134
135
136
137
138
139
140
141 @Parameter( defaultValue = "false" )
142 private boolean projectArtifactFirstInClassPath;
143
144
145
146
147 @Parameter( defaultValue = "repo" )
148 private String repositoryName;
149
150
151
152
153
154 @Parameter( defaultValue = "true" )
155 private boolean showConsoleWindow;
156
157
158
159
160
161
162
163 @Parameter( defaultValue = "false" )
164 private boolean useAllProjectDependencies;
165
166
167
168
169
170
171
172
173
174 private static final Set<String> VALID_PLATFORMS =
175 Collections.unmodifiableSet( new HashSet<String>( Arrays.asList( new String[] { "unix", "windows" } ) ) );
176
177
178
179
180
181 private void validate( Set<String> defaultPlatforms )
182 throws MojoFailureException, MojoExecutionException
183 {
184
185
186
187
188 ArrayList<String> programNames = new ArrayList<String>();
189
190 for ( Program program : programs )
191 {
192 if ( program.getName() != null )
193 {
194 program.setId( program.getName() );
195 getLog().warn( "The usage of program name (" + program.getName()
196 + ") is deprecated. Please use program.id instead." );
197 }
198
199 if ( program.getMainClass() == null || program.getMainClass().trim().equals( "" ) )
200 {
201 throw new MojoFailureException( "Missing main class in Program configuration" );
202 }
203
204
205
206 if ( !programNames.contains( program.getId() ) )
207 {
208 programNames.add( program.getId() );
209 }
210 else
211 {
212 throw new MojoFailureException( "The program id: " + program.getId() + " exists more than once!" );
213 }
214
215
216 program.setPlatforms( validatePlatforms( program.getPlatforms(), defaultPlatforms ) );
217 }
218
219 }
220
221
222
223
224
225 public void checkDeprecatedParameterAndFailIfOneOfThemIsUsed()
226 throws MojoExecutionException
227 {
228 }
229
230
231
232
233
234
235
236
237 public void execute()
238 throws MojoExecutionException, MojoFailureException
239 {
240 Set<String> defaultPlatforms = validatePlatforms( platforms, VALID_PLATFORMS );
241
242 checkDeprecatedParameterAndFailIfOneOfThemIsUsed();
243
244
245 validate( defaultPlatforms );
246
247 if ( useWildcardClassPath && !repositoryLayout.equalsIgnoreCase( "flat" ) )
248 {
249 throw new MojoExecutionException( "useWildcardClassPath works only in "
250 + "combination with repositoryLayout flat." );
251 }
252
253
254 setBinFileExtensions();
255
256 ArtifactRepositoryLayout artifactRepositoryLayout = getArtifactRepositoryLayout();
257
258 if ( useAllProjectDependencies )
259 {
260
261
262 Set dependencyArtifacts = mavenProject.getDependencyArtifacts();
263 artifacts = new ArrayList<Artifact>();
264 for ( Iterator it = dependencyArtifacts.iterator(); it.hasNext(); )
265 {
266 Artifact artifact = (Artifact) it.next();
267 artifacts.add( artifact );
268 }
269 }
270
271
272
273
274 super.installDependencies( assembleDirectory.getAbsolutePath(), repositoryName );
275
276
277
278
279
280 setUpWorkingArea();
281
282
283
284
285
286 for ( Program program : programs )
287 {
288 if ( program.getName() != null )
289 {
290 program.setId( program.getName() );
291 }
292
293 Set<String> validatedPlatforms = validatePlatforms( program.getPlatforms(), defaultPlatforms );
294
295 for ( String platform : validatedPlatforms )
296 {
297
298
299 org.codehaus.mojo.appassembler.model.Daemon daemon =
300 programToDaemon( program, artifactRepositoryLayout );
301 DaemonGenerationRequest request =
302 new DaemonGenerationRequest( daemon, mavenProject, localRepository, assembleDirectory, binFolder );
303 request.setStubDaemon( request.getDaemon() );
304
305 request.setPlatform( platform );
306
307 try
308 {
309 daemonGeneratorService.generateDaemon( request );
310 }
311 catch ( DaemonGeneratorException e )
312 {
313 throw new MojoExecutionException( "Error while generating script for the program '"
314 + program.getId() + "' for the platform '" + platform + "': " + e.getMessage(), e );
315 }
316 }
317 }
318
319
320
321
322
323 if ( this.preAssembleDirectory != null && this.preAssembleDirectory.isDirectory() )
324 {
325 doCopyPreAssembleDirectory( assembleDirectory.getAbsolutePath() );
326 }
327
328 if ( this.copyConfigurationDirectory && configurationSourceDirectory.isDirectory() )
329 {
330 doCopyConfigurationDirectory( assembleDirectory.getAbsolutePath() );
331 }
332
333
334
335
336
337 doCreateExtraDirectories( assembleDirectory );
338 }
339
340 private org.codehaus.mojo.appassembler.model.Daemon programToDaemon( Program program,
341 ArtifactRepositoryLayout artifactRepositoryLayout )
342 {
343 org.codehaus.mojo.appassembler.model.Daemon daemon = new org.codehaus.mojo.appassembler.model.Daemon();
344
345 if ( program.getName() == null )
346 {
347 daemon.setId( program.getId() );
348 }
349 else
350 {
351 daemon.setId( program.getName() );
352 }
353 daemon.setMainClass( program.getMainClass() );
354 daemon.setShowConsoleWindow( showConsoleWindow );
355 daemon.setCommandLineArguments( program.getCommandLineArguments() );
356
357 if ( program.getLicenseHeaderFile() != null )
358 {
359 getLog().debug( "Using the program specific license header. :" + program.getLicenseHeaderFile() );
360 daemon.setLicenseHeaderFile( program.getLicenseHeaderFile().getPath() );
361 }
362 else
363 {
364 getLog().debug( "Using the global defined license header. :" + licenseHeaderFile );
365
366 if ( licenseHeaderFile != null )
367 {
368 daemon.setLicenseHeaderFile( this.licenseHeaderFile.getAbsolutePath() );
369 }
370 else
371 {
372 daemon.setLicenseHeaderFile( null );
373 }
374 }
375
376 List<Directory> directories = new ArrayList<Directory>();
377
378 if ( includeConfigurationDirectoryInClasspath )
379 {
380 Directory directory = new Directory();
381 directory.setRelativePath( configurationDirectory );
382 directories.add( directory );
383 }
384
385 if ( daemon.getClasspath() == null )
386 {
387 daemon.setClasspath( new Classpath() );
388 }
389
390 daemon.getClasspath().setDirectories( directories );
391
392 daemon.setRepositoryName( repositoryName );
393
394 daemon.setEndorsedDir( endorsedDir );
395
396 List<Dependency> dependencies = new ArrayList<Dependency>();
397
398
399
400
401 if ( useWildcardClassPath )
402 {
403 Dependency dependency = new Dependency();
404 dependency.setGroupId( "" );
405 dependency.setArtifactId( "" );
406 dependency.setVersion( "" );
407 dependency.setRelativePath( "*" );
408 dependencies.add( dependency );
409 }
410 else
411 {
412 List<Artifact> classPathArtifacts = new ArrayList<Artifact>();
413
414 if ( projectArtifactFirstInClassPath )
415 {
416 classPathArtifacts.add( projectArtifact );
417 classPathArtifacts.addAll( artifacts );
418 }
419 else
420 {
421 classPathArtifacts.addAll( artifacts );
422 classPathArtifacts.add( projectArtifact );
423 }
424
425 for ( Artifact artifact : classPathArtifacts )
426 {
427 dependencies.add( DependencyFactory.create( artifact, artifactRepositoryLayout,
428 this.useTimestampInSnapshotFileName, outputFileNameMapping ) );
429 }
430
431 }
432
433 daemon.getClasspath().setDependencies( dependencies );
434
435 daemon.setJvmSettings( convertToJvmSettingsWithDefaultHandling( program ) );
436
437 daemon.setEnvironmentSetupFileName( this.environmentSetupFileName );
438
439 if ( this.unixScriptTemplate != null )
440 {
441 daemon.setUnixScriptTemplate( unixScriptTemplate );
442 }
443 if ( this.windowsScriptTemplate != null )
444 {
445 daemon.setWindowsScriptTemplate( windowsScriptTemplate );
446 }
447
448 return daemon;
449 }
450
451 private JvmSettings convertToJvmSettingsWithDefaultHandling( Program program )
452 {
453 JvmSettings jvmSettings = new JvmSettings();
454
455 if ( program.getJvmSettings() != null )
456 {
457
458
459 jvmSettings = program.getJvmSettings();
460 }
461 else
462 {
463
464 if ( StringUtils.isNotBlank( this.extraJvmArguments ) )
465 {
466 jvmSettings.setExtraArguments( parseTokens( this.extraJvmArguments ) );
467 }
468 }
469
470 return jvmSettings;
471 }
472
473
474
475
476
477 private void setUpWorkingArea()
478 throws MojoFailureException
479 {
480
481 File binDir = new File( assembleDirectory.getAbsolutePath(), binFolder.toString() );
482
483 if ( !binDir.exists() )
484 {
485
486 boolean success = binDir.mkdirs();
487
488 if ( !success )
489 {
490 throw new MojoFailureException( "Failed to create directory for bin files." );
491 }
492 }
493 }
494
495 private Set<String> validatePlatforms( Set<String> platformsToValidate, Set<String> defaultPlatforms )
496 throws MojoFailureException
497 {
498 if ( platformsToValidate == null )
499 {
500 return defaultPlatforms;
501 }
502
503 if ( platformsToValidate.size() == 1 && platformsToValidate.iterator().next().equals( "all" ) )
504 {
505 return VALID_PLATFORMS;
506 }
507
508 if ( !VALID_PLATFORMS.containsAll( platformsToValidate ) )
509 {
510 throw new MojoFailureException( "Non-valid default platform declared, supported types are: "
511 + VALID_PLATFORMS );
512 }
513
514 return platformsToValidate;
515 }
516
517
518
519
520
521
522
523 public static List<String> parseTokens( String arg )
524 {
525 List<String> extraJvmArguments = new ArrayList<String>();
526
527 if ( StringUtils.isEmpty( arg ) )
528 {
529 return extraJvmArguments;
530 }
531
532 StringTokenizer tokenizer = new StringTokenizer( arg );
533
534 String argument = null;
535
536 while ( tokenizer.hasMoreTokens() )
537 {
538 String token = tokenizer.nextToken();
539
540 if ( argument != null )
541 {
542 if ( token.length() == 0 )
543 {
544
545 continue;
546 }
547
548 int length = token.length();
549
550 if ( token.charAt( length - 1 ) == '\"' )
551 {
552 extraJvmArguments.add( argument + " " + token.substring( 0, length - 1 ) );
553 argument = null;
554 }
555 else
556 {
557 argument += " " + token;
558 }
559 }
560 else
561 {
562
563 if ( token.charAt( 0 ) == '\"' )
564 {
565 argument = token.substring( 1 );
566 }
567 else
568 {
569 extraJvmArguments.add( token );
570 }
571 }
572 }
573
574 return extraJvmArguments;
575 }
576
577
578
579
580
581 private void setBinFileExtensions()
582 throws MojoFailureException
583 {
584 if ( binFileExtensions != null )
585 {
586 for ( String platformName : binFileExtensions.keySet() )
587 {
588 if ( !VALID_PLATFORMS.contains( platformName ) )
589 {
590 getLog().warn( "Bin file extension configured for a non-valid platform (" + platformName
591 + "), supported platforms are: " + VALID_PLATFORMS );
592 }
593 else
594 {
595 try
596 {
597 Platform platform = Platform.getInstance( platformName );
598 platform.setBinFileExtension( binFileExtensions.get( platformName ) );
599 }
600 catch ( DaemonGeneratorException e )
601 {
602 getLog().warn( "Unable to set the bin file extension for " + platformName, e );
603 }
604 }
605 }
606 }
607 }
608
609 }