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             cl.createArg().setValue( "--non-interactive" );
133         }
134         
135         if (SvnUtil.getSettings().isTrustServerCert()) {
136             cl.createArg().setValue( "--trust-server-cert" );
137         }
138 
139         return cl;
140     }
141 
142     public static int execute( Commandline cl, StreamConsumer consumer, CommandLineUtils.StringStreamConsumer stderr,
143                                ScmLogger logger )
144         throws CommandLineException
145     {
146         // SCM-482: force English resource bundle
147         cl.addEnvironment( "LC_MESSAGES", "en" );
148 
149         int exitCode = CommandLineUtils.executeCommandLine( cl, consumer, stderr );
150 
151         exitCode = checkIfCleanUpIsNeeded( exitCode, cl, consumer, stderr, logger );
152 
153         return exitCode;
154     }
155 
156     public static int execute( Commandline cl, CommandLineUtils.StringStreamConsumer stdout,
157                                CommandLineUtils.StringStreamConsumer stderr, ScmLogger logger )
158         throws CommandLineException
159     {
160         int exitCode = CommandLineUtils.executeCommandLine( cl, stdout, stderr );
161 
162         exitCode = checkIfCleanUpIsNeeded( exitCode, cl, stdout, stderr, logger );
163 
164         return exitCode;
165     }
166 
167     private static int checkIfCleanUpIsNeeded( int exitCode, Commandline cl, StreamConsumer consumer,
168                                                CommandLineUtils.StringStreamConsumer stderr, ScmLogger logger )
169         throws CommandLineException
170     {
171         if ( exitCode != 0 && stderr.getOutput() != null && stderr.getOutput().indexOf( "'svn cleanup'" ) > 0
172             && stderr.getOutput().indexOf( "'svn help cleanup'" ) > 0 )
173         {
174             if ( logger.isInfoEnabled() )
175             {
176                 logger.info( "Svn command failed due to some locks in working copy. We try to run a 'svn cleanup'." );
177             }
178 
179             if ( executeCleanUp( cl.getWorkingDirectory(), consumer, stderr, logger ) == 0 )
180             {
181                 exitCode = CommandLineUtils.executeCommandLine( cl, consumer, stderr );
182             }
183         }
184         return exitCode;
185     }
186 
187     public static int executeCleanUp( File workinDirectory, StreamConsumer stdout, StreamConsumer stderr )
188         throws CommandLineException
189     {
190         return executeCleanUp( workinDirectory, stdout, stderr, null );
191     }
192 
193     public static int executeCleanUp( File workinDirectory, StreamConsumer stdout, StreamConsumer stderr,
194                                       ScmLogger logger )
195         throws CommandLineException
196     {
197         Commandline cl = new Commandline();
198 
199         cl.setExecutable( "svn" );
200 
201         cl.setWorkingDirectory( workinDirectory.getAbsolutePath() );
202 
203         if ( logger != null )
204         {
205             if ( logger.isInfoEnabled() )
206             {
207                 logger.info( "Executing: " + SvnCommandLineUtils.cryptPassword( cl ) );
208                 logger.info( "Working directory: " + cl.getWorkingDirectory().getAbsolutePath() );
209             }
210         }
211 
212         return CommandLineUtils.executeCommandLine( cl, stdout, stderr );
213     }
214 
215     public static String cryptPassword( Commandline cl )
216     {
217         String clString = cl.toString();
218 
219         int pos = clString.indexOf( "--password" );
220 
221         if ( pos > 0 )
222         {
223             String beforePassword = clString.substring( 0, pos + "--password ".length() );
224             String afterPassword = clString.substring( pos + "--password ".length() );
225             afterPassword = afterPassword.substring( afterPassword.indexOf( ' ' ) );
226             if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
227             {
228                 clString = beforePassword + "*****" + afterPassword;
229             }
230             else
231             {
232                 clString = beforePassword + "'*****'" + afterPassword;
233             }
234         }
235 
236         return clString;
237     }
238 }