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