xref: /illumos-gate/usr/src/lib/libslp/javalib/com/sun/slp/ServiceURL.java (revision 55fea89dcaa64928bed4327112404dcb3e07b79f)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*9a70fc3bSMark J. Nelson  * Common Development and Distribution License (the "License").
6*9a70fc3bSMark J. Nelson  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate  * Copyright (c) 1999 by Sun Microsystems, Inc.
237c478bd9Sstevel@tonic-gate  * All rights reserved.
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27*9a70fc3bSMark J. Nelson //  ServiceURL.java :  The service URL.
287c478bd9Sstevel@tonic-gate //  Author:           James Kempf, Erik Guttman
297c478bd9Sstevel@tonic-gate //
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate package com.sun.slp;
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate import java.util.*;
347c478bd9Sstevel@tonic-gate import java.io.*;
357c478bd9Sstevel@tonic-gate import java.net.*;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /**
387c478bd9Sstevel@tonic-gate  * The ServiceURL object models the SLP service URL. Both service: URLs
397c478bd9Sstevel@tonic-gate  * and regular URLs are handled by this class.
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  * @author James Kempf, Erik Guttman
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate public class ServiceURL extends Object implements Serializable   {
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate     // Recognized transports.
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate     private final static String IPX = "ipx";
497c478bd9Sstevel@tonic-gate     private final static String AT = "at";
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate     /**
527c478bd9Sstevel@tonic-gate      * Indicates that no port information is required or was returned
537c478bd9Sstevel@tonic-gate      * for this service URL.
547c478bd9Sstevel@tonic-gate      */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate     public static final int NO_PORT = 0;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate     /**
597c478bd9Sstevel@tonic-gate      * No life time parameter is given.
607c478bd9Sstevel@tonic-gate      */
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate     public static final int LIFETIME_NONE    =  0;
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate     /**
657c478bd9Sstevel@tonic-gate      * Default lifetime, 3 hours.
667c478bd9Sstevel@tonic-gate      */
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate     public static final int LIFETIME_DEFAULT = 10800;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate     /**
717c478bd9Sstevel@tonic-gate      * Maximum lifetime, approximately 18 hours.
727c478bd9Sstevel@tonic-gate      */
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate     public static final int LIFETIME_MAXIMUM = 0xFFFF;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate     /**
777c478bd9Sstevel@tonic-gate      * Reregister periodically.
787c478bd9Sstevel@tonic-gate      */
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate     public static final int LIFETIME_PERMANENT = -1;
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate     // Maximum port size.
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate     static final int PORT_MAXIMUM = 0xFFFF;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate     //
887c478bd9Sstevel@tonic-gate     // data fields
897c478bd9Sstevel@tonic-gate     //
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate     private ServiceType serviceType = null;
927c478bd9Sstevel@tonic-gate     private ServiceType originalServiceType = null;
937c478bd9Sstevel@tonic-gate     private String transport = "";
947c478bd9Sstevel@tonic-gate     private String host = "";
957c478bd9Sstevel@tonic-gate     private int port = NO_PORT;
967c478bd9Sstevel@tonic-gate     private String URLPath = "";
977c478bd9Sstevel@tonic-gate     private int lifetime = LIFETIME_DEFAULT;
987c478bd9Sstevel@tonic-gate     private boolean isPermanent = false;
997c478bd9Sstevel@tonic-gate     private boolean noDoubleSlash = false;
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate     /**
1027c478bd9Sstevel@tonic-gate      * Construct a service URL object.
1037c478bd9Sstevel@tonic-gate      *
1047c478bd9Sstevel@tonic-gate      * @param URL		The service URL as a string.
1057c478bd9Sstevel@tonic-gate      * @param iLifetime		The service advertisement lifetime.
1067c478bd9Sstevel@tonic-gate      * @exception IllegalArgumentException Thrown if parse
1077c478bd9Sstevel@tonic-gate      *				          errors occur in the
1087c478bd9Sstevel@tonic-gate      *					  parameter.
1097c478bd9Sstevel@tonic-gate      */
1107c478bd9Sstevel@tonic-gate 
ServiceURL(String URL, int iLifetime)1117c478bd9Sstevel@tonic-gate     public ServiceURL(String URL, int iLifetime)
1127c478bd9Sstevel@tonic-gate 	throws IllegalArgumentException {
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	Assert.nonNullParameter(URL, "URL");
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if ((iLifetime > LIFETIME_MAXIMUM) ||
1177c478bd9Sstevel@tonic-gate 	   (iLifetime < LIFETIME_PERMANENT)) {
1187c478bd9Sstevel@tonic-gate 	    throw
1197c478bd9Sstevel@tonic-gate 		new IllegalArgumentException(
1207c478bd9Sstevel@tonic-gate 		SLPConfig.getSLPConfig().formatMessage("lifetime_error",
1217c478bd9Sstevel@tonic-gate 						       new Object[0]));
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	checkURLString(URL);
1257c478bd9Sstevel@tonic-gate 	parseURL(URL);
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	if (iLifetime == LIFETIME_PERMANENT) {
1287c478bd9Sstevel@tonic-gate 	    isPermanent = true;
1297c478bd9Sstevel@tonic-gate 	    iLifetime = LIFETIME_MAXIMUM;
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	}
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	lifetime = iLifetime;
1347c478bd9Sstevel@tonic-gate     }
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate     //
1377c478bd9Sstevel@tonic-gate     // ------------------------------------------------------------------
1387c478bd9Sstevel@tonic-gate     // Accessors
1397c478bd9Sstevel@tonic-gate     // ------------------------------------------------------------------
1407c478bd9Sstevel@tonic-gate     //
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate     /**
1437c478bd9Sstevel@tonic-gate      * @return The service type name.
1447c478bd9Sstevel@tonic-gate      */
1457c478bd9Sstevel@tonic-gate 
getServiceType()1467c478bd9Sstevel@tonic-gate     public ServiceType getServiceType() {
1477c478bd9Sstevel@tonic-gate 	return serviceType;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate     }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate     /**
1527c478bd9Sstevel@tonic-gate      * Set service type and naming authority if this is not a service: URL.
1537c478bd9Sstevel@tonic-gate      *
1547c478bd9Sstevel@tonic-gate      * @param type The new ServiceType object.
1557c478bd9Sstevel@tonic-gate      * @exception IllegalArgumentException If the service type name or
1567c478bd9Sstevel@tonic-gate      *					 naming authority name is invalid.
1577c478bd9Sstevel@tonic-gate      */
1587c478bd9Sstevel@tonic-gate 
setServiceType(ServiceType type)1597c478bd9Sstevel@tonic-gate     public void setServiceType(ServiceType type) {
1607c478bd9Sstevel@tonic-gate 	if (!serviceType.isServiceURL()) {
1617c478bd9Sstevel@tonic-gate 	    serviceType = type;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate     }
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate     /**
1687c478bd9Sstevel@tonic-gate      * @return The machine name or IP address.
1697c478bd9Sstevel@tonic-gate      */
1707c478bd9Sstevel@tonic-gate 
getHost()1717c478bd9Sstevel@tonic-gate     public String getHost() {
1727c478bd9Sstevel@tonic-gate 	return host;
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate     }
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate     /**
1777c478bd9Sstevel@tonic-gate      * @return The port number, if any.
1787c478bd9Sstevel@tonic-gate      */
1797c478bd9Sstevel@tonic-gate 
getPort()1807c478bd9Sstevel@tonic-gate     public int getPort() {
1817c478bd9Sstevel@tonic-gate 	return port;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate     }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate     /**
1867c478bd9Sstevel@tonic-gate      * @return The URL path description, if any.
1877c478bd9Sstevel@tonic-gate      */
1887c478bd9Sstevel@tonic-gate 
getURLPath()1897c478bd9Sstevel@tonic-gate     public String getURLPath() {
1907c478bd9Sstevel@tonic-gate 	return URLPath;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate     }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate     /**
1957c478bd9Sstevel@tonic-gate      * @return The service advertisement lifetime.
1967c478bd9Sstevel@tonic-gate      */
1977c478bd9Sstevel@tonic-gate 
getLifetime()1987c478bd9Sstevel@tonic-gate     public int getLifetime() {
1997c478bd9Sstevel@tonic-gate 	return lifetime;
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate     }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate     /**
2047c478bd9Sstevel@tonic-gate      * Formats the service URL into standard URL form.
2057c478bd9Sstevel@tonic-gate      *
2067c478bd9Sstevel@tonic-gate      * @return Formatted string with the service URL.
2077c478bd9Sstevel@tonic-gate      */
2087c478bd9Sstevel@tonic-gate 
toString()2097c478bd9Sstevel@tonic-gate     public String toString() {  // Overrides Object.toString();
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	return
2127c478bd9Sstevel@tonic-gate 	    originalServiceType.toString() +
2137c478bd9Sstevel@tonic-gate 	    ":/" + transport + (noDoubleSlash == false ? "/":"") +
2147c478bd9Sstevel@tonic-gate 	    host + (port != NO_PORT ? (":" + port) : "") +
2157c478bd9Sstevel@tonic-gate 	    URLPath;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate     }
2187c478bd9Sstevel@tonic-gate 
hashCode()2197c478bd9Sstevel@tonic-gate     public int hashCode() {
2207c478bd9Sstevel@tonic-gate 	return
2217c478bd9Sstevel@tonic-gate 	    serviceType.hashCode() +
2227c478bd9Sstevel@tonic-gate 	    transport.hashCode() +
2237c478bd9Sstevel@tonic-gate 	    host.hashCode() +
2247c478bd9Sstevel@tonic-gate 	    port +
2257c478bd9Sstevel@tonic-gate 	    URLPath.hashCode();
2267c478bd9Sstevel@tonic-gate     }
2277c478bd9Sstevel@tonic-gate 
equals(Object obj)2287c478bd9Sstevel@tonic-gate     public boolean equals(Object obj) {
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (obj == this) {
2317c478bd9Sstevel@tonic-gate 	    return true;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	if (!(obj instanceof ServiceURL)) {
2367c478bd9Sstevel@tonic-gate 	    return false;
2377c478bd9Sstevel@tonic-gate 	}
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	ServiceURL surl = (ServiceURL)obj;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	return
2427c478bd9Sstevel@tonic-gate 	    serviceType.equals(surl.serviceType) &&
2437c478bd9Sstevel@tonic-gate 	    transport.equals(surl.transport) &&
2447c478bd9Sstevel@tonic-gate 	    host.equals(surl.host) &&
2457c478bd9Sstevel@tonic-gate 	    (port == surl.port) &&
2467c478bd9Sstevel@tonic-gate 	    (noDoubleSlash == surl.noDoubleSlash) &&
2477c478bd9Sstevel@tonic-gate 	    URLPath.equals(surl.URLPath);
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate     }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate     // Return permanent status.
2527c478bd9Sstevel@tonic-gate 
getIsPermanent()2537c478bd9Sstevel@tonic-gate     boolean getIsPermanent() {
2547c478bd9Sstevel@tonic-gate 	return isPermanent;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate     }
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate     // Check URL characters for correctness.
2597c478bd9Sstevel@tonic-gate 
checkURLString(String s)2607c478bd9Sstevel@tonic-gate     private void checkURLString(String s)
2617c478bd9Sstevel@tonic-gate 	throws IllegalArgumentException {
2627c478bd9Sstevel@tonic-gate 	for (int i = 0; i < s.length(); i++) {
2637c478bd9Sstevel@tonic-gate 	    char c = s.charAt(i);
2647c478bd9Sstevel@tonic-gate 	    // allowed by RFC1738
2657c478bd9Sstevel@tonic-gate 	    if (c == '/' || c == ':' || c == '-' || c == ':' ||
2667c478bd9Sstevel@tonic-gate 		c == '.' || c == '%' || c == '_' || c == '\'' ||
2677c478bd9Sstevel@tonic-gate 		c == '*' || c == '(' || c == ')' || c == '$' ||
2687c478bd9Sstevel@tonic-gate 		c == '!' || c == ',' || c == '+' || c == '\\') {
2697c478bd9Sstevel@tonic-gate 							// defer to Windows
2707c478bd9Sstevel@tonic-gate 		continue;
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	    }
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	    // reserved by RFC1738, and thus allowed, pg. 20
2757c478bd9Sstevel@tonic-gate 	    if (c == ';' || c == '@' || c == '?' || c == '&' || c == '=') {
2767c478bd9Sstevel@tonic-gate 		continue;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	    }
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	    if (Character.isLetterOrDigit(c)) {
2817c478bd9Sstevel@tonic-gate 		continue;
2827c478bd9Sstevel@tonic-gate 	    }
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 	    SLPConfig conf = SLPConfig.getSLPConfig();
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	    throw
2877c478bd9Sstevel@tonic-gate 		new IllegalArgumentException(
2887c478bd9Sstevel@tonic-gate 				conf.formatMessage("url_char_error",
2897c478bd9Sstevel@tonic-gate 						   new Object[] {
2907c478bd9Sstevel@tonic-gate 				    new Character(c)}));
2917c478bd9Sstevel@tonic-gate 	}
2927c478bd9Sstevel@tonic-gate     }
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate     // Parse the incoming service URL specification.
2957c478bd9Sstevel@tonic-gate 
parseURL(String sURL)2967c478bd9Sstevel@tonic-gate     private void parseURL(String sURL)
2977c478bd9Sstevel@tonic-gate 	throws IllegalArgumentException {
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	StringTokenizer st = new StringTokenizer(sURL, "/", true);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	try {
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	    // This loop is a kludgy way to break out of the parse so
3047c478bd9Sstevel@tonic-gate 	    //  we only throw at one location in the code.
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	    do {
3077c478bd9Sstevel@tonic-gate 		String typeName = st.nextToken();
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 		// First token must be service type name.
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 		if (typeName.equals("/")) {
3127c478bd9Sstevel@tonic-gate 		    break; // error!
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 		}
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 		// Check for colon terminator, not part of service
3177c478bd9Sstevel@tonic-gate 		// type name.
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 		if (!typeName.endsWith(":")) {
3207c478bd9Sstevel@tonic-gate 		    break; // error!
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 		}
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 		// Create service type, remove trailing colon.
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 		serviceType =
3277c478bd9Sstevel@tonic-gate 		    new ServiceType(typeName.substring(0,
3287c478bd9Sstevel@tonic-gate 						       typeName.length() - 1));
3297c478bd9Sstevel@tonic-gate 		originalServiceType = serviceType;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 		// Separator between service type name and transport.
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 		String slash1 = st.nextToken();
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 		if (!slash1.equals("/")) {
3367c478bd9Sstevel@tonic-gate 		    break; // error!
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 		}
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 		String slash2 = st.nextToken();
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 		String sAddr = "";  // address...
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 		// Check for abstract type or alternate transport.
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 		if (!slash2.equals("/")) {
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 		    // If this is an abstract type, then we could have
3497c478bd9Sstevel@tonic-gate 		    //  something like: service:file-printer:file:/foo/bar.
3507c478bd9Sstevel@tonic-gate 		    //  This is OK. Also, if this is a non-service: URL,
3517c478bd9Sstevel@tonic-gate 		    //  something like file:/foo/bar is OK.
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 		    if (!serviceType.isServiceURL()) {
3547c478bd9Sstevel@tonic-gate 			sAddr = slash2;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 			noDoubleSlash = true;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 		    } else {
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 			// We only recognize IPX and Appletalk at this point.
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 			if (!slash2.equalsIgnoreCase(IPX) &&
3637c478bd9Sstevel@tonic-gate 			    !slash2.equalsIgnoreCase(AT)) {
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 			    // Abstract type is OK. We must check here because
3667c478bd9Sstevel@tonic-gate 			    //  something like
3677c478bd9Sstevel@tonic-gate 			    //  service:printing:lpr:/ipx/foo/bar
3687c478bd9Sstevel@tonic-gate 			    //  is allowed.
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 			    if (serviceType.isAbstractType()) {
3717c478bd9Sstevel@tonic-gate 				sAddr = slash2;
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 				noDoubleSlash = true;
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 			    } else {
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 				break;  // error!
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 			    }
3807c478bd9Sstevel@tonic-gate 			} else {
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 			    transport = slash2.toLowerCase();
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 			    // Check for separator between transport and host.
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 			    if (!st.nextToken().equals("/")) {
3877c478bd9Sstevel@tonic-gate 				break; // error!
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 			    }
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 			    sAddr = st.nextToken();
3927c478bd9Sstevel@tonic-gate 			}
3937c478bd9Sstevel@tonic-gate 		    }
3947c478bd9Sstevel@tonic-gate 		} else {
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 		    // Not abstract type, no alternate transport. Get host.
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 		    sAddr = st.nextToken();
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 		}
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 		if (sAddr.equals("/")) {// no host part
4037c478bd9Sstevel@tonic-gate 		    URLPath = "/" + st.nextToken("");
4047c478bd9Sstevel@tonic-gate 		    return; // we're done!
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 		}
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 		host = sAddr;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 		// Need to check for port number if this is an IP transport.
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 		if (transport.equals("")) {
4137c478bd9Sstevel@tonic-gate 		    StringTokenizer tk = new StringTokenizer(host, ":");
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 		    host = tk.nextToken();
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 		    // Get port if any.
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 		    if (tk.hasMoreTokens()) {
4207c478bd9Sstevel@tonic-gate 			String p = tk.nextToken();
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 			if (tk.hasMoreTokens()) {
4237c478bd9Sstevel@tonic-gate 			    break; // error!
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 			}
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 			try {
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 			    port = Integer.parseInt(p);
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 			} catch (NumberFormatException ex) {
4327c478bd9Sstevel@tonic-gate 			    break; // error!
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 			}
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 			if (port <= 0 || port > PORT_MAXIMUM) {
4377c478bd9Sstevel@tonic-gate 			    break; // error!
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 			}
4407c478bd9Sstevel@tonic-gate 		    }
4417c478bd9Sstevel@tonic-gate 		}
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 		//
4447c478bd9Sstevel@tonic-gate 		// after this point we have to check if there is a token
4457c478bd9Sstevel@tonic-gate 		// remaining before we read it: It is legal to stop at any
4467c478bd9Sstevel@tonic-gate 		// point now.  Before all the tokens were required, so
4477c478bd9Sstevel@tonic-gate 		// missing any was an error.
4487c478bd9Sstevel@tonic-gate 		//
4497c478bd9Sstevel@tonic-gate 		if (st.hasMoreTokens() == false) {
4507c478bd9Sstevel@tonic-gate 					//  minimal url service:t:// a
4517c478bd9Sstevel@tonic-gate 		    return; // we're done!
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 		}
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 		String sSep  = st.nextToken();
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 		if (!sSep.equals("/")) {
4587c478bd9Sstevel@tonic-gate 		    break; // error!
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 		}
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 		// there is a URL path
4637c478bd9Sstevel@tonic-gate 		// URLPath is all remaining tokens
4647c478bd9Sstevel@tonic-gate 		URLPath = sSep;
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 		if (st.hasMoreTokens()) {
4677c478bd9Sstevel@tonic-gate 		    URLPath += st.nextToken("");
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 		}
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		URLPath = URLPath.trim();
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 		return; // done!
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	    } while (false); // done with parse.
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	} catch (NoSuchElementException ex) {
4787c478bd9Sstevel@tonic-gate 	    throw
4797c478bd9Sstevel@tonic-gate 		new IllegalArgumentException(
4807c478bd9Sstevel@tonic-gate 		SLPConfig.getSLPConfig().formatMessage("url_syntax_error",
4817c478bd9Sstevel@tonic-gate 						       new Object[] {sURL}));
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	}
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	// The only way to get here is if there was an error in the
4867c478bd9Sstevel@tonic-gate 	//  parse.
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	throw
4897c478bd9Sstevel@tonic-gate 	    new IllegalArgumentException(
4907c478bd9Sstevel@tonic-gate 		SLPConfig.getSLPConfig().formatMessage("url_syntax_error",
4917c478bd9Sstevel@tonic-gate 						       new Object[] {sURL}));
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate     }
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate }
496