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
59a70fc3bSMark J. Nelson  * Common Development and Distribution License (the "License").
69a70fc3bSMark 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 
277c478bd9Sstevel@tonic-gate //  SLPTemplateRegistry.java: Service object for registering a new service
287c478bd9Sstevel@tonic-gate //			  template.
297c478bd9Sstevel@tonic-gate //  Author:           James Kempf
307c478bd9Sstevel@tonic-gate //  Created On:       Tue May 27 15:04:35 1997
317c478bd9Sstevel@tonic-gate //  Last Modified By: James Kempf
327c478bd9Sstevel@tonic-gate //  Last Modified On: Thu Jan  7 14:25:20 1999
337c478bd9Sstevel@tonic-gate //  Update Count:     134
347c478bd9Sstevel@tonic-gate //
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate package com.sun.slp;
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate import java.util.*;
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /**
417c478bd9Sstevel@tonic-gate  * The SLPTemplateRegistry class registers and unregisters service templates,
427c478bd9Sstevel@tonic-gate  * looks up the template based on the service type name, and returns an
437c478bd9Sstevel@tonic-gate  * attribute verifier for the service.It subclasses the TemplateRegistry
447c478bd9Sstevel@tonic-gate  * abstract class.
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  * An slp-template URL has the following format:
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  *   service:slp-template:<document URL>;type=<service type>;
497c478bd9Sstevel@tonic-gate  *				          version=<version no.>;
507c478bd9Sstevel@tonic-gate  *					  language=<language locale>
517c478bd9Sstevel@tonic-gate  *
527c478bd9Sstevel@tonic-gate  * @author James Kempf
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate class SLPTemplateRegistry extends TemplateRegistry {
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate     /**
597c478bd9Sstevel@tonic-gate      * Attribute id for attribute describing service type name.
607c478bd9Sstevel@tonic-gate      * String, single valued attribute.
617c478bd9Sstevel@tonic-gate      */
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate     static final String SERVICE_ATTR_ID = "template-type";
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate     /**
667c478bd9Sstevel@tonic-gate      * Attribute id for attribute describing help text.
677c478bd9Sstevel@tonic-gate      * String, single valued, required attribute, .
687c478bd9Sstevel@tonic-gate      */
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate     static final String DESCRIPTION_ATTR_ID = "template-description";
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate     /**
737c478bd9Sstevel@tonic-gate      * Attribute id for attribute describing service version. The
747c478bd9Sstevel@tonic-gate      * version number is of the form ``n.m'', where n and m are integers.
757c478bd9Sstevel@tonic-gate      * String, single valued, required attribute.
767c478bd9Sstevel@tonic-gate      */
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate     static final String VERSION_ATTR_ID = "template-version";
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate     /**
817c478bd9Sstevel@tonic-gate      * Attribute id for attribute describing service URL url part grammer.
827c478bd9Sstevel@tonic-gate      * String, single valued, required attribute.
837c478bd9Sstevel@tonic-gate      */
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate     static final String SERVICE_URL_ATTR_ID = "template-url-syntax";
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate     /**
887c478bd9Sstevel@tonic-gate      * The service type name for the template type.
897c478bd9Sstevel@tonic-gate      */
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate     static final String TEMPLATE_SERVICE_TYPE = "service:slp-template";
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate     // The distinguished template registry object.
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate     private static TemplateRegistry registry = null;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate     // Package private constructor for singleton pattern maintained
987c478bd9Sstevel@tonic-gate     // by the ServiceLocationManager.
997c478bd9Sstevel@tonic-gate 
SLPTemplateRegistry()1007c478bd9Sstevel@tonic-gate     SLPTemplateRegistry() throws ServiceLocationException {
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate     }
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate     //
1057c478bd9Sstevel@tonic-gate     // Public implementation.
1067c478bd9Sstevel@tonic-gate     //
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate     /**
1097c478bd9Sstevel@tonic-gate      * Register the new service.
1107c478bd9Sstevel@tonic-gate      *
1117c478bd9Sstevel@tonic-gate      * @param serviceType	Name of the service.
1127c478bd9Sstevel@tonic-gate      * @param documentURL	URL of the template document.
1137c478bd9Sstevel@tonic-gate      * @param languageLocale	Locale of the template langugae.
1147c478bd9Sstevel@tonic-gate      * @param version		Version number of template document.
1157c478bd9Sstevel@tonic-gate      * @exception ServiceLocationException Error code is
1167c478bd9Sstevel@tonic-gate      *				    INVALID_REGISTRATION
1177c478bd9Sstevel@tonic-gate      *					   if the service already exists or
1187c478bd9Sstevel@tonic-gate      *					   the registration fails.
1197c478bd9Sstevel@tonic-gate      *					   Throws
1207c478bd9Sstevel@tonic-gate      *				    SYSTEM_ERROR
1217c478bd9Sstevel@tonic-gate      *					   if the scope vector is null or
1227c478bd9Sstevel@tonic-gate      *					   empty.
1237c478bd9Sstevel@tonic-gate      *					   Throws
1247c478bd9Sstevel@tonic-gate      *				    PARSE_ERROR
1257c478bd9Sstevel@tonic-gate      *					   if an attribute is bad.
1267c478bd9Sstevel@tonic-gate      * @exception IllegalArgumentException Thrown if any parameters are null.
1277c478bd9Sstevel@tonic-gate      *
1287c478bd9Sstevel@tonic-gate      */
1297c478bd9Sstevel@tonic-gate 
registerServiceTemplate(ServiceType serviceType, String documentURL, Locale languageLocale, String version)1307c478bd9Sstevel@tonic-gate     public void registerServiceTemplate(ServiceType serviceType,
1317c478bd9Sstevel@tonic-gate 					String documentURL,
1327c478bd9Sstevel@tonic-gate 					Locale languageLocale,
1337c478bd9Sstevel@tonic-gate 					String version)
1347c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	// Check for illegal parameters.
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	Assert.nonNullParameter(serviceType, "serviceType");
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	Assert.nonNullParameter(documentURL, "documentURL");
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	Assert.nonNullParameter(languageLocale, "language");
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	Assert.nonNullParameter(version, "version");
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	String language = languageLocale.getLanguage();
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	if (language == null || language.length() <= 0) {
1497c478bd9Sstevel@tonic-gate 	    throw
1507c478bd9Sstevel@tonic-gate 		new IllegalArgumentException(
1517c478bd9Sstevel@tonic-gate 		SLPConfig.getSLPConfig().formatMessage("template_lang_null",
1527c478bd9Sstevel@tonic-gate 						       new Object[] {
1537c478bd9Sstevel@tonic-gate 		    documentURL}));
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	String turl = null;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	try {
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	    turl = findTemplateURL(serviceType,
1617c478bd9Sstevel@tonic-gate 				   languageLocale,
1627c478bd9Sstevel@tonic-gate 				   version);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	    // Ignore if language not supported, it just means there
1677c478bd9Sstevel@tonic-gate 	    //  isn't any.
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	    if (ex.getErrorCode() !=
1707c478bd9Sstevel@tonic-gate 		ServiceLocationException.LANGUAGE_NOT_SUPPORTED) {
1717c478bd9Sstevel@tonic-gate 		throw ex;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	    }
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	// Throw an exception if it exists.
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	if (turl != null) {
1797c478bd9Sstevel@tonic-gate 	    throw
1807c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
1817c478bd9Sstevel@tonic-gate 				ServiceLocationException.INVALID_REGISTRATION,
1827c478bd9Sstevel@tonic-gate 				"template_already_registered",
1837c478bd9Sstevel@tonic-gate 				new Object[] {
1847c478bd9Sstevel@tonic-gate 		    documentURL,
1857c478bd9Sstevel@tonic-gate 			version,
1867c478bd9Sstevel@tonic-gate 			languageLocale});
1877c478bd9Sstevel@tonic-gate 	}
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	// Construct attributes for the registration.
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	Vector attributes = new Vector();
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	// Add the service type name.
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	Vector values = new Vector();
1967c478bd9Sstevel@tonic-gate 	values.addElement(serviceType.toString());
1977c478bd9Sstevel@tonic-gate 	ServiceLocationAttribute attr =
1987c478bd9Sstevel@tonic-gate 	    new ServiceLocationAttribute(SERVICE_ATTR_ID, values);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	attributes.addElement(attr);
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	// Add the version.
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	values = new Vector();
2057c478bd9Sstevel@tonic-gate 	values.addElement(version);
2067c478bd9Sstevel@tonic-gate 	attr =
2077c478bd9Sstevel@tonic-gate 	    new ServiceLocationAttribute(VERSION_ATTR_ID, values);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	attributes.addElement(attr);
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	// Construct a service URL for the template.
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	ServiceURL surl =
2147c478bd9Sstevel@tonic-gate 	    new ServiceURL(TEMPLATE_SERVICE_TYPE +
2157c478bd9Sstevel@tonic-gate 			   ":"+
2167c478bd9Sstevel@tonic-gate 			   documentURL+
2177c478bd9Sstevel@tonic-gate 			   ";"+
2187c478bd9Sstevel@tonic-gate 			   SERVICE_ATTR_ID+
2197c478bd9Sstevel@tonic-gate 			   "="+
2207c478bd9Sstevel@tonic-gate 			   serviceType+
2217c478bd9Sstevel@tonic-gate 			   ";"+
2227c478bd9Sstevel@tonic-gate 			   VERSION_ATTR_ID+
2237c478bd9Sstevel@tonic-gate 			   "="+
2247c478bd9Sstevel@tonic-gate 			   version,
2257c478bd9Sstevel@tonic-gate 			   ServiceURL.LIFETIME_MAXIMUM);
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	// Do the registration.
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	Advertiser serviceAgent =
2317c478bd9Sstevel@tonic-gate 	    ServiceLocationManager.getAdvertiser(languageLocale);
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (serviceAgent == null) {
2347c478bd9Sstevel@tonic-gate 	    throw
2357c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
2367c478bd9Sstevel@tonic-gate 				ServiceLocationException.NOT_IMPLEMENTED,
2377c478bd9Sstevel@tonic-gate 				"no_advertiser",
2387c478bd9Sstevel@tonic-gate 				new Object[0]);
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	serviceAgent.register(surl, attributes);
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	// Note that the assumption here is that the URL containing the
2447c478bd9Sstevel@tonic-gate 	//  path to the template document is written "somehow".
2457c478bd9Sstevel@tonic-gate 	//  It is up to the client to make sure that the template document
2467c478bd9Sstevel@tonic-gate 	//  has been written.
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate     }
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate     /**
2517c478bd9Sstevel@tonic-gate      * Deregister the template for service type.
2527c478bd9Sstevel@tonic-gate      *
2537c478bd9Sstevel@tonic-gate      * @param serviceType	Name of service.
2547c478bd9Sstevel@tonic-gate      * @param <i>languageLocale</i> Language locale of template.
2557c478bd9Sstevel@tonic-gate      * @param <i>version</i> Version of the template, null for latest.
2567c478bd9Sstevel@tonic-gate      * @exception ServiceLocationException Thrown if the deregistration
2577c478bd9Sstevel@tonic-gate      *					  fails.
2587c478bd9Sstevel@tonic-gate      * @exception IllegalArgumentException Thrown if the parameter is null.
2597c478bd9Sstevel@tonic-gate      *
2607c478bd9Sstevel@tonic-gate      */
2617c478bd9Sstevel@tonic-gate 
deregisterServiceTemplate(ServiceType serviceType, Locale languageLocale, String version)2627c478bd9Sstevel@tonic-gate     public void deregisterServiceTemplate(ServiceType serviceType,
2637c478bd9Sstevel@tonic-gate 					  Locale languageLocale,
2647c478bd9Sstevel@tonic-gate 					  String version)
2657c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	// Check the parameter.
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	Assert.nonNullParameter(serviceType, "serviceType");
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	Assert.nonNullParameter(languageLocale, "languageLocale");
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	// Get the template document URL for the service.
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	ServiceURL turl = findVersionedURL(serviceType,
2767c478bd9Sstevel@tonic-gate 					   languageLocale,
2777c478bd9Sstevel@tonic-gate 					   version);
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	// If there's no template, then throw an exception.
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	if (turl == null) {
2827c478bd9Sstevel@tonic-gate 	    throw
2837c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
2847c478bd9Sstevel@tonic-gate 				ServiceLocationException.INVALID_REGISTRATION,
2857c478bd9Sstevel@tonic-gate 				"template_not_registered",
2867c478bd9Sstevel@tonic-gate 				new Object[] {
2877c478bd9Sstevel@tonic-gate 		    serviceType,
2887c478bd9Sstevel@tonic-gate 			version,
2897c478bd9Sstevel@tonic-gate 			languageLocale});
2907c478bd9Sstevel@tonic-gate 	}
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	// Deregister in all scopes.
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	Advertiser serviceAgent =
2957c478bd9Sstevel@tonic-gate 	    ServiceLocationManager.getAdvertiser(languageLocale);
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	if (serviceAgent == null) {
2987c478bd9Sstevel@tonic-gate 	    throw
2997c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
3007c478bd9Sstevel@tonic-gate 				ServiceLocationException.NOT_IMPLEMENTED,
3017c478bd9Sstevel@tonic-gate 				"no_advertiser",
3027c478bd9Sstevel@tonic-gate 				new Object[0]);
3037c478bd9Sstevel@tonic-gate 	}
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	// Deregister the service URL.
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	serviceAgent.deregister(turl);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate     }
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate     /**
3147c478bd9Sstevel@tonic-gate      * Find the service URL for the service.
3157c478bd9Sstevel@tonic-gate      *
3167c478bd9Sstevel@tonic-gate      * @param serviceType		Name of service.
3177c478bd9Sstevel@tonic-gate      * @param <i>languageLocale</i> Language locale of template.
3187c478bd9Sstevel@tonic-gate      * @param <i>version</i> Version of the template, null for latest.
3197c478bd9Sstevel@tonic-gate      * @return ServiceURL for the service template. If the service doesn't
3207c478bd9Sstevel@tonic-gate      *		exist, returns null.
3217c478bd9Sstevel@tonic-gate      * @exception ServiceLocationException Error code is
3227c478bd9Sstevel@tonic-gate      *				    SYSTEM_ERROR
3237c478bd9Sstevel@tonic-gate      *					   if the scope vector is null or
3247c478bd9Sstevel@tonic-gate      *					   empty or if more than one
3257c478bd9Sstevel@tonic-gate      *					   template URL is returned.
3267c478bd9Sstevel@tonic-gate      * @exception IllegalArgumentException Thrown if any parameters are null.
3277c478bd9Sstevel@tonic-gate      *
3287c478bd9Sstevel@tonic-gate      */
3297c478bd9Sstevel@tonic-gate 
findTemplateURL(ServiceType serviceType, Locale languageLocale, String version)3307c478bd9Sstevel@tonic-gate     public String findTemplateURL(ServiceType serviceType,
3317c478bd9Sstevel@tonic-gate 				  Locale languageLocale,
3327c478bd9Sstevel@tonic-gate 				  String version)
3337c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	// Check the parameter.
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	Assert.nonNullParameter(serviceType, "serviceType");
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	Assert.nonNullParameter(languageLocale, "languageLocale");
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	ServiceURL turl = findVersionedURL(serviceType,
3427c478bd9Sstevel@tonic-gate 					   languageLocale,
3437c478bd9Sstevel@tonic-gate 					   version);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	// If nothing returned, then simply return.
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	if (turl == null) {
3487c478bd9Sstevel@tonic-gate 	    return null;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	// Form the document URL.
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	ServiceType type = turl.getServiceType();
3557c478bd9Sstevel@tonic-gate 	String url = turl.toString();
3567c478bd9Sstevel@tonic-gate 	String abstractType = type.getAbstractTypeName();
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	if (!abstractType.equals(TEMPLATE_SERVICE_TYPE)) {
3597c478bd9Sstevel@tonic-gate 	    throw
3607c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
3617c478bd9Sstevel@tonic-gate 				ServiceLocationException.PARSE_ERROR,
3627c478bd9Sstevel@tonic-gate 				"template_url_malformed",
3637c478bd9Sstevel@tonic-gate 				new Object[] {turl});
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	}
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	// Parse off the URL path.
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	int idx = url.indexOf(";"+SERVICE_ATTR_ID+"=");
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	if (idx == -1) {
3727c478bd9Sstevel@tonic-gate 	    throw
3737c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
3747c478bd9Sstevel@tonic-gate 				ServiceLocationException.PARSE_ERROR,
3757c478bd9Sstevel@tonic-gate 				"template_url_malformed",
3767c478bd9Sstevel@tonic-gate 				new Object[] {turl});
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	}
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	int jdx = TEMPLATE_SERVICE_TYPE.length() + 1; // don't forget :!!!
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	// Return the document URL.
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	return url.substring(jdx, idx);
3857c478bd9Sstevel@tonic-gate     }
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate     // Return a URL given a version and language locale.
3887c478bd9Sstevel@tonic-gate 
findVersionedURL(ServiceType serviceType, Locale languageLocale, String version)3897c478bd9Sstevel@tonic-gate     private ServiceURL findVersionedURL(ServiceType serviceType,
3907c478bd9Sstevel@tonic-gate 					Locale languageLocale,
3917c478bd9Sstevel@tonic-gate 					String version)
3927c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	// Templates should be registered in all scopes. Look for them
3957c478bd9Sstevel@tonic-gate 	//  in all.
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	Vector scopes = ServiceLocationManager.findScopes();
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	// Set up query.
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	ServiceLocationEnumeration results = null;
4027c478bd9Sstevel@tonic-gate 	String query = "(" + SERVICE_ATTR_ID + "=" + serviceType + ")";
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	if (version != null) {
4057c478bd9Sstevel@tonic-gate 	    query = query + "(" + VERSION_ATTR_ID + "=" + version + ")";
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	}
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	query = "(&" + query + ")";
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	// Get user agent for query.
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	Locator userAgent =
4147c478bd9Sstevel@tonic-gate 	    ServiceLocationManager.getLocator(languageLocale);
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	if (userAgent == null) {
4177c478bd9Sstevel@tonic-gate 	    throw
4187c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
4197c478bd9Sstevel@tonic-gate 				ServiceLocationException.NOT_IMPLEMENTED,
4207c478bd9Sstevel@tonic-gate 				"no_locator",
4217c478bd9Sstevel@tonic-gate 				new Object[0]);
4227c478bd9Sstevel@tonic-gate 	}
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	try {
4257c478bd9Sstevel@tonic-gate 	    ServiceType type = new ServiceType(TEMPLATE_SERVICE_TYPE);
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	    results =
428*55fea89dSDan Cross 		userAgent.findServices(type,
429*55fea89dSDan Cross 				       scopes,
4307c478bd9Sstevel@tonic-gate 				       query);
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	    // If language not supported, it just means none there.
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	    if (ex.getErrorCode() !=
4377c478bd9Sstevel@tonic-gate 		ServiceLocationException.LANGUAGE_NOT_SUPPORTED) {
4387c478bd9Sstevel@tonic-gate 		throw ex;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	    }
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	// If nothing came back, then return null.
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	if (!results.hasMoreElements()) {
4477c478bd9Sstevel@tonic-gate 	    return null;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	}
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	ServiceURL turl = null;
4537c478bd9Sstevel@tonic-gate 	float highest = (float)-1.0;
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	// If there's more than one service of this type registered, then
4567c478bd9Sstevel@tonic-gate 	//  take highest version if version number was null.
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	while (results.hasMoreElements()) {
4597c478bd9Sstevel@tonic-gate 	    ServiceURL surl = (ServiceURL)results.nextElement();
4607c478bd9Sstevel@tonic-gate 	    String urlPath = surl.getURLPath();
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	    if (version == null) {
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		// Get the version attribute from the URL.
465*55fea89dSDan Cross 
4667c478bd9Sstevel@tonic-gate 		String token = ";"+VERSION_ATTR_ID+"=";
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 		int idx = urlPath.indexOf(token);
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 		if (idx == -1) { // ignore, there may be more...
4717c478bd9Sstevel@tonic-gate 		    continue;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 		urlPath =
4767c478bd9Sstevel@tonic-gate 		    urlPath.substring(idx+token.length(), urlPath.length());
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 		idx = urlPath.indexOf(";");
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 		if (idx == -1) { // ignore, there may be more...
4817c478bd9Sstevel@tonic-gate 		    continue;
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 		}
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 		String temversion = urlPath.substring(0, idx);
4867c478bd9Sstevel@tonic-gate 		float current = (float)0.0;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 		// Convert to float.
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 		try {
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 		    current = Float.valueOf(temversion).floatValue();
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 		} catch (NumberFormatException ex) {
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 		    continue;  // ignore, there may be more...
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 		}
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 		// Identify if this is the highest version number so far.
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 		if (current > highest) {
5037c478bd9Sstevel@tonic-gate 		    turl = surl;
5047c478bd9Sstevel@tonic-gate 		}
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	    } else {
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 		// If we found more than one, may be a problem.
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 		if (turl != null) {
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 		    throw
5137c478bd9Sstevel@tonic-gate 			new ServiceLocationException(
5147c478bd9Sstevel@tonic-gate 				ServiceLocationException.INTERNAL_SYSTEM_ERROR,
5157c478bd9Sstevel@tonic-gate 				"template_multiple",
5167c478bd9Sstevel@tonic-gate 				new Object[] {
5177c478bd9Sstevel@tonic-gate 			    serviceType,
5187c478bd9Sstevel@tonic-gate 				version,
5197c478bd9Sstevel@tonic-gate 				languageLocale});
5207c478bd9Sstevel@tonic-gate 		}
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 		turl = surl;
5237c478bd9Sstevel@tonic-gate 	    }
5247c478bd9Sstevel@tonic-gate 	}
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	return turl;
5277c478bd9Sstevel@tonic-gate     }
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate     /**
5307c478bd9Sstevel@tonic-gate      * Create an attribute verifier for the template document URL.
5317c478bd9Sstevel@tonic-gate      *
5327c478bd9Sstevel@tonic-gate      * @param documentURL A URL for the template document URL.
5337c478bd9Sstevel@tonic-gate      * @return An attribute verifier for the service
5347c478bd9Sstevel@tonic-gate      * @exception ServiceLocationException Throws
5357c478bd9Sstevel@tonic-gate      *					  PARSE_ERROR
5367c478bd9Sstevel@tonic-gate      *					  if any syntax errors
5377c478bd9Sstevel@tonic-gate      *					  are encountered during parsing
5387c478bd9Sstevel@tonic-gate      *					  of service's template definition.
5397c478bd9Sstevel@tonic-gate      *					  Throws
5407c478bd9Sstevel@tonic-gate      *					SYSTEM_ERROR
5417c478bd9Sstevel@tonic-gate      *					  if URL parsing error occurs.
5427c478bd9Sstevel@tonic-gate      *					  Throws ServiceLocationException
5437c478bd9Sstevel@tonic-gate      *					  if any other errors occur.
5447c478bd9Sstevel@tonic-gate      * @exception IllegalArgumentException Thrown if any parameters are null.
5457c478bd9Sstevel@tonic-gate      *
5467c478bd9Sstevel@tonic-gate      */
5477c478bd9Sstevel@tonic-gate 
attributeVerifier( String documentURL)5487c478bd9Sstevel@tonic-gate     public ServiceLocationAttributeVerifier attributeVerifier(
5497c478bd9Sstevel@tonic-gate 							String documentURL)
5507c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	// Check the parameter.
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	Assert.nonNullParameter(documentURL, "documentURL");
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	// Create a URL attribute parser to parse the document.
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	return new URLAttributeVerifier(documentURL);
5597c478bd9Sstevel@tonic-gate     }
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate }
562