xref: /illumos-gate/usr/src/lib/libslp/javalib/com/sun/slp/SLPTemplateRegistry.java (revision a5f69788de7ac07553de47f7fec8c05a9a94c105)
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:      @(#)SLPTemplateRegistry.java	1.2	06/12/98
31 //  SLPTemplateRegistry.java: Service object for registering a new service
32 //			  template.
33 //  Author:           James Kempf
34 //  Created On:       Tue May 27 15:04:35 1997
35 //  Last Modified By: James Kempf
36 //  Last Modified On: Thu Jan  7 14:25:20 1999
37 //  Update Count:     134
38 //
39 
40 package com.sun.slp;
41 
42 import java.util.*;
43 
44 /**
45  * The SLPTemplateRegistry class registers and unregisters service templates,
46  * looks up the template based on the service type name, and returns an
47  * attribute verifier for the service.It subclasses the TemplateRegistry
48  * abstract class.
49  *
50  * An slp-template URL has the following format:
51  *
52  *   service:slp-template:<document URL>;type=<service type>;
53  *				          version=<version no.>;
54  *					  language=<language locale>
55  *
56  * @author James Kempf
57  * @version 1.2 98/10/14
58  *
59  */
60 
61 class SLPTemplateRegistry extends TemplateRegistry {
62 
63     /**
64      * Attribute id for attribute describing service type name.
65      * String, single valued attribute.
66      */
67 
68     static final String SERVICE_ATTR_ID = "template-type";
69 
70     /**
71      * Attribute id for attribute describing help text.
72      * String, single valued, required attribute, .
73      */
74 
75     static final String DESCRIPTION_ATTR_ID = "template-description";
76 
77     /**
78      * Attribute id for attribute describing service version. The
79      * version number is of the form ``n.m'', where n and m are integers.
80      * String, single valued, required attribute.
81      */
82 
83     static final String VERSION_ATTR_ID = "template-version";
84 
85     /**
86      * Attribute id for attribute describing service URL url part grammer.
87      * String, single valued, required attribute.
88      */
89 
90     static final String SERVICE_URL_ATTR_ID = "template-url-syntax";
91 
92     /**
93      * The service type name for the template type.
94      */
95 
96     static final String TEMPLATE_SERVICE_TYPE = "service:slp-template";
97 
98     // The distinguished template registry object.
99 
100     private static TemplateRegistry registry = null;
101 
102     // Package private constructor for singleton pattern maintained
103     // by the ServiceLocationManager.
104 
105     SLPTemplateRegistry() throws ServiceLocationException {
106 
107     }
108 
109     //
110     // Public implementation.
111     //
112 
113     /**
114      * Register the new service.
115      *
116      * @param serviceType	Name of the service.
117      * @param documentURL	URL of the template document.
118      * @param languageLocale	Locale of the template langugae.
119      * @param version		Version number of template document.
120      * @exception ServiceLocationException Error code is
121      *				    INVALID_REGISTRATION
122      *					   if the service already exists or
123      *					   the registration fails.
124      *					   Throws
125      *				    SYSTEM_ERROR
126      *					   if the scope vector is null or
127      *					   empty.
128      *					   Throws
129      *				    PARSE_ERROR
130      *					   if an attribute is bad.
131      * @exception IllegalArgumentException Thrown if any parameters are null.
132      *
133      */
134 
135     public void registerServiceTemplate(ServiceType serviceType,
136 					String documentURL,
137 					Locale languageLocale,
138 					String version)
139 	throws ServiceLocationException {
140 
141 	// Check for illegal parameters.
142 
143 	Assert.nonNullParameter(serviceType, "serviceType");
144 
145 	Assert.nonNullParameter(documentURL, "documentURL");
146 
147 	Assert.nonNullParameter(languageLocale, "language");
148 
149 	Assert.nonNullParameter(version, "version");
150 
151 	String language = languageLocale.getLanguage();
152 
153 	if (language == null || language.length() <= 0) {
154 	    throw
155 		new IllegalArgumentException(
156 		SLPConfig.getSLPConfig().formatMessage("template_lang_null",
157 						       new Object[] {
158 		    documentURL}));
159 	}
160 
161 	String turl = null;
162 
163 	try {
164 
165 	    turl = findTemplateURL(serviceType,
166 				   languageLocale,
167 				   version);
168 
169 	} catch (ServiceLocationException ex) {
170 
171 	    // Ignore if language not supported, it just means there
172 	    //  isn't any.
173 
174 	    if (ex.getErrorCode() !=
175 		ServiceLocationException.LANGUAGE_NOT_SUPPORTED) {
176 		throw ex;
177 
178 	    }
179 	}
180 
181 	// Throw an exception if it exists.
182 
183 	if (turl != null) {
184 	    throw
185 		new ServiceLocationException(
186 				ServiceLocationException.INVALID_REGISTRATION,
187 				"template_already_registered",
188 				new Object[] {
189 		    documentURL,
190 			version,
191 			languageLocale});
192 	}
193 
194 	// Construct attributes for the registration.
195 
196 	Vector attributes = new Vector();
197 
198 	// Add the service type name.
199 
200 	Vector values = new Vector();
201 	values.addElement(serviceType.toString());
202 	ServiceLocationAttribute attr =
203 	    new ServiceLocationAttribute(SERVICE_ATTR_ID, values);
204 
205 	attributes.addElement(attr);
206 
207 	// Add the version.
208 
209 	values = new Vector();
210 	values.addElement(version);
211 	attr =
212 	    new ServiceLocationAttribute(VERSION_ATTR_ID, values);
213 
214 	attributes.addElement(attr);
215 
216 	// Construct a service URL for the template.
217 
218 	ServiceURL surl =
219 	    new ServiceURL(TEMPLATE_SERVICE_TYPE +
220 			   ":"+
221 			   documentURL+
222 			   ";"+
223 			   SERVICE_ATTR_ID+
224 			   "="+
225 			   serviceType+
226 			   ";"+
227 			   VERSION_ATTR_ID+
228 			   "="+
229 			   version,
230 			   ServiceURL.LIFETIME_MAXIMUM);
231 
232 
233 	// Do the registration.
234 
235 	Advertiser serviceAgent =
236 	    ServiceLocationManager.getAdvertiser(languageLocale);
237 
238 	if (serviceAgent == null) {
239 	    throw
240 		new ServiceLocationException(
241 				ServiceLocationException.NOT_IMPLEMENTED,
242 				"no_advertiser",
243 				new Object[0]);
244 	}
245 
246 	serviceAgent.register(surl, attributes);
247 
248 	// Note that the assumption here is that the URL containing the
249 	//  path to the template document is written "somehow".
250 	//  It is up to the client to make sure that the template document
251 	//  has been written.
252 
253     }
254 
255     /**
256      * Deregister the template for service type.
257      *
258      * @param serviceType	Name of service.
259      * @param <i>languageLocale</i> Language locale of template.
260      * @param <i>version</i> Version of the template, null for latest.
261      * @exception ServiceLocationException Thrown if the deregistration
262      *					  fails.
263      * @exception IllegalArgumentException Thrown if the parameter is null.
264      *
265      */
266 
267     public void deregisterServiceTemplate(ServiceType serviceType,
268 					  Locale languageLocale,
269 					  String version)
270 	throws ServiceLocationException {
271 
272 	// Check the parameter.
273 
274 	Assert.nonNullParameter(serviceType, "serviceType");
275 
276 	Assert.nonNullParameter(languageLocale, "languageLocale");
277 
278 	// Get the template document URL for the service.
279 
280 	ServiceURL turl = findVersionedURL(serviceType,
281 					   languageLocale,
282 					   version);
283 
284 	// If there's no template, then throw an exception.
285 
286 	if (turl == null) {
287 	    throw
288 		new ServiceLocationException(
289 				ServiceLocationException.INVALID_REGISTRATION,
290 				"template_not_registered",
291 				new Object[] {
292 		    serviceType,
293 			version,
294 			languageLocale});
295 	}
296 
297 	// Deregister in all scopes.
298 
299 	Advertiser serviceAgent =
300 	    ServiceLocationManager.getAdvertiser(languageLocale);
301 
302 	if (serviceAgent == null) {
303 	    throw
304 		new ServiceLocationException(
305 				ServiceLocationException.NOT_IMPLEMENTED,
306 				"no_advertiser",
307 				new Object[0]);
308 	}
309 
310 	// Deregister the service URL.
311 
312 	serviceAgent.deregister(turl);
313 
314     }
315 
316 
317 
318     /**
319      * Find the service URL for the service.
320      *
321      * @param serviceType		Name of service.
322      * @param <i>languageLocale</i> Language locale of template.
323      * @param <i>version</i> Version of the template, null for latest.
324      * @return ServiceURL for the service template. If the service doesn't
325      *		exist, returns null.
326      * @exception ServiceLocationException Error code is
327      *				    SYSTEM_ERROR
328      *					   if the scope vector is null or
329      *					   empty or if more than one
330      *					   template URL is returned.
331      * @exception IllegalArgumentException Thrown if any parameters are null.
332      *
333      */
334 
335     public String findTemplateURL(ServiceType serviceType,
336 				  Locale languageLocale,
337 				  String version)
338 	throws ServiceLocationException {
339 
340 	// Check the parameter.
341 
342 	Assert.nonNullParameter(serviceType, "serviceType");
343 
344 	Assert.nonNullParameter(languageLocale, "languageLocale");
345 
346 	ServiceURL turl = findVersionedURL(serviceType,
347 					   languageLocale,
348 					   version);
349 
350 	// If nothing returned, then simply return.
351 
352 	if (turl == null) {
353 	    return null;
354 
355 	}
356 
357 	// Form the document URL.
358 
359 	ServiceType type = turl.getServiceType();
360 	String url = turl.toString();
361 	String abstractType = type.getAbstractTypeName();
362 
363 	if (!abstractType.equals(TEMPLATE_SERVICE_TYPE)) {
364 	    throw
365 		new ServiceLocationException(
366 				ServiceLocationException.PARSE_ERROR,
367 				"template_url_malformed",
368 				new Object[] {turl});
369 
370 	}
371 
372 	// Parse off the URL path.
373 
374 	int idx = url.indexOf(";"+SERVICE_ATTR_ID+"=");
375 
376 	if (idx == -1) {
377 	    throw
378 		new ServiceLocationException(
379 				ServiceLocationException.PARSE_ERROR,
380 				"template_url_malformed",
381 				new Object[] {turl});
382 
383 	}
384 
385 	int jdx = TEMPLATE_SERVICE_TYPE.length() + 1; // don't forget :!!!
386 
387 	// Return the document URL.
388 
389 	return url.substring(jdx, idx);
390     }
391 
392     // Return a URL given a version and language locale.
393 
394     private ServiceURL findVersionedURL(ServiceType serviceType,
395 					Locale languageLocale,
396 					String version)
397 	throws ServiceLocationException {
398 
399 	// Templates should be registered in all scopes. Look for them
400 	//  in all.
401 
402 	Vector scopes = ServiceLocationManager.findScopes();
403 
404 	// Set up query.
405 
406 	ServiceLocationEnumeration results = null;
407 	String query = "(" + SERVICE_ATTR_ID + "=" + serviceType + ")";
408 
409 	if (version != null) {
410 	    query = query + "(" + VERSION_ATTR_ID + "=" + version + ")";
411 
412 	}
413 
414 	query = "(&" + query + ")";
415 
416 	// Get user agent for query.
417 
418 	Locator userAgent =
419 	    ServiceLocationManager.getLocator(languageLocale);
420 
421 	if (userAgent == null) {
422 	    throw
423 		new ServiceLocationException(
424 				ServiceLocationException.NOT_IMPLEMENTED,
425 				"no_locator",
426 				new Object[0]);
427 	}
428 
429 	try {
430 	    ServiceType type = new ServiceType(TEMPLATE_SERVICE_TYPE);
431 
432 	    results =
433 		userAgent.findServices(type,
434 				       scopes,
435 				       query);
436 
437 	} catch (ServiceLocationException ex) {
438 
439 	    // If language not supported, it just means none there.
440 
441 	    if (ex.getErrorCode() !=
442 		ServiceLocationException.LANGUAGE_NOT_SUPPORTED) {
443 		throw ex;
444 
445 	    }
446 
447 	}
448 
449 	// If nothing came back, then return null.
450 
451 	if (!results.hasMoreElements()) {
452 	    return null;
453 
454 	}
455 
456 
457 	ServiceURL turl = null;
458 	float highest = (float)-1.0;
459 
460 	// If there's more than one service of this type registered, then
461 	//  take highest version if version number was null.
462 
463 	while (results.hasMoreElements()) {
464 	    ServiceURL surl = (ServiceURL)results.nextElement();
465 	    String urlPath = surl.getURLPath();
466 
467 	    if (version == null) {
468 
469 		// Get the version attribute from the URL.
470 
471 		String token = ";"+VERSION_ATTR_ID+"=";
472 
473 		int idx = urlPath.indexOf(token);
474 
475 		if (idx == -1) { // ignore, there may be more...
476 		    continue;
477 
478 		}
479 
480 		urlPath =
481 		    urlPath.substring(idx+token.length(), urlPath.length());
482 
483 		idx = urlPath.indexOf(";");
484 
485 		if (idx == -1) { // ignore, there may be more...
486 		    continue;
487 
488 		}
489 
490 		String temversion = urlPath.substring(0, idx);
491 		float current = (float)0.0;
492 
493 		// Convert to float.
494 
495 		try {
496 
497 		    current = Float.valueOf(temversion).floatValue();
498 
499 		} catch (NumberFormatException ex) {
500 
501 		    continue;  // ignore, there may be more...
502 
503 		}
504 
505 		// Identify if this is the highest version number so far.
506 
507 		if (current > highest) {
508 		    turl = surl;
509 		}
510 
511 	    } else {
512 
513 		// If we found more than one, may be a problem.
514 
515 		if (turl != null) {
516 
517 		    throw
518 			new ServiceLocationException(
519 				ServiceLocationException.INTERNAL_SYSTEM_ERROR,
520 				"template_multiple",
521 				new Object[] {
522 			    serviceType,
523 				version,
524 				languageLocale});
525 		}
526 
527 		turl = surl;
528 	    }
529 	}
530 
531 	return turl;
532     }
533 
534     /**
535      * Create an attribute verifier for the template document URL.
536      *
537      * @param documentURL A URL for the template document URL.
538      * @return An attribute verifier for the service
539      * @exception ServiceLocationException Throws
540      *					  PARSE_ERROR
541      *					  if any syntax errors
542      *					  are encountered during parsing
543      *					  of service's template definition.
544      *					  Throws
545      *					SYSTEM_ERROR
546      *					  if URL parsing error occurs.
547      *					  Throws ServiceLocationException
548      *					  if any other errors occur.
549      * @exception IllegalArgumentException Thrown if any parameters are null.
550      *
551      */
552 
553     public ServiceLocationAttributeVerifier attributeVerifier(
554 							String documentURL)
555 	throws ServiceLocationException {
556 
557 	// Check the parameter.
558 
559 	Assert.nonNullParameter(documentURL, "documentURL");
560 
561 	// Create a URL attribute parser to parse the document.
562 
563 	return new URLAttributeVerifier(documentURL);
564     }
565 
566 }
567