1 package org.apache.maven.report.projectinfo;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.commons.lang.SystemUtils;
23 import org.apache.maven.doxia.sink.Sink;
24 import org.apache.maven.model.Model;
25 import org.apache.maven.model.Scm;
26 import org.apache.maven.plugin.logging.Log;
27 import org.apache.maven.plugins.annotations.Component;
28 import org.apache.maven.plugins.annotations.Mojo;
29 import org.apache.maven.plugins.annotations.Parameter;
30 import org.apache.maven.scm.manager.NoSuchScmProviderException;
31 import org.apache.maven.scm.manager.ScmManager;
32 import org.apache.maven.scm.provider.cvslib.repository.CvsScmProviderRepository;
33 import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
34 import org.apache.maven.scm.provider.hg.repository.HgScmProviderRepository;
35 import org.apache.maven.scm.provider.perforce.repository.PerforceScmProviderRepository;
36 import org.apache.maven.scm.provider.starteam.repository.StarteamScmProviderRepository;
37 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
38 import org.apache.maven.scm.repository.ScmRepository;
39 import org.apache.maven.scm.repository.ScmRepositoryException;
40 import org.codehaus.plexus.i18n.I18N;
41 import org.codehaus.plexus.util.StringUtils;
42
43 import java.util.ArrayList;
44 import java.util.List;
45 import java.util.Locale;
46
47
48
49
50
51
52
53
54 @Mojo( name = "scm" )
55 public class ScmReport
56 extends AbstractProjectInfoReport
57 {
58
59
60
61
62
63
64
65 @Component
66 protected ScmManager scmManager;
67
68
69
70
71 @Parameter( defaultValue = "${project.artifactId}", required = true )
72 private String checkoutDirectoryName;
73
74
75
76
77
78
79
80 @Parameter( defaultValue = "${project.scm.connection}" )
81 private String anonymousConnection;
82
83
84
85
86
87
88
89 @Parameter( defaultValue = "${project.scm.developerConnection}" )
90 private String developerConnection;
91
92
93
94
95
96
97 @Parameter( defaultValue = "${project.scm.url}" )
98 private String webAccessUrl;
99
100
101
102
103
104 @Override
105 public void executeReport( Locale locale )
106 {
107 ScmRenderer r =
108 new ScmRenderer( getLog(), scmManager, getSink(), getProject().getModel(), getI18N( locale ), locale,
109 checkoutDirectoryName, webAccessUrl, anonymousConnection, developerConnection );
110
111 r.render();
112 }
113
114
115 public String getOutputName()
116 {
117 return "source-repository";
118 }
119
120 @Override
121 protected String getI18Nsection()
122 {
123 return "scm";
124 }
125
126
127
128
129
130
131
132
133 private static class ScmRenderer
134 extends AbstractProjectInfoRenderer
135 {
136 private Log log;
137
138 private Model model;
139
140 private ScmManager scmManager;
141
142
143
144
145 private String anonymousConnection;
146
147 private String devConnection;
148
149 private String checkoutDirectoryName;
150
151 private String webAccessUrl;
152
153 ScmRenderer( Log log, ScmManager scmManager, Sink sink, Model model, I18N i18n, Locale locale,
154 String checkoutDirName, String webAccessUrl, String anonymousConnection, String devConnection )
155 {
156 super( sink, i18n, locale );
157
158 this.log = log;
159
160 this.scmManager = scmManager;
161
162 this.model = model;
163
164 this.checkoutDirectoryName = checkoutDirName;
165
166 this.webAccessUrl = webAccessUrl;
167
168 this.anonymousConnection = anonymousConnection;
169
170 this.devConnection = devConnection;
171
172 }
173
174 @Override
175 protected String getI18Nsection()
176 {
177 return "scm";
178 }
179
180 @Override
181 public void renderBody()
182 {
183 Scm scm = model.getScm();
184 if ( scm == null )
185 {
186 startSection( getTitle() );
187
188 paragraph( getI18nString( "noscm" ) );
189
190 endSection();
191
192 return;
193 }
194
195 if ( StringUtils.isEmpty( anonymousConnection ) && StringUtils.isEmpty( devConnection )
196 && StringUtils.isEmpty( scm.getUrl() ) )
197 {
198 startSection( getTitle() );
199
200 paragraph( getI18nString( "noscm" ) );
201
202 endSection();
203
204 return;
205 }
206
207 ScmRepository anonymousRepository = getScmRepository( anonymousConnection );
208 ScmRepository devRepository = getScmRepository( devConnection );
209
210
211 renderOverViewSection( anonymousRepository );
212
213
214 renderWebAccesSection( webAccessUrl );
215
216
217 renderAnonymousAccessSection( anonymousRepository );
218
219
220 renderDeveloperAccessSection( devRepository );
221
222
223 renderAccessBehindFirewallSection( devRepository );
224
225
226 renderAccessThroughProxySection( anonymousRepository, devRepository );
227 }
228
229
230
231
232
233
234 private void renderOverViewSection( ScmRepository anonymousRepository )
235 {
236 startSection( getI18nString( "overview.title" ) );
237
238 if ( isScmSystem( anonymousRepository, "clearcase" ) )
239 {
240 sink.paragraph();
241 linkPatternedText( getI18nString( "clearcase.intro" ) );
242 sink.paragraph_();
243 }
244 else if ( isScmSystem( anonymousRepository, "cvs" ) )
245 {
246 sink.paragraph();
247 linkPatternedText( getI18nString( "cvs.intro" ) );
248 sink.paragraph_();
249 }
250 else if ( isScmSystem( anonymousRepository, "git" ) )
251 {
252 sink.paragraph();
253 linkPatternedText( getI18nString( "git.intro" ) );
254 sink.paragraph_();
255 }
256 else if ( isScmSystem( anonymousRepository, "hg" ) )
257 {
258 sink.paragraph();
259 linkPatternedText( getI18nString( "hg.intro" ) );
260 sink.paragraph_();
261 }
262 else if ( isScmSystem( anonymousRepository, "perforce" ) )
263 {
264 sink.paragraph();
265 linkPatternedText( getI18nString( "perforce.intro" ) );
266 sink.paragraph_();
267 }
268 else if ( isScmSystem( anonymousRepository, "starteam" ) )
269 {
270 sink.paragraph();
271 linkPatternedText( getI18nString( "starteam.intro" ) );
272 sink.paragraph_();
273 }
274 else if ( isScmSystem( anonymousRepository, "svn" ) )
275 {
276 sink.paragraph();
277 linkPatternedText( getI18nString( "svn.intro" ) );
278 sink.paragraph_();
279 }
280 else
281 {
282 paragraph( getI18nString( "general.intro" ) );
283 }
284
285 endSection();
286 }
287
288
289
290
291
292
293 private void renderWebAccesSection( String scmUrl )
294 {
295 startSection( getI18nString( "webaccess.title" ) );
296
297 if ( StringUtils.isEmpty( scmUrl ) )
298 {
299 paragraph( getI18nString( "webaccess.nourl" ) );
300 }
301 else
302 {
303 paragraph( getI18nString( "webaccess.url" ) );
304
305 verbatimLink( scmUrl, scmUrl );
306 }
307
308 endSection();
309 }
310
311
312
313
314
315
316
317 private void renderAnonymousAccessSection( ScmRepository anonymousRepository )
318 {
319 if ( isScmSystem( anonymousRepository, "clearcase" ) || isScmSystem( anonymousRepository, "perforce" )
320 || isScmSystem( anonymousRepository, "starteam" ) || StringUtils.isEmpty( anonymousConnection ) )
321 {
322 return;
323 }
324
325 startSection( getI18nString( "anonymousaccess.title" ) );
326
327 if ( anonymousRepository != null && isScmSystem( anonymousRepository, "cvs" ) )
328 {
329 CvsScmProviderRepository cvsRepo = (CvsScmProviderRepository) anonymousRepository
330 .getProviderRepository();
331
332 anonymousAccessCVS( cvsRepo );
333 }
334 else if ( anonymousRepository != null && isScmSystem( anonymousRepository, "git" ) )
335 {
336 GitScmProviderRepository gitRepo = (GitScmProviderRepository) anonymousRepository
337 .getProviderRepository();
338
339 anonymousAccessGit( gitRepo );
340 }
341 else if ( anonymousRepository != null && isScmSystem( anonymousRepository, "hg" ) )
342 {
343 HgScmProviderRepository hgRepo = (HgScmProviderRepository) anonymousRepository
344 .getProviderRepository();
345
346 anonymousAccessMercurial( hgRepo );
347 }
348 else if ( anonymousRepository != null && isScmSystem( anonymousRepository, "svn" ) )
349 {
350 SvnScmProviderRepository svnRepo = (SvnScmProviderRepository) anonymousRepository
351 .getProviderRepository();
352
353 anonymousAccessSVN( svnRepo );
354 }
355 else
356 {
357 paragraph( getI18nString( "anonymousaccess.general.intro" ) );
358
359 verbatimText( anonymousConnection.substring( 4 ) );
360 }
361
362 endSection();
363 }
364
365
366
367
368
369
370 private void renderDeveloperAccessSection( ScmRepository devRepository )
371 {
372 if ( StringUtils.isEmpty( devConnection ) )
373 {
374 return;
375 }
376
377 startSection( getI18nString( "devaccess.title" ) );
378
379 if ( devRepository != null && isScmSystem( devRepository, "clearcase" ) )
380 {
381 developerAccessClearCase();
382 }
383 else if ( devRepository != null && isScmSystem( devRepository, "cvs" ) )
384 {
385 CvsScmProviderRepository cvsRepo = (CvsScmProviderRepository) devRepository.getProviderRepository();
386
387 developerAccessCVS( cvsRepo );
388 }
389 else if ( devRepository != null && isScmSystem( devRepository, "git" ) )
390 {
391 GitScmProviderRepository gitRepo = (GitScmProviderRepository) devRepository.getProviderRepository();
392
393 developerAccessGit( gitRepo );
394 }
395 else if ( devRepository != null && isScmSystem( devRepository, "hg" ) )
396 {
397 HgScmProviderRepository hgRepo = (HgScmProviderRepository) devRepository.getProviderRepository();
398
399 developerAccessMercurial( hgRepo );
400 }
401 else if ( devRepository != null && isScmSystem( devRepository, "perforce" ) )
402 {
403 PerforceScmProviderRepository perforceRepo = (PerforceScmProviderRepository) devRepository
404 .getProviderRepository();
405
406 developerAccessPerforce( perforceRepo );
407 }
408 else if ( devRepository != null && isScmSystem( devRepository, "starteam" ) )
409 {
410 StarteamScmProviderRepository starteamRepo = (StarteamScmProviderRepository) devRepository
411 .getProviderRepository();
412
413 developerAccessStarteam( starteamRepo );
414 }
415 else if ( devRepository != null && isScmSystem( devRepository, "svn" ) )
416 {
417 SvnScmProviderRepository svnRepo = (SvnScmProviderRepository) devRepository.getProviderRepository();
418
419 developerAccessSVN( svnRepo );
420 }
421 else
422 {
423 paragraph( getI18nString( "devaccess.general.intro" ) );
424
425 verbatimText( devConnection.substring( 4 ) );
426 }
427
428 endSection();
429 }
430
431
432
433
434
435
436 private void renderAccessBehindFirewallSection( ScmRepository devRepository )
437 {
438 startSection( getI18nString( "accessbehindfirewall.title" ) );
439
440 if ( devRepository != null && isScmSystem( devRepository, "svn" ) )
441 {
442 SvnScmProviderRepository svnRepo = (SvnScmProviderRepository) devRepository.getProviderRepository();
443
444 paragraph( getI18nString( "accessbehindfirewall.svn.intro" ) );
445
446 StringBuilder sb = new StringBuilder();
447 sb.append( "$ svn checkout " ).append( svnRepo.getUrl() );
448 sb.append( " " ).append( checkoutDirectoryName );
449 verbatimText( sb.toString() );
450 }
451 else if ( devRepository != null && isScmSystem( devRepository, "cvs" ) )
452 {
453 linkPatternedText( getI18nString( "accessbehindfirewall.cvs.intro" ) );
454 }
455 else
456 {
457 paragraph( getI18nString( "accessbehindfirewall.general.intro" ) );
458 }
459
460 endSection();
461 }
462
463
464
465
466
467
468
469 private void renderAccessThroughProxySection( ScmRepository anonymousRepository, ScmRepository devRepository )
470 {
471 if ( isScmSystem( anonymousRepository, "svn" ) || isScmSystem( devRepository, "svn" ) )
472 {
473 startSection( getI18nString( "accessthroughtproxy.title" ) );
474
475 paragraph( getI18nString( "accessthroughtproxy.svn.intro1" ) );
476 paragraph( getI18nString( "accessthroughtproxy.svn.intro2" ) );
477 paragraph( getI18nString( "accessthroughtproxy.svn.intro3" ) );
478
479 StringBuilder sb = new StringBuilder();
480 sb.append( "[global]" );
481 sb.append( SystemUtils.LINE_SEPARATOR );
482 sb.append( "http-proxy-host = your.proxy.name" ).append( SystemUtils.LINE_SEPARATOR );
483 sb.append( "http-proxy-port = 3128" ).append( SystemUtils.LINE_SEPARATOR );
484 verbatimText( sb.toString() );
485
486 endSection();
487 }
488 }
489
490
491
492
493
494
495
496
497 private void developerAccessClearCase()
498 {
499 paragraph( getI18nString( "devaccess.clearcase.intro" ) );
500
501 StringBuilder command = new StringBuilder();
502 command.append( "$ cleartool checkout " );
503
504 verbatimText( command.toString() );
505 }
506
507
508
509
510
511
512
513
514
515
516
517
518 private void anonymousAccessCVS( CvsScmProviderRepository cvsRepo )
519 {
520 paragraph( getI18nString( "anonymousaccess.cvs.intro" ) );
521
522 StringBuilder command = new StringBuilder();
523 command.append( "$ cvs -d " ).append( cvsRepo.getCvsRoot() ).append( " login" );
524 command.append( SystemUtils.LINE_SEPARATOR );
525 command.append( "$ cvs -z3 -d " ).append( cvsRepo.getCvsRoot() );
526 command.append( " co " ).append( cvsRepo.getModule() );
527
528 verbatimText( command.toString() );
529 }
530
531
532
533
534
535
536
537
538
539
540 private void anonymousAccessGit( GitScmProviderRepository gitRepo )
541 {
542 sink.paragraph();
543 linkPatternedText( getI18nString( "anonymousaccess.git.intro" ) );
544 sink.paragraph_();
545
546 StringBuilder command = new StringBuilder();
547 command.append( "$ git clone " ).append( gitRepo.getFetchUrl() );
548
549 verbatimText( command.toString() );
550 }
551
552
553
554
555
556
557
558
559
560
561 private void anonymousAccessMercurial( HgScmProviderRepository hgRepo )
562 {
563 sink.paragraph();
564 linkPatternedText( getI18nString( "anonymousaccess.hg.intro" ) );
565 sink.paragraph_();
566
567 StringBuilder command = new StringBuilder();
568 command.append( "$ hg clone " ).append( hgRepo.getURI() );
569
570 verbatimText( command.toString() );
571 }
572
573
574
575
576
577
578
579
580
581
582 private void developerAccessCVS( CvsScmProviderRepository cvsRepo )
583 {
584 paragraph( getI18nString( "devaccess.cvs.intro" ) );
585
586
587 String cvsRoot = StringUtils.replace( cvsRepo.getCvsRoot(), cvsRepo.getUser(), "username" );
588
589 StringBuilder command = new StringBuilder();
590 command.append( "$ cvs -d " ).append( cvsRoot ).append( " login" );
591 command.append( SystemUtils.LINE_SEPARATOR );
592 command.append( "$ cvs -z3 -d " ).append( cvsRoot ).append( " co " ).append( cvsRepo.getModule() );
593
594 verbatimText( command.toString() );
595 }
596
597
598
599
600
601
602
603
604
605
606 private void developerAccessGit( GitScmProviderRepository gitRepo )
607 {
608 sink.paragraph();
609 linkPatternedText( getI18nString( "devaccess.git.intro" ) );
610 sink.paragraph_();
611
612 StringBuilder command = new StringBuilder();
613 command.append( "$ git clone " );
614 command.append( gitRepo.getPushUrl() );
615
616 verbatimText( command.toString() );
617 }
618
619
620
621
622
623
624
625
626
627
628 private void developerAccessMercurial( HgScmProviderRepository hgRepo )
629 {
630 sink.paragraph();
631 linkPatternedText( getI18nString( "devaccess.hg.intro" ) );
632 sink.paragraph_();
633
634 StringBuilder command = new StringBuilder();
635 command.append( "$ hg clone " );
636 command.append( hgRepo.getURI() );
637
638 verbatimText( command.toString() );
639 }
640
641
642
643
644
645
646
647
648
649
650
651
652 private void developerAccessPerforce( PerforceScmProviderRepository perforceRepo )
653 {
654 paragraph( getI18nString( "devaccess.perforce.intro" ) );
655
656 StringBuilder command = new StringBuilder();
657 command.append( "$ p4" );
658 if ( !StringUtils.isEmpty( perforceRepo.getHost() ) )
659 {
660 command.append( " -H " ).append( perforceRepo.getHost() );
661 }
662 if ( perforceRepo.getPort() > 0 )
663 {
664 command.append( " -p " ).append( perforceRepo.getPort() );
665 }
666 command.append( " -u username" );
667 command.append( " -P password" );
668 command.append( " " );
669 command.append( perforceRepo.getPath() );
670 command.append( SystemUtils.LINE_SEPARATOR );
671 command.append( "$ p4 submit -c \"A comment\"" );
672
673 verbatimText( command.toString() );
674 }
675
676
677
678
679
680
681
682
683
684
685
686 private void developerAccessStarteam( StarteamScmProviderRepository starteamRepo )
687 {
688 paragraph( getI18nString( "devaccess.starteam.intro" ) );
689
690 StringBuilder command = new StringBuilder();
691
692
693 String fullUrl = StringUtils.replace( starteamRepo.getFullUrl(), starteamRepo.getUser(), "username" );
694 fullUrl = StringUtils.replace( fullUrl, starteamRepo.getPassword(), "password" );
695
696 command.append( "$ stcmd co -x -nologo -stop -p " );
697 command.append( fullUrl );
698 command.append( " -is" );
699 command.append( SystemUtils.LINE_SEPARATOR );
700 command.append( "$ stcmd ci -x -nologo -stop -p " );
701 command.append( fullUrl );
702 command.append( " -f NCI -is" );
703
704 verbatimText( command.toString() );
705 }
706
707
708
709
710
711
712
713
714
715
716
717 private void anonymousAccessSVN( SvnScmProviderRepository svnRepo )
718 {
719 paragraph( getI18nString( "anonymousaccess.svn.intro" ) );
720
721 StringBuilder sb = new StringBuilder();
722 sb.append( "$ svn checkout " ).append( svnRepo.getUrl() ).append( " " ).append( checkoutDirectoryName );
723
724 verbatimText( sb.toString() );
725 }
726
727
728
729
730
731
732
733
734
735
736 private void developerAccessSVN( SvnScmProviderRepository svnRepo )
737 {
738 if ( svnRepo.getUrl() != null )
739 {
740 if ( svnRepo.getUrl().startsWith( "https://" ) )
741 {
742 paragraph( getI18nString( "devaccess.svn.intro1.https" ) );
743 }
744 else if ( svnRepo.getUrl().startsWith( "svn://" ) )
745 {
746 paragraph( getI18nString( "devaccess.svn.intro1.svn" ) );
747 }
748 else if ( svnRepo.getUrl().startsWith( "svn+ssh://" ) )
749 {
750 paragraph( getI18nString( "devaccess.svn.intro1.svnssh" ) );
751 }
752 else
753 {
754 paragraph( getI18nString( "devaccess.svn.intro1.other" ) );
755 }
756 }
757
758 StringBuilder sb = new StringBuilder();
759
760 sb.append( "$ svn checkout " ).append( svnRepo.getUrl() ).append( " " ).append( checkoutDirectoryName );
761
762 verbatimText( sb.toString() );
763
764 paragraph( getI18nString( "devaccess.svn.intro2" ) );
765
766 sb = new StringBuilder();
767 sb.append( "$ svn commit --username your-username -m \"A message\"" );
768
769 verbatimText( sb.toString() );
770 }
771
772
773
774
775
776
777
778 public ScmRepository getScmRepository( String scmUrl )
779 {
780 if ( StringUtils.isEmpty( scmUrl ) )
781 {
782 return null;
783 }
784
785 ScmRepository repo = null;
786 List<String> messages = new ArrayList<String>();
787 try
788 {
789 messages.addAll( scmManager.validateScmRepository( scmUrl ) );
790 }
791 catch ( Exception e )
792 {
793 messages.add( e.getMessage() );
794 }
795
796 if ( messages.size() > 0 )
797 {
798 StringBuilder sb = new StringBuilder();
799 boolean isIntroAdded = false;
800 for ( String msg : messages )
801 {
802
803
804 if ( msg.startsWith( "No such provider" ) )
805 {
806 continue;
807 }
808
809 if ( !isIntroAdded )
810 {
811 sb.append( "This SCM url '" + scmUrl + "' is invalid due to the following errors:" );
812 sb.append( SystemUtils.LINE_SEPARATOR );
813 isIntroAdded = true;
814 }
815 sb.append( " * " );
816 sb.append( msg );
817 sb.append( SystemUtils.LINE_SEPARATOR );
818 }
819
820 if ( StringUtils.isNotEmpty( sb.toString() ) )
821 {
822 sb.append( "For more information about SCM URL Format, please refer to: "
823 + "http://maven.apache.org/scm/scm-url-format.html" );
824
825 throw new IllegalArgumentException( sb.toString() );
826 }
827 }
828
829 try
830 {
831 repo = scmManager.makeScmRepository( scmUrl );
832 }
833 catch ( NoSuchScmProviderException e )
834 {
835 if ( log.isDebugEnabled() )
836 {
837 log.debug( e.getMessage(), e );
838 }
839 }
840 catch ( ScmRepositoryException e )
841 {
842 if ( log.isDebugEnabled() )
843 {
844 log.debug( e.getMessage(), e );
845 }
846 }
847 catch ( Exception e )
848 {
849
850 if ( log.isDebugEnabled() )
851 {
852 log.debug( e.getMessage(), e );
853 }
854 }
855
856 return repo;
857 }
858
859
860
861
862
863
864
865
866
867
868
869
870 private static boolean isScmSystem( ScmRepository scmRepository, String scmProvider )
871 {
872 if ( StringUtils.isEmpty( scmProvider ) )
873 {
874 return false;
875 }
876
877 if ( scmRepository != null && scmProvider.equalsIgnoreCase( scmRepository.getProvider() ) )
878 {
879 return true;
880 }
881
882 return false;
883 }
884 }
885 }