001    package org.apache.maven.scm.provider.bazaar.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    
022    import org.apache.maven.scm.provider.ScmProviderRepositoryWithHost;
023    import org.codehaus.plexus.util.StringUtils;
024    
025    import java.io.File;
026    
027    /**
028     * @author <a href="mailto:torbjorn@smorgrav.org">Torbj�rn Eikli Sm�rgrav</a>
029     * @version $Id: BazaarScmProviderRepository.java 1134851 2011-06-12 01:24:05Z godin $
030     */
031    public class BazaarScmProviderRepository
032        extends ScmProviderRepositoryWithHost
033    {
034        //Known and tested protocols
035        private static final String FILE = "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 static final String BZR = "bzr://";
048    
049        private static final String BZR_SSH = "bzr+ssh://";
050    
051        /** this is basically an abbreviation of {@value #BZR_SSH} */
052        private static final String SSH = "ssh://";
053    
054        private static final String UNKNOWN = "";
055    
056        private final String path;
057    
058        private final String protocol;
059    
060        private final String orgUrl;
061    
062        public BazaarScmProviderRepository( String url )
063        {
064            orgUrl = url;
065            protocol = getProtocol( url );
066            path = parseUrl( url );
067        }
068    
069        public String getURI()
070        {
071            if ( FILE.equals( protocol ) )
072            {
073                return orgUrl;
074            }
075            else
076            {
077                return protocol + ( needsAuthentication() ? addUser() + addPassword() + addAt() : "" ) + addHost()
078                    + addPort() + addPath();
079            }
080        }
081    
082        /**
083         * @return A message if the repository as an invalid URI, null if the URI seems fine.
084         */
085        public String validateURI()
086        {
087    
088            String msg = null;
089    
090            if ( UNKNOWN.equals( protocol ) )
091            {
092                msg = "Unknown protocol (URL should start with something like 'sftp://' or 'file://'";
093            }
094            else if ( needsAuthentication() )
095            {
096                if ( getUser() == null )
097                {
098                    msg = "Username is missing for protocol " + protocol;
099                }
100                else if ( getPassword() == null )
101                {
102                    msg = "Password is missing for protocol " + protocol;
103                }
104                else if ( getHost() == null )
105                {
106                    msg = "Host (eg. www.myhost.com) is missing for protocol " + protocol;
107                }
108            }
109    
110            else if ( getPort() != 0 && getHost() == null )
111            {
112                msg = "Got port information without any host for protocol " + protocol;
113            }
114    
115            if ( msg != null )
116            {
117                msg = "Something could be wrong about the repository URL: " + orgUrl + "\nReason: " + msg
118                    + "\nCheck http://maven.apache.org/scm for usage and hints.";
119            }
120            return msg;
121        }
122    
123        private String getProtocol( String url )
124        {
125            String prot = UNKNOWN;
126            if ( url.startsWith( FILE ) )
127            {
128                prot = FILE;
129            }
130            else if ( url.startsWith( FTP ) )
131            {
132                prot = FTP;
133            }
134            else if ( url.startsWith( SFTP ) )
135            {
136                prot = SFTP;
137            }
138            else if ( url.startsWith( AFTP ) )
139            {
140                prot = AFTP;
141            }
142            else if ( url.startsWith( HTTP ) )
143            {
144                prot = HTTP;
145            }
146            else if ( url.startsWith( HTTPS ) )
147            {
148                prot = HTTPS;
149            }
150            else if ( url.startsWith( BZR ) )
151            {
152                prot = BZR;
153            }
154            else if ( url.startsWith( BZR_SSH ) )
155            {
156                prot = BZR_SSH;
157            }
158            else if ( url.startsWith( SSH ) )
159            {
160                prot = SSH;
161            }
162    
163            return prot;
164        }
165    
166        private String parseUrl( String url )
167        {
168            if ( UNKNOWN.equals( protocol ) )
169            {
170                return url;
171            }
172    
173            //Strip protocol
174            url = url.substring( protocol.length() );
175    
176            url = parseUsernameAndPassword( url );
177    
178            url = parseHostAndPort( url );
179    
180            url = parsePath( url );
181    
182            return url; //is now only the path
183        }
184    
185        private String parseHostAndPort( String url )
186        {
187            if ( !FILE.equals( protocol ) )
188            {
189                int indexSlash = url.indexOf( '/' );
190    
191                String hostPort = url;
192                if ( indexSlash > 0 )
193                {
194                    hostPort = url.substring( 0, indexSlash );
195                }
196    
197                int indexColon = hostPort.indexOf( ':' );
198                if ( indexColon > 0 )
199                {
200                    setHost( hostPort.substring( 0, indexColon ) );
201                    url = StringUtils.replace( url, getHost(), "" );
202                    setPort( Integer.parseInt( hostPort.substring( indexColon + 1 ) ) );
203                    url = StringUtils.replace( url, ":" + getPort(), "" );
204                }
205                else
206                {
207                    setHost( hostPort );
208                    url = StringUtils.replace( url, getHost(), "" );
209                }
210            }
211    
212            return url;
213        }
214    
215        private String parseUsernameAndPassword( String url )
216        {
217            if ( needsAuthentication() )
218            {
219                String[] split = url.split( "@" );
220                if ( split.length == 2 )
221                {
222                    url = split[1]; //Strip away 'username:password@' from url
223                    split = split[0].split( ":" );
224                    if ( split.length == 2 )
225                    { //both username and password
226                        setUser( split[0] );
227                        setPassword( split[1] );
228                    }
229                    else
230                    { //only username
231                        setUser( split[0] );
232                    }
233                }
234            }
235            return url;
236        }
237    
238        private String parsePath( String url )
239        {
240            if ( FILE.equals( protocol ) )
241            {
242                //Use OS dependent path separator
243                url = StringUtils.replace( url, "/", File.separator );
244    
245                //Test first path separator (*nix systems use them to denote root)
246                File tmpFile = new File( url ); //most likly a *nix system
247                String url2 = url.substring( File.pathSeparator.length() );
248                File tmpFile2 = new File( url2 ); //most likly a windows system
249                if ( !tmpFile.exists() && !tmpFile2.exists() )
250                {
251                    // This is trouble - Trouble is reported in validateURI()
252                }
253    
254                url = tmpFile2.exists() ? url2 : url;
255    
256                //Use URL path separator
257                url = StringUtils.replace( url, File.separator, "/" );
258            }
259    
260            return url;
261        }
262    
263        private String addUser()
264        {
265            return ( getUser() == null ) ? "" : getUser();
266        }
267    
268        private String addPassword()
269        {
270            return ( getPassword() == null ) ? "" : ":" + getPassword();
271        }
272    
273        private String addAt()
274        {
275            return needsAuthentication() ? "@" : "";
276        }
277    
278        private String addHost()
279        {
280            return ( getHost() == null ) ? "" : getHost();
281        }
282    
283        private String addPort()
284        {
285            return ( getPort() == 0 ) ? "" : ":" + getPort();
286        }
287    
288        private String addPath()
289        {
290            return path;
291        }
292    
293        private boolean needsAuthentication()
294        {
295            return SFTP.equals( protocol ) || 
296                   FTP.equals( protocol ) || 
297                   HTTPS.equals( protocol ) || 
298                   AFTP.equals( protocol ) ||
299                   BZR.equals( protocol ) ||
300                   BZR_SSH.equals( protocol ) ||
301                   SSH.equals( protocol );
302        }
303    
304        /** {@inheritDoc} */
305        public String toString()
306        {
307            return "Bazaar Repository Interpreted from: " + orgUrl + ":\nProtocol: " + protocol + "\nHost: "
308                + getHost() + "\nPort: " + getPort() + "\nUsername: " + getUser() + "\nPassword: " + getPassword()
309                + "\nPath: " + path;
310        }
311    }