10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7298SMark.J.Nelson@Sun.COM * Common Development and Distribution License (the "License"). 6*7298SMark.J.Nelson@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 220Sstevel@tonic-gate * Copyright (c) 1999 by Sun Microsystems, Inc. 230Sstevel@tonic-gate * All rights reserved. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate // AttributePattern.java: Models a pattern for attribute matching. 280Sstevel@tonic-gate // Author: James Kempf 290Sstevel@tonic-gate // Created On: Tue Feb 3 15:26:30 1998 300Sstevel@tonic-gate // Last Modified By: James Kempf 310Sstevel@tonic-gate // Last Modified On: Thu Aug 6 14:33:57 1998 320Sstevel@tonic-gate // Update Count: 19 330Sstevel@tonic-gate // 340Sstevel@tonic-gate 350Sstevel@tonic-gate package com.sun.slp; 360Sstevel@tonic-gate 370Sstevel@tonic-gate import java.util.*; 380Sstevel@tonic-gate import java.io.*; 390Sstevel@tonic-gate 400Sstevel@tonic-gate /** 410Sstevel@tonic-gate * The AttributePattern class models an attribute pattern. It handles 420Sstevel@tonic-gate * wildcard matching of lowercased, space-compressed strings. Each 430Sstevel@tonic-gate * element in the parts vector is a PatternPart object. A PatternPart 440Sstevel@tonic-gate * object is a pattern consisting of (maximally) a beginning wildcard and 450Sstevel@tonic-gate * string pattern. A PatternPart may be lacking the 460Sstevel@tonic-gate * any of these, but will always have at least one. 470Sstevel@tonic-gate * 480Sstevel@tonic-gate * @author James Kempf 490Sstevel@tonic-gate */ 500Sstevel@tonic-gate 510Sstevel@tonic-gate class AttributePattern extends AttributeString { 520Sstevel@tonic-gate 530Sstevel@tonic-gate private static final String WILDCARD = "*"; 540Sstevel@tonic-gate 550Sstevel@tonic-gate private Vector parts = new Vector(); 560Sstevel@tonic-gate 570Sstevel@tonic-gate /** 580Sstevel@tonic-gate * The PatternPart class models a single component of a pattern. 590Sstevel@tonic-gate * It may have a beginning wildcard and string 600Sstevel@tonic-gate * pattern in the middle. Any of the parts may be missing, but it will 610Sstevel@tonic-gate * always have at least one. 620Sstevel@tonic-gate * 630Sstevel@tonic-gate * @author James Kempf 640Sstevel@tonic-gate */ 650Sstevel@tonic-gate 660Sstevel@tonic-gate 670Sstevel@tonic-gate private class PatternPart extends Object { 680Sstevel@tonic-gate 690Sstevel@tonic-gate boolean wildcard = false; 700Sstevel@tonic-gate String pattern = ""; 710Sstevel@tonic-gate PatternPart(boolean wc, String str)720Sstevel@tonic-gate PatternPart(boolean wc, String str) { 730Sstevel@tonic-gate wildcard = wc; 740Sstevel@tonic-gate pattern = str; 750Sstevel@tonic-gate 760Sstevel@tonic-gate } 770Sstevel@tonic-gate } 780Sstevel@tonic-gate AttributePattern(String str, Locale locale)790Sstevel@tonic-gate AttributePattern(String str, Locale locale) { 800Sstevel@tonic-gate 810Sstevel@tonic-gate super(str, locale); 820Sstevel@tonic-gate 830Sstevel@tonic-gate // Parse out wildcards into PatternPart objects. 840Sstevel@tonic-gate 850Sstevel@tonic-gate // If there's no wildcards, simply insert the string in as the pattern. 860Sstevel@tonic-gate 870Sstevel@tonic-gate if (cstring.indexOf(WILDCARD) == -1) { 880Sstevel@tonic-gate parts.addElement(new PatternPart(false, cstring)); 890Sstevel@tonic-gate 900Sstevel@tonic-gate } else { 910Sstevel@tonic-gate 920Sstevel@tonic-gate // Parse the patterns into parts. 930Sstevel@tonic-gate 940Sstevel@tonic-gate StringTokenizer tk = new StringTokenizer(cstring, WILDCARD, true); 950Sstevel@tonic-gate 960Sstevel@tonic-gate while (tk.hasMoreTokens()) { 970Sstevel@tonic-gate String middle = ""; 980Sstevel@tonic-gate boolean wc = false; 990Sstevel@tonic-gate 1000Sstevel@tonic-gate String tok = tk.nextToken(); 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate // Beginning wildcard, or, if none, then the middle. 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate if (tok.equals(WILDCARD)) { 1050Sstevel@tonic-gate wc = true; 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate // Need to look for middle. 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate if (tk.hasMoreTokens()) { 1100Sstevel@tonic-gate middle = tk.nextToken(); 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate } 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate } else { 1150Sstevel@tonic-gate middle = tok; 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate // Note that there may be a terminal pattern part that just 1200Sstevel@tonic-gate // consists of a wildcard. 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate parts.addElement(new PatternPart(wc, middle)); 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate } 1260Sstevel@tonic-gate isWildcarded()1270Sstevel@tonic-gate boolean isWildcarded() { 1280Sstevel@tonic-gate return (parts.size() > 1); 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate } 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate // Match the AttributeString object against this pattern, 1330Sstevel@tonic-gate // returning true if they match. 1340Sstevel@tonic-gate match(AttributeString str)1350Sstevel@tonic-gate public boolean match(AttributeString str) { 1360Sstevel@tonic-gate String cstring = str.cstring; 1370Sstevel@tonic-gate int offset = 0, len = cstring.length(); 1380Sstevel@tonic-gate int i = 0, n = parts.size(); 1390Sstevel@tonic-gate boolean match = true; 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate // March through the parts, matching against the string. 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate for (; i < n; i++) { 1440Sstevel@tonic-gate PatternPart p = (PatternPart)parts.elementAt(i); 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate // If there's a wildcard, check the remainder of the string for 1470Sstevel@tonic-gate // the pattern. 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate if (p.wildcard) { 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate // Note that if the pattern string is empty (""), then this 1520Sstevel@tonic-gate // will return offset, but on the next iteration, it will 1530Sstevel@tonic-gate // fall out of the loop because an empty pattern string 1540Sstevel@tonic-gate // can only occur at the end (like "foo*"). 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate if ((offset = cstring.indexOf(p.pattern, offset)) == -1) { 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate // The pattern was not found. Break out of the loop. 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate match = false; 1610Sstevel@tonic-gate break; 1620Sstevel@tonic-gate } 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate offset += p.pattern.length(); 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate // We are at the end of the string. 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate if (offset >= len) { 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate // If we are not at the end of the pattern, then we may not 1710Sstevel@tonic-gate // have a match. 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate if (i < (n - 1)) { 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate // If there is one more in the pattern, and it is 1760Sstevel@tonic-gate // a pure wildcard, then we *do* have a match. 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate if (i == (n - 2)) { 1790Sstevel@tonic-gate p = (PatternPart)parts.elementAt(i+1); 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate if (p.wildcard == true && 1820Sstevel@tonic-gate p.pattern.length() <= 0) { 1830Sstevel@tonic-gate break; 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate match = false; 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate // Break out of the loop, no more string to analyze. 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate break; 1950Sstevel@tonic-gate } 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate } else { 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate // The pattern string must match the beginning part of the 2000Sstevel@tonic-gate // argument string. 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate if (!cstring.regionMatches(offset, 2030Sstevel@tonic-gate p.pattern, 2040Sstevel@tonic-gate 0, 2050Sstevel@tonic-gate p. 2060Sstevel@tonic-gate pattern.length())) { 2070Sstevel@tonic-gate match = false; 2080Sstevel@tonic-gate break; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate // Bump up offset by the pattern length, and exit if 2130Sstevel@tonic-gate // we're beyond the end of the string. 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate offset += p.pattern.length(); 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate if (offset >= len) { 2180Sstevel@tonic-gate break; 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate } 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate return match; 2250Sstevel@tonic-gate } 2260Sstevel@tonic-gate } 227