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