1 /* 2 * Copyright (c) 1999, 2011, 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.cosnaming; 27 28 import javax.naming.Name; 29 import javax.naming.NamingException; 30 31 import java.net.MalformedURLException; 32 import java.util.Vector; 33 import java.util.StringTokenizer; 34 import com.sun.jndi.toolkit.url.UrlUtil; 35 36 /** 37 * Extract components of an "iiop" or "iiopname" URL. 38 * 39 * The format of an iiopname URL is defined in INS 98-10-11 as follows: 40 * 41 * <pre> 42 * iiopname url = "iiopname://" [addr_list]["/" string_name] 43 * addr_list = [address ","]* address 44 * address = [version host [":" port]] 45 * host = DNS style host name | IP address 46 * version = major "." minor "@" | empty_string 47 * port = number 48 * major = number 49 * minor = number 50 * string_name = stringified name | empty_string 51 * </pre> 52 * 53 * The default port is 9999. The default version is "1.0" 54 * US-ASCII alphanumeric characters are not escaped. Any characters outside 55 * of this range are escaped except for the following: 56 * <pre>{@code 57 * ; / : ? : @ & = + $ , - _ . ! ~ * ' ( ) 58 * }</pre> 59 * Escaped characters is escaped by using a % followed by its 2 hexadecimal 60 * numbers representing the octet. 61 * 62 * For backward compatibility, the "iiop" URL as defined in INS 97-6-6 63 * is also supported: 64 * <pre>{@code 65 * iiop url = "iiop://" [host [":" port]] ["/" string_name] 66 * }</pre> 67 * The default port is 900. 68 * 69 * @author Rosanna Lee 70 */ 71 72 public final class IiopUrl { 73 static final private int DEFAULT_IIOPNAME_PORT = 9999; 74 static final private int DEFAULT_IIOP_PORT = 900; 75 static final private String DEFAULT_HOST = "localhost"; 76 private Vector<Address> addresses; 77 private String stringName; 78 79 public static class Address { 80 public int port = -1; 81 public int major, minor; 82 public String host; 83 84 public Address(String hostPortVers, boolean oldFormat) 85 throws MalformedURLException { 86 // [version host [":" port]] 87 int start; 88 89 // Parse version 90 int at; 91 if (oldFormat || (at = hostPortVers.indexOf('@')) < 0) { 92 major = 1; 93 minor = 0; 94 start = 0; // start at the beginning 95 } else { 96 int dot = hostPortVers.indexOf('.'); 97 if (dot < 0) { 98 throw new MalformedURLException( 99 "invalid version: " + hostPortVers); 100 } 101 try { 102 major = Integer.parseInt(hostPortVers.substring(0, dot)); 103 minor = Integer.parseInt(hostPortVers.substring(dot+1, at)); 104 } catch (NumberFormatException e) { 105 throw new MalformedURLException( 106 "Nonnumeric version: " + hostPortVers); 107 } 108 start = at + 1; // skip '@' sign 109 } 110 111 // Parse host and port 112 int slash = hostPortVers.indexOf('/', start); 113 if (slash < 0) { 114 slash = hostPortVers.length(); 115 } 116 if (hostPortVers.startsWith("[", start)) { // at IPv6 literal 117 int brac = hostPortVers.indexOf(']', start + 1); 118 if (brac < 0 || brac > slash) { 119 throw new IllegalArgumentException( 120 "IiopURL: name is an Invalid URL: " + hostPortVers); 121 } 122 123 // include brackets 124 host = hostPortVers.substring(start, brac + 1); 125 start = brac + 1; 126 } else { // at hostname or IPv4 127 int colon = hostPortVers.indexOf(':', start); 128 int hostEnd = (colon < 0 || colon > slash) 129 ? slash 130 : colon; 131 if (start < hostEnd) { 132 host = hostPortVers.substring(start, hostEnd); 133 } 134 start = hostEnd; // skip past host 135 } 136 if ((start + 1 < slash)) { 137 if ( hostPortVers.startsWith(":", start)) { // parse port 138 start++; // skip past ":" 139 port = Integer.parseInt(hostPortVers. 140 substring(start, slash)); 141 } else { 142 throw new IllegalArgumentException( 143 "IiopURL: name is an Invalid URL: " + hostPortVers); 144 } 145 } 146 start = slash; 147 if ("".equals(host) || host == null) { 148 host = DEFAULT_HOST ; 149 } 150 if (port == -1) { 151 port = (oldFormat ? DEFAULT_IIOP_PORT : 152 DEFAULT_IIOPNAME_PORT); 153 } 154 } 155 } 156 157 public Vector<Address> getAddresses() { 158 return addresses; 159 } 160 161 /** 162 * Returns a possibly empty but non-null string that is the "string_name" 163 * portion of the URL. 164 */ 165 public String getStringName() { 166 return stringName; 167 } 168 169 public Name getCosName() throws NamingException { 170 return CNCtx.parser.parse(stringName); 171 } 172 173 public IiopUrl(String url) throws MalformedURLException { 174 int addrStart; 175 boolean oldFormat; 176 177 if (url.startsWith("iiopname://")) { 178 oldFormat = false; 179 addrStart = 11; 180 } else if (url.startsWith("iiop://")) { 181 oldFormat = true; 182 addrStart = 7; 183 } else { 184 throw new MalformedURLException("Invalid iiop/iiopname URL: " + url); 185 } 186 int addrEnd = url.indexOf('/', addrStart); 187 if (addrEnd < 0) { 188 addrEnd = url.length(); 189 stringName = ""; 190 } else { 191 stringName = UrlUtil.decode(url.substring(addrEnd+1)); 192 } 193 addresses = new Vector<>(3); 194 if (oldFormat) { 195 // Only one host:port part, not multiple 196 addresses.addElement( 197 new Address(url.substring(addrStart, addrEnd), oldFormat)); 198 } else { 199 StringTokenizer tokens = 200 new StringTokenizer(url.substring(addrStart, addrEnd), ","); 201 while (tokens.hasMoreTokens()) { 202 addresses.addElement(new Address(tokens.nextToken(), oldFormat)); 203 } 204 if (addresses.size() == 0) { 205 addresses.addElement(new Address("", oldFormat)); 206 } 207 } 208 } 209 210 // for testing only 211 /*public static void main(String[] args) { 212 try { 213 IiopUrl url = new IiopUrl(args[0]); 214 Vector addrs = url.getAddresses(); 215 String name = url.getStringName(); 216 217 for (int i = 0; i < addrs.size(); i++) { 218 Address addr = (Address)addrs.elementAt(i); 219 System.out.println("host: " + addr.host); 220 System.out.println("port: " + addr.port); 221 System.out.println("version: " + addr.major + " " + addr.minor); 222 } 223 System.out.println("name: " + name); 224 } catch (MalformedURLException e) { 225 e.printStackTrace(); 226 } 227 } */ 228 }