001 package 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
022 import java.io.File;
023 import java.io.IOException;
024 import java.util.ArrayList;
025 import java.util.List;
026
027 import org.apache.maven.scm.CommandParameters;
028 import org.apache.maven.scm.ScmException;
029 import org.apache.maven.scm.ScmFileSet;
030 import org.apache.maven.scm.command.add.AddScmResult;
031 import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
032 import org.apache.maven.scm.command.checkin.CheckInScmResult;
033 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
034 import org.apache.maven.scm.command.diff.DiffScmResult;
035 import org.apache.maven.scm.command.edit.EditScmResult;
036 import org.apache.maven.scm.command.remove.RemoveScmResult;
037 import org.apache.maven.scm.command.status.StatusScmResult;
038 import org.apache.maven.scm.command.tag.TagScmResult;
039 import org.apache.maven.scm.command.unedit.UnEditScmResult;
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.starteam.command.add.StarteamAddCommand;
044 import org.apache.maven.scm.provider.starteam.command.changelog.StarteamChangeLogCommand;
045 import org.apache.maven.scm.provider.starteam.command.checkin.StarteamCheckInCommand;
046 import org.apache.maven.scm.provider.starteam.command.checkout.StarteamCheckOutCommand;
047 import org.apache.maven.scm.provider.starteam.command.diff.StarteamDiffCommand;
048 import org.apache.maven.scm.provider.starteam.command.edit.StarteamEditCommand;
049 import org.apache.maven.scm.provider.starteam.command.remove.StarteamRemoveCommand;
050 import org.apache.maven.scm.provider.starteam.command.status.StarteamStatusCommand;
051 import org.apache.maven.scm.provider.starteam.command.tag.StarteamTagCommand;
052 import org.apache.maven.scm.provider.starteam.command.unedit.StarteamUnEditCommand;
053 import org.apache.maven.scm.provider.starteam.command.update.StarteamUpdateCommand;
054 import org.apache.maven.scm.provider.starteam.repository.StarteamScmProviderRepository;
055 import org.apache.maven.scm.repository.ScmRepositoryException;
056 import 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 */
063 public 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 = new Integer( 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 relPathFiles.add( new File( getRelativePath( basedir, file ) ));
339 } else {
340 relPathFiles.add( file );
341 }
342
343 }
344
345 newFileSet = new ScmFileSet( basedir, relPathFiles );
346 }
347 catch ( IOException e )
348 {
349 throw new ScmException( "Invalid file set.", e );
350 }
351
352 return newFileSet;
353 }
354
355 public static String getRelativePath( File basedir, File f )
356 throws ScmException, IOException
357 {
358 File fileOrDir = getAbsoluteFilePath( f );
359
360 if ( !fileOrDir.getCanonicalPath().startsWith( basedir.getCanonicalPath() ) )
361 {
362 throw new ScmException( fileOrDir.getPath() + " was not contained in " + basedir.getPath() );
363 }
364
365 if ( basedir.getCanonicalFile().equals(basedir.getAbsoluteFile()) )
366 {
367 return fileOrDir.getPath().substring( basedir.getPath().length() + 1, fileOrDir.getPath().length() );
368 }
369 return fileOrDir.getPath().substring( basedir.getCanonicalPath().length() + 1, fileOrDir.getPath().length() );
370 }
371
372 private static File getAbsoluteFilePath( File fileOrDir )
373 throws IOException
374 {
375 String javaPathString = fileOrDir.getCanonicalPath().replace( '\\', '/' );
376
377 if ( javaPathString.endsWith( "/" ) )
378 {
379 javaPathString = javaPathString.substring( 0, javaPathString.length() - 1 );
380 }
381
382 return new File( javaPathString );
383 }
384 }