KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > antmod > scm > ScmUrl


1 package org.antmod.scm;
2
3 import java.text.ParseException JavaDoc;
4 import java.util.StringTokenizer JavaDoc;
5
6 import org.apache.commons.lang.math.NumberUtils;
7
8 /**
9  * Representation of an SCM url.
10  * <p/>
11  * The format of this element is as follows:
12  * <pre>scm:&lt;provider&gt;:&lt;provider-parameters&gt;</pre>
13  * <p/>
14  *
15  * For cvs, the format for pserver repositories should be (password is optional):
16  * <ul>
17  * <pre>scm:cvs:pserver:user[:password]@host:/cvs/root:module-name</pre>
18  * </ul>
19  *
20  * For local system repositories
21  * <ul>
22  * <pre>scm:cvs:local:ignored:/cvs/root:module-name</pre>
23  * </ul>
24  *
25  * For ssh access:
26  * <ul>
27  * <pre>scm:cvs:ext:user@host:/cvs/root:module-name</pre>
28  * </ul>
29  *
30  * Subversion syntax (between brackets is optional):
31  * <ul>
32  * <pre>scm:svn:protocol://[user[:password]@]host/path/to/svn[:module-name]</pre>
33  * </ul>
34  *
35  * Subversion urls using this syntax look for example like this:
36  * <ul>
37  * <pre>scm:svn:http://user:password@host.example.com/path/to/svn</pre>
38  * <pre>scm:svn:http://host.example.com:8080/path/to/svn</pre>
39  * <pre>scm:svn:svn://host.example.com/path/to/svn</pre>
40  * <pre>scm:svn:file:///C:/path/to/localsvn</pre>
41  * <pre>scm:svn:file:///cygdrive/c/path/to/localsvn</pre>
42  * </ul>
43  *
44  * Remember that CVS will expect an environment variable called
45  * <code>CVS_RSH</code> to be set, typically to <code>ssh</code> or your ssh client.
46  *
47  * @author Klaas Waslander
48  */

49 public class ScmUrl {
50     private String JavaDoc urlString;
51     private String JavaDoc type;
52     private String JavaDoc protocol;
53     private String JavaDoc user;
54     private String JavaDoc password;
55     private String JavaDoc host;
56     private String JavaDoc path;
57     private String JavaDoc module;
58
59     /**
60      * Constructs new ScmUrl instance based on the parsed
61      * contents of the given scm url string.
62      * @param urlString The string representing the SCM url.
63      */

64     public ScmUrl(String JavaDoc urlString) throws IllegalArgumentException JavaDoc, ParseException JavaDoc {
65         this.urlString = urlString;
66         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(urlString, ":");
67         if (!st.hasMoreTokens() || !st.nextToken().equals("scm")) {
68             throw new IllegalArgumentException JavaDoc("Invalid URL \"" + urlString + "\": does not start with 'scm:'");
69         }
70         this.type = st.nextToken();
71         
72         if (this.type.equals("cvs")) {
73             cvsParse(st);
74         } else if (this.type.equals("svn")) {
75             svnParse(st);
76         } else {
77             throw new IllegalArgumentException JavaDoc("Unknown URL type: '" + this.type + "'");
78         }
79     }
80
81     /** utility to parse CVS tokens, assuming first token with type is already parsed */
82     private void cvsParse(StringTokenizer JavaDoc st) throws ParseException JavaDoc {
83         // required protocol element
84
if (!st.hasMoreTokens()) {
85             throw new ParseException JavaDoc("Element 'protocol' missing from CVS url", 1);
86         }
87         this.protocol = st.nextToken();
88
89         // required user-host element
90
if (!st.hasMoreTokens()) {
91             throw new ParseException JavaDoc("Element 'user@host' missing from CVS url", 2);
92         }
93
94         // for non-local URLs parse
95
String JavaDoc userHost = st.nextToken();
96         if (!this.protocol.equals("local")) {
97             int atIndex = userHost.indexOf("@");
98             if (atIndex < 0) {
99                 // safely assume password in URL
100
this.user = userHost;
101
102                 if (!st.hasMoreTokens()) {
103                     throw new ParseException JavaDoc("After username \"" + this.user + "\" the element 'password@host' is missing from CVS url", 3);
104                 }
105                 String JavaDoc passHost = st.nextToken();
106                 atIndex = passHost.indexOf("@");
107                 if (atIndex < 0) {
108                     throw new ParseException JavaDoc("After username \"" + this.user + "\" the element 'password@host' is missing from CVS url", 3);
109                 } else {
110                     this.password = passHost.substring(0, atIndex);
111                     this.host = passHost.substring(atIndex + 1);
112                 }
113             } else {
114                 // no password in URL
115
this.user = userHost.substring(0, atIndex);
116                 this.host = userHost.substring(atIndex + 1);
117             }
118         }
119         
120         // required path element
121
if (this.protocol.equals("local") && !userHost.equalsIgnoreCase("ignored")) {
122             this.path = userHost;
123         } else {
124             if (!st.hasMoreTokens()) {
125                 throw new ParseException JavaDoc("Element 'path' missing from CVS url", 4);
126             }
127             this.path = st.nextToken();
128         }
129
130         // handle windows path with drive letter in it
131
if (this.path.length() == 1) {
132             // assume this is a windows drive letter with path following
133
this.path = this.path + ":" + st.nextToken();
134             this.protocol = null;
135         }
136         
137         // check if path is prepended with a port number
138
int slashIndex = this.path.indexOf("/");
139         if (slashIndex > 0 && NumberUtils.isNumber(this.path.substring(0, slashIndex))) {
140             this.host = this.host + ":" + this.path.substring(0, slashIndex);
141             this.path = this.path.substring(slashIndex);
142         }
143
144         // optional module element
145
if (st.hasMoreTokens()) {
146             this.module = st.nextToken();
147         }
148     }
149
150     /** utility to parse subversion tokens, assuming first token with type is already parsed */
151     private void svnParse(StringTokenizer JavaDoc st) throws ParseException JavaDoc {
152         // required protocol element
153
if (!st.hasMoreTokens()) {
154             throw new ParseException JavaDoc("Element 'protocol' missing from Subversion url", 1);
155         }
156         this.protocol = st.nextToken();
157
158         // required user-host element
159
if (!st.hasMoreTokens()) {
160             throw new ParseException JavaDoc("Subversion url seems to have only protocol part.", 2);
161         }
162
163         String JavaDoc userHost = st.nextToken();
164         if (!userHost.startsWith("//")) {
165             throw new ParseException JavaDoc("Subversion url does not have '//' after protocol.", 3);
166         }
167
168         if (protocol.equals("file")) {
169             while (userHost.startsWith("/")) {
170                 userHost = userHost.substring(1);
171             }
172             this.path = userHost;
173         } else {
174             // http or svn protocol
175
userHost = userHost.substring(2);
176     
177             int atIndex = userHost.indexOf("@");
178             int slashIndex = userHost.indexOf("/");
179             if (atIndex > 0) {
180                 // there is a username and no password here
181
this.user = userHost.substring(0, atIndex);
182                 userHost = userHost.substring(atIndex + 1);
183             } else if (slashIndex < 0) {
184                 // there is a username, and password follows in next token
185
this.user = userHost;
186                 
187                 if (!st.hasMoreTokens()) {
188                     throw new ParseException JavaDoc("After username \"" + this.user + "\" the element 'password@host' is missing from Subversion url", 4);
189                 }
190                 String JavaDoc passHost = st.nextToken();
191                 atIndex = passHost.indexOf("@");
192                 if (atIndex < 0) {
193                     throw new ParseException JavaDoc("After username \"" + this.user + "\" the element 'password@host' is missing from CVS url", 4);
194                 }
195                 this.password = passHost.substring(0, atIndex);
196                 userHost = passHost.substring(atIndex + 1);
197             } else {
198                 // no username or password, nothing to do
199
}
200             
201             // parse hostname and path next
202
slashIndex = userHost.indexOf("/");
203             if (slashIndex < 0) {
204                 // check if a port number is inserted before the path
205
if (st.hasMoreTokens()) {
206                     String JavaDoc portPath = st.nextToken();
207                     slashIndex = portPath.indexOf("/");
208                     if (slashIndex < 0) {
209                         throw new ParseException JavaDoc("Element 'path' missing from Subversion url, no '/' found that separates host and path", 5);
210                     } else {
211                         this.host = userHost + portPath.substring(0, slashIndex);
212                         this.path = portPath.substring(slashIndex);
213                     }
214                 } else {
215                     throw new ParseException JavaDoc("Element 'path' missing from Subversion url, no '/' found that separates host and path", 5);
216                 }
217             } else {
218                 this.host = userHost.substring(0, slashIndex);
219                 this.path = userHost.substring(slashIndex);
220             }
221         }
222         
223         // make sure path does not end with a slash
224
if (this.path.endsWith("/")) {
225             this.path = this.path.substring(0, this.path.length() - 1);
226         }
227         if (this.path.length() == 1) {
228             // assume this is a windows drive letter with path following
229
this.path = this.path + ":" + st.nextToken();
230         }
231
232         // optional module element
233
if (st.hasMoreTokens()) {
234             this.module = st.nextToken();
235         }
236     }
237
238
239     /**
240      * @return
241      */

242     public String JavaDoc getHost() {
243         return host;
244     }
245
246     /**
247      * @return
248      */

249     public String JavaDoc getModule() {
250         return module;
251     }
252
253     /**
254      * @return
255      */

256     public String JavaDoc getPassword() {
257         return password;
258     }
259
260     /**
261      * @return
262      */

263     public String JavaDoc getPath() {
264         return path;
265     }
266
267     /**
268      * @return
269      */

270     public String JavaDoc getProtocol() {
271         return protocol;
272     }
273
274     /**
275      * @return
276      */

277     public String JavaDoc getType() {
278         return type;
279     }
280
281     /**
282      * @return
283      */

284     public String JavaDoc getUser() {
285         return user;
286     }
287
288     /**
289      * Get the original URL string with which this ScmUrl was created.
290      */

291     public String JavaDoc getUrlString() {
292         return urlString;
293     }
294
295     /**
296      * Get the original URL string with which this ScmUrl was created,
297      * without the module element (if any).
298      */

299     public String JavaDoc getUrlStringNoModule() {
300         if (getModule() != null) {
301             int lastColon = urlString.lastIndexOf(":");
302             if (lastColon <= 0) {
303                 throw new IllegalStateException JavaDoc("URL string appears to have a module element but no ':' in its url string.");
304             }
305             return urlString.substring(0, lastColon);
306         } else {
307             return urlString;
308         }
309     }
310 }
311
Popular Tags