xref: /illumos-gate/usr/src/lib/libslp/javalib/com/sun/slp/UARequester.java (revision 55fea89dcaa64928bed4327112404dcb3e07b79f)
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