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 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 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 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 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 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 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 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 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 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