1 package org.apache.maven.scm.manager;
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.util.ArrayList;
24 import java.util.Date;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.concurrent.ConcurrentHashMap;
28
29 import org.apache.maven.scm.ScmBranch;
30 import org.apache.maven.scm.ScmBranchParameters;
31 import org.apache.maven.scm.ScmException;
32 import org.apache.maven.scm.ScmFileSet;
33 import org.apache.maven.scm.ScmTagParameters;
34 import org.apache.maven.scm.ScmVersion;
35 import org.apache.maven.scm.command.add.AddScmResult;
36 import org.apache.maven.scm.command.blame.BlameScmRequest;
37 import org.apache.maven.scm.command.blame.BlameScmResult;
38 import org.apache.maven.scm.command.branch.BranchScmResult;
39 import org.apache.maven.scm.command.changelog.ChangeLogScmRequest;
40 import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
41 import org.apache.maven.scm.command.checkin.CheckInScmResult;
42 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
43 import org.apache.maven.scm.command.diff.DiffScmResult;
44 import org.apache.maven.scm.command.edit.EditScmResult;
45 import org.apache.maven.scm.command.export.ExportScmResult;
46 import org.apache.maven.scm.command.list.ListScmResult;
47 import org.apache.maven.scm.command.mkdir.MkdirScmResult;
48 import org.apache.maven.scm.command.remove.RemoveScmResult;
49 import org.apache.maven.scm.command.status.StatusScmResult;
50 import org.apache.maven.scm.command.tag.TagScmResult;
51 import org.apache.maven.scm.command.unedit.UnEditScmResult;
52 import org.apache.maven.scm.command.update.UpdateScmResult;
53 import org.apache.maven.scm.provider.ScmProvider;
54 import org.apache.maven.scm.provider.ScmProviderRepository;
55 import org.apache.maven.scm.provider.ScmUrlUtils;
56 import org.apache.maven.scm.repository.ScmRepository;
57 import org.apache.maven.scm.repository.ScmRepositoryException;
58 import org.apache.maven.scm.repository.UnknownRepositoryStructure;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 import static java.util.Objects.requireNonNull;
63
64
65
66
67
68
69 public abstract class AbstractScmManager
70 implements ScmManager
71 {
72 protected final Logger logger = LoggerFactory.getLogger( getClass() );
73
74 private final Map<String, ScmProvider> scmProviders = new ConcurrentHashMap<>();
75
76 private final Map<String, String> userProviderTypes = new ConcurrentHashMap<>();
77
78 protected void setScmProviders( Map<String, ScmProvider> providers )
79 {
80 requireNonNull( providers );
81 this.scmProviders.clear();
82
83 providers.forEach( this.scmProviders::putIfAbsent );
84 }
85
86
87
88
89
90
91 @Deprecated
92 protected void addScmProvider( String providerType, ScmProvider provider )
93 {
94 setScmProvider( providerType, provider );
95 }
96
97
98
99
100
101
102
103
104 @Override
105 public void setScmProvider( String providerType, ScmProvider provider )
106 {
107 requireNonNull( providerType );
108 requireNonNull( provider );
109 scmProviders.put( providerType, provider );
110 }
111
112
113
114
115
116
117
118
119 @Override
120 public ScmProvider getProviderByUrl( String scmUrl )
121 throws ScmRepositoryException, NoSuchScmProviderException
122 {
123 requireNonNull( scmUrl, "The scm url cannot be null." );
124
125 String providerType = ScmUrlUtils.getProvider( scmUrl );
126
127 return getProviderByType( providerType );
128 }
129
130
131
132
133 @Override
134 public void setScmProviderImplementation( String providerType, String providerImplementation )
135 {
136 requireNonNull( providerType );
137 requireNonNull( providerImplementation );
138 userProviderTypes.put( providerType, providerImplementation );
139 }
140
141
142
143
144 @Override
145 public ScmProvider getProviderByType( String providerType )
146 throws NoSuchScmProviderException
147 {
148 String usedProviderType = System.getProperty( "maven.scm.provider." + providerType + ".implementation" );
149
150 if ( usedProviderType == null )
151 {
152 usedProviderType = userProviderTypes.getOrDefault( providerType, providerType );
153 }
154
155 ScmProvider scmProvider = scmProviders.get( usedProviderType );
156
157 if ( scmProvider == null )
158 {
159 throw new NoSuchScmProviderException( usedProviderType );
160 }
161
162 return scmProvider;
163 }
164
165
166
167
168 @Override
169 public ScmProvider getProviderByRepository( ScmRepository repository )
170 throws NoSuchScmProviderException
171 {
172 return getProviderByType( repository.getProvider() );
173 }
174
175
176
177
178
179
180
181
182 @Override
183 public ScmRepository makeScmRepository( String scmUrl )
184 throws ScmRepositoryException, NoSuchScmProviderException
185 {
186 requireNonNull( scmUrl, "The scm url cannot be null." );
187
188 char delimiter = ScmUrlUtils.getDelimiter( scmUrl ).charAt( 0 );
189
190 String providerType = ScmUrlUtils.getProvider( scmUrl );
191
192 ScmProvider provider = getProviderByType( providerType );
193
194 String scmSpecificUrl = cleanScmUrl( scmUrl.substring( providerType.length() + 5 ) );
195
196 ScmProviderRepository providerRepository = provider.makeProviderScmRepository( scmSpecificUrl, delimiter );
197
198 return new ScmRepository( providerType, providerRepository );
199 }
200
201
202
203
204
205
206
207 protected String cleanScmUrl( String scmUrl )
208 {
209 requireNonNull( scmUrl, "The scm url cannot be null." );
210
211 String pathSeparator = "";
212
213 int indexOfDoubleDot = -1;
214
215
216 if ( scmUrl.indexOf( "../" ) > 1 )
217 {
218 pathSeparator = "/";
219
220 indexOfDoubleDot = scmUrl.indexOf( "../" );
221 }
222
223
224 if ( scmUrl.indexOf( "..\\" ) > 1 )
225 {
226 pathSeparator = "\\";
227
228 indexOfDoubleDot = scmUrl.indexOf( "..\\" );
229 }
230
231 if ( indexOfDoubleDot > 1 )
232 {
233 int startOfTextToRemove = scmUrl.substring( 0, indexOfDoubleDot - 1 ).lastIndexOf( pathSeparator );
234
235 String beginUrl = "";
236 if ( startOfTextToRemove >= 0 )
237 {
238 beginUrl = scmUrl.substring( 0, startOfTextToRemove );
239 }
240
241 String endUrl = scmUrl.substring( indexOfDoubleDot + 3 );
242
243 scmUrl = beginUrl + pathSeparator + endUrl;
244
245
246 if ( scmUrl.indexOf( "../" ) > 1 || scmUrl.indexOf( "..\\" ) > 1 )
247 {
248 scmUrl = cleanScmUrl( scmUrl );
249 }
250 }
251
252 return scmUrl;
253 }
254
255
256
257
258 @Override
259 public ScmRepository makeProviderScmRepository( String providerType, File path )
260 throws ScmRepositoryException, UnknownRepositoryStructure, NoSuchScmProviderException
261 {
262 requireNonNull( providerType, "The provider type cannot be null." );
263
264 ScmProvider provider = getProviderByType( providerType );
265
266 ScmProviderRepository providerRepository = provider.makeProviderScmRepository( path );
267
268 return new ScmRepository( providerType, providerRepository );
269 }
270
271
272
273
274 @Override
275 public List<String> validateScmRepository( String scmUrl )
276 {
277 List<String> messages = new ArrayList<>( ScmUrlUtils.validate( scmUrl ) );
278
279 String providerType = ScmUrlUtils.getProvider( scmUrl );
280
281 ScmProvider provider;
282
283 try
284 {
285 provider = getProviderByType( providerType );
286 }
287 catch ( NoSuchScmProviderException e )
288 {
289 messages.add( "No such provider installed '" + providerType + "'." );
290
291 return messages;
292 }
293
294 String scmSpecificUrl = cleanScmUrl( scmUrl.substring( providerType.length() + 5 ) );
295
296 List<String> providerMessages =
297 provider.validateScmUrl( scmSpecificUrl, ScmUrlUtils.getDelimiter( scmUrl ).charAt( 0 ) );
298
299 requireNonNull( providerMessages, "The SCM provider cannot return null from validateScmUrl()." );
300
301 messages.addAll( providerMessages );
302
303 return messages;
304 }
305
306
307
308
309 @Override
310 public AddScmResult add( ScmRepository repository, ScmFileSet fileSet )
311 throws ScmException
312 {
313 return this.getProviderByRepository( repository ).add( repository, fileSet );
314 }
315
316
317
318
319 @Override
320 public AddScmResult add( ScmRepository repository, ScmFileSet fileSet, String message )
321 throws ScmException
322 {
323 return this.getProviderByRepository( repository ).add( repository, fileSet, message );
324 }
325
326
327
328
329 @Override
330 public BranchScmResult branch( ScmRepository repository, ScmFileSet fileSet, String branchName )
331 throws ScmException
332 {
333 ScmBranchParameters scmBranchParameters = new ScmBranchParameters( "" );
334 return this.getProviderByRepository( repository ).branch( repository, fileSet, branchName,
335 scmBranchParameters );
336 }
337
338
339
340
341 @Override
342 public BranchScmResult branch( ScmRepository repository, ScmFileSet fileSet, String branchName, String message )
343 throws ScmException
344 {
345 ScmBranchParameters scmBranchParameters = new ScmBranchParameters( message );
346 return this.getProviderByRepository( repository ).branch( repository, fileSet, branchName,
347 scmBranchParameters );
348 }
349
350
351
352
353 @Override
354 public ChangeLogScmResult changeLog( ScmRepository repository, ScmFileSet fileSet, Date startDate, Date endDate,
355 int numDays, ScmBranch branch )
356 throws ScmException
357 {
358 return this.getProviderByRepository( repository ).changeLog( repository, fileSet, startDate, endDate, numDays,
359 branch );
360 }
361
362
363
364
365 @Override
366 public ChangeLogScmResult changeLog( ScmRepository repository, ScmFileSet fileSet, Date startDate, Date endDate,
367 int numDays, ScmBranch branch, String datePattern )
368 throws ScmException
369 {
370 return this.getProviderByRepository( repository ).changeLog( repository, fileSet, startDate, endDate, numDays,
371 branch, datePattern );
372 }
373
374
375
376
377 @Override
378 public ChangeLogScmResult changeLog( ChangeLogScmRequest scmRequest )
379 throws ScmException
380 {
381 return this.getProviderByRepository( scmRequest.getScmRepository() ).changeLog( scmRequest );
382 }
383
384
385
386
387 @Override
388 public ChangeLogScmResult changeLog( ScmRepository repository, ScmFileSet fileSet, ScmVersion startVersion,
389 ScmVersion endVersion )
390 throws ScmException
391 {
392 return this.getProviderByRepository( repository ).changeLog( repository, fileSet, startVersion, endVersion );
393 }
394
395
396
397
398 @Override
399 public ChangeLogScmResult changeLog( ScmRepository repository, ScmFileSet fileSet, ScmVersion startRevision,
400 ScmVersion endRevision, String datePattern )
401 throws ScmException
402 {
403 return this.getProviderByRepository( repository ).changeLog( repository, fileSet, startRevision, endRevision,
404 datePattern );
405 }
406
407
408
409
410 @Override
411 public CheckInScmResult checkIn( ScmRepository repository, ScmFileSet fileSet, String message )
412 throws ScmException
413 {
414 return this.getProviderByRepository( repository ).checkIn( repository, fileSet, message );
415 }
416
417
418
419
420 @Override
421 public CheckInScmResult checkIn( ScmRepository repository, ScmFileSet fileSet, ScmVersion revision, String message )
422 throws ScmException
423 {
424 return this.getProviderByRepository( repository ).checkIn( repository, fileSet, revision, message );
425 }
426
427
428
429
430 @Override
431 public CheckOutScmResult checkOut( ScmRepository repository, ScmFileSet fileSet )
432 throws ScmException
433 {
434 return this.getProviderByRepository( repository ).checkOut( repository, fileSet );
435 }
436
437
438
439
440 @Override
441 public CheckOutScmResult checkOut( ScmRepository repository, ScmFileSet fileSet, ScmVersion version )
442 throws ScmException
443 {
444 return this.getProviderByRepository( repository ).checkOut( repository, fileSet, version );
445 }
446
447
448
449
450 @Override
451 public CheckOutScmResult checkOut( ScmRepository repository, ScmFileSet fileSet, boolean recursive )
452 throws ScmException
453 {
454 return this.getProviderByRepository( repository ).checkOut( repository, fileSet, recursive );
455 }
456
457
458
459
460 @Override
461 public CheckOutScmResult checkOut( ScmRepository repository, ScmFileSet fileSet, ScmVersion version,
462 boolean recursive )
463 throws ScmException
464 {
465 return this.getProviderByRepository( repository ).checkOut( repository, fileSet, version, recursive );
466 }
467
468
469
470
471 @Override
472 public DiffScmResult diff( ScmRepository repository, ScmFileSet fileSet, ScmVersion startVersion,
473 ScmVersion endVersion )
474 throws ScmException
475 {
476 return this.getProviderByRepository( repository ).diff( repository, fileSet, startVersion, endVersion );
477 }
478
479
480
481
482 @Override
483 public EditScmResult edit( ScmRepository repository, ScmFileSet fileSet )
484 throws ScmException
485 {
486 return this.getProviderByRepository( repository ).edit( repository, fileSet );
487 }
488
489
490
491
492 @Override
493 public ExportScmResult export( ScmRepository repository, ScmFileSet fileSet )
494 throws ScmException
495 {
496 return this.getProviderByRepository( repository ).export( repository, fileSet );
497 }
498
499
500
501
502 @Override
503 public ExportScmResult export( ScmRepository repository, ScmFileSet fileSet, ScmVersion version )
504 throws ScmException
505 {
506 return this.getProviderByRepository( repository ).export( repository, fileSet, version );
507 }
508
509
510
511
512 @Override
513 public ExportScmResult export( ScmRepository repository, ScmFileSet fileSet, String outputDirectory )
514 throws ScmException
515 {
516 return this.getProviderByRepository( repository ).export( repository, fileSet, (ScmVersion) null,
517 outputDirectory );
518 }
519
520
521
522
523 @Override
524 public ExportScmResult export( ScmRepository repository, ScmFileSet fileSet, ScmVersion version,
525 String outputDirectory )
526 throws ScmException
527 {
528 return this.getProviderByRepository( repository ).export( repository, fileSet, version, outputDirectory );
529 }
530
531
532
533
534 @Override
535 public ListScmResult list( ScmRepository repository, ScmFileSet fileSet, boolean recursive, ScmVersion version )
536 throws ScmException
537 {
538 return this.getProviderByRepository( repository ).list( repository, fileSet, recursive, version );
539 }
540
541
542
543
544 @Override
545 public MkdirScmResult mkdir( ScmRepository repository, ScmFileSet fileSet, String message, boolean createInLocal )
546 throws ScmException
547 {
548 return this.getProviderByRepository( repository ).mkdir( repository, fileSet, message, createInLocal );
549 }
550
551
552
553
554 @Override
555 public RemoveScmResult remove( ScmRepository repository, ScmFileSet fileSet, String message )
556 throws ScmException
557 {
558 return this.getProviderByRepository( repository ).remove( repository, fileSet, message );
559 }
560
561
562
563
564 @Override
565 public StatusScmResult status( ScmRepository repository, ScmFileSet fileSet )
566 throws ScmException
567 {
568 return this.getProviderByRepository( repository ).status( repository, fileSet );
569 }
570
571
572
573
574 @Override
575 public TagScmResult tag( ScmRepository repository, ScmFileSet fileSet, String tagName )
576 throws ScmException
577 {
578 return this.tag( repository, fileSet, tagName, "" );
579 }
580
581
582
583
584 @Override
585 public TagScmResult tag( ScmRepository repository, ScmFileSet fileSet, String tagName, String message )
586 throws ScmException
587 {
588 ScmTagParameters scmTagParameters = new ScmTagParameters( message );
589 return this.getProviderByRepository( repository ).tag( repository, fileSet, tagName, scmTagParameters );
590 }
591
592
593
594
595 @Override
596 public UnEditScmResult unedit( ScmRepository repository, ScmFileSet fileSet )
597 throws ScmException
598 {
599 return this.getProviderByRepository( repository ).unedit( repository, fileSet );
600 }
601
602
603
604
605 @Override
606 public UpdateScmResult update( ScmRepository repository, ScmFileSet fileSet )
607 throws ScmException
608 {
609 return this.getProviderByRepository( repository ).update( repository, fileSet );
610 }
611
612
613
614
615 @Override
616 public UpdateScmResult update( ScmRepository repository, ScmFileSet fileSet, ScmVersion version )
617 throws ScmException
618 {
619 return this.getProviderByRepository( repository ).update( repository, fileSet, version );
620 }
621
622
623
624
625 @Override
626 public UpdateScmResult update( ScmRepository repository, ScmFileSet fileSet, boolean runChangelog )
627 throws ScmException
628 {
629 return this.getProviderByRepository( repository ).update( repository, fileSet, runChangelog );
630 }
631
632
633
634
635 @Override
636 public UpdateScmResult update( ScmRepository repository, ScmFileSet fileSet, ScmVersion version,
637 boolean runChangelog )
638 throws ScmException
639 {
640 return this.getProviderByRepository( repository ).update( repository, fileSet, version, runChangelog );
641 }
642
643
644
645
646 @Override
647 public UpdateScmResult update( ScmRepository repository, ScmFileSet fileSet, String datePattern )
648 throws ScmException
649 {
650 return this.getProviderByRepository( repository ).update( repository, fileSet, (ScmVersion) null, datePattern );
651 }
652
653
654
655
656 @Override
657 public UpdateScmResult update( ScmRepository repository, ScmFileSet fileSet, ScmVersion version,
658 String datePattern )
659 throws ScmException
660 {
661 return this.getProviderByRepository( repository ).update( repository, fileSet, version, datePattern );
662 }
663
664
665
666
667 @Override
668 public UpdateScmResult update( ScmRepository repository, ScmFileSet fileSet, Date lastUpdate )
669 throws ScmException
670 {
671 return this.getProviderByRepository( repository ).update( repository, fileSet, (ScmVersion) null, lastUpdate );
672 }
673
674
675
676
677 @Override
678 public UpdateScmResult update( ScmRepository repository, ScmFileSet fileSet, ScmVersion version, Date lastUpdate )
679 throws ScmException
680 {
681 return this.getProviderByRepository( repository ).update( repository, fileSet, version, lastUpdate );
682 }
683
684
685
686
687 @Override
688 public UpdateScmResult update( ScmRepository repository, ScmFileSet fileSet, Date lastUpdate, String datePattern )
689 throws ScmException
690 {
691 return this.getProviderByRepository( repository ).update( repository, fileSet, (ScmVersion) null, lastUpdate,
692 datePattern );
693 }
694
695
696
697
698 @Override
699 public UpdateScmResult update( ScmRepository repository, ScmFileSet fileSet, ScmVersion version, Date lastUpdate,
700 String datePattern )
701 throws ScmException
702 {
703 return this.getProviderByRepository( repository ).update( repository, fileSet, version, lastUpdate,
704 datePattern );
705 }
706
707
708
709
710 @Override
711 public BlameScmResult blame( ScmRepository repository, ScmFileSet fileSet, String filename )
712 throws ScmException
713 {
714 return this.getProviderByRepository( repository ).blame( repository, fileSet, filename );
715 }
716
717 @Override
718 public BlameScmResult blame( BlameScmRequest blameScmRequest )
719 throws ScmException
720 {
721 return this.getProviderByRepository( blameScmRequest.getScmRepository() ).blame( blameScmRequest );
722 }
723 }