2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 1999 by Sun Microsystems, Inc.
2N/A * All rights reserved.
2N/A *
2N/A */
2N/A
2N/A// ServiceLocationManager.java : The service locator object.
2N/A// Author: Erik Guttman
2N/A//
2N/A
2N/Apackage com.sun.slp;
2N/A
2N/Aimport java.util.*;
2N/Aimport java.io.*;
2N/Aimport java.lang.reflect.*;
2N/A
2N/A/**
2N/A * The ServiceLocationManager class provides entry to SLP services.
2N/A * The ServiceLocationManager class uses static methods
2N/A * to provide objects encapsulating the connection with the Service
2N/A * Location facility. In addition, it provides access to known
2N/A * scopes.
2N/A *
2N/A * @author Erik Guttman
2N/A *
2N/A */
2N/A
2N/Aabstract public class ServiceLocationManager extends Object {
2N/A
2N/A // Properties.
2N/A
2N/A protected static DATable dat = null;
2N/A protected static SLPConfig config = null;
2N/A
2N/A protected static Hashtable locators = new Hashtable();
2N/A protected static Hashtable advertisers = new Hashtable();
2N/A protected static Class locatorClass = null;
2N/A protected static Class advertiserClass = null;
2N/A
2N/A // Public interface
2N/A
2N/A /**
2N/A * The property accessor for the Locator object. If user agent
2N/A * functionality is not available, returns null.
2N/A *
2N/A * @param locale The Locale of the Locator object. Use null for default.
2N/A * @return The Locator object.
2N/A * @exception ServiceLocationException Thrown if the locator can't
2N/A * be created.
2N/A *
2N/A */
2N/A
2N/A public static Locator getLocator(Locale locale)
2N/A throws ServiceLocationException
2N/A {
2N/A
2N/A if (locale == null) {
2N/A locale = config.getLocale();
2N/A
2N/A }
2N/A
2N/A String lang = locale.getLanguage();
2N/A Locator locator = (Locator)locators.get(lang);
2N/A
2N/A if (locator == null) {
2N/A
2N/A if (locatorClass == null) {
2N/A String className =
2N/A System.getProperty("sun.net.slp.LocatorImpl");
2N/A if (className == null) {
2N/A className = "com.sun.slp.UARequester";
2N/A }
2N/A locatorClass = getClass(className);
2N/A }
2N/A
2N/A locator = (Locator)getInstance(locatorClass, locale);
2N/A
2N/A if (locator != null) {
2N/A locators.put(lang, locator);
2N/A
2N/A }
2N/A }
2N/A
2N/A return locator;
2N/A }
2N/A
2N/A /**
2N/A * The property accessor for the Advertiser object. If service agent
2N/A * functionality is not available, returns null.
2N/A *
2N/A * @param locale The Locale of the Advertiser object. Use null for default.
2N/A * @return The Advertiser object.
2N/A * @exception ServiceLocationException Thrown if the locator can't
2N/A * be created.
2N/A *
2N/A */
2N/A
2N/A public static Advertiser getAdvertiser(Locale locale)
2N/A throws ServiceLocationException {
2N/A
2N/A if (locale == null) {
2N/A locale = config.getLocale();
2N/A
2N/A }
2N/A
2N/A String lang = locale.getLanguage();
2N/A Advertiser advertiser = (Advertiser)advertisers.get(lang);
2N/A
2N/A if (advertiser == null) {
2N/A
2N/A if (advertiserClass == null) {
2N/A String className =
2N/A System.getProperty("sun.net.slp.AdvertiserImpl");
2N/A if (className == null) {
2N/A className = "com.sun.slp.SARequester";
2N/A }
2N/A advertiserClass = getClass(className);
2N/A }
2N/A
2N/A advertiser = (Advertiser)getInstance(advertiserClass, locale);
2N/A
2N/A if (advertiser != null) {
2N/A advertisers.put(lang, advertiser);
2N/A
2N/A }
2N/A }
2N/A
2N/A return advertiser;
2N/A }
2N/A
2N/A /**
2N/A * Returns a vector of known scope names. It will include any
2N/A * scopes defined in the configuration file and ensure that the
2N/A * <i>order</i> of those scope strings is kept in the list of
2N/A * scopes which is returned. This method enforces the constraint
2N/A * that the default scope is returned if no other is available.
2N/A *
2N/A * @param typeHint Type to look for if SA advertisment required.
2N/A * @return Vector containing Strings with scope names.
2N/A */
2N/A
2N/A public static synchronized Vector findScopes()
2N/A throws ServiceLocationException {
2N/A
2N/A Vector accessableScopes = null;
2N/A
2N/A // For the UA, return configured scopes if we have them.
2N/A
2N/A accessableScopes = config.getConfiguredScopes();
2N/A
2N/A // If no configured scopes, get discovered scopes from
2N/A // DA table.
2N/A
2N/A if (accessableScopes.size() <= 0) {
2N/A accessableScopes = dat.findScopes();
2N/A
2N/A // If still none, perform SA discovery.
2N/A
2N/A if (accessableScopes.size() <= 0) {
2N/A accessableScopes = performSADiscovery();
2N/A
2N/A // If still none, then return default scope. The client won`t
2N/A // be able to contact anyone because there`s nobody out there.
2N/A
2N/A if (accessableScopes.size() <= 0) {
2N/A accessableScopes.addElement(Defaults.DEFAULT_SCOPE);
2N/A
2N/A }
2N/A }
2N/A }
2N/A
2N/A return accessableScopes;
2N/A }
2N/A
2N/A /**
2N/A * Returns the maximum across all DAs of the min-refresh-interval
2N/A * attribute. This value satisfies the advertised refresh interval
2N/A * bounds for all DAs, and, if used by the SA, assures that no
2N/A * refresh registration will be rejected. If no DA advertises a
2N/A * min-refresh-interval attribute, a value of 0 is returned.
2N/A *
2N/A * @return The maximum min-refresh-interval attribute value.
2N/A */
2N/A
2N/A public static int getRefreshInterval() throws ServiceLocationException {
2N/A
2N/A // Get the min-refresh-interval attribute values for all DA's from
2N/A // the server.
2N/A
2N/A Vector tags = new Vector();
2N/A tags.addElement(Defaults.MIN_REFRESH_INTERVAL_ATTR_ID);
2N/A
2N/A // We don't simply do Locator.findAttributes() here because we
2N/A // need to contact the SA server directly.
2N/A
2N/A Vector saOnlyScopes = config.getSAOnlyScopes();
2N/A
2N/A CAttrMsg msg = new CAttrMsg(Defaults.locale,
2N/A Defaults.SUN_DA_SERVICE_TYPE,
2N/A saOnlyScopes,
2N/A tags);
2N/A
2N/A // Send it down the pipe to the IPC process. It's a bad bug
2N/A // if the reply comes back as not a CAttrMsg.
2N/A
2N/A CAttrMsg rply =
2N/A (CAttrMsg)Transact.transactTCPMsg(config.getLoopback(), msg, true);
2N/A
2N/A // Check error code.
2N/A
2N/A if (rply == null ||
2N/A rply.getErrorCode() != ServiceLocationException.OK) {
2N/A short errCode =
2N/A (rply == null ?
2N/A ServiceLocationException.INTERNAL_SYSTEM_ERROR :
2N/A rply.getErrorCode());
2N/A throw
2N/A new ServiceLocationException(errCode,
2N/A "loopback_error",
2N/A new Object[] {
2N/A new Short(errCode)});
2N/A
2N/A }
2N/A
2N/A // Sort through the attribute values to determine reply.
2N/A
2N/A int ri = 0;
2N/A Vector attrs = rply.attrList;
2N/A ServiceLocationAttribute attr =
2N/A (attrs.size() > 0 ?
2N/A (ServiceLocationAttribute)attrs.elementAt(0):
2N/A null);
2N/A Vector values = (attr != null ? attr.getValues():new Vector());
2N/A int i, n = values.size();
2N/A
2N/A for (i = 0; i < n; i++) {
2N/A Integer mri = (Integer)values.elementAt(i);
2N/A int mriv = mri.intValue();
2N/A
2N/A if (mriv > ri) {
2N/A ri = mriv;
2N/A
2N/A }
2N/A }
2N/A
2N/A return ri;
2N/A }
2N/A
2N/A //
2N/A // Private implementation.
2N/A //
2N/A
2N/A // Return the requested class, or null if it can't be found.
2N/A
2N/A private static Class getClass(String name) {
2N/A
2N/A Class ret = null;
2N/A
2N/A try {
2N/A
2N/A ret = Class.forName(name);
2N/A
2N/A } catch (ClassNotFoundException ex) {
2N/A
2N/A }
2N/A
2N/A return ret;
2N/A
2N/A }
2N/A
2N/A // Return an instance from the class.
2N/A
2N/A private static Object getInstance(Class cobj, Locale locale) {
2N/A
2N/A Object ret = null;
2N/A
2N/A if (cobj != null) {
2N/A
2N/A try {
2N/A Class[] paramClasses = {locale.getClass()};
2N/A
2N/A Constructor con = cobj.getDeclaredConstructor(paramClasses);
2N/A
2N/A Object[] params = {locale};
2N/A
2N/A ret = con.newInstance(params);
2N/A
2N/A } catch (InstantiationException ex) {
2N/A
2N/A } catch (IllegalAccessException ex) {
2N/A
2N/A } catch (InvocationTargetException ex) {
2N/A
2N/A } catch (NoSuchMethodException ex) {
2N/A
2N/A }
2N/A }
2N/A
2N/A return ret;
2N/A }
2N/A
2N/A // Perform SA discovery, since no DA scopes found.
2N/A
2N/A private static Vector performSADiscovery()
2N/A throws ServiceLocationException {
2N/A
2N/A // Get type hint if any.
2N/A
2N/A Vector hint = config.getTypeHint();
2N/A
2N/A // Format query.
2N/A
2N/A StringBuffer buf = new StringBuffer();
2N/A int i, n = hint.size();
2N/A
2N/A for (i = 0; i < n; i++) {
2N/A buf.append("(");
2N/A buf.append(Defaults.SERVICE_TYPE_ATTR_ID);
2N/A buf.append("=");
2N/A buf.append(hint.elementAt(i).toString());
2N/A
2N/A }
2N/A
2N/A // Add logical disjunction if more than one element.
2N/A
2N/A if (i > 1) {
2N/A buf.insert(0, "(|");
2N/A buf.append(")");
2N/A }
2N/A
2N/A // Form SA discovery request.
2N/A
2N/A CSrvMsg rqst = new CSrvMsg(config.getLocale(),
2N/A Defaults.SA_SERVICE_TYPE,
2N/A new Vector(), // seeking scopes...
2N/A buf.toString());
2N/A
2N/A // Transact the advert request.
2N/A
2N/A Vector scopes =
2N/A Transact.transactActiveAdvertRequest(Defaults.SA_SERVICE_TYPE,
2N/A rqst,
2N/A null);
2N/A // DA table not needed...
2N/A
2N/A return scopes;
2N/A
2N/A }
2N/A
2N/A // Initialize SLPConfig and DATable.
2N/A
2N/A static {
2N/A
2N/A if (config == null) {
2N/A config = SLPConfig.getSLPConfig();
2N/A
2N/A }
2N/A
2N/A if (dat == null) {
2N/A dat = DATable.getDATable();
2N/A
2N/A }
2N/A }
2N/A}