001package org.apache.maven.scm.provider.tfs;
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.net.URI;
023
024import org.apache.maven.scm.CommandParameters;
025import org.apache.maven.scm.ScmException;
026import org.apache.maven.scm.ScmFileSet;
027import org.apache.maven.scm.command.add.AddScmResult;
028import org.apache.maven.scm.command.blame.BlameScmResult;
029import org.apache.maven.scm.command.branch.BranchScmResult;
030import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
031import org.apache.maven.scm.command.checkin.CheckInScmResult;
032import org.apache.maven.scm.command.checkout.CheckOutScmResult;
033import org.apache.maven.scm.command.diff.DiffScmResult;
034import org.apache.maven.scm.command.edit.EditScmResult;
035import org.apache.maven.scm.command.export.ExportScmResult;
036import org.apache.maven.scm.command.list.ListScmResult;
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.tfs.command.TfsAddCommand;
044import org.apache.maven.scm.provider.tfs.command.TfsBranchCommand;
045import org.apache.maven.scm.provider.tfs.command.TfsChangeLogCommand;
046import org.apache.maven.scm.provider.tfs.command.TfsCheckInCommand;
047import org.apache.maven.scm.provider.tfs.command.TfsCheckOutCommand;
048import org.apache.maven.scm.provider.tfs.command.TfsEditCommand;
049import org.apache.maven.scm.provider.tfs.command.TfsListCommand;
050import org.apache.maven.scm.provider.tfs.command.TfsStatusCommand;
051import org.apache.maven.scm.provider.tfs.command.TfsTagCommand;
052import org.apache.maven.scm.provider.tfs.command.TfsUnEditCommand;
053import org.apache.maven.scm.provider.tfs.command.TfsUpdateCommand;
054import org.apache.maven.scm.provider.tfs.command.blame.TfsBlameCommand;
055import org.apache.maven.scm.repository.ScmRepositoryException;
056
057/**
058 * @plexus.component role="org.apache.maven.scm.provider.ScmProvider" role-hint="tfs"
059 */
060public class TfsScmProvider
061    extends AbstractScmProvider
062{
063
064    public static final String TFS_URL_FORMAT = "[[domain\\]username[;password]@]http[s]://server_name[:port]"
065        + "[:isCheckinPoliciesEnabled]:workspace:$/TeamProject/Path/To/Project";
066
067    // ----------------------------------------------------------------------
068    // ScmProvider Implementation
069    // ----------------------------------------------------------------------
070
071    public String getScmType()
072    {
073        return "tfs";
074    }
075
076    /**
077     * {@inheritDoc}
078     */
079    public boolean requiresEditMode()
080    {
081        return true;
082    }
083
084    public ScmProviderRepository makeProviderScmRepository( String scmUrl, char delimiter )
085        throws ScmRepositoryException
086    {
087        // Look for the TFS URL after any '@' delmiter used to pass
088        // usernames/password etc
089        // We deliberately look for the last '@' character as username could
090        // contain an '@' also.
091        int lastAtPos = scmUrl.lastIndexOf( '@' );
092        getLogger().info( "scmUrl - " + scmUrl );
093
094        String tfsUrl = ( lastAtPos < 0 ) ? scmUrl : scmUrl.substring( lastAtPos + 1 );
095        String usernamePassword = ( lastAtPos < 0 ) ? null : scmUrl.substring( 0, lastAtPos );
096
097        // Look for TFS path after the end of the TFS URL
098        int tfsPathPos = tfsUrl.lastIndexOf( delimiter + "$/" );
099        String serverPath = "$/";
100        if ( tfsPathPos > 0 )
101        {
102            serverPath = tfsUrl.substring( tfsPathPos + 1 );
103            tfsUrl = tfsUrl.substring( 0, tfsPathPos );
104        }
105
106        // Look for workspace ater the end of the TFS URL
107        int workspacePos = tfsUrl.lastIndexOf( delimiter );
108        String workspace = tfsUrl.substring( workspacePos + 1 );
109        tfsUrl = tfsUrl.substring( 0, workspacePos );
110        getLogger().info( "workspace: " + workspace );
111
112        // Look for workspace ater the end of the TFS URL
113        int checkinPoliciesPos = tfsUrl.lastIndexOf( delimiter );
114        String checkinPolicies = tfsUrl.substring( checkinPoliciesPos + 1 );
115        tfsUrl = tfsUrl.substring( 0, checkinPoliciesPos );
116        getLogger().info( "checkinPolicies: " + checkinPolicies );
117
118        try
119        {
120            // Use URI's validation to determine if valid URI.
121            URI tfsUri = URI.create( tfsUrl );
122            String scheme = tfsUri.getScheme();
123            getLogger().info( "Scheme - " + scheme );
124            if ( scheme == null || !( scheme.equalsIgnoreCase( "http" ) || scheme.equalsIgnoreCase( "https" ) ) )
125            {
126                throw new ScmRepositoryException( "TFS Url \"" + tfsUrl + "\" is not a valid URL. "
127                    + "The TFS Url syntax is " + TFS_URL_FORMAT );
128            }
129        }
130        catch ( IllegalArgumentException e )
131        {
132            throw new ScmRepositoryException( "TFS Url \"" + tfsUrl + "\" is not a valid URL. The TFS Url syntax is "
133                + TFS_URL_FORMAT );
134        }
135
136        String username = null;
137        String password = null;
138
139        if ( usernamePassword != null )
140        {
141            // Deliberately not using .split here in case password contains a
142            // ';'
143            int delimPos = usernamePassword.indexOf( ';' );
144            username = ( delimPos < 0 ) ? usernamePassword : usernamePassword.substring( 0, delimPos );
145            password = ( delimPos < 0 ) ? null : usernamePassword.substring( delimPos + 1 );
146        }
147
148        boolean useCheckinPolicies = Boolean.parseBoolean( checkinPolicies );
149
150        return new TfsScmProviderRepository( tfsUrl, username, password, serverPath, workspace, useCheckinPolicies );
151    }
152
153    protected ChangeLogScmResult changelog( ScmProviderRepository repository, ScmFileSet fileSet,
154                                            CommandParameters parameters )
155        throws ScmException
156    {
157        TfsChangeLogCommand command = new TfsChangeLogCommand();
158        command.setLogger( getLogger() );
159        return (ChangeLogScmResult) command.execute( repository, fileSet, parameters );
160    }
161
162    protected CheckOutScmResult checkout( ScmProviderRepository repository, ScmFileSet fileSet,
163                                          CommandParameters parameters )
164        throws ScmException
165    {
166        TfsCheckOutCommand command = new TfsCheckOutCommand();
167        command.setLogger( getLogger() );
168        return (CheckOutScmResult) command.execute( repository, fileSet, parameters );
169    }
170
171    protected EditScmResult edit( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
172        throws ScmException
173    {
174        TfsEditCommand command = new TfsEditCommand();
175        command.setLogger( getLogger() );
176        return (EditScmResult) command.execute( repository, fileSet, parameters );
177    }
178
179    protected UnEditScmResult unedit( ScmProviderRepository repository, ScmFileSet fileSet,
180                                      CommandParameters parameters )
181        throws ScmException
182    {
183        TfsUnEditCommand command = new TfsUnEditCommand();
184        command.setLogger( getLogger() );
185        return (UnEditScmResult) command.execute( repository, fileSet, parameters );
186    }
187
188    protected StatusScmResult status( ScmProviderRepository repository, ScmFileSet fileSet,
189                                      CommandParameters parameters )
190        throws ScmException
191    {
192        TfsStatusCommand command = new TfsStatusCommand();
193        command.setLogger( getLogger() );
194        return (StatusScmResult) command.execute( repository, fileSet, parameters );
195    }
196
197    protected UpdateScmResult update( ScmProviderRepository repository, ScmFileSet fileSet,
198                                      CommandParameters parameters )
199        throws ScmException
200    {
201        TfsUpdateCommand command = new TfsUpdateCommand();
202        command.setLogger( getLogger() );
203        return (UpdateScmResult) command.execute( repository, fileSet, parameters );
204    }
205
206    protected CheckInScmResult checkin( ScmProviderRepository repository, ScmFileSet fileSet,
207                                        CommandParameters parameters )
208        throws ScmException
209    {
210        TfsCheckInCommand command = new TfsCheckInCommand();
211        command.setLogger( getLogger() );
212        return (CheckInScmResult) command.execute( repository, fileSet, parameters );
213    }
214
215    public AddScmResult add( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
216        throws ScmException
217    {
218        TfsAddCommand command = new TfsAddCommand();
219        command.setLogger( getLogger() );
220        return (AddScmResult) command.execute( repository, fileSet, parameters );
221    }
222
223    protected TagScmResult tag( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
224        throws ScmException
225    {
226        TfsTagCommand command = new TfsTagCommand();
227        command.setLogger( getLogger() );
228        return (TagScmResult) command.execute( repository, fileSet, parameters );
229    }
230
231    protected BranchScmResult branch( ScmProviderRepository repository, ScmFileSet fileSet,
232                                      CommandParameters parameters )
233        throws ScmException
234    {
235        TfsBranchCommand command = new TfsBranchCommand();
236        command.setLogger( getLogger() );
237        return (BranchScmResult) command.execute( repository, fileSet, parameters );
238    }
239
240    protected ListScmResult list( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
241        throws ScmException
242    {
243        TfsListCommand command = new TfsListCommand();
244        command.setLogger( getLogger() );
245        return (ListScmResult) command.execute( repository, fileSet, parameters );
246    }
247
248    protected BlameScmResult blame( ScmProviderRepository repository, ScmFileSet fileSet,
249                                    CommandParameters parameters )
250        throws ScmException
251    {
252        TfsBlameCommand command = new TfsBlameCommand();
253        command.setLogger( getLogger() );
254        return (BlameScmResult) command.execute( repository, fileSet, parameters );
255    }
256
257    protected DiffScmResult diff( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
258        throws ScmException
259    {
260        // Because tf launches only external diffs
261        return super.diff( repository, fileSet, parameters );
262    }
263
264    protected ExportScmResult export( ScmProviderRepository repository, ScmFileSet fileSet,
265                                      CommandParameters parameters )
266        throws ScmException
267    {
268        // Use checkout instead
269        return super.export( repository, fileSet, parameters );
270    }
271
272}