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) 2001 by Sun Microsystems, Inc.
237c478bd9Sstevel@tonic-gate  * All rights reserved.
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate //  SunServerDATable.java: Server DA Table for Sun's client/SA server SLP.
287c478bd9Sstevel@tonic-gate //  Author:           James Kempf
297c478bd9Sstevel@tonic-gate //  Created On:       Wed May 20 09:58:46 1998
307c478bd9Sstevel@tonic-gate //  Last Modified By: James Kempf
317c478bd9Sstevel@tonic-gate //  Last Modified On: Mon Mar  8 14:30:29 1999
327c478bd9Sstevel@tonic-gate //  Update Count:     79
337c478bd9Sstevel@tonic-gate //
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate package com.sun.slp;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate import java.util.*;
387c478bd9Sstevel@tonic-gate import java.net.*;
397c478bd9Sstevel@tonic-gate import java.io.*;
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /**
427c478bd9Sstevel@tonic-gate  * SunServerDATable is a subclass class that provides the
437c478bd9Sstevel@tonic-gate  * implementation for DA storage on Solaris. As described in
447c478bd9Sstevel@tonic-gate  * the header for SunDATable, DA information is stored in the server's
457c478bd9Sstevel@tonic-gate  * SA table as the service type "directory-agent.sun"  with a
467c478bd9Sstevel@tonic-gate  * attribute, scopes. The attribute contains a list of scopes supported
477c478bd9Sstevel@tonic-gate  * by the DA. The service: URL of the registration contains the
487c478bd9Sstevel@tonic-gate  * DA address as the host, followed by the list of scopes as an attribute
497c478bd9Sstevel@tonic-gate  * in the URL part. An example is:
507c478bd9Sstevel@tonic-gate  *
517c478bd9Sstevel@tonic-gate  *   service:directory-agent.sun:// 199.200.200.5/scopes=eng, corp, freeb
527c478bd9Sstevel@tonic-gate  *
537c478bd9Sstevel@tonic-gate  * The scopes of the registration are the scopes provided as the Sun-specific
547c478bd9Sstevel@tonic-gate  * system property "sun.net.slp.SAOnlyScopes". By convention, this is
557c478bd9Sstevel@tonic-gate  * initialized to be the local machine name, but it may also include other
567c478bd9Sstevel@tonic-gate  * names.
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  * @author James Kempf
597c478bd9Sstevel@tonic-gate  */
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate class SunServerDATable extends ServerDATable {
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate     // DA boot timestamp.
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate     static final private String TIMESTAMP_ID =
667c478bd9Sstevel@tonic-gate 	"424242SUN-TABLE-TIMESTAMP424242";
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate     // Address. Makes deletion easier.
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate     static final private String ADDRESS_ID = "424242SUN-TABLE-ADDRESS424242";
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate     private ServiceTable serviceTable = null;  // SA table for regs.
737c478bd9Sstevel@tonic-gate     private Vector saOnlyScopes = null;	       // Scopes for SA only.
747c478bd9Sstevel@tonic-gate 
SunServerDATable()757c478bd9Sstevel@tonic-gate     SunServerDATable() {
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	// Get the service table.
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	try {
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	    serviceTable = ServiceTable.getServiceTable();
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	}
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	// Get the vector of SA scopes.
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	saOnlyScopes = conf.getSAOnlyScopes();
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	Assert.slpassert(saOnlyScopes.size() > 0,
927c478bd9Sstevel@tonic-gate 		      "no_sa_scopes",
937c478bd9Sstevel@tonic-gate 		      new Object[0]);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate     }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate     /**
987c478bd9Sstevel@tonic-gate      * Record a new DA in the service table.
997c478bd9Sstevel@tonic-gate      *
1007c478bd9Sstevel@tonic-gate      * @param URL The DAAdvert URL.
1017c478bd9Sstevel@tonic-gate      * @param scopes The scopes.
1027c478bd9Sstevel@tonic-gate      * @param version DA version number.
1037c478bd9Sstevel@tonic-gate      * @param spis SPIs this DA can support
1047c478bd9Sstevel@tonic-gate      * @return The boot timestamp in the previous registration. Used
1057c478bd9Sstevel@tonic-gate      *         to determine if registration is necessary. If an error occurs,
1067c478bd9Sstevel@tonic-gate      *	       the returned value is negative. If the DA is new, the return
1077c478bd9Sstevel@tonic-gate      *         value is the maximum long value. This will cause all
1087c478bd9Sstevel@tonic-gate      *         registrations to be forwarded, because it is larger than any
1097c478bd9Sstevel@tonic-gate      *         current time.
1107c478bd9Sstevel@tonic-gate      */
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate     public synchronized long
recordNewDA(ServiceURL url, Vector scopes, long timestamp, int version, Vector attrs, String spis)1137c478bd9Sstevel@tonic-gate 	recordNewDA(ServiceURL url,
1147c478bd9Sstevel@tonic-gate 		    Vector scopes,
1157c478bd9Sstevel@tonic-gate 		    long timestamp,
1167c478bd9Sstevel@tonic-gate 		    int version,
1177c478bd9Sstevel@tonic-gate 		    Vector attrs,
1187c478bd9Sstevel@tonic-gate 		    String spis) {
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	String addr = url.getHost();
1217c478bd9Sstevel@tonic-gate 	long formerTimestamp = -1L;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	// We record all DAs regardless of whether we support them or not,
1247c478bd9Sstevel@tonic-gate 	//  because a UA client may be using the user selectable scoping
1257c478bd9Sstevel@tonic-gate 	//  model and therefore may want to see them.
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	Vector v = (Vector)scopes.clone();
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	// Add the Sun attributes.
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	ServiceLocationAttribute attr =
1327c478bd9Sstevel@tonic-gate 	    new ServiceLocationAttribute(SunDATable.SCOPES_ID, scopes);
1337c478bd9Sstevel@tonic-gate 	attrs.addElement(attr);
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	Vector vals = new Vector();
1367c478bd9Sstevel@tonic-gate 	vals.addElement(Long.toString(timestamp));
1377c478bd9Sstevel@tonic-gate 	attr =
1387c478bd9Sstevel@tonic-gate 	    new ServiceLocationAttribute(SunServerDATable.TIMESTAMP_ID, vals);
1397c478bd9Sstevel@tonic-gate 	attrs.addElement(attr);
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	vals = new Vector();
1427c478bd9Sstevel@tonic-gate 	vals.addElement(new Integer(version));
1437c478bd9Sstevel@tonic-gate 	attr = new ServiceLocationAttribute(SunDATable.VERSION_ID, vals);
1447c478bd9Sstevel@tonic-gate 	attrs.addElement(attr);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	vals = new Vector();
1477c478bd9Sstevel@tonic-gate 	vals.addElement(url.getHost());
1487c478bd9Sstevel@tonic-gate 	attr = new ServiceLocationAttribute(SunServerDATable.ADDRESS_ID, vals);
1497c478bd9Sstevel@tonic-gate 	attrs.addElement(attr);
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	// Form the URL for the DA.
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	ServiceURL adURL = formServiceTableDAURL(url, attrs);
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	// Reach *around* the service table for registration, because
1567c478bd9Sstevel@tonic-gate 	//  we don't need a message. The service table abstraction
1577c478bd9Sstevel@tonic-gate 	//  is basically for decoding message objects, and we already
1587c478bd9Sstevel@tonic-gate 	//  have things in the internal form needed by the service store.
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	ServiceStore store = serviceTable.store;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	try {
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	    // First, get the boot time stamp if there.
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	    Vector tags = new Vector();
1677c478bd9Sstevel@tonic-gate 	    tags.addElement(SunServerDATable.TIMESTAMP_ID);
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	    Hashtable attrRec =
1707c478bd9Sstevel@tonic-gate 		store.findAttributes(adURL,
1717c478bd9Sstevel@tonic-gate 				     saOnlyScopes,
1727c478bd9Sstevel@tonic-gate 				     tags,
1737c478bd9Sstevel@tonic-gate 				     Defaults.locale);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	    Vector formerAttrs =
1767c478bd9Sstevel@tonic-gate 		(Vector)attrRec.get(ServiceStore.FA_ATTRIBUTES);
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	    // If there, then get the old timestamp.
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	    if (formerAttrs != null && !(formerAttrs.size() <= 0)) {
181*55fea89dSDan Cross 
1827c478bd9Sstevel@tonic-gate 		// Get the timestamp into a long.
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 		attr = (ServiceLocationAttribute)formerAttrs.elementAt(0);
1857c478bd9Sstevel@tonic-gate 		vals = attr.getValues();
1867c478bd9Sstevel@tonic-gate 		String stamp = (String)vals.elementAt(0);
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 		try {
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 		    formerTimestamp = Long.parseLong(stamp.trim());
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 		} catch (NumberFormatException ex) {
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 		    Assert.slpassert(false,
1957c478bd9Sstevel@tonic-gate 				  "ssdat_number_format",
1967c478bd9Sstevel@tonic-gate 				  new Object[0]);
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 		}
1997c478bd9Sstevel@tonic-gate 	    }
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	    // Now register the URL.
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	    store.register(adURL,
2047c478bd9Sstevel@tonic-gate 			   attrs,
2057c478bd9Sstevel@tonic-gate 			   saOnlyScopes,
2067c478bd9Sstevel@tonic-gate 			   Defaults.locale,
2077c478bd9Sstevel@tonic-gate 			   null,
2087c478bd9Sstevel@tonic-gate 			   null);
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	    // Keep track of this DAs supported SPIs
2117c478bd9Sstevel@tonic-gate 	    LinkedList spiList =
2127c478bd9Sstevel@tonic-gate 		AuthBlock.commaSeparatedListToLinkedList(spis);
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	    // convert addr to an InetAddress for hashing
2157c478bd9Sstevel@tonic-gate 	    InetAddress inetAddr = null;
2167c478bd9Sstevel@tonic-gate 	    try {
2177c478bd9Sstevel@tonic-gate 		inetAddr = InetAddress.getByName(addr);
2187c478bd9Sstevel@tonic-gate 	    } catch (UnknownHostException e) {}
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	    // If we didn't get the InetAddress, this DA will never be used
2217c478bd9Sstevel@tonic-gate 	    // anyway
2227c478bd9Sstevel@tonic-gate 	    if (addr != null) {
2237c478bd9Sstevel@tonic-gate 		daSPIsHash.put(inetAddr, spiList);
2247c478bd9Sstevel@tonic-gate 	    }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
2277c478bd9Sstevel@tonic-gate 	    conf.writeLog("ssdat_register_error",
2287c478bd9Sstevel@tonic-gate 			  new Object[] {
2297c478bd9Sstevel@tonic-gate 		ex.getMessage(),
2307c478bd9Sstevel@tonic-gate 		    adURL,
2317c478bd9Sstevel@tonic-gate 		    saOnlyScopes});
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	return formerTimestamp;
2357c478bd9Sstevel@tonic-gate     }
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate     /**
2387c478bd9Sstevel@tonic-gate      * Remove a DA. The Sun-specific convention is used to deregister
2397c478bd9Sstevel@tonic-gate      * the URL.
2407c478bd9Sstevel@tonic-gate      *
2417c478bd9Sstevel@tonic-gate      * @param address The host address of the DA, from its service URL.
2427c478bd9Sstevel@tonic-gate      * @param scopes The scopes.
2437c478bd9Sstevel@tonic-gate      * @return True if removed, false if not.
2447c478bd9Sstevel@tonic-gate      */
2457c478bd9Sstevel@tonic-gate 
removeDA(InetAddress address, Vector scopes)2467c478bd9Sstevel@tonic-gate     public synchronized boolean removeDA(InetAddress address, Vector scopes) {
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	// Find URLs corresponding to this address.
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	String query = "(" + ADDRESS_ID + "=" + address.getHostAddress() + ")";
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	// Reach *around* the service table for dregistration, because
2537c478bd9Sstevel@tonic-gate 	//  we don't need a message. The service table abstraction
2547c478bd9Sstevel@tonic-gate 	//  is basically for decoding message objects, and we already
2557c478bd9Sstevel@tonic-gate 	//  have things in the internal form needed by the service store.
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	ServiceStore store = serviceTable.store;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	try {
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	    Hashtable das = returnMatchingDAs(query);
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	    Enumeration daURLs = das.keys();
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	    while (daURLs.hasMoreElements()) {
2667c478bd9Sstevel@tonic-gate 		ServiceURL adURL = (ServiceURL)daURLs.nextElement();
2677c478bd9Sstevel@tonic-gate 		store.deregister(adURL, saOnlyScopes, null);
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	    }
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
2727c478bd9Sstevel@tonic-gate 	    conf.writeLog("ssdat_deregister_error",
2737c478bd9Sstevel@tonic-gate 			  new Object[] {
2747c478bd9Sstevel@tonic-gate 		ex.getMessage(),
2757c478bd9Sstevel@tonic-gate 		    address,
2767c478bd9Sstevel@tonic-gate 		    saOnlyScopes});
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	    return false;
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	return true;
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate     }
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate     /**
2867c478bd9Sstevel@tonic-gate      * Return a hashtable in ServiceTable.findServices() format (e.g.
2877c478bd9Sstevel@tonic-gate      * URL's as keys, scopes as values) for DAs matching the query.
2887c478bd9Sstevel@tonic-gate      *
2897c478bd9Sstevel@tonic-gate      * @param query Query for DA attributes.
2907c478bd9Sstevel@tonic-gate      */
2917c478bd9Sstevel@tonic-gate 
returnMatchingDAs(String query)2927c478bd9Sstevel@tonic-gate     public synchronized Hashtable returnMatchingDAs(String query)
2937c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
2947c478bd9Sstevel@tonic-gate 	ServiceStore store = ServiceTable.getServiceTable().store;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	// Get DA records matching the query.
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	Vector saOnlyScopes = conf.getSAOnlyScopes();
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	Hashtable returns =
3017c478bd9Sstevel@tonic-gate 	    store.findServices(Defaults.SUN_DA_SERVICE_TYPE.toString(),
3027c478bd9Sstevel@tonic-gate 			       saOnlyScopes,
3037c478bd9Sstevel@tonic-gate 			       query,
3047c478bd9Sstevel@tonic-gate 			       Defaults.locale);
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	// Return the hashtable of services v.s. scopes.
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	return (Hashtable)returns.get(ServiceStore.FS_SERVICES);
3097c478bd9Sstevel@tonic-gate     }
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate     /**
3127c478bd9Sstevel@tonic-gate      * Return a hashtable of DA equivalence classes and multicast
3137c478bd9Sstevel@tonic-gate      * scopes. Multicast scopes are stored in the special hashtable
3147c478bd9Sstevel@tonic-gate      * key MULTICAST_KEY. Unicast DA equivalence classes are stored
3157c478bd9Sstevel@tonic-gate      * under the key UNICAST_KEY. This implementation goes directly
3167c478bd9Sstevel@tonic-gate      * to the service table in the SA server for the DA addresses.
3177c478bd9Sstevel@tonic-gate      *
3187c478bd9Sstevel@tonic-gate      * @param scopes Scope list for DAs needed.
3197c478bd9Sstevel@tonic-gate      * @return Hashtable with DA addresses as keys and scopes to contact
3207c478bd9Sstevel@tonic-gate      *         them with as values. Any scopes not associated with a
3217c478bd9Sstevel@tonic-gate      *         DA come back stored under the key MULTICAST_KEY.
3227c478bd9Sstevel@tonic-gate      *         Unicast DA equivalence classes are stored
3237c478bd9Sstevel@tonic-gate      * 	     under the key UNICAST_KEY.
3247c478bd9Sstevel@tonic-gate      */
3257c478bd9Sstevel@tonic-gate 
findDAScopes(Vector scopes)3267c478bd9Sstevel@tonic-gate     public synchronized Hashtable findDAScopes(Vector scopes)
3277c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	// Formulate a query for the DAs.
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	int i, n = scopes.size();
3327c478bd9Sstevel@tonic-gate 	StringBuffer buf = new StringBuffer();
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
3357c478bd9Sstevel@tonic-gate 	    buf.append("(");
3367c478bd9Sstevel@tonic-gate 	    buf.append(SunDATable.SCOPES_ID);
3377c478bd9Sstevel@tonic-gate 	    buf.append("=");
3387c478bd9Sstevel@tonic-gate 	    buf.append((String)scopes.elementAt(i));
3397c478bd9Sstevel@tonic-gate 	    buf.append(")");
3407c478bd9Sstevel@tonic-gate 	}
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	// Add logical disjunction if more than one element.
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	if (i > 1) {
3457c478bd9Sstevel@tonic-gate 	    buf.insert(0, "(|");
3467c478bd9Sstevel@tonic-gate 	    buf.append(")");
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	// Add version number.
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	if (i > 0) {
3537c478bd9Sstevel@tonic-gate 	    buf.insert(0, "(&");
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	buf.append("(");
3587c478bd9Sstevel@tonic-gate 	buf.append(SunDATable.VERSION_ID);
3597c478bd9Sstevel@tonic-gate 	buf.append("=");
3607c478bd9Sstevel@tonic-gate 	buf.append((new Integer(Defaults.version)).toString());
3617c478bd9Sstevel@tonic-gate 	buf.append(")");
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	// Add closing paren if there were any scopes.
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	if (i > 0) {
3667c478bd9Sstevel@tonic-gate 	    buf.append(")");
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	ServiceStore store = serviceTable.store;
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	Hashtable returns =
3737c478bd9Sstevel@tonic-gate 	    store.findServices(Defaults.SUN_DA_SERVICE_TYPE.toString(),
3747c478bd9Sstevel@tonic-gate 			       saOnlyScopes,
3757c478bd9Sstevel@tonic-gate 			       buf.toString(),
3767c478bd9Sstevel@tonic-gate 			       Defaults.locale);
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	Hashtable retRec = (Hashtable)returns.get(ServiceStore.FS_SERVICES);
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	// Convert to a vector. Keys are the service: URLs.
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	Enumeration en = retRec.keys();
3837c478bd9Sstevel@tonic-gate 	Vector ret = new Vector();
3847c478bd9Sstevel@tonic-gate 	Vector multiScopes = (Vector)scopes.clone();
3857c478bd9Sstevel@tonic-gate 	Vector attrTags = new Vector();
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	attrTags.addElement(SunDATable.SCOPES_ID);
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	while (en.hasMoreElements()) {
3907c478bd9Sstevel@tonic-gate 	    ServiceURL url = (ServiceURL)en.nextElement();
3917c478bd9Sstevel@tonic-gate 	    Vector urlScopes = (Vector)retRec.get(url);
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	    // Get the scope attributes for this URL.
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	    Hashtable attrRec =
3967c478bd9Sstevel@tonic-gate 		store.findAttributes(url,
3977c478bd9Sstevel@tonic-gate 				     urlScopes,
3987c478bd9Sstevel@tonic-gate 				     attrTags,
3997c478bd9Sstevel@tonic-gate 				     Defaults.locale);
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	    Vector retAttrs = (Vector)attrRec.get(ServiceStore.FA_ATTRIBUTES);
4027c478bd9Sstevel@tonic-gate 	    String host = url.getHost();
4037c478bd9Sstevel@tonic-gate 	    Vector retScopes = null;
4047c478bd9Sstevel@tonic-gate 	    n = retAttrs.size();
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	    for (i = 0; i < n; i++) {
4077c478bd9Sstevel@tonic-gate 		ServiceLocationAttribute attr =
4087c478bd9Sstevel@tonic-gate 		    (ServiceLocationAttribute)retAttrs.elementAt(i);
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 		// Distinguish based on type. We assume the attributes are
4117c478bd9Sstevel@tonic-gate 		// prescreened when the URL was formed to make sure they're OK
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 		String id = attr.getId();
4147c478bd9Sstevel@tonic-gate 		Vector vals = attr.getValues();
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 		if (id.equals(SunDATable.SCOPES_ID)) {
4177c478bd9Sstevel@tonic-gate 		    retScopes = vals;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 		}
4207c478bd9Sstevel@tonic-gate 	    }
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	    // Add to equivalence class.
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	    DATable.addToEquivClass(host, retScopes, ret);
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	    // Filter scopes for any that might be multicast.
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	    DATable.filterScopes(multiScopes, retScopes, false);
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	}
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	// Format the return.
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	retRec.clear();
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	if (multiScopes.size() > 0) {
4377c478bd9Sstevel@tonic-gate 	    retRec.put(DATable.MULTICAST_KEY, multiScopes);
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	}
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	if (ret.size() > 0) {
4427c478bd9Sstevel@tonic-gate 	    retRec.put(DATable.UNICAST_KEY, ret);
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	}
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	return retRec;
4477c478bd9Sstevel@tonic-gate     }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate     // Form a URL for the service table, from the DA URL and attributes.
4507c478bd9Sstevel@tonic-gate     //  Attributes and scope have been prechecked for correctness.
4517c478bd9Sstevel@tonic-gate 
formServiceTableDAURL(ServiceURL url, Vector attrs)4527c478bd9Sstevel@tonic-gate     private ServiceURL formServiceTableDAURL(ServiceURL url, Vector attrs) {
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	// Form up the URL part.
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	StringBuffer buf = new StringBuffer();
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	int i, n = attrs.size();
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
4617c478bd9Sstevel@tonic-gate 	    ServiceLocationAttribute attr =
4627c478bd9Sstevel@tonic-gate 		(ServiceLocationAttribute)attrs.elementAt(i);
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	    // If this is a URL attribute, then externalize and
4657c478bd9Sstevel@tonic-gate 	    //  put into URL.
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	    String id = attr.getId();
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	    if (id.equals(SunDATable.SCOPES_ID)) {
4707c478bd9Sstevel@tonic-gate 		String rep = "";
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 		try {
4737c478bd9Sstevel@tonic-gate 		    rep = attr.externalize();
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 		} catch (ServiceLocationException ex) {
4767c478bd9Sstevel@tonic-gate 		    conf.writeLog("ssdat_inter_attr_err",
4777c478bd9Sstevel@tonic-gate 				  new Object[] {attr, ex.getMessage()});
4787c478bd9Sstevel@tonic-gate 		    continue;
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 		}
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 		// Add semi if something already there.
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 		if (buf.length() > 0) {
4857c478bd9Sstevel@tonic-gate 		    buf.append(";");
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 		}
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 		// Remove parens before inserting.
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 		buf.append(rep.substring(1, rep.length()-1));
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	    }
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	// Create the URL.
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	ServiceURL daURL =
4997c478bd9Sstevel@tonic-gate 	    new ServiceURL(Defaults.SUN_DA_SERVICE_TYPE+
5007c478bd9Sstevel@tonic-gate 			   "://"+
5017c478bd9Sstevel@tonic-gate 			   url.getHost()+
5027c478bd9Sstevel@tonic-gate 			   "/"+
5037c478bd9Sstevel@tonic-gate 			   buf.toString(),
5047c478bd9Sstevel@tonic-gate 			   url.getLifetime());
5057c478bd9Sstevel@tonic-gate 	return daURL;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate     }
5087c478bd9Sstevel@tonic-gate }
509