| /* |
| * Copyright 1999-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.cocoon.matching.helpers; |
| |
| import java.util.HashMap; |
| |
| /** |
| * This class is an utility class that perform wilcard-patterns matching and |
| * isolation. |
| * |
| * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a> |
| * (Apache Software Foundation) |
| * @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a> |
| * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a> |
| * @version CVS $Id: WildcardURIMatcher.java,v 1.2 2004/03/05 13:02:42 bdelacretaz Exp $ |
| * @deprecated renamed to WildcardHelper |
| */ |
| public class WildcardURIMatcher { |
| |
| /** The int representing '*' in the pattern <code>int []</code>. */ |
| protected static final int MATCH_FILE = -1; |
| /** The int representing '**' in the pattern <code>int []</code>. */ |
| protected static final int MATCH_PATH = -2; |
| /** The int representing begin in the pattern <code>int []</code>. */ |
| protected static final int MATCH_BEGIN = -4; |
| /** The int representing end in pattern <code>int []</code>. */ |
| protected static final int MATCH_THEEND = -5; |
| /** The int value that terminates the pattern <code>int []</code>. */ |
| protected static final int MATCH_END = -3; |
| |
| /** |
| * match a pattern agains a string and isolates wildcard replacement into a |
| * <code>Stack</code>. |
| */ |
| public static boolean match (HashMap map, String data, |
| int[] expr) throws NullPointerException { |
| if (map == null) |
| throw new NullPointerException ("No map provided"); |
| if (data == null) |
| throw new NullPointerException ("No data provided"); |
| if (expr == null) |
| throw new NullPointerException ("No pattern expression provided"); |
| |
| |
| char buff[] = data.toCharArray(); |
| // Allocate the result buffer |
| char rslt[] = new char[expr.length + buff.length]; |
| |
| |
| // The previous and current position of the expression character |
| // (MATCH_*) |
| int charpos = 0; |
| |
| // The position in the expression, input, translation and result arrays |
| int exprpos = 0; |
| int buffpos = 0; |
| int rsltpos = 0; |
| int offset = -1; |
| |
| // The matching count |
| int mcount = 0; |
| |
| // We want the complete data be in {0} |
| map.put(Integer.toString(mcount),data); |
| |
| // First check for MATCH_BEGIN |
| boolean matchBegin = false; |
| if (expr[charpos] == MATCH_BEGIN) { |
| matchBegin = true; |
| exprpos = ++charpos; |
| } |
| |
| // Search the fist expression character (except MATCH_BEGIN - already skipped) |
| while (expr[charpos] >= 0) |
| charpos++; |
| |
| // The expression charater (MATCH_*) |
| int exprchr = expr[charpos]; |
| |
| while (true) { |
| // Check if the data in the expression array before the current |
| // expression character matches the data in the input buffer |
| if (matchBegin) { |
| if (!matchArray(expr, exprpos, charpos, buff, buffpos)) |
| return (false); |
| matchBegin = false; |
| } else { |
| offset = indexOfArray (expr, exprpos, charpos, buff, |
| buffpos); |
| if (offset < 0) |
| return (false); |
| } |
| |
| // Check for MATCH_BEGIN |
| if (matchBegin) { |
| if (offset != 0) |
| return (false); |
| matchBegin = false; |
| } |
| |
| // Advance buffpos |
| buffpos += (charpos - exprpos); |
| |
| // Check for END's |
| if (exprchr == MATCH_END) { |
| if (rsltpos > 0) |
| map.put(Integer.toString(++mcount),new String(rslt, 0, rsltpos)); |
| // Don't care about rest of input buffer |
| return (true); |
| } else if (exprchr == MATCH_THEEND) { |
| if (rsltpos > 0) |
| map.put (Integer.toString(++mcount),new String(rslt, 0, rsltpos)); |
| // Check that we reach buffer's end |
| return (buffpos == buff.length); |
| } |
| |
| // Search the next expression character |
| exprpos = ++charpos; |
| while (expr[charpos] >= 0) |
| charpos++; |
| int prevchr = exprchr; |
| exprchr = expr[charpos]; |
| |
| // We have here prevchr == * or **. |
| offset = (prevchr == MATCH_FILE) ? |
| indexOfArray (expr, exprpos, charpos, buff, buffpos) : |
| lastIndexOfArray (expr, exprpos, charpos, buff, |
| buffpos); |
| |
| if (offset < 0) |
| return (false); |
| |
| // Copy the data from the source buffer into the result buffer |
| // to substitute the expression character |
| if (prevchr == MATCH_PATH) { |
| while (buffpos < offset) |
| rslt[rsltpos++] = buff[buffpos++]; |
| } else { |
| // Matching file, don't copy '/' |
| while (buffpos < offset) { |
| if (buff[buffpos] == '/') |
| return (false); |
| rslt[rsltpos++] = buff[buffpos++]; |
| } |
| } |
| |
| map.put(Integer.toString(++mcount),new String (rslt, 0, rsltpos)); |
| rsltpos = 0; |
| } |
| } |
| |
| /** |
| * Get the offset of a part of an int array within a char array. |
| * <br> |
| * This method return the index in d of the first occurrence after dpos of |
| * that part of array specified by r, starting at rpos and terminating at |
| * rend. |
| * |
| * @param r The array containing the data that need to be matched in d. |
| * @param rpos The index of the first character in r to look for. |
| * @param rend The index of the last character in r to look for plus 1. |
| * @param d The array of char that should contain a part of r. |
| * @param dpos The starting offset in d for the matching. |
| * @return The offset in d of the part of r matched in d or -1 if that was |
| * not found. |
| */ |
| protected static int indexOfArray (int r[], int rpos, int rend, |
| char d[], int dpos) { |
| // Check if pos and len are legal |
| if (rend < rpos) |
| throw new IllegalArgumentException ("rend < rpos"); |
| // If we need to match a zero length string return current dpos |
| if (rend == rpos) |
| return (d.length); //?? dpos? |
| // If we need to match a 1 char length string do it simply |
| if ((rend - rpos) == 1) { |
| // Search for the specified character |
| for (int x = dpos; x < d.length; x++) |
| if (r[rpos] == d[x]) |
| return (x); |
| } |
| // Main string matching loop. It gets executed if the characters to |
| // match are less then the characters left in the d buffer |
| while ((dpos + rend - rpos) <= d.length) { |
| // Set current startpoint in d |
| int y = dpos; |
| // Check every character in d for equity. If the string is matched |
| // return dpos |
| for (int x = rpos; x <= rend; x++) { |
| if (x == rend) |
| return (dpos); |
| if (r[x] != d[y++]) |
| break; |
| } |
| // Increase dpos to search for the same string at next offset |
| dpos++; |
| } |
| // The remaining chars in d buffer were not enough or the string |
| // wasn't matched |
| return (-1); |
| } |
| |
| /** |
| * Get the offset of a last occurance of an int array within a char array. |
| * <br> |
| * This method return the index in d of the last occurrence after dpos of |
| * that part of array specified by r, starting at rpos and terminating at |
| * rend. |
| * |
| * @param r The array containing the data that need to be matched in d. |
| * @param rpos The index of the first character in r to look for. |
| * @param rend The index of the last character in r to look for plus 1. |
| * @param d The array of char that should contain a part of r. |
| * @param dpos The starting offset in d for the matching. |
| * @return The offset in d of the last part of r matched in d or -1 if that was |
| * not found. |
| */ |
| protected static int lastIndexOfArray (int r[], int rpos, int rend, |
| char d[], int dpos) { |
| // Check if pos and len are legal |
| if (rend < rpos) |
| throw new IllegalArgumentException ("rend < rpos"); |
| // If we need to match a zero length string return current dpos |
| if (rend == rpos) |
| return (d.length); //?? dpos? |
| |
| // If we need to match a 1 char length string do it simply |
| if ((rend - rpos) == 1) { |
| // Search for the specified character |
| for (int x = d.length - 1; x > dpos; x--) |
| if (r[rpos] == d[x]) |
| return (x); |
| } |
| |
| // Main string matching loop. It gets executed if the characters to |
| // match are less then the characters left in the d buffer |
| int l = d.length - (rend - rpos); |
| while (l >= dpos) { |
| // Set current startpoint in d |
| int y = l; |
| // Check every character in d for equity. If the string is matched |
| // return dpos |
| for (int x = rpos; x <= rend; x++) { |
| if (x == rend) |
| return (l); |
| if (r[x] != d[y++]) |
| break; |
| } |
| // Decrease l to search for the same string at next offset |
| l--; |
| } |
| // The remaining chars in d buffer were not enough or the string |
| // wasn't matched |
| return (-1); |
| } |
| |
| /** |
| * Matches elements of array r from rpos to rend with array d, starting from dpos. |
| * <br> |
| * This method return true if elements of array r from rpos to rend |
| * equals elements of array d starting from dpos to dpos+(rend-rpos). |
| * |
| * @param r The array containing the data that need to be matched in d. |
| * @param rpos The index of the first character in r to look for. |
| * @param d The array of char that should start from a part of r. |
| * @param dpos The starting offset in d for the matching. |
| * @return true if array d starts from portion of array r. |
| */ |
| protected static boolean matchArray (int r[], int rpos, int rend, |
| char d[], int dpos) { |
| if (d.length - dpos < rend - rpos) |
| return (false); |
| for (int i = rpos; i < rend; i++) |
| if (r[i] != d[dpos++]) |
| return (false); |
| return (true); |
| } |
| } |