xref: /onnv-gate/usr/src/lib/libslp/javalib/com/sun/slp/UARequester.java (revision 7298:b69e27387f74)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7298SMark.J.Nelson@Sun.COM  * Common Development and Distribution License (the "License").
6*7298SMark.J.Nelson@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
220Sstevel@tonic-gate  * Copyright (c) 1999 by Sun Microsystems, Inc.
230Sstevel@tonic-gate  * All rights reserved.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate //  UARequester.java: Requester operations for UA.
280Sstevel@tonic-gate //  Author:           James Kempf
290Sstevel@tonic-gate //  Created On:       Thu Jan  8 15:17:35 1998
300Sstevel@tonic-gate //  Last Modified By: James Kempf
310Sstevel@tonic-gate //  Last Modified On: Mon Feb 22 13:47:06 1999
320Sstevel@tonic-gate //  Update Count:     78
330Sstevel@tonic-gate //
340Sstevel@tonic-gate 
350Sstevel@tonic-gate package com.sun.slp;
360Sstevel@tonic-gate 
370Sstevel@tonic-gate import java.util.*;
380Sstevel@tonic-gate 
390Sstevel@tonic-gate /**
400Sstevel@tonic-gate  * The URequester class implements the Locator interface.
410Sstevel@tonic-gate  * It handles the request for the API.  If any of the parameters
420Sstevel@tonic-gate  * are missing, they will be supplied with a default value if
430Sstevel@tonic-gate  * possible.  If a cached value may be supplied, it will be.
440Sstevel@tonic-gate  * If no DA is present, and convergence is used to gather
450Sstevel@tonic-gate  * results, these will be merged into one result.
460Sstevel@tonic-gate  *
470Sstevel@tonic-gate  * @author Erik Guttman, James Kempf
480Sstevel@tonic-gate  */
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 
510Sstevel@tonic-gate class UARequester extends Object implements Locator {
520Sstevel@tonic-gate 
530Sstevel@tonic-gate     private static SLPConfig config = null;
540Sstevel@tonic-gate     private static DATable dat = null;
550Sstevel@tonic-gate 
560Sstevel@tonic-gate     private Locale locale;
570Sstevel@tonic-gate 
UARequester(Locale nlocale)580Sstevel@tonic-gate     UARequester(Locale nlocale) {
590Sstevel@tonic-gate 
600Sstevel@tonic-gate 	Assert.nonNullParameter(nlocale, "locale");
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	if (config == null) {
630Sstevel@tonic-gate 	    config = SLPConfig.getSLPConfig();
640Sstevel@tonic-gate 	}
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	if (dat == null) {
670Sstevel@tonic-gate 	    dat = DATable.getDATable();
680Sstevel@tonic-gate 	}
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	locale = nlocale;
710Sstevel@tonic-gate     }
720Sstevel@tonic-gate 
730Sstevel@tonic-gate     /**
740Sstevel@tonic-gate      * Return the Locator's locale object. All requests are made in
750Sstevel@tonic-gate      * this locale.
760Sstevel@tonic-gate      *
770Sstevel@tonic-gate      * @return The Locale object.
780Sstevel@tonic-gate      */
790Sstevel@tonic-gate 
getLocale()800Sstevel@tonic-gate     public Locale getLocale() {
810Sstevel@tonic-gate 	return locale;
820Sstevel@tonic-gate 
830Sstevel@tonic-gate     }
840Sstevel@tonic-gate 
850Sstevel@tonic-gate     /**
860Sstevel@tonic-gate      * Return an enumeration of known service types for this scope and naming
870Sstevel@tonic-gate      * authority.  Unless a proprietary or experimental service is being
880Sstevel@tonic-gate      * discovered, the namingAuthority parameter should be the empty
890Sstevel@tonic-gate      * string, "".
900Sstevel@tonic-gate      *
910Sstevel@tonic-gate      * @param NA	The naming authority, "" for default,
920Sstevel@tonic-gate      *           '*' for any naming authority.
930Sstevel@tonic-gate      * @param scopes	The SLP scopes of the types.
940Sstevel@tonic-gate      * @return ServiceLocationEnumeration of ServiceType objects for
950Sstevel@tonic-gate      *	      the service type names.
960Sstevel@tonic-gate      * @exception IllegalArgumentException If any of the parameters are
970Sstevel@tonic-gate      *					  null or syntactically incorrect.
980Sstevel@tonic-gate      * @exception ServiceLocationException An exception is thrown if the
990Sstevel@tonic-gate      *					  operation fails.
1000Sstevel@tonic-gate      */
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate     public synchronized ServiceLocationEnumeration
findServiceTypes(String NA, Vector scopes)1030Sstevel@tonic-gate 	findServiceTypes(String NA, Vector scopes)
1040Sstevel@tonic-gate 	throws ServiceLocationException {
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	Assert.nonNullParameter(NA, " NA");
1070Sstevel@tonic-gate 	Assert.nonNullParameter(scopes, "scopes");
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	// Formulate and send off messages.
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	Vector msgs = createMessages(SrvLocHeader.SrvTypeRqst,
1120Sstevel@tonic-gate 				     NA,
1130Sstevel@tonic-gate 				     null,
1140Sstevel@tonic-gate 				     null,
1150Sstevel@tonic-gate 				     scopes);
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	// Collate results.
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	Vector ret = new Vector();
1200Sstevel@tonic-gate 	int i, n = msgs.size();
1210Sstevel@tonic-gate 	int max = config.getMaximumResults();
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
1240Sstevel@tonic-gate 	    CSrvTypeMsg msg = (CSrvTypeMsg)msgs.elementAt(i);
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	    // Check for errors.
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	    checkForError(msg, msgs);
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	    Vector serviceTypes = msg.serviceTypes;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	    addUnique(serviceTypes, ret, max);
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	}
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	// Return.
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	return new ServiceLocationEnumerator(ret);
1390Sstevel@tonic-gate     }
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate     /**
1420Sstevel@tonic-gate      * Return an enumeration of ServiceURL objects for services matching
1430Sstevel@tonic-gate      * the query. The services are returned from the locale of the
1440Sstevel@tonic-gate      * locator.
1450Sstevel@tonic-gate      *
1460Sstevel@tonic-gate      * @param type	The type of the service (e.g. printer, etc.).
1470Sstevel@tonic-gate      * @param scopes	The SLP scopes of the service types.
1480Sstevel@tonic-gate      * @param query		A string with the SLP query.
1490Sstevel@tonic-gate      * @return ServiceLocationEnumeration of ServiceURL objects for
1500Sstevel@tonic-gate      *	      services matching the
1510Sstevel@tonic-gate      *         attributes.
1520Sstevel@tonic-gate      * @exception ServiceLocationException An exception is returned if the
1530Sstevel@tonic-gate      *					  operation fails.
1540Sstevel@tonic-gate      * @see ServiceURL
1550Sstevel@tonic-gate      */
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate     public synchronized ServiceLocationEnumeration
findServices(ServiceType type, Vector scopes, String query)1580Sstevel@tonic-gate 	findServices(ServiceType type, Vector scopes, String query)
1590Sstevel@tonic-gate 	throws ServiceLocationException {
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	Assert.nonNullParameter(type, "type");
1620Sstevel@tonic-gate 	Assert.nonNullParameter(scopes, "scopes");
1630Sstevel@tonic-gate 	Assert.nonNullParameter(query, "query");
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	// Formulate and send off messages.
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	Vector msgs = createMessages(SrvLocHeader.SrvReq,
1680Sstevel@tonic-gate 				     type,
1690Sstevel@tonic-gate 				     query,
1700Sstevel@tonic-gate 				     type,
1710Sstevel@tonic-gate 				     scopes);
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	// Collate results.
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	Vector ret = new Vector();
1760Sstevel@tonic-gate 	int i, n = msgs.size();
1770Sstevel@tonic-gate 	int max = config.getMaximumResults();
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
1800Sstevel@tonic-gate 	    SrvLocMsg msg = (SrvLocMsg)msgs.elementAt(i);
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	    // Check for errors.
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	    checkForError(msg, msgs);
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 	    // Be sure to account for DAAdverts and SAAdverts.
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	    Vector serviceURLs = null;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	    if (msg instanceof CSrvMsg) {
1910Sstevel@tonic-gate 		serviceURLs = ((CSrvMsg)msg).serviceURLs;
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	    } else if (msg instanceof CSAAdvert) {
1940Sstevel@tonic-gate 		serviceURLs = new Vector();
1950Sstevel@tonic-gate 		serviceURLs.addElement(((CSAAdvert)msg).URL);
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	    } else if (msg instanceof CDAAdvert) {
1980Sstevel@tonic-gate 		serviceURLs = new Vector();
1990Sstevel@tonic-gate 		serviceURLs.addElement(((CDAAdvert)msg).URL);
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	    }
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	    addUnique(serviceURLs, ret, max);
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	}
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	// Return.
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	return new ServiceLocationEnumerator(ret);
2100Sstevel@tonic-gate     }
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate     /**
2130Sstevel@tonic-gate      * Return the attributes for the service URL, using the locale
2140Sstevel@tonic-gate      * of the locator.
2150Sstevel@tonic-gate      *
2160Sstevel@tonic-gate      * @param URL	The service URL.
2170Sstevel@tonic-gate      * @param scopes	The SLP scopes of the service.
2180Sstevel@tonic-gate      * @param attributeIds A vector of strings identifying the desired
2190Sstevel@tonic-gate      *			  attributes. A null value means return all
2200Sstevel@tonic-gate      *			  the attributes.  <b>Partial id strings</b> may
2210Sstevel@tonic-gate      *                     begin with '*' to match all ids which end with
2220Sstevel@tonic-gate      *                     the given suffix, or end with '*' to match all
2230Sstevel@tonic-gate      *                     ids which begin with a given prefix, or begin
2240Sstevel@tonic-gate      *                     and end with '*' to do substring matching for
2250Sstevel@tonic-gate      *                     ids containing the given partial id.
2260Sstevel@tonic-gate      * @return ServiceLocationEnumeration of ServiceLocationAttribute
2270Sstevel@tonic-gate      *         objects matching the ids.
2280Sstevel@tonic-gate      * @exception ServiceLocationException An exception is returned if the
2290Sstevel@tonic-gate      *					  operation fails.
2300Sstevel@tonic-gate      * @exception IllegalArgumentException If any of the parameters are
2310Sstevel@tonic-gate      *					  null or syntactically incorrect.
2320Sstevel@tonic-gate      * @see ServiceLocationAttribute
2330Sstevel@tonic-gate      *
2340Sstevel@tonic-gate      */
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate     public synchronized ServiceLocationEnumeration
findAttributes(ServiceURL URL, Vector scopes, Vector attributeIds)2370Sstevel@tonic-gate 	findAttributes(ServiceURL URL, Vector scopes, Vector attributeIds)
2380Sstevel@tonic-gate 	throws ServiceLocationException {
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	Assert.nonNullParameter(URL, "URL");
2410Sstevel@tonic-gate 	Assert.nonNullParameter(scopes, "scopes");
2420Sstevel@tonic-gate 	Assert.nonNullParameter(attributeIds, "attributeIds");
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	Vector msgs = createMessages(SrvLocHeader.AttrRqst,
2450Sstevel@tonic-gate 				     URL,
2460Sstevel@tonic-gate 				     attributeIds,
2470Sstevel@tonic-gate 				     URL.getServiceType(),
2480Sstevel@tonic-gate 				     scopes);
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	// Check results.
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	Vector ret = new Vector();
2530Sstevel@tonic-gate 	int i, n = msgs.size();
2540Sstevel@tonic-gate 	int max = config.getMaximumResults();
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	// We only take the first message that came back and is OK.
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
2590Sstevel@tonic-gate 	    SrvLocMsg msg = (SrvLocMsg)msgs.elementAt(i);
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	    // Check for errors.
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	    checkForError(msg, msgs);
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	    // Select out attribute list.
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	    if (msg instanceof CAttrMsg) {
2680Sstevel@tonic-gate 		ret = ((CAttrMsg)msg).attrList;
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	    } else if (msg instanceof CSAAdvert) {
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 		// Need to check that URL matches.
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 		CSAAdvert smsg = (CSAAdvert)msg;
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 		if (!URL.equals(smsg.URL)) {
2770Sstevel@tonic-gate 		    continue;
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 		}
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 		ret = smsg.attrs;
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	    } else if (msg instanceof CDAAdvert) {
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 		// Need to check that URL matches.
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 		CDAAdvert smsg = (CDAAdvert)msg;
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 		if (!URL.equals(smsg.URL)) {
2900Sstevel@tonic-gate 		    continue;
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 		}
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 		ret = smsg.attrs;
2950Sstevel@tonic-gate 	    }
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 	    // Truncate, if return is larger than maximum.
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	    if (ret.size() > max) {
3000Sstevel@tonic-gate 		ret.setSize(max);
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	    }
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	    // Break out, we only need one.
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	    break;
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	}
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	// Return.
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	return new ServiceLocationEnumerator(ret);
3130Sstevel@tonic-gate     }
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate     /**
3160Sstevel@tonic-gate      * Return all attributes for all service URL's having this
3170Sstevel@tonic-gate      * service type in the locale of the Locator.
3180Sstevel@tonic-gate      *
3190Sstevel@tonic-gate      * @param type The service type.
3200Sstevel@tonic-gate      * @param scopes	The SLP scopes of the service type.
3210Sstevel@tonic-gate      * @param attributeIds A vector of strings identifying the desired
3220Sstevel@tonic-gate      *			  attributes. A null value means return all
3230Sstevel@tonic-gate      *			  the attributes.  <b>Partial id strings</b> may
3240Sstevel@tonic-gate      *                     begin with '*' to match all ids which end with
3250Sstevel@tonic-gate      *                     the given suffix, or end with '*' to match all
3260Sstevel@tonic-gate      *                     ids which begin with a given prefix, or begin
3270Sstevel@tonic-gate      *                     and end with '*' to do substring matching for
3280Sstevel@tonic-gate      *                     ids containing the given partial id.
3290Sstevel@tonic-gate      * @return ServiceLocationEnumeration of ServiceLocationAttribute
3300Sstevel@tonic-gate      *         objects matching the ids.
3310Sstevel@tonic-gate      * @exception ServiceLocationException An exception is returned if the
3320Sstevel@tonic-gate      *					  operation fails.
3330Sstevel@tonic-gate      * @exception IllegalArgumentException If any of the parameters are
3340Sstevel@tonic-gate      *					  null or syntactically incorrect.
3350Sstevel@tonic-gate      * @see ServiceLocationAttribute
3360Sstevel@tonic-gate      *
3370Sstevel@tonic-gate      */
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate     public synchronized ServiceLocationEnumeration
findAttributes(ServiceType type, Vector scopes, Vector attributeIds)3400Sstevel@tonic-gate 	findAttributes(ServiceType type, Vector scopes, Vector attributeIds)
3410Sstevel@tonic-gate 	throws ServiceLocationException {
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 	Assert.nonNullParameter(type, "URL");
3440Sstevel@tonic-gate 	Assert.nonNullParameter(scopes, "scopes");
3450Sstevel@tonic-gate 	Assert.nonNullParameter(attributeIds, "attributeIds");
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	// Formulate and send off messages.
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	Vector msgs = createMessages(SrvLocHeader.AttrRqst,
3500Sstevel@tonic-gate 				     type,
3510Sstevel@tonic-gate 				     attributeIds,
3520Sstevel@tonic-gate 				     type,
3530Sstevel@tonic-gate 				     scopes);
3540Sstevel@tonic-gate 	// Collate results.
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 	Vector ret = new Vector();
3570Sstevel@tonic-gate 	int i, n = msgs.size();
3580Sstevel@tonic-gate 	int max = config.getMaximumResults();
3590Sstevel@tonic-gate 	Hashtable ht = new Hashtable();
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	for (i = 0; i < n && ret.size() < max; i++) {
3620Sstevel@tonic-gate 	    SrvLocMsg msg = (SrvLocMsg)msgs.elementAt(i);
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 	    // Check for errors.
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 	    checkForError(msg, msgs);
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	    Vector attrList = null;
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	    // Get the instance variable.
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	    if (msg instanceof CAttrMsg) {
3730Sstevel@tonic-gate 		attrList = ((CAttrMsg)msg).attrList;
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	    } else if (msg instanceof CSAAdvert) {
3760Sstevel@tonic-gate 		attrList = ((CSAAdvert)msg).attrs;
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	    } else if (msg instanceof CDAAdvert) {
3790Sstevel@tonic-gate 		attrList = ((CDAAdvert)msg).attrs;
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 	    }
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	    // Merge any duplicates.
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	    int j, m = attrList.size();
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	    for (j = 0; j < m; j++) {
3880Sstevel@tonic-gate 		ServiceLocationAttribute attr =
3890Sstevel@tonic-gate 		    (ServiceLocationAttribute)attrList.elementAt(j);
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 		ServiceLocationAttribute.mergeDuplicateAttributes(attr,
3920Sstevel@tonic-gate 								  ht,
3930Sstevel@tonic-gate 								  ret,
3940Sstevel@tonic-gate 								  true);
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 		if (ret.size() >= max) {
3970Sstevel@tonic-gate 		    break;
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 		}
4000Sstevel@tonic-gate 	    }
4010Sstevel@tonic-gate 	}
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	// Return.
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	return new ServiceLocationEnumerator(ret);
4060Sstevel@tonic-gate     }
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate     // Execute the message request, returning messages.
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate     private Vector
createMessages(int msgType, Object t1, Object t2, ServiceType type, Vector scopes)4110Sstevel@tonic-gate 	createMessages(int msgType,
4120Sstevel@tonic-gate 		       Object t1,
4130Sstevel@tonic-gate 		       Object t2,
4140Sstevel@tonic-gate 		       ServiceType type,
4150Sstevel@tonic-gate 		       Vector scopes)
4160Sstevel@tonic-gate 	throws ServiceLocationException {
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	// Validate, lower case scopes.
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	DATable.validateScopes(scopes, locale);
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	SrvLocMsg multiMsg = null;
4230Sstevel@tonic-gate 	SrvLocMsg uniMsg = null;
4240Sstevel@tonic-gate 	Vector daAddresses = null;
4250Sstevel@tonic-gate 	Vector multiCastScopes = null;
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 	// Get the hashtable of unicast DA addresses and multicast scopes.
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	Hashtable daRecords = dat.findDAScopes(scopes);
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	// Get multicast scopes and DA addresses.
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	multiCastScopes =
4340Sstevel@tonic-gate 	    (Vector)daRecords.get(DATable.MULTICAST_KEY);
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	daAddresses =
4370Sstevel@tonic-gate 	    (Vector)daRecords.get(DATable.UNICAST_KEY);
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	// Special case for service request and attribute request
4400Sstevel@tonic-gate 	//  if the user is looking for a special SLP type.
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	if (((msgType == SrvLocHeader.SrvReq) ||
4430Sstevel@tonic-gate 	    (msgType == SrvLocHeader.AttrRqst)) &&
4440Sstevel@tonic-gate 	    (type.equals(Defaults.DA_SERVICE_TYPE) ||
4450Sstevel@tonic-gate 	    type.equals(Defaults.SA_SERVICE_TYPE))) {
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate 	    multiCastScopes = scopes;
4480Sstevel@tonic-gate 	    daAddresses = null;
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	    // Get query. If an attribute request, then the user
4510Sstevel@tonic-gate 	    //  needs to sort out the attributes.
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	    String query = "";
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 	    if (msgType == SrvLocHeader.SrvReq) {
4560Sstevel@tonic-gate 		query = (String)t2;
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	    }
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	    multiMsg = new CSrvMsg(locale, type, multiCastScopes, query);
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	} else {
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate 	    // Handle a regular message.
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 	    // Multicast scopes are all scopes not supported by any DA.
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 	    if (multiCastScopes != null) {
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 		switch (msgType) {
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 		case SrvLocHeader.SrvTypeRqst:
4730Sstevel@tonic-gate 		    multiMsg =
4740Sstevel@tonic-gate 			new CSrvTypeMsg(locale, (String)t1, multiCastScopes);
4750Sstevel@tonic-gate 		    break;
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 		case SrvLocHeader.SrvReq:
4780Sstevel@tonic-gate 		    multiMsg =
4790Sstevel@tonic-gate 			new CSrvMsg(locale, type, multiCastScopes, (String)t2);
4800Sstevel@tonic-gate 		    break;
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 		case SrvLocHeader.AttrRqst:
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 		    if (t1 instanceof ServiceURL) {
4850Sstevel@tonic-gate 			multiMsg =
4860Sstevel@tonic-gate 			    new CAttrMsg(locale,
4870Sstevel@tonic-gate 					 (ServiceURL)t1,
4880Sstevel@tonic-gate 					 multiCastScopes,
4890Sstevel@tonic-gate 					 (Vector)t2);
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 		    } else {
4920Sstevel@tonic-gate 			multiMsg =
4930Sstevel@tonic-gate 			    new CAttrMsg(locale,
4940Sstevel@tonic-gate 					 type,
4950Sstevel@tonic-gate 					 multiCastScopes,
4960Sstevel@tonic-gate 					 (Vector)t2);
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate 		    }
4990Sstevel@tonic-gate 		}
5000Sstevel@tonic-gate 	    }
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	    // Unicast only requires a single message because the DAs will
5030Sstevel@tonic-gate 	    //  ignore any scopes they do not support, just as long as
5040Sstevel@tonic-gate 	    //  they support one of them.
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	    if (daAddresses != null) {
5070Sstevel@tonic-gate 		switch (msgType) {
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 		case SrvLocHeader.SrvTypeRqst:
5100Sstevel@tonic-gate 		    uniMsg =
5110Sstevel@tonic-gate 			new CSrvTypeMsg(locale, (String)t1, scopes);
5120Sstevel@tonic-gate 		    break;
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 		case SrvLocHeader.SrvReq:
5150Sstevel@tonic-gate 		    uniMsg =
5160Sstevel@tonic-gate 			new CSrvMsg(locale, type, scopes, (String)t2);
5170Sstevel@tonic-gate 		    break;
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 		case SrvLocHeader.AttrRqst:
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 		    if (t1 instanceof ServiceURL) {
5220Sstevel@tonic-gate 			uniMsg =
5230Sstevel@tonic-gate 			    new CAttrMsg(locale,
5240Sstevel@tonic-gate 					 (ServiceURL)t1,
5250Sstevel@tonic-gate 					 scopes,
5260Sstevel@tonic-gate 					 (Vector)t2);
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 		    } else {
5290Sstevel@tonic-gate 			uniMsg =
5300Sstevel@tonic-gate 			    new CAttrMsg(locale,
5310Sstevel@tonic-gate 					 type,
5320Sstevel@tonic-gate 					 scopes,
5330Sstevel@tonic-gate 					 (Vector)t2);
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 		    }
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 		}
5380Sstevel@tonic-gate 	    }
5390Sstevel@tonic-gate 	}
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	// Send off messages, return results.
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 	return Transact.transactUA(daAddresses,
5440Sstevel@tonic-gate 				   uniMsg,
5450Sstevel@tonic-gate 				   multiMsg,
5460Sstevel@tonic-gate 				   config.getMulticastAddress());
5470Sstevel@tonic-gate     }
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate     // Check message for error code.
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate     private static void
checkForError(SrvLocMsg msg, Vector v)5520Sstevel@tonic-gate 	checkForError(SrvLocMsg msg, Vector v)
5530Sstevel@tonic-gate 	throws ServiceLocationException {
5540Sstevel@tonic-gate 	int err = msg.getErrorCode();
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	if (err != ServiceLocationException.OK) {
5570Sstevel@tonic-gate 	    if (v.size() == 1) {
5580Sstevel@tonic-gate 		config.writeLog("single_exception",
5590Sstevel@tonic-gate 				new Object[] {
5600Sstevel@tonic-gate 		    new Integer(err)});
5610Sstevel@tonic-gate 		throw
5620Sstevel@tonic-gate 		    new ServiceLocationException((short)err,
5630Sstevel@tonic-gate 						 "remote_error",
5640Sstevel@tonic-gate 						 new Object[] {});
5650Sstevel@tonic-gate 	    } else {
5660Sstevel@tonic-gate 		config.writeLog("multiple_exception",
5670Sstevel@tonic-gate 				new Object[] {
5680Sstevel@tonic-gate 		    new Integer(err)});
5690Sstevel@tonic-gate 	    }
5700Sstevel@tonic-gate 	}
5710Sstevel@tonic-gate     }
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate     // Process the incoming vector, adding any unique returns.
5740Sstevel@tonic-gate 
addUnique(Vector incoming, Vector returns, int max)5750Sstevel@tonic-gate     private static void addUnique(Vector incoming, Vector returns, int max) {
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	int i, n = incoming.size();
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
5800Sstevel@tonic-gate 	    Object o = incoming.elementAt(i);
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	    if (!returns.contains(o) && returns.size() < max) {
5830Sstevel@tonic-gate 		returns.addElement(o);
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	    }
5860Sstevel@tonic-gate 	}
5870Sstevel@tonic-gate     }
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate }
590