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 by Sun Microsystems, Inc. 237c478bd9Sstevel@tonic-gate * All rights reserved. 247c478bd9Sstevel@tonic-gate * 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate // AttributePattern.java: Models a pattern for attribute matching. 287c478bd9Sstevel@tonic-gate // Author: James Kempf 297c478bd9Sstevel@tonic-gate // Created On: Tue Feb 3 15:26:30 1998 307c478bd9Sstevel@tonic-gate // Last Modified By: James Kempf 317c478bd9Sstevel@tonic-gate // Last Modified On: Thu Aug 6 14:33:57 1998 327c478bd9Sstevel@tonic-gate // Update Count: 19 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 AttributePattern class models an attribute pattern. It handles 427c478bd9Sstevel@tonic-gate * wildcard matching of lowercased, space-compressed strings. Each 437c478bd9Sstevel@tonic-gate * element in the parts vector is a PatternPart object. A PatternPart 447c478bd9Sstevel@tonic-gate * object is a pattern consisting of (maximally) a beginning wildcard and 457c478bd9Sstevel@tonic-gate * string pattern. A PatternPart may be lacking the 46*55fea89dSDan Cross * any of these, but will always have at least one. 477c478bd9Sstevel@tonic-gate * 487c478bd9Sstevel@tonic-gate * @author James Kempf 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate class AttributePattern extends AttributeString { 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate private static final String WILDCARD = "*"; 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate private Vector parts = new Vector(); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /** 587c478bd9Sstevel@tonic-gate * The PatternPart class models a single component of a pattern. 597c478bd9Sstevel@tonic-gate * It may have a beginning wildcard and string 60*55fea89dSDan Cross * pattern in the middle. Any of the parts may be missing, but it will 61*55fea89dSDan Cross * always have at least one. 627c478bd9Sstevel@tonic-gate * 637c478bd9Sstevel@tonic-gate * @author James Kempf 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate private class PatternPart extends Object { 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate boolean wildcard = false; 707c478bd9Sstevel@tonic-gate String pattern = ""; 717c478bd9Sstevel@tonic-gate PatternPart(boolean wc, String str)727c478bd9Sstevel@tonic-gate PatternPart(boolean wc, String str) { 737c478bd9Sstevel@tonic-gate wildcard = wc; 747c478bd9Sstevel@tonic-gate pattern = str; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate AttributePattern(String str, Locale locale)797c478bd9Sstevel@tonic-gate AttributePattern(String str, Locale locale) { 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate super(str, locale); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate // Parse out wildcards into PatternPart objects. 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate // If there's no wildcards, simply insert the string in as the pattern. 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate if (cstring.indexOf(WILDCARD) == -1) { 887c478bd9Sstevel@tonic-gate parts.addElement(new PatternPart(false, cstring)); 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate } else { 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate // Parse the patterns into parts. 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate StringTokenizer tk = new StringTokenizer(cstring, WILDCARD, true); 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate while (tk.hasMoreTokens()) { 977c478bd9Sstevel@tonic-gate String middle = ""; 987c478bd9Sstevel@tonic-gate boolean wc = false; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate String tok = tk.nextToken(); 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate // Beginning wildcard, or, if none, then the middle. 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate if (tok.equals(WILDCARD)) { 1057c478bd9Sstevel@tonic-gate wc = true; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate // Need to look for middle. 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate if (tk.hasMoreTokens()) { 1107c478bd9Sstevel@tonic-gate middle = tk.nextToken(); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate } else { 1157c478bd9Sstevel@tonic-gate middle = tok; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate // Note that there may be a terminal pattern part that just 1207c478bd9Sstevel@tonic-gate // consists of a wildcard. 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate parts.addElement(new PatternPart(wc, middle)); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate isWildcarded()1277c478bd9Sstevel@tonic-gate boolean isWildcarded() { 1287c478bd9Sstevel@tonic-gate return (parts.size() > 1); 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate // Match the AttributeString object against this pattern, 1337c478bd9Sstevel@tonic-gate // returning true if they match. 1347c478bd9Sstevel@tonic-gate match(AttributeString str)1357c478bd9Sstevel@tonic-gate public boolean match(AttributeString str) { 1367c478bd9Sstevel@tonic-gate String cstring = str.cstring; 1377c478bd9Sstevel@tonic-gate int offset = 0, len = cstring.length(); 1387c478bd9Sstevel@tonic-gate int i = 0, n = parts.size(); 1397c478bd9Sstevel@tonic-gate boolean match = true; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate // March through the parts, matching against the string. 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate for (; i < n; i++) { 1447c478bd9Sstevel@tonic-gate PatternPart p = (PatternPart)parts.elementAt(i); 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate // If there's a wildcard, check the remainder of the string for 1477c478bd9Sstevel@tonic-gate // the pattern. 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate if (p.wildcard) { 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate // Note that if the pattern string is empty (""), then this 1527c478bd9Sstevel@tonic-gate // will return offset, but on the next iteration, it will 1537c478bd9Sstevel@tonic-gate // fall out of the loop because an empty pattern string 1547c478bd9Sstevel@tonic-gate // can only occur at the end (like "foo*"). 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate if ((offset = cstring.indexOf(p.pattern, offset)) == -1) { 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate // The pattern was not found. Break out of the loop. 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate match = false; 1617c478bd9Sstevel@tonic-gate break; 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate offset += p.pattern.length(); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate // We are at the end of the string. 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate if (offset >= len) { 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate // If we are not at the end of the pattern, then we may not 1717c478bd9Sstevel@tonic-gate // have a match. 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate if (i < (n - 1)) { 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate // If there is one more in the pattern, and it is 1767c478bd9Sstevel@tonic-gate // a pure wildcard, then we *do* have a match. 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate if (i == (n - 2)) { 1797c478bd9Sstevel@tonic-gate p = (PatternPart)parts.elementAt(i+1); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate if (p.wildcard == true && 1827c478bd9Sstevel@tonic-gate p.pattern.length() <= 0) { 1837c478bd9Sstevel@tonic-gate break; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate match = false; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate // Break out of the loop, no more string to analyze. 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate break; 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate } else { 1987c478bd9Sstevel@tonic-gate 199*55fea89dSDan Cross // The pattern string must match the beginning part of the 2007c478bd9Sstevel@tonic-gate // argument string. 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate if (!cstring.regionMatches(offset, 2037c478bd9Sstevel@tonic-gate p.pattern, 2047c478bd9Sstevel@tonic-gate 0, 2057c478bd9Sstevel@tonic-gate p. 2067c478bd9Sstevel@tonic-gate pattern.length())) { 2077c478bd9Sstevel@tonic-gate match = false; 2087c478bd9Sstevel@tonic-gate break; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate // Bump up offset by the pattern length, and exit if 2137c478bd9Sstevel@tonic-gate // we're beyond the end of the string. 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate offset += p.pattern.length(); 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (offset >= len) { 2187c478bd9Sstevel@tonic-gate break; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate return match; 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate } 227