001 package org.apache.maven.scm.provider.svn; 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 org.apache.maven.scm.CommandParameters; 023 import org.apache.maven.scm.ScmException; 024 import org.apache.maven.scm.ScmFileSet; 025 import org.apache.maven.scm.ScmResult; 026 import org.apache.maven.scm.command.add.AddScmResult; 027 import org.apache.maven.scm.command.blame.BlameScmResult; 028 import org.apache.maven.scm.command.branch.BranchScmResult; 029 import org.apache.maven.scm.command.changelog.ChangeLogScmResult; 030 import org.apache.maven.scm.command.checkin.CheckInScmResult; 031 import org.apache.maven.scm.command.checkout.CheckOutScmResult; 032 import org.apache.maven.scm.command.diff.DiffScmResult; 033 import org.apache.maven.scm.command.export.ExportScmResult; 034 import org.apache.maven.scm.command.info.InfoScmResult; 035 import org.apache.maven.scm.command.list.ListScmResult; 036 import org.apache.maven.scm.command.mkdir.MkdirScmResult; 037 import org.apache.maven.scm.command.remove.RemoveScmResult; 038 import org.apache.maven.scm.command.status.StatusScmResult; 039 import org.apache.maven.scm.command.tag.TagScmResult; 040 import org.apache.maven.scm.command.update.UpdateScmResult; 041 import org.apache.maven.scm.provider.AbstractScmProvider; 042 import org.apache.maven.scm.provider.ScmProviderRepository; 043 import org.apache.maven.scm.provider.svn.command.SvnCommand; 044 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository; 045 import org.apache.maven.scm.provider.svn.util.SvnUtil; 046 import org.apache.maven.scm.repository.ScmRepositoryException; 047 import org.apache.maven.scm.repository.UnknownRepositoryStructure; 048 import org.codehaus.plexus.util.StringUtils; 049 050 import java.io.File; 051 import java.util.ArrayList; 052 import java.util.List; 053 054 /** 055 * SCM Provider for Subversion 056 * 057 * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a> 058 * @version $Id: AbstractSvnScmProvider.java 1380486 2012-09-04 08:33:18Z olamy $ 059 */ 060 public abstract class AbstractSvnScmProvider 061 extends AbstractScmProvider 062 { 063 // ---------------------------------------------------------------------- 064 // 065 // ---------------------------------------------------------------------- 066 067 private static class ScmUrlParserResult 068 { 069 private List<String> messages = new ArrayList<String>(); 070 071 private ScmProviderRepository repository; 072 } 073 074 // ---------------------------------------------------------------------- 075 // ScmProvider Implementation 076 // ---------------------------------------------------------------------- 077 078 /** 079 * {@inheritDoc} 080 */ 081 public String getScmSpecificFilename() 082 { 083 return ".svn"; 084 } 085 086 /** 087 * {@inheritDoc} 088 */ 089 public ScmProviderRepository makeProviderScmRepository( String scmSpecificUrl, char delimiter ) 090 throws ScmRepositoryException 091 { 092 ScmUrlParserResult result = parseScmUrl( scmSpecificUrl ); 093 094 if ( result.messages.size() > 0 ) 095 { 096 throw new ScmRepositoryException( "The scm url is invalid.", result.messages ); 097 } 098 099 return result.repository; 100 } 101 102 /** 103 * {@inheritDoc} 104 */ 105 public ScmProviderRepository makeProviderScmRepository( File path ) 106 throws ScmRepositoryException, UnknownRepositoryStructure 107 { 108 if ( path == null ) 109 { 110 throw new NullPointerException( "Path argument is null" ); 111 } 112 113 if ( !path.isDirectory() ) 114 { 115 throw new ScmRepositoryException( path.getAbsolutePath() + " isn't a valid directory." ); 116 } 117 118 if ( !new File( path, ".svn" ).exists() ) 119 { 120 throw new ScmRepositoryException( path.getAbsolutePath() + " isn't a svn checkout directory." ); 121 } 122 123 try 124 { 125 return makeProviderScmRepository( getRepositoryURL( path ), ':' ); 126 } 127 catch ( ScmException e ) 128 { 129 // XXX We should allow throwing of SCMException. 130 throw new ScmRepositoryException( "Error executing info command", e ); 131 } 132 } 133 134 protected abstract String getRepositoryURL( File path ) 135 throws ScmException; 136 137 /** 138 * {@inheritDoc} 139 */ 140 public List<String> validateScmUrl( String scmSpecificUrl, char delimiter ) 141 { 142 List<String> messages = new ArrayList<String>(); 143 try 144 { 145 makeProviderScmRepository( scmSpecificUrl, delimiter ); 146 } 147 catch ( ScmRepositoryException e ) 148 { 149 messages = e.getValidationMessages(); 150 } 151 return messages; 152 } 153 154 /** 155 * {@inheritDoc} 156 */ 157 public String getScmType() 158 { 159 return "svn"; 160 } 161 162 // ---------------------------------------------------------------------- 163 // 164 // ---------------------------------------------------------------------- 165 166 private ScmUrlParserResult parseScmUrl( String scmSpecificUrl ) 167 { 168 ScmUrlParserResult result = new ScmUrlParserResult(); 169 170 String url = scmSpecificUrl; 171 172 // ---------------------------------------------------------------------- 173 // Do some sanity checking of the SVN url 174 // ---------------------------------------------------------------------- 175 176 if ( url.startsWith( "file" ) ) 177 { 178 if ( !url.startsWith( "file://" ) ) 179 { 180 result.messages.add( "A svn 'file' url must be on the form 'file://[hostname]/'." ); 181 182 return result; 183 } 184 } 185 else if ( url.startsWith( "https" ) ) 186 { 187 if ( !url.startsWith( "https://" ) ) 188 { 189 result.messages.add( "A svn 'http' url must be on the form 'https://'." ); 190 191 return result; 192 } 193 } 194 else if ( url.startsWith( "http" ) ) 195 { 196 if ( !url.startsWith( "http://" ) ) 197 { 198 result.messages.add( "A svn 'http' url must be on the form 'http://'." ); 199 200 return result; 201 } 202 } 203 // Support of tunnels: svn+xxx with xxx defined in subversion conf file 204 else if ( url.startsWith( "svn+" ) ) 205 { 206 if ( url.indexOf( "://" ) < 0 ) 207 { 208 result.messages.add( "A svn 'svn+xxx' url must be on the form 'svn+xxx://'." ); 209 210 return result; 211 } 212 else 213 { 214 String tunnel = url.substring( "svn+".length(), url.indexOf( "://" ) ); 215 216 //ssh is always an allowed tunnel 217 if ( !"ssh".equals( tunnel ) ) 218 { 219 SvnConfigFileReader reader = new SvnConfigFileReader(); 220 if ( SvnUtil.getSettings().getConfigDirectory() != null ) 221 { 222 reader.setConfigDirectory( new File( SvnUtil.getSettings().getConfigDirectory() ) ); 223 } 224 225 if ( StringUtils.isEmpty( reader.getProperty( "tunnels", tunnel ) ) ) 226 { 227 result.messages.add( 228 "The tunnel '" + tunnel + "' isn't defined in your subversion configuration file." ); 229 230 return result; 231 } 232 } 233 } 234 } 235 else if ( url.startsWith( "svn" ) ) 236 { 237 if ( !url.startsWith( "svn://" ) ) 238 { 239 result.messages.add( "A svn 'svn' url must be on the form 'svn://'." ); 240 241 return result; 242 } 243 } 244 else 245 { 246 result.messages.add( url + " url isn't a valid svn URL." ); 247 248 return result; 249 } 250 251 result.repository = new SvnScmProviderRepository( url ); 252 253 return result; 254 } 255 256 protected abstract SvnCommand getAddCommand(); 257 258 /** 259 * {@inheritDoc} 260 */ 261 public AddScmResult add( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 262 throws ScmException 263 { 264 return (AddScmResult) executeCommand( getAddCommand(), repository, fileSet, parameters ); 265 } 266 267 protected abstract SvnCommand getBranchCommand(); 268 269 /** 270 * {@inheritDoc} 271 */ 272 protected BranchScmResult branch( ScmProviderRepository repository, ScmFileSet fileSet, 273 CommandParameters parameters ) 274 throws ScmException 275 { 276 return (BranchScmResult) executeCommand( getBranchCommand(), repository, fileSet, parameters ); 277 } 278 279 protected abstract SvnCommand getChangeLogCommand(); 280 281 /** 282 * {@inheritDoc} 283 */ 284 public ChangeLogScmResult changelog( ScmProviderRepository repository, ScmFileSet fileSet, 285 CommandParameters parameters ) 286 throws ScmException 287 { 288 return (ChangeLogScmResult) executeCommand( getChangeLogCommand(), repository, fileSet, parameters ); 289 } 290 291 protected abstract SvnCommand getCheckInCommand(); 292 293 /** 294 * {@inheritDoc} 295 */ 296 public CheckInScmResult checkin( ScmProviderRepository repository, ScmFileSet fileSet, 297 CommandParameters parameters ) 298 throws ScmException 299 { 300 return (CheckInScmResult) executeCommand( getCheckInCommand(), repository, fileSet, parameters ); 301 } 302 303 protected abstract SvnCommand getCheckOutCommand(); 304 305 /** 306 * {@inheritDoc} 307 */ 308 public CheckOutScmResult checkout( ScmProviderRepository repository, ScmFileSet fileSet, 309 CommandParameters parameters ) 310 throws ScmException 311 { 312 return (CheckOutScmResult) executeCommand( getCheckOutCommand(), repository, fileSet, parameters ); 313 } 314 315 protected abstract SvnCommand getDiffCommand(); 316 317 /** 318 * {@inheritDoc} 319 */ 320 public DiffScmResult diff( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 321 throws ScmException 322 { 323 return (DiffScmResult) executeCommand( getDiffCommand(), repository, fileSet, parameters ); 324 } 325 326 protected abstract SvnCommand getExportCommand(); 327 328 /** 329 * {@inheritDoc} 330 */ 331 protected ExportScmResult export( ScmProviderRepository repository, ScmFileSet fileSet, 332 CommandParameters parameters ) 333 throws ScmException 334 { 335 return (ExportScmResult) executeCommand( getExportCommand(), repository, fileSet, parameters ); 336 } 337 338 protected abstract SvnCommand getRemoveCommand(); 339 340 /** 341 * {@inheritDoc} 342 */ 343 public RemoveScmResult remove( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 344 throws ScmException 345 { 346 return (RemoveScmResult) executeCommand( getRemoveCommand(), repository, fileSet, parameters ); 347 } 348 349 protected abstract SvnCommand getStatusCommand(); 350 351 /** 352 * {@inheritDoc} 353 */ 354 public StatusScmResult status( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 355 throws ScmException 356 { 357 return (StatusScmResult) executeCommand( getStatusCommand(), repository, fileSet, parameters ); 358 } 359 360 protected abstract SvnCommand getTagCommand(); 361 362 /** 363 * {@inheritDoc} 364 */ 365 public TagScmResult tag( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 366 throws ScmException 367 { 368 return (TagScmResult) executeCommand( getTagCommand(), repository, fileSet, parameters ); 369 } 370 371 protected abstract SvnCommand getUpdateCommand(); 372 373 /** 374 * {@inheritDoc} 375 */ 376 public UpdateScmResult update( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 377 throws ScmException 378 { 379 return (UpdateScmResult) executeCommand( getUpdateCommand(), repository, fileSet, parameters ); 380 } 381 382 protected ScmResult executeCommand( SvnCommand command, ScmProviderRepository repository, ScmFileSet fileSet, 383 CommandParameters parameters ) 384 throws ScmException 385 { 386 command.setLogger( getLogger() ); 387 388 return command.execute( repository, fileSet, parameters ); 389 } 390 391 protected abstract SvnCommand getListCommand(); 392 393 /** 394 * {@inheritDoc} 395 */ 396 public ListScmResult list( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 397 throws ScmException 398 { 399 SvnCommand cmd = getListCommand(); 400 401 return (ListScmResult) executeCommand( cmd, repository, fileSet, parameters ); 402 } 403 404 protected abstract SvnCommand getInfoCommand(); 405 406 public InfoScmResult info( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 407 throws ScmException 408 { 409 SvnCommand cmd = getInfoCommand(); 410 411 return (InfoScmResult) executeCommand( cmd, repository, fileSet, parameters ); 412 } 413 414 /** 415 * {@inheritDoc} 416 */ 417 protected BlameScmResult blame( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 418 throws ScmException 419 { 420 SvnCommand cmd = getBlameCommand(); 421 422 return (BlameScmResult) executeCommand( cmd, repository, fileSet, parameters ); 423 } 424 425 protected abstract SvnCommand getBlameCommand(); 426 427 /** 428 * {@inheritDoc} 429 */ 430 public MkdirScmResult mkdir( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 431 throws ScmException 432 { 433 SvnCommand cmd = getMkdirCommand(); 434 435 return (MkdirScmResult) executeCommand( cmd, repository, fileSet, parameters ); 436 } 437 438 protected abstract SvnCommand getMkdirCommand(); 439 440 /** 441 * @param repository 442 * @param parameters 443 * @return true if remote url exists 444 * @throws ScmException 445 * @since 1.8 446 */ 447 public abstract boolean remoteUrlExist( ScmProviderRepository repository, CommandParameters parameters ) 448 throws ScmException; 449 }