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 @Deprecated
192 private String workItem;
193
194
195 public void execute()
196 throws MojoExecutionException
197 {
198 if ( systemProperties != null )
199 {
200
201 Iterator<Object> iter = systemProperties.keySet().iterator();
202
203 while ( iter.hasNext() )
204 {
205 String key = (String) iter.next();
206
207 String value = systemProperties.getProperty( key );
208
209 System.setProperty( key, value );
210 }
211 }
212
213 if ( providerImplementations != null && !providerImplementations.isEmpty() )
214 {
215 for ( Entry<String, String> entry : providerImplementations.entrySet() )
216 {
217 String providerType = entry.getKey();
218 String providerImplementation = entry.getValue();
219 getLog().info(
220 "Change the default '" + providerType + "' provider implementation to '"
221 + providerImplementation + "'." );
222 getScmManager().setScmProviderImplementation( providerType, providerImplementation );
223 }
224 }
225 }
226
227 protected void setConnectionType( String connectionType )
228 {
229 this.connectionType = connectionType;
230 }
231
232 public String getConnectionUrl()
233 {
234 boolean requireDeveloperConnection = !"connection".equals( connectionType.toLowerCase() );
235 if ( StringUtils.isNotEmpty( connectionUrl ) && !requireDeveloperConnection )
236 {
237 return connectionUrl;
238 }
239 else if ( StringUtils.isNotEmpty( developerConnectionUrl ) )
240 {
241 return developerConnectionUrl;
242 }
243 if ( requireDeveloperConnection )
244 {
245 throw new NullPointerException( "You need to define a developerConnectionUrl parameter" );
246 }
247 else
248 {
249 throw new NullPointerException( "You need to define a connectionUrl parameter" );
250 }
251 }
252
253 public void setConnectionUrl( String connectionUrl )
254 {
255 this.connectionUrl = connectionUrl;
256 }
257
258 public File getWorkingDirectory()
259 {
260 if ( workingDirectory == null )
261 {
262 return basedir;
263 }
264
265 return workingDirectory;
266 }
267
268 public File getBasedir()
269 {
270 return this.basedir;
271 }
272
273 public void setWorkingDirectory( File workingDirectory )
274 {
275 this.workingDirectory = workingDirectory;
276 }
277
278 public ScmManager getScmManager()
279 {
280 return manager;
281 }
282
283 public ScmFileSet getFileSet()
284 throws IOException
285 {
286 if ( includes != null || excludes != null )
287 {
288 return new ScmFileSet( getWorkingDirectory(), includes, excludes );
289 }
290 else
291 {
292 return new ScmFileSet( getWorkingDirectory() );
293 }
294 }
295
296 public ScmRepository getScmRepository()
297 throws ScmException
298 {
299 ScmRepository repository;
300
301 try
302 {
303 repository = getScmManager().makeScmRepository( getConnectionUrl() );
304
305 ScmProviderRepository providerRepo = repository.getProviderRepository();
306
307 providerRepo.setPushChanges( pushChanges );
308
309 if ( !StringUtils.isEmpty( workItem ) )
310 {
311 providerRepo.setWorkItem( workItem );
312 }
313
314 if ( !StringUtils.isEmpty( username ) )
315 {
316 providerRepo.setUser( username );
317 }
318
319 if ( !StringUtils.isEmpty( password ) )
320 {
321 providerRepo.setPassword( password );
322 }
323
324 if ( repository.getProviderRepository() instanceof ScmProviderRepositoryWithHost )
325 {
326 ScmProviderRepositoryWithHost repo = (ScmProviderRepositoryWithHost) repository.getProviderRepository();
327
328 loadInfosFromSettings( repo );
329
330 if ( !StringUtils.isEmpty( username ) )
331 {
332 repo.setUser( username );
333 }
334
335 if ( !StringUtils.isEmpty( password ) )
336 {
337 repo.setPassword( password );
338 }
339
340 if ( !StringUtils.isEmpty( privateKey ) )
341 {
342 repo.setPrivateKey( privateKey );
343 }
344
345 if ( !StringUtils.isEmpty( passphrase ) )
346 {
347 repo.setPassphrase( passphrase );
348 }
349 }
350
351 if ( !StringUtils.isEmpty( tagBase ) && repository.getProvider().equals( "svn" ) )
352 {
353 SvnScmProviderRepository svnRepo = (SvnScmProviderRepository) repository.getProviderRepository();
354
355 svnRepo.setTagBase( tagBase );
356 }
357 }
358 catch ( ScmRepositoryException e )
359 {
360 if ( !e.getValidationMessages().isEmpty() )
361 {
362 for ( String message : e.getValidationMessages() )
363 {
364 getLog().error( message );
365 }
366 }
367
368 throw new ScmException( "Can't load the scm provider.", e );
369 }
370 catch ( Exception e )
371 {
372 throw new ScmException( "Can't load the scm provider.", e );
373 }
374
375 return repository;
376 }
377
378
379
380
381
382
383 private void loadInfosFromSettings( ScmProviderRepositoryWithHost repo )
384 {
385 if ( username == null || password == null )
386 {
387 String host = repo.getHost();
388
389 int port = repo.getPort();
390
391 if ( port > 0 )
392 {
393 host += ":" + port;
394 }
395
396 Server server = this.settings.getServer( host );
397
398 if ( server != null )
399 {
400 if ( username == null )
401 {
402 username = server.getUsername();
403 }
404
405 if ( password == null )
406 {
407 password = decrypt( server.getPassword(), host );
408 }
409
410 if ( privateKey == null )
411 {
412 privateKey = server.getPrivateKey();
413 }
414
415 if ( passphrase == null )
416 {
417 passphrase = decrypt( server.getPassphrase(), host );
418 }
419 }
420 }
421 }
422
423 private String decrypt( String str, String server )
424 {
425 try
426 {
427 return secDispatcher.decrypt( str );
428 }
429 catch ( SecDispatcherException e )
430 {
431 getLog().warn( "Failed to decrypt password/passphrase for server " + server + ", using auth token as is" );
432 return str;
433 }
434 }
435
436 public void checkResult( ScmResult result )
437 throws MojoExecutionException
438 {
439 if ( !result.isSuccess() )
440 {
441 getLog().error( "Provider message:" );
442
443 getLog().error( result.getProviderMessage() == null ? "" : result.getProviderMessage() );
444
445 getLog().error( "Command output:" );
446
447 getLog().error( result.getCommandOutput() == null ? "" : result.getCommandOutput() );
448
449 throw new MojoExecutionException(
450 "Command failed: " + Objects.toString( result.getProviderMessage() ) );
451 }
452 }
453
454 public String getIncludes()
455 {
456 return includes;
457 }
458
459 public void setIncludes( String includes )
460 {
461 this.includes = includes;
462 }
463
464 public String getExcludes()
465 {
466 return excludes;
467 }
468
469 public void setExcludes( String excludes )
470 {
471 this.excludes = excludes;
472 }
473
474 public ScmVersion getScmVersion( String versionType, String version )
475 throws MojoExecutionException
476 {
477 if ( StringUtils.isEmpty( versionType ) && StringUtils.isNotEmpty( version ) )
478 {
479 throw new MojoExecutionException( "You must specify the version type." );
480 }
481
482 if ( StringUtils.isEmpty( version ) )
483 {
484 return null;
485 }
486
487 if ( VERSION_TYPE_BRANCH.equals( versionType ) )
488 {
489 return new ScmBranch( version );
490 }
491
492 if ( VERSION_TYPE_TAG.equals( versionType ) )
493 {
494 return new ScmTag( version );
495 }
496
497 if ( VERSION_TYPE_REVISION.equals( versionType ) )
498 {
499 return new ScmRevision( version );
500 }
501
502 throw new MojoExecutionException( "Unknown '" + versionType + "' version type." );
503 }
504
505 protected void handleExcludesIncludesAfterCheckoutAndExport( File checkoutDirectory )
506 throws MojoExecutionException
507 {
508 List<String> includes = new ArrayList<String>();
509
510 if ( ! StringUtils.isBlank( this.getIncludes() ) )
511 {
512 String[] tokens = StringUtils.split( this.getIncludes(), "," );
513 for ( int i = 0; i < tokens.length; ++i )
514 {
515 includes.add( tokens[i] );
516 }
517 }
518
519 List<String> excludes = new ArrayList<String>();
520
521 if ( ! StringUtils.isBlank( this.getExcludes() ) )
522 {
523 String[] tokens = StringUtils.split( this.getExcludes(), "," );
524 for ( int i = 0; i < tokens.length; ++i )
525 {
526 excludes.add( tokens[i] );
527 }
528 }
529
530 if ( includes.isEmpty() && excludes.isEmpty() )
531 {
532 return;
533 }
534
535 FileSetManager fileSetManager = new FileSetManager();
536
537 FileSet fileset = new FileSet();
538 fileset.setDirectory( checkoutDirectory.getAbsolutePath() );
539 fileset.setIncludes( excludes );
540 fileset.setExcludes( includes );
541 fileset.setUseDefaultExcludes( false );
542
543 try
544 {
545 fileSetManager.delete( fileset );
546 }
547 catch ( IOException e )
548 {
549 throw new MojoExecutionException( "Error found while cleaning up output directory base on "
550 + "excludes/includes configurations.", e );
551 }
552
553 }
554 }