View Javadoc
1   package org.apache.maven.scm.provider.svn.svnexe.command;
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 java.io.File;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.io.PrintStream;
26  import java.util.List;
27  
28  import org.apache.maven.scm.log.ScmLogger;
29  import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
30  import org.apache.maven.scm.provider.svn.util.SvnUtil;
31  import org.codehaus.plexus.util.Os;
32  import org.codehaus.plexus.util.StringUtils;
33  import org.codehaus.plexus.util.cli.CommandLineException;
34  import org.codehaus.plexus.util.cli.CommandLineUtils;
35  import org.codehaus.plexus.util.cli.Commandline;
36  import org.codehaus.plexus.util.cli.StreamConsumer;
37  
38  /**
39   * Command line construction utility.
40   *
41   * @author Brett Porter
42   * @author Olivier Lamy
43   *
44   */
45  public final class SvnCommandLineUtils
46  {
47      private SvnCommandLineUtils()
48      {
49      }
50  
51      public static void addTarget( Commandline cl, List<File> files )
52          throws IOException
53      {
54          if ( files == null || files.isEmpty() )
55          {
56              return;
57          }
58  
59          StringBuilder sb = new StringBuilder();
60          String ls = System.getProperty( "line.separator" );
61          for ( File f : files )
62          {
63              sb.append( f.getPath().replace( '\\', '/' ) );
64              sb.append( ls );
65          }
66  
67          File targets = File.createTempFile( "maven-scm-", "-targets" );
68          PrintStream out = new PrintStream( new FileOutputStream( targets ) );
69          out.print( sb.toString() );
70          out.flush();
71          out.close();
72  
73          cl.createArg().setValue( "--targets" );
74          cl.createArg().setValue( targets.getAbsolutePath() );
75  
76          targets.deleteOnExit();
77      }
78  
79      public static Commandline getBaseSvnCommandLine( File workingDirectory, SvnScmProviderRepository repository )
80      {
81          Commandline cl = new Commandline();
82  
83          cl.setExecutable( "svn" );
84          try
85          {
86              cl.addSystemEnvironment();
87              cl.addEnvironment( "LC_MESSAGES", "C" );
88          }
89          catch ( Exception e )
90          {
91              //Do nothing
92          }
93  
94          if ( workingDirectory != null )
95          {
96              cl.setWorkingDirectory( workingDirectory.getAbsolutePath() );
97          }
98  
99          if ( !StringUtils.isEmpty( System.getProperty( "maven.scm.svn.config_directory" ) ) )
100         {
101             cl.createArg().setValue( "--config-dir" );
102             cl.createArg().setValue( System.getProperty( "maven.scm.svn.config_directory" ) );
103         }
104         else if ( !StringUtils.isEmpty( SvnUtil.getSettings().getConfigDirectory() ) )
105         {
106             cl.createArg().setValue( "--config-dir" );
107             cl.createArg().setValue( SvnUtil.getSettings().getConfigDirectory() );
108         }
109 
110         boolean hasAuthInfo = false; 
111         if ( repository != null && !StringUtils.isEmpty( repository.getUser() ) )
112         {
113             hasAuthInfo = true; 
114             cl.createArg().setValue( "--username" );
115             cl.createArg().setValue( repository.getUser() );
116         }
117 
118         if ( repository != null && !StringUtils.isEmpty( repository.getPassword() ) )
119         {
120             hasAuthInfo = true; 
121             cl.createArg().setValue( "--password" );
122             cl.createArg().setValue( repository.getPassword() );
123         }
124 
125         // [by Lenik] don't overwrite existing auth cache by default. 
126         if ( hasAuthInfo && !SvnUtil.getSettings().isUseAuthCache() ) 
127         {
128             cl.createArg().setValue( "--no-auth-cache" ); 
129         }
130 
131         if ( SvnUtil.getSettings().isUseNonInteractive() )
132         {
133             cl.createArg().setValue( "--non-interactive" );
134         }
135 
136         if ( SvnUtil.getSettings().isTrustServerCert() )
137         {
138             cl.createArg().setValue( "--trust-server-cert" );
139         }
140 
141         return cl;
142     }
143 
144     public static int execute( Commandline cl, StreamConsumer consumer, CommandLineUtils.StringStreamConsumer stderr,
145                                ScmLogger logger )
146         throws CommandLineException
147     {
148         // SCM-482: force English resource bundle
149         cl.addEnvironment( "LC_MESSAGES", "en" );
150 
151         int exitCode = CommandLineUtils.executeCommandLine( cl, consumer, stderr );
152 
153         exitCode = checkIfCleanUpIsNeeded( exitCode, cl, consumer, stderr, logger );
154 
155         return exitCode;
156     }
157 
158     public static int execute( Commandline cl, CommandLineUtils.StringStreamConsumer stdout,
159                                CommandLineUtils.StringStreamConsumer stderr, ScmLogger logger )
160         throws CommandLineException
161     {
162         int exitCode = CommandLineUtils.executeCommandLine( cl, stdout, stderr );
163 
164         exitCode = checkIfCleanUpIsNeeded( exitCode, cl, stdout, stderr, logger );
165 
166         return exitCode;
167     }
168 
169     private static int checkIfCleanUpIsNeeded( int exitCode, Commandline cl, StreamConsumer consumer,
170                                                CommandLineUtils.StringStreamConsumer stderr, ScmLogger logger )
171         throws CommandLineException
172     {
173         if ( exitCode != 0 && stderr.getOutput() != null && stderr.getOutput().indexOf( "'svn cleanup'" ) > 0
174             && stderr.getOutput().indexOf( "'svn help cleanup'" ) > 0 )
175         {
176             if ( logger.isInfoEnabled() )
177             {
178                 logger.info( "Svn command failed due to some locks in working copy. We try to run a 'svn cleanup'." );
179             }
180 
181             if ( executeCleanUp( cl.getWorkingDirectory(), consumer, stderr, logger ) == 0 )
182             {
183                 exitCode = CommandLineUtils.executeCommandLine( cl, consumer, stderr );
184             }
185         }
186         return exitCode;
187     }
188 
189     public static int executeCleanUp( File workinDirectory, StreamConsumer stdout, StreamConsumer stderr )
190         throws CommandLineException
191     {
192         return executeCleanUp( workinDirectory, stdout, stderr, null );
193     }
194 
195     public static int executeCleanUp( File workinDirectory, StreamConsumer stdout, StreamConsumer stderr,
196                                       ScmLogger logger )
197         throws CommandLineException
198     {
199         Commandline cl = new Commandline();
200 
201         cl.setExecutable( "svn" );
202 
203         cl.setWorkingDirectory( workinDirectory.getAbsolutePath() );
204 
205         if ( logger != null )
206         {
207             if ( logger.isInfoEnabled() )
208             {
209                 logger.info( "Executing: " + SvnCommandLineUtils.cryptPassword( cl ) );
210 
211                 if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
212                 {
213                     logger.info( "Working directory: " + cl.getWorkingDirectory().getAbsolutePath() );
214                 }
215             }
216         }
217 
218         return CommandLineUtils.executeCommandLine( cl, stdout, stderr );
219     }
220 
221     public static String cryptPassword( Commandline cl )
222     {
223         String clString = cl.toString();
224 
225         int pos = clString.indexOf( "--password" );
226 
227         if ( pos > 0 )
228         {
229             String beforePassword = clString.substring( 0, pos + "--password ".length() );
230             String afterPassword = clString.substring( pos + "--password ".length() );
231             afterPassword = afterPassword.substring( afterPassword.indexOf( ' ' ) );
232             if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
233             {
234                 clString = beforePassword + "*****" + afterPassword;
235             }
236             else
237             {
238                 clString = beforePassword + "'*****'" + afterPassword;
239             }
240         }
241 
242         return clString;
243     }
244 }