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