1 /* 2 * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jndi.toolkit.url; 27 28 29 import java.net.MalformedURLException; 30 31 32 /** 33 * A Uri object represents an absolute Uniform Resource Identifier 34 * (URI) as defined by RFC 2396 and updated by RFC 2373 and RFC 2732. 35 * The most commonly used form of URI is the Uniform Resource Locator (URL). 36 * 37 * <p> The java.net.URL class cannot be used to parse URIs since it 38 * requires the installation of URL stream handlers that may not be 39 * available. The hack of getting around this by temporarily 40 * replacing the scheme part of a URI is not appropriate here: JNDI 41 * service providers must work on older Java platforms, and we want 42 * new features and bug fixes that are not available in old versions 43 * of the URL class. 44 * 45 * <p> It may be appropriate to drop this code in favor of the 46 * java.net.URI class. The changes would need to be written so as to 47 * still run on pre-1.4 platforms not containing that class. 48 * 49 * <p> The format of an absolute URI (see the RFCs mentioned above) is: 50 * <blockquote><pre>{@code 51 * absoluteURI = scheme ":" ( hier_part | opaque_part ) 52 * 53 * scheme = alpha *( alpha | digit | "+" | "-" | "." ) 54 * 55 * hier_part = ( net_path | abs_path ) [ "?" query ] 56 * opaque_part = uric_no_slash *uric 57 * 58 * net_path = "//" authority [ abs_path ] 59 * abs_path = "/" path_segments 60 * 61 * authority = server | reg_name 62 * reg_name = 1*( unreserved | escaped | "$" | "," | 63 * ";" | ":" | "@" | "&" | "=" | "+" ) 64 * server = [ [ userinfo "@" ] hostport ] 65 * userinfo = *( unreserved | escaped | 66 * ";" | ":" | "&" | "=" | "+" | "$" | "," ) 67 * 68 * hostport = host [ ":" port ] 69 * host = hostname | IPv4address | IPv6reference 70 * port = *digit 71 * 72 * IPv6reference = "[" IPv6address "]" 73 * IPv6address = hexpart [ ":" IPv4address ] 74 * IPv4address = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit 75 * hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ] 76 * hexseq = hex4 *( ":" hex4) 77 * hex4 = 1*4hex 78 * 79 * path = [ abs_path | opaque_part ] 80 * path_segments = segment *( "/" segment ) 81 * segment = *pchar *( ";" param ) 82 * param = *pchar 83 * pchar = unreserved | escaped | 84 * ":" | "@" | "&" | "=" | "+" | "$" | "," 85 * 86 * query = *uric 87 * 88 * uric = reserved | unreserved | escaped 89 * uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | 90 * "&" | "=" | "+" | "$" | "," 91 * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | 92 * "$" | "," | "[" | "]" 93 * unreserved = alphanum | mark 94 * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" 95 * escaped = "%" hex hex 96 * unwise = "{" | "}" | "|" | "\" | "^" | "`" 97 * }</pre></blockquote> 98 * 99 * <p> Currently URIs containing {@code userinfo} or {@code reg_name} 100 * are not supported. 101 * The {@code opaque_part} of a non-hierarchical URI is treated as if 102 * if were a {@code path} without a leading slash. 103 */ 104 105 106 public class Uri { 107 108 protected String uri; 109 protected String scheme; 110 protected String host = null; 111 protected int port = -1; 112 protected boolean hasAuthority; 113 protected String path; 114 protected String query = null; 115 116 117 /** 118 * Creates a Uri object given a URI string. 119 */ 120 public Uri(String uri) throws MalformedURLException { 121 init(uri); 122 } 123 124 /** 125 * Creates an uninitialized Uri object. The init() method must 126 * be called before any other Uri methods. 127 */ 128 protected Uri() { 129 } 130 131 /** 132 * Initializes a Uri object given a URI string. 133 * This method must be called exactly once, and before any other Uri 134 * methods. 135 */ 136 protected void init(String uri) throws MalformedURLException { 137 this.uri = uri; 138 parse(uri); 139 } 140 141 /** 142 * Returns the URI's scheme. 143 */ 144 public String getScheme() { 145 return scheme; 146 } 147 148 /** 149 * Returns the host from the URI's authority part, or null 150 * if no host is provided. If the host is an IPv6 literal, the 151 * delimiting brackets are part of the returned value (see 152 * {@link java.net.URI#getHost}). 153 */ 154 public String getHost() { 155 return host; 156 } 157 158 /** 159 * Returns the port from the URI's authority part, or -1 if 160 * no port is provided. 161 */ 162 public int getPort() { 163 return port; 164 } 165 166 /** 167 * Returns the URI's path. The path is never null. Note that a 168 * slash following the authority part (or the scheme if there is 169 * no authority part) is part of the path. For example, the path 170 * of "http://host/a/b" is "/a/b". 171 */ 172 public String getPath() { 173 return path; 174 } 175 176 /** 177 * Returns the URI's query part, or null if no query is provided. 178 * Note that a query always begins with a leading "?". 179 */ 180 public String getQuery() { 181 return query; 182 } 183 184 /** 185 * Returns the URI as a string. 186 */ 187 public String toString() { 188 return uri; 189 } 190 191 /* 192 * Parses a URI string and sets this object's fields accordingly. 193 */ 194 private void parse(String uri) throws MalformedURLException { 195 int i; // index into URI 196 197 i = uri.indexOf(':'); // parse scheme 198 if (i < 0) { 199 throw new MalformedURLException("Invalid URI: " + uri); 200 } 201 scheme = uri.substring(0, i); 202 i++; // skip past ":" 203 204 hasAuthority = uri.startsWith("//", i); 205 if (hasAuthority) { // parse "//host:port" 206 i += 2; // skip past "//" 207 int slash = uri.indexOf('/', i); 208 if (slash < 0) { 209 slash = uri.length(); 210 } 211 if (uri.startsWith("[", i)) { // at IPv6 literal 212 int brac = uri.indexOf(']', i + 1); 213 if (brac < 0 || brac > slash) { 214 throw new MalformedURLException("Invalid URI: " + uri); 215 } 216 host = uri.substring(i, brac + 1); // include brackets 217 i = brac + 1; // skip past "[...]" 218 } else { // at host name or IPv4 219 int colon = uri.indexOf(':', i); 220 int hostEnd = (colon < 0 || colon > slash) 221 ? slash 222 : colon; 223 if (i < hostEnd) { 224 host = uri.substring(i, hostEnd); 225 } 226 i = hostEnd; // skip past host 227 } 228 229 if ((i + 1 < slash) && 230 uri.startsWith(":", i)) { // parse port 231 i++; // skip past ":" 232 port = Integer.parseInt(uri.substring(i, slash)); 233 } 234 i = slash; // skip to path 235 } 236 int qmark = uri.indexOf('?', i); // look for query 237 if (qmark < 0) { 238 path = uri.substring(i); 239 } else { 240 path = uri.substring(i, qmark); 241 query = uri.substring(qmark); 242 } 243 } 244 245 /* 246 // Debug 247 public static void main(String args[]) throws MalformedURLException { 248 for (int i = 0; i < args.length; i++) { 249 Uri uri = new Uri(args[i]); 250 251 String h = (uri.getHost() != null) ? uri.getHost() : ""; 252 String p = (uri.getPort() != -1) ? (":" + uri.getPort()) : ""; 253 String a = uri.hasAuthority ? ("//" + h + p) : ""; 254 String q = (uri.getQuery() != null) ? uri.getQuery() : ""; 255 256 String str = uri.getScheme() + ":" + a + uri.getPath() + q; 257 if (! uri.toString().equals(str)) { 258 System.out.println(str); 259 } 260 System.out.println(h); 261 } 262 } 263 */ 264 }