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 //  ServiceTable.java: Storage of all services.
287c478bd9Sstevel@tonic-gate //  Author:           James Kempf
297c478bd9Sstevel@tonic-gate //  Created On:       Fri Oct 10 14:23:25 1997
307c478bd9Sstevel@tonic-gate //  Last Modified By: James Kempf
317c478bd9Sstevel@tonic-gate //  Last Modified On: Thu Apr  1 10:33:46 1999
327c478bd9Sstevel@tonic-gate //  Update Count:     461
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.io.*;
397c478bd9Sstevel@tonic-gate import java.security.*;
407c478bd9Sstevel@tonic-gate import java.net.*;
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /**
437c478bd9Sstevel@tonic-gate  * The ServiceTable object records all service registrations. Note
447c478bd9Sstevel@tonic-gate  * that any exceptions internal to the service table are processed
457c478bd9Sstevel@tonic-gate  * and either returned as SrvRply objects or are reported.
467c478bd9Sstevel@tonic-gate  *
477c478bd9Sstevel@tonic-gate  * @author James Kempf
487c478bd9Sstevel@tonic-gate  */
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate class ServiceTable extends Object {
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate     // Key for SDAAdvert class.
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate     static final String SDAADVERT = "com.sun.slp.SDAAdvert";
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate     private static final String locationMsg = "Service table";
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate     //
597c478bd9Sstevel@tonic-gate     // Instance variables.
607c478bd9Sstevel@tonic-gate     //
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate     // The service store.
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate     protected ServiceStore store = null;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate     //
677c478bd9Sstevel@tonic-gate     // Class variables.
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate     // System properties.
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate     static protected SLPConfig conf = null;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate     // Singleton objects for the service tables.
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate     static protected ServiceTable table = null;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate     // The ager thread.
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate     static protected AgerThread thrAger = null;
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate     // Time to sleep. Adjusted depending on incoming URLs.
827c478bd9Sstevel@tonic-gate 
83*55fea89dSDan Cross     private static long sleepyTime = Defaults.lMaxSleepTime;
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate     //
867c478bd9Sstevel@tonic-gate     // Creation of singleton.
877c478bd9Sstevel@tonic-gate     //
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate     // Protected constructor.
907c478bd9Sstevel@tonic-gate 
ServiceTable()917c478bd9Sstevel@tonic-gate     protected ServiceTable() {
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	if (thrAger != null) {
947c478bd9Sstevel@tonic-gate 	    return;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	}
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	// Create the ager thread.
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	thrAger = new AgerThread();
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	// Set the priority low, so other things (like active discovery)
1037c478bd9Sstevel@tonic-gate 	//  take priority.
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	thrAger.setPriority(Thread.MIN_PRIORITY);
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	thrAger.start();
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate     }
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate     /**
1127c478bd9Sstevel@tonic-gate      * Return an SA service store.
1137c478bd9Sstevel@tonic-gate      *
1147c478bd9Sstevel@tonic-gate      * @return The distinguished table object.
1157c478bd9Sstevel@tonic-gate      */
1167c478bd9Sstevel@tonic-gate 
getServiceTable()1177c478bd9Sstevel@tonic-gate     static ServiceTable getServiceTable()
1187c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	if (conf == null) {
1217c478bd9Sstevel@tonic-gate 	    conf = SLPConfig.getSLPConfig();
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	if (table == null) {
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	    table = createServiceTable();
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	return table;
1327c478bd9Sstevel@tonic-gate     }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate     /**
1357c478bd9Sstevel@tonic-gate      * Return a service table object.
1367c478bd9Sstevel@tonic-gate      *
1377c478bd9Sstevel@tonic-gate      * @return The service table object.
1387c478bd9Sstevel@tonic-gate      */
1397c478bd9Sstevel@tonic-gate 
createServiceTable()1407c478bd9Sstevel@tonic-gate     private static ServiceTable createServiceTable()
1417c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	ServiceTable table = new ServiceTable();
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	table.store = ServiceStoreFactory.createServiceStore();
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	return table;
1487c478bd9Sstevel@tonic-gate     }
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate     //
1517c478bd9Sstevel@tonic-gate     // Support for serializated registrations.
1527c478bd9Sstevel@tonic-gate     //
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate     /**
1557c478bd9Sstevel@tonic-gate      * If any serialized registrations are pending, then unserialize
1567c478bd9Sstevel@tonic-gate      * and register.
1577c478bd9Sstevel@tonic-gate      */
1587c478bd9Sstevel@tonic-gate 
deserializeTable()1597c478bd9Sstevel@tonic-gate     public void deserializeTable() {
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	// If there are any serialized registrations, then get
1627c478bd9Sstevel@tonic-gate 	//  them and perform registrations.
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	String serializedURL = conf.getSerializedRegURL();
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	if (serializedURL != null) {
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	    ServiceStore serStore = getStoreFromURL(serializedURL);
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	    if (serStore != null) {
1717c478bd9Sstevel@tonic-gate 		registerStore(serStore);
1727c478bd9Sstevel@tonic-gate 	    }
1737c478bd9Sstevel@tonic-gate 	}
1747c478bd9Sstevel@tonic-gate     }
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate     /**
1777c478bd9Sstevel@tonic-gate      * Serialize the table to the URL.
1787c478bd9Sstevel@tonic-gate      *
1797c478bd9Sstevel@tonic-gate      * @param URL String giving the URL to which the store should be
1807c478bd9Sstevel@tonic-gate      * serialized.
1817c478bd9Sstevel@tonic-gate      */
1827c478bd9Sstevel@tonic-gate 
serializeServiceStore(String URL)1837c478bd9Sstevel@tonic-gate     void serializeServiceStore(String URL) {
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	// Open an object output stream for the URL, serialize through
1867c478bd9Sstevel@tonic-gate 	//  the factory.
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	try {
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	    URL url = new URL(URL);
1917c478bd9Sstevel@tonic-gate 	    URLConnection urlConn = url.openConnection();
1927c478bd9Sstevel@tonic-gate 	    OutputStream os = urlConn.getOutputStream();
1937c478bd9Sstevel@tonic-gate 	    BufferedWriter di =
1947c478bd9Sstevel@tonic-gate 		new BufferedWriter(new OutputStreamWriter(os));
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	    // Serialize the store.
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	    ServiceStoreFactory.serialize(di, store);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	} catch (MalformedURLException ex) {
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	    conf.writeLog("st_serialized_malform",
2037c478bd9Sstevel@tonic-gate 			  new Object[] {URL});
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	} catch (UnsupportedEncodingException ex) {
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	    conf.writeLog("st_unsupported_encoding",
2087c478bd9Sstevel@tonic-gate 			  new Object[] {URL});
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	} catch (IOException ex) {
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	    conf.writeLog("st_serialized_ioexception",
2137c478bd9Sstevel@tonic-gate 			  new Object[] {URL, ex});
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	    conf.writeLog("st_serialized_sle",
2187c478bd9Sstevel@tonic-gate 			  new Object[] {URL, ex.getMessage()});
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	}
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate     }
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate     // Read proxy registrations from the URL.
2257c478bd9Sstevel@tonic-gate 
getStoreFromURL(String serializedURL)2267c478bd9Sstevel@tonic-gate     private ServiceStore getStoreFromURL(String serializedURL) {
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	ServiceStore serStore = null;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	// Open an object input stream for the URL, deserialize through
2317c478bd9Sstevel@tonic-gate 	//  the factory.
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	try {
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	    URL url = new URL(serializedURL);
2367c478bd9Sstevel@tonic-gate 	    InputStream is = url.openStream();
2377c478bd9Sstevel@tonic-gate 	    BufferedReader di = new BufferedReader(new InputStreamReader(is));
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	    // Deserialize the objects.
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	    serStore =
2427c478bd9Sstevel@tonic-gate 		ServiceStoreFactory.deserializeServiceStore(di);
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	} catch (MalformedURLException ex) {
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	    conf.writeLog("st_serialized_malform",
2477c478bd9Sstevel@tonic-gate 			  new Object[] {serializedURL});
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	} catch (UnsupportedEncodingException ex) {
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	    conf.writeLog("st_unsupported_encoding",
2527c478bd9Sstevel@tonic-gate 			  new Object[] {serializedURL});
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	} catch (IOException ex) {
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	    conf.writeLog("st_serialized_ioexception",
2577c478bd9Sstevel@tonic-gate 			  new Object[] {
2587c478bd9Sstevel@tonic-gate 		serializedURL,
2597c478bd9Sstevel@tonic-gate 		    ex.getMessage()});
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	    conf.writeLog("st_serialized_sle",
2647c478bd9Sstevel@tonic-gate 			  new Object[] {
2657c478bd9Sstevel@tonic-gate 		serializedURL,
2667c478bd9Sstevel@tonic-gate 		    ex.getMessage()});
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	return serStore;
2717c478bd9Sstevel@tonic-gate     }
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate     // Walk the table, performing actual registrations on all records.
2747c478bd9Sstevel@tonic-gate 
registerStore(ServiceStore serStore)2757c478bd9Sstevel@tonic-gate     private void registerStore(ServiceStore serStore) {
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	// Walk the table.
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	Enumeration en = serStore.getServiceRecordsByScope(null);
2807c478bd9Sstevel@tonic-gate 	boolean hasURLSig = conf.getHasSecurity();
2817c478bd9Sstevel@tonic-gate 	boolean hasAttrSig = conf.getHasSecurity();
2827c478bd9Sstevel@tonic-gate 	PermSARegTable pregTable = 	SARequester.getPermSARegTable();
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 	while (en.hasMoreElements()) {
2857c478bd9Sstevel@tonic-gate 	    ServiceStore.ServiceRecord rec =
2867c478bd9Sstevel@tonic-gate 		(ServiceStore.ServiceRecord)en.nextElement();
2877c478bd9Sstevel@tonic-gate 	    ServiceURL surl = rec.getServiceURL();
2887c478bd9Sstevel@tonic-gate 	    Vector scopes = rec.getScopes();
2897c478bd9Sstevel@tonic-gate 	    Vector attrs = rec.getAttrList();
2907c478bd9Sstevel@tonic-gate 	    Locale locale = rec.getLocale();
2917c478bd9Sstevel@tonic-gate 	    Hashtable urlSig = null;
2927c478bd9Sstevel@tonic-gate 	    Hashtable attrSig = null;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	    // Note that we can't use the Advertiser to register here,
2957c478bd9Sstevel@tonic-gate 	    //  because we may not be listening yet for registrations.
2967c478bd9Sstevel@tonic-gate 	    //  We need to do this all by hand.
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	    try {
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 		// Create a registration message for refreshing.
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 		CSrvReg creg = new CSrvReg(false,
3037c478bd9Sstevel@tonic-gate 					   locale,
3047c478bd9Sstevel@tonic-gate 					   surl,
3057c478bd9Sstevel@tonic-gate 					   scopes,
3067c478bd9Sstevel@tonic-gate 					   attrs,
3077c478bd9Sstevel@tonic-gate 					   null,
3087c478bd9Sstevel@tonic-gate 					   null);
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 		// We externalize to a server side message if authentication
3117c478bd9Sstevel@tonic-gate 		//  is needed. This creates the auth blocks for the scopes.
3127c478bd9Sstevel@tonic-gate 		//  Doing this in any other way is alot more complicated,
3137c478bd9Sstevel@tonic-gate 		//  although doing it this way seems kludgy.
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 		if (hasURLSig || hasAttrSig) {
3167c478bd9Sstevel@tonic-gate 		    ByteArrayOutputStream baos = new ByteArrayOutputStream();
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 		    creg.getHeader().externalize(baos, false, true);
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 		    ByteArrayInputStream bais =
3217c478bd9Sstevel@tonic-gate 			new ByteArrayInputStream(baos.toByteArray());
3227c478bd9Sstevel@tonic-gate 		    bais.read();	// pop off version and function code...
3237c478bd9Sstevel@tonic-gate 		    bais.read();
3247c478bd9Sstevel@tonic-gate 		    DataInputStream dis = new DataInputStream(bais);
3257c478bd9Sstevel@tonic-gate 		    SLPHeaderV2 hdr = new SLPHeaderV2();
3267c478bd9Sstevel@tonic-gate 		    hdr.parseHeader(SrvLocHeader.SrvReg, dis);
3277c478bd9Sstevel@tonic-gate 		    SSrvReg sreg = new SSrvReg(hdr, dis);
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 		    // Now we've got it, after much effort. Get the auths.
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 		    urlSig = sreg.URLSignature;
3327c478bd9Sstevel@tonic-gate 		    attrSig = sreg.attrSignature;
333*55fea89dSDan Cross 
3347c478bd9Sstevel@tonic-gate 		}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 		store.register(surl, attrs, scopes, locale, urlSig, attrSig);
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 		// Now we've got to put the registration into the
3397c478bd9Sstevel@tonic-gate 		//  PermSARegTable. Again, we do everything by hand
3407c478bd9Sstevel@tonic-gate 		//  because we can't use Advertiser.
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 		if (surl.getIsPermanent()) {
3437c478bd9Sstevel@tonic-gate 		    pregTable.reg(surl, creg);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 		}
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 		// Report registration.
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 		if (conf.regTest()) {
3507c478bd9Sstevel@tonic-gate 		    conf.writeLog("st_reg_add",
3517c478bd9Sstevel@tonic-gate 				  new Object[] {
3527c478bd9Sstevel@tonic-gate 			locationMsg,
3537c478bd9Sstevel@tonic-gate 			    locale,
3547c478bd9Sstevel@tonic-gate 			    surl.getServiceType(),
3557c478bd9Sstevel@tonic-gate 			    surl,
3567c478bd9Sstevel@tonic-gate 			    attrs,
3577c478bd9Sstevel@tonic-gate 			    scopes});
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 		}
3607c478bd9Sstevel@tonic-gate 	    } catch (ServiceLocationException ex) {
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 		String msg = ex.getMessage();
363*55fea89dSDan Cross 
3647c478bd9Sstevel@tonic-gate 		conf.writeLog("st_serialized_seex",
3657c478bd9Sstevel@tonic-gate 			      new Object[] {
3667c478bd9Sstevel@tonic-gate 		    new Integer(ex.getErrorCode()),
3677c478bd9Sstevel@tonic-gate 			surl,
3687c478bd9Sstevel@tonic-gate 			(msg == null ? "<no message>":msg)});
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	    } catch (Exception ex) {
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 		String msg = ex.getMessage();
373*55fea89dSDan Cross 
3747c478bd9Sstevel@tonic-gate 		conf.writeLog("st_serialized_seex",
3757c478bd9Sstevel@tonic-gate 			      new Object[] {
3767c478bd9Sstevel@tonic-gate 		    surl,
3777c478bd9Sstevel@tonic-gate 			(msg == null ? "<no message>":msg)});
3787c478bd9Sstevel@tonic-gate 	    }
3797c478bd9Sstevel@tonic-gate 	}
3807c478bd9Sstevel@tonic-gate     }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate     //
3837c478bd9Sstevel@tonic-gate     // Record aging.
3847c478bd9Sstevel@tonic-gate     //
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate     //
3877c478bd9Sstevel@tonic-gate     // Run the thread that ages out records.
3887c478bd9Sstevel@tonic-gate     //
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate     private class AgerThread extends Thread {
3917c478bd9Sstevel@tonic-gate 
run()3927c478bd9Sstevel@tonic-gate 	public void run() {
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	    setName("SLP Service Table Age-out");
3957c478bd9Sstevel@tonic-gate 	    long alarmTime = sleepyTime;  // when to wake up next
3967c478bd9Sstevel@tonic-gate 	    long wentToSleep = 0;	    // what time we went to bed
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	    while (true) {
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 		try {
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 		    // Record when we went to sleep.
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 		    wentToSleep = System.currentTimeMillis();
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 		    // Sleep for the minimum amount of time needed before we
4077c478bd9Sstevel@tonic-gate 		    //  must wake up and check.
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 		    sleep(alarmTime);
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 		} catch (InterruptedException ie) {
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 		    // A new registration came in. Calculate how much time
4147c478bd9Sstevel@tonic-gate 		    //  remains until we would have woken up. If this is
4157c478bd9Sstevel@tonic-gate 		    //  less than the new sleepyTime, then we set the alarm
4167c478bd9Sstevel@tonic-gate 		    //  for this time. If it is more, then we set the alarm
4177c478bd9Sstevel@tonic-gate 		    //  for the new sleepyTime.
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 		    long remainingSleepTime =
4207c478bd9Sstevel@tonic-gate 			(wentToSleep + alarmTime) - System.currentTimeMillis();
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 		    remainingSleepTime =		// just in case...
4237c478bd9Sstevel@tonic-gate 			((remainingSleepTime <= 0) ? 0 : remainingSleepTime);
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 		    alarmTime = sleepyTime;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 		    if (remainingSleepTime < alarmTime) {
4287c478bd9Sstevel@tonic-gate 			alarmTime = remainingSleepTime;
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 		    }
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 		    continue;  // we don't have to walk yet...
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 		}
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 		// Walk the table, get the new alarm and sleepy times.
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 		if (table != null) {
4397c478bd9Sstevel@tonic-gate 		    table.ageStore();
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 		    alarmTime = sleepyTime;
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 		}
4447c478bd9Sstevel@tonic-gate 	    }
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate     }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate     /**
4507c478bd9Sstevel@tonic-gate      * Age the service store.
4517c478bd9Sstevel@tonic-gate      */
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate     // this method cannot be private... due to compiler weakness
ageStore()4547c478bd9Sstevel@tonic-gate     void ageStore() {
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	try {
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	    // We synchronize in case somebody registers and tries to
4597c478bd9Sstevel@tonic-gate 	    //  change sleepy time.
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	    synchronized (store) {
4627c478bd9Sstevel@tonic-gate 		Vector deleted = new Vector();
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		sleepyTime = store.ageOut(deleted);
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 		// Track unregistered services.
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 		int i, n = deleted.size();
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 		for (i = 0; i < n; i++) {
4717c478bd9Sstevel@tonic-gate 		    ServiceStore.ServiceRecord rec =
4727c478bd9Sstevel@tonic-gate 			(ServiceStore.ServiceRecord)deleted.elementAt(i);
4737c478bd9Sstevel@tonic-gate 		    ServiceURL surl = rec.getServiceURL();
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 		    trackRegisteredServiceTypes(); // it's deleted...
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 		}
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	    }
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	} catch (RuntimeException ex) {
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	    reportNonfatalException(ex, new Vector(), store);
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	    reportNonfatalException(ex, new Vector(), store);
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	}
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate     }
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate     //
4947c478bd9Sstevel@tonic-gate     // SLP Service Table operations (register, deregister, etc.)
4957c478bd9Sstevel@tonic-gate     //
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate     /**
4987c478bd9Sstevel@tonic-gate      * Process the registration and record if no errors found.
4997c478bd9Sstevel@tonic-gate      *
5007c478bd9Sstevel@tonic-gate      * @param req Service registration request message.
5017c478bd9Sstevel@tonic-gate      * @return SrvLocMsg A service registration acknowledgement.
5027c478bd9Sstevel@tonic-gate      */
5037c478bd9Sstevel@tonic-gate 
register(SSrvReg req)5047c478bd9Sstevel@tonic-gate     SrvLocMsg register(SSrvReg req) {
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	SrvLocHeader hdr = req.getHeader();
5077c478bd9Sstevel@tonic-gate 	Locale locale = hdr.locale;
5087c478bd9Sstevel@tonic-gate 	boolean fresh = hdr.fresh;
5097c478bd9Sstevel@tonic-gate 	Vector scopes = hdr.scopes;
5107c478bd9Sstevel@tonic-gate 	ServiceURL surl = req.URL;
5117c478bd9Sstevel@tonic-gate 	String serviceType = req.serviceType;
5127c478bd9Sstevel@tonic-gate 	Vector attrList = req.attrList;
5137c478bd9Sstevel@tonic-gate 	Hashtable urlSig = req.URLSignature;
5147c478bd9Sstevel@tonic-gate 	Hashtable attrSig = req.attrSignature;
5157c478bd9Sstevel@tonic-gate 	short errorCode =
5167c478bd9Sstevel@tonic-gate 	    (fresh ? ServiceLocationException.INVALID_REGISTRATION :
5177c478bd9Sstevel@tonic-gate 	    ServiceLocationException.INVALID_UPDATE);
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	try {
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	    // If a sig block came in, verify it.
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	    if (urlSig != null) {
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 		AuthBlock.verifyAll(urlSig);
5267c478bd9Sstevel@tonic-gate 	    }
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	    if (attrSig != null) {
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 		AuthBlock.verifyAll(attrSig);
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	    }
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	    // Check whether the URL has a zero lifetime. If so, it
5357c478bd9Sstevel@tonic-gate 	    // isn't cached.
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	    if (surl.getLifetime() <= 0) {
5387c478bd9Sstevel@tonic-gate 		throw
5397c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(errorCode,
5407c478bd9Sstevel@tonic-gate 						 "st_zero",
5417c478bd9Sstevel@tonic-gate 						 new Object[0]);
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	    }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	    // Check if the service type is restricted. If so, nobody outside
5467c478bd9Sstevel@tonic-gate 	    //  this process is allowed to register it.
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	    checkForRestrictedType(surl.getServiceType());
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	    // Check that attribute signature bit on implies URL signature
5517c478bd9Sstevel@tonic-gate 	    //  bit on.
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	    if (attrSig != null && urlSig == null) {
5547c478bd9Sstevel@tonic-gate 		throw
5557c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(errorCode,
5567c478bd9Sstevel@tonic-gate 						 "st_attr_sig",
5577c478bd9Sstevel@tonic-gate 						 new Object[0]);
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	    }
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	    // If a signature and the fresh bit was not set, error since signed
5627c478bd9Sstevel@tonic-gate 	    //  registrations don't allow updating.
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 	    if (urlSig != null && !fresh) {
5657c478bd9Sstevel@tonic-gate 		throw
5667c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(
5677c478bd9Sstevel@tonic-gate 				ServiceLocationException.INVALID_UPDATE,
5687c478bd9Sstevel@tonic-gate 				"st_prot_update",
5697c478bd9Sstevel@tonic-gate 				new Object[0]);
5707c478bd9Sstevel@tonic-gate 	    }
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	    // Check if scopes are supported.
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 	    if (!areSupportedScopes(scopes)) {
5757c478bd9Sstevel@tonic-gate 		throw
5767c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(
5777c478bd9Sstevel@tonic-gate 				ServiceLocationException.SCOPE_NOT_SUPPORTED,
5787c478bd9Sstevel@tonic-gate 				"st_scope_unsup",
5797c478bd9Sstevel@tonic-gate 				new Object[0]);
5807c478bd9Sstevel@tonic-gate 	    }
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	    // Check if the reg is signed and auth is off or vice versa.
5837c478bd9Sstevel@tonic-gate 	    //  Check is really simple. If security is on, then all regs
5847c478bd9Sstevel@tonic-gate 	    //  to this DA/SA server must be signed, so toss out any regs
5857c478bd9Sstevel@tonic-gate 	    //  that aren't, and vice versa.
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	    if (conf.getHasSecurity() && (urlSig == null || attrSig == null)) {
5887c478bd9Sstevel@tonic-gate 		throw
5897c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(
5907c478bd9Sstevel@tonic-gate 				ServiceLocationException.AUTHENTICATION_FAILED,
5917c478bd9Sstevel@tonic-gate 				"st_unprot_non_reg",
5927c478bd9Sstevel@tonic-gate 				new Object[0]);
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	    } else if (!conf.getHasSecurity() &&
5957c478bd9Sstevel@tonic-gate 		       (urlSig != null || attrSig != null)) {
5967c478bd9Sstevel@tonic-gate 		throw
5977c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(
5987c478bd9Sstevel@tonic-gate 				ServiceLocationException.INVALID_REGISTRATION,
5997c478bd9Sstevel@tonic-gate 				"st_prot_non_reg",
6007c478bd9Sstevel@tonic-gate 				new Object[0]);
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	    }
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	    // Merge any duplicates.
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	    Vector attrs = new Vector();
6077c478bd9Sstevel@tonic-gate 	    Hashtable attrHash = new Hashtable();
6087c478bd9Sstevel@tonic-gate 	    int i, n = attrList.size();
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	    for (i = 0; i < n; i++) {
6117c478bd9Sstevel@tonic-gate 		ServiceLocationAttribute attr =
6127c478bd9Sstevel@tonic-gate 		    (ServiceLocationAttribute)attrList.elementAt(i);
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 		ServiceLocationAttribute.mergeDuplicateAttributes(
6157c478bd9Sstevel@tonic-gate 								  attr,
6167c478bd9Sstevel@tonic-gate 								  attrHash,
6177c478bd9Sstevel@tonic-gate 								  attrs,
6187c478bd9Sstevel@tonic-gate 								  false);
6197c478bd9Sstevel@tonic-gate 	    }
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	    // Store register or update.
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	    boolean existing = false;
624*55fea89dSDan Cross 
6257c478bd9Sstevel@tonic-gate 	    if (fresh) {
6267c478bd9Sstevel@tonic-gate 		existing = store.register(surl,
6277c478bd9Sstevel@tonic-gate 					  attrs,
6287c478bd9Sstevel@tonic-gate 					  scopes,
6297c478bd9Sstevel@tonic-gate 					  locale,
6307c478bd9Sstevel@tonic-gate 					  urlSig,
6317c478bd9Sstevel@tonic-gate 					  attrSig);
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 		// Track registred service types in case we get a
6347c478bd9Sstevel@tonic-gate 		// SAAdvert solicatation.
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 		trackRegisteredServiceTypes();
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	    } else {
6397c478bd9Sstevel@tonic-gate 		store.updateRegistration(surl, attrs, scopes, locale);
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	    }
642*55fea89dSDan Cross 
6437c478bd9Sstevel@tonic-gate 	    // Create the reply.
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	    SrvLocMsg ack = req.makeReply(existing);
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	    if (conf.regTest()) {
6487c478bd9Sstevel@tonic-gate 		conf.writeLog((fresh ? "st_reg_add":"st_reg_update"),
6497c478bd9Sstevel@tonic-gate 			      new Object[] {
6507c478bd9Sstevel@tonic-gate 		    locationMsg,
6517c478bd9Sstevel@tonic-gate 			locale,
6527c478bd9Sstevel@tonic-gate 			serviceType,
6537c478bd9Sstevel@tonic-gate 			surl,
6547c478bd9Sstevel@tonic-gate 			attrs,
6557c478bd9Sstevel@tonic-gate 			scopes});
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	    }
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate 	    if (conf.traceAll()) {
6607c478bd9Sstevel@tonic-gate 		conf.writeLog("st_dump", new Object[] {locationMsg});
6617c478bd9Sstevel@tonic-gate 		store.dumpServiceStore();
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	    }
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	    // Calculate time increment until next update. This is used
6667c478bd9Sstevel@tonic-gate 	    //  to adjust the sleep interval in the ager thread.
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	    long sTime = getSleepIncrement(surl);
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	    // We synchronize in case the ager thread is in the middle
6717c478bd9Sstevel@tonic-gate 	    //  of trying to set the time.
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	    synchronized (store) {
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 		// If we need to wake up sooner, adjust the sleep time.
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 		if (sTime < sleepyTime) {
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 		    sleepyTime = sTime;
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 		    // Interrupt the thread so we go back to
6827c478bd9Sstevel@tonic-gate 		    //  sleep for the right amount of time.
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 		    thrAger.interrupt();
6857c478bd9Sstevel@tonic-gate 		}
6867c478bd9Sstevel@tonic-gate 	    }
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	    return ack;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 	    if (conf.traceDrop()) {
6937c478bd9Sstevel@tonic-gate 		conf.writeLog("st_reg_drop",
6947c478bd9Sstevel@tonic-gate 			      new Object[] {
6957c478bd9Sstevel@tonic-gate 		    locationMsg,
6967c478bd9Sstevel@tonic-gate 			ex.getMessage()+"("+ex.getErrorCode()+")",
6977c478bd9Sstevel@tonic-gate 			locale,
6987c478bd9Sstevel@tonic-gate 			serviceType,
6997c478bd9Sstevel@tonic-gate 			surl,
7007c478bd9Sstevel@tonic-gate 			attrList,
7017c478bd9Sstevel@tonic-gate 			scopes});
7027c478bd9Sstevel@tonic-gate 	    }
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	} catch (RuntimeException ex) {
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	    // These exceptions are not declared in throws but can occur
7097c478bd9Sstevel@tonic-gate 	    //  anywhere.
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	    Vector args = new Vector();
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	    args.addElement(req);
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	    reportNonfatalException(ex, args, store);
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate     }
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate     /**
7237c478bd9Sstevel@tonic-gate      * Process the deregistration and return the result in a reply.
7247c478bd9Sstevel@tonic-gate      *
7257c478bd9Sstevel@tonic-gate      * @param req Service deregistration request message.
7267c478bd9Sstevel@tonic-gate      * @return SrvLocMsg A service registration acknowledgement.
7277c478bd9Sstevel@tonic-gate      */
7287c478bd9Sstevel@tonic-gate 
deregister(SSrvDereg req)7297c478bd9Sstevel@tonic-gate     SrvLocMsg deregister(SSrvDereg req) {
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	// We need to determine whether this is an attribute deregistration
7327c478bd9Sstevel@tonic-gate 	//  or a deregistration of the entire URL.
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	SrvLocHeader hdr = req.getHeader();
7357c478bd9Sstevel@tonic-gate 	Locale locale = hdr.locale;
7367c478bd9Sstevel@tonic-gate 	Vector scopes = hdr.scopes;
7377c478bd9Sstevel@tonic-gate 	ServiceURL surl = req.URL;
7387c478bd9Sstevel@tonic-gate 	Hashtable urlSig = req.URLSignature;
7397c478bd9Sstevel@tonic-gate 	Vector tags = req.tags;
7407c478bd9Sstevel@tonic-gate 	short errorCode = ServiceLocationException.OK;
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	try {
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	    // Verify if signature is nonnull.
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 	    if (urlSig != null) {
7477c478bd9Sstevel@tonic-gate 		AuthBlock.verifyAll(urlSig);
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	    }
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	    // Check if the service type is restricted. If so, nobody outside
7527c478bd9Sstevel@tonic-gate 	    //  this process is allowed to register it.
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	    checkForRestrictedType(surl.getServiceType());
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	    // Error if there's a signature and attempt at deleting attributes.
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	    if ((urlSig != null) && (tags != null)) {
7597c478bd9Sstevel@tonic-gate 		throw
7607c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(
7617c478bd9Sstevel@tonic-gate 				ServiceLocationException.AUTHENTICATION_FAILED,
7627c478bd9Sstevel@tonic-gate 				"st_prot_attr_dereg",
7637c478bd9Sstevel@tonic-gate 				new Object[0]);
7647c478bd9Sstevel@tonic-gate 	    }
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 	    // Check if scope is protected and auth is off or vice versa.
7677c478bd9Sstevel@tonic-gate 	    //  Check is really simple. If security is on, then all scopes
7687c478bd9Sstevel@tonic-gate 	    //  in this DA/SA server are protected, so toss out any regs
7697c478bd9Sstevel@tonic-gate 	    //  that aren't, and vice versa.
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	    if (conf.getHasSecurity() && urlSig == null) {
7727c478bd9Sstevel@tonic-gate 		throw
7737c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(
7747c478bd9Sstevel@tonic-gate 				ServiceLocationException.AUTHENTICATION_FAILED,
7757c478bd9Sstevel@tonic-gate 				"st_unprot_non_dereg",
7767c478bd9Sstevel@tonic-gate 				new Object[0]);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	    } else if (!conf.getHasSecurity() && urlSig != null) {
7797c478bd9Sstevel@tonic-gate 		throw
7807c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(
7817c478bd9Sstevel@tonic-gate 				ServiceLocationException.INVALID_REGISTRATION,
7827c478bd9Sstevel@tonic-gate 				"st_prot_non_dereg",
7837c478bd9Sstevel@tonic-gate 				new Object[0]);
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	    }
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	    // If it's a service URL, then deregister the URL.
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	    if (tags == null) {
7907c478bd9Sstevel@tonic-gate 		store.deregister(surl, scopes, urlSig);
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate 		// Track registred service types in case we get a
7937c478bd9Sstevel@tonic-gate 		// SAAdvert solicatation.
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 		trackRegisteredServiceTypes();
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	    } else {
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 		// Just delete the attributes.
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 		store.deleteAttributes(surl, scopes, tags, locale);
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 	    }
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate 	    // Create the reply.
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 	    SrvLocMsg ack = req.makeReply();
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	    if (conf.regTest()) {
8107c478bd9Sstevel@tonic-gate 		conf.writeLog((tags == null ? "st_dereg":"st_delattr"),
8117c478bd9Sstevel@tonic-gate 			      new Object[] {
8127c478bd9Sstevel@tonic-gate 		    locationMsg,
8137c478bd9Sstevel@tonic-gate 	                locale,
8147c478bd9Sstevel@tonic-gate 			surl.getServiceType(),
8157c478bd9Sstevel@tonic-gate 			surl,
8167c478bd9Sstevel@tonic-gate 			tags});
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	    }
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 	    if (conf.traceAll()) {
8217c478bd9Sstevel@tonic-gate 		conf.writeLog("st_dump",
8227c478bd9Sstevel@tonic-gate 			      new Object[] {locationMsg});
8237c478bd9Sstevel@tonic-gate 		store.dumpServiceStore();
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 	    }
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	    return ack;
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	    if (conf.traceDrop()) {
8327c478bd9Sstevel@tonic-gate 		conf.writeLog((tags == null ?
8337c478bd9Sstevel@tonic-gate 			       "st_dereg_drop" : "st_dereg_attr_drop"),
8347c478bd9Sstevel@tonic-gate 			      new Object[] {
8357c478bd9Sstevel@tonic-gate 		    locationMsg,
8367c478bd9Sstevel@tonic-gate 			ex.getMessage()+"("+ex.getErrorCode()+")",
8377c478bd9Sstevel@tonic-gate 			locale,
8387c478bd9Sstevel@tonic-gate 			surl.getServiceType(),
8397c478bd9Sstevel@tonic-gate 			surl,
8407c478bd9Sstevel@tonic-gate 			tags});
8417c478bd9Sstevel@tonic-gate 	    }
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	} catch (RuntimeException ex) {
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	    // These exceptions are not declared in throws but can occur
8487c478bd9Sstevel@tonic-gate 	    //  anywhere.
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	    Vector args = new Vector();
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 	    args.addElement(req);
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 	    reportNonfatalException(ex, args, store);
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	}
8597c478bd9Sstevel@tonic-gate     }
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate     /**
8627c478bd9Sstevel@tonic-gate      * Process the service type request and return the result in a reply.
8637c478bd9Sstevel@tonic-gate      *
8647c478bd9Sstevel@tonic-gate      * @param req Service type request message.
8657c478bd9Sstevel@tonic-gate      * @return SrvTypeRply A service type reply.
8667c478bd9Sstevel@tonic-gate      */
8677c478bd9Sstevel@tonic-gate 
findServiceTypes(SSrvTypeMsg req)8687c478bd9Sstevel@tonic-gate     SrvLocMsg findServiceTypes(SSrvTypeMsg req) {
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	SrvLocHeader hdr = req.getHeader();
8717c478bd9Sstevel@tonic-gate 	Vector scopes = hdr.scopes;
8727c478bd9Sstevel@tonic-gate 	String namingAuthority = req.namingAuthority;
8737c478bd9Sstevel@tonic-gate 	short errorCode = ServiceLocationException.OK;
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	try {
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 	    // Check whether the scope is supported.
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	    if (!areSupportedScopes(scopes)) {
8807c478bd9Sstevel@tonic-gate 		throw
8817c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(
8827c478bd9Sstevel@tonic-gate 				ServiceLocationException.SCOPE_NOT_SUPPORTED,
8837c478bd9Sstevel@tonic-gate 				"st_scope_unsup",
8847c478bd9Sstevel@tonic-gate 				new Object[0]);
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 	    }
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 	    // Get the vector of service types in the store, independent
8897c478bd9Sstevel@tonic-gate 	    //  of language.
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 	    Vector types = store.findServiceTypes(namingAuthority, scopes);
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 	    // Create the reply.
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 	    SrvLocMsg ack = req.makeReply(types);
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 	    if (conf.traceAll()) {
8987c478bd9Sstevel@tonic-gate 		conf.writeLog("st_stypes",
8997c478bd9Sstevel@tonic-gate 			      new Object[] {
9007c478bd9Sstevel@tonic-gate 		    locationMsg,
9017c478bd9Sstevel@tonic-gate 			namingAuthority,
9027c478bd9Sstevel@tonic-gate 			scopes,
9037c478bd9Sstevel@tonic-gate 			types});
9047c478bd9Sstevel@tonic-gate 	    }
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 	    return ack;
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate 	    if (conf.traceDrop()) {
9117c478bd9Sstevel@tonic-gate 		conf.writeLog("st_stypes_drop",
9127c478bd9Sstevel@tonic-gate 			      new Object[] {
9137c478bd9Sstevel@tonic-gate 		    locationMsg,
9147c478bd9Sstevel@tonic-gate 			ex.getMessage()+"("+ex.getErrorCode()+")",
9157c478bd9Sstevel@tonic-gate 			namingAuthority,
9167c478bd9Sstevel@tonic-gate 			scopes,
9177c478bd9Sstevel@tonic-gate 			hdr.locale});
9187c478bd9Sstevel@tonic-gate 	    }
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 	} catch (RuntimeException ex) {
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 	    // These exceptions are not declared in throws but can occur
9257c478bd9Sstevel@tonic-gate 	    //  anywhere.
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 	    Vector args = new Vector();
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 	    args.addElement(req);
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	    reportNonfatalException(ex, args, store);
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 	}
9367c478bd9Sstevel@tonic-gate     }
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate     /**
9397c478bd9Sstevel@tonic-gate      * Process the service request and return the result in a reply.
9407c478bd9Sstevel@tonic-gate      *
9417c478bd9Sstevel@tonic-gate      * @param req Service request message.
9427c478bd9Sstevel@tonic-gate      * @return SrvRply A service reply.
9437c478bd9Sstevel@tonic-gate      */
9447c478bd9Sstevel@tonic-gate 
findServices(SSrvMsg req)9457c478bd9Sstevel@tonic-gate     SrvLocMsg findServices(SSrvMsg req) {
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate 	SrvLocHeader hdr = req.getHeader();
9487c478bd9Sstevel@tonic-gate 	Locale locale = hdr.locale;
9497c478bd9Sstevel@tonic-gate 	Vector scopes = hdr.scopes;
9507c478bd9Sstevel@tonic-gate 	String serviceType = req.serviceType;
9517c478bd9Sstevel@tonic-gate 	String query = req.query;
9527c478bd9Sstevel@tonic-gate 	short errorCode = ServiceLocationException.OK;
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 	try {
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 	    // Check whether the scope is supported.
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	    if (!areSupportedScopes(scopes)) {
9597c478bd9Sstevel@tonic-gate 		throw
9607c478bd9Sstevel@tonic-gate 		    new ServiceLocationException(
9617c478bd9Sstevel@tonic-gate 				ServiceLocationException.SCOPE_NOT_SUPPORTED,
9627c478bd9Sstevel@tonic-gate 				"st_scope_unsup",
9637c478bd9Sstevel@tonic-gate 				new Object[0]);
9647c478bd9Sstevel@tonic-gate 	    }
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 	    // Get the hashtable of returns.
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate 	    Hashtable returns =
9697c478bd9Sstevel@tonic-gate 		store.findServices(serviceType,
9707c478bd9Sstevel@tonic-gate 				   scopes,
9717c478bd9Sstevel@tonic-gate 				   query,
9727c478bd9Sstevel@tonic-gate 				   locale);
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate 	    // Get the hashtable of services v.s. scopes, and signatures, if
9757c478bd9Sstevel@tonic-gate 	    //  any.
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 	    Hashtable services =
9787c478bd9Sstevel@tonic-gate 		(Hashtable)returns.get(ServiceStore.FS_SERVICES);
9797c478bd9Sstevel@tonic-gate 	    Hashtable signatures =
9807c478bd9Sstevel@tonic-gate 		(Hashtable)returns.get(ServiceStore.FS_SIGTABLE);
9817c478bd9Sstevel@tonic-gate 	    boolean hasSignatures = (signatures != null);
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate 	    // for each candidate URL, make sure it has the requested SPI
9847c478bd9Sstevel@tonic-gate 	    // (if any)
9857c478bd9Sstevel@tonic-gate 	    if (hasSignatures && !req.spi.equals("")) {
9867c478bd9Sstevel@tonic-gate 		Enumeration allSurls = services.keys();
9877c478bd9Sstevel@tonic-gate 		while (allSurls.hasMoreElements()) {
9887c478bd9Sstevel@tonic-gate 		    Object aSurl = allSurls.nextElement();
9897c478bd9Sstevel@tonic-gate 		    Hashtable auths = (Hashtable) signatures.get(aSurl);
9907c478bd9Sstevel@tonic-gate 		    AuthBlock auth =
9917c478bd9Sstevel@tonic-gate 			AuthBlock.getEquivalentAuth(req.spi, auths);
9927c478bd9Sstevel@tonic-gate 		    if (auth == null) {
9937c478bd9Sstevel@tonic-gate 			// doesn't have the requested SPI
9947c478bd9Sstevel@tonic-gate 			services.remove(aSurl);
9957c478bd9Sstevel@tonic-gate 		    }
9967c478bd9Sstevel@tonic-gate 		}
9977c478bd9Sstevel@tonic-gate 	    }
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate 	    // Create return message.
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 	    SrvLocMsg ack = req.makeReply(services, signatures);
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 	    if (conf.traceAll()) {
10047c478bd9Sstevel@tonic-gate 		conf.writeLog("st_sreq",
10057c478bd9Sstevel@tonic-gate 			      new Object[] {
10067c478bd9Sstevel@tonic-gate 		    locationMsg,
10077c478bd9Sstevel@tonic-gate 			serviceType,
10087c478bd9Sstevel@tonic-gate 			scopes,
10097c478bd9Sstevel@tonic-gate 			query,
10107c478bd9Sstevel@tonic-gate 			locale,
10117c478bd9Sstevel@tonic-gate 			services,
10127c478bd9Sstevel@tonic-gate 			signatures});
10137c478bd9Sstevel@tonic-gate 	    }
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 	    return ack;
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate 	    if (conf.traceDrop()) {
10207c478bd9Sstevel@tonic-gate 		conf.writeLog("st_sreq_drop",
10217c478bd9Sstevel@tonic-gate 			      new Object[] {
10227c478bd9Sstevel@tonic-gate 		    locationMsg,
10237c478bd9Sstevel@tonic-gate 			ex.getMessage()+"("+ex.getErrorCode()+")",
10247c478bd9Sstevel@tonic-gate 			serviceType,
10257c478bd9Sstevel@tonic-gate 			scopes,
10267c478bd9Sstevel@tonic-gate 			query,
10277c478bd9Sstevel@tonic-gate 			locale});
10287c478bd9Sstevel@tonic-gate 	    }
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	} catch (RuntimeException ex) {
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 	    // These exceptions are not declared in throws but can occur
10357c478bd9Sstevel@tonic-gate 	    //  anywhere.
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	    Vector args = new Vector();
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate 	    args.addElement(req);
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 	    reportNonfatalException(ex, args, store);
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	}
10467c478bd9Sstevel@tonic-gate     }
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate     /**
10497c478bd9Sstevel@tonic-gate      * Process the attribute request and return the result in a reply.
10507c478bd9Sstevel@tonic-gate      *
10517c478bd9Sstevel@tonic-gate      * @param req Attribute request message.
10527c478bd9Sstevel@tonic-gate      * @return AttrRply An attribute reply.
10537c478bd9Sstevel@tonic-gate      */
10547c478bd9Sstevel@tonic-gate 
findAttributes(SAttrMsg req)10557c478bd9Sstevel@tonic-gate     SrvLocMsg findAttributes(SAttrMsg req) {
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 	// We need to determine whether this is a request for attributes
10587c478bd9Sstevel@tonic-gate 	//  on a specific URL or for an entire service type.
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 	SrvLocHeader hdr = req.getHeader();
10617c478bd9Sstevel@tonic-gate 	Vector scopes = hdr.scopes;
10627c478bd9Sstevel@tonic-gate 	Locale locale = hdr.locale;
10637c478bd9Sstevel@tonic-gate 	ServiceURL surl = req.URL;
10647c478bd9Sstevel@tonic-gate 	String serviceType = req.serviceType;
10657c478bd9Sstevel@tonic-gate 	Vector tags = req.tags;
10667c478bd9Sstevel@tonic-gate 	short errorCode = ServiceLocationException.OK;
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 	try {
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate 	    // Check whether the scope is supported.
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 	    if (!areSupportedScopes(scopes)) {
10737c478bd9Sstevel@tonic-gate 	throw
10747c478bd9Sstevel@tonic-gate 	    new ServiceLocationException(
10757c478bd9Sstevel@tonic-gate 				ServiceLocationException.SCOPE_NOT_SUPPORTED,
10767c478bd9Sstevel@tonic-gate 				"st_scope_unsup",
10777c478bd9Sstevel@tonic-gate 				new Object[0]);
10787c478bd9Sstevel@tonic-gate 	    }
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 	    Vector attributes = null;
10817c478bd9Sstevel@tonic-gate 	    Hashtable sig = null;
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	    // If it's a service URL, then get the attributes just for
10847c478bd9Sstevel@tonic-gate 	    // that URL.
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	    if (serviceType == null) {
10877c478bd9Sstevel@tonic-gate 
10887c478bd9Sstevel@tonic-gate 		// If the attrs are signed, then error if any tags, since
10897c478bd9Sstevel@tonic-gate 		//  we must ask for *all* attributes in for a signed reg
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 		if (!req.spi.equals("") && tags.size() > 0) {
10927c478bd9Sstevel@tonic-gate 		    throw
10937c478bd9Sstevel@tonic-gate 			new ServiceLocationException(
10947c478bd9Sstevel@tonic-gate 				ServiceLocationException.AUTHENTICATION_FAILED,
10957c478bd9Sstevel@tonic-gate 				"st_par_attr",
10967c478bd9Sstevel@tonic-gate 				new Object[0]);
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 		}
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 		Hashtable ht =
11017c478bd9Sstevel@tonic-gate 		    store.findAttributes(surl, scopes, tags, locale);
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 		// Get the attributes and signatures.
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate 		attributes = (Vector)ht.get(ServiceStore.FA_ATTRIBUTES);
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 		sig = (Hashtable)ht.get(ServiceStore.FA_SIG);
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 		// make sure the attr has the requested SPI (if any)
11107c478bd9Sstevel@tonic-gate 		if (sig != null && !req.spi.equals("")) {
11117c478bd9Sstevel@tonic-gate 		    AuthBlock auth = AuthBlock.getEquivalentAuth(req.spi, sig);
11127c478bd9Sstevel@tonic-gate 		    if (auth == null) {
11137c478bd9Sstevel@tonic-gate 			// return empty
11147c478bd9Sstevel@tonic-gate 			attributes = new Vector();
11157c478bd9Sstevel@tonic-gate 		    }
11167c478bd9Sstevel@tonic-gate 		}
1117*55fea89dSDan Cross 
11187c478bd9Sstevel@tonic-gate 	    } else {
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 		if (!req.spi.equals("")) {
11217c478bd9Sstevel@tonic-gate 		    throw
11227c478bd9Sstevel@tonic-gate 			new ServiceLocationException(
11237c478bd9Sstevel@tonic-gate 				ServiceLocationException.AUTHENTICATION_FAILED,
11247c478bd9Sstevel@tonic-gate 				"st_par_attr",
11257c478bd9Sstevel@tonic-gate 				new Object[0]);
11267c478bd9Sstevel@tonic-gate 		}
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate 		// Otherwise find the attributes for all service types.
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 		attributes =
11317c478bd9Sstevel@tonic-gate 		    store.findAttributes(serviceType, scopes, tags, locale);
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate 	    }
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 	    ServiceType type =
11367c478bd9Sstevel@tonic-gate 		(serviceType == null ? surl.getServiceType():
11377c478bd9Sstevel@tonic-gate 		 new ServiceType(serviceType));
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate 	    // Create the reply.
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 	    SrvLocMsg ack = req.makeReply(attributes, sig);
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate 	    if (conf.traceAll()) {
11457c478bd9Sstevel@tonic-gate 		conf.writeLog((serviceType != null ?
11467c478bd9Sstevel@tonic-gate 			       "st_st_attr" : "st_url_attr"),
11477c478bd9Sstevel@tonic-gate 			      new Object[] {
11487c478bd9Sstevel@tonic-gate 		    locationMsg,
11497c478bd9Sstevel@tonic-gate 			(serviceType != null ? serviceType.toString() :
11507c478bd9Sstevel@tonic-gate 			 surl.toString()),
11517c478bd9Sstevel@tonic-gate 		      	scopes,
11527c478bd9Sstevel@tonic-gate 			tags,
11537c478bd9Sstevel@tonic-gate 			locale,
11547c478bd9Sstevel@tonic-gate 			attributes});
11557c478bd9Sstevel@tonic-gate 	    }
11567c478bd9Sstevel@tonic-gate 
11577c478bd9Sstevel@tonic-gate 	    return ack;
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 	    if (conf.traceDrop()) {
11627c478bd9Sstevel@tonic-gate 		conf.writeLog((serviceType != null ? "st_st_attr_drop":
11637c478bd9Sstevel@tonic-gate 			       "st_url_attr_drop"),
11647c478bd9Sstevel@tonic-gate 			      new Object[] {
11657c478bd9Sstevel@tonic-gate 		    locationMsg,
11667c478bd9Sstevel@tonic-gate 			ex.getMessage()+"("+ex.getErrorCode()+")",
11677c478bd9Sstevel@tonic-gate 		        (serviceType != null ? serviceType.toString() :
11687c478bd9Sstevel@tonic-gate 			 surl.toString()),
11697c478bd9Sstevel@tonic-gate 		        scopes,
11707c478bd9Sstevel@tonic-gate 			tags,
11717c478bd9Sstevel@tonic-gate 			locale});
11727c478bd9Sstevel@tonic-gate 	    }
11737c478bd9Sstevel@tonic-gate 
11747c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate 	} catch (RuntimeException ex) {
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 	    // These exceptions are not declared in throws but can occur
11797c478bd9Sstevel@tonic-gate 	    //  anywhere.
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 	    Vector args = new Vector();
11827c478bd9Sstevel@tonic-gate 
11837c478bd9Sstevel@tonic-gate 	    args.addElement(req);
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	    reportNonfatalException(ex, args, store);
11867c478bd9Sstevel@tonic-gate 
11877c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
11887c478bd9Sstevel@tonic-gate 
11897c478bd9Sstevel@tonic-gate 	}
11907c478bd9Sstevel@tonic-gate     }
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate     // Return the service record corresponding to the URL.
11937c478bd9Sstevel@tonic-gate 
getServiceRecord(ServiceURL URL, Locale locale)11947c478bd9Sstevel@tonic-gate     ServiceStore.ServiceRecord getServiceRecord(ServiceURL URL,
11957c478bd9Sstevel@tonic-gate 						Locale locale) {
11967c478bd9Sstevel@tonic-gate 	return store.getServiceRecord(URL, locale);
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate     }
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate     //
12017c478bd9Sstevel@tonic-gate     // Utility methods.
12027c478bd9Sstevel@tonic-gate     //
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate     //
12057c478bd9Sstevel@tonic-gate     //  Protected/private methods.
12067c478bd9Sstevel@tonic-gate     //
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate     // Check whether the type is restricted, through an exception if so.
12097c478bd9Sstevel@tonic-gate 
checkForRestrictedType(ServiceType type)12107c478bd9Sstevel@tonic-gate     private void checkForRestrictedType(ServiceType type)
12117c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate 	if (Defaults.restrictedTypes.contains(type)) {
12147c478bd9Sstevel@tonic-gate 	    throw
12157c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
12167c478bd9Sstevel@tonic-gate 				ServiceLocationException.INVALID_REGISTRATION,
12177c478bd9Sstevel@tonic-gate 				"st_restricted_type",
12187c478bd9Sstevel@tonic-gate 				new Object[] {type});
12197c478bd9Sstevel@tonic-gate 	}
12207c478bd9Sstevel@tonic-gate     }
12217c478bd9Sstevel@tonic-gate 
12227c478bd9Sstevel@tonic-gate     // Insert a record for type "service-agent" with attributes having
12237c478bd9Sstevel@tonic-gate     //  the types currently supported, if the new URL is not on the
12247c478bd9Sstevel@tonic-gate     //  list of supported types. This allows us to perform queries
12257c478bd9Sstevel@tonic-gate     //  for supported service types.
12267c478bd9Sstevel@tonic-gate 
trackRegisteredServiceTypes()12277c478bd9Sstevel@tonic-gate     private void trackRegisteredServiceTypes()
12287c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate 	// First find the types.
12317c478bd9Sstevel@tonic-gate 
12327c478bd9Sstevel@tonic-gate 	Vector types = store.findServiceTypes(Defaults.ALL_AUTHORITIES,
12337c478bd9Sstevel@tonic-gate 					      conf.getSAConfiguredScopes());
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate 	// Get preconfigured attributes.
12367c478bd9Sstevel@tonic-gate 
12377c478bd9Sstevel@tonic-gate 	Vector attrs = conf.getSAAttributes();
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate 	// Make an attribute with the service types.
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 	ServiceLocationAttribute attr =
12427c478bd9Sstevel@tonic-gate 	    new ServiceLocationAttribute(Defaults.SERVICE_TYPE_ATTR_ID,
12437c478bd9Sstevel@tonic-gate 					 types);
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 	attrs.addElement(attr);
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 	// Construct URL to use on all interfaces.
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	Vector interfaces = conf.getInterfaces();
12507c478bd9Sstevel@tonic-gate 	int i, n = interfaces.size();
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
12537c478bd9Sstevel@tonic-gate 	    InetAddress addr = (InetAddress)interfaces.elementAt(i);
12547c478bd9Sstevel@tonic-gate 	    ServiceURL url =
12557c478bd9Sstevel@tonic-gate 		new ServiceURL(Defaults.SUN_SA_SERVICE_TYPE + "://" +
12567c478bd9Sstevel@tonic-gate 			       addr.getHostAddress(),
12577c478bd9Sstevel@tonic-gate 			       ServiceURL.LIFETIME_MAXIMUM);
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 	    Vector scopes = conf.getSAOnlyScopes();
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 	    Locale locale = Defaults.locale;
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 	    // Make a new registration for this SA.
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 	    store.register(url,
12667c478bd9Sstevel@tonic-gate 			   attrs,
12677c478bd9Sstevel@tonic-gate 			   scopes,
12687c478bd9Sstevel@tonic-gate 			   locale,
12697c478bd9Sstevel@tonic-gate 			   null,
12707c478bd9Sstevel@tonic-gate 			   null);  // we could sign, but we do that later...
12717c478bd9Sstevel@tonic-gate 	}
12727c478bd9Sstevel@tonic-gate 
12737c478bd9Sstevel@tonic-gate 	// Note that we don't need a refresh on the URLs because they
12747c478bd9Sstevel@tonic-gate 	//  will get refreshed when the service URLs that they track
12757c478bd9Sstevel@tonic-gate 	//  are refreshed. If the tracked URLs aren't refreshed, then
12767c478bd9Sstevel@tonic-gate 	//  these will get updated when the tracked URLs age out.
12777c478bd9Sstevel@tonic-gate     }
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate     // Return true if the scopes in the vector are supported by the DA
12807c478bd9Sstevel@tonic-gate     //  or SA server.
12817c478bd9Sstevel@tonic-gate 
areSupportedScopes(Vector scopes)12827c478bd9Sstevel@tonic-gate     final private boolean areSupportedScopes(Vector scopes) {
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 	Vector configuredScopes = conf.getSAConfiguredScopes();
12857c478bd9Sstevel@tonic-gate 	Vector saOnlyScopes = conf.getSAOnlyScopes();
12867c478bd9Sstevel@tonic-gate 	int i = 0;
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate 	while (i < scopes.size()) {
12897c478bd9Sstevel@tonic-gate 	    Object o = scopes.elementAt(i);
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 	    // Remove it if we don't support it.
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate 	    if (!configuredScopes.contains(o) && !saOnlyScopes.contains(o)) {
12947c478bd9Sstevel@tonic-gate 		// This will shift the Vector's elements down one, so
12957c478bd9Sstevel@tonic-gate 		// don't increment i
12967c478bd9Sstevel@tonic-gate 		scopes.removeElementAt(i);
12977c478bd9Sstevel@tonic-gate 	    } else {
12987c478bd9Sstevel@tonic-gate 		i++;
12997c478bd9Sstevel@tonic-gate 	    }
13007c478bd9Sstevel@tonic-gate 	}
13017c478bd9Sstevel@tonic-gate 
13027c478bd9Sstevel@tonic-gate 	if (scopes.size() <= 0) {
13037c478bd9Sstevel@tonic-gate 	    return false;
13047c478bd9Sstevel@tonic-gate 
13057c478bd9Sstevel@tonic-gate 	}
13067c478bd9Sstevel@tonic-gate 
13077c478bd9Sstevel@tonic-gate 	return true;
13087c478bd9Sstevel@tonic-gate     }
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate     /**
13117c478bd9Sstevel@tonic-gate      * Return the sleep increment from the URL lifetime. Used by the
13127c478bd9Sstevel@tonic-gate      * ServiceStore to calculate the new sleep interval in addition
13137c478bd9Sstevel@tonic-gate      * to this class, when a new URL comes in. The algorithm
13147c478bd9Sstevel@tonic-gate      * subtracts x% of the lifetime from the lifetime and schedules the
13157c478bd9Sstevel@tonic-gate      * timeout at that time.
13167c478bd9Sstevel@tonic-gate      *
13177c478bd9Sstevel@tonic-gate      * @param url The URL to use for calculation.
13187c478bd9Sstevel@tonic-gate      * @return The sleep interval.
13197c478bd9Sstevel@tonic-gate      */
13207c478bd9Sstevel@tonic-gate 
getSleepIncrement(ServiceURL url)13217c478bd9Sstevel@tonic-gate     private long getSleepIncrement(ServiceURL url) {
13227c478bd9Sstevel@tonic-gate 	long urlLifetime = (long)(url.getLifetime() * 1000);
13237c478bd9Sstevel@tonic-gate 	long increment =
13247c478bd9Sstevel@tonic-gate 	    (long)((float)urlLifetime * Defaults.fRefreshGranularity);
13257c478bd9Sstevel@tonic-gate 	long sTime = urlLifetime - increment;
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 	// If URL lives only one second, update every half second.
13287c478bd9Sstevel@tonic-gate 
13297c478bd9Sstevel@tonic-gate 	if (sTime <= 0) {
13307c478bd9Sstevel@tonic-gate 	    sTime = 500;
13317c478bd9Sstevel@tonic-gate 
13327c478bd9Sstevel@tonic-gate 	}
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate 	return sTime;
13357c478bd9Sstevel@tonic-gate     }
13367c478bd9Sstevel@tonic-gate 
13377c478bd9Sstevel@tonic-gate     // Make a DAADvert for the DA service request. This only applies
13387c478bd9Sstevel@tonic-gate     //  to DAs, not to SA servers.
13397c478bd9Sstevel@tonic-gate 
13407c478bd9Sstevel@tonic-gate     SrvLocMsg
makeDAAdvert(SSrvMsg rqst, InetAddress daAddr, SLPConfig conf)13417c478bd9Sstevel@tonic-gate 	makeDAAdvert(SSrvMsg rqst,
13427c478bd9Sstevel@tonic-gate 		     InetAddress daAddr,
13437c478bd9Sstevel@tonic-gate 		     SLPConfig conf) {
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 	SrvLocHeader hdr = rqst.getHeader();
13467c478bd9Sstevel@tonic-gate 	Vector scopes = hdr.scopes;
13477c478bd9Sstevel@tonic-gate 	short xid = hdr.xid;
13487c478bd9Sstevel@tonic-gate 	String query = rqst.query;
13497c478bd9Sstevel@tonic-gate 
13507c478bd9Sstevel@tonic-gate 	try {
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate 	    // If security is on, proceed only if we can sign as rqst.spi
13537c478bd9Sstevel@tonic-gate 	    if (conf.getHasSecurity() && !AuthBlock.canSignAs(rqst.spi)) {
13547c478bd9Sstevel@tonic-gate 		throw new ServiceLocationException(
13557c478bd9Sstevel@tonic-gate 			ServiceLocationException.AUTHENTICATION_UNKNOWN,
13567c478bd9Sstevel@tonic-gate 			"st_cant_sign_as",
13577c478bd9Sstevel@tonic-gate 			new Object[] {rqst.spi});
13587c478bd9Sstevel@tonic-gate 	    }
13597c478bd9Sstevel@tonic-gate 
13607c478bd9Sstevel@tonic-gate 	    // Get the hashtable of service URLs v.s. scopes.
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate 	    Hashtable services =
13637c478bd9Sstevel@tonic-gate 		ServerDATable.getServerDATable().returnMatchingDAs(query);
13647c478bd9Sstevel@tonic-gate 
13657c478bd9Sstevel@tonic-gate 	    // Go through the table checking whether the IP address came back.
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 	    Enumeration urls = services.keys();
13687c478bd9Sstevel@tonic-gate 	    boolean foundIt = false;
13697c478bd9Sstevel@tonic-gate 	    String strDAAddr = daAddr.getHostAddress();
13707c478bd9Sstevel@tonic-gate 
13717c478bd9Sstevel@tonic-gate 	    while (urls.hasMoreElements()) {
13727c478bd9Sstevel@tonic-gate 		ServiceURL url = (ServiceURL)urls.nextElement();
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate 		if (url.getHost().equals(strDAAddr)) {
13757c478bd9Sstevel@tonic-gate 		    foundIt = true;
13767c478bd9Sstevel@tonic-gate 		    break;
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate 		}
13797c478bd9Sstevel@tonic-gate 	    }
13807c478bd9Sstevel@tonic-gate 
13817c478bd9Sstevel@tonic-gate 	    // If we didn't find anything, make a null service reply.
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate 	    if (!foundIt) {
13847c478bd9Sstevel@tonic-gate 		return rqst.makeReply(new Hashtable(), new Hashtable());
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate 	    }
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate 	    return makeDAAdvert(hdr, daAddr, xid, scopes, conf);
13897c478bd9Sstevel@tonic-gate 
13907c478bd9Sstevel@tonic-gate 
13917c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
13927c478bd9Sstevel@tonic-gate 
13937c478bd9Sstevel@tonic-gate 	    return hdr.makeErrorReply(ex);
13947c478bd9Sstevel@tonic-gate 
13957c478bd9Sstevel@tonic-gate 	}
13967c478bd9Sstevel@tonic-gate 
13977c478bd9Sstevel@tonic-gate     }
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate     // Make a DAAdvert from the input arguments.
14007c478bd9Sstevel@tonic-gate     SrvLocMsg
makeDAAdvert(SrvLocHeader hdr, InetAddress daAddr, short xid, Vector scopes, SLPConfig config)14017c478bd9Sstevel@tonic-gate 	makeDAAdvert(SrvLocHeader hdr,
14027c478bd9Sstevel@tonic-gate 		     InetAddress daAddr,
14037c478bd9Sstevel@tonic-gate 		     short xid,
14047c478bd9Sstevel@tonic-gate 		     Vector scopes,
14057c478bd9Sstevel@tonic-gate 		     SLPConfig config)
14067c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 	// If this is a request for a V1 Advert, truncate the scopes vector
14097c478bd9Sstevel@tonic-gate 	//  since DA solicitations in V1 are always unscoped
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 	if (hdr.version == 1) {
14127c478bd9Sstevel@tonic-gate 	    scopes = new Vector();
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate 	}
14157c478bd9Sstevel@tonic-gate 
14167c478bd9Sstevel@tonic-gate 	// Check if we support scopes first. If not, return an
14177c478bd9Sstevel@tonic-gate 	//  error reply unless the scope vector is zero. Upper layers
14187c478bd9Sstevel@tonic-gate 	//  must sort out whether this is a unicast or multicast.
1419*55fea89dSDan Cross 
14207c478bd9Sstevel@tonic-gate 	if (scopes.size() > 0 && !areSupportedScopes(scopes)) {
14217c478bd9Sstevel@tonic-gate 	    throw
14227c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
14237c478bd9Sstevel@tonic-gate 				ServiceLocationException.SCOPE_NOT_SUPPORTED,
14247c478bd9Sstevel@tonic-gate 				"st_scope_unsup",
14257c478bd9Sstevel@tonic-gate 				new Object[0]);
14267c478bd9Sstevel@tonic-gate 
14277c478bd9Sstevel@tonic-gate 	}
14287c478bd9Sstevel@tonic-gate 
14297c478bd9Sstevel@tonic-gate 	// Get the service store's timestamp. This must be the
14307c478bd9Sstevel@tonic-gate 	//  time since last stateless reboot for a stateful store,
14317c478bd9Sstevel@tonic-gate 	//  or the current time.
14327c478bd9Sstevel@tonic-gate 
14337c478bd9Sstevel@tonic-gate 	long timestamp = store.getStateTimestamp();
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate 	ServiceURL url =
14367c478bd9Sstevel@tonic-gate 	    new ServiceURL(Defaults.DA_SERVICE_TYPE + "://" +
14377c478bd9Sstevel@tonic-gate 			   daAddr.getHostAddress(),
14387c478bd9Sstevel@tonic-gate 			   ServiceURL.LIFETIME_DEFAULT);
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate 	SDAAdvert advert =
14417c478bd9Sstevel@tonic-gate 	    hdr.getDAAdvert(xid,
14427c478bd9Sstevel@tonic-gate 			    timestamp,
14437c478bd9Sstevel@tonic-gate 			    url,
14447c478bd9Sstevel@tonic-gate 			    scopes,
14457c478bd9Sstevel@tonic-gate 			    conf.getDAAttributes());
14467c478bd9Sstevel@tonic-gate 
14477c478bd9Sstevel@tonic-gate 	return advert;
14487c478bd9Sstevel@tonic-gate     }
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate     // Make a SAADvert for the SA service request. This only applies
14517c478bd9Sstevel@tonic-gate     //  to SA servers, not DA's. Note that we only advertise the "public"
14527c478bd9Sstevel@tonic-gate     //  scopes, not the private ones.
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate     SSAAdvert
makeSAAdvert(SSrvMsg rqst, InetAddress interfac, SLPConfig conf)14557c478bd9Sstevel@tonic-gate 	makeSAAdvert(SSrvMsg rqst,
14567c478bd9Sstevel@tonic-gate 		     InetAddress interfac,
14577c478bd9Sstevel@tonic-gate 		     SLPConfig conf)
14587c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
14597c478bd9Sstevel@tonic-gate 	SrvLocHeader hdr = rqst.getHeader();
14607c478bd9Sstevel@tonic-gate 	int version = hdr.version;
14617c478bd9Sstevel@tonic-gate 	short xid = hdr.xid;
14627c478bd9Sstevel@tonic-gate 	Locale locale = hdr.locale;
14637c478bd9Sstevel@tonic-gate 	Vector scopes = hdr.scopes;
14647c478bd9Sstevel@tonic-gate 	String query = rqst.query;
14657c478bd9Sstevel@tonic-gate 	String serviceType = rqst.serviceType;
14667c478bd9Sstevel@tonic-gate 	Vector saOnlyScopes = conf.getSAOnlyScopes();
14677c478bd9Sstevel@tonic-gate 
14687c478bd9Sstevel@tonic-gate 	// If security is on, proceed only if we can sign as rqst.spi
14697c478bd9Sstevel@tonic-gate 	if (conf.getHasSecurity() && !AuthBlock.canSignAs(rqst.spi)) {
14707c478bd9Sstevel@tonic-gate 	    throw new ServiceLocationException(
14717c478bd9Sstevel@tonic-gate 			ServiceLocationException.AUTHENTICATION_UNKNOWN,
14727c478bd9Sstevel@tonic-gate 			"st_cant_sign_as",
14737c478bd9Sstevel@tonic-gate 			new Object[] {rqst.spi});
14747c478bd9Sstevel@tonic-gate 	}
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate 
14777c478bd9Sstevel@tonic-gate 	// Check if we support scopes first. Note that this may allow
14787c478bd9Sstevel@tonic-gate 	//  someone to get at the SA only scopes off machine, but that's
14797c478bd9Sstevel@tonic-gate 	//  OK. Since the SAAdvert is only ever multicast, this is OK.
14807c478bd9Sstevel@tonic-gate 
14817c478bd9Sstevel@tonic-gate 	if (!areSupportedScopes(scopes) && !(scopes.size() <= 0)) {
14827c478bd9Sstevel@tonic-gate 	    return null;
14837c478bd9Sstevel@tonic-gate 
14847c478bd9Sstevel@tonic-gate 	}
14857c478bd9Sstevel@tonic-gate 
14867c478bd9Sstevel@tonic-gate 	// If the scopes vector is null, then use all configured scopes.
14877c478bd9Sstevel@tonic-gate 
14887c478bd9Sstevel@tonic-gate 	if (scopes.size() <= 0) {
14897c478bd9Sstevel@tonic-gate 	    scopes = (Vector)conf.getSAConfiguredScopes().clone();
14907c478bd9Sstevel@tonic-gate 
14917c478bd9Sstevel@tonic-gate 	}
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate 	// Check to be sure the query matches.
14947c478bd9Sstevel@tonic-gate 	//  If it doesn't, we don't need to return anything.
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate 	Hashtable returns =
14977c478bd9Sstevel@tonic-gate 	    store.findServices(Defaults.SUN_SA_SERVICE_TYPE.toString(),
14987c478bd9Sstevel@tonic-gate 			       saOnlyScopes,
14997c478bd9Sstevel@tonic-gate 			       query,
15007c478bd9Sstevel@tonic-gate 			       Defaults.locale);
15017c478bd9Sstevel@tonic-gate 	Hashtable services =
15027c478bd9Sstevel@tonic-gate 	    (Hashtable)returns.get(ServiceStore.FS_SERVICES);
15037c478bd9Sstevel@tonic-gate 	Enumeration en = services.keys();
15047c478bd9Sstevel@tonic-gate 
15057c478bd9Sstevel@tonic-gate 	// Indicates we don't support the service type.
15067c478bd9Sstevel@tonic-gate 
15077c478bd9Sstevel@tonic-gate 	if (!en.hasMoreElements()) {
15087c478bd9Sstevel@tonic-gate 	    return null;
15097c478bd9Sstevel@tonic-gate 
15107c478bd9Sstevel@tonic-gate 	}
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 	// Find the URL to use. The interface on which the message came in
15137c478bd9Sstevel@tonic-gate 	//  needs to match one of the registered URLs.
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 	ServiceURL url = null;
15167c478bd9Sstevel@tonic-gate 	ServiceURL surl = null;
15177c478bd9Sstevel@tonic-gate 	String addr = interfac.getHostAddress();
15187c478bd9Sstevel@tonic-gate 
15197c478bd9Sstevel@tonic-gate 	while (en.hasMoreElements()) {
15207c478bd9Sstevel@tonic-gate 	    surl = (ServiceURL)en.nextElement();
15217c478bd9Sstevel@tonic-gate 
15227c478bd9Sstevel@tonic-gate 	    if (addr.equals(surl.getHost())) {
15237c478bd9Sstevel@tonic-gate 		url = new ServiceURL(Defaults.SA_SERVICE_TYPE + "://" +
15247c478bd9Sstevel@tonic-gate 				     addr,
15257c478bd9Sstevel@tonic-gate 				     ServiceURL.LIFETIME_DEFAULT);
15267c478bd9Sstevel@tonic-gate 		break;
15277c478bd9Sstevel@tonic-gate 	    }
15287c478bd9Sstevel@tonic-gate 	}
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate 	// If none of the URLs matched this interface, then return null.
15317c478bd9Sstevel@tonic-gate 
15327c478bd9Sstevel@tonic-gate 	if (url == null) {
15337c478bd9Sstevel@tonic-gate 	    return null;
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate 	}
15367c478bd9Sstevel@tonic-gate 
15377c478bd9Sstevel@tonic-gate 	// Find the SA's attributes.
15387c478bd9Sstevel@tonic-gate 
15397c478bd9Sstevel@tonic-gate 	Hashtable ht =
15407c478bd9Sstevel@tonic-gate 	    store.findAttributes(surl,
15417c478bd9Sstevel@tonic-gate 				 saOnlyScopes,
15427c478bd9Sstevel@tonic-gate 				 new Vector(),
15437c478bd9Sstevel@tonic-gate 				 Defaults.locale);
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate 	Vector attrs = (Vector)ht.get(ServiceStore.FA_ATTRIBUTES);
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate 	// Construct return.
15487c478bd9Sstevel@tonic-gate 
15497c478bd9Sstevel@tonic-gate 	return
15507c478bd9Sstevel@tonic-gate 	    new SSAAdvert(version,
15517c478bd9Sstevel@tonic-gate 			  xid,
15527c478bd9Sstevel@tonic-gate 			  locale,
15537c478bd9Sstevel@tonic-gate 			  url,
15547c478bd9Sstevel@tonic-gate 			  conf.getSAConfiguredScopes(), // report all scopes...
15557c478bd9Sstevel@tonic-gate 			  attrs);
15567c478bd9Sstevel@tonic-gate     }
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate     /**
15597c478bd9Sstevel@tonic-gate      * Report a fatal exception to the log.
15607c478bd9Sstevel@tonic-gate      *
15617c478bd9Sstevel@tonic-gate      * @param ex The exception to report.
15627c478bd9Sstevel@tonic-gate      */
15637c478bd9Sstevel@tonic-gate 
reportFatalException(Exception ex)15647c478bd9Sstevel@tonic-gate     protected static void reportFatalException(Exception ex) {
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate 	reportException(true, ex, new Vector());
15677c478bd9Sstevel@tonic-gate 
15687c478bd9Sstevel@tonic-gate 	if (table != null) {
15697c478bd9Sstevel@tonic-gate 	    table.store.dumpServiceStore();
15707c478bd9Sstevel@tonic-gate 	}
15717c478bd9Sstevel@tonic-gate 
15727c478bd9Sstevel@tonic-gate 	conf.writeLog("exiting_msg", new Object[0]);
15737c478bd9Sstevel@tonic-gate 
15747c478bd9Sstevel@tonic-gate 	System.exit(1);
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate     }
15777c478bd9Sstevel@tonic-gate 
15787c478bd9Sstevel@tonic-gate     /**
15797c478bd9Sstevel@tonic-gate      * Report a nonfatal exception to the log.
15807c478bd9Sstevel@tonic-gate      *
15817c478bd9Sstevel@tonic-gate      * @param ex The exception to report.
15827c478bd9Sstevel@tonic-gate      * @param args The method arguments.
15837c478bd9Sstevel@tonic-gate      * @param store The service store being processed.
15847c478bd9Sstevel@tonic-gate      */
15857c478bd9Sstevel@tonic-gate 
reportNonfatalException(Exception ex, Vector args, ServiceStore store)15867c478bd9Sstevel@tonic-gate     protected static void reportNonfatalException(Exception ex,
15877c478bd9Sstevel@tonic-gate 						  Vector args,
15887c478bd9Sstevel@tonic-gate 						  ServiceStore store) {
15897c478bd9Sstevel@tonic-gate 
15907c478bd9Sstevel@tonic-gate 	reportException(false, ex, args);
15917c478bd9Sstevel@tonic-gate 
15927c478bd9Sstevel@tonic-gate 	if (conf.traceAll()) {
15937c478bd9Sstevel@tonic-gate 	    store.dumpServiceStore();
15947c478bd9Sstevel@tonic-gate 	}
15957c478bd9Sstevel@tonic-gate 
15967c478bd9Sstevel@tonic-gate     }
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate     /**
15997c478bd9Sstevel@tonic-gate      * Report an exception to the log.
16007c478bd9Sstevel@tonic-gate      *
16017c478bd9Sstevel@tonic-gate      * @param isFatal Indicates whether the exception is fatal or not.
16027c478bd9Sstevel@tonic-gate      * @param ex The exception to report.
16037c478bd9Sstevel@tonic-gate      * @param args A potentially null vector of arguments to the
16047c478bd9Sstevel@tonic-gate      * 			method where the exception was caught.
16057c478bd9Sstevel@tonic-gate      */
16067c478bd9Sstevel@tonic-gate 
16077c478bd9Sstevel@tonic-gate     private static void
reportException(boolean isFatal, Exception ex, Vector args)16087c478bd9Sstevel@tonic-gate 	reportException(boolean isFatal, Exception ex, Vector args) {
16097c478bd9Sstevel@tonic-gate 
16107c478bd9Sstevel@tonic-gate 	StringWriter sw = new StringWriter();
16117c478bd9Sstevel@tonic-gate 	PrintWriter writer = new PrintWriter(sw);
16127c478bd9Sstevel@tonic-gate 
16137c478bd9Sstevel@tonic-gate 	// Get the backtrace.
16147c478bd9Sstevel@tonic-gate 
16157c478bd9Sstevel@tonic-gate 	ex.printStackTrace(writer);
16167c478bd9Sstevel@tonic-gate 
16177c478bd9Sstevel@tonic-gate 	String severity = (isFatal ? "fatal_error":"nonfatal_error");
16187c478bd9Sstevel@tonic-gate 	String msg = ex.getMessage();
16197c478bd9Sstevel@tonic-gate 
16207c478bd9Sstevel@tonic-gate 	if (msg == null) {
16217c478bd9Sstevel@tonic-gate 	    msg = conf.formatMessage("no_message", new Object[0]);
16227c478bd9Sstevel@tonic-gate 
16237c478bd9Sstevel@tonic-gate 	} else if (ex instanceof ServiceLocationException) {
16247c478bd9Sstevel@tonic-gate 	    msg = msg +
16257c478bd9Sstevel@tonic-gate 		"(" + ((ServiceLocationException)ex).getErrorCode() + ")";
16267c478bd9Sstevel@tonic-gate 
16277c478bd9Sstevel@tonic-gate 	}
16287c478bd9Sstevel@tonic-gate 
16297c478bd9Sstevel@tonic-gate 	StringBuffer argMsg = new StringBuffer();
16307c478bd9Sstevel@tonic-gate 
16317c478bd9Sstevel@tonic-gate 	int i, n = args.size();
16327c478bd9Sstevel@tonic-gate 
16337c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
16347c478bd9Sstevel@tonic-gate 	    argMsg.append("\n        (" + Integer.toString(i) + "):" +
16357c478bd9Sstevel@tonic-gate 			  args.elementAt(i).toString());
16367c478bd9Sstevel@tonic-gate 	}
16377c478bd9Sstevel@tonic-gate 
16387c478bd9Sstevel@tonic-gate 	conf.writeLog(severity,
16397c478bd9Sstevel@tonic-gate 		      new Object[] {
16407c478bd9Sstevel@tonic-gate 	    ex.getClass().getName(),
16417c478bd9Sstevel@tonic-gate 		msg,
16427c478bd9Sstevel@tonic-gate 		argMsg,
16437c478bd9Sstevel@tonic-gate 		sw.toString()});
16447c478bd9Sstevel@tonic-gate 
16457c478bd9Sstevel@tonic-gate     }
16467c478bd9Sstevel@tonic-gate }
1647