001package 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 022import java.io.File; 023import java.io.FileOutputStream; 024import java.io.IOException; 025import java.io.PrintStream; 026import java.util.List; 027 028import org.apache.maven.scm.log.ScmLogger; 029import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository; 030import org.apache.maven.scm.provider.svn.util.SvnUtil; 031import org.codehaus.plexus.util.Os; 032import org.codehaus.plexus.util.StringUtils; 033import org.codehaus.plexus.util.cli.CommandLineException; 034import org.codehaus.plexus.util.cli.CommandLineUtils; 035import org.codehaus.plexus.util.cli.Commandline; 036import org.codehaus.plexus.util.cli.StreamConsumer; 037 038/** 039 * Command line construction utility. 040 * 041 * @author Brett Porter 042 * @author Olivier Lamy 043 * 044 */ 045public 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 { 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 logger.info( "Working directory: " + cl.getWorkingDirectory().getAbsolutePath() ); 211 } 212 } 213 214 return CommandLineUtils.executeCommandLine( cl, stdout, stderr ); 215 } 216 217 public static String cryptPassword( Commandline cl ) 218 { 219 String clString = cl.toString(); 220 221 int pos = clString.indexOf( "--password" ); 222 223 if ( pos > 0 ) 224 { 225 String beforePassword = clString.substring( 0, pos + "--password ".length() ); 226 String afterPassword = clString.substring( pos + "--password ".length() ); 227 afterPassword = afterPassword.substring( afterPassword.indexOf( ' ' ) ); 228 if ( Os.isFamily( Os.FAMILY_WINDOWS ) ) 229 { 230 clString = beforePassword + "*****" + afterPassword; 231 } 232 else 233 { 234 clString = beforePassword + "'*****'" + afterPassword; 235 } 236 } 237 238 return clString; 239 } 240}