/*
* 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
* 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-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
*/
// AttributeVerifier.java: An attribute verifier for SLP attributes.
// Author: James Kempf
// Created On: Thu Jun 19 10:51:32 1997
// Last Modified By: James Kempf
// Last Modified On: Mon Nov 9 10:21:02 1998
// Update Count: 200
//
/**
* The AttributeVerifier class implements the ServiceLocationAttributeVerifier
* interface, but without committment to a particular mechanism for
* obtaining the template defintion. Subclasses provide the mechanism,
* and pass in the template to the parent as a Reader during object
* creation. The AttributeVerifier class parses tokens from the Reader and
* constructs the attribute descriptor objects describing the attribute. These
* are used during verification of the attribute. The AttributeVerifier
* and implementations of the attribute descriptors are free to optimize
* space utilization by lazily evaluating portions of the attribute
* template.
*
* @author James Kempf
*
*/
class AttributeVerifier
extends Object
implements ServiceLocationAttributeVerifier {
// Template specific escape.
// Number of template attributes.
// Bitfields for found template attributes.
// When all template attribute assignments are found.
// These are the valid SLP types.
// These are the corresponding Java types. Package public so
// others (SLPConfig for example) can get at them.
"java.lang.String";
"java.lang.Integer";
"java.lang.Boolean";
"[B";
// Tokens for boolean values.
// This is the number of flags.
// These are the flags.
// These masks help determine whether the flags have been duplicated.
// These are tokens for separator characters.
// This token is for checking version number
// attribute assignment.
// Radix64 code characters.
// The SLP service type of this template.
// The template's language locale.
// The template's version.
// The template's URL syntax.
// The template's description.
// The attribute descriptors.
//
// Constructors.
}
// Initialize the attribute verifier with a reader. Subclasses or clients
// pass in a Reader on the template that is used for parsing. This
// method is used when the template includes the template attributes
// and URL rules.
// Use a StreamTokenizer to parse.
// Initialize tokenizer for parsing main.
// Now parse the attribute template, including template attributes.
}
// Initialize with this method when no template attributes are involved.
throws ServiceLocationException {
// Use a StreamTokenizer to parse.
// Initialize tokenizer for parsing main.
// Now parse the attribute templates, but no template attributes.
}
//
// ServiceLocationAttributeVerifier interface implementation.
//
/**
* Returns the SLP service type for which this is the verifier.
*
* @return The SLP service type name.
*/
return serviceType;
}
/**
* Returns the SLP language locale of this is the verifier.
*
* @return The SLP language locale.
*/
return locale;
}
/**
* Returns the SLP version of this is the verifier.
*
* @return The SLP version.
*/
return version;
}
/**
* Returns the SLP URL syntax of this is the verifier.
*
* @return The SLP URL syntax.
*/
return URLSyntax;
}
/**
* Returns the SLP description of this is the verifier.
*
* @return The SLP description.
*/
return description;
}
/**
* Returns the ServiceLocationAttributeDescriptor object for the
* attribute having the named id. IF no such attribute exists in the
* template, returns null. This method is primarily for GUI tools to
* display attribute information. Programmatic verification of attributes
* should use the verifyAttribute() method.
*
* @param attrId Id of attribute to return.
* @return The ServiceLocationAttributeDescriptor object corresponding
* to the parameter, or null if none.
*/
return
}
/**
* Returns an Enumeration of
* ServiceLocationAttributeDescriptors for the template. This method
* is primarily for GUI tools to display attribute information.
* Programmatic verification of attributes should use the
* verifyAttribute() method. Note that small memory implementations
* may want to implement the Enumeration so that attributes are
* parsed on demand rather than at creation time.
*
* @return A Dictionary with attribute id's as the keys and
* ServiceLocationAttributeDescriptor objects for the
* attributes as the values.
*/
}
/**
* Verify that the attribute parameter is a valid SLP attribute.
*
* @param attribute The ServiceLocationAttribute to be verified.
*/
throws ServiceLocationException {
throw
"template_no_attribute",
}
// If keyword, check that no values were specified.
if (des.getIsKeyword()) {
throw
"template_not_null",
}
} else {
int i, n;
// Check that a values vector exists, and, if the attribute is
// not multivalued, only one element is in it.
throw
"template_null",
}
throw
"template_not_multi",
}
// Get allowed values.
if (en.hasMoreElements()) {
while (en.hasMoreElements()) {
// Lower case if string, convert to Opaque if byte array.
v = ((String)v).toLowerCase();
v = new Opaque((byte[])v);
}
av.addElement(v);
}
}
// Check that the types of the values vector match the attribute
// type. Also, if any allowed values, that attribute values
// match.
for (i = 0; i < n; i++) {
throw
"template_type_mismatch",
}
// Convert value for comparison, if necessary.
}
throw
"template_not_allowed_value",
}
}
}
// No way to verify `X' because that's a search property. We
// must verify `O' in the context of an attribute set.
}
/**
* Verify that the set of registration attributes matches the
* required attributes for the service.
*
* @param attributeVector A Vector of ServiceLocationAttribute objects
* for the registration.
* @exception ServiceLocationException Thrown if the
* attribute set is not valid. The message contains information
* on the attribute name and problem.
*/
throws ServiceLocationException {
// Check whether any attributes are required. If so, then
// there's an error.
while (en.hasMoreElements()) {
if (!attDesc.getIsOptional()) {
throw
"template_missing_required",
}
}
} else {
// Construct a hashtable of incoming objects, verifying them
// while doing so.
int i, n = attributeVector.size();
for (i = 0; i < n; i++) {
// If we already have it, signal a duplicate.
throw
"template_dup",
}
}
// Now check that all required attributes are present.
while (en.hasMoreElements()) {
if (!attDesc.getIsOptional() &&
throw
"template_missing_required",
}
}
}
}
//
// Private implementation. This is the template attribute parser.
//
//
// Tokenizer initializers.
// Base initialization. Resets syntax tables, sets up EOL parsing,
// and makes word case significant.
// Each part of an attribute production must specify which
// characters belong to words.
tk.resetSyntax();
// Note that we have to make EOL be whitespace even if significant
// because otherwise the line number won't be correctly incremented.
// Don't lower case tokens.
tk.lowerCaseMode(false);
}
// Initialize those token characters that appear in all
// productions.
// These characters are recognized as parts of tokens.
}
// Initialize tokenizer for parsing attribute name,
// attribute type and flags,
// and for boolean initializer lists.
// Need backslash for escaping.
// Attribute id, Type, flags, and boolean initialzers
// all ignore white space.
// Attribute part won't view newline as being significant.
tk.eolIsSignificant(false);
// Case is not folded.
tk.lowerCaseMode(false);
}
// Initialize tokenizer for parsing service type name.
// need to restrict characters.
// Scheme name, type, flags, and boolean initialzers
// all ignore white space.
// Scheme part won't view newline as being significant.
tk.eolIsSignificant(false);
// Case is not folded.
tk.lowerCaseMode(false);
}
// Initialize tokenizer for string list parsing.
// Everything except '#' and ',' is recognized.
// Note that whitespace is significant, but
// EOL is ignored.
// '#' goes here
// ',' goes here
// ';' goes here
// '%' is also reserved, but it is postprocessed
// after the string is collected.
// Parse by lines to check when we've reached the end of the list.
tk.eolIsSignificant(true);
}
// Initialize tokenizer for integer list parsing.
// Integer value list parsing ignores white space.
// Parse by lines so we can find the end.
tk.eolIsSignificant(true);
}
// Boolean lists have same item syntax as scheme char.
// Initialize main production parsing. The only
// significant token character is <NL> because
// parsing is done on a line-oriented basis.
tk.eolIsSignificant(true);
}
//
// Parsing methods.
//
// Parse a template from the tokenizer.
throws ServiceLocationException {
// First parse past the template attributes.
// Finally, parse the attributes.
}
// Parse the template attributes from the tokenizer.
throws ServiceLocationException {
int found = 0;
// Parse each of the template attributes. Note that we are parsing
// the attribute value assignments, not definitions.
try {
do {
} while (found != TEMPLATE_FOUND);
} catch (IOException ex) {
throw
"template_io_error",
}
}
// Parse a template attribute.
throws ServiceLocationException, IOException {
// Get line including id and equals.
throw
"template_assign_error",
}
// Get tokenizer for id and potential value line.
// Make sure newline is there.
throw
"template_end_error",
}
throw
"template_unk_token",
}
// Parse off id.
throw
"template_missing_id",
}
boolean duplicate = false;
int mask = 0;
// Check for the equals.
throw
"template_missing_eq ",
}
// Depending on the id, parse the rest.
// Just need to parse off the service type.
throw
"template_srv_type_err",
}
// Check for characters which are not alphanumerics, + and -.
// Service type names are more heavily restricted.
throw
"template_srv_type_err",
}
// Need to prefix with "serivce:".
}
// Set service type instance variable.
// Check for extra stuff.
throw
"template_srv_type_err",
}
mask = SERVICE_MASK;
} else {
duplicate = true;
}
// Just need to parse off the version number.
throw
"template_vers_err",
}
// Make sure it's a valid version number.
throw
"template_vers_mssing",
}
try {
} catch (NumberFormatException ex) {
throw
"template_vers_err",
}
// Check for extra stuff.
throw
"template_vers_err",
}
mask = VERSION_MASK;
} else {
duplicate = true;
}
} else if (id.equalsIgnoreCase(
// Make sure there is nothing else on that line.
throw
"template_attr_syntax",
}
// Need to continue parsing help text until we reach a blank
// line.
do {
// If previous token was end of line, quit.
// Store any text first.
}
break;
}
throw
"template_end_error",
} else {
throw
"template_unk_token",
}
} while (true);
} else {
duplicate = true;
}
} else if (id.equalsIgnoreCase(
// Pull everything out of the rdr StringReader until empty.
int ic;
serviceURLGrammer += (char)ic;
}
serviceURLGrammer += "\n";
// Need to continue parsing service URL syntax until we
// reach a blank line.
do {
// If previous token was end of line, quit.
// Store any text first.
}
break;
}
throw
"template_end_error",
} else {
throw
"template_unk_token",
}
} while (true);
} else {
duplicate = true;
}
} else {
throw
"template_nontattribute_err",
}
// Throw exception if a duplicate definition was detected.
if (duplicate) {
throw
"template_dup_def",
}
// Make sure the assignment ends with a blank line.
throw
"template_attr_syntax",
}
return mask;
}
// Parse the attributes from the tokenizer.
throws ServiceLocationException {
try {
do {
// Check if at end of file yet.
break;
}
// If not, push token back so we can get it next time.
// Parse off the attribute descriptor.
// Check whether default values, if any, are correct.
// If the attribute already exists, then throw exception.
// We could arguably replace existing, but it might
// suprise the user.
throw
"template_dup_def",
}
// Add the attribute to the descriptor table.
} while (true);
} catch (IOException ex) {
throw
"template_io_error",
}
}
// Parse a single attribute description from the tokenizer.
private AttributeDescriptor
int lineno = 0;
try {
// Parse the string for attribute id, type, and flags.
throw
"template_attr_syntax",
}
// Parse the attribute id.
// Parse the type and flags.
throw
"template_end_error",
}
throw
"template_unk_token",
}
// Parse initial values.
if (!attDesc.getIsKeyword()) {
// Read in entire list.
do {
// Trim line, check for '#', indicating end of list.
// it's help text already.
stk =
}
break;
} else {
// Otherwise concatenate onto growing list.
}
// end of attribute definition.
// Process any accumulated list.
stk =
}
return attDesc;
}
throw
"template_end_error",
} else {
throw
"template_unk_token",
}
} while (true);
} else {
// Check for end of definition.
return attDesc;
// Check for start of help text.
throw
"template_attr_syntax",
} else {
}
throw
"template_end_error",
} else {
throw
"template_unk_token",
}
}
// Parse help text.
do {
// Check for end of help text.
// Help text is collected verbatim after '#'.
helpText =
} else {
// We've reached the end of the help text. Store it
// and break out of the loop.
}
break;
}
// If previous token was end of line, quit.
// Store any text first.
}
// If this is a keyword attribute, set the allowed
// values list to null.
if (attDesc.getIsKeyword()) {
}
return attDesc;
// Error if previous token wasn't EOL.
throw
"template_end_error",
}
} else {
throw
"template_unk_token",
}
} while (true);
// Parse allowed values.
if (!attDesc.getIsKeyword()) {
// Read in entire list.
do {
// Concatenate onto growing list.
// end of attribute definition.
// Process any accumulated list.
stk =
}
return attDesc;
}
throw
"template_end_error",
} else {
throw
"template_unk_token",
}
} while (true);
} else {
// Error. Keyword attribute should have ended during help text
// parsing or before.
throw
"template_attr_syntax",
}
} catch (IOException ex) {
throw
"template_io_error",
new Object[] {
ex.getMessage()});
}
}
// Check whether the default values, if any, are correct.
throws ServiceLocationException {
// Don't bother if it's a keyword attribute, parsing has checked.
if (attDesc.getIsKeyword()) {
return;
}
// First, collect the allowed values.
while (en.hasMoreElements()) {
// Lower case strings and create opaques for comparison
// if type is opaque.
}
}
// Now compare the allowed with the initial.
// Error if allowed is restricted but no initializers.
if (!init.hasMoreElements()) {
throw
"template_no_init",
}
// Compare init values with allowed.
while (init.hasMoreElements()) {
}
return; // found it!
}
}
// Initializer wasn't found.
throw
"template_wrong_init",
new Object[] {
}
}
// Parse the attribute's id string.
int baseLineno)
throws ServiceLocationException, IOException {
// Parse the attribute's identifier tag.
// Parse the seperator.
throw
"template_attr_syntax",
new Object[] {
}
// Expand out any escaped ``#''. It won't be handled by
// SLA.
// Expand out character escapes.
id =
}
// Parse the attribute's type and flags.
private void
int baseLineno)
throws ServiceLocationException, IOException {
int existingFlags = 0;
// Parse the attribute's type.
// Parse the flags.
do {
// Check if any flags are left.
break;
} else {
}
// Parse the flag.
// Error if flags with keyword.
if (attDesc.getIsKeyword()) {
throw
"template_attr_syntax",
new Object[] {
}
// Check and assign it to the attribute.
baseLineno + lineno);
} while (true);
}
// Parse the attribute's initial value(s).
int baseLineno)
throws ServiceLocationException, IOException {
// First get the vector of initial values.
// Check whether it works for this attribute. Type
// checking will be done by value list parsing.
throw
"template_attr_syntax",
new Object[] {
}
}
// Parse the attribute's allowed values.
private void
int baseLineno)
throws ServiceLocationException, IOException {
// First get the vector of all allowed values.
// Now set the allowed value vector.
}
// Parse a value list.
int baseLineno)
throws ServiceLocationException, IOException {
// Set up the tokenizer according to the type of the
// attribute.
}
// Parse through a potentially multivalued value list.
boolean wordRequired = true; // true when a word is required,
// false when a comma required.
boolean syntaxError = false;
int lineno = 0;
do {
// If a word isn't required, then the case is
// "token token" and is an error.
if (!wordRequired) {
syntaxError = true;
}
// Convert the value to the proper object.
wordRequired = false;
// If a word is required, then list ends with
// a comma, so error.
if (wordRequired) {
syntaxError = true;
}
break;
// If a word is required, then error. The case is ",,".
if (wordRequired) {
syntaxError = true;
break;
}
// Otherwise, the next token must be a word.
wordRequired = true;
} else {
// No other tokens are allowed.
syntaxError = true;
break;
}
} while (true);
if (syntaxError) {
throw
"template_attr_syntax",
}
return req;
}
// Check the type and add it to the attribute descriptor.
int lineno)
throws ServiceLocationException {
// Check token against recognized types.
attDesc.setIsKeyword(true);
} else {
throw
"template_not_slp_type",
}
}
// Check the flag and add it to the attribute descriptor.
int matched,
int lineno)
throws ServiceLocationException {
boolean duplicate = false;
// We depend on the attribute descriptor being initialized to
// nothing, i.e. false for all flags and for keyword.
duplicate = true;
} else {
// Check for boolean. Booleans may not have
// multiple values.
throw
"template_boolean_multi",
}
attDesc.setIsMultivalued(true);
return MULTIPLE_MASK;
}
duplicate = true;
} else {
attDesc.setIsLiteral(true);
return LITERAL_MASK;
}
duplicate = true;
} else {
attDesc.setRequiresExplicitMatch(true);
return EXPLICIT_MASK;
}
duplicate = true;
} else {
attDesc.setIsOptional(true);
return OPTIONAL_MASK;
}
} else {
throw
"template_invalid_attr_flag",
}
if (duplicate) {
throw
"template_dup_attr_flag",
}
return 0; // never happens.
}
// Parse a word out of the tokenizer. The exact characters
// will depend on what the syntax tables have been set to.
throws ServiceLocationException, IOException {
} else {
// Report the erroneous characters.
errorToken = "<end of line>";
errorToken = "<end of file>";
} else {
}
throw
"template_invalid_tok",
new Object[] {
}
}
// Convert a value list token to the value.
int lineno)
throws ServiceLocationException,
// Expand out any escaped ``#''. It won't be handled by
// SLA.
// Expand out character escapes.
reqVal =
false);
try {
} catch (NumberFormatException ex) {
throw
"template_expect_int",
new Object[] {
}
// Boolean.valueOf() doesn't handle this properly.
} else {
throw
"template_expect_bool",
new Object[] {
}
} else {
"template_attr_desc",
new Object[0]);
}
return reqVal;
}
// Expand out any escaped hashes. Not handled by SLA.
int i, j = 0;
i != -1;
j = i + len;
}
if (j < len) {
}
}
}