1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * ident "%Z%%M% %I% %E% SMI" 24 * 25 * Copyright (c) 1999 by Sun Microsystems, Inc. 26 * All rights reserved. 27 * 28 */ 29 30 // SCCS Status: @(#)ServiceLocationManager.java 1.18 07/23/97 31 // %M : The service locator object. 32 // Author: Erik Guttman 33 // 34 35 package com.sun.slp; 36 37 import java.util.*; 38 import java.io.*; 39 import java.lang.reflect.*; 40 41 /** 42 * The ServiceLocationManager class provides entry to SLP services. 43 * The ServiceLocationManager class uses static methods 44 * to provide objects encapsulating the connection with the Service 45 * Location facility. In addition, it provides access to known 46 * scopes. 47 * 48 * @version %R%.%L% %D% 49 * @author Erik Guttman 50 * 51 */ 52 53 abstract public class ServiceLocationManager extends Object { 54 55 // Properties. 56 57 protected static DATable dat = null; 58 protected static SLPConfig config = null; 59 60 protected static Hashtable locators = new Hashtable(); 61 protected static Hashtable advertisers = new Hashtable(); 62 protected static Class locatorClass = null; 63 protected static Class advertiserClass = null; 64 65 // Public interface 66 67 /** 68 * The property accessor for the Locator object. If user agent 69 * functionality is not available, returns null. 70 * 71 * @param locale The Locale of the Locator object. Use null for default. 72 * @return The Locator object. 73 * @exception ServiceLocationException Thrown if the locator can't 74 * be created. 75 * 76 */ 77 78 public static Locator getLocator(Locale locale) 79 throws ServiceLocationException 80 { 81 82 if (locale == null) { 83 locale = config.getLocale(); 84 85 } 86 87 String lang = locale.getLanguage(); 88 Locator locator = (Locator)locators.get(lang); 89 90 if (locator == null) { 91 92 if (locatorClass == null) { 93 String className = 94 System.getProperty("sun.net.slp.LocatorImpl"); 95 if (className == null) { 96 className = "com.sun.slp.UARequester"; 97 } 98 locatorClass = getClass(className); 99 } 100 101 locator = (Locator)getInstance(locatorClass, locale); 102 103 if (locator != null) { 104 locators.put(lang, locator); 105 106 } 107 } 108 109 return locator; 110 } 111 112 /** 113 * The property accessor for the Advertiser object. If service agent 114 * functionality is not available, returns null. 115 * 116 * @param locale The Locale of the Advertiser object. Use null for default. 117 * @return The Advertiser object. 118 * @exception ServiceLocationException Thrown if the locator can't 119 * be created. 120 * 121 */ 122 123 public static Advertiser getAdvertiser(Locale locale) 124 throws ServiceLocationException { 125 126 if (locale == null) { 127 locale = config.getLocale(); 128 129 } 130 131 String lang = locale.getLanguage(); 132 Advertiser advertiser = (Advertiser)advertisers.get(lang); 133 134 if (advertiser == null) { 135 136 if (advertiserClass == null) { 137 String className = 138 System.getProperty("sun.net.slp.AdvertiserImpl"); 139 if (className == null) { 140 className = "com.sun.slp.SARequester"; 141 } 142 advertiserClass = getClass(className); 143 } 144 145 advertiser = (Advertiser)getInstance(advertiserClass, locale); 146 147 if (advertiser != null) { 148 advertisers.put(lang, advertiser); 149 150 } 151 } 152 153 return advertiser; 154 } 155 156 /** 157 * Returns a vector of known scope names. It will include any 158 * scopes defined in the configuration file and ensure that the 159 * <i>order</i> of those scope strings is kept in the list of 160 * scopes which is returned. This method enforces the constraint 161 * that the default scope is returned if no other is available. 162 * 163 * @param typeHint Type to look for if SA advertisment required. 164 * @return Vector containing Strings with scope names. 165 */ 166 167 public static synchronized Vector findScopes() 168 throws ServiceLocationException { 169 170 Vector accessableScopes = null; 171 172 // For the UA, return configured scopes if we have them. 173 174 accessableScopes = config.getConfiguredScopes(); 175 176 // If no configured scopes, get discovered scopes from 177 // DA table. 178 179 if (accessableScopes.size() <= 0) { 180 accessableScopes = dat.findScopes(); 181 182 // If still none, perform SA discovery. 183 184 if (accessableScopes.size() <= 0) { 185 accessableScopes = performSADiscovery(); 186 187 // If still none, then return default scope. The client won`t 188 // be able to contact anyone because there`s nobody out there. 189 190 if (accessableScopes.size() <= 0) { 191 accessableScopes.addElement(Defaults.DEFAULT_SCOPE); 192 193 } 194 } 195 } 196 197 return accessableScopes; 198 } 199 200 /** 201 * Returns the maximum across all DAs of the min-refresh-interval 202 * attribute. This value satisfies the advertised refresh interval 203 * bounds for all DAs, and, if used by the SA, assures that no 204 * refresh registration will be rejected. If no DA advertises a 205 * min-refresh-interval attribute, a value of 0 is returned. 206 * 207 * @return The maximum min-refresh-interval attribute value. 208 */ 209 210 public static int getRefreshInterval() throws ServiceLocationException { 211 212 // Get the min-refresh-interval attribute values for all DA's from 213 // the server. 214 215 Vector tags = new Vector(); 216 tags.addElement(Defaults.MIN_REFRESH_INTERVAL_ATTR_ID); 217 218 // We don't simply do Locator.findAttributes() here because we 219 // need to contact the SA server directly. 220 221 Vector saOnlyScopes = config.getSAOnlyScopes(); 222 223 CAttrMsg msg = new CAttrMsg(Defaults.locale, 224 Defaults.SUN_DA_SERVICE_TYPE, 225 saOnlyScopes, 226 tags); 227 228 // Send it down the pipe to the IPC process. It's a bad bug 229 // if the reply comes back as not a CAttrMsg. 230 231 CAttrMsg rply = 232 (CAttrMsg)Transact.transactTCPMsg(config.getLoopback(), msg, true); 233 234 // Check error code. 235 236 if (rply == null || 237 rply.getErrorCode() != ServiceLocationException.OK) { 238 short errCode = 239 (rply == null ? 240 ServiceLocationException.INTERNAL_SYSTEM_ERROR : 241 rply.getErrorCode()); 242 throw 243 new ServiceLocationException(errCode, 244 "loopback_error", 245 new Object[] { 246 new Short(errCode)}); 247 248 } 249 250 // Sort through the attribute values to determine reply. 251 252 int ri = 0; 253 Vector attrs = rply.attrList; 254 ServiceLocationAttribute attr = 255 (attrs.size() > 0 ? 256 (ServiceLocationAttribute)attrs.elementAt(0): 257 null); 258 Vector values = (attr != null ? attr.getValues():new Vector()); 259 int i, n = values.size(); 260 261 for (i = 0; i < n; i++) { 262 Integer mri = (Integer)values.elementAt(i); 263 int mriv = mri.intValue(); 264 265 if (mriv > ri) { 266 ri = mriv; 267 268 } 269 } 270 271 return ri; 272 } 273 274 // 275 // Private implementation. 276 // 277 278 // Return the requested class, or null if it can't be found. 279 280 private static Class getClass(String name) { 281 282 Class ret = null; 283 284 try { 285 286 ret = Class.forName(name); 287 288 } catch (ClassNotFoundException ex) { 289 290 } 291 292 return ret; 293 294 } 295 296 // Return an instance from the class. 297 298 private static Object getInstance(Class cobj, Locale locale) { 299 300 Object ret = null; 301 302 if (cobj != null) { 303 304 try { 305 Class[] paramClasses = {locale.getClass()}; 306 307 Constructor con = cobj.getDeclaredConstructor(paramClasses); 308 309 Object[] params = {locale}; 310 311 ret = con.newInstance(params); 312 313 } catch (InstantiationException ex) { 314 315 } catch (IllegalAccessException ex) { 316 317 } catch (InvocationTargetException ex) { 318 319 } catch (NoSuchMethodException ex) { 320 321 } 322 } 323 324 return ret; 325 } 326 327 // Perform SA discovery, since no DA scopes found. 328 329 private static Vector performSADiscovery() 330 throws ServiceLocationException { 331 332 // Get type hint if any. 333 334 Vector hint = config.getTypeHint(); 335 336 // Format query. 337 338 StringBuffer buf = new StringBuffer(); 339 int i, n = hint.size(); 340 341 for (i = 0; i < n; i++) { 342 buf.append("("); 343 buf.append(Defaults.SERVICE_TYPE_ATTR_ID); 344 buf.append("="); 345 buf.append(hint.elementAt(i).toString()); 346 347 } 348 349 // Add logical disjunction if more than one element. 350 351 if (i > 1) { 352 buf.insert(0, "(|"); 353 buf.append(")"); 354 } 355 356 // Form SA discovery request. 357 358 CSrvMsg rqst = new CSrvMsg(config.getLocale(), 359 Defaults.SA_SERVICE_TYPE, 360 new Vector(), // seeking scopes... 361 buf.toString()); 362 363 // Transact the advert request. 364 365 Vector scopes = 366 Transact.transactActiveAdvertRequest(Defaults.SA_SERVICE_TYPE, 367 rqst, 368 null); 369 // DA table not needed... 370 371 return scopes; 372 373 } 374 375 // Initialize SLPConfig and DATable. 376 377 static { 378 379 if (config == null) { 380 config = SLPConfig.getSLPConfig(); 381 382 } 383 384 if (dat == null) { 385 dat = DATable.getDATable(); 386 387 } 388 } 389 } 390