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