001    package org.apache.maven.scm.provider.svn.svnexe.command;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     * http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.io.File;
023    import java.io.FileOutputStream;
024    import java.io.IOException;
025    import java.io.PrintStream;
026    import java.util.List;
027    
028    import org.apache.maven.scm.log.ScmLogger;
029    import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
030    import org.apache.maven.scm.provider.svn.util.SvnUtil;
031    import org.codehaus.plexus.util.Os;
032    import org.codehaus.plexus.util.StringUtils;
033    import org.codehaus.plexus.util.cli.CommandLineException;
034    import org.codehaus.plexus.util.cli.CommandLineUtils;
035    import org.codehaus.plexus.util.cli.Commandline;
036    import org.codehaus.plexus.util.cli.StreamConsumer;
037    
038    /**
039     * Command line construction utility.
040     *
041     * @author Brett Porter
042     * @author Olivier Lamy
043     * @version $Id: SvnCommandLineUtils.java 1325497 2012-04-12 20:38:55Z rfscholte $
044     */
045    public final class SvnCommandLineUtils
046    {
047        private SvnCommandLineUtils()
048        {
049        }
050    
051        public static void addTarget( Commandline cl, List<File> files )
052            throws IOException
053        {
054            if ( files == null || files.isEmpty() )
055            {
056                return;
057            }
058    
059            StringBuilder sb = new StringBuilder();
060            String ls = System.getProperty( "line.separator" );
061            for ( File f : files )
062            {
063                sb.append( f.getPath().replace( '\\', '/' ) );
064                sb.append( ls );
065            }
066    
067            File targets = File.createTempFile( "maven-scm-", "-targets" );
068            PrintStream out = new PrintStream( new FileOutputStream( targets ) );
069            out.print( sb.toString() );
070            out.flush();
071            out.close();
072    
073            cl.createArg().setValue( "--targets" );
074            cl.createArg().setValue( targets.getAbsolutePath() );
075    
076            targets.deleteOnExit();
077        }
078    
079        public static Commandline getBaseSvnCommandLine( File workingDirectory, SvnScmProviderRepository repository )
080        {
081            Commandline cl = new Commandline();
082    
083            cl.setExecutable( "svn" );
084            try
085            {
086                cl.addSystemEnvironment();
087                cl.addEnvironment( "LC_MESSAGES", "C" );
088            }
089            catch ( Exception e )
090            {
091                //Do nothing
092            }
093    
094            if ( workingDirectory != null )
095            {
096                cl.setWorkingDirectory( workingDirectory.getAbsolutePath() );
097            }
098    
099            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    }