001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.matching.helpers;
018:
019: import java.util.HashMap;
020:
021: /**
022: * This class is an utility class that perform wilcard-patterns matching and
023: * isolation.
024: *
025: * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
026: * (Apache Software Foundation)
027: * @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
028: * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
029: * @version CVS $Id: WildcardURIMatcher.java 433543 2006-08-22 06:22:54Z crossley $
030: * @deprecated renamed to WildcardHelper
031: */
032: public class WildcardURIMatcher {
033:
034: /** The int representing '*' in the pattern <code>int []</code>. */
035: protected static final int MATCH_FILE = -1;
036: /** The int representing '**' in the pattern <code>int []</code>. */
037: protected static final int MATCH_PATH = -2;
038: /** The int representing begin in the pattern <code>int []</code>. */
039: protected static final int MATCH_BEGIN = -4;
040: /** The int representing end in pattern <code>int []</code>. */
041: protected static final int MATCH_THEEND = -5;
042: /** The int value that terminates the pattern <code>int []</code>. */
043: protected static final int MATCH_END = -3;
044:
045: /**
046: * match a pattern agains a string and isolates wildcard replacement into a
047: * <code>Stack</code>.
048: */
049: public static boolean match(HashMap map, String data, int[] expr)
050: throws NullPointerException {
051: if (map == null)
052: throw new NullPointerException("No map provided");
053: if (data == null)
054: throw new NullPointerException("No data provided");
055: if (expr == null)
056: throw new NullPointerException(
057: "No pattern expression provided");
058:
059: char buff[] = data.toCharArray();
060: // Allocate the result buffer
061: char rslt[] = new char[expr.length + buff.length];
062:
063: // The previous and current position of the expression character
064: // (MATCH_*)
065: int charpos = 0;
066:
067: // The position in the expression, input, translation and result arrays
068: int exprpos = 0;
069: int buffpos = 0;
070: int rsltpos = 0;
071: int offset = -1;
072:
073: // The matching count
074: int mcount = 0;
075:
076: // We want the complete data be in {0}
077: map.put(Integer.toString(mcount), data);
078:
079: // First check for MATCH_BEGIN
080: boolean matchBegin = false;
081: if (expr[charpos] == MATCH_BEGIN) {
082: matchBegin = true;
083: exprpos = ++charpos;
084: }
085:
086: // Search the fist expression character (except MATCH_BEGIN - already skipped)
087: while (expr[charpos] >= 0)
088: charpos++;
089:
090: // The expression charater (MATCH_*)
091: int exprchr = expr[charpos];
092:
093: while (true) {
094: // Check if the data in the expression array before the current
095: // expression character matches the data in the input buffer
096: if (matchBegin) {
097: if (!matchArray(expr, exprpos, charpos, buff, buffpos))
098: return (false);
099: matchBegin = false;
100: } else {
101: offset = indexOfArray(expr, exprpos, charpos, buff,
102: buffpos);
103: if (offset < 0)
104: return (false);
105: }
106:
107: // Check for MATCH_BEGIN
108: if (matchBegin) {
109: if (offset != 0)
110: return (false);
111: matchBegin = false;
112: }
113:
114: // Advance buffpos
115: buffpos += (charpos - exprpos);
116:
117: // Check for END's
118: if (exprchr == MATCH_END) {
119: if (rsltpos > 0)
120: map.put(Integer.toString(++mcount), new String(
121: rslt, 0, rsltpos));
122: // Don't care about rest of input buffer
123: return (true);
124: } else if (exprchr == MATCH_THEEND) {
125: if (rsltpos > 0)
126: map.put(Integer.toString(++mcount), new String(
127: rslt, 0, rsltpos));
128: // Check that we reach buffer's end
129: return (buffpos == buff.length);
130: }
131:
132: // Search the next expression character
133: exprpos = ++charpos;
134: while (expr[charpos] >= 0)
135: charpos++;
136: int prevchr = exprchr;
137: exprchr = expr[charpos];
138:
139: // We have here prevchr == * or **.
140: offset = (prevchr == MATCH_FILE) ? indexOfArray(expr,
141: exprpos, charpos, buff, buffpos)
142: : lastIndexOfArray(expr, exprpos, charpos, buff,
143: buffpos);
144:
145: if (offset < 0)
146: return (false);
147:
148: // Copy the data from the source buffer into the result buffer
149: // to substitute the expression character
150: if (prevchr == MATCH_PATH) {
151: while (buffpos < offset)
152: rslt[rsltpos++] = buff[buffpos++];
153: } else {
154: // Matching file, don't copy '/'
155: while (buffpos < offset) {
156: if (buff[buffpos] == '/')
157: return (false);
158: rslt[rsltpos++] = buff[buffpos++];
159: }
160: }
161:
162: map.put(Integer.toString(++mcount), new String(rslt, 0,
163: rsltpos));
164: rsltpos = 0;
165: }
166: }
167:
168: /**
169: * Get the offset of a part of an int array within a char array.
170: * <br>
171: * This method return the index in d of the first occurrence after dpos of
172: * that part of array specified by r, starting at rpos and terminating at
173: * rend.
174: *
175: * @param r The array containing the data that need to be matched in d.
176: * @param rpos The index of the first character in r to look for.
177: * @param rend The index of the last character in r to look for plus 1.
178: * @param d The array of char that should contain a part of r.
179: * @param dpos The starting offset in d for the matching.
180: * @return The offset in d of the part of r matched in d or -1 if that was
181: * not found.
182: */
183: protected static int indexOfArray(int r[], int rpos, int rend,
184: char d[], int dpos) {
185: // Check if pos and len are legal
186: if (rend < rpos)
187: throw new IllegalArgumentException("rend < rpos");
188: // If we need to match a zero length string return current dpos
189: if (rend == rpos)
190: return (d.length); //?? dpos?
191: // If we need to match a 1 char length string do it simply
192: if ((rend - rpos) == 1) {
193: // Search for the specified character
194: for (int x = dpos; x < d.length; x++)
195: if (r[rpos] == d[x])
196: return (x);
197: }
198: // Main string matching loop. It gets executed if the characters to
199: // match are less then the characters left in the d buffer
200: while ((dpos + rend - rpos) <= d.length) {
201: // Set current startpoint in d
202: int y = dpos;
203: // Check every character in d for equity. If the string is matched
204: // return dpos
205: for (int x = rpos; x <= rend; x++) {
206: if (x == rend)
207: return (dpos);
208: if (r[x] != d[y++])
209: break;
210: }
211: // Increase dpos to search for the same string at next offset
212: dpos++;
213: }
214: // The remaining chars in d buffer were not enough or the string
215: // wasn't matched
216: return (-1);
217: }
218:
219: /**
220: * Get the offset of a last occurance of an int array within a char array.
221: * <br>
222: * This method return the index in d of the last occurrence after dpos of
223: * that part of array specified by r, starting at rpos and terminating at
224: * rend.
225: *
226: * @param r The array containing the data that need to be matched in d.
227: * @param rpos The index of the first character in r to look for.
228: * @param rend The index of the last character in r to look for plus 1.
229: * @param d The array of char that should contain a part of r.
230: * @param dpos The starting offset in d for the matching.
231: * @return The offset in d of the last part of r matched in d or -1 if that was
232: * not found.
233: */
234: protected static int lastIndexOfArray(int r[], int rpos, int rend,
235: char d[], int dpos) {
236: // Check if pos and len are legal
237: if (rend < rpos)
238: throw new IllegalArgumentException("rend < rpos");
239: // If we need to match a zero length string return current dpos
240: if (rend == rpos)
241: return (d.length); //?? dpos?
242:
243: // If we need to match a 1 char length string do it simply
244: if ((rend - rpos) == 1) {
245: // Search for the specified character
246: for (int x = d.length - 1; x > dpos; x--)
247: if (r[rpos] == d[x])
248: return (x);
249: }
250:
251: // Main string matching loop. It gets executed if the characters to
252: // match are less then the characters left in the d buffer
253: int l = d.length - (rend - rpos);
254: while (l >= dpos) {
255: // Set current startpoint in d
256: int y = l;
257: // Check every character in d for equity. If the string is matched
258: // return dpos
259: for (int x = rpos; x <= rend; x++) {
260: if (x == rend)
261: return (l);
262: if (r[x] != d[y++])
263: break;
264: }
265: // Decrease l to search for the same string at next offset
266: l--;
267: }
268: // The remaining chars in d buffer were not enough or the string
269: // wasn't matched
270: return (-1);
271: }
272:
273: /**
274: * Matches elements of array r from rpos to rend with array d, starting from dpos.
275: * <br>
276: * This method return true if elements of array r from rpos to rend
277: * equals elements of array d starting from dpos to dpos+(rend-rpos).
278: *
279: * @param r The array containing the data that need to be matched in d.
280: * @param rpos The index of the first character in r to look for.
281: * @param d The array of char that should start from a part of r.
282: * @param dpos The starting offset in d for the matching.
283: * @return true if array d starts from portion of array r.
284: */
285: protected static boolean matchArray(int r[], int rpos, int rend,
286: char d[], int dpos) {
287: if (d.length - dpos < rend - rpos)
288: return (false);
289: for (int i = rpos; i < rend; i++)
290: if (r[i] != d[dpos++])
291: return (false);
292: return (true);
293: }
294: }
|