10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7298SMark.J.Nelson@Sun.COM * Common Development and Distribution License (the "License"). 6*7298SMark.J.Nelson@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 220Sstevel@tonic-gate * Copyright (c) 1999 by Sun Microsystems, Inc. 230Sstevel@tonic-gate * All rights reserved. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 27*7298SMark.J.Nelson@Sun.COM // ServiceLocationManager.java : The service locator object. 280Sstevel@tonic-gate // Author: Erik Guttman 290Sstevel@tonic-gate // 300Sstevel@tonic-gate 310Sstevel@tonic-gate package com.sun.slp; 320Sstevel@tonic-gate 330Sstevel@tonic-gate import java.util.*; 340Sstevel@tonic-gate import java.io.*; 350Sstevel@tonic-gate import java.lang.reflect.*; 360Sstevel@tonic-gate 370Sstevel@tonic-gate /** 380Sstevel@tonic-gate * The ServiceLocationManager class provides entry to SLP services. 390Sstevel@tonic-gate * The ServiceLocationManager class uses static methods 400Sstevel@tonic-gate * to provide objects encapsulating the connection with the Service 410Sstevel@tonic-gate * Location facility. In addition, it provides access to known 420Sstevel@tonic-gate * scopes. 430Sstevel@tonic-gate * 440Sstevel@tonic-gate * @author Erik Guttman 450Sstevel@tonic-gate * 460Sstevel@tonic-gate */ 470Sstevel@tonic-gate 480Sstevel@tonic-gate abstract public class ServiceLocationManager extends Object { 490Sstevel@tonic-gate 500Sstevel@tonic-gate // Properties. 510Sstevel@tonic-gate 520Sstevel@tonic-gate protected static DATable dat = null; 530Sstevel@tonic-gate protected static SLPConfig config = null; 540Sstevel@tonic-gate 550Sstevel@tonic-gate protected static Hashtable locators = new Hashtable(); 560Sstevel@tonic-gate protected static Hashtable advertisers = new Hashtable(); 570Sstevel@tonic-gate protected static Class locatorClass = null; 580Sstevel@tonic-gate protected static Class advertiserClass = null; 590Sstevel@tonic-gate 600Sstevel@tonic-gate // Public interface 610Sstevel@tonic-gate 620Sstevel@tonic-gate /** 630Sstevel@tonic-gate * The property accessor for the Locator object. If user agent 640Sstevel@tonic-gate * functionality is not available, returns null. 650Sstevel@tonic-gate * 660Sstevel@tonic-gate * @param locale The Locale of the Locator object. Use null for default. 670Sstevel@tonic-gate * @return The Locator object. 680Sstevel@tonic-gate * @exception ServiceLocationException Thrown if the locator can't 690Sstevel@tonic-gate * be created. 700Sstevel@tonic-gate * 710Sstevel@tonic-gate */ 720Sstevel@tonic-gate getLocator(Locale locale)730Sstevel@tonic-gate public static Locator getLocator(Locale locale) 740Sstevel@tonic-gate throws ServiceLocationException 750Sstevel@tonic-gate { 760Sstevel@tonic-gate 770Sstevel@tonic-gate if (locale == null) { 780Sstevel@tonic-gate locale = config.getLocale(); 790Sstevel@tonic-gate 800Sstevel@tonic-gate } 810Sstevel@tonic-gate 820Sstevel@tonic-gate String lang = locale.getLanguage(); 830Sstevel@tonic-gate Locator locator = (Locator)locators.get(lang); 840Sstevel@tonic-gate 850Sstevel@tonic-gate if (locator == null) { 860Sstevel@tonic-gate 870Sstevel@tonic-gate if (locatorClass == null) { 880Sstevel@tonic-gate String className = 890Sstevel@tonic-gate System.getProperty("sun.net.slp.LocatorImpl"); 900Sstevel@tonic-gate if (className == null) { 910Sstevel@tonic-gate className = "com.sun.slp.UARequester"; 920Sstevel@tonic-gate } 930Sstevel@tonic-gate locatorClass = getClass(className); 940Sstevel@tonic-gate } 950Sstevel@tonic-gate 960Sstevel@tonic-gate locator = (Locator)getInstance(locatorClass, locale); 970Sstevel@tonic-gate 980Sstevel@tonic-gate if (locator != null) { 990Sstevel@tonic-gate locators.put(lang, locator); 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate return locator; 1050Sstevel@tonic-gate } 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate /** 1080Sstevel@tonic-gate * The property accessor for the Advertiser object. If service agent 1090Sstevel@tonic-gate * functionality is not available, returns null. 1100Sstevel@tonic-gate * 1110Sstevel@tonic-gate * @param locale The Locale of the Advertiser object. Use null for default. 1120Sstevel@tonic-gate * @return The Advertiser object. 1130Sstevel@tonic-gate * @exception ServiceLocationException Thrown if the locator can't 1140Sstevel@tonic-gate * be created. 1150Sstevel@tonic-gate * 1160Sstevel@tonic-gate */ 1170Sstevel@tonic-gate getAdvertiser(Locale locale)1180Sstevel@tonic-gate public static Advertiser getAdvertiser(Locale locale) 1190Sstevel@tonic-gate throws ServiceLocationException { 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate if (locale == null) { 1220Sstevel@tonic-gate locale = config.getLocale(); 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate String lang = locale.getLanguage(); 1270Sstevel@tonic-gate Advertiser advertiser = (Advertiser)advertisers.get(lang); 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate if (advertiser == null) { 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate if (advertiserClass == null) { 1320Sstevel@tonic-gate String className = 1330Sstevel@tonic-gate System.getProperty("sun.net.slp.AdvertiserImpl"); 1340Sstevel@tonic-gate if (className == null) { 1350Sstevel@tonic-gate className = "com.sun.slp.SARequester"; 1360Sstevel@tonic-gate } 1370Sstevel@tonic-gate advertiserClass = getClass(className); 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate advertiser = (Advertiser)getInstance(advertiserClass, locale); 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate if (advertiser != null) { 1430Sstevel@tonic-gate advertisers.put(lang, advertiser); 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate return advertiser; 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate /** 1520Sstevel@tonic-gate * Returns a vector of known scope names. It will include any 1530Sstevel@tonic-gate * scopes defined in the configuration file and ensure that the 1540Sstevel@tonic-gate * <i>order</i> of those scope strings is kept in the list of 1550Sstevel@tonic-gate * scopes which is returned. This method enforces the constraint 1560Sstevel@tonic-gate * that the default scope is returned if no other is available. 1570Sstevel@tonic-gate * 1580Sstevel@tonic-gate * @param typeHint Type to look for if SA advertisment required. 1590Sstevel@tonic-gate * @return Vector containing Strings with scope names. 1600Sstevel@tonic-gate */ 1610Sstevel@tonic-gate findScopes()1620Sstevel@tonic-gate public static synchronized Vector findScopes() 1630Sstevel@tonic-gate throws ServiceLocationException { 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate Vector accessableScopes = null; 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate // For the UA, return configured scopes if we have them. 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate accessableScopes = config.getConfiguredScopes(); 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate // If no configured scopes, get discovered scopes from 1720Sstevel@tonic-gate // DA table. 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate if (accessableScopes.size() <= 0) { 1750Sstevel@tonic-gate accessableScopes = dat.findScopes(); 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate // If still none, perform SA discovery. 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate if (accessableScopes.size() <= 0) { 1800Sstevel@tonic-gate accessableScopes = performSADiscovery(); 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate // If still none, then return default scope. The client won`t 1830Sstevel@tonic-gate // be able to contact anyone because there`s nobody out there. 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate if (accessableScopes.size() <= 0) { 1860Sstevel@tonic-gate accessableScopes.addElement(Defaults.DEFAULT_SCOPE); 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate return accessableScopes; 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate /** 1960Sstevel@tonic-gate * Returns the maximum across all DAs of the min-refresh-interval 1970Sstevel@tonic-gate * attribute. This value satisfies the advertised refresh interval 1980Sstevel@tonic-gate * bounds for all DAs, and, if used by the SA, assures that no 1990Sstevel@tonic-gate * refresh registration will be rejected. If no DA advertises a 2000Sstevel@tonic-gate * min-refresh-interval attribute, a value of 0 is returned. 2010Sstevel@tonic-gate * 2020Sstevel@tonic-gate * @return The maximum min-refresh-interval attribute value. 2030Sstevel@tonic-gate */ 2040Sstevel@tonic-gate getRefreshInterval()2050Sstevel@tonic-gate public static int getRefreshInterval() throws ServiceLocationException { 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate // Get the min-refresh-interval attribute values for all DA's from 2080Sstevel@tonic-gate // the server. 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate Vector tags = new Vector(); 2110Sstevel@tonic-gate tags.addElement(Defaults.MIN_REFRESH_INTERVAL_ATTR_ID); 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate // We don't simply do Locator.findAttributes() here because we 2140Sstevel@tonic-gate // need to contact the SA server directly. 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate Vector saOnlyScopes = config.getSAOnlyScopes(); 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate CAttrMsg msg = new CAttrMsg(Defaults.locale, 2190Sstevel@tonic-gate Defaults.SUN_DA_SERVICE_TYPE, 2200Sstevel@tonic-gate saOnlyScopes, 2210Sstevel@tonic-gate tags); 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate // Send it down the pipe to the IPC process. It's a bad bug 2240Sstevel@tonic-gate // if the reply comes back as not a CAttrMsg. 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate CAttrMsg rply = 2270Sstevel@tonic-gate (CAttrMsg)Transact.transactTCPMsg(config.getLoopback(), msg, true); 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate // Check error code. 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate if (rply == null || 2320Sstevel@tonic-gate rply.getErrorCode() != ServiceLocationException.OK) { 2330Sstevel@tonic-gate short errCode = 2340Sstevel@tonic-gate (rply == null ? 2350Sstevel@tonic-gate ServiceLocationException.INTERNAL_SYSTEM_ERROR : 2360Sstevel@tonic-gate rply.getErrorCode()); 2370Sstevel@tonic-gate throw 2380Sstevel@tonic-gate new ServiceLocationException(errCode, 2390Sstevel@tonic-gate "loopback_error", 2400Sstevel@tonic-gate new Object[] { 2410Sstevel@tonic-gate new Short(errCode)}); 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate } 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate // Sort through the attribute values to determine reply. 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate int ri = 0; 2480Sstevel@tonic-gate Vector attrs = rply.attrList; 2490Sstevel@tonic-gate ServiceLocationAttribute attr = 2500Sstevel@tonic-gate (attrs.size() > 0 ? 2510Sstevel@tonic-gate (ServiceLocationAttribute)attrs.elementAt(0): 2520Sstevel@tonic-gate null); 2530Sstevel@tonic-gate Vector values = (attr != null ? attr.getValues():new Vector()); 2540Sstevel@tonic-gate int i, n = values.size(); 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate for (i = 0; i < n; i++) { 2570Sstevel@tonic-gate Integer mri = (Integer)values.elementAt(i); 2580Sstevel@tonic-gate int mriv = mri.intValue(); 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate if (mriv > ri) { 2610Sstevel@tonic-gate ri = mriv; 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate return ri; 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate // 2700Sstevel@tonic-gate // Private implementation. 2710Sstevel@tonic-gate // 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate // Return the requested class, or null if it can't be found. 2740Sstevel@tonic-gate getClass(String name)2750Sstevel@tonic-gate private static Class getClass(String name) { 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate Class ret = null; 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate try { 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate ret = Class.forName(name); 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate } catch (ClassNotFoundException ex) { 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate return ret; 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate // Return an instance from the class. 2920Sstevel@tonic-gate getInstance(Class cobj, Locale locale)2930Sstevel@tonic-gate private static Object getInstance(Class cobj, Locale locale) { 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate Object ret = null; 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate if (cobj != null) { 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate try { 3000Sstevel@tonic-gate Class[] paramClasses = {locale.getClass()}; 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate Constructor con = cobj.getDeclaredConstructor(paramClasses); 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate Object[] params = {locale}; 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate ret = con.newInstance(params); 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate } catch (InstantiationException ex) { 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate } catch (IllegalAccessException ex) { 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate } catch (InvocationTargetException ex) { 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate } catch (NoSuchMethodException ex) { 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate } 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate return ret; 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate // Perform SA discovery, since no DA scopes found. 3230Sstevel@tonic-gate performSADiscovery()3240Sstevel@tonic-gate private static Vector performSADiscovery() 3250Sstevel@tonic-gate throws ServiceLocationException { 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate // Get type hint if any. 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate Vector hint = config.getTypeHint(); 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate // Format query. 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate StringBuffer buf = new StringBuffer(); 3340Sstevel@tonic-gate int i, n = hint.size(); 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate for (i = 0; i < n; i++) { 3370Sstevel@tonic-gate buf.append("("); 3380Sstevel@tonic-gate buf.append(Defaults.SERVICE_TYPE_ATTR_ID); 3390Sstevel@tonic-gate buf.append("="); 3400Sstevel@tonic-gate buf.append(hint.elementAt(i).toString()); 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate } 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate // Add logical disjunction if more than one element. 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate if (i > 1) { 3470Sstevel@tonic-gate buf.insert(0, "(|"); 3480Sstevel@tonic-gate buf.append(")"); 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate // Form SA discovery request. 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate CSrvMsg rqst = new CSrvMsg(config.getLocale(), 3540Sstevel@tonic-gate Defaults.SA_SERVICE_TYPE, 3550Sstevel@tonic-gate new Vector(), // seeking scopes... 3560Sstevel@tonic-gate buf.toString()); 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate // Transact the advert request. 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate Vector scopes = 3610Sstevel@tonic-gate Transact.transactActiveAdvertRequest(Defaults.SA_SERVICE_TYPE, 3620Sstevel@tonic-gate rqst, 3630Sstevel@tonic-gate null); 3640Sstevel@tonic-gate // DA table not needed... 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate return scopes; 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate } 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate // Initialize SLPConfig and DATable. 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate static { 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate if (config == null) { 3750Sstevel@tonic-gate config = SLPConfig.getSLPConfig(); 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate } 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate if (dat == null) { 3800Sstevel@tonic-gate dat = DATable.getDATable(); 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate } 385