/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1999 by Sun Microsystems, Inc.
* All rights reserved.
*
*/
// ServiceType.java: Model a service type.
// Author: James Kempf
// Created On: Thu Apr 9 09:23:18 1998
// Last Modified By: James Kempf
// Last Modified On: Mon Oct 19 15:43:18 1998
// Update Count: 33
//
package com.sun.slp;
import java.util.*;
import java.io.*;
/**
* The ServiceType class conceals the complex details of whether a
* service type name is a simple URL scheme identifier, a service:
* type, an abstract type or protocol type.
*
* @author James Kempf
*/
public class ServiceType extends Object implements Serializable {
boolean isServiceURL = true; // was it originally a service: type?
private String type1 = ""; // scheme, abstract, or protocol.
private String type2 = ""; // concrete, if type was abstract.
private String na = ""; // naming authority.
// For removing IANA.
static final String IANA = "iana";
/**
* Create a service type object from the type name. The name may
* take the form of any valid SLP service type name.
*
* @param t The type name.
* @return The ServiceType object.
* @exception IllegalArgumentException If the name is syntactically
* incorrect.
*/
public ServiceType(String t) throws IllegalArgumentException {
parse(t);
}
/**
* Return true if type name was from a service: URL.
*
* @return True if type name came from service: URL.
*/
public boolean isServiceURL() {
return isServiceURL;
}
/**
* Return true if type name is for an abstract type.
*
* @return True if type name is for an abstract type.
*/
public boolean isAbstractType() {
return (type2.length() > 0);
}
/**
* Return true if naming authority is default.
*
* @return True if naming authority is default.
*/
public boolean isNADefault() {
return (na.length() <= 0);
}
/**
* Return the concrete service type name without naming authority.
*
* @return concrete type name.
*/
public String getConcreteTypeName() {
return type2;
}
/**
* Return the principle type name, which is either the abstract
* type name or the protocol name, without naming authority.
*
* @return Principle type name.
*/
public String getPrincipleTypeName() {
return type1;
}
/**
* Return the fully formatted abstract type name, if it is an abstract
* type, otherwise the empty string.
*/
public String getAbstractTypeName() {
if (isAbstractType()) {
return "service:" + type1 + (na.length() > 0 ? ("." + na):"");
}
return "";
}
/**
* Return the naming authority name.
*
* @return Naming authority name.
*/
public String getNamingAuthority() {
return na;
}
/**
*Validate a naming authority name.
*/
static void validateTypeComponent(String name)
throws ServiceLocationException {
validateTypeComponentInternal(name, false);
}
// Validate, allowing '.' if allowDot is true.
static private void
validateTypeComponentInternal(String name, boolean allowDot)
throws ServiceLocationException {
int i, n = name.length();
for (i = 0; i < n; i++) {
char c = name.charAt(i);
if ((Character.isLetterOrDigit(c) == false) &&
(c != '+') && (c != '-')) {
boolean throwIt = true;
// If dot is allowed, don't throw it.
if (allowDot && (c == '.')) {
throwIt = false;
}
if (throwIt) {
throw
new IllegalArgumentException(
SLPConfig.getSLPConfig().formatMessage("service_type_syntax",
new Object[] {name}));
}
}
}
}
// Two service type names are equal if they have the same
// types, naming authority, and same service: flag.
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof ServiceType)) {
return false;
}
ServiceType type = (ServiceType)o;
return
(isServiceURL == type.isServiceURL) &&
type1.equals(type.type1) &&
type2.equals(type.type2) &&
na.equals(type.na);
}
// Format the service type name for output.
public String toString() {
return
(isServiceURL ? "service:" : "") +
type1 +
(na.length() > 0 ? ("." + na) : "") +
(type2.length() > 0 ? (":" + type2) : "");
}
// Return a hash code for the type.
public int hashCode() {
return type1.hashCode() +
na.hashCode() +
type2.hashCode() +
(isServiceURL ? Defaults.SERVICE_PREFIX.hashCode():0);
}
// Parse a service type name with optional naming authority.
private void parse(String t) {
StringTokenizer st = new StringTokenizer(t, ":.", true);
try {
// This loop is a kludgy way to break out of the parse so
// we only throw at one location in the code.
do {
String tok = st.nextToken();
if (tok.equals(":") || tok.equals(".")) {
break; // error!
}
// Look for a nonservice: URL.
if (!tok.equalsIgnoreCase(Defaults.SERVICE_PREFIX)) {
isServiceURL = false;
// Need to eat through all dots.
do {
type1 = type1 + tok.toLowerCase();
// Break when we run out of tokens.
if (!st.hasMoreTokens()) {
break;
}
tok = st.nextToken();
} while (true);
// Check for disallowed characters. Allow '.'.
validateTypeComponentInternal(type1, true);
// There should be no more tokens.
if (st.hasMoreTokens()) {
break; // error!
}
return; // done!
}
tok = st.nextToken();
if (!tok.equals(":")) {
break; // error!
}
// Get the protocol or abstract type name.
type1 = st.nextToken().toLowerCase();
validateTypeComponent(type1);
// From here on in, everything is optional, so be sure
// to check for no remaining tokens.
if (!st.hasMoreTokens()) {
return;
// done! It's a simple protocol type w.o. naming authority.
}
// It's either got a naming authority or is an abstract
// type (or both).
tok = st.nextToken();
// Check for naming authorithy.
if (tok.equals(".")) {
tok = st.nextToken();
validateTypeComponent(tok);
if (!tok.equalsIgnoreCase(IANA)) {
na = tok.toLowerCase();
} else {
// Error to have IANA.
break;
}
if (!st.hasMoreTokens()) {
return;
// done! It's a simple protocol type w. naming authority.
}
tok = st.nextToken();
}
// Should be at the separator to concrete type.
if (!tok.equals(":")) {
break; // error!
}
tok = st.nextToken();
// This is the concrete type name.
validateTypeComponent(tok);
type2 = tok.toLowerCase();
// Should be no more tokens.
if (st.hasMoreTokens()) {
break; // error!
}
return; // done!
} while (false);
} catch (NoSuchElementException ex) {
throw
new IllegalArgumentException(
SLPConfig.getSLPConfig().formatMessage("service_type_syntax",
new Object[] {t}));
} catch (ServiceLocationException ex) {
throw
new IllegalArgumentException(ex.getMessage());
}
throw
new IllegalArgumentException(
SLPConfig.getSLPConfig().formatMessage("service_type_syntax",
new Object[] {t}));
}
}