Switch jgit library to the EDL (3-clause BSD)
[jgit.git] / org.spearce.jgit / src / org / spearce / jgit / transport / URIish.java
blob307b591f201ea76e43cff1416f8fa234c5744f99
1 /*
2 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or
8 * without modification, are permitted provided that the following
9 * conditions are met:
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
19 * - Neither the name of the Git Development Community nor the
20 * names of its contributors may be used to endorse or promote
21 * products derived from this software without specific prior
22 * written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 package org.spearce.jgit.transport;
41 import java.net.URISyntaxException;
42 import java.util.regex.Matcher;
43 import java.util.regex.Pattern;
45 /**
46 * This URI like construct used for referencing Git archives over the net, as
47 * well as locally stored archives. The most important difference compared to
48 * RFC 2396 URI's is that no URI encoding/decoding ever takes place. A space or
49 * any special character is written as-is.
51 public class URIish {
52 private static final Pattern FULL_URI = Pattern
53 .compile("^(?:([a-z+]+)://(?:([^/]+?)(?::([^/]+?))?@)?(?:([^/]+?))?(?::(\\d+))?)?((?:[A-Za-z]:)?/.+)$");
55 private static final Pattern SCP_URI = Pattern
56 .compile("^(?:([^@]+?)@)?([^:]+?):(.+)$");
58 private String scheme;
60 private String path;
62 private String user;
64 private String pass;
66 private int port = -1;
68 private String host;
70 /**
71 * Parse and construct an {@link URIish} from a string
73 * @param s
74 * @throws URISyntaxException
76 public URIish(String s) throws URISyntaxException {
77 Matcher matcher = FULL_URI.matcher(s);
78 if (matcher.matches()) {
79 scheme = matcher.group(1);
80 user = matcher.group(2);
81 pass = matcher.group(3);
82 host = matcher.group(4);
83 if (matcher.group(5) != null)
84 port = Integer.parseInt(matcher.group(5));
85 path = matcher.group(6);
86 if (path.length() >= 3
87 && path.charAt(0) == '/'
88 && path.charAt(2) == ':'
89 && (path.charAt(1) >= 'A' && path.charAt(1) <= 'Z'
90 || path.charAt(1) >= 'a' && path.charAt(1) <= 'z'))
91 path = path.substring(1);
92 } else {
93 matcher = SCP_URI.matcher(s);
94 if (matcher.matches()) {
95 user = matcher.group(1);
96 host = matcher.group(2);
97 path = matcher.group(3);
98 } else
99 throw new URISyntaxException(s, "Cannot parse Git URI-ish");
103 /** Create an empty, non-configured URI. */
104 public URIish() {
105 // Configure nothing.
108 private URIish(final URIish u) {
109 this.scheme = u.scheme;
110 this.path = u.path;
111 this.user = u.user;
112 this.pass = u.pass;
113 this.port = u.port;
114 this.host = u.host;
118 * @return true if this URI references a repository on another system.
120 public boolean isRemote() {
121 return getHost() != null;
125 * @return host name part or null
127 public String getHost() {
128 return host;
132 * Return a new URI matching this one, but with a different host.
134 * @param n
135 * the new value for host.
136 * @return a new URI with the updated value.
138 public URIish setHost(final String n) {
139 final URIish r = new URIish(this);
140 r.host = n;
141 return r;
145 * @return protocol name or null for local references
147 public String getScheme() {
148 return scheme;
152 * Return a new URI matching this one, but with a different scheme.
154 * @param n
155 * the new value for scheme.
156 * @return a new URI with the updated value.
158 public URIish setScheme(final String n) {
159 final URIish r = new URIish(this);
160 r.scheme = n;
161 return r;
165 * @return path name component
167 public String getPath() {
168 return path;
172 * Return a new URI matching this one, but with a different path.
174 * @param n
175 * the new value for path.
176 * @return a new URI with the updated value.
178 public URIish setPath(final String n) {
179 final URIish r = new URIish(this);
180 r.path = n;
181 return r;
185 * @return user name requested for transfer or null
187 public String getUser() {
188 return user;
192 * Return a new URI matching this one, but with a different user.
194 * @param n
195 * the new value for user.
196 * @return a new URI with the updated value.
198 public URIish setUser(final String n) {
199 final URIish r = new URIish(this);
200 r.user = n;
201 return r;
205 * @return password requested for transfer or null
207 public String getPass() {
208 return pass;
212 * Return a new URI matching this one, but with a different password.
214 * @param n
215 * the new value for password.
216 * @return a new URI with the updated value.
218 public URIish setPass(final String n) {
219 final URIish r = new URIish(this);
220 r.pass = n;
221 return r;
225 * @return port number requested for transfer or -1 if not explicit
227 public int getPort() {
228 return port;
232 * Return a new URI matching this one, but with a different port.
234 * @param n
235 * the new value for port.
236 * @return a new URI with the updated value.
238 public URIish setPort(final int n) {
239 final URIish r = new URIish(this);
240 r.port = n > 0 ? n : -1;
241 return r;
244 public int hashCode() {
245 int hc = 0;
246 if (getScheme() != null)
247 hc = hc * 31 + getScheme().hashCode();
248 if (getUser() != null)
249 hc = hc * 31 + getUser().hashCode();
250 if (getPass() != null)
251 hc = hc * 31 + getPass().hashCode();
252 if (getHost() != null)
253 hc = hc * 31 + getHost().hashCode();
254 if (getPort() > 0)
255 hc = hc * 31 + getPort();
256 if (getPath() != null)
257 hc = hc * 31 + getPath().hashCode();
258 return hc;
261 public boolean equals(final Object obj) {
262 if (!(obj instanceof URIish))
263 return false;
264 final URIish b = (URIish) obj;
265 if (!eq(getScheme(), b.getScheme()))
266 return false;
267 if (!eq(getUser(), b.getUser()))
268 return false;
269 if (!eq(getPass(), b.getPass()))
270 return false;
271 if (!eq(getHost(), b.getHost()))
272 return false;
273 if (getPort() != b.getPort())
274 return false;
275 if (!eq(getPath(), b.getPath()))
276 return false;
277 return true;
280 private static boolean eq(final String a, final String b) {
281 if (a == b)
282 return true;
283 if (a == null || b == null)
284 return false;
285 return a.equals(b);
288 public String toString() {
289 final StringBuilder r = new StringBuilder();
290 if (getScheme() != null) {
291 r.append(getScheme());
292 r.append("://");
295 if (getUser() != null) {
296 r.append(getUser());
297 if (getPass() != null) {
298 r.append(':');
299 r.append(getPass());
303 if (getHost() != null) {
304 if (getUser() != null)
305 r.append('@');
306 r.append(getHost());
307 if (getScheme() != null && getPort() > 0) {
308 r.append(':');
309 r.append(getPort());
313 if (getPath() != null) {
314 if (getScheme() != null) {
315 if (!getPath().startsWith("/"))
316 r.append('/');
317 } else if (getHost() != null)
318 r.append(':');
319 r.append(getPath());
322 return r.toString();