001package org.apache.maven.scm.provider.starteam; 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.IOException; 024import java.util.ArrayList; 025import java.util.List; 026 027import org.apache.maven.scm.CommandParameters; 028import org.apache.maven.scm.ScmException; 029import org.apache.maven.scm.ScmFileSet; 030import org.apache.maven.scm.command.add.AddScmResult; 031import org.apache.maven.scm.command.changelog.ChangeLogScmResult; 032import org.apache.maven.scm.command.checkin.CheckInScmResult; 033import org.apache.maven.scm.command.checkout.CheckOutScmResult; 034import org.apache.maven.scm.command.diff.DiffScmResult; 035import org.apache.maven.scm.command.edit.EditScmResult; 036import org.apache.maven.scm.command.remove.RemoveScmResult; 037import org.apache.maven.scm.command.status.StatusScmResult; 038import org.apache.maven.scm.command.tag.TagScmResult; 039import org.apache.maven.scm.command.unedit.UnEditScmResult; 040import org.apache.maven.scm.command.update.UpdateScmResult; 041import org.apache.maven.scm.provider.AbstractScmProvider; 042import org.apache.maven.scm.provider.ScmProviderRepository; 043import org.apache.maven.scm.provider.starteam.command.add.StarteamAddCommand; 044import org.apache.maven.scm.provider.starteam.command.changelog.StarteamChangeLogCommand; 045import org.apache.maven.scm.provider.starteam.command.checkin.StarteamCheckInCommand; 046import org.apache.maven.scm.provider.starteam.command.checkout.StarteamCheckOutCommand; 047import org.apache.maven.scm.provider.starteam.command.diff.StarteamDiffCommand; 048import org.apache.maven.scm.provider.starteam.command.edit.StarteamEditCommand; 049import org.apache.maven.scm.provider.starteam.command.remove.StarteamRemoveCommand; 050import org.apache.maven.scm.provider.starteam.command.status.StarteamStatusCommand; 051import org.apache.maven.scm.provider.starteam.command.tag.StarteamTagCommand; 052import org.apache.maven.scm.provider.starteam.command.unedit.StarteamUnEditCommand; 053import org.apache.maven.scm.provider.starteam.command.update.StarteamUpdateCommand; 054import org.apache.maven.scm.provider.starteam.repository.StarteamScmProviderRepository; 055import org.apache.maven.scm.repository.ScmRepositoryException; 056import org.codehaus.plexus.util.StringUtils; 057 058/** 059 * @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a> 060 * 061 * @plexus.component role="org.apache.maven.scm.provider.ScmProvider" role-hint="starteam" 062 */ 063public class StarteamScmProvider 064 extends AbstractScmProvider 065{ 066 public static final String STARTEAM_URL_FORMAT = 067 "[username[:password]@]hostname:port:/projectName/[viewName/][folderHiearchy/]"; 068 069 // ---------------------------------------------------------------------- 070 // ScmProvider Implementation 071 // ---------------------------------------------------------------------- 072 073 /** {@inheritDoc} */ 074 public ScmProviderRepository makeProviderScmRepository( String scmSpecificUrl, char delimiter ) 075 throws ScmRepositoryException 076 { 077 String user = null; 078 079 String password = null; 080 081 int index = scmSpecificUrl.indexOf( '@' ); 082 083 String rest = scmSpecificUrl; 084 085 if ( index != -1 ) 086 { 087 String userAndPassword = scmSpecificUrl.substring( 0, index ); 088 089 rest = scmSpecificUrl.substring( index + 1 ); 090 091 index = userAndPassword.indexOf( ':' ); 092 093 if ( index != -1 ) 094 { 095 user = userAndPassword.substring( 0, index ); 096 097 password = userAndPassword.substring( index + 1 ); 098 } 099 else 100 { 101 user = userAndPassword; 102 } 103 } 104 105 String[] tokens = StringUtils.split( rest, Character.toString( delimiter ) ); 106 107 String host; 108 109 int port; 110 111 String path; 112 113 if ( tokens.length == 3 ) 114 { 115 host = tokens[0]; 116 117 port = Integer.valueOf( tokens[1] ).intValue(); 118 119 path = tokens[2]; 120 } 121 else if ( tokens.length == 2 ) 122 { 123 if ( getLogger().isWarnEnabled() ) 124 { 125 getLogger().warn( 126 "Your scm URL use a deprecated format. The new format is :" 127 + STARTEAM_URL_FORMAT ); 128 } 129 130 host = tokens[0]; 131 132 if ( tokens[1].indexOf( '/' ) == -1 ) 133 { 134 throw new ScmRepositoryException( 135 "Invalid SCM URL: The url has to be on the form: " + STARTEAM_URL_FORMAT ); 136 } 137 138 int at = tokens[1].indexOf( '/' ); 139 140 port = new Integer( tokens[1].substring( 0, at ) ).intValue(); 141 142 path = tokens[1].substring( at ); 143 } 144 else 145 { 146 throw new ScmRepositoryException( 147 "Invalid SCM URL: The url has to be on the form: " + STARTEAM_URL_FORMAT ); 148 } 149 150 try 151 { 152 return new StarteamScmProviderRepository( user, password, host, port, path ); 153 } 154 catch ( Exception e ) 155 { 156 throw new ScmRepositoryException( 157 "Invalid SCM URL: The url has to be on the form: " + STARTEAM_URL_FORMAT ); 158 } 159 } 160 161 public String getScmType() 162 { 163 return "starteam"; 164 } 165 166 /** {@inheritDoc} */ 167 public AddScmResult add( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 168 throws ScmException 169 { 170 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 171 172 StarteamAddCommand command = new StarteamAddCommand(); 173 174 command.setLogger( getLogger() ); 175 176 return (AddScmResult) command.execute( repository, fileSet, parameters ); 177 } 178 179 /** {@inheritDoc} */ 180 public ChangeLogScmResult changelog( ScmProviderRepository repository, ScmFileSet fileSet, 181 CommandParameters parameters ) 182 throws ScmException 183 { 184 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 185 186 StarteamChangeLogCommand command = new StarteamChangeLogCommand(); 187 188 command.setLogger( getLogger() ); 189 190 return (ChangeLogScmResult) command.execute( repository, fileSet, parameters ); 191 } 192 193 /** {@inheritDoc} */ 194 public CheckInScmResult checkin( ScmProviderRepository repository, ScmFileSet fileSet, 195 CommandParameters parameters ) 196 throws ScmException 197 { 198 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 199 200 StarteamCheckInCommand command = new StarteamCheckInCommand(); 201 202 command.setLogger( getLogger() ); 203 204 return (CheckInScmResult) command.execute( repository, fileSet, parameters ); 205 } 206 207 /** {@inheritDoc} */ 208 public CheckOutScmResult checkout( ScmProviderRepository repository, ScmFileSet fileSet, 209 CommandParameters parameters ) 210 throws ScmException 211 { 212 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 213 214 StarteamCheckOutCommand command = new StarteamCheckOutCommand(); 215 216 command.setLogger( getLogger() ); 217 218 return (CheckOutScmResult) command.execute( repository, fileSet, parameters ); 219 } 220 221 /** {@inheritDoc} */ 222 public DiffScmResult diff( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 223 throws ScmException 224 { 225 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 226 227 StarteamDiffCommand command = new StarteamDiffCommand(); 228 229 command.setLogger( getLogger() ); 230 231 return (DiffScmResult) command.execute( repository, fileSet, parameters ); 232 } 233 234 /** {@inheritDoc} */ 235 public StatusScmResult status( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 236 throws ScmException 237 { 238 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 239 240 StarteamStatusCommand command = new StarteamStatusCommand(); 241 242 command.setLogger( getLogger() ); 243 244 return (StatusScmResult) command.execute( repository, fileSet, parameters ); 245 } 246 247 /** {@inheritDoc} */ 248 public TagScmResult tag( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 249 throws ScmException 250 { 251 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 252 253 StarteamTagCommand command = new StarteamTagCommand(); 254 255 command.setLogger( getLogger() ); 256 257 return (TagScmResult) command.execute( repository, fileSet, parameters ); 258 } 259 260 /** {@inheritDoc} */ 261 public UpdateScmResult update( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 262 throws ScmException 263 { 264 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 265 266 StarteamUpdateCommand command = new StarteamUpdateCommand(); 267 268 command.setLogger( getLogger() ); 269 270 return (UpdateScmResult) command.execute( repository, fileSet, parameters ); 271 } 272 273 /** {@inheritDoc} */ 274 protected EditScmResult edit( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 275 throws ScmException 276 { 277 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 278 279 StarteamEditCommand command = new StarteamEditCommand(); 280 281 command.setLogger( getLogger() ); 282 283 return (EditScmResult) command.execute( repository, fileSet, parameters ); 284 } 285 286 /** {@inheritDoc} */ 287 protected UnEditScmResult unedit( ScmProviderRepository repository, ScmFileSet fileSet, 288 CommandParameters parameters ) 289 throws ScmException 290 { 291 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 292 293 StarteamUnEditCommand command = new StarteamUnEditCommand(); 294 295 command.setLogger( getLogger() ); 296 297 return (UnEditScmResult) command.execute( repository, fileSet, parameters ); 298 } 299 300 /** {@inheritDoc} */ 301 public RemoveScmResult remove( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 302 throws ScmException 303 { 304 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 305 306 StarteamRemoveCommand command = new StarteamRemoveCommand(); 307 308 command.setLogger( getLogger() ); 309 310 return (RemoveScmResult) command.execute( repository, fileSet, parameters ); 311 } 312 313 /** 314 * Starteam provider requires that all files in ScmFileSet must be relative to basedir 315 * This function ensures and converts all absolute paths to relative paths 316 * 317 * @param currentFileSet 318 * @return 319 * @throws ScmException 320 */ 321 private static ScmFileSet fixUpScmFileSetAbsoluteFilePath( ScmFileSet currentFileSet ) 322 throws ScmException 323 { 324 ScmFileSet newFileSet = null; 325 326 try 327 { 328 File basedir = getAbsoluteFilePath( currentFileSet.getBasedir() ); 329 330 List<File> files = currentFileSet.getFileList(); 331 332 List<File> relPathFiles = new ArrayList<File>( files.size() ); 333 334 for ( File file : files ) 335 { 336 if ( file.isAbsolute() ) 337 { 338 file = new File( getRelativePath( basedir, file ) ); 339 } 340 relPathFiles.add( file ); 341 } 342 343 newFileSet = new ScmFileSet( basedir, relPathFiles ); 344 } 345 catch ( IOException e ) 346 { 347 throw new ScmException( "Invalid file set.", e ); 348 } 349 350 return newFileSet; 351 } 352 353 public static String getRelativePath( File basedir, File f ) 354 throws ScmException, IOException 355 { 356 File fileOrDir = getAbsoluteFilePath( f ); 357 358 if ( !fileOrDir.getCanonicalPath().startsWith( basedir.getCanonicalPath() ) ) 359 { 360 throw new ScmException( fileOrDir.getPath() + " was not contained in " + basedir.getPath() ); 361 } 362 363 if ( basedir.getCanonicalFile().equals( basedir.getAbsoluteFile() ) ) 364 { 365 return fileOrDir.getPath().substring( basedir.getPath().length() + 1, fileOrDir.getPath().length() ); 366 } 367 return fileOrDir.getPath().substring( basedir.getCanonicalPath().length() + 1, fileOrDir.getPath().length() ); 368 } 369 370 private static File getAbsoluteFilePath( File fileOrDir ) 371 throws IOException 372 { 373 String javaPathString = fileOrDir.getCanonicalPath().replace( '\\', '/' ); 374 375 if ( javaPathString.endsWith( "/" ) ) 376 { 377 javaPathString = javaPathString.substring( 0, javaPathString.length() - 1 ); 378 } 379 380 return new File( javaPathString ); 381 } 382}