IiopUrl.java revision 820:9205e980062a
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
26package com.sun.jndi.cosnaming;
27
28import javax.naming.Name;
29import javax.naming.NamingException;
30
31import java.net.MalformedURLException;
32import java.util.Vector;
33import java.util.StringTokenizer;
34import com.sun.jndi.toolkit.corba.CorbaUtils;
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
72public 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 = CorbaUtils.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}
229