View Javadoc

1   package org.apache.maven.report.projectinfo;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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.List;
41  import java.util.Locale;
42  
43  /**
44   * Generates the Project Source Code Management (SCM) report.
45   *
46   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton </a>
47   * @version $Id: ScmReport.java 1038048 2010-11-23 10:52:14Z vsiveton $
48   * @since 2.0
49   * @goal scm
50   */
51  public class ScmReport
52      extends AbstractProjectInfoReport
53  {
54      // ----------------------------------------------------------------------
55      // Mojo parameters
56      // ----------------------------------------------------------------------
57  
58      /**
59       * Maven SCM Manager.
60       *
61       * @component
62       */
63      protected ScmManager scmManager;
64  
65      /**
66       * The directory name to checkout right after the SCM URL.
67       *
68       * @parameter default-value="${project.artifactId}"
69       * @required
70       */
71      private String checkoutDirectoryName;
72  
73      /**
74       * The SCM anonymous connection url respecting the SCM URL Format.
75       *
76       * @parameter default-value="${project.scm.connection}"
77       * @since 2.1
78       * @see <a href="http://maven.apache.org/scm/scm-url-format.html">SCM URL Format< /a>
79       */
80      private String anonymousConnection;
81  
82      /**
83       * The SCM developer connection url respecting the SCM URL Format.
84       *
85       * @parameter default-value="${project.scm.developerConnection}"
86       * @since 2.1
87       * @see <a href="http://maven.apache.org/scm/scm-url-format.html">SCM URL Format< /a>
88       */
89      private String developerConnection;
90  
91      /**
92       * The SCM web access url.
93       *
94       * @parameter default-value="${project.scm.url}"
95       * @since 2.1
96       */
97      private String webAccessUrl;
98  
99      // ----------------------------------------------------------------------
100     // Public methods
101     // ----------------------------------------------------------------------
102 
103     @Override
104     public void executeReport( Locale locale )
105     {
106         ScmRenderer r = new ScmRenderer( getLog(), scmManager, getSink(), getProject().getModel(), getI18N( locale ), locale,
107                                          checkoutDirectoryName, webAccessUrl, anonymousConnection,
108                                          developerConnection );
109 
110         r.render();
111     }
112 
113     /** {@inheritDoc} */
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     // Private
127     // ----------------------------------------------------------------------
128 
129     /**
130      * Internal renderer class
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          * To support more SCM
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             // Overview section
210             renderOverViewSection( anonymousRepository );
211 
212             // Web access section
213             renderWebAccesSection( webAccessUrl );
214 
215             // Anonymous access section if needed
216             renderAnonymousAccessSection( anonymousRepository );
217 
218             // Developer access section
219             renderDeveloperAccessSection( devRepository );
220 
221             // Access from behind a firewall section if needed
222             renderAccessBehindFirewallSection( devRepository );
223 
224             // Access through a proxy section if needed
225             renderAccessThroughProxySection( anonymousRepository, devRepository );
226         }
227 
228         /**
229          * Render the overview section
230          *
231          * @param anonymousRepository the anonymous repository
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          * Render the web access section
283          *
284          * @param scmUrl The URL to the project's browsable repository.
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          * Render the anonymous access section depending the repository.
306          * <p>Note: ClearCase, Starteam et Perforce seems to have no anonymous access.</p>
307          *
308          * @param anonymousRepository the anonymous repository
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          * Render the developer access section
353          *
354          * @param devRepository the dev repository
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          * Render the access from behind a firewall section
413          *
414          * @param devRepository the dev repository
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          * Render the access from behind a firewall section
445          *
446          * @param anonymousRepository the anonymous repository
447          * @param devRepository the dev repository
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         // Clearcase
471 
472         /**
473          * Create the documentation to provide an developer access with a <code>Clearcase</code> SCM.
474          * For example, generate the following command line:
475          * <p>cleartool checkout module</p>
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         // CVS
488 
489         /**
490          * Create the documentation to provide an anonymous access with a <code>CVS</code> SCM.
491          * For example, generate the following command line:
492          * <p>cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login</p>
493          * <p>cvs -z3 -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic co maven-plugins/dist</p>
494          *
495          * @param cvsRepo
496          * @see <a href="https://www.cvshome.org/docs/manual/cvs-1.12.12/cvs_16.html#SEC115">https://www.cvshome.org/docs/manual/cvs-1.12.12/cvs_16.html#SEC115</a>
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         // Mercurial
512 
513         /**
514          * Create the documentation to provide an anonymous access with a <code>Mercurial</code> SCM.
515          * For example, generate the following command line:
516          * <p>hg clone uri</p>
517          *
518          * @param hgRepo
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          * Create the documentation to provide an developer access with a <code>CVS</code> SCM.
534          * For example, generate the following command line:
535          * <p>cvs -d :pserver:username@cvs.apache.org:/home/cvs login</p>
536          * <p>cvs -z3 -d :ext:username@cvs.apache.org:/home/cvs co maven-plugins/dist</p>
537          *
538          * @param cvsRepo
539          * @see <a href="https://www.cvshome.org/docs/manual/cvs-1.12.12/cvs_16.html#SEC115">https://www.cvshome.org/docs/manual/cvs-1.12.12/cvs_16.html#SEC115</a>
540          */
541         private void developerAccessCVS( CvsScmProviderRepository cvsRepo )
542         {
543             paragraph( getI18nString( "devaccess.cvs.intro" ) );
544 
545             // Safety: remove the username if present
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         // Mercurial
557 
558         /**
559          * Create the documentation to provide an developer access with a <code>Mercurial</code> SCM.
560          * For example, generate the following command line:
561          * <p>hg clone repo </p>
562          *
563          * @param hgRepo
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         // Perforce
579 
580         /**
581          * Create the documentation to provide an developer access with a <code>Perforce</code> SCM.
582          * For example, generate the following command line:
583          * <p>p4 -H hostname -p port -u username -P password path</p>
584          * <p>p4 -H hostname -p port -u username -P password path submit -c changement</p>
585          *
586          * @param perforceRepo
587          * @see <a href="http://www.perforce.com/perforce/doc.051/manuals/cmdref/index.html">http://www.perforce.com/perforce/doc.051/manuals/cmdref/index.html</>
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         // Starteam
614 
615         /**
616          * Create the documentation to provide an developer access with a <code>Starteam</code> SCM.
617          * For example, generate the following command line:
618          * <p>stcmd co -x -nologo -stop -p myusername:mypassword@myhost:1234/projecturl -is</p>
619          * <p>stcmd ci -x -nologo -stop -p myusername:mypassword@myhost:1234/projecturl -f NCI -is</p>
620          *
621          * @param starteamRepo
622          */
623         private void developerAccessStarteam( StarteamScmProviderRepository starteamRepo )
624         {
625             paragraph( getI18nString( "devaccess.starteam.intro" ) );
626 
627             StringBuffer command = new StringBuffer();
628 
629             // Safety: remove the username/password if present
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         // SVN
645 
646         /**
647          * Create the documentation to provide an anonymous access with a <code>SVN</code> SCM.
648          * For example, generate the following command line:
649          * <p>svn checkout http://svn.apache.org/repos/asf/maven/components/trunk maven</p>
650          *
651          * @param svnRepo
652          * @see <a href="http://svnbook.red-bean.com/">http://svnbook.red-bean.com/</a>
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          * Create the documentation to provide an developer access with a <code>SVN</code> SCM.
666          * For example, generate the following command line:
667          * <p>svn checkout https://svn.apache.org/repos/asf/maven/components/trunk maven</p>
668          * <p>svn commit --username your-username -m "A message"</p>
669          *
670          * @param svnRepo
671          * @see <a href="http://svnbook.red-bean.com/">http://svnbook.red-bean.com/</a>
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          * Return a <code>SCM repository</code> defined by a given url
711          *
712          * @param scmUrl an SCM URL
713          * @return a valid SCM repository or null
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                     // Ignore NoSuchScmProviderException msg
741                     // See impl of AbstractScmManager#validateScmRepository()
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                 // Should be already catched
788                 if ( log.isDebugEnabled() )
789                 {
790                     log.debug( e.getMessage(), e );
791                 }
792             }
793 
794             return repo;
795         }
796 
797         /**
798          * Convenience method that return true is the defined <code>SCM repository</code> is a known provider.
799          * <p>
800          * Actually, we fully support Clearcase, CVS, Perforce, Starteam, SVN by the maven-scm-providers component.
801          * </p>
802          *
803          * @param scmRepository a SCM repository
804          * @param scmProvider a SCM provider name
805          * @return true if the provider of the given SCM repository is equal to the given scm provider.
806          * @see <a href="http://svn.apache.org/repos/asf/maven/scm/trunk/maven-scm-providers/">maven-scm-providers</a>
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 }