View Javadoc
1   package org.apache.maven.scm.provider.starteam.command;
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 org.apache.maven.scm.ScmException;
23  import org.apache.maven.scm.ScmFileSet;
24  import org.apache.maven.scm.log.ScmLogger;
25  import org.apache.maven.scm.provider.starteam.repository.StarteamScmProviderRepository;
26  import org.apache.maven.scm.provider.starteam.util.StarteamUtil;
27  import org.apache.maven.scm.providers.starteam.settings.Settings;
28  import org.codehaus.plexus.util.cli.CommandLineException;
29  import org.codehaus.plexus.util.cli.CommandLineUtils;
30  import org.codehaus.plexus.util.cli.Commandline;
31  import org.codehaus.plexus.util.cli.StreamConsumer;
32  
33  import java.io.File;
34  import java.io.IOException;
35  import java.util.List;
36  
37  /**
38   * Command line construction utility.
39   *
40   * @author Dan T. Tran
41   *
42   */
43  public final class StarteamCommandLineUtils
44  {
45  
46      private StarteamCommandLineUtils()
47      {
48      }
49  
50      private static Settings settings = StarteamUtil.getSettings();
51  
52      public static Commandline createStarteamBaseCommandLine( String action, StarteamScmProviderRepository repo )
53      {
54          Commandline cl = new Commandline();
55  
56          cl.createArg().setValue( "stcmd" );
57  
58          cl.createArg().setValue( action );
59  
60          cl.createArg().setValue( "-x" );
61  
62          cl.createArg().setValue( "-nologo" );
63  
64          cl.createArg().setValue( "-stop" );
65  
66          return cl;
67      }
68  
69      private static Commandline addCommandlineArguments( Commandline cl, List<String> args )
70      {
71          if ( args == null )
72          {
73            return cl;
74          }
75          for ( String arg : args )
76          {
77              cl.createArg().setValue( arg );
78          }
79          return cl;
80      }
81  
82      public static Commandline createStarteamCommandLine( String action, List<String> args, ScmFileSet scmFileSet,
83                                                           StarteamScmProviderRepository repo )
84      {
85          Commandline cl = StarteamCommandLineUtils.createStarteamBaseCommandLine( action, repo );
86  
87          // case 1: scmFileSet has only basedir
88          if ( scmFileSet.getFileList().size() == 0 )
89          {
90              //perform an action on directory
91              cl.createArg().setValue( "-p" );
92              cl.createArg().setValue( repo.getFullUrl() );
93              cl.createArg().setValue( "-fp" );
94              cl.createArg().setValue( scmFileSet.getBasedir().getAbsolutePath().replace( '\\', '/' ) );
95  
96              cl.createArg().setValue( "-is" );
97  
98              addCompressionOption( cl );
99  
100             addCommandlineArguments( cl, args );
101 
102             return cl;
103         }
104 
105         //case 2 scmFileSet has a sub file, but we dont know if the sub file is a directory or a file
106         File fileInFileSet = (File) scmFileSet.getFileList().get( 0 );
107         File subFile = new File( scmFileSet.getBasedir(), fileInFileSet.getPath() );
108 
109         //Perform an scm action on a single file where the orignal
110         // url and local directory ( -p and -fp options ) are altered
111         // to deal with single file/subdirectory
112 
113         File workingDirectory = subFile;
114         String scmUrl = repo.getFullUrl() + "/" + fileInFileSet.getPath().replace( '\\', '/' );
115         if ( !subFile.isDirectory() )
116         {
117             workingDirectory = subFile.getParentFile();
118             if ( fileInFileSet.getParent() != null )
119             {
120                 scmUrl = repo.getFullUrl() + "/" + fileInFileSet.getParent().replace( '\\', '/' );
121             }
122             else
123             {
124                 //subFile is right under root
125                 scmUrl = repo.getFullUrl();
126             }
127         }
128 
129         cl.createArg().setValue( "-p" );
130         cl.createArg().setValue( scmUrl );
131 
132         cl.createArg().setValue( "-fp" );
133         cl.createArg().setValue( workingDirectory.getPath().replace( '\\', '/' ) );
134 
135         cl.setWorkingDirectory( workingDirectory.getPath() );
136 
137         if ( subFile.isDirectory() )
138         {
139             cl.createArg().setValue( "-is" );
140         }
141 
142         StarteamCommandLineUtils.addCompressionOption( cl );
143 
144         addCommandlineArguments( cl, args );
145 
146         if ( !subFile.isDirectory() )
147         {
148             cl.createArg().setValue( subFile.getName() );
149         }
150 
151         return cl;
152     }
153 
154     public static void addCompressionOption( Commandline cl )
155     {
156         if ( settings.isCompressionEnable() )
157         {
158             cl.createArg().setValue( "-cmp" );
159         }
160     }
161 
162     public static void addEOLOption( List<String> args )
163     {
164         if ( settings.getEol() != null  )
165         {
166             args.add( "-eol" );
167             args.add( settings.getEol() );
168         }
169     }
170 
171     public static String toJavaPath( String path )
172     {
173         return path.replace( '\\', '/' );
174     }
175 
176     /**
177      * Hellper method to display command line without password
178      *
179      * @param cl
180      * @return String
181      * @throws ScmException
182      */
183     public static String displayCommandlineWithoutPassword( Commandline cl )
184         throws ScmException
185     {
186         String retStr = "";
187 
188         String fullStr = cl.toString();
189 
190         //look for -p and take out the password arugment
191 
192         int usernamePos = fullStr.indexOf( "-p " ) + 3;
193 
194         if ( usernamePos == 2 )
195         {
196             //should never get here since all starteam command lines
197             // have -p argument
198 
199             throw new ScmException( "Invalid command line" );
200         }
201 
202         retStr = fullStr.substring( 0, usernamePos );
203 
204         int passwordStartPos = fullStr.indexOf( ':' );
205 
206         if ( passwordStartPos == -1 )
207         {
208             throw new ScmException( "Invalid command line" );
209         }
210 
211         int passwordEndPos = fullStr.indexOf( '@' );
212 
213         if ( passwordEndPos == -1 )
214         {
215             throw new ScmException( "Invalid command line" );
216         }
217 
218         retStr += fullStr.substring( usernamePos, passwordStartPos );
219 
220         retStr += fullStr.substring( passwordEndPos );
221 
222         return retStr;
223 
224     }
225 
226     public static int executeCommandline( Commandline cl, StreamConsumer consumer,
227                                           CommandLineUtils.StringStreamConsumer stderr, ScmLogger logger )
228         throws ScmException
229     {
230         if ( logger.isInfoEnabled() )
231         {
232             logger.info( "Command line: " + displayCommandlineWithoutPassword( cl ) );
233         }
234 
235         try
236         {
237             return CommandLineUtils.executeCommandLine( cl, consumer, stderr );
238         }
239         catch ( CommandLineException ex )
240         {
241             throw new ScmException( "Error while executing command.", ex );
242         }
243     }
244 
245     /**
246      * Given 2 paths, make sure parent and child are on the same tree
247      * return the port of child that not in parent
248      *
249      * @param parent
250      * @param child
251      * @return
252      */
253     public static String getRelativeChildDirectory( String parent, String child )
254     {
255         //expect parentDir contains childDir
256         try
257         {
258             String childPath = new File( child ).getCanonicalFile().getPath().replace( '\\', '/' );
259 
260             String parentPath = new File( parent ).getCanonicalFile().getPath().replace( '\\', '/' );
261 
262             if ( !childPath.startsWith( parentPath ) )
263             {
264                 throw new IllegalStateException();
265             }
266 
267             String retDir = "." + childPath.substring( parentPath.length() );
268 
269             return retDir;
270 
271         }
272         catch ( IOException e )
273         {
274             throw new IllegalStateException(
275                 "Unable to convert to canonical path of either " + parent + " or " + child );
276         }
277     }
278 
279 }