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