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            }
153
154            int indexColon = hostPort.indexOf( ':' );
155            if ( indexColon > 0 )
156            {
157                setHost( hostPort.substring( 0, indexColon ) );
158                url = StringUtils.replace( url, getHost(), "" );
159                setPort( Integer.parseInt( hostPort.substring( indexColon + 1 ) ) );
160                url = StringUtils.replace( url, ":" + getPort(), "" );
161            }
162            else
163            {
164                setHost( hostPort );
165                url = StringUtils.replace( url, getHost(), "" );
166            }
167        }
168
169        return url;
170    }
171
172    private String parseUsernameAndPassword( String url )
173    {
174        if ( canAuthenticate() )
175        {
176            String[] split = url.split( "@" );
177            if ( split.length == 2 )
178            {
179                url = split[1]; //Strip away 'username:password@' from url
180                split = split[0].split( ":" );
181                if ( split.length == 2 )
182                { //both username and password
183                    setUser( split[0] );
184                    setPassword( split[1] );
185                }
186                else
187                { //only username
188                    setUser( split[0] );
189                }
190            }
191        }
192        return url;
193    }
194
195    private String parsePath( String url )
196    {
197        if ( protocol == FILE )
198        {
199            //Use OS dependent path separator
200            url = StringUtils.replace( url, "/", File.separator );
201
202            //Test first path separator (*nix systems use them to denote root)
203            File tmpFile = new File( url ); //most likly a *nix system
204            String url2 = url.substring( File.pathSeparator.length() );
205            File tmpFile2 = new File( url2 ); //most likly a windows system
206            if ( !tmpFile.exists() && !tmpFile2.exists() )
207            {
208                // This is trouble - Trouble is reported in validateURI()
209            }
210
211            url = tmpFile2.exists() ? url2 : url;
212        }
213
214        return url;
215    }
216
217    private String addUser()
218    {
219        return ( getUser() == null ) ? "" : getUser();
220    }
221
222    private String addPassword()
223    {
224        return ( getPassword() == null ) ? "" : ":" + getPassword();
225    }
226
227    private String addHost()
228    {
229        return ( getHost() == null ) ? "" : getHost();
230    }
231
232    private String addPort()
233    {
234        return ( getPort() == 0 ) ? "" : ":" + getPort();
235    }
236
237    private String addPath()
238    {
239        return path;
240    }
241
242    private boolean needsAuthentication()
243    {
244        return protocol == SFTP || protocol == FTP || protocol == HTTPS || protocol == AFTP;
245    }
246
247    private String addAuthority()
248    {
249        return ( (canAuthenticate() && (getUser() != null))
250                ? addUser() + addPassword() + "@"
251                : "" );
252    }
253
254
255    private boolean canAuthenticate()
256    {
257        return needsAuthentication() || protocol == HTTP;
258    }
259    /** {@inheritDoc} */
260    public String toString()
261    {
262        return "Hg Repository Interpreted from: " + orgUrl + ":\nProtocol: " + protocol + "\nHost: " + getHost()
263            + "\nPort: " + getPort() + "\nUsername: " + getUser() + "\nPassword: " + getPassword() + "\nPath: "
264            + path;
265    }
266}