1 package org.apache.maven.scm.plugin;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Map.Entry;
29 import java.util.Objects;
30 import java.util.Properties;
31
32 import org.apache.maven.plugin.AbstractMojo;
33 import org.apache.maven.plugin.MojoExecutionException;
34 import org.apache.maven.plugins.annotations.Component;
35 import org.apache.maven.plugins.annotations.Parameter;
36 import org.apache.maven.scm.ScmBranch;
37 import org.apache.maven.scm.ScmException;
38 import org.apache.maven.scm.ScmFileSet;
39 import org.apache.maven.scm.ScmResult;
40 import org.apache.maven.scm.ScmRevision;
41 import org.apache.maven.scm.ScmTag;
42 import org.apache.maven.scm.ScmVersion;
43 import org.apache.maven.scm.manager.ScmManager;
44 import org.apache.maven.scm.provider.ScmProviderRepository;
45 import org.apache.maven.scm.provider.ScmProviderRepositoryWithHost;
46 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
47 import org.apache.maven.scm.repository.ScmRepository;
48 import org.apache.maven.scm.repository.ScmRepositoryException;
49 import org.apache.maven.settings.Server;
50 import org.apache.maven.settings.Settings;
51 import org.apache.maven.shared.model.fileset.FileSet;
52 import org.apache.maven.shared.model.fileset.util.FileSetManager;
53 import org.codehaus.plexus.util.StringUtils;
54 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
55 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
56
57
58
59
60
61 public abstract class AbstractScmMojo
62 extends AbstractMojo
63 {
64
65 protected static final String VERSION_TYPE_BRANCH = "branch";
66
67 protected static final String VERSION_TYPE_REVISION = "revision";
68
69 protected static final String VERSION_TYPE_TAG = "tag";
70
71 protected static final String[] VALID_VERSION_TYPES = { VERSION_TYPE_BRANCH,
72 VERSION_TYPE_REVISION, VERSION_TYPE_TAG };
73
74
75
76
77 @Parameter( property = "connectionUrl", defaultValue = "${project.scm.connection}" )
78 private String connectionUrl;
79
80
81
82
83 @Parameter( property = "developerConnectionUrl", defaultValue = "${project.scm.developerConnection}" )
84 private String developerConnectionUrl;
85
86
87
88
89 @Parameter( property = "connectionType", defaultValue = "connection" )
90 private String connectionType;
91
92
93
94
95 @Parameter( property = "workingDirectory" )
96 private File workingDirectory;
97
98
99
100
101 @Parameter( property = "username" )
102 private String username;
103
104
105
106
107 @Parameter( property = "password" )
108 private String password;
109
110
111
112
113 @Parameter( property = "privateKey" )
114 private String privateKey;
115
116
117
118
119 @Parameter( property = "passphrase" )
120 private String passphrase;
121
122
123
124
125
126
127 @Parameter( property = "tagBase" )
128 private String tagBase;
129
130
131
132
133 @Parameter( property = "includes" )
134 private String includes;
135
136
137
138
139 @Parameter( property = "excludes" )
140 private String excludes;
141
142 @Component
143 private ScmManager manager;
144
145
146
147
148
149 @Component( hint = "mng-4384" )
150 private SecDispatcher secDispatcher;
151
152
153
154
155 @Parameter( property = "basedir", required = true )
156 private File basedir;
157
158 @Parameter( defaultValue = "${settings}", readonly = true )
159 private Settings settings;
160
161
162
163
164 @Parameter
165 private Properties systemProperties;
166
167
168
169
170 @Parameter
171 private Map<String, String> providerImplementations;
172
173
174
175
176
177
178
179
180
181 @Parameter( property = "pushChanges", defaultValue = "true" )
182 private boolean pushChanges;
183
184
185
186
187
188
189
190 @Parameter( property = "workItem" )
191 private String workItem;
192
193
194 public void execute()
195 throws MojoExecutionException
196 {
197 if ( systemProperties != null )
198 {
199
200 Iterator<Object> iter = systemProperties.keySet().iterator();
201
202 while ( iter.hasNext() )
203 {
204 String key = (String) iter.next();
205
206 String value = systemProperties.getProperty( key );
207
208 System.setProperty( key, value );
209 }
210 }
211
212 if ( providerImplementations != null && !providerImplementations.isEmpty() )
213 {
214 for ( Entry<String, String> entry : providerImplementations.entrySet() )
215 {
216 String providerType = entry.getKey();
217 String providerImplementation = entry.getValue();
218 getLog().info(
219 "Change the default '" + providerType + "' provider implementation to '"
220 + providerImplementation + "'." );
221 getScmManager().setScmProviderImplementation( providerType, providerImplementation );
222 }
223 }
224 }
225
226 protected void setConnectionType( String connectionType )
227 {
228 this.connectionType = connectionType;
229 }
230
231 public String getConnectionUrl()
232 {
233 boolean requireDeveloperConnection = !"connection".equals( connectionType.toLowerCase() );
234 if ( StringUtils.isNotEmpty( connectionUrl ) && !requireDeveloperConnection )
235 {
236 return connectionUrl;
237 }
238 else if ( StringUtils.isNotEmpty( developerConnectionUrl ) )
239 {
240 return developerConnectionUrl;
241 }
242 if ( requireDeveloperConnection )
243 {
244 throw new NullPointerException( "You need to define a developerConnectionUrl parameter" );
245 }
246 else
247 {
248 throw new NullPointerException( "You need to define a connectionUrl parameter" );
249 }
250 }
251
252 public void setConnectionUrl( String connectionUrl )
253 {
254 this.connectionUrl = connectionUrl;
255 }
256
257 public File getWorkingDirectory()
258 {
259 if ( workingDirectory == null )
260 {
261 return basedir;
262 }
263
264 return workingDirectory;
265 }
266
267 public File getBasedir()
268 {
269 return this.basedir;
270 }
271
272 public void setWorkingDirectory( File workingDirectory )
273 {
274 this.workingDirectory = workingDirectory;
275 }
276
277 public ScmManager getScmManager()
278 {
279 return manager;
280 }
281
282 public ScmFileSet getFileSet()
283 throws IOException
284 {
285 if ( includes != null || excludes != null )
286 {
287 return new ScmFileSet( getWorkingDirectory(), includes, excludes );
288 }
289 else
290 {
291 return new ScmFileSet( getWorkingDirectory() );
292 }
293 }
294
295 public ScmRepository getScmRepository()
296 throws ScmException
297 {
298 ScmRepository repository;
299
300 try
301 {
302 repository = getScmManager().makeScmRepository( getConnectionUrl() );
303
304 ScmProviderRepository providerRepo = repository.getProviderRepository();
305
306 providerRepo.setPushChanges( pushChanges );
307
308 if ( !StringUtils.isEmpty( workItem ) )
309 {
310 providerRepo.setWorkItem( workItem );
311 }
312
313 if ( !StringUtils.isEmpty( username ) )
314 {
315 providerRepo.setUser( username );
316 }
317
318 if ( !StringUtils.isEmpty( password ) )
319 {
320 providerRepo.setPassword( password );
321 }
322
323 if ( repository.getProviderRepository() instanceof ScmProviderRepositoryWithHost )
324 {
325 ScmProviderRepositoryWithHost repo = (ScmProviderRepositoryWithHost) repository.getProviderRepository();
326
327 loadInfosFromSettings( repo );
328
329 if ( !StringUtils.isEmpty( username ) )
330 {
331 repo.setUser( username );
332 }
333
334 if ( !StringUtils.isEmpty( password ) )
335 {
336 repo.setPassword( password );
337 }
338
339 if ( !StringUtils.isEmpty( privateKey ) )
340 {
341 repo.setPrivateKey( privateKey );
342 }
343
344 if ( !StringUtils.isEmpty( passphrase ) )
345 {
346 repo.setPassphrase( passphrase );
347 }
348 }
349
350 if ( !StringUtils.isEmpty( tagBase ) && repository.getProvider().equals( "svn" ) )
351 {
352 SvnScmProviderRepository svnRepo = (SvnScmProviderRepository) repository.getProviderRepository();
353
354 svnRepo.setTagBase( tagBase );
355 }
356 }
357 catch ( ScmRepositoryException e )
358 {
359 if ( !e.getValidationMessages().isEmpty() )
360 {
361 for ( String message : e.getValidationMessages() )
362 {
363 getLog().error( message );
364 }
365 }
366
367 throw new ScmException( "Can't load the scm provider.", e );
368 }
369 catch ( Exception e )
370 {
371 throw new ScmException( "Can't load the scm provider.", e );
372 }
373
374 return repository;
375 }
376
377
378
379
380
381
382 private void loadInfosFromSettings( ScmProviderRepositoryWithHost repo )
383 {
384 if ( username == null || password == null )
385 {
386 String host = repo.getHost();
387
388 int port = repo.getPort();
389
390 if ( port > 0 )
391 {
392 host += ":" + port;
393 }
394
395 Server server = this.settings.getServer( host );
396
397 if ( server != null )
398 {
399 if ( username == null )
400 {
401 username = server.getUsername();
402 }
403
404 if ( password == null )
405 {
406 password = decrypt( server.getPassword(), host );
407 }
408
409 if ( privateKey == null )
410 {
411 privateKey = server.getPrivateKey();
412 }
413
414 if ( passphrase == null )
415 {
416 passphrase = decrypt( server.getPassphrase(), host );
417 }
418 }
419 }
420 }
421
422 private String decrypt( String str, String server )
423 {
424 try
425 {
426 return secDispatcher.decrypt( str );
427 }
428 catch ( SecDispatcherException e )
429 {
430 getLog().warn( "Failed to decrypt password/passphrase for server " + server + ", using auth token as is" );
431 return str;
432 }
433 }
434
435 public void checkResult( ScmResult result )
436 throws MojoExecutionException
437 {
438 if ( !result.isSuccess() )
439 {
440 getLog().error( "Provider message:" );
441
442 getLog().error( result.getProviderMessage() == null ? "" : result.getProviderMessage() );
443
444 getLog().error( "Command output:" );
445
446 getLog().error( result.getCommandOutput() == null ? "" : result.getCommandOutput() );
447
448 throw new MojoExecutionException(
449 "Command failed: " + Objects.toString( result.getProviderMessage() ) );
450 }
451 }
452
453 public String getIncludes()
454 {
455 return includes;
456 }
457
458 public void setIncludes( String includes )
459 {
460 this.includes = includes;
461 }
462
463 public String getExcludes()
464 {
465 return excludes;
466 }
467
468 public void setExcludes( String excludes )
469 {
470 this.excludes = excludes;
471 }
472
473 public ScmVersion getScmVersion( String versionType, String version )
474 throws MojoExecutionException
475 {
476 if ( StringUtils.isEmpty( versionType ) && StringUtils.isNotEmpty( version ) )
477 {
478 throw new MojoExecutionException( "You must specify the version type." );
479 }
480
481 if ( StringUtils.isEmpty( version ) )
482 {
483 return null;
484 }
485
486 if ( VERSION_TYPE_BRANCH.equals( versionType ) )
487 {
488 return new ScmBranch( version );
489 }
490
491 if ( VERSION_TYPE_TAG.equals( versionType ) )
492 {
493 return new ScmTag( version );
494 }
495
496 if ( VERSION_TYPE_REVISION.equals( versionType ) )
497 {
498 return new ScmRevision( version );
499 }
500
501 throw new MojoExecutionException( "Unknown '" + versionType + "' version type." );
502 }
503
504 protected void handleExcludesIncludesAfterCheckoutAndExport( File checkoutDirectory )
505 throws MojoExecutionException
506 {
507 List<String> includes = new ArrayList<String>();
508
509 if ( ! StringUtils.isBlank( this.getIncludes() ) )
510 {
511 String[] tokens = StringUtils.split( this.getIncludes(), "," );
512 for ( int i = 0; i < tokens.length; ++i )
513 {
514 includes.add( tokens[i] );
515 }
516 }
517
518 List<String> excludes = new ArrayList<String>();
519
520 if ( ! StringUtils.isBlank( this.getExcludes() ) )
521 {
522 String[] tokens = StringUtils.split( this.getExcludes(), "," );
523 for ( int i = 0; i < tokens.length; ++i )
524 {
525 excludes.add( tokens[i] );
526 }
527 }
528
529 if ( includes.isEmpty() && excludes.isEmpty() )
530 {
531 return;
532 }
533
534 FileSetManager fileSetManager = new FileSetManager();
535
536 FileSet fileset = new FileSet();
537 fileset.setDirectory( checkoutDirectory.getAbsolutePath() );
538 fileset.setIncludes( excludes );
539 fileset.setExcludes( includes );
540 fileset.setUseDefaultExcludes( false );
541
542 try
543 {
544 fileSetManager.delete( fileset );
545 }
546 catch ( IOException e )
547 {
548 throw new MojoExecutionException( "Error found while cleaning up output directory base on "
549 + "excludes/includes configurations.", e );
550 }
551
552 }
553 }