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