001package org.apache.maven.scm.provider.hg.repository;
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 org.apache.maven.scm.provider.ScmProviderRepositoryWithHost;
023import org.codehaus.plexus.util.StringUtils;
024
025import java.io.File;
026
027/**
028 * @author <a href="mailto:thurner.rupert@ymono.net">thurner rupert</a>
029 *
030 */
031public class HgScmProviderRepository
032    extends ScmProviderRepositoryWithHost
033{
034    //Known and tested protocols
035    private static final String FILE = "";
036
037    private static final String SFTP = "sftp://";
038
039    private static final String FTP = "ftp://";
040
041    private static final String AFTP = "aftp://";
042
043    private static final String HTTP = "http://";
044
045    private static final String HTTPS = "https://";
046
047    private final String path;
048
049    private final String protocol;
050
051    private final String orgUrl;
052
053    public HgScmProviderRepository( String url )
054    {
055        orgUrl = url;
056        protocol = getProtocol( url );
057        path = parseUrl( url );
058    }
059
060    public String getURI()
061    {
062        return protocol + addAuthority() + addHost() + addPort() + addPath();
063    }
064
065    /**
066     * @return A message if the repository as an invalid URI, null if the URI seems fine.
067     */
068    public String validateURI()
069    {
070
071        String msg = null;
072
073        if ( needsAuthentication() )
074        {
075            if ( getUser() == null )
076            {
077                msg = "Username is missing for protocol " + protocol;
078            }
079            else if ( getPassword() == null )
080            {
081                msg = "Password is missing for protocol " + protocol;
082            }
083            else if ( getHost() == null )
084            {
085                msg = "Host (eg. www.myhost.com) is missing for protocol " + protocol;
086            }
087        }
088
089        else if ( getPort() != 0 && getHost() == null )
090        {
091            msg = "Got port information without any host for protocol " + protocol;
092        }
093
094        if ( msg != null )
095        {
096            msg =
097                "Something could be wrong about the repository URL: " + orgUrl + "\nReason: " + msg
098                    + "\nCheck http://maven.apache.org/scm for usage and hints.";
099        }
100        return msg;
101    }
102
103    private String getProtocol( String url )
104    {
105        // Assume we have a file unless we find a URL based syntax
106        String prot = FILE;
107        if ( url.startsWith( SFTP ) )
108        {
109            prot = SFTP;
110        }
111        else if ( url.startsWith( HTTP ) )
112        {
113            prot = HTTP;
114        }
115        else if ( url.startsWith( HTTPS ) )
116        {
117            prot = HTTPS;
118        }
119
120        return prot;
121    }
122
123    private String parseUrl( String url )
124    {
125        if ( protocol == FILE )
126        {
127            return url;
128        }
129
130        //Strip protocol
131        url = url.substring( protocol.length() );
132
133        url = parseUsernameAndPassword( url );
134
135        url = parseHostAndPort( url );
136
137        url = parsePath( url );
138
139        return url; //is now only the path
140    }
141
142    private String parseHostAndPort( String url )
143    {
144        if ( protocol != FILE )
145        {
146            int indexSlash = url.indexOf( '/' );
147
148            String hostPort = url;
149            if ( indexSlash > 0 )
150            {
151                hostPort = url.substring( 0, indexSlash );
152                url = url.substring( indexSlash );
153            }
154
155            int indexColon = hostPort.indexOf( ':' );
156            if ( indexColon > 0 )
157            {
158                setHost( hostPort.substring( 0, indexColon ) );
159                setPort( Integer.parseInt( hostPort.substring( indexColon + 1 ) ) );
160            }
161            else
162            {
163                setHost( hostPort );
164            }
165        }
166
167        return url;
168    }
169
170    private String parseUsernameAndPassword( String url )
171    {
172        if ( canAuthenticate() )
173        {
174            String[] split = url.split( "@" );
175            if ( split.length == 2 )
176            {
177                url = split[1]; //Strip away 'username:password@' from url
178                split = split[0].split( ":" );
179                if ( split.length == 2 )
180                { //both username and password
181                    setUser( split[0] );
182                    setPassword( split[1] );
183                }
184                else
185                { //only username
186                    setUser( split[0] );
187                }
188            }
189        }
190        return url;
191    }
192
193    private String parsePath( String url )
194    {
195        if ( protocol == FILE )
196        {
197            //Use OS dependent path separator
198            url = StringUtils.replace( url, "/", File.separator );
199
200            //Test first path separator (*nix systems use them to denote root)
201            File tmpFile = new File( url ); //most likly a *nix system
202            String url2 = url.substring( File.pathSeparator.length() );
203            File tmpFile2 = new File( url2 ); //most likly a windows system
204            if ( !tmpFile.exists() && !tmpFile2.exists() )
205            {
206                // This is trouble - Trouble is reported in validateURI()
207            }
208
209            url = tmpFile2.exists() ? url2 : url;
210        }
211
212        return url;
213    }
214
215    private String addUser()
216    {
217        return ( getUser() == null ) ? "" : getUser();
218    }
219
220    private String addPassword()
221    {
222        return ( getPassword() == null ) ? "" : ":" + getPassword();
223    }
224
225    private String addHost()
226    {
227        return ( getHost() == null ) ? "" : getHost();
228    }
229
230    private String addPort()
231    {
232        return ( getPort() == 0 ) ? "" : ":" + getPort();
233    }
234
235    private String addPath()
236    {
237        return path;
238    }
239
240    private boolean needsAuthentication()
241    {
242        return protocol == SFTP || protocol == FTP || protocol == HTTPS || protocol == AFTP;
243    }
244
245    private String addAuthority()
246    {
247        return ( ( canAuthenticate() && ( getUser() != null ) ) ? addUser() + addPassword() + "@" : "" );
248    }
249
250
251    private boolean canAuthenticate()
252    {
253        return needsAuthentication() || protocol == HTTP;
254    }
255    /** {@inheritDoc} */
256    public String toString()
257    {
258        return "Hg Repository Interpreted from: " + orgUrl + ":\nProtocol: " + protocol + "\nHost: " + getHost()
259            + "\nPort: " + getPort() + "\nUsername: " + getUser() + "\nPassword: " + getPassword() + "\nPath: "
260            + path;
261    }
262}