1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package no.sesat.mojo;
20
21 import java.io.BufferedReader;
22 import java.io.BufferedWriter;
23 import java.io.File;
24 import java.io.FileReader;
25 import java.io.FileWriter;
26 import java.io.IOException;
27 import java.io.StringReader;
28 import java.io.StringWriter;
29 import java.text.SimpleDateFormat;
30 import java.util.ArrayList;
31 import java.util.Calendar;
32 import java.util.Date;
33 import java.util.List;
34 import org.apache.maven.artifact.Artifact;
35 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
36 import org.apache.maven.artifact.resolver.ArtifactCollector;
37 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
38 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
39 import org.apache.maven.model.Profile;
40 import org.apache.maven.plugin.MojoExecutionException;
41 import org.apache.maven.plugin.dependency.fromConfiguration.CopyMojo;
42 import org.apache.maven.project.MavenProject;
43 import org.apache.maven.scm.ScmException;
44 import org.apache.maven.scm.ScmFileSet;
45 import org.apache.maven.scm.command.status.StatusScmResult;
46 import org.apache.maven.scm.command.tag.TagScmResult;
47 import org.apache.maven.scm.manager.ScmManager;
48 import org.apache.maven.wagon.ConnectionException;
49 import org.apache.maven.wagon.ResourceDoesNotExistException;
50 import org.apache.maven.wagon.TransferFailedException;
51 import org.apache.maven.wagon.Wagon;
52 import org.apache.maven.wagon.authentication.AuthenticationException;
53 import org.apache.maven.wagon.authorization.AuthorizationException;
54 import org.apache.maven.wagon.repository.Repository;
55 import org.apache.maven.wagon.repository.RepositoryPermissions;
56 import org.codehaus.plexus.PlexusConstants;
57 import org.codehaus.plexus.PlexusContainer;
58 import org.codehaus.plexus.archiver.manager.ArchiverManager;
59 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
60 import org.codehaus.plexus.context.Context;
61 import org.codehaus.plexus.context.ContextException;
62 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 public final class DeploySesatWarfilesMojo extends CopyMojo implements Contextualizable{
82
83
84
85 private static final String[] ENVIRONMENTS = new String[]{"alpha","nuclei","beta","electron","gamma","production"};
86
87 private static final String TAG_ON_DEPLOY = "tag.on.deploy";
88
89 private static final String DRY_RUN = "sesat.mojo.dryRun";
90
91
92
93 private PlexusContainer container;
94
95 private String profile = null;
96 private Date now = Calendar.getInstance().getTime();
97 private MavenProject pomProject;
98
99
100
101
102
103
104
105
106
107
108 private boolean stripVersion = false;
109
110
111
112
113
114
115
116
117
118 private File outputDirectory;
119
120
121
122
123
124
125
126
127 private boolean overWriteReleases;
128
129
130
131
132
133
134
135
136 private boolean overWriteSnapshots;
137
138
139
140
141
142
143
144
145 private boolean overWriteIfNewer;
146
147
148
149
150
151
152
153
154
155
156 private ArrayList artifactItems;
157
158
159
160
161
162
163
164
165 private org.apache.maven.artifact.factory.ArtifactFactory factory;
166
167
168
169
170
171
172
173
174 private org.apache.maven.artifact.resolver.ArtifactResolver resolver;
175
176
177
178
179
180
181
182
183 private ArtifactCollector artifactCollector;
184
185
186
187
188
189
190
191 private ArtifactMetadataSource artifactMetadataSource;
192
193
194
195
196
197
198
199
200 private org.apache.maven.artifact.repository.ArtifactRepository local;
201
202
203
204
205
206
207
208
209 private java.util.List remoteRepos;
210
211
212
213
214
215
216
217
218 private ArchiverManager archiverManager;
219
220
221
222
223
224
225
226
227 private MavenProject project;
228
229
230
231
232
233
234
235
236 private List reactorProjects;
237
238
239
240
241
242
243
244
245 private boolean silent;
246
247
248
249
250
251
252
253
254
255 private boolean outputAbsoluteArtifactFilename;
256
257
258
259
260
261
262
263
264 public DeploySesatWarfilesMojo() {
265 }
266
267
268
269
270
271
272
273 public void contextualize(final Context context) throws ContextException {
274
275 container = (PlexusContainer) context.get(PlexusConstants.PLEXUS_KEY);
276 }
277
278
279
280
281
282 public void execute() throws MojoExecutionException{
283
284
285 if("war".equals(project.getPackaging())){
286
287 pushFields();
288
289 final Wagon wagon = getWagon();
290 if(null != wagon){
291
292 try{
293 executeServerDeploy(wagon);
294
295 }finally{
296 try{
297 wagon.disconnect();
298
299 }catch(ConnectionException ex){
300 getLog().error(ex);
301 throw new MojoExecutionException("repository wagon not disconnected", ex);
302 }
303 }
304
305 }else{
306
307 executeLocalDeploy();
308 }
309 }
310
311 }
312
313
314
315
316
317
318
319 private void executeServerDeploy(final Wagon wagon) throws MojoExecutionException{
320
321
322 try{
323 if(ensureNoLocalModifications()){
324
325 @SuppressWarnings("unchecked")
326 final List<ArtifactItem> theArtifactItems = getProcessedArtifactItems(stripVersion);
327
328 for(ArtifactItem item : theArtifactItems){
329
330 final Artifact artifact = factory.createArtifactWithClassifier(
331 item.getGroupId(),
332 item.getArtifactId(),
333 item.getVersion(),
334 item.getType(),
335 profile);
336
337 resolver.resolve(artifact, getRemoteRepos(), getLocal());
338
339 final String sesamSite = project.getProperties().getProperty("sesam.site");
340 final String destName = null != sesamSite
341 ? sesamSite
342 : project.getBuild().getFinalName();
343
344
345 if(Boolean.parseBoolean(project.getProperties().getProperty(TAG_ON_DEPLOY))
346 && !Boolean.getBoolean(DRY_RUN)){
347
348 tagDeploy();
349 }
350
351
352 getLog().info("Uploading " + artifact.getFile().getAbsolutePath()
353 + " to " + wagon.getRepository().getUrl() + '/' + destName + ".war");
354
355 if(!Boolean.getBoolean(DRY_RUN)){
356 wagon.put(artifact.getFile(), destName + ".war");
357 }
358
359
360 getLog().info("Updating " + wagon.getRepository().getUrl() + "/version.txt");
361
362 if(Boolean.getBoolean(DRY_RUN)){
363
364 final StringWriter sb = new StringWriter();
365 final BufferedWriter w = new BufferedWriter(sb);
366 updateArtifactEntry(new BufferedReader(new StringReader("")), w);
367 w.flush();
368 getLog().info("version.txt entry will be \n" + sb.toString());
369
370 }else{
371
372 updateVersionFile(wagon);
373 }
374 }
375 }
376
377 }catch(TransferFailedException ex){
378 getLog().error(ex);
379 throw new MojoExecutionException("transfer failed", ex);
380 }catch(ResourceDoesNotExistException ex){
381 getLog().error(ex);
382 throw new MojoExecutionException("resource does not exist", ex);
383 }catch(AuthorizationException ex){
384 getLog().error(ex);
385 throw new MojoExecutionException("authorisation exception", ex);
386 }catch(ArtifactNotFoundException ex){
387 getLog().error(ex);
388 throw new MojoExecutionException("artifact not found", ex);
389 }catch(ArtifactResolutionException ex){
390 getLog().error(ex);
391 throw new MojoExecutionException("artifact resolution exception", ex);
392 }catch(ScmException ex){
393 getLog().error(ex);
394 throw new MojoExecutionException("scm exception", ex);
395 }catch(ComponentLookupException ex){
396 getLog().error(ex);
397 throw new MojoExecutionException("failed to lookup ScmManager", ex);
398 }catch(IOException ex){
399 getLog().error(ex);
400 throw new MojoExecutionException("IOException", ex);
401 }
402
403 }
404
405 private void executeLocalDeploy() throws MojoExecutionException{
406
407
408
409
410
411 if(getOutputDirectory().exists()){
412
413
414 if(getOutputDirectory().canWrite()){
415
416 super.execute();
417
418 }else{
419
420
421 getLog().error(getOutputDirectory().getAbsolutePath() + " can not be written to.");
422 }
423 }else{
424
425
426 getLog().error(getOutputDirectory().getAbsolutePath() + " does not exist.");
427 final String catalinaBase = System.getProperty("env.CATALINA_BASE");
428 if(null == catalinaBase || 0 == catalinaBase.length()){
429 getLog().info("Define system variable CATALINA_BASE to enable automatic deployment.");
430 }
431 }
432
433 }
434
435 private void pushFields(){
436 setArchiverManager(archiverManager);
437 setArtifactCollector(artifactCollector);
438 setArtifactMetadataSource(artifactMetadataSource);
439 setFactory(factory);
440 setResolver(resolver);
441 }
442
443 private void loadPomProject(){
444
445 if(null == pomProject){
446 pomProject = project;
447 do{
448 pomProject = pomProject.getParent();
449 }while(!"pom".equals(pomProject.getPackaging()));
450 }
451 }
452
453
454
455
456
457
458 private Wagon getWagon() throws MojoExecutionException {
459
460 loadProfile();
461
462 try {
463
464 Wagon wagon = null;
465
466 if(null != profile){
467
468 final String serverDeployLocation = project.getProperties().getProperty("serverDeployLocation");
469
470 final String protocol = serverDeployLocation.substring(0, serverDeployLocation.indexOf(':'));
471
472 final Repository wagonRepository = new Repository();
473
474 wagonRepository.setUrl(serverDeployLocation);
475
476 final RepositoryPermissions permissions = new RepositoryPermissions();
477 permissions.setFileMode("g+w");
478 wagonRepository.setPermissions(permissions);
479
480 wagon = (Wagon) container.lookup(Wagon.ROLE, protocol);
481 wagon.connect(wagonRepository);
482
483 }
484 return wagon;
485
486 }catch (ConnectionException ex) {
487 getLog().error(ex);
488 throw new MojoExecutionException("repository wagon not connected", ex);
489 }catch (AuthenticationException ex) {
490 getLog().error(ex);
491 throw new MojoExecutionException("repository wagon not authenticated", ex);
492 }catch (ComponentLookupException ex) {
493 getLog().error(ex);
494 throw new MojoExecutionException("repository wagon not found", ex);
495 }
496
497 }
498
499 private void loadProfile(){
500
501 if(null == profile){
502
503 @SuppressWarnings("unchecked")
504 final List<Profile> profiles = project.getActiveProfiles();
505
506 for(String entry : ENVIRONMENTS){
507 for(Profile p : profiles){
508 if(null != p && null != p.getId() && p.getId().equals(entry)){
509 profile = p.getId();
510 return;
511 }
512 }
513 }
514 }
515 }
516
517 private void tagDeploy() throws ComponentLookupException, ScmException{
518
519 final ScmManager scmManager = (ScmManager) container.lookup(ScmManager.ROLE);
520 final String date = new SimpleDateFormat("yyyyMMddHHmm").format(now);
521
522 loadPomProject();
523
524 final TagScmResult result = scmManager.tag(
525 scmManager.makeScmRepository(project.getScm().getDeveloperConnection()),
526 new ScmFileSet(pomProject.getBasedir()),
527 profile + "-deployments/" + date + "-" + project.getArtifactId(),
528 "sesat " + profile + " deployment");
529
530 if(!result.isSuccess()){
531 throw new ScmException(result.getCommandOutput());
532 }
533 }
534
535 private boolean ensureNoLocalModifications() throws ComponentLookupException, ScmException, MojoExecutionException{
536
537 if(!Boolean.getBoolean("sesat.mojo.localModifications.ignore")){
538
539 final ScmManager scmManager = (ScmManager) container.lookup(ScmManager.ROLE);
540
541 loadPomProject();
542
543 final StatusScmResult result = scmManager.status(
544 scmManager.makeScmRepository(project.getScm().getDeveloperConnection()),
545 new ScmFileSet(pomProject.getBasedir()));
546
547
548 if(!result.isSuccess()){
549
550 getLog().error(result.getCommandOutput());
551 throw new MojoExecutionException("Failed to ensure checkout has no modifications");
552 }
553
554 if(0 < result.getChangedFiles().size()){
555
556 throw new MojoExecutionException("Your checkout has local modifications. "
557 + "Server deploy can *only* be done with a clean workbench.");
558 }
559
560 return result.isSuccess() && 0 == result.getChangedFiles().size();
561 }
562 return true;
563 }
564
565 private void updateVersionFile(final Wagon wagon)
566 throws IOException, TransferFailedException, ResourceDoesNotExistException, AuthorizationException{
567
568
569 final File versionOldFile = File.createTempFile("version-old", "txt");
570 final File versionNewFile = File.createTempFile("version-new", "txt");
571 wagon.get("version.txt", versionOldFile);
572
573 boolean updated = false;
574
575
576 final BufferedReader reader = new BufferedReader(new FileReader(versionOldFile));
577 final BufferedWriter writer = new BufferedWriter(new FileWriter(versionNewFile));
578 for(String line = reader.readLine(); null != line; line = reader.readLine()){
579 if(line.equals(project.getArtifactId())){
580 updateArtifactEntry(reader, writer);
581 updated = true;
582 }else{
583
584 writer.write(line);
585 writer.newLine();
586 }
587 }
588 if(!updated){
589 writer.newLine();
590 updateArtifactEntry(reader, writer);
591 }
592 reader.close();
593 writer.close();
594 wagon.put(versionNewFile, "version.txt");
595 }
596
597 private void updateArtifactEntry(final BufferedReader reader, final BufferedWriter writer) throws IOException{
598
599
600 writer.write(project.getArtifactId());
601 writer.newLine();
602
603 reader.readLine();
604 writer.write(project.getVersion()
605 + " was last deployed by " + System.getProperty("user.name")
606 + " at " + SimpleDateFormat.getDateTimeInstance().format(now));
607 writer.newLine();
608
609 for(String line = reader.readLine(); null != line && 0 < line.length(); line = reader.readLine()){};
610 final String quote = project.getProperties().getProperty("version.quote");
611 if(null != quote){
612 writer.write(quote);
613 writer.newLine();
614 writer.newLine();
615 }
616
617 }
618
619
620 }