17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 59a70fc3bSMark J. Nelson * Common Development and Distribution License (the "License"). 69a70fc3bSMark J. Nelson * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 227c478bd9Sstevel@tonic-gate * Copyright (c) 1999-2001 by Sun Microsystems, Inc. 237c478bd9Sstevel@tonic-gate * All rights reserved. 247c478bd9Sstevel@tonic-gate * 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27*55fea89dSDan Cross // AttributeVerifier.java: An attribute verifier for SLP attributes. 287c478bd9Sstevel@tonic-gate // Author: James Kempf 297c478bd9Sstevel@tonic-gate // Created On: Thu Jun 19 10:51:32 1997 307c478bd9Sstevel@tonic-gate // Last Modified By: James Kempf 317c478bd9Sstevel@tonic-gate // Last Modified On: Mon Nov 9 10:21:02 1998 327c478bd9Sstevel@tonic-gate // Update Count: 200 337c478bd9Sstevel@tonic-gate // 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate package com.sun.slp; 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate import java.util.*; 387c478bd9Sstevel@tonic-gate import java.io.*; 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /** 417c478bd9Sstevel@tonic-gate * The AttributeVerifier class implements the ServiceLocationAttributeVerifier 427c478bd9Sstevel@tonic-gate * interface, but without committment to a particular mechanism for 437c478bd9Sstevel@tonic-gate * obtaining the template defintion. Subclasses provide the mechanism, 447c478bd9Sstevel@tonic-gate * and pass in the template to the parent as a Reader during object 45*55fea89dSDan Cross * creation. The AttributeVerifier class parses tokens from the Reader and 467c478bd9Sstevel@tonic-gate * constructs the attribute descriptor objects describing the attribute. These 477c478bd9Sstevel@tonic-gate * are used during verification of the attribute. The AttributeVerifier 487c478bd9Sstevel@tonic-gate * and implementations of the attribute descriptors are free to optimize 49*55fea89dSDan Cross * space utilization by lazily evaluating portions of the attribute 507c478bd9Sstevel@tonic-gate * template. 517c478bd9Sstevel@tonic-gate * 527c478bd9Sstevel@tonic-gate * @author James Kempf 537c478bd9Sstevel@tonic-gate * 547c478bd9Sstevel@tonic-gate */ 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate class AttributeVerifier 577c478bd9Sstevel@tonic-gate extends Object 587c478bd9Sstevel@tonic-gate implements ServiceLocationAttributeVerifier { 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate // Template specific escape. 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate private static final String ESC_HASH = "\\23"; 637c478bd9Sstevel@tonic-gate private static final String HASH = "#"; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate // Number of template attributes. 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate private static final int TEMPLATE_ATTR_NO = 5; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate // Bitfields for found template attributes. 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate private static final int SERVICE_MASK = 0x01; 727c478bd9Sstevel@tonic-gate private static final int VERSION_MASK = 0x02; 737c478bd9Sstevel@tonic-gate private static final int DESCRIPTION_MASK = 0x08; 747c478bd9Sstevel@tonic-gate private static final int URL_PATH_RULES_MASK = 0x10; 757c478bd9Sstevel@tonic-gate 76*55fea89dSDan Cross // When all template attribute assignments are found. 777c478bd9Sstevel@tonic-gate 78*55fea89dSDan Cross private static final int TEMPLATE_FOUND = (SERVICE_MASK | 79*55fea89dSDan Cross VERSION_MASK | 80*55fea89dSDan Cross DESCRIPTION_MASK | 817c478bd9Sstevel@tonic-gate URL_PATH_RULES_MASK); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate // These are the valid SLP types. 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate private static final String INTEGER_TYPE = "integer"; 867c478bd9Sstevel@tonic-gate private static final String STRING_TYPE = "string"; 877c478bd9Sstevel@tonic-gate private static final String BOOLEAN_TYPE = "boolean"; 887c478bd9Sstevel@tonic-gate private static final String OPAQUE_TYPE = "opaque"; 897c478bd9Sstevel@tonic-gate private static final String KEYWORD_TYPE = "keyword"; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate // These are the corresponding Java types. Package public so 927c478bd9Sstevel@tonic-gate // others (SLPConfig for example) can get at them. 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate static final String JAVA_STRING_TYPE = 957c478bd9Sstevel@tonic-gate "java.lang.String"; 96*55fea89dSDan Cross static final String JAVA_INTEGER_TYPE = 977c478bd9Sstevel@tonic-gate "java.lang.Integer"; 987c478bd9Sstevel@tonic-gate static final String JAVA_BOOLEAN_TYPE = 997c478bd9Sstevel@tonic-gate "java.lang.Boolean"; 1007c478bd9Sstevel@tonic-gate static final String JAVA_OPAQUE_TYPE = 1017c478bd9Sstevel@tonic-gate "[B"; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate // Tokens for boolean values. 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate private static final String TRUE_TOKEN = "true"; 1067c478bd9Sstevel@tonic-gate private static final String FALSE_TOKEN = "false"; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate // This is the number of flags. 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate private static final int FLAG_NO = 4; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate // These are the flags. 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate private static final String MULTIPLE_FLAG = "m"; 1157c478bd9Sstevel@tonic-gate private static final String LITERAL_FLAG = "l"; 1167c478bd9Sstevel@tonic-gate private static final String EXPLICIT_FLAG = "x"; 1177c478bd9Sstevel@tonic-gate private static final String OPTIONAL_FLAG = "o"; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate // These masks help determine whether the flags have been duplicated. 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate private static final byte MULTIPLE_MASK = 0x01; 1227c478bd9Sstevel@tonic-gate private static final byte LITERAL_MASK = 0x02; 1237c478bd9Sstevel@tonic-gate private static final byte EXPLICIT_MASK = 0x04; 1247c478bd9Sstevel@tonic-gate private static final byte OPTIONAL_MASK = 0x08; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate // These are tokens for separator characters. 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate private static final char TT_COMMA = ','; 1297c478bd9Sstevel@tonic-gate private static final char TT_EQUALS = '='; 1307c478bd9Sstevel@tonic-gate private static final char TT_FIELD = '#'; 1317c478bd9Sstevel@tonic-gate private static final char TT_ESCAPE = '\\'; 1327c478bd9Sstevel@tonic-gate 133*55fea89dSDan Cross // This token is for checking version number 1347c478bd9Sstevel@tonic-gate // attribute assignment. 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate private static final char TT_PERIOD = '.'; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate // Radix64 code characters. 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate private static final char UPPER_START_CODE = 'A'; 1417c478bd9Sstevel@tonic-gate private static final char UPPER_END_CODE = 'Z'; 1427c478bd9Sstevel@tonic-gate private static final char LOWER_START_CODE = 'a'; 1437c478bd9Sstevel@tonic-gate private static final char LOWER_END_CODE = 'z'; 1447c478bd9Sstevel@tonic-gate private static final char NUMBER_START_CODE = '0'; 1457c478bd9Sstevel@tonic-gate private static final char NUMBER_END_CODE = '9'; 1467c478bd9Sstevel@tonic-gate private static final char EXTRA_CODE1 = '+'; 1477c478bd9Sstevel@tonic-gate private static final char EXTRA_CODE2 = '/'; 1487c478bd9Sstevel@tonic-gate private static final char PAD_CODE = '='; 1497c478bd9Sstevel@tonic-gate private static final char LENGTH_SEPERATOR = ':'; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate // The SLP service type of this template. 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate private ServiceType serviceType; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate // The template's language locale. 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate private Locale locale; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate // The template's version. 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate private String version; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate // The template's URL syntax. 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate private String URLSyntax; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate // The template's description. 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate private String description; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate // The attribute descriptors. 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate private Hashtable attributeDescriptors = new Hashtable(); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate // 1767c478bd9Sstevel@tonic-gate // Constructors. 1777c478bd9Sstevel@tonic-gate AttributeVerifier()1787c478bd9Sstevel@tonic-gate AttributeVerifier() { 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 182*55fea89dSDan Cross // Initialize the attribute verifier with a reader. Subclasses or clients 1837c478bd9Sstevel@tonic-gate // pass in a Reader on the template that is used for parsing. This 1847c478bd9Sstevel@tonic-gate // method is used when the template includes the template attributes 1857c478bd9Sstevel@tonic-gate // and URL rules. 1867c478bd9Sstevel@tonic-gate initialize(Reader r)1877c478bd9Sstevel@tonic-gate void initialize(Reader r) throws ServiceLocationException { 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate // Use a StreamTokenizer to parse. 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate StreamTokenizer tk = new StreamTokenizer(r); 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate // Initialize tokenizer for parsing main. 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate initFieldChar(tk); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate // Now parse the attribute template, including template attributes. 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate parseTemplate(tk); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate // Initialize with this method when no template attributes are involved. 2037c478bd9Sstevel@tonic-gate initializeAttributesOnly(Reader r)204*55fea89dSDan Cross void initializeAttributesOnly(Reader r) 2057c478bd9Sstevel@tonic-gate throws ServiceLocationException { 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate // Use a StreamTokenizer to parse. 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate StreamTokenizer tk = new StreamTokenizer(r); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate // Initialize tokenizer for parsing main. 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate initFieldChar(tk); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate // Now parse the attribute templates, but no template attributes. 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate parseAttributes(tk); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate // 2217c478bd9Sstevel@tonic-gate // ServiceLocationAttributeVerifier interface implementation. 2227c478bd9Sstevel@tonic-gate // 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /** 2257c478bd9Sstevel@tonic-gate * Returns the SLP service type for which this is the verifier. 2267c478bd9Sstevel@tonic-gate * 2277c478bd9Sstevel@tonic-gate * @return The SLP service type name. 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate getServiceType()2307c478bd9Sstevel@tonic-gate public ServiceType getServiceType() { 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate return serviceType; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate /** 2367c478bd9Sstevel@tonic-gate * Returns the SLP language locale of this is the verifier. 2377c478bd9Sstevel@tonic-gate * 2387c478bd9Sstevel@tonic-gate * @return The SLP language locale. 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate getLocale()2417c478bd9Sstevel@tonic-gate public Locale getLocale() { 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate return locale; 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /** 2477c478bd9Sstevel@tonic-gate * Returns the SLP version of this is the verifier. 2487c478bd9Sstevel@tonic-gate * 2497c478bd9Sstevel@tonic-gate * @return The SLP version. 2507c478bd9Sstevel@tonic-gate */ 2517c478bd9Sstevel@tonic-gate getVersion()2527c478bd9Sstevel@tonic-gate public String getVersion() { 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate return version; 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate /** 2587c478bd9Sstevel@tonic-gate * Returns the SLP URL syntax of this is the verifier. 2597c478bd9Sstevel@tonic-gate * 2607c478bd9Sstevel@tonic-gate * @return The SLP URL syntax. 2617c478bd9Sstevel@tonic-gate */ 2627c478bd9Sstevel@tonic-gate getURLSyntax()2637c478bd9Sstevel@tonic-gate public String getURLSyntax() { 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate return URLSyntax; 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate /** 2697c478bd9Sstevel@tonic-gate * Returns the SLP description of this is the verifier. 2707c478bd9Sstevel@tonic-gate * 2717c478bd9Sstevel@tonic-gate * @return The SLP description. 2727c478bd9Sstevel@tonic-gate */ 2737c478bd9Sstevel@tonic-gate getDescription()2747c478bd9Sstevel@tonic-gate public String getDescription() { 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate return description; 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /** 2807c478bd9Sstevel@tonic-gate * Returns the ServiceLocationAttributeDescriptor object for the 281*55fea89dSDan Cross * attribute having the named id. IF no such attribute exists in the 2827c478bd9Sstevel@tonic-gate * template, returns null. This method is primarily for GUI tools to 2837c478bd9Sstevel@tonic-gate * display attribute information. Programmatic verification of attributes 2847c478bd9Sstevel@tonic-gate * should use the verifyAttribute() method. 2857c478bd9Sstevel@tonic-gate * 2867c478bd9Sstevel@tonic-gate * @param attrId Id of attribute to return. 2877c478bd9Sstevel@tonic-gate * @return The ServiceLocationAttributeDescriptor object corresponding 2887c478bd9Sstevel@tonic-gate * to the parameter, or null if none. 2897c478bd9Sstevel@tonic-gate */ 2907c478bd9Sstevel@tonic-gate 291*55fea89dSDan Cross public ServiceLocationAttributeDescriptor getAttributeDescriptor(String attrId)2927c478bd9Sstevel@tonic-gate getAttributeDescriptor(String attrId) { 2937c478bd9Sstevel@tonic-gate 294*55fea89dSDan Cross return 2957c478bd9Sstevel@tonic-gate (ServiceLocationAttributeDescriptor) 2967c478bd9Sstevel@tonic-gate attributeDescriptors.get(attrId.toLowerCase()); 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate /** 3017c478bd9Sstevel@tonic-gate * Returns an Enumeration of 3027c478bd9Sstevel@tonic-gate * ServiceLocationAttributeDescriptors for the template. This method 3037c478bd9Sstevel@tonic-gate * is primarily for GUI tools to display attribute information. 304*55fea89dSDan Cross * Programmatic verification of attributes should use the 3057c478bd9Sstevel@tonic-gate * verifyAttribute() method. Note that small memory implementations 3067c478bd9Sstevel@tonic-gate * may want to implement the Enumeration so that attributes are 3077c478bd9Sstevel@tonic-gate * parsed on demand rather than at creation time. 3087c478bd9Sstevel@tonic-gate * 3097c478bd9Sstevel@tonic-gate * @return A Dictionary with attribute id's as the keys and 310*55fea89dSDan Cross * ServiceLocationAttributeDescriptor objects for the 3117c478bd9Sstevel@tonic-gate * attributes as the values. 3127c478bd9Sstevel@tonic-gate */ 3137c478bd9Sstevel@tonic-gate getAttributeDescriptors()3147c478bd9Sstevel@tonic-gate public Enumeration getAttributeDescriptors() { 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate return ((Hashtable)attributeDescriptors.clone()).elements(); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /** 3217c478bd9Sstevel@tonic-gate * Verify that the attribute parameter is a valid SLP attribute. 322*55fea89dSDan Cross * 3237c478bd9Sstevel@tonic-gate * @param attribute The ServiceLocationAttribute to be verified. 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate verifyAttribute(ServiceLocationAttribute attribute)3267c478bd9Sstevel@tonic-gate public void verifyAttribute(ServiceLocationAttribute attribute) 3277c478bd9Sstevel@tonic-gate throws ServiceLocationException { 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate String id = attribute.getId().toLowerCase(); 330*55fea89dSDan Cross ServiceLocationAttributeDescriptor des = 3317c478bd9Sstevel@tonic-gate (ServiceLocationAttributeDescriptor)attributeDescriptors.get(id); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate if (des == null) { 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate throw 3367c478bd9Sstevel@tonic-gate new ServiceLocationException( 3377c478bd9Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 3387c478bd9Sstevel@tonic-gate "template_no_attribute", 3397c478bd9Sstevel@tonic-gate new Object[] { id }); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate String type = des.getValueType(); 3447c478bd9Sstevel@tonic-gate Vector vals = attribute.getValues(); 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate // If keyword, check that no values were specified. 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate if (des.getIsKeyword()) { 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (vals != null) { 3517c478bd9Sstevel@tonic-gate throw 3527c478bd9Sstevel@tonic-gate new ServiceLocationException( 3537c478bd9Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 3547c478bd9Sstevel@tonic-gate "template_not_null", 3557c478bd9Sstevel@tonic-gate new Object[] { id }); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate } else { 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate int i, n; 360*55fea89dSDan Cross 3617c478bd9Sstevel@tonic-gate // Check that a values vector exists, and, if the attribute is 3627c478bd9Sstevel@tonic-gate // not multivalued, only one element is in it. 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if (vals == null) { 3657c478bd9Sstevel@tonic-gate throw 3667c478bd9Sstevel@tonic-gate new ServiceLocationException( 3677c478bd9Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 3687c478bd9Sstevel@tonic-gate "template_null", 3697c478bd9Sstevel@tonic-gate new Object[] { id }); 3707c478bd9Sstevel@tonic-gate 371*55fea89dSDan Cross } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate n = vals.size(); 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate if (n > 1 && !des.getIsMultivalued()) { 3767c478bd9Sstevel@tonic-gate throw 3777c478bd9Sstevel@tonic-gate new ServiceLocationException( 3787c478bd9Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 3797c478bd9Sstevel@tonic-gate "template_not_multi", 3807c478bd9Sstevel@tonic-gate new Object[] { id }); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate // Get allowed values. 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate Vector av = null; 3867c478bd9Sstevel@tonic-gate Enumeration en = des.getAllowedValues(); 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate if (en.hasMoreElements()) { 3897c478bd9Sstevel@tonic-gate av = new Vector(); 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate while (en.hasMoreElements()) { 3927c478bd9Sstevel@tonic-gate Object v = en.nextElement(); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate // Lower case if string, convert to Opaque if byte array. 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate if (type.equals(JAVA_STRING_TYPE)) { 3977c478bd9Sstevel@tonic-gate v = ((String)v).toLowerCase(); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate } else if (type.equals(JAVA_OPAQUE_TYPE)) { 4007c478bd9Sstevel@tonic-gate v = new Opaque((byte[])v); 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate av.addElement(v); 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate // Check that the types of the values vector match the attribute 4097c478bd9Sstevel@tonic-gate // type. Also, if any allowed values, that attribute values 4107c478bd9Sstevel@tonic-gate // match. 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate String attTypeName = des.getValueType(); 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 4157c478bd9Sstevel@tonic-gate Object val = vals.elementAt(i); 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate String typeName = val.getClass().getName(); 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate if (!typeName.equals(attTypeName)) { 4207c478bd9Sstevel@tonic-gate throw 4217c478bd9Sstevel@tonic-gate new ServiceLocationException( 4227c478bd9Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 4237c478bd9Sstevel@tonic-gate "template_type_mismatch", 4247c478bd9Sstevel@tonic-gate new Object[] { id, typeName, attTypeName }); 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate // Convert value for comparison, if necessary. 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate if (type.equals(JAVA_STRING_TYPE)) { 4317c478bd9Sstevel@tonic-gate val = ((String)val).toLowerCase(); 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate } else if (type.equals(JAVA_OPAQUE_TYPE)) { 4347c478bd9Sstevel@tonic-gate val = new Opaque((byte[])val); 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate if (av != null && !av.contains(val)) { 4397c478bd9Sstevel@tonic-gate throw 4407c478bd9Sstevel@tonic-gate new ServiceLocationException( 4417c478bd9Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 4427c478bd9Sstevel@tonic-gate "template_not_allowed_value", 4437c478bd9Sstevel@tonic-gate new Object[] {id, val}); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate // No way to verify `X' because that's a search property. We 4517c478bd9Sstevel@tonic-gate // must verify `O' in the context of an attribute set. 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate /** 4557c478bd9Sstevel@tonic-gate * Verify that the set of registration attributes matches the 4567c478bd9Sstevel@tonic-gate * required attributes for the service. 4577c478bd9Sstevel@tonic-gate * 4587c478bd9Sstevel@tonic-gate * @param attributeVector A Vector of ServiceLocationAttribute objects 4597c478bd9Sstevel@tonic-gate * for the registration. 4607c478bd9Sstevel@tonic-gate * @exception ServiceLocationException Thrown if the 4617c478bd9Sstevel@tonic-gate * attribute set is not valid. The message contains information 4627c478bd9Sstevel@tonic-gate * on the attribute name and problem. 4637c478bd9Sstevel@tonic-gate */ 4647c478bd9Sstevel@tonic-gate verifyRegistration(Vector attributeVector)4657c478bd9Sstevel@tonic-gate public void verifyRegistration(Vector attributeVector) 4667c478bd9Sstevel@tonic-gate throws ServiceLocationException { 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate Assert.nonNullParameter(attributeVector, "attributeVector"); 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate if (attributeVector.size() <= 0) { 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate // Check whether any attributes are required. If so, then 4747c478bd9Sstevel@tonic-gate // there's an error. 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate Enumeration en = attributeDescriptors.elements(); 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate while (en.hasMoreElements()) { 4797c478bd9Sstevel@tonic-gate ServiceLocationAttributeDescriptor attDesc = 4807c478bd9Sstevel@tonic-gate (ServiceLocationAttributeDescriptor)en.nextElement(); 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate if (!attDesc.getIsOptional()) { 4837c478bd9Sstevel@tonic-gate 484*55fea89dSDan Cross throw 4857c478bd9Sstevel@tonic-gate new ServiceLocationException( 4867c478bd9Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 4877c478bd9Sstevel@tonic-gate "template_missing_required", 4887c478bd9Sstevel@tonic-gate new Object[] { attDesc.getId() }); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate } else { 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate // Construct a hashtable of incoming objects, verifying them 4947c478bd9Sstevel@tonic-gate // while doing so. 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate int i, n = attributeVector.size(); 4977c478bd9Sstevel@tonic-gate Hashtable incoming = new Hashtable(); 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 5007c478bd9Sstevel@tonic-gate ServiceLocationAttribute attribute = 5017c478bd9Sstevel@tonic-gate (ServiceLocationAttribute)attributeVector.elementAt(i); 5027c478bd9Sstevel@tonic-gate String id = attribute.getId().toLowerCase(); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate // If we already have it, signal a duplicate. 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate if (incoming.get(id) != null) { 5077c478bd9Sstevel@tonic-gate throw 5087c478bd9Sstevel@tonic-gate new ServiceLocationException( 5097c478bd9Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 5107c478bd9Sstevel@tonic-gate "template_dup", 5117c478bd9Sstevel@tonic-gate new Object[] { attribute.getId() }); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate verifyAttribute(attribute); 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate incoming.put(id, attribute); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate // Now check that all required attributes are present. 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate Enumeration en = attributeDescriptors.elements(); 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate while (en.hasMoreElements()) { 5257c478bd9Sstevel@tonic-gate ServiceLocationAttributeDescriptor attDesc = 5267c478bd9Sstevel@tonic-gate (ServiceLocationAttributeDescriptor)en.nextElement(); 5277c478bd9Sstevel@tonic-gate String attrId = attDesc.getId(); 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate if (!attDesc.getIsOptional() && 5307c478bd9Sstevel@tonic-gate incoming.get(attrId.toLowerCase()) == null) { 5317c478bd9Sstevel@tonic-gate 532*55fea89dSDan Cross throw 5337c478bd9Sstevel@tonic-gate new ServiceLocationException( 5347c478bd9Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 5357c478bd9Sstevel@tonic-gate "template_missing_required", 5367c478bd9Sstevel@tonic-gate new Object[] { attrId }); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate 541*55fea89dSDan Cross } 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate // 5447c478bd9Sstevel@tonic-gate // Private implementation. This is the template attribute parser. 5457c478bd9Sstevel@tonic-gate // 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate // 5487c478bd9Sstevel@tonic-gate // Tokenizer initializers. 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate // Base initialization. Resets syntax tables, sets up EOL parsing, 5517c478bd9Sstevel@tonic-gate // and makes word case significant. 5527c478bd9Sstevel@tonic-gate initForBase(StreamTokenizer tk)5537c478bd9Sstevel@tonic-gate private void initForBase(StreamTokenizer tk) { 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate // Each part of an attribute production must specify which 5567c478bd9Sstevel@tonic-gate // characters belong to words. 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate tk.resetSyntax(); 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate // Note that we have to make EOL be whitespace even if significant 5617c478bd9Sstevel@tonic-gate // because otherwise the line number won't be correctly incremented. 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)'\n', (int)'\n'); 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate // Don't lower case tokens. 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate tk.lowerCaseMode(false); 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate // Initialize those token characters that appear in all 5717c478bd9Sstevel@tonic-gate // productions. 5727c478bd9Sstevel@tonic-gate initCommonToken(StreamTokenizer tk)5737c478bd9Sstevel@tonic-gate private void initCommonToken(StreamTokenizer tk) { 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate // These characters are recognized as parts of tokens. 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate tk.wordChars((int)'A', (int)'Z'); 5787c478bd9Sstevel@tonic-gate tk.wordChars((int)'a', (int)'z'); 5797c478bd9Sstevel@tonic-gate tk.wordChars((int)'0', (int)'9'); 5807c478bd9Sstevel@tonic-gate tk.wordChars((int)'&', (int)'&'); 5817c478bd9Sstevel@tonic-gate tk.wordChars((int)'*', (int)'*'); 5827c478bd9Sstevel@tonic-gate tk.wordChars((int)':', (int)':'); 5837c478bd9Sstevel@tonic-gate tk.wordChars((int)'-', (int)'-'); 5847c478bd9Sstevel@tonic-gate tk.wordChars((int)'_', (int)'_'); 5857c478bd9Sstevel@tonic-gate tk.wordChars((int)'$', (int)'$'); 5867c478bd9Sstevel@tonic-gate tk.wordChars((int)'+', (int)'+'); 5877c478bd9Sstevel@tonic-gate tk.wordChars((int)'@', (int)'@'); 5887c478bd9Sstevel@tonic-gate tk.wordChars((int)'.', (int)'.'); 5897c478bd9Sstevel@tonic-gate tk.wordChars((int)'|', (int)'|'); 5907c478bd9Sstevel@tonic-gate tk.wordChars((int)'<', (int)'<'); 5917c478bd9Sstevel@tonic-gate tk.wordChars((int)'>', (int)'>'); 5927c478bd9Sstevel@tonic-gate tk.wordChars((int)'~', (int)'~'); 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 596*55fea89dSDan Cross // Initialize tokenizer for parsing attribute name, 597*55fea89dSDan Cross // attribute type and flags, 5987c478bd9Sstevel@tonic-gate // and for boolean initializer lists. 5997c478bd9Sstevel@tonic-gate initIdChar(StreamTokenizer tk)6007c478bd9Sstevel@tonic-gate private void initIdChar(StreamTokenizer tk) { 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate initForBase(tk); 6037c478bd9Sstevel@tonic-gate initCommonToken(tk); 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate // Need backslash for escaping. 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate tk.wordChars((int)'\\', (int)'\\'); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate // Attribute id, Type, flags, and boolean initialzers 6107c478bd9Sstevel@tonic-gate // all ignore white space. 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)' ', (int)' '); 6137c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)'\t', (int)'\t'); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate // Attribute part won't view newline as being significant. 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate tk.eolIsSignificant(false); 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate // Case is not folded. 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate tk.lowerCaseMode(false); 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate // Initialize tokenizer for parsing service type name. 6257c478bd9Sstevel@tonic-gate // need to restrict characters. 6267c478bd9Sstevel@tonic-gate initSchemeIdChar(StreamTokenizer tk)6277c478bd9Sstevel@tonic-gate private void initSchemeIdChar(StreamTokenizer tk) { 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate initForBase(tk); 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate tk.wordChars((int)'A', (int)'Z'); 6327c478bd9Sstevel@tonic-gate tk.wordChars((int)'a', (int)'z'); 6337c478bd9Sstevel@tonic-gate tk.wordChars((int)'0', (int)'9'); 6347c478bd9Sstevel@tonic-gate tk.wordChars((int)'-', (int)'-'); 6357c478bd9Sstevel@tonic-gate tk.wordChars((int)'+', (int)'+'); 6367c478bd9Sstevel@tonic-gate tk.wordChars((int)'.', (int)'.'); // allows naming authority. 6377c478bd9Sstevel@tonic-gate tk.wordChars((int)':', (int)':'); // for abstract and concrete type. 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate // Scheme name, type, flags, and boolean initialzers 6407c478bd9Sstevel@tonic-gate // all ignore white space. 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)' ', (int)' '); 6437c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)'\t', (int)'\t'); 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate // Scheme part won't view newline as being significant. 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate tk.eolIsSignificant(false); 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate // Case is not folded. 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate tk.lowerCaseMode(false); 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate // Initialize tokenizer for string list parsing. 6567c478bd9Sstevel@tonic-gate // Everything except '#' and ',' is recognized. 6577c478bd9Sstevel@tonic-gate // Note that whitespace is significant, but 6587c478bd9Sstevel@tonic-gate // EOL is ignored. 6597c478bd9Sstevel@tonic-gate initStringItemChar(StreamTokenizer tk)6607c478bd9Sstevel@tonic-gate private void initStringItemChar(StreamTokenizer tk) { 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate initForBase(tk); 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate tk.wordChars((int)'\t', (int)'\t'); 6657c478bd9Sstevel@tonic-gate tk.wordChars((int)' ', (int)'"'); 6667c478bd9Sstevel@tonic-gate // '#' goes here 6677c478bd9Sstevel@tonic-gate tk.wordChars((int)'$', (int)'+'); 6687c478bd9Sstevel@tonic-gate // ',' goes here 6697c478bd9Sstevel@tonic-gate tk.wordChars((int)'-', (int)'/'); 6707c478bd9Sstevel@tonic-gate tk.wordChars((int)'0', (int)'9'); 6717c478bd9Sstevel@tonic-gate tk.wordChars((int)':', (int)':'); 6727c478bd9Sstevel@tonic-gate // ';' goes here 6737c478bd9Sstevel@tonic-gate tk.wordChars((int)'<', (int)'@'); 6747c478bd9Sstevel@tonic-gate tk.wordChars((int)'A', (int)'Z'); 6757c478bd9Sstevel@tonic-gate tk.wordChars((int)'[', (int)'`'); 6767c478bd9Sstevel@tonic-gate tk.wordChars((int)'a', (int)'z'); 6777c478bd9Sstevel@tonic-gate tk.wordChars((int)'{', (int)'~'); 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate // '%' is also reserved, but it is postprocessed 6807c478bd9Sstevel@tonic-gate // after the string is collected. 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate // Parse by lines to check when we've reached the end of the list. 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)'\r', (int)'\r'); 6857c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)'\n', (int)'\n'); 6867c478bd9Sstevel@tonic-gate tk.eolIsSignificant(true); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate // Initialize tokenizer for integer list parsing. 6917c478bd9Sstevel@tonic-gate initIntItemChar(StreamTokenizer tk)6927c478bd9Sstevel@tonic-gate private void initIntItemChar(StreamTokenizer tk) { 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate initForBase(tk); 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate tk.wordChars((int)'0', (int)'9'); 6977c478bd9Sstevel@tonic-gate tk.wordChars((int)'-', (int)'-'); 698*55fea89dSDan Cross tk.wordChars((int)'+', (int)'+'); 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate // Integer value list parsing ignores white space. 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)' ', (int)' '); 7037c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)'\t', (int)'\t'); 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate // Parse by lines so we can find the end. 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)'\r', (int)'\r'); 7087c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)'\n', (int)'\n'); 7097c478bd9Sstevel@tonic-gate tk.eolIsSignificant(true); 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate // Boolean lists have same item syntax as scheme char. 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate // Initialize main production parsing. The only 7167c478bd9Sstevel@tonic-gate // significant token character is <NL> because 7177c478bd9Sstevel@tonic-gate // parsing is done on a line-oriented basis. 7187c478bd9Sstevel@tonic-gate initFieldChar(StreamTokenizer tk)7197c478bd9Sstevel@tonic-gate private void initFieldChar(StreamTokenizer tk) { 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate initForBase(tk); 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate tk.wordChars((int)'\t', (int)'\t'); 7247c478bd9Sstevel@tonic-gate tk.wordChars((int)' ', (int)'/'); 7257c478bd9Sstevel@tonic-gate tk.wordChars((int)'0', (int)'9'); 7267c478bd9Sstevel@tonic-gate tk.wordChars((int)':', (int)'@'); 7277c478bd9Sstevel@tonic-gate tk.wordChars((int)'A', (int)'Z'); 7287c478bd9Sstevel@tonic-gate tk.wordChars((int)'[', (int)'`'); 7297c478bd9Sstevel@tonic-gate tk.wordChars((int)'a', (int)'z'); 7307c478bd9Sstevel@tonic-gate tk.wordChars((int)'{', (int)'~'); 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)'\r', (int)'\r'); 7337c478bd9Sstevel@tonic-gate tk.whitespaceChars((int)'\n', (int)'\n'); 7347c478bd9Sstevel@tonic-gate tk.eolIsSignificant(true); 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate // 7387c478bd9Sstevel@tonic-gate // Parsing methods. 7397c478bd9Sstevel@tonic-gate // 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate // Parse a template from the tokenizer. 7427c478bd9Sstevel@tonic-gate parseTemplate(StreamTokenizer tk)743*55fea89dSDan Cross private void parseTemplate(StreamTokenizer tk) 7447c478bd9Sstevel@tonic-gate throws ServiceLocationException { 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate // First parse past the template attributes. 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate parseTemplateAttributes(tk); 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate // Finally, parse the attributes. 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate parseAttributes(tk); 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate // Parse the template attributes from the tokenizer. 7577c478bd9Sstevel@tonic-gate parseTemplateAttributes(StreamTokenizer tk)758*55fea89dSDan Cross private void parseTemplateAttributes(StreamTokenizer tk) 7597c478bd9Sstevel@tonic-gate throws ServiceLocationException { 760*55fea89dSDan Cross 7617c478bd9Sstevel@tonic-gate int found = 0; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate // Parse each of the template attributes. Note that we are parsing 7647c478bd9Sstevel@tonic-gate // the attribute value assignments, not definitions. 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate try { 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate do { 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate found = found | parseTemplateAttribute(tk, found); 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate } while (found != TEMPLATE_FOUND); 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate } catch (IOException ex) { 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate throw 7777c478bd9Sstevel@tonic-gate new ServiceLocationException( 7787c478bd9Sstevel@tonic-gate ServiceLocationException.INTERNAL_SYSTEM_ERROR, 7797c478bd9Sstevel@tonic-gate "template_io_error", 7807c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 781*55fea89dSDan Cross 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate // Parse a template attribute. 7867c478bd9Sstevel@tonic-gate parseTemplateAttribute(StreamTokenizer tk, int found)787*55fea89dSDan Cross private int parseTemplateAttribute(StreamTokenizer tk, int found) 7887c478bd9Sstevel@tonic-gate throws ServiceLocationException, IOException { 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate // Get line including id and equals. 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate int tt = tk.nextToken(); 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate if (tt != StreamTokenizer.TT_WORD) { 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate throw 7977c478bd9Sstevel@tonic-gate new ServiceLocationException( 798*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 7997c478bd9Sstevel@tonic-gate "template_assign_error", 8007c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate // Get tokenizer for id and potential value line. 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate StringReader rdr = new StringReader(tk.sval); 8067c478bd9Sstevel@tonic-gate StreamTokenizer stk = new StreamTokenizer(rdr); 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate initIdChar(stk); 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate // Make sure newline is there. 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate if ((tt = tk.nextToken()) == StreamTokenizer.TT_EOF) { 8137c478bd9Sstevel@tonic-gate 814*55fea89dSDan Cross throw 8157c478bd9Sstevel@tonic-gate new ServiceLocationException( 816*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 8177c478bd9Sstevel@tonic-gate "template_end_error", 8187c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate if (tt != StreamTokenizer.TT_EOL) { 8237c478bd9Sstevel@tonic-gate 824*55fea89dSDan Cross throw 8257c478bd9Sstevel@tonic-gate new ServiceLocationException( 826*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 8277c478bd9Sstevel@tonic-gate "template_unk_token", 8287c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate } 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate // Parse off id. 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate if ((tt = stk.nextToken()) != StreamTokenizer.TT_WORD) { 8367c478bd9Sstevel@tonic-gate 837*55fea89dSDan Cross throw 8387c478bd9Sstevel@tonic-gate new ServiceLocationException( 839*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 8407c478bd9Sstevel@tonic-gate "template_missing_id", 8417c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate String id = stk.sval; 8457c478bd9Sstevel@tonic-gate boolean duplicate = false; 8467c478bd9Sstevel@tonic-gate int mask = 0; 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate // Check for the equals. 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate if ((tt = stk.nextToken()) != TT_EQUALS) { 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate throw 8537c478bd9Sstevel@tonic-gate new ServiceLocationException( 854*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 8557c478bd9Sstevel@tonic-gate "template_missing_eq ", 8567c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate // Depending on the id, parse the rest. 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate if (id.equalsIgnoreCase(SLPTemplateRegistry.SERVICE_ATTR_ID)) { 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate if ((found & SERVICE_MASK) == 0) { 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate // Just need to parse off the service type. 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate if ((tt = stk.nextToken()) != StreamTokenizer.TT_WORD) { 8697c478bd9Sstevel@tonic-gate throw 8707c478bd9Sstevel@tonic-gate new ServiceLocationException( 871*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 8727c478bd9Sstevel@tonic-gate "template_srv_type_err", 8737c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate // Check for characters which are not alphanumerics, + and -. 8777c478bd9Sstevel@tonic-gate // Service type names are more heavily restricted. 8787c478bd9Sstevel@tonic-gate 879*55fea89dSDan Cross StreamTokenizer sttk = 8807c478bd9Sstevel@tonic-gate new StreamTokenizer(new StringReader(stk.sval)); 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate initSchemeIdChar(sttk); 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate if (sttk.nextToken() != StreamTokenizer.TT_WORD || 8857c478bd9Sstevel@tonic-gate !stk.sval.equals(sttk.sval)) { 8867c478bd9Sstevel@tonic-gate throw 8877c478bd9Sstevel@tonic-gate new ServiceLocationException( 888*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 8897c478bd9Sstevel@tonic-gate "template_srv_type_err", 8907c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate // Need to prefix with "serivce:". 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate String typeName = sttk.sval; 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate if (!typeName.startsWith(Defaults.SERVICE_PREFIX+":")) { 8997c478bd9Sstevel@tonic-gate typeName = Defaults.SERVICE_PREFIX+":"+typeName; 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate // Set service type instance variable. 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate serviceType = new ServiceType(typeName); 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate // Check for extra stuff. 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate if ((tt = stk.nextToken()) != StreamTokenizer.TT_EOF) { 9107c478bd9Sstevel@tonic-gate throw 9117c478bd9Sstevel@tonic-gate new ServiceLocationException( 912*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 9137c478bd9Sstevel@tonic-gate "template_srv_type_err", 9147c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 9157c478bd9Sstevel@tonic-gate } 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate mask = SERVICE_MASK; 9187c478bd9Sstevel@tonic-gate } else { 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate duplicate = true; 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate } else if (id.equalsIgnoreCase(SLPTemplateRegistry.VERSION_ATTR_ID)) { 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate if ((found & VERSION_MASK) == 0) { 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate // Just need to parse off the version number. 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate if ((tt = stk.nextToken()) != StreamTokenizer.TT_WORD) { 9297c478bd9Sstevel@tonic-gate throw 9307c478bd9Sstevel@tonic-gate new ServiceLocationException( 931*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 9327c478bd9Sstevel@tonic-gate "template_vers_err", 9337c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate // Make sure it's a valid version number. 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate String version = stk.sval; 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate if (version.indexOf(TT_PERIOD) == -1) { 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate throw 9437c478bd9Sstevel@tonic-gate new ServiceLocationException( 944*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 9457c478bd9Sstevel@tonic-gate "template_vers_mssing", 9467c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate try { 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate new Float(version); 9537c478bd9Sstevel@tonic-gate } catch (NumberFormatException ex) { 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate throw 9567c478bd9Sstevel@tonic-gate new ServiceLocationException( 957*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 9587c478bd9Sstevel@tonic-gate "template_vers_err", 9597c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate this.version = version; 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate // Check for extra stuff. 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate if ((tt = stk.nextToken()) != StreamTokenizer.TT_EOF) { 9687c478bd9Sstevel@tonic-gate throw 9697c478bd9Sstevel@tonic-gate new ServiceLocationException( 970*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 9717c478bd9Sstevel@tonic-gate "template_vers_err", 9727c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate mask = VERSION_MASK; 9767c478bd9Sstevel@tonic-gate } else { 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate duplicate = true; 9797c478bd9Sstevel@tonic-gate } 9807c478bd9Sstevel@tonic-gate } else if (id.equalsIgnoreCase( 9817c478bd9Sstevel@tonic-gate SLPTemplateRegistry.DESCRIPTION_ATTR_ID)) { 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate // Make sure there is nothing else on that line. 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate if (stk.nextToken() != StreamTokenizer.TT_EOF) { 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate throw 9887c478bd9Sstevel@tonic-gate new ServiceLocationException( 989*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 9907c478bd9Sstevel@tonic-gate "template_attr_syntax", 9917c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate if ((found & DESCRIPTION_MASK) == 0) { 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate // Need to continue parsing help text until we reach a blank 9977c478bd9Sstevel@tonic-gate // line. 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate String helpText = ""; 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate do { 1002*55fea89dSDan Cross int ptt = tt; 10037c478bd9Sstevel@tonic-gate tt = tk.nextToken(); 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate if (tt == StreamTokenizer.TT_WORD) { 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate helpText = helpText + tk.sval + "\n"; 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOL) { 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate // If previous token was end of line, quit. 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate if (ptt == StreamTokenizer.TT_EOL) { 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate // Store any text first. 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate if (helpText.length() > 0) { 10187c478bd9Sstevel@tonic-gate description = helpText; 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate tk.pushBack(); // so same as above 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate break; 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOF) { 1027*55fea89dSDan Cross throw 10287c478bd9Sstevel@tonic-gate new ServiceLocationException( 1029*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 10307c478bd9Sstevel@tonic-gate "template_end_error", 10317c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate } else { 10347c478bd9Sstevel@tonic-gate 1035*55fea89dSDan Cross throw 10367c478bd9Sstevel@tonic-gate new ServiceLocationException( 1037*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 10387c478bd9Sstevel@tonic-gate "template_unk_token", 10397c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate } while (true); 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate mask = DESCRIPTION_MASK; 10467c478bd9Sstevel@tonic-gate } else { 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate duplicate = true; 10497c478bd9Sstevel@tonic-gate } 10507c478bd9Sstevel@tonic-gate } else if (id.equalsIgnoreCase( 10517c478bd9Sstevel@tonic-gate SLPTemplateRegistry.SERVICE_URL_ATTR_ID)) { 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate if ((found & URL_PATH_RULES_MASK) == 0) { 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate String serviceURLGrammer = ""; 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate // Pull everything out of the rdr StringReader until empty. 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate int ic; 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate while ((ic = rdr.read()) != -1) { 10627c478bd9Sstevel@tonic-gate serviceURLGrammer += (char)ic; 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate serviceURLGrammer += "\n"; 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate // Need to continue parsing service URL syntax until we 10697c478bd9Sstevel@tonic-gate // reach a blank line. 10707c478bd9Sstevel@tonic-gate 1071*55fea89dSDan Cross tt = StreamTokenizer.TT_EOL; 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate do { 10747c478bd9Sstevel@tonic-gate int ptt = tt; 10757c478bd9Sstevel@tonic-gate tt = tk.nextToken(); 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate if (tt == StreamTokenizer.TT_WORD) { 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate serviceURLGrammer = serviceURLGrammer + tk.sval + "\n"; 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOL) { 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate // If previous token was end of line, quit. 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate if (ptt == StreamTokenizer.TT_EOL) { 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate // Store any text first. 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate if (serviceURLGrammer.length() > 0) { 10907c478bd9Sstevel@tonic-gate URLSyntax = serviceURLGrammer; 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate tk.pushBack(); // so same as above. 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate break; 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOF) { 1099*55fea89dSDan Cross throw 11007c478bd9Sstevel@tonic-gate new ServiceLocationException( 1101*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 11027c478bd9Sstevel@tonic-gate "template_end_error", 11037c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate } else { 11067c478bd9Sstevel@tonic-gate 1107*55fea89dSDan Cross throw 11087c478bd9Sstevel@tonic-gate new ServiceLocationException( 1109*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 11107c478bd9Sstevel@tonic-gate "template_unk_token", 11117c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate } while (true); 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate mask = URL_PATH_RULES_MASK; 11187c478bd9Sstevel@tonic-gate } else { 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate duplicate = true; 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate } else { 11237c478bd9Sstevel@tonic-gate 11247c478bd9Sstevel@tonic-gate throw 11257c478bd9Sstevel@tonic-gate new ServiceLocationException( 1126*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 11277c478bd9Sstevel@tonic-gate "template_nontattribute_err", 11287c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate } 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate // Throw exception if a duplicate definition was detected. 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate if (duplicate) { 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate throw 11377c478bd9Sstevel@tonic-gate new ServiceLocationException( 1138*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 11397c478bd9Sstevel@tonic-gate "template_dup_def", 11407c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate 11457c478bd9Sstevel@tonic-gate // Make sure the assignment ends with a blank line. 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate if ((tt = tk.nextToken()) != StreamTokenizer.TT_EOL) { 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate throw 11507c478bd9Sstevel@tonic-gate new ServiceLocationException( 1151*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 11527c478bd9Sstevel@tonic-gate "template_attr_syntax", 11537c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate return mask; 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate // Parse the attributes from the tokenizer. 11637c478bd9Sstevel@tonic-gate parseAttributes(StreamTokenizer tk)1164*55fea89dSDan Cross private void parseAttributes(StreamTokenizer tk) 11657c478bd9Sstevel@tonic-gate throws ServiceLocationException { 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate try { 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate do { 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate // Check if at end of file yet. 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate int tt = tk.nextToken(); 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate if (tt == StreamTokenizer.TT_EOF) { 11767c478bd9Sstevel@tonic-gate break; 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate // If not, push token back so we can get it next time. 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate tk.pushBack(); 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate // Parse off the attribute descriptor. 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate AttributeDescriptor attDesc = parseAttribute(tk); 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate // Check whether default values, if any, are correct. 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate checkDefaultValues(attDesc); 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate // If the attribute already exists, then throw exception. 11927c478bd9Sstevel@tonic-gate // We could arguably replace existing, but it might 11937c478bd9Sstevel@tonic-gate // suprise the user. 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate String attrId = attDesc.getId().toLowerCase(); 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate if (attributeDescriptors.get(attrId) != null) { 11987c478bd9Sstevel@tonic-gate 1199*55fea89dSDan Cross throw 12007c478bd9Sstevel@tonic-gate new ServiceLocationException( 1201*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 12027c478bd9Sstevel@tonic-gate "template_dup_def", 12037c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate } 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate // Add the attribute to the descriptor table. 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate attributeDescriptors.put(attrId, attDesc); 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate } while (true); 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate } catch (IOException ex) { 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate throw 12167c478bd9Sstevel@tonic-gate new ServiceLocationException( 12177c478bd9Sstevel@tonic-gate ServiceLocationException.INTERNAL_SYSTEM_ERROR, 12187c478bd9Sstevel@tonic-gate "template_io_error", 12197c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 12207c478bd9Sstevel@tonic-gate } 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate } 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate // Parse a single attribute description from the tokenizer. 12257c478bd9Sstevel@tonic-gate 1226*55fea89dSDan Cross private AttributeDescriptor parseAttribute(StreamTokenizer tk)12277c478bd9Sstevel@tonic-gate parseAttribute(StreamTokenizer tk) throws ServiceLocationException { 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate AttributeDescriptor attDesc = new AttributeDescriptor(); 12307c478bd9Sstevel@tonic-gate int lineno = 0; 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate try { 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate // Parse the string for attribute id, type, and flags. 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate lineno = tk.lineno(); 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate int tt = tk.nextToken(); 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate if (tt != StreamTokenizer.TT_WORD) { 12417c478bd9Sstevel@tonic-gate throw 12427c478bd9Sstevel@tonic-gate new ServiceLocationException( 12437c478bd9Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 12447c478bd9Sstevel@tonic-gate "template_attr_syntax", 12457c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 12467c478bd9Sstevel@tonic-gate } 12477c478bd9Sstevel@tonic-gate 1248*55fea89dSDan Cross StreamTokenizer stk = 12497c478bd9Sstevel@tonic-gate new StreamTokenizer(new StringReader(tk.sval)); 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate initIdChar(stk); 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate // Parse the attribute id. 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate parseId(stk, attDesc, lineno); 1256*55fea89dSDan Cross 12577c478bd9Sstevel@tonic-gate // Parse the type and flags. 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate parseTypeAndFlags(stk, attDesc, lineno); 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate tt = tk.nextToken(); 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate if (tt == StreamTokenizer.TT_EOF) { 12647c478bd9Sstevel@tonic-gate 1265*55fea89dSDan Cross throw 12667c478bd9Sstevel@tonic-gate new ServiceLocationException( 1267*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 12687c478bd9Sstevel@tonic-gate "template_end_error", 12697c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate } 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate if (tt != StreamTokenizer.TT_EOL) { 12747c478bd9Sstevel@tonic-gate 1275*55fea89dSDan Cross throw 12767c478bd9Sstevel@tonic-gate new ServiceLocationException( 1277*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 12787c478bd9Sstevel@tonic-gate "template_unk_token", 12797c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate // Parse initial values. 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate if (!attDesc.getIsKeyword()) { 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate String tok = ""; 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate // Read in entire list. 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate do { 12927c478bd9Sstevel@tonic-gate int ptt = tt; 12937c478bd9Sstevel@tonic-gate lineno = tk.lineno(); 12947c478bd9Sstevel@tonic-gate tt = tk.nextToken(); 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate if (tt == StreamTokenizer.TT_WORD) { 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate // Trim line, check for '#', indicating end of list. 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate String line = tk.sval.trim(); 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate if (line.charAt(0) == TT_FIELD) { 13037c478bd9Sstevel@tonic-gate // it's help text already. 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate if (tok.length() > 0) { 13067c478bd9Sstevel@tonic-gate stk = 13077c478bd9Sstevel@tonic-gate new StreamTokenizer(new StringReader(tok)); 13087c478bd9Sstevel@tonic-gate parseDefaultValues(stk, attDesc, lineno); 13097c478bd9Sstevel@tonic-gate } 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate tk.pushBack(); 13127c478bd9Sstevel@tonic-gate break; 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate } else { 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate // Otherwise concatenate onto growing list. 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate tok = tok + line; 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate } 13217c478bd9Sstevel@tonic-gate 1322*55fea89dSDan Cross } else if (tt == StreamTokenizer.TT_EOL) { 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate if (ptt == StreamTokenizer.TT_EOL) { 13257c478bd9Sstevel@tonic-gate // end of attribute definition. 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate // Process any accumulated list. 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate if (tok.length() > 0) { 13307c478bd9Sstevel@tonic-gate stk = 13317c478bd9Sstevel@tonic-gate new StreamTokenizer(new StringReader(tok)); 13327c478bd9Sstevel@tonic-gate parseDefaultValues(stk, attDesc, lineno); 13337c478bd9Sstevel@tonic-gate } 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate return attDesc; 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOF) { 1339*55fea89dSDan Cross throw 13407c478bd9Sstevel@tonic-gate new ServiceLocationException( 1341*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 13427c478bd9Sstevel@tonic-gate "template_end_error", 13437c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate } else { 13467c478bd9Sstevel@tonic-gate 1347*55fea89dSDan Cross throw 13487c478bd9Sstevel@tonic-gate new ServiceLocationException( 1349*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 13507c478bd9Sstevel@tonic-gate "template_unk_token", 13517c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate } 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate } while (true); 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate } else { 13587c478bd9Sstevel@tonic-gate attDesc.setDefaultValues(null); 13597c478bd9Sstevel@tonic-gate attDesc.setAllowedValues(null); 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate // Check for end of definition. 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate if ((tt = tk.nextToken()) == StreamTokenizer.TT_EOL) { 13647c478bd9Sstevel@tonic-gate return attDesc; 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_WORD) { 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate // Check for start of help text. 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate String line = tk.sval.trim(); 1371*55fea89dSDan Cross 13727c478bd9Sstevel@tonic-gate if (line.charAt(0) != TT_FIELD) { 13737c478bd9Sstevel@tonic-gate throw 13747c478bd9Sstevel@tonic-gate new ServiceLocationException( 1375*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 13767c478bd9Sstevel@tonic-gate "template_attr_syntax", 13777c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate } else { 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate tk.pushBack(); 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate } 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOF) { 1386*55fea89dSDan Cross throw 13877c478bd9Sstevel@tonic-gate new ServiceLocationException( 1388*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 13897c478bd9Sstevel@tonic-gate "template_end_error", 13907c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate } else { 13937c478bd9Sstevel@tonic-gate 1394*55fea89dSDan Cross throw 13957c478bd9Sstevel@tonic-gate new ServiceLocationException( 1396*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 13977c478bd9Sstevel@tonic-gate "template_unk_token", 13987c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate } 14017c478bd9Sstevel@tonic-gate } 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate // Parse help text. 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate String helpText = ""; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate do { 1409*55fea89dSDan Cross int ptt = tt; 14107c478bd9Sstevel@tonic-gate lineno = tk.lineno(); 14117c478bd9Sstevel@tonic-gate tt = tk.nextToken(); 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate if (tt == StreamTokenizer.TT_WORD) { 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate // Check for end of help text. 14167c478bd9Sstevel@tonic-gate 14177c478bd9Sstevel@tonic-gate String line = tk.sval.trim(); 1418*55fea89dSDan Cross 14197c478bd9Sstevel@tonic-gate if (line.charAt(0) == TT_FIELD) { 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate // Help text is collected verbatim after '#'. 14227c478bd9Sstevel@tonic-gate 1423*55fea89dSDan Cross helpText = 14247c478bd9Sstevel@tonic-gate helpText + line.substring(1) + "\n"; 14257c478bd9Sstevel@tonic-gate 14267c478bd9Sstevel@tonic-gate } else { 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate // We've reached the end of the help text. Store it 14297c478bd9Sstevel@tonic-gate // and break out of the loop. 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate if (helpText.length() > 0) { 14327c478bd9Sstevel@tonic-gate attDesc.setDescription(helpText); 14337c478bd9Sstevel@tonic-gate } 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate tk.pushBack(); 14367c478bd9Sstevel@tonic-gate break; 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate } 14397c478bd9Sstevel@tonic-gate 14407c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOL || 14417c478bd9Sstevel@tonic-gate tt == StreamTokenizer.TT_EOF) { 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate // If previous token was end of line, quit. 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate if (ptt == StreamTokenizer.TT_EOL) { 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate // Store any text first. 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate if (helpText.length() > 0) { 14507c478bd9Sstevel@tonic-gate attDesc.setDescription(helpText); 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate // If this is a keyword attribute, set the allowed 14547c478bd9Sstevel@tonic-gate // values list to null. 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate if (attDesc.getIsKeyword()) { 14577c478bd9Sstevel@tonic-gate attDesc.setAllowedValues(null); 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate return attDesc; 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOF) { 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate // Error if previous token wasn't EOL. 14657c478bd9Sstevel@tonic-gate 1466*55fea89dSDan Cross throw 14677c478bd9Sstevel@tonic-gate new ServiceLocationException( 1468*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 14697c478bd9Sstevel@tonic-gate "template_end_error", 14707c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate } else { 14747c478bd9Sstevel@tonic-gate 1475*55fea89dSDan Cross throw 14767c478bd9Sstevel@tonic-gate new ServiceLocationException( 1477*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 14787c478bd9Sstevel@tonic-gate "template_unk_token", 14797c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 14807c478bd9Sstevel@tonic-gate } 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate } while (true); 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate // Parse allowed values. 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate if (!attDesc.getIsKeyword()) { 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate String tok = ""; 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate // Read in entire list. 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate do { 14937c478bd9Sstevel@tonic-gate int ptt = tt; 14947c478bd9Sstevel@tonic-gate lineno = tk.lineno(); 14957c478bd9Sstevel@tonic-gate tt = tk.nextToken(); 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate if (tt == StreamTokenizer.TT_WORD) { 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate // Concatenate onto growing list. 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate tok = tok + tk.sval; 15027c478bd9Sstevel@tonic-gate 1503*55fea89dSDan Cross } else if (tt == StreamTokenizer.TT_EOL) { 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate if (ptt == StreamTokenizer.TT_EOL) { 15067c478bd9Sstevel@tonic-gate // end of attribute definition. 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate // Process any accumulated list. 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate if (tok.length() > 0) { 15117c478bd9Sstevel@tonic-gate stk = 15127c478bd9Sstevel@tonic-gate new StreamTokenizer(new StringReader(tok)); 15137c478bd9Sstevel@tonic-gate parseAllowedValues(stk, attDesc, lineno); 15147c478bd9Sstevel@tonic-gate } 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate return attDesc; 15177c478bd9Sstevel@tonic-gate 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOF) { 1520*55fea89dSDan Cross throw 15217c478bd9Sstevel@tonic-gate new ServiceLocationException( 1522*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 15237c478bd9Sstevel@tonic-gate "template_end_error", 15247c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate } else { 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate throw 15297c478bd9Sstevel@tonic-gate new ServiceLocationException( 1530*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 15317c478bd9Sstevel@tonic-gate "template_unk_token", 15327c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 15337c478bd9Sstevel@tonic-gate } 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate } while (true); 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate } else { 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate // Error. Keyword attribute should have ended during help text 15407c478bd9Sstevel@tonic-gate // parsing or before. 1541*55fea89dSDan Cross 15427c478bd9Sstevel@tonic-gate throw 15437c478bd9Sstevel@tonic-gate new ServiceLocationException( 1544*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 15457c478bd9Sstevel@tonic-gate "template_attr_syntax", 15467c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(tk.lineno())}); 15477c478bd9Sstevel@tonic-gate } 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate } catch (IOException ex) { 15507c478bd9Sstevel@tonic-gate 15517c478bd9Sstevel@tonic-gate throw 15527c478bd9Sstevel@tonic-gate new ServiceLocationException( 15537c478bd9Sstevel@tonic-gate ServiceLocationException.INTERNAL_SYSTEM_ERROR, 15547c478bd9Sstevel@tonic-gate "template_io_error", 15557c478bd9Sstevel@tonic-gate new Object[] { 1556*55fea89dSDan Cross Integer.toString(tk.lineno()), 15577c478bd9Sstevel@tonic-gate ex.getMessage()}); 15587c478bd9Sstevel@tonic-gate } 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate } 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate // Check whether the default values, if any, are correct. 15637c478bd9Sstevel@tonic-gate checkDefaultValues(AttributeDescriptor attDesc)1564*55fea89dSDan Cross private void checkDefaultValues(AttributeDescriptor attDesc) 15657c478bd9Sstevel@tonic-gate throws ServiceLocationException { 15667c478bd9Sstevel@tonic-gate 15677c478bd9Sstevel@tonic-gate // Don't bother if it's a keyword attribute, parsing has checked. 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate if (attDesc.getIsKeyword()) { 15707c478bd9Sstevel@tonic-gate return; 15717c478bd9Sstevel@tonic-gate } 15727c478bd9Sstevel@tonic-gate 15737c478bd9Sstevel@tonic-gate Enumeration init = attDesc.getDefaultValues(); 15747c478bd9Sstevel@tonic-gate Enumeration en = attDesc.getAllowedValues(); 15757c478bd9Sstevel@tonic-gate Vector allowed = new Vector(); 15767c478bd9Sstevel@tonic-gate String attDescType = attDesc.getValueType(); 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate // First, collect the allowed values. 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate while (en.hasMoreElements()) { 15817c478bd9Sstevel@tonic-gate Object allval = en.nextElement(); 15827c478bd9Sstevel@tonic-gate 15837c478bd9Sstevel@tonic-gate // Lower case strings and create opaques for comparison 15847c478bd9Sstevel@tonic-gate // if type is opaque. 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate if (attDescType.equals(JAVA_STRING_TYPE)) { 15877c478bd9Sstevel@tonic-gate allval = ((String)allval).toLowerCase(); 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate } else if (attDescType.equals(JAVA_OPAQUE_TYPE)) { 15907c478bd9Sstevel@tonic-gate allval = new Opaque((byte[])allval); 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate } 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate allowed.addElement(allval); 15957c478bd9Sstevel@tonic-gate } 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate // Now compare the allowed with the initial. 15987c478bd9Sstevel@tonic-gate 15997c478bd9Sstevel@tonic-gate if (allowed.size() > 0) { 16007c478bd9Sstevel@tonic-gate 16017c478bd9Sstevel@tonic-gate // Error if allowed is restricted but no initializers. 16027c478bd9Sstevel@tonic-gate 16037c478bd9Sstevel@tonic-gate if (!init.hasMoreElements()) { 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate throw 16067c478bd9Sstevel@tonic-gate new ServiceLocationException( 1607*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 16087c478bd9Sstevel@tonic-gate "template_no_init", 16097c478bd9Sstevel@tonic-gate new Object[] {attDesc.getId()}); 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate } 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate Object val = null; 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate // Compare init values with allowed. 16167c478bd9Sstevel@tonic-gate 16177c478bd9Sstevel@tonic-gate while (init.hasMoreElements()) { 16187c478bd9Sstevel@tonic-gate Object test = init.nextElement(); 16197c478bd9Sstevel@tonic-gate val = test; // for exception.. 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate if (attDescType.equals(JAVA_STRING_TYPE)) { 16227c478bd9Sstevel@tonic-gate test = ((String)test).toLowerCase(); 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate } else if (attDescType.equals(JAVA_OPAQUE_TYPE)) { 16257c478bd9Sstevel@tonic-gate test = new Opaque((byte[])test); 16267c478bd9Sstevel@tonic-gate 16277c478bd9Sstevel@tonic-gate } 16287c478bd9Sstevel@tonic-gate 16297c478bd9Sstevel@tonic-gate if (allowed.indexOf(test) != -1) { 16307c478bd9Sstevel@tonic-gate return; // found it! 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate // Initializer wasn't found. 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate throw 16367c478bd9Sstevel@tonic-gate new ServiceLocationException( 1637*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 16387c478bd9Sstevel@tonic-gate "template_wrong_init", 16397c478bd9Sstevel@tonic-gate new Object[] { 16407c478bd9Sstevel@tonic-gate val.toString(), attDesc.getId()}); 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate } 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate // Parse the attribute's id string. 16457c478bd9Sstevel@tonic-gate parseId(StreamTokenizer tk, AttributeDescriptor attDesc, int baseLineno)16467c478bd9Sstevel@tonic-gate private void parseId(StreamTokenizer tk, 16477c478bd9Sstevel@tonic-gate AttributeDescriptor attDesc, 16487c478bd9Sstevel@tonic-gate int baseLineno) 16497c478bd9Sstevel@tonic-gate throws ServiceLocationException, IOException { 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate // Parse the attribute's identifier tag. 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate String id = parseWord(tk, baseLineno); 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate int tt = tk.nextToken(); 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate // Parse the seperator. 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate if (tt != TT_EQUALS) { 16607c478bd9Sstevel@tonic-gate throw 16617c478bd9Sstevel@tonic-gate new ServiceLocationException( 1662*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 16637c478bd9Sstevel@tonic-gate "template_attr_syntax", 16647c478bd9Sstevel@tonic-gate new Object[] { 16657c478bd9Sstevel@tonic-gate Integer.toString(tk.lineno() + baseLineno)}); 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate } 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate // Expand out any escaped ``#''. It won't be handled by 16707c478bd9Sstevel@tonic-gate // SLA. 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate id = unescapeHash(id); 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate // Expand out character escapes. 16757c478bd9Sstevel@tonic-gate 1676*55fea89dSDan Cross id = 16777c478bd9Sstevel@tonic-gate ServiceLocationAttribute.unescapeAttributeString(id, true); 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate attDesc.setId(id); 16817c478bd9Sstevel@tonic-gate } 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate // Parse the attribute's type and flags. 16847c478bd9Sstevel@tonic-gate 1685*55fea89dSDan Cross private void parseTypeAndFlags(StreamTokenizer tk, AttributeDescriptor attDesc, int baseLineno)16867c478bd9Sstevel@tonic-gate parseTypeAndFlags(StreamTokenizer tk, 16877c478bd9Sstevel@tonic-gate AttributeDescriptor attDesc, 16887c478bd9Sstevel@tonic-gate int baseLineno) 16897c478bd9Sstevel@tonic-gate throws ServiceLocationException, IOException { 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate int existingFlags = 0; 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate // Parse the attribute's type. 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate String type = parseWord(tk, baseLineno); 16967c478bd9Sstevel@tonic-gate 16977c478bd9Sstevel@tonic-gate checkAndAddType(type, attDesc, tk.lineno() + baseLineno); 16987c478bd9Sstevel@tonic-gate 16997c478bd9Sstevel@tonic-gate // Parse the flags. 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate do { 17027c478bd9Sstevel@tonic-gate 17037c478bd9Sstevel@tonic-gate // Check if any flags are left. 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate if (tk.nextToken() == StreamTokenizer.TT_EOF) { 17067c478bd9Sstevel@tonic-gate break; 17077c478bd9Sstevel@tonic-gate 17087c478bd9Sstevel@tonic-gate } else { 17097c478bd9Sstevel@tonic-gate tk.pushBack(); 17107c478bd9Sstevel@tonic-gate } 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate int lineno = tk.lineno(); 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate // Parse the flag. 17157c478bd9Sstevel@tonic-gate 17167c478bd9Sstevel@tonic-gate String flag = parseWord(tk, baseLineno); 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate // Error if flags with keyword. 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate if (attDesc.getIsKeyword()) { 17217c478bd9Sstevel@tonic-gate throw 17227c478bd9Sstevel@tonic-gate new ServiceLocationException( 1723*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 17247c478bd9Sstevel@tonic-gate "template_attr_syntax", 17257c478bd9Sstevel@tonic-gate new Object[] { 17267c478bd9Sstevel@tonic-gate Integer.toString(tk.lineno() + baseLineno)}); 17277c478bd9Sstevel@tonic-gate } 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate // Check and assign it to the attribute. 1731*55fea89dSDan Cross 1732*55fea89dSDan Cross existingFlags = 17337c478bd9Sstevel@tonic-gate existingFlags | checkAndAddFlag(flag, 17347c478bd9Sstevel@tonic-gate existingFlags, 17357c478bd9Sstevel@tonic-gate attDesc, 17367c478bd9Sstevel@tonic-gate baseLineno + lineno); 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate } while (true); 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate // Parse the attribute's initial value(s). 17427c478bd9Sstevel@tonic-gate parseDefaultValues(StreamTokenizer tk, AttributeDescriptor attDesc, int baseLineno)17437c478bd9Sstevel@tonic-gate private void parseDefaultValues(StreamTokenizer tk, 17447c478bd9Sstevel@tonic-gate AttributeDescriptor attDesc, 17457c478bd9Sstevel@tonic-gate int baseLineno) 17467c478bd9Sstevel@tonic-gate throws ServiceLocationException, IOException { 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate // First get the vector of initial values. 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate Vector vals = parseValueList(tk, attDesc, baseLineno); 17517c478bd9Sstevel@tonic-gate 17527c478bd9Sstevel@tonic-gate // Check whether it works for this attribute. Type 17537c478bd9Sstevel@tonic-gate // checking will be done by value list parsing. 17547c478bd9Sstevel@tonic-gate 17557c478bd9Sstevel@tonic-gate if (!attDesc.getIsMultivalued() && vals.size() > 1) { 17567c478bd9Sstevel@tonic-gate throw 17577c478bd9Sstevel@tonic-gate new ServiceLocationException( 1758*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 17597c478bd9Sstevel@tonic-gate "template_attr_syntax", 17607c478bd9Sstevel@tonic-gate new Object[] { 17617c478bd9Sstevel@tonic-gate Integer.toString(tk.lineno() + baseLineno)}); 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate 17647c478bd9Sstevel@tonic-gate attDesc.setDefaultValues(vals); 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate // Parse the attribute's allowed values. 17687c478bd9Sstevel@tonic-gate 1769*55fea89dSDan Cross private void parseAllowedValues(StreamTokenizer tk, AttributeDescriptor attDesc, int baseLineno)17707c478bd9Sstevel@tonic-gate parseAllowedValues(StreamTokenizer tk, 17717c478bd9Sstevel@tonic-gate AttributeDescriptor attDesc, 17727c478bd9Sstevel@tonic-gate int baseLineno) 17737c478bd9Sstevel@tonic-gate throws ServiceLocationException, IOException { 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate // First get the vector of all allowed values. 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate Vector vals = parseValueList(tk, attDesc, baseLineno); 17787c478bd9Sstevel@tonic-gate 17797c478bd9Sstevel@tonic-gate // Now set the allowed value vector. 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate attDesc.setAllowedValues(vals); 17827c478bd9Sstevel@tonic-gate } 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate // Parse a value list. 17857c478bd9Sstevel@tonic-gate parseValueList(StreamTokenizer stk, AttributeDescriptor attDesc, int baseLineno)17867c478bd9Sstevel@tonic-gate private Vector parseValueList(StreamTokenizer stk, 17877c478bd9Sstevel@tonic-gate AttributeDescriptor attDesc, 17887c478bd9Sstevel@tonic-gate int baseLineno) 17897c478bd9Sstevel@tonic-gate throws ServiceLocationException, IOException { 17907c478bd9Sstevel@tonic-gate 17917c478bd9Sstevel@tonic-gate Vector req = new Vector(); 17927c478bd9Sstevel@tonic-gate 17937c478bd9Sstevel@tonic-gate // Set up the tokenizer according to the type of the 17947c478bd9Sstevel@tonic-gate // attribute. 17957c478bd9Sstevel@tonic-gate 17967c478bd9Sstevel@tonic-gate String type = attDesc.getValueType(); 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate if (type.equals(JAVA_STRING_TYPE) || type.equals(JAVA_OPAQUE_TYPE)) { 17997c478bd9Sstevel@tonic-gate initStringItemChar(stk); 18007c478bd9Sstevel@tonic-gate } else if (type.equals(JAVA_INTEGER_TYPE)) { 18017c478bd9Sstevel@tonic-gate initIntItemChar(stk); 18027c478bd9Sstevel@tonic-gate } else if (type.equals(JAVA_BOOLEAN_TYPE)) { 18037c478bd9Sstevel@tonic-gate initIdChar(stk); 18047c478bd9Sstevel@tonic-gate } 18057c478bd9Sstevel@tonic-gate 18067c478bd9Sstevel@tonic-gate // Parse through a potentially multivalued value list. 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate boolean wordRequired = true; // true when a word is required, 18097c478bd9Sstevel@tonic-gate // false when a comma required. 18107c478bd9Sstevel@tonic-gate boolean syntaxError = false; 18117c478bd9Sstevel@tonic-gate String reqTok = ""; 18127c478bd9Sstevel@tonic-gate int lineno = 0; 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate do { 18157c478bd9Sstevel@tonic-gate int tt = stk.nextToken(); 18167c478bd9Sstevel@tonic-gate lineno = stk.lineno() + baseLineno; 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate if (tt == StreamTokenizer.TT_WORD) { 18197c478bd9Sstevel@tonic-gate 18207c478bd9Sstevel@tonic-gate // If a word isn't required, then the case is 18217c478bd9Sstevel@tonic-gate // "token token" and is an error. 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate if (!wordRequired) { 18247c478bd9Sstevel@tonic-gate syntaxError = true; 18257c478bd9Sstevel@tonic-gate } 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate reqTok = stk.sval.trim(); 18287c478bd9Sstevel@tonic-gate 18297c478bd9Sstevel@tonic-gate // Convert the value to the proper object. 18307c478bd9Sstevel@tonic-gate 18317c478bd9Sstevel@tonic-gate Object reqVal = convertValue(type, reqTok, baseLineno); 18327c478bd9Sstevel@tonic-gate req.addElement(reqVal); 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate wordRequired = false; 18357c478bd9Sstevel@tonic-gate 18367c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOF) { 18377c478bd9Sstevel@tonic-gate 18387c478bd9Sstevel@tonic-gate // If a word is required, then list ends with 18397c478bd9Sstevel@tonic-gate // a comma, so error. 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate if (wordRequired) { 18427c478bd9Sstevel@tonic-gate syntaxError = true; 18437c478bd9Sstevel@tonic-gate } 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate break; 18467c478bd9Sstevel@tonic-gate 18477c478bd9Sstevel@tonic-gate } else if (tt == TT_COMMA) { 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate // If a word is required, then error. The case is ",,". 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate if (wordRequired) { 18527c478bd9Sstevel@tonic-gate syntaxError = true; 18537c478bd9Sstevel@tonic-gate break; 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate // Otherwise, the next token must be a word. 18577c478bd9Sstevel@tonic-gate 18587c478bd9Sstevel@tonic-gate wordRequired = true; 18597c478bd9Sstevel@tonic-gate 18607c478bd9Sstevel@tonic-gate } else { 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate // No other tokens are allowed. 18637c478bd9Sstevel@tonic-gate 18647c478bd9Sstevel@tonic-gate syntaxError = true; 18657c478bd9Sstevel@tonic-gate break; 18667c478bd9Sstevel@tonic-gate } 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate } while (true); 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate if (syntaxError) { 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate throw 18737c478bd9Sstevel@tonic-gate new ServiceLocationException( 1874*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 18757c478bd9Sstevel@tonic-gate "template_attr_syntax", 18767c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(lineno)}); 18777c478bd9Sstevel@tonic-gate } 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate return req; 18807c478bd9Sstevel@tonic-gate 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate // Check the type and add it to the attribute descriptor. 18847c478bd9Sstevel@tonic-gate checkAndAddType(String type, AttributeDescriptor attDesc, int lineno)18857c478bd9Sstevel@tonic-gate private void checkAndAddType(String type, 18867c478bd9Sstevel@tonic-gate AttributeDescriptor attDesc, 1887*55fea89dSDan Cross int lineno) 18887c478bd9Sstevel@tonic-gate throws ServiceLocationException { 18897c478bd9Sstevel@tonic-gate 18907c478bd9Sstevel@tonic-gate // Check token against recognized types. 18917c478bd9Sstevel@tonic-gate 18927c478bd9Sstevel@tonic-gate if (type.equalsIgnoreCase(STRING_TYPE)) { 18937c478bd9Sstevel@tonic-gate attDesc.setValueType(JAVA_STRING_TYPE); 18947c478bd9Sstevel@tonic-gate 18957c478bd9Sstevel@tonic-gate } else if (type.equalsIgnoreCase(INTEGER_TYPE)) { 18967c478bd9Sstevel@tonic-gate attDesc.setValueType(JAVA_INTEGER_TYPE); 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate } else if (type.equalsIgnoreCase(BOOLEAN_TYPE)) { 18997c478bd9Sstevel@tonic-gate attDesc.setValueType(JAVA_BOOLEAN_TYPE); 19007c478bd9Sstevel@tonic-gate 19017c478bd9Sstevel@tonic-gate } else if (type.equalsIgnoreCase(OPAQUE_TYPE)) { 19027c478bd9Sstevel@tonic-gate attDesc.setValueType(JAVA_OPAQUE_TYPE); 19037c478bd9Sstevel@tonic-gate 19047c478bd9Sstevel@tonic-gate } else if (type.equalsIgnoreCase(KEYWORD_TYPE)) { 19057c478bd9Sstevel@tonic-gate attDesc.setIsKeyword(true); 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate } else { 19087c478bd9Sstevel@tonic-gate 19097c478bd9Sstevel@tonic-gate throw 19107c478bd9Sstevel@tonic-gate new ServiceLocationException( 1911*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 19127c478bd9Sstevel@tonic-gate "template_not_slp_type", 19137c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(lineno)}); 19147c478bd9Sstevel@tonic-gate } 19157c478bd9Sstevel@tonic-gate 19167c478bd9Sstevel@tonic-gate } 1917*55fea89dSDan Cross 19187c478bd9Sstevel@tonic-gate // Check the flag and add it to the attribute descriptor. 19197c478bd9Sstevel@tonic-gate checkAndAddFlag(String flag, int matched, AttributeDescriptor attDesc, int lineno)19207c478bd9Sstevel@tonic-gate private int checkAndAddFlag(String flag, 19217c478bd9Sstevel@tonic-gate int matched, 19227c478bd9Sstevel@tonic-gate AttributeDescriptor attDesc, 1923*55fea89dSDan Cross int lineno) 19247c478bd9Sstevel@tonic-gate throws ServiceLocationException { 19257c478bd9Sstevel@tonic-gate 19267c478bd9Sstevel@tonic-gate boolean duplicate = false; 19277c478bd9Sstevel@tonic-gate 19287c478bd9Sstevel@tonic-gate // We depend on the attribute descriptor being initialized to 19297c478bd9Sstevel@tonic-gate // nothing, i.e. false for all flags and for keyword. 19307c478bd9Sstevel@tonic-gate 19317c478bd9Sstevel@tonic-gate if (flag.equalsIgnoreCase(MULTIPLE_FLAG)) { 19327c478bd9Sstevel@tonic-gate 19337c478bd9Sstevel@tonic-gate if ((matched & MULTIPLE_MASK) != 0) { 19347c478bd9Sstevel@tonic-gate duplicate = true; 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate } else { 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate // Check for boolean. Booleans may not have 19397c478bd9Sstevel@tonic-gate // multiple values. 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate if (attDesc.getValueType().equals(JAVA_BOOLEAN_TYPE)) { 19427c478bd9Sstevel@tonic-gate 19437c478bd9Sstevel@tonic-gate throw 19447c478bd9Sstevel@tonic-gate new ServiceLocationException( 1945*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 19467c478bd9Sstevel@tonic-gate "template_boolean_multi", 19477c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(lineno)}); 19487c478bd9Sstevel@tonic-gate } 19497c478bd9Sstevel@tonic-gate 19507c478bd9Sstevel@tonic-gate attDesc.setIsMultivalued(true); 19517c478bd9Sstevel@tonic-gate return MULTIPLE_MASK; 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate } 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate } else if (flag.equalsIgnoreCase(LITERAL_FLAG)) { 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate if ((matched & LITERAL_MASK) != 0) { 19587c478bd9Sstevel@tonic-gate duplicate = true; 19597c478bd9Sstevel@tonic-gate 19607c478bd9Sstevel@tonic-gate } else { 19617c478bd9Sstevel@tonic-gate attDesc.setIsLiteral(true); 19627c478bd9Sstevel@tonic-gate return LITERAL_MASK; 19637c478bd9Sstevel@tonic-gate } 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate } else if (flag.equalsIgnoreCase(EXPLICIT_FLAG)) { 19667c478bd9Sstevel@tonic-gate 19677c478bd9Sstevel@tonic-gate if ((matched & EXPLICIT_MASK) != 0) { 19687c478bd9Sstevel@tonic-gate duplicate = true; 19697c478bd9Sstevel@tonic-gate 19707c478bd9Sstevel@tonic-gate } else { 19717c478bd9Sstevel@tonic-gate attDesc.setRequiresExplicitMatch(true); 19727c478bd9Sstevel@tonic-gate return EXPLICIT_MASK; 19737c478bd9Sstevel@tonic-gate } 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate } else if (flag.equalsIgnoreCase(OPTIONAL_FLAG)) { 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate if ((matched & OPTIONAL_MASK) != 0) { 19787c478bd9Sstevel@tonic-gate duplicate = true; 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate } else { 19817c478bd9Sstevel@tonic-gate attDesc.setIsOptional(true); 19827c478bd9Sstevel@tonic-gate return OPTIONAL_MASK; 19837c478bd9Sstevel@tonic-gate } 19847c478bd9Sstevel@tonic-gate 19857c478bd9Sstevel@tonic-gate } else { 19867c478bd9Sstevel@tonic-gate 19877c478bd9Sstevel@tonic-gate throw 19887c478bd9Sstevel@tonic-gate new ServiceLocationException( 1989*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 19907c478bd9Sstevel@tonic-gate "template_invalid_attr_flag", 19917c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(lineno)}); 19927c478bd9Sstevel@tonic-gate } 19937c478bd9Sstevel@tonic-gate 19947c478bd9Sstevel@tonic-gate 19957c478bd9Sstevel@tonic-gate if (duplicate) { 19967c478bd9Sstevel@tonic-gate throw 19977c478bd9Sstevel@tonic-gate new ServiceLocationException( 1998*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 19997c478bd9Sstevel@tonic-gate "template_dup_attr_flag", 20007c478bd9Sstevel@tonic-gate new Object[] {Integer.toString(lineno)}); 20017c478bd9Sstevel@tonic-gate } 20027c478bd9Sstevel@tonic-gate 20037c478bd9Sstevel@tonic-gate return 0; // never happens. 20047c478bd9Sstevel@tonic-gate } 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate // Parse a word out of the tokenizer. The exact characters 20077c478bd9Sstevel@tonic-gate // will depend on what the syntax tables have been set to. 20087c478bd9Sstevel@tonic-gate parseWord(StreamTokenizer tk, int baseLineno)2009*55fea89dSDan Cross private String parseWord(StreamTokenizer tk, int baseLineno) 20107c478bd9Sstevel@tonic-gate throws ServiceLocationException, IOException { 20117c478bd9Sstevel@tonic-gate 20127c478bd9Sstevel@tonic-gate int tt = tk.nextToken(); 20137c478bd9Sstevel@tonic-gate 20147c478bd9Sstevel@tonic-gate if (tt == StreamTokenizer.TT_WORD) { 20157c478bd9Sstevel@tonic-gate return (tk.sval); 20167c478bd9Sstevel@tonic-gate 20177c478bd9Sstevel@tonic-gate } else { 20187c478bd9Sstevel@tonic-gate 20197c478bd9Sstevel@tonic-gate String errorToken = ""; 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate // Report the erroneous characters. 20227c478bd9Sstevel@tonic-gate 20237c478bd9Sstevel@tonic-gate if (tt == StreamTokenizer.TT_NUMBER) { 20247c478bd9Sstevel@tonic-gate errorToken = Double.toString(tk.nval); 20257c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOL) { 20267c478bd9Sstevel@tonic-gate errorToken = "<end of line>"; 20277c478bd9Sstevel@tonic-gate } else if (tt == StreamTokenizer.TT_EOF) { 20287c478bd9Sstevel@tonic-gate errorToken = "<end of file>"; 20297c478bd9Sstevel@tonic-gate } else { 20307c478bd9Sstevel@tonic-gate errorToken = (new Character((char)tt)).toString(); 20317c478bd9Sstevel@tonic-gate } 2032*55fea89dSDan Cross 20337c478bd9Sstevel@tonic-gate throw 20347c478bd9Sstevel@tonic-gate new ServiceLocationException( 2035*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 20367c478bd9Sstevel@tonic-gate "template_invalid_tok", 20377c478bd9Sstevel@tonic-gate new Object[] { 20387c478bd9Sstevel@tonic-gate Integer.toString(tk.lineno() + baseLineno)}); 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate } 20417c478bd9Sstevel@tonic-gate 20427c478bd9Sstevel@tonic-gate } 20437c478bd9Sstevel@tonic-gate 20447c478bd9Sstevel@tonic-gate // Convert a value list token to the value. 20457c478bd9Sstevel@tonic-gate convertValue(String type, String reqTok, int lineno)20467c478bd9Sstevel@tonic-gate private Object convertValue(String type, 20477c478bd9Sstevel@tonic-gate String reqTok, 2048*55fea89dSDan Cross int lineno) 20497c478bd9Sstevel@tonic-gate throws ServiceLocationException, 20507c478bd9Sstevel@tonic-gate IOException { 20517c478bd9Sstevel@tonic-gate 20527c478bd9Sstevel@tonic-gate Object reqVal = null; 20537c478bd9Sstevel@tonic-gate 20547c478bd9Sstevel@tonic-gate if (type.equals(JAVA_STRING_TYPE)) { 2055*55fea89dSDan Cross 20567c478bd9Sstevel@tonic-gate // Expand out any escaped ``#''. It won't be handled by 20577c478bd9Sstevel@tonic-gate // SLA. 20587c478bd9Sstevel@tonic-gate 20597c478bd9Sstevel@tonic-gate reqTok = unescapeHash(reqTok); 20607c478bd9Sstevel@tonic-gate 20617c478bd9Sstevel@tonic-gate // Expand out character escapes. 20627c478bd9Sstevel@tonic-gate 2063*55fea89dSDan Cross reqVal = 20647c478bd9Sstevel@tonic-gate ServiceLocationAttribute.unescapeAttributeString(reqTok, 20657c478bd9Sstevel@tonic-gate false); 20667c478bd9Sstevel@tonic-gate 20677c478bd9Sstevel@tonic-gate } else if (type.equals(JAVA_INTEGER_TYPE)) { 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate try { 20707c478bd9Sstevel@tonic-gate 20717c478bd9Sstevel@tonic-gate reqVal = Integer.valueOf(reqTok); 20727c478bd9Sstevel@tonic-gate 20737c478bd9Sstevel@tonic-gate } catch (NumberFormatException ex) { 20747c478bd9Sstevel@tonic-gate 2075*55fea89dSDan Cross throw 20767c478bd9Sstevel@tonic-gate new ServiceLocationException( 2077*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 20787c478bd9Sstevel@tonic-gate "template_expect_int", 20797c478bd9Sstevel@tonic-gate new Object[] { 20807c478bd9Sstevel@tonic-gate Integer.toString(lineno), reqTok }); 20817c478bd9Sstevel@tonic-gate } 20827c478bd9Sstevel@tonic-gate } else if (type.equals(JAVA_BOOLEAN_TYPE)) { 20837c478bd9Sstevel@tonic-gate 20847c478bd9Sstevel@tonic-gate // Boolean.valueOf() doesn't handle this properly. 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate if (reqTok.equalsIgnoreCase(TRUE_TOKEN)) { 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate reqVal = new Boolean(true); 20897c478bd9Sstevel@tonic-gate 20907c478bd9Sstevel@tonic-gate } else if (reqTok.equalsIgnoreCase(FALSE_TOKEN)) { 2091*55fea89dSDan Cross 20927c478bd9Sstevel@tonic-gate reqVal = new Boolean(false); 20937c478bd9Sstevel@tonic-gate 20947c478bd9Sstevel@tonic-gate } else { 20957c478bd9Sstevel@tonic-gate 20967c478bd9Sstevel@tonic-gate throw 20977c478bd9Sstevel@tonic-gate new ServiceLocationException( 2098*55fea89dSDan Cross ServiceLocationException.PARSE_ERROR, 20997c478bd9Sstevel@tonic-gate "template_expect_bool", 21007c478bd9Sstevel@tonic-gate new Object[] { 21017c478bd9Sstevel@tonic-gate Integer.toString(lineno), reqTok}); 21027c478bd9Sstevel@tonic-gate } 21037c478bd9Sstevel@tonic-gate } else if (type.equals(JAVA_OPAQUE_TYPE)) { 2104*55fea89dSDan Cross 21057c478bd9Sstevel@tonic-gate reqVal = Opaque.unescapeByteArray(reqTok); 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate } else { 21087c478bd9Sstevel@tonic-gate 21097c478bd9Sstevel@tonic-gate Assert.slpassert(false, 21107c478bd9Sstevel@tonic-gate "template_attr_desc", 21117c478bd9Sstevel@tonic-gate new Object[0]); 21127c478bd9Sstevel@tonic-gate } 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate return reqVal; 21157c478bd9Sstevel@tonic-gate } 21167c478bd9Sstevel@tonic-gate 21177c478bd9Sstevel@tonic-gate // Expand out any escaped hashes. Not handled by SLA. 21187c478bd9Sstevel@tonic-gate unescapeHash(String str)21197c478bd9Sstevel@tonic-gate private String unescapeHash(String str) { 21207c478bd9Sstevel@tonic-gate 21217c478bd9Sstevel@tonic-gate StringBuffer buf = new StringBuffer(); 21227c478bd9Sstevel@tonic-gate int len = ESC_HASH.length(); 21237c478bd9Sstevel@tonic-gate int i, j = 0; 21247c478bd9Sstevel@tonic-gate 21257c478bd9Sstevel@tonic-gate for (i = str.indexOf(ESC_HASH, j); 2126*55fea89dSDan Cross i != -1; 21277c478bd9Sstevel@tonic-gate i = str.indexOf(ESC_HASH, j)) { 21287c478bd9Sstevel@tonic-gate 21297c478bd9Sstevel@tonic-gate buf.append(str.substring(j, i)); 21307c478bd9Sstevel@tonic-gate buf.append(HASH); 21317c478bd9Sstevel@tonic-gate j = i + len; 21327c478bd9Sstevel@tonic-gate } 21337c478bd9Sstevel@tonic-gate 21347c478bd9Sstevel@tonic-gate len = str.length(); 21357c478bd9Sstevel@tonic-gate 21367c478bd9Sstevel@tonic-gate if (j < len) { 21377c478bd9Sstevel@tonic-gate buf.append(str.substring(j, len)); 21387c478bd9Sstevel@tonic-gate 21397c478bd9Sstevel@tonic-gate } 21407c478bd9Sstevel@tonic-gate 21417c478bd9Sstevel@tonic-gate return buf.toString(); 21427c478bd9Sstevel@tonic-gate } 21437c478bd9Sstevel@tonic-gate 21447c478bd9Sstevel@tonic-gate } 2145