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 *
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 }