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 // ServiceType.java: Model a service type. 28 // Author: James Kempf 29 // Created On: Thu Apr 9 09:23:18 1998 30 // Last Modified By: James Kempf 31 // Last Modified On: Mon Oct 19 15:43:18 1998 32 // Update Count: 33 33 // 34 35 package com.sun.slp; 36 37 import java.util.*; 38 import java.io.*; 39 40 41 /** 42 * The ServiceType class conceals the complex details of whether a 43 * service type name is a simple URL scheme identifier, a service: 44 * type, an abstract type or protocol type. 45 * 46 * @author James Kempf 47 */ 48 49 public class ServiceType extends Object implements Serializable { 50 51 boolean isServiceURL = true; // was it originally a service: type? 52 private String type1 = ""; // scheme, abstract, or protocol. 53 private String type2 = ""; // concrete, if type was abstract. 54 private String na = ""; // naming authority. 55 56 // For removing IANA. 57 58 static final String IANA = "iana"; 59 60 /** 61 * Create a service type object from the type name. The name may 62 * take the form of any valid SLP service type name. 63 * 64 * @param t The type name. 65 * @return The ServiceType object. 66 * @exception IllegalArgumentException If the name is syntactically 67 * incorrect. 68 */ 69 ServiceType(String t)70 public ServiceType(String t) throws IllegalArgumentException { 71 72 parse(t); 73 74 } 75 76 /** 77 * Return true if type name was from a service: URL. 78 * 79 * @return True if type name came from service: URL. 80 */ 81 isServiceURL()82 public boolean isServiceURL() { 83 return isServiceURL; 84 85 } 86 87 /** 88 * Return true if type name is for an abstract type. 89 * 90 * @return True if type name is for an abstract type. 91 */ 92 isAbstractType()93 public boolean isAbstractType() { 94 return (type2.length() > 0); 95 96 } 97 98 /** 99 * Return true if naming authority is default. 100 * 101 * @return True if naming authority is default. 102 */ 103 isNADefault()104 public boolean isNADefault() { 105 return (na.length() <= 0); 106 107 } 108 109 /** 110 * Return the concrete service type name without naming authority. 111 * 112 * @return concrete type name. 113 */ 114 getConcreteTypeName()115 public String getConcreteTypeName() { 116 return type2; 117 118 } 119 120 /** 121 * Return the principle type name, which is either the abstract 122 * type name or the protocol name, without naming authority. 123 * 124 * @return Principle type name. 125 */ 126 getPrincipleTypeName()127 public String getPrincipleTypeName() { 128 return type1; 129 130 } 131 132 /** 133 * Return the fully formatted abstract type name, if it is an abstract 134 * type, otherwise the empty string. 135 */ 136 getAbstractTypeName()137 public String getAbstractTypeName() { 138 if (isAbstractType()) { 139 return "service:" + type1 + (na.length() > 0 ? ("." + na):""); 140 141 } 142 return ""; 143 144 } 145 146 /** 147 * Return the naming authority name. 148 * 149 * @return Naming authority name. 150 */ 151 getNamingAuthority()152 public String getNamingAuthority() { 153 return na; 154 155 } 156 157 /** 158 *Validate a naming authority name. 159 */ 160 validateTypeComponent(String name)161 static void validateTypeComponent(String name) 162 throws ServiceLocationException { 163 164 validateTypeComponentInternal(name, false); 165 } 166 167 // Validate, allowing '.' if allowDot is true. 168 169 static private void validateTypeComponentInternal(String name, boolean allowDot)170 validateTypeComponentInternal(String name, boolean allowDot) 171 throws ServiceLocationException { 172 int i, n = name.length(); 173 174 for (i = 0; i < n; i++) { 175 char c = name.charAt(i); 176 177 if ((Character.isLetterOrDigit(c) == false) && 178 (c != '+') && (c != '-')) { 179 boolean throwIt = true; 180 181 // If dot is allowed, don't throw it. 182 183 if (allowDot && (c == '.')) { 184 throwIt = false; 185 186 } 187 188 if (throwIt) { 189 throw 190 new IllegalArgumentException( 191 SLPConfig.getSLPConfig().formatMessage("service_type_syntax", 192 new Object[] {name})); 193 } 194 } 195 } 196 } 197 198 // Two service type names are equal if they have the same 199 // types, naming authority, and same service: flag. 200 equals(Object o)201 public boolean equals(Object o) { 202 203 if (o == this) { 204 return true; 205 206 } 207 208 if (!(o instanceof ServiceType)) { 209 return false; 210 211 } 212 213 ServiceType type = (ServiceType)o; 214 215 return 216 (isServiceURL == type.isServiceURL) && 217 type1.equals(type.type1) && 218 type2.equals(type.type2) && 219 na.equals(type.na); 220 221 } 222 223 // Format the service type name for output. 224 toString()225 public String toString() { 226 227 return 228 (isServiceURL ? "service:" : "") + 229 type1 + 230 (na.length() > 0 ? ("." + na) : "") + 231 (type2.length() > 0 ? (":" + type2) : ""); 232 233 } 234 235 // Return a hash code for the type. 236 hashCode()237 public int hashCode() { 238 239 return type1.hashCode() + 240 na.hashCode() + 241 type2.hashCode() + 242 (isServiceURL ? Defaults.SERVICE_PREFIX.hashCode():0); 243 244 } 245 246 // Parse a service type name with optional naming authority. 247 parse(String t)248 private void parse(String t) { 249 StringTokenizer st = new StringTokenizer(t, ":.", true); 250 251 try { 252 253 // This loop is a kludgy way to break out of the parse so 254 // we only throw at one location in the code. 255 256 do { 257 258 String tok = st.nextToken(); 259 260 if (tok.equals(":") || tok.equals(".")) { 261 break; // error! 262 263 } 264 265 // Look for a nonservice: URL. 266 267 if (!tok.equalsIgnoreCase(Defaults.SERVICE_PREFIX)) { 268 isServiceURL = false; 269 270 // Need to eat through all dots. 271 272 do { 273 type1 = type1 + tok.toLowerCase(); 274 275 // Break when we run out of tokens. 276 277 if (!st.hasMoreTokens()) { 278 break; 279 280 } 281 282 tok = st.nextToken(); 283 284 } while (true); 285 286 // Check for disallowed characters. Allow '.'. 287 288 validateTypeComponentInternal(type1, true); 289 290 // There should be no more tokens. 291 292 if (st.hasMoreTokens()) { 293 break; // error! 294 295 } 296 297 return; // done! 298 299 } 300 301 tok = st.nextToken(); 302 303 if (!tok.equals(":")) { 304 break; // error! 305 306 } 307 308 // Get the protocol or abstract type name. 309 310 type1 = st.nextToken().toLowerCase(); 311 312 validateTypeComponent(type1); 313 314 // From here on in, everything is optional, so be sure 315 // to check for no remaining tokens. 316 317 if (!st.hasMoreTokens()) { 318 return; 319 // done! It's a simple protocol type w.o. naming authority. 320 321 } 322 323 // It's either got a naming authority or is an abstract 324 // type (or both). 325 326 tok = st.nextToken(); 327 328 // Check for naming authorithy. 329 330 if (tok.equals(".")) { 331 tok = st.nextToken(); 332 333 validateTypeComponent(tok); 334 335 if (!tok.equalsIgnoreCase(IANA)) { 336 337 na = tok.toLowerCase(); 338 339 } else { 340 341 // Error to have IANA. 342 343 break; 344 345 } 346 347 if (!st.hasMoreTokens()) { 348 return; 349 // done! It's a simple protocol type w. naming authority. 350 351 } 352 353 tok = st.nextToken(); 354 355 } 356 357 // Should be at the separator to concrete type. 358 359 if (!tok.equals(":")) { 360 break; // error! 361 362 } 363 364 tok = st.nextToken(); 365 366 // This is the concrete type name. 367 368 validateTypeComponent(tok); 369 370 type2 = tok.toLowerCase(); 371 372 // Should be no more tokens. 373 374 if (st.hasMoreTokens()) { 375 break; // error! 376 377 } 378 379 return; // done! 380 381 } while (false); 382 383 } catch (NoSuchElementException ex) { 384 throw 385 new IllegalArgumentException( 386 SLPConfig.getSLPConfig().formatMessage("service_type_syntax", 387 new Object[] {t})); 388 389 } catch (ServiceLocationException ex) { 390 throw 391 new IllegalArgumentException(ex.getMessage()); 392 393 } 394 395 throw 396 new IllegalArgumentException( 397 SLPConfig.getSLPConfig().formatMessage("service_type_syntax", 398 new Object[] {t})); 399 400 } 401 402 } 403