Coverage Report - org.apache.maven.scm.provider.clearcase.command.checkout.ClearCaseCheckOutCommand
 
Classes in this File Line Coverage Branch Coverage Complexity
ClearCaseCheckOutCommand
40 %
50/125
27 %
15/54
3,467
 
 1  
 package org.apache.maven.scm.provider.clearcase.command.checkout;
 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.FileWriter;
 24  
 import java.io.IOException;
 25  
 import java.net.InetAddress;
 26  
 import java.net.UnknownHostException;
 27  
 
 28  
 import org.apache.maven.scm.ScmException;
 29  
 import org.apache.maven.scm.ScmFileSet;
 30  
 import org.apache.maven.scm.ScmVersion;
 31  
 import org.apache.maven.scm.command.checkout.AbstractCheckOutCommand;
 32  
 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
 33  
 import org.apache.maven.scm.provider.ScmProviderRepository;
 34  
 import org.apache.maven.scm.provider.clearcase.command.ClearCaseCommand;
 35  
 import org.apache.maven.scm.provider.clearcase.repository.ClearCaseScmProviderRepository;
 36  
 import org.apache.maven.scm.providers.clearcase.settings.Settings;
 37  
 import org.codehaus.plexus.util.FileUtils;
 38  
 import org.codehaus.plexus.util.StringUtils;
 39  
 import org.codehaus.plexus.util.cli.CommandLineException;
 40  
 import org.codehaus.plexus.util.cli.CommandLineUtils;
 41  
 import org.codehaus.plexus.util.cli.Commandline;
 42  
 
 43  
 /**
 44  
  * @author <a href="mailto:wim.deblauwe@gmail.com">Wim Deblauwe</a>
 45  
  * @author <a href="mailto:frederic.mura@laposte.net">Frederic Mura</a>
 46  
  * @version $Id: ClearCaseCheckOutCommand.java 1306867 2012-03-29 13:45:10Z olamy $
 47  
  */
 48  4
 public class ClearCaseCheckOutCommand
 49  
     extends AbstractCheckOutCommand
 50  
     implements ClearCaseCommand
 51  
 {
 52  4
     private Settings settings = null;
 53  
 
 54  
     // ----------------------------------------------------------------------
 55  
     // AbstractCheckOutCommand Implementation
 56  
     // ----------------------------------------------------------------------
 57  
 
 58  
     /** {@inheritDoc} */
 59  
     protected CheckOutScmResult executeCheckOutCommand( ScmProviderRepository repository, ScmFileSet fileSet,
 60  
                                                         ScmVersion version, boolean recursive )
 61  
         throws ScmException
 62  
     {
 63  0
         if ( getLogger().isDebugEnabled() )
 64  
         {
 65  0
             getLogger().debug( "executing checkout command..." );
 66  
         }
 67  0
         ClearCaseScmProviderRepository repo = (ClearCaseScmProviderRepository) repository;
 68  0
         File workingDirectory = fileSet.getBasedir();
 69  
 
 70  0
         if ( version != null && getLogger().isDebugEnabled() )
 71  
         {
 72  0
             getLogger().debug( version.getType() + ": " + version.getName() );
 73  
         }
 74  
 
 75  0
         if ( getLogger().isDebugEnabled() )
 76  
         {
 77  0
             getLogger().debug( "Running with CLEARCASE " + settings.getClearcaseType() );
 78  
         }
 79  
 
 80  0
         ClearCaseCheckOutConsumer consumer = new ClearCaseCheckOutConsumer( getLogger() );
 81  
 
 82  0
         CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
 83  
 
 84  
         int exitCode;
 85  
 
 86  
         Commandline cl;
 87  0
         String projectDirectory = "";
 88  
 
 89  
         try
 90  
         {
 91  
             // Since clearcase only wants to checkout to a non-existent directory, first delete the working dir
 92  
             // if it already exists
 93  0
             FileUtils.deleteDirectory( workingDirectory );
 94  
             // First create the view
 95  0
             String viewName = getUniqueViewName( repo, workingDirectory.getAbsolutePath() );
 96  0
             String streamIdentifier = getStreamIdentifier( repo.getStreamName(), repo.getVobName() );
 97  0
             cl = createCreateViewCommandLine( workingDirectory, viewName, streamIdentifier );
 98  0
             if ( getLogger().isInfoEnabled() )
 99  
             {
 100  0
                 getLogger().info( "Executing: " + cl.getWorkingDirectory().getAbsolutePath() + ">>" + cl.toString() );
 101  
             }
 102  0
             exitCode =
 103  
                 CommandLineUtils.executeCommandLine( cl, new CommandLineUtils.StringStreamConsumer(), stderr );
 104  
 
 105  0
             if ( exitCode == 0 )
 106  
             {
 107  
                 File configSpecLocation;
 108  
 
 109  0
                 if ( !repo.isAutoConfigSpec() )
 110  
                 {
 111  0
                     configSpecLocation = repo.getConfigSpec();
 112  0
                     if ( version != null && StringUtils.isNotEmpty( version.getName() ) )
 113  
                     {
 114  
                         // Another config spec is needed in this case.
 115  
                         //
 116  
                         // One option how to implement this would be to use a name convention for the config specs,
 117  
                         // e.g. the tag name could be appended to the original config spec name.
 118  
                         // If the config spec from the SCM URL would be \\myserver\configspecs\someproj.txt
 119  
                         // and the tag name would be mytag, the new config spec location could be
 120  
                         // \\myserver\configspecs\someproj-mytag.txt
 121  
                         //
 122  0
                         throw new UnsupportedOperationException(
 123  
                             "Building on a label not supported with user-specified config specs" );
 124  
                     }
 125  
                 }
 126  
                 else
 127  
                 {
 128  
 
 129  
                     // write config spec to temp file
 130  
                     String configSpec;
 131  0
                     if ( !repo.hasElements() )
 132  
                     {
 133  0
                         configSpec = createConfigSpec( repo.getLoadDirectory(), version );
 134  
                     }
 135  
                     else
 136  
                     {
 137  0
                         configSpec = createConfigSpec( repo.getLoadDirectory(), repo.getElementName(), version );
 138  
                     }
 139  0
                     if ( getLogger().isInfoEnabled() )
 140  
                     {
 141  0
                         getLogger().info( "Created config spec for view '" + viewName + "':\n" + configSpec );
 142  
                     }
 143  0
                     configSpecLocation = writeTemporaryConfigSpecFile( configSpec, viewName );
 144  
 
 145  
                     // When checking out from ClearCase, the directory structure of the
 146  
                     // SCM system is repeated within the checkout directory. E.g. if you check out the
 147  
                     // project "my/project" to "/some/dir", the project sources are actually checked out
 148  
                     // to "my/project/some/dir".
 149  0
                     projectDirectory = repo.getLoadDirectory();
 150  
                     // strip off leading / to make the path relative
 151  0
                     if ( projectDirectory.startsWith( "/" ) )
 152  
                     {
 153  0
                         projectDirectory = projectDirectory.substring( 1 );
 154  
                     }
 155  
                 }
 156  
 
 157  0
                 cl = createUpdateConfigSpecCommandLine( workingDirectory, configSpecLocation, viewName );
 158  
 
 159  0
                 if ( getLogger().isInfoEnabled() )
 160  
                 {
 161  0
                     getLogger().info( "Executing: " + cl.getWorkingDirectory().getAbsolutePath() + ">>" + cl.toString() );
 162  
                 }
 163  0
                 exitCode = CommandLineUtils.executeCommandLine( cl, consumer, stderr );
 164  
 
 165  
             }
 166  
         }
 167  0
         catch ( CommandLineException ex )
 168  
         {
 169  0
             throw new ScmException( "Error while executing clearcase command.", ex );
 170  
         }
 171  0
         catch ( IOException ex )
 172  
         {
 173  0
             throw new ScmException( "Error while deleting working directory.", ex );
 174  0
         }
 175  
 
 176  0
         if ( exitCode != 0 )
 177  
         {
 178  0
             return new CheckOutScmResult( cl.toString(), "The cleartool command failed.", stderr.getOutput(), false );
 179  
         }
 180  
 
 181  0
         return new CheckOutScmResult( cl.toString(), consumer.getCheckedOutFiles(), projectDirectory );
 182  
     }
 183  
 
 184  
     // ----------------------------------------------------------------------
 185  
     //
 186  
     // ----------------------------------------------------------------------
 187  
 
 188  
     /**
 189  
      * Creates a temporary config spec file with the given contents that will be
 190  
      * deleted on VM exit.
 191  
      *
 192  
      * @param configSpecContents The contents for the file
 193  
      * @param viewName           The name of the view; used to determine an appropriate file
 194  
      *                           name
 195  
      * @throws IOException
 196  
      */
 197  
     protected File writeTemporaryConfigSpecFile( String configSpecContents, String viewName )
 198  
         throws IOException
 199  
     {
 200  0
         File configSpecLocation = File.createTempFile( "configspec-" + viewName, ".txt" );
 201  0
         FileWriter fw = new FileWriter( configSpecLocation );
 202  
         try
 203  
         {
 204  0
             fw.write( configSpecContents );
 205  
         }
 206  
         finally
 207  
         {
 208  0
             try
 209  
             {
 210  0
                 fw.close();
 211  
             }
 212  0
             catch ( IOException e )
 213  
             {
 214  
                 // ignore
 215  0
             }
 216  0
         }
 217  0
         configSpecLocation.deleteOnExit();
 218  0
         return configSpecLocation;
 219  
     }
 220  
 
 221  
     /**
 222  
      * Creates a config spec that loads the given loadDirectory and uses the
 223  
      * given version tag
 224  
      *
 225  
      * @param loadDirectory the VOB directory to be loaded
 226  
      * @param version       ClearCase label type; notice that branch types are not
 227  
      *                      supported
 228  
      * @return Config Spec as String
 229  
      */
 230  
     protected String createConfigSpec( String loadDirectory, ScmVersion version )
 231  
     {
 232  
         // create config spec
 233  2
         StringBuilder configSpec = new StringBuilder();
 234  2
         configSpec.append( "element * CHECKEDOUT\n" );
 235  2
         if ( version != null && StringUtils.isNotEmpty( version.getName() ) )
 236  
         {
 237  1
             configSpec.append( "element * " + version.getName() + "\n" );
 238  1
             configSpec.append( "element -directory * /main/LATEST\n" );
 239  
             // configSpec.append( "element * /main/QualityControl_INT/RAD7_Migration/LATEST\n" );
 240  
         }
 241  
         else
 242  
         {
 243  1
             configSpec.append( "element * /main/LATEST\n" );
 244  
         }
 245  2
         configSpec.append( "load " + loadDirectory + "\n" );
 246  2
         return configSpec.toString();
 247  
     }
 248  
 
 249  
     protected String createConfigSpec( String loadDirectory, String elementName, ScmVersion version )
 250  
     {
 251  
         // create config spec
 252  0
         StringBuilder configSpec = new StringBuilder();
 253  0
         configSpec.append( "element * CHECKEDOUT\n" );
 254  0
         if ( version != null && StringUtils.isNotEmpty( version.getName() ) )
 255  
         {
 256  0
             configSpec.append( "element * " + version.getName() + "\n" );
 257  0
             configSpec.append( "element * " + elementName + "\n" );
 258  
         }
 259  
         else
 260  
         {
 261  0
             configSpec.append( "element * /main/LATEST\n" );
 262  
         }
 263  0
         configSpec.append( "load " + loadDirectory + "\n" );
 264  0
         return configSpec.toString();
 265  
     }
 266  
 
 267  
 //    private static Commandline createDeleteViewCommandLine( ClearCaseScmProviderRepository repository,
 268  
 //                                                            File workingDirectory )
 269  
 //    {
 270  
 //        Commandline command = new Commandline();
 271  
 //
 272  
 //        command.setWorkingDirectory( workingDirectory.getAbsolutePath() );
 273  
 //
 274  
 //        command.setExecutable( "cleartool" );
 275  
 //
 276  
 //        command.createArg().setValue( "rmview" );
 277  
 //        command.createArg().setValue( "-force" );
 278  
 //        command.createArg().setValue( "-tag" );
 279  
 //        if ( isClearCaseLT() )
 280  
 //        {
 281  
 //            command.createArg().setValue( getViewStore() );
 282  
 //        }
 283  
 //        else
 284  
 //        {
 285  
 //            command.createArg().setValue( getUniqueViewName( repository, workingDirectory.getAbsolutePath() ) );
 286  
 //        }
 287  
 //
 288  
 //        return command;
 289  
 //    }
 290  
 
 291  
     protected Commandline createCreateViewCommandLine( File workingDirectory, String viewName, String streamIdentifier )
 292  
         throws IOException
 293  
     {
 294  6
         Commandline command = new Commandline();
 295  
 
 296  
         // We have to execute from 1 level up from the working dir, since we had to delete the working dir
 297  6
         command.setWorkingDirectory( workingDirectory.getParentFile().getAbsolutePath() );
 298  
 
 299  6
         command.setExecutable( "cleartool" );
 300  
 
 301  6
         command.createArg().setValue( "mkview" );
 302  6
         command.createArg().setValue( "-snapshot" );
 303  6
         command.createArg().setValue( "-tag" );
 304  6
         command.createArg().setValue( viewName );
 305  
 
 306  6
         if ( isClearCaseUCM() )
 307  
         {
 308  2
             command.createArg().setValue( "-stream" );
 309  2
             command.createArg().setValue( streamIdentifier );
 310  
         }
 311  
 
 312  6
         if ( !isClearCaseLT() )
 313  
         {
 314  4
             if ( useVWS() )
 315  
             {
 316  2
                 command.createArg().setValue( "-vws" );
 317  2
                 command.createArg().setValue( getViewStore() + viewName + ".vws" );
 318  
             }
 319  
         }
 320  
 
 321  6
         command.createArg().setValue( workingDirectory.getCanonicalPath() );
 322  
 
 323  6
         return command;
 324  
     }
 325  
 
 326  
     /**
 327  
      * Format the stream identifier for ClearCaseUCM
 328  
      * @param streamName
 329  
      * @param vobName
 330  
      * @return the formatted stream identifier if the two parameter are not null
 331  
      */
 332  
     protected String getStreamIdentifier( String streamName, String vobName )
 333  
     {
 334  3
         if ( streamName == null || vobName == null )
 335  
         {
 336  2
             return null;
 337  
         }
 338  1
         return "stream:" + streamName + "@" + vobName;
 339  
     }
 340  
 
 341  
     protected Commandline createUpdateConfigSpecCommandLine( File workingDirectory, File configSpecLocation,
 342  
                                                                     String viewName )
 343  
     {
 344  2
         Commandline command = new Commandline();
 345  
 
 346  2
         command.setWorkingDirectory( workingDirectory.getAbsolutePath() );
 347  
 
 348  2
         command.setExecutable( "cleartool" );
 349  
 
 350  2
         command.createArg().setValue( "setcs" );
 351  2
         command.createArg().setValue( "-tag" );
 352  2
         command.createArg().setValue( viewName );
 353  2
         command.createArg().setValue( configSpecLocation.getAbsolutePath() );
 354  
 
 355  2
         return command;
 356  
 
 357  
     }
 358  
 
 359  
     private String getUniqueViewName( ClearCaseScmProviderRepository repository, String absolutePath )
 360  
     {
 361  
         String uniqueId;
 362  0
         int lastIndexBack = absolutePath.lastIndexOf( '\\' );
 363  0
         int lastIndexForward = absolutePath.lastIndexOf( '/' );
 364  0
         if ( lastIndexBack != -1 )
 365  
         {
 366  0
             uniqueId = absolutePath.substring( lastIndexBack + 1 );
 367  
         }
 368  
         else
 369  
         {
 370  0
             uniqueId = absolutePath.substring( lastIndexForward + 1 );
 371  
         }
 372  0
         return repository.getViewName( uniqueId );
 373  
     }
 374  
 
 375  
     protected String getViewStore()
 376  
     {
 377  4
         String result = null;
 378  
 
 379  4
         if ( settings.getViewstore() != null )
 380  
         {
 381  0
             result = settings.getViewstore();
 382  
         }
 383  
 
 384  4
         if ( result == null )
 385  
         {
 386  4
             result = "\\\\" + getHostName() + "\\viewstore\\";
 387  
         }
 388  
         else
 389  
         {
 390  
             // If ClearCase LT are use, the View store is identify by the
 391  
             // username.
 392  0
             if ( isClearCaseLT() )
 393  
             {
 394  0
                 result = result + getUserName() + "\\";
 395  
             }
 396  
         }
 397  4
         return result;
 398  
     }
 399  
 
 400  
     protected boolean isClearCaseLT()
 401  
     {
 402  6
         return ClearCaseScmProviderRepository.CLEARCASE_LT.equals( settings.getClearcaseType() );
 403  
     }
 404  
 
 405  
     protected boolean isClearCaseUCM()
 406  
     {
 407  6
         return ClearCaseScmProviderRepository.CLEARCASE_UCM.equals( settings.getClearcaseType() );
 408  
     }
 409  
 
 410  
     /**
 411  
      * @return the value of the setting property 'useVWS'
 412  
      */
 413  
     protected boolean useVWS()
 414  
     {
 415  4
         return settings.isUseVWSParameter();
 416  
     }
 417  
 
 418  
     private String getHostName()
 419  
     {
 420  
         String hostname;
 421  
         try
 422  
         {
 423  4
             hostname = InetAddress.getLocalHost().getHostName();
 424  
         }
 425  0
         catch ( UnknownHostException e )
 426  
         {
 427  
             // Should never happen
 428  0
             throw new RuntimeException( e );
 429  4
         }
 430  4
         return hostname;
 431  
     }
 432  
 
 433  
     private String getUserName()
 434  
     {
 435  
         String username;
 436  0
         username = System.getProperty( "user.name" );
 437  0
         return username;
 438  
     }
 439  
 
 440  
     public void setSettings( Settings settings )
 441  
     {
 442  4
         this.settings = settings;
 443  4
     }
 444  
 }