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