You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by mr...@apache.org on 2003/09/29 03:24:21 UTC

cvs commit: jakarta-struts/src/share/org/apache/struts/util ActionMappingMatcher.java WildcardHelper.java

mrdon       2003/09/28 18:24:21

  Modified:    src/share/org/apache/struts/action RequestProcessor.java
  Added:       src/share/org/apache/struts/util ActionMappingMatcher.java
                        WildcardHelper.java
  Log:
  Added optional wildcard support for action mappings
  
  PR: 21813
  
  Revision  Changes    Path
  1.35      +17 -6     jakarta-struts/src/share/org/apache/struts/action/RequestProcessor.java
  
  Index: RequestProcessor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/RequestProcessor.java,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- RequestProcessor.java	11 Sep 2003 01:18:45 -0000	1.34
  +++ RequestProcessor.java	29 Sep 2003 01:24:21 -0000	1.35
  @@ -82,6 +82,7 @@
   import org.apache.struts.config.ModuleConfig;
   import org.apache.struts.taglib.html.Constants;
   import org.apache.struts.upload.MultipartRequestWrapper;
  +import org.apache.struts.util.ActionMappingMatcher;
   import org.apache.struts.util.MessageResources;
   import org.apache.struts.util.RequestUtils;
   
  @@ -145,6 +146,10 @@
        */
       protected ActionServlet servlet = null;
   
  +    /**
  +     * Matches action mapping paths against compiled wildcard patterns
  +     */
  +    protected ActionMappingMatcher matcher = null;
   
       // --------------------------------------------------------- Public Methods
   
  @@ -184,7 +189,7 @@
           
           this.servlet = servlet;
           this.moduleConfig = moduleConfig;
  -
  +        matcher = new ActionMappingMatcher(moduleConfig);
       }
   
       /**
  @@ -659,9 +664,15 @@
                                              String path)
           throws IOException {
   
  -        // Is there a directly defined mapping for this path?
  +        // Is there a directly defined or wildcard-matched mapping for this 
  +        // path?
           ActionMapping mapping = (ActionMapping)
               moduleConfig.findActionConfig(path);
  +        if (mapping == null) {
  +            mapping = matcher.match(path);
  +        }
  +
  +        // If a mapping is found, put it in the request and return it
           if (mapping != null) {
               request.setAttribute(Globals.MAPPING_KEY, mapping);
               return (mapping);
  
  
  
  1.1                  jakarta-struts/src/share/org/apache/struts/util/ActionMappingMatcher.java
  
  Index: ActionMappingMatcher.java
  ===================================================================
  /*
   *  ====================================================================
   *
   *  The Apache Software License, Version 1.1
   *
   *  Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   *  reserved.
   *
   *  Redistribution and use in source and binary forms, with or without
   *  modification, are permitted provided that the following conditions
   *  are met:
   *
   *  1. Redistributions of source code must retain the above copyright
   *  notice, this list of conditions and the following disclaimer.
   *
   *  2. Redistributions in binary form must reproduce the above copyright
   *  notice, this list of conditions and the following disclaimer in
   *  the documentation and/or other materials provided with the
   *  distribution.
   *
   *  3. The end-user documentation included with the redistribution, if
   *  any, must include the following acknowlegement:
   *  "This product includes software developed by the
   *  Apache Software Foundation (http://www.apache.org/)."
   *  Alternately, this acknowlegement may appear in the software itself,
   *  if and wherever such third-party acknowlegements normally appear.
   *
   *  4. The names "The Jakarta Project", "Struts", and "Apache Software
   *  Foundation" must not be used to endorse or promote products derived
   *  from this software without prior written permission. For written
   *  permission, please contact apache@apache.org.
   *
   *  5. Products derived from this software may not be called "Apache"
   *  nor may "Apache" appear in their names without prior written
   *  permission of the Apache Group.
   *
   *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   *  DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   *  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   *  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   *  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   *  SUCH DAMAGE.
   *  ====================================================================
   *
   *  This software consists of voluntary contributions made by many
   *  individuals on behalf of the Apache Software Foundation.  For more
   *  information on the Apache Software Foundation, please see
   *  <http://www.apache.org/>.
   *
   */
  package org.apache.struts.util;
  
  // Struts imports:
  import org.apache.struts.action.ActionMapping;
  import org.apache.struts.action.ActionForward;
  import org.apache.struts.config.ActionConfig;
  import org.apache.struts.config.ExceptionConfig;
  import org.apache.struts.config.ForwardConfig;
  import org.apache.struts.config.ModuleConfig;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import java.util.List;
  import java.util.ArrayList;
  import java.util.Map;
  import java.util.HashMap;
  import java.util.Iterator;
  
  
  /**
   *  Matches paths against pre-compiled wildcard expressions pulled from 
   *  action mappings. It uses the wildcard matcher from the Apache
   *  Cocoon project.
   *
   * @author    Don Brown
   */
  public class ActionMappingMatcher {
  
      /**  
       * The logging instance 
       */
      private static final Log log =
          LogFactory.getLog(ActionMappingMatcher.class);
      
      /**  
       * The compiled paths and their associated ActionMapping's 
       */
      private List compiledPaths;
  
      /**
       *  Finds and precompiles the wildcard patterns from the ActionMapping
       *  "path" attributes.
       *  ActionMapping's will be evaluated in the order they exist in the
       *  Struts config file. Only paths that actually contain a wildcard
       *  will be compiled.
       *
       * @param  appConfig  The ModuleConfig we are associated with
       */
      public ActionMappingMatcher(ModuleConfig appConfig) {
          compiledPaths = new ArrayList();
          ActionConfig[] configs = appConfig.findActionConfigs();
          int[] pattern;
          String path;
          for (int x = 0; x < configs.length; x++) {
              path = configs[x].getPath();
              if (path.indexOf('*') > -1) {
                  if (path.length() > 0 && path.charAt(0) == '/') {
                      path = path.substring(1);
                  }
                  if (log.isDebugEnabled()) {
                      log.debug("Compiling action mapping path '" + path + "'");
                  }    
                  pattern = WildcardHelper.compilePattern(path);
                  compiledPaths.add(new Mapping(pattern, configs[x]));
              }    
          }
      }
  
      /**
       *  Matches the path against the compiled wildcard patterns.
       *
       * @param  path             The portion of the request URI for selecting a
       *      mapping
       * @return                  The action mapping if matched, else null
       */
      public ActionMapping match(String path) {
  
          ActionMapping mapping = null;
          if (compiledPaths.size() > 0) {
              if (log.isDebugEnabled()) {
                  log.debug("Attempting to match '" + path
                      + "' to a wildcard pattern");
              }    
              if (path.length() > 0 && path.charAt(0) == '/') {
                  path = path.substring(1);
              }    
              Mapping m;
              HashMap vars = new HashMap();
              for (Iterator i = compiledPaths.iterator(); i.hasNext();) {
                  m = (Mapping) i.next();
                  if (WildcardHelper.match(vars, path, m.getPattern())) {
                      mapping = convertActionMapping(
                              path,
                              (ActionMapping) m.getActionConfig(),
                              vars);
                  }
              }
          }    
  
          return mapping;
      }
      
      /**
       *  Clones the ActionMapping and its children, replacing various properties
       *  with the values of the wildcard-matched strings.
       *
       * @param  path  The requested path
       * @param  orig  The original ActionMapping
       * @param  vars  A Map of wildcard-matched strings
       * @return       A cloned ActionMapping with appropriate properties replaced
       *      with wildcard-matched values
       */
      protected ActionMapping convertActionMapping(String path, 
              ActionMapping orig, Map vars) {
          ActionMapping mapping = new ActionMapping();
          mapping.setModuleConfig(orig.getModuleConfig());
  
          mapping.setMultipartClass(orig.getMultipartClass());
          mapping.setName(convertParam(orig.getName(), vars));
          if (path.charAt(0) != '/') {
              path = "/" + path;
          }    
          mapping.setPath(path);
          mapping.setPrefix(orig.getPrefix());
          mapping.setScope(orig.getScope());
          mapping.setSuffix(orig.getSuffix());
          mapping.setUnknown(orig.getUnknown());
          mapping.setValidate(orig.getValidate());
  
          mapping.setType(convertParam(orig.getType(), vars));
          mapping.setRoles(convertParam(orig.getRoles(), vars));
          mapping.setParameter(convertParam(orig.getParameter(), vars));
          mapping.setAttribute(convertParam(orig.getAttribute(), vars));
          mapping.setForward(convertParam(orig.getForward(), vars));
          mapping.setInclude(convertParam(orig.getInclude(), vars));
          mapping.setInput(convertParam(orig.getInput(), vars));
  
          ExceptionConfig[] exConfigs = orig.findExceptionConfigs();
          for (int x = 0; x < exConfigs.length; x++) {
              mapping.addExceptionConfig(exConfigs[x]);
          }
  
          ForwardConfig[] fConfigs = orig.findForwardConfigs();
          ForwardConfig cfg;
          for (int x = 0; x < fConfigs.length; x++) {
              cfg = new ActionForward();
              cfg.setContextRelative(fConfigs[x].getContextRelative());
              cfg.setName(fConfigs[x].getName());
              cfg.setPath(convertParam(fConfigs[x].getPath(), vars));
              mapping.addForwardConfig(cfg);
          }
          return mapping;
      }
  
      /**
       *  Inserts into a value wildcard-matched strings where specified.
       *
       * @param  val   The value to convert
       * @param  vars  A Map of wildcard-matched strings
       * @return       The new value
       */
      protected String convertParam(String val, Map vars) {
          if (val == null) {
              return null;
          } else if (val.indexOf("{") == -1) {
              return val;
          }
  
          Map.Entry entry;
          StringBuffer key = new StringBuffer("{0}");
          StringBuffer ret = new StringBuffer(val);
          int x;
          for (Iterator i = vars.entrySet().iterator(); i.hasNext();) {
              entry = (Map.Entry) i.next();
              key.setCharAt(1, ((String) entry.getKey()).charAt(0));
              x = ret.toString().indexOf(key.toString());
              if (x > -1) {
                  ret.replace(x, x + 3, (String) entry.getValue());
              }
          }
          return ret.toString();
      }
  
      /**
       *  Stores a compiled wildcard pattern and the ActionConfig it came from
       */
      private class Mapping {
  
          /**  The compiled pattern */
          private int[] pattern;
  
          /**  The original ActionConfig */
          private ActionConfig config;
  
          /**
           *  Contructs a read-only Mapping instance
           *
           *  @param pattern  The compiled pattern
           *  @param config   The original ActionConfig
           */
          public Mapping(int[] pattern, ActionConfig config) {
              this.pattern = pattern;
              this.config = config;
          }    
  
          /**
           *  Gets the compiled wildcard pattern
           *
           *  @return The compiled pattern
           */
          public int[] getPattern() {
              return this.pattern;
          }
  
          /**
           *  Gets the ActionConfig that contains the pattern
           *
           *  @return The associated ActionConfig
           */
          public ActionConfig getActionConfig() {
              return this.config;
          }    
      }    
  }
  
  
  
  
  1.1                  jakarta-struts/src/share/org/apache/struts/util/WildcardHelper.java
  
  Index: WildcardHelper.java
  ===================================================================
  /*
   *  ====================================================================
   *
   *  The Apache Software License, Version 1.1
   *
   *  Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   *  reserved.
   *
   *  Redistribution and use in source and binary forms, with or without
   *  modification, are permitted provided that the following conditions
   *  are met:
   *
   *  1. Redistributions of source code must retain the above copyright
   *  notice, this list of conditions and the following disclaimer.
   *
   *  2. Redistributions in binary form must reproduce the above copyright
   *  notice, this list of conditions and the following disclaimer in
   *  the documentation and/or other materials provided with the
   *  distribution.
   *
   *  3. The end-user documentation included with the redistribution, if
   *  any, must include the following acknowlegement:
   *  "This product includes software developed by the
   *  Apache Software Foundation (http://www.apache.org/)."
   *  Alternately, this acknowlegement may appear in the software itself,
   *  if and wherever such third-party acknowlegements normally appear.
   *
   *  4. The names "The Jakarta Project", "Struts", and "Apache Software
   *  Foundation" must not be used to endorse or promote products derived
   *  from this software without prior written permission. For written
   *  permission, please contact apache@apache.org.
   *
   *  5. Products derived from this software may not be called "Apache"
   *  nor may "Apache" appear in their names without prior written
   *  permission of the Apache Group.
   *
   *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   *  DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   *  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   *  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   *  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   *  SUCH DAMAGE.
   *  ====================================================================
   *
   *  This software consists of voluntary contributions made by many
   *  individuals on behalf of the Apache Software Foundation.  For more
   *  information on the Apache Software Foundation, please see
   *  <http://www.apache.org/>.
   *
   */
  package org.apache.struts.util;
  
  // java util imports:
  import java.util.HashMap;
  
  
  /**
   * This class is an utility class that perform wilcard-patterns matching and
   * isolation taken from Apache Cocoon.
   *
   * @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>
   * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
   * @version CVS $Id: WildcardHelper.java,v 1.1 2003/09/29 01:24:21 mrdon Exp $
   */
  public class WildcardHelper {
  
      /** 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;
  
  
      /**
       * Translate the given <code>String</code> into a <code>int []</code>
       * representing the pattern matchable by this class.
       * <br>
       * This function translates a <code>String</code> into an int array
       * converting the special '*' and '\' characters.
       * <br>
       * Here is how the conversion algorithm works:
       * <ul>
       *   <li>The '*' character is converted to MATCH_FILE, meaning that zero
       *        or more characters (excluding the path separator '/') are to
       *        be matched.</li>
       *   <li>The '**' sequence is converted to MATCH_PATH, meaning that zero
       *       or more characters (including the path separator '/') are to
       *        be matched.</li>
       *   <li>The '\' character is used as an escape sequence ('\*' is
       *       translated in '*', not in MATCH_FILE). If an exact '\' character
       *       is to be matched the source string must contain a '\\'.
       *       sequence.</li>
       * </ul>
       * When more than two '*' characters, not separated by another character,
       * are found their value is considered as '**' (MATCH_PATH).
       * <br>
       * The array is always terminated by a special value (MATCH_END).
       * <br>
       * All MATCH* values are less than zero, while normal characters are equal
       * or greater.
       *
       * @param data The string to translate.
       * @return The encoded string as an int array, terminated by the MATCH_END
       *         value (don't consider the array length).
       * @exception NullPointerException If data is null.
       */
      public static int[] compilePattern(String data)
      throws NullPointerException {
  
          // Prepare the arrays
          int expr[] = new int[data.length() + 2];
          char buff[] = data.toCharArray();
  
          // Prepare variables for the translation loop
          int y = 0;
          boolean slash = false;
  
          // Must start from beginning
          expr[y++] = MATCH_BEGIN;
  
          if (buff.length > 0) {
              if (buff[0] == '\\') {
                  slash = true;
              } else if (buff[0] == '*') {
                  expr[y++] = MATCH_FILE;
              }  else {
                  expr[y++] = buff[0];
              }
  
              // Main translation loop
              for (int x = 1; x < buff.length; x++) {
                  // If the previous char was '\' simply copy this char.
                  if (slash) {
                      expr[y++] = buff[x];
                      slash = false;
                  // If the previous char was not '\' we have to do a bunch of 
                  // checks
                  } else {
                      // If this char is '\' declare that and continue
                      if (buff[x] == '\\') {
                          slash = true;
                      // If this char is '*' check the previous one
                      } else if (buff[x] == '*') {
                          // If the previous character als was '*' match a path
                          if (expr[y - 1] <= MATCH_FILE) {
                              expr[y - 1] = MATCH_PATH;
                          } else {
                              expr[y++] = MATCH_FILE;
                          }
                      } else {
                          expr[y++] = buff[x];
                      }
                  }
              }
          }
  
          // Must match end at the end
          expr[y] = MATCH_THEEND;
          return expr;
      }
  
      /**
       * Match a pattern agains a string and isolates wildcard replacement into a
       * <code>Stack</code>.
       *
       * @param map  The map to store matched values
       * @param data The string to match
       * @param expr The compiled wildcard expression
       * @return True if a match
       * @throws NullPointerException If any parameters are null
       */
      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 rend The index of the last 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);
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org


Re: cvs commit: jakarta-struts/src/share/org/apache/struts/util ActionMappingMatcher.java WildcardHelper.java

Posted by Don Brown <mr...@twdata.org>.
Good point, I'll change it when I put in the unit tests I'm working on.

Don

On Sun, 28 Sep 2003, Robert Leland wrote:

> mrdon@apache.org wrote:
>
> >mrdon       2003/09/28 18:24:21
> >
> >
> >  Added:       src/share/org/apache/struts/util ActionMappingMatcher.java
> >WildcardHelper.java
> >
>
> Wouldnt this be better placed in the action package ?
> Would any other package other than action ever use these ?
> If not then these classes could have package scope access.
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: struts-dev-help@jakarta.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org


Re: cvs commit: jakarta-struts/src/share/org/apache/struts/util ActionMappingMatcher.java WildcardHelper.java

Posted by Robert Leland <rl...@apache.org>.
mrdon@apache.org wrote:

>mrdon       2003/09/28 18:24:21
>
>
>  Added:       src/share/org/apache/struts/util ActionMappingMatcher.java 
>WildcardHelper.java
>

Wouldnt this be better placed in the action package ?
Would any other package other than action ever use these ?
If not then these classes could have package scope access.




---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org