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 // UARequester.java: Requester operations for UA. 28 // Author: James Kempf 29 // Created On: Thu Jan 8 15:17:35 1998 30 // Last Modified By: James Kempf 31 // Last Modified On: Mon Feb 22 13:47:06 1999 32 // Update Count: 78 33 // 34 35 package com.sun.slp; 36 37 import java.util.*; 38 39 /** 40 * The URequester class implements the Locator interface. 41 * It handles the request for the API. If any of the parameters 42 * are missing, they will be supplied with a default value if 43 * possible. If a cached value may be supplied, it will be. 44 * If no DA is present, and convergence is used to gather 45 * results, these will be merged into one result. 46 * 47 * @author Erik Guttman, James Kempf 48 */ 49 50 51 class UARequester extends Object implements Locator { 52 53 private static SLPConfig config = null; 54 private static DATable dat = null; 55 56 private Locale locale; 57 UARequester(Locale nlocale)58 UARequester(Locale nlocale) { 59 60 Assert.nonNullParameter(nlocale, "locale"); 61 62 if (config == null) { 63 config = SLPConfig.getSLPConfig(); 64 } 65 66 if (dat == null) { 67 dat = DATable.getDATable(); 68 } 69 70 locale = nlocale; 71 } 72 73 /** 74 * Return the Locator's locale object. All requests are made in 75 * this locale. 76 * 77 * @return The Locale object. 78 */ 79 getLocale()80 public Locale getLocale() { 81 return locale; 82 83 } 84 85 /** 86 * Return an enumeration of known service types for this scope and naming 87 * authority. Unless a proprietary or experimental service is being 88 * discovered, the namingAuthority parameter should be the empty 89 * string, "". 90 * 91 * @param NA The naming authority, "" for default, 92 * '*' for any naming authority. 93 * @param scopes The SLP scopes of the types. 94 * @return ServiceLocationEnumeration of ServiceType objects for 95 * the service type names. 96 * @exception IllegalArgumentException If any of the parameters are 97 * null or syntactically incorrect. 98 * @exception ServiceLocationException An exception is thrown if the 99 * operation fails. 100 */ 101 102 public synchronized ServiceLocationEnumeration findServiceTypes(String NA, Vector scopes)103 findServiceTypes(String NA, Vector scopes) 104 throws ServiceLocationException { 105 106 Assert.nonNullParameter(NA, " NA"); 107 Assert.nonNullParameter(scopes, "scopes"); 108 109 // Formulate and send off messages. 110 111 Vector msgs = createMessages(SrvLocHeader.SrvTypeRqst, 112 NA, 113 null, 114 null, 115 scopes); 116 117 // Collate results. 118 119 Vector ret = new Vector(); 120 int i, n = msgs.size(); 121 int max = config.getMaximumResults(); 122 123 for (i = 0; i < n; i++) { 124 CSrvTypeMsg msg = (CSrvTypeMsg)msgs.elementAt(i); 125 126 // Check for errors. 127 128 checkForError(msg, msgs); 129 130 Vector serviceTypes = msg.serviceTypes; 131 132 addUnique(serviceTypes, ret, max); 133 134 } 135 136 // Return. 137 138 return new ServiceLocationEnumerator(ret); 139 } 140 141 /** 142 * Return an enumeration of ServiceURL objects for services matching 143 * the query. The services are returned from the locale of the 144 * locator. 145 * 146 * @param type The type of the service (e.g. printer, etc.). 147 * @param scopes The SLP scopes of the service types. 148 * @param query A string with the SLP query. 149 * @return ServiceLocationEnumeration of ServiceURL objects for 150 * services matching the 151 * attributes. 152 * @exception ServiceLocationException An exception is returned if the 153 * operation fails. 154 * @see ServiceURL 155 */ 156 157 public synchronized ServiceLocationEnumeration findServices(ServiceType type, Vector scopes, String query)158 findServices(ServiceType type, Vector scopes, String query) 159 throws ServiceLocationException { 160 161 Assert.nonNullParameter(type, "type"); 162 Assert.nonNullParameter(scopes, "scopes"); 163 Assert.nonNullParameter(query, "query"); 164 165 // Formulate and send off messages. 166 167 Vector msgs = createMessages(SrvLocHeader.SrvReq, 168 type, 169 query, 170 type, 171 scopes); 172 173 // Collate results. 174 175 Vector ret = new Vector(); 176 int i, n = msgs.size(); 177 int max = config.getMaximumResults(); 178 179 for (i = 0; i < n; i++) { 180 SrvLocMsg msg = (SrvLocMsg)msgs.elementAt(i); 181 182 // Check for errors. 183 184 checkForError(msg, msgs); 185 186 // Be sure to account for DAAdverts and SAAdverts. 187 188 Vector serviceURLs = null; 189 190 if (msg instanceof CSrvMsg) { 191 serviceURLs = ((CSrvMsg)msg).serviceURLs; 192 193 } else if (msg instanceof CSAAdvert) { 194 serviceURLs = new Vector(); 195 serviceURLs.addElement(((CSAAdvert)msg).URL); 196 197 } else if (msg instanceof CDAAdvert) { 198 serviceURLs = new Vector(); 199 serviceURLs.addElement(((CDAAdvert)msg).URL); 200 201 } 202 203 addUnique(serviceURLs, ret, max); 204 205 } 206 207 // Return. 208 209 return new ServiceLocationEnumerator(ret); 210 } 211 212 /** 213 * Return the attributes for the service URL, using the locale 214 * of the locator. 215 * 216 * @param URL The service URL. 217 * @param scopes The SLP scopes of the service. 218 * @param attributeIds A vector of strings identifying the desired 219 * attributes. A null value means return all 220 * the attributes. <b>Partial id strings</b> may 221 * begin with '*' to match all ids which end with 222 * the given suffix, or end with '*' to match all 223 * ids which begin with a given prefix, or begin 224 * and end with '*' to do substring matching for 225 * ids containing the given partial id. 226 * @return ServiceLocationEnumeration of ServiceLocationAttribute 227 * objects matching the ids. 228 * @exception ServiceLocationException An exception is returned if the 229 * operation fails. 230 * @exception IllegalArgumentException If any of the parameters are 231 * null or syntactically incorrect. 232 * @see ServiceLocationAttribute 233 * 234 */ 235 236 public synchronized ServiceLocationEnumeration findAttributes(ServiceURL URL, Vector scopes, Vector attributeIds)237 findAttributes(ServiceURL URL, Vector scopes, Vector attributeIds) 238 throws ServiceLocationException { 239 240 Assert.nonNullParameter(URL, "URL"); 241 Assert.nonNullParameter(scopes, "scopes"); 242 Assert.nonNullParameter(attributeIds, "attributeIds"); 243 244 Vector msgs = createMessages(SrvLocHeader.AttrRqst, 245 URL, 246 attributeIds, 247 URL.getServiceType(), 248 scopes); 249 250 // Check results. 251 252 Vector ret = new Vector(); 253 int i, n = msgs.size(); 254 int max = config.getMaximumResults(); 255 256 // We only take the first message that came back and is OK. 257 258 for (i = 0; i < n; i++) { 259 SrvLocMsg msg = (SrvLocMsg)msgs.elementAt(i); 260 261 // Check for errors. 262 263 checkForError(msg, msgs); 264 265 // Select out attribute list. 266 267 if (msg instanceof CAttrMsg) { 268 ret = ((CAttrMsg)msg).attrList; 269 270 } else if (msg instanceof CSAAdvert) { 271 272 // Need to check that URL matches. 273 274 CSAAdvert smsg = (CSAAdvert)msg; 275 276 if (!URL.equals(smsg.URL)) { 277 continue; 278 279 } 280 281 ret = smsg.attrs; 282 283 } else if (msg instanceof CDAAdvert) { 284 285 // Need to check that URL matches. 286 287 CDAAdvert smsg = (CDAAdvert)msg; 288 289 if (!URL.equals(smsg.URL)) { 290 continue; 291 292 } 293 294 ret = smsg.attrs; 295 } 296 297 // Truncate, if return is larger than maximum. 298 299 if (ret.size() > max) { 300 ret.setSize(max); 301 302 } 303 304 // Break out, we only need one. 305 306 break; 307 308 } 309 310 // Return. 311 312 return new ServiceLocationEnumerator(ret); 313 } 314 315 /** 316 * Return all attributes for all service URL's having this 317 * service type in the locale of the Locator. 318 * 319 * @param type The service type. 320 * @param scopes The SLP scopes of the service type. 321 * @param attributeIds A vector of strings identifying the desired 322 * attributes. A null value means return all 323 * the attributes. <b>Partial id strings</b> may 324 * begin with '*' to match all ids which end with 325 * the given suffix, or end with '*' to match all 326 * ids which begin with a given prefix, or begin 327 * and end with '*' to do substring matching for 328 * ids containing the given partial id. 329 * @return ServiceLocationEnumeration of ServiceLocationAttribute 330 * objects matching the ids. 331 * @exception ServiceLocationException An exception is returned if the 332 * operation fails. 333 * @exception IllegalArgumentException If any of the parameters are 334 * null or syntactically incorrect. 335 * @see ServiceLocationAttribute 336 * 337 */ 338 339 public synchronized ServiceLocationEnumeration findAttributes(ServiceType type, Vector scopes, Vector attributeIds)340 findAttributes(ServiceType type, Vector scopes, Vector attributeIds) 341 throws ServiceLocationException { 342 343 Assert.nonNullParameter(type, "URL"); 344 Assert.nonNullParameter(scopes, "scopes"); 345 Assert.nonNullParameter(attributeIds, "attributeIds"); 346 347 // Formulate and send off messages. 348 349 Vector msgs = createMessages(SrvLocHeader.AttrRqst, 350 type, 351 attributeIds, 352 type, 353 scopes); 354 // Collate results. 355 356 Vector ret = new Vector(); 357 int i, n = msgs.size(); 358 int max = config.getMaximumResults(); 359 Hashtable ht = new Hashtable(); 360 361 for (i = 0; i < n && ret.size() < max; i++) { 362 SrvLocMsg msg = (SrvLocMsg)msgs.elementAt(i); 363 364 // Check for errors. 365 366 checkForError(msg, msgs); 367 368 Vector attrList = null; 369 370 // Get the instance variable. 371 372 if (msg instanceof CAttrMsg) { 373 attrList = ((CAttrMsg)msg).attrList; 374 375 } else if (msg instanceof CSAAdvert) { 376 attrList = ((CSAAdvert)msg).attrs; 377 378 } else if (msg instanceof CDAAdvert) { 379 attrList = ((CDAAdvert)msg).attrs; 380 381 } 382 383 // Merge any duplicates. 384 385 int j, m = attrList.size(); 386 387 for (j = 0; j < m; j++) { 388 ServiceLocationAttribute attr = 389 (ServiceLocationAttribute)attrList.elementAt(j); 390 391 ServiceLocationAttribute.mergeDuplicateAttributes(attr, 392 ht, 393 ret, 394 true); 395 396 if (ret.size() >= max) { 397 break; 398 399 } 400 } 401 } 402 403 // Return. 404 405 return new ServiceLocationEnumerator(ret); 406 } 407 408 // Execute the message request, returning messages. 409 410 private Vector createMessages(int msgType, Object t1, Object t2, ServiceType type, Vector scopes)411 createMessages(int msgType, 412 Object t1, 413 Object t2, 414 ServiceType type, 415 Vector scopes) 416 throws ServiceLocationException { 417 418 // Validate, lower case scopes. 419 420 DATable.validateScopes(scopes, locale); 421 422 SrvLocMsg multiMsg = null; 423 SrvLocMsg uniMsg = null; 424 Vector daAddresses = null; 425 Vector multiCastScopes = null; 426 427 // Get the hashtable of unicast DA addresses and multicast scopes. 428 429 Hashtable daRecords = dat.findDAScopes(scopes); 430 431 // Get multicast scopes and DA addresses. 432 433 multiCastScopes = 434 (Vector)daRecords.get(DATable.MULTICAST_KEY); 435 436 daAddresses = 437 (Vector)daRecords.get(DATable.UNICAST_KEY); 438 439 // Special case for service request and attribute request 440 // if the user is looking for a special SLP type. 441 442 if (((msgType == SrvLocHeader.SrvReq) || 443 (msgType == SrvLocHeader.AttrRqst)) && 444 (type.equals(Defaults.DA_SERVICE_TYPE) || 445 type.equals(Defaults.SA_SERVICE_TYPE))) { 446 447 multiCastScopes = scopes; 448 daAddresses = null; 449 450 // Get query. If an attribute request, then the user 451 // needs to sort out the attributes. 452 453 String query = ""; 454 455 if (msgType == SrvLocHeader.SrvReq) { 456 query = (String)t2; 457 458 } 459 460 multiMsg = new CSrvMsg(locale, type, multiCastScopes, query); 461 462 } else { 463 464 // Handle a regular message. 465 466 // Multicast scopes are all scopes not supported by any DA. 467 468 if (multiCastScopes != null) { 469 470 switch (msgType) { 471 472 case SrvLocHeader.SrvTypeRqst: 473 multiMsg = 474 new CSrvTypeMsg(locale, (String)t1, multiCastScopes); 475 break; 476 477 case SrvLocHeader.SrvReq: 478 multiMsg = 479 new CSrvMsg(locale, type, multiCastScopes, (String)t2); 480 break; 481 482 case SrvLocHeader.AttrRqst: 483 484 if (t1 instanceof ServiceURL) { 485 multiMsg = 486 new CAttrMsg(locale, 487 (ServiceURL)t1, 488 multiCastScopes, 489 (Vector)t2); 490 491 } else { 492 multiMsg = 493 new CAttrMsg(locale, 494 type, 495 multiCastScopes, 496 (Vector)t2); 497 498 } 499 } 500 } 501 502 // Unicast only requires a single message because the DAs will 503 // ignore any scopes they do not support, just as long as 504 // they support one of them. 505 506 if (daAddresses != null) { 507 switch (msgType) { 508 509 case SrvLocHeader.SrvTypeRqst: 510 uniMsg = 511 new CSrvTypeMsg(locale, (String)t1, scopes); 512 break; 513 514 case SrvLocHeader.SrvReq: 515 uniMsg = 516 new CSrvMsg(locale, type, scopes, (String)t2); 517 break; 518 519 case SrvLocHeader.AttrRqst: 520 521 if (t1 instanceof ServiceURL) { 522 uniMsg = 523 new CAttrMsg(locale, 524 (ServiceURL)t1, 525 scopes, 526 (Vector)t2); 527 528 } else { 529 uniMsg = 530 new CAttrMsg(locale, 531 type, 532 scopes, 533 (Vector)t2); 534 535 } 536 537 } 538 } 539 } 540 541 // Send off messages, return results. 542 543 return Transact.transactUA(daAddresses, 544 uniMsg, 545 multiMsg, 546 config.getMulticastAddress()); 547 } 548 549 // Check message for error code. 550 551 private static void checkForError(SrvLocMsg msg, Vector v)552 checkForError(SrvLocMsg msg, Vector v) 553 throws ServiceLocationException { 554 int err = msg.getErrorCode(); 555 556 if (err != ServiceLocationException.OK) { 557 if (v.size() == 1) { 558 config.writeLog("single_exception", 559 new Object[] { 560 new Integer(err)}); 561 throw 562 new ServiceLocationException((short)err, 563 "remote_error", 564 new Object[] {}); 565 } else { 566 config.writeLog("multiple_exception", 567 new Object[] { 568 new Integer(err)}); 569 } 570 } 571 } 572 573 // Process the incoming vector, adding any unique returns. 574 addUnique(Vector incoming, Vector returns, int max)575 private static void addUnique(Vector incoming, Vector returns, int max) { 576 577 int i, n = incoming.size(); 578 579 for (i = 0; i < n; i++) { 580 Object o = incoming.elementAt(i); 581 582 if (!returns.contains(o) && returns.size() < max) { 583 returns.addElement(o); 584 585 } 586 } 587 } 588 589 } 590