You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by cz...@apache.org on 2006/06/23 11:22:50 UTC

svn commit: r416650 - in /cocoon/trunk: blocks/cocoon-portal/cocoon-portal-impl/src/main/java/org/apache/cocoon/portal/tools/service/ blocks/cocoon-scratchpad/cocoon-scratchpad-impl/src/main/java/org/apache/cocoon/components/flow/javascript/fom/ core/c...

Author: cziegeler
Date: Fri Jun 23 02:22:48 2006
New Revision: 416650

URL: http://svn.apache.org/viewvc?rev=416650&view=rev
Log:
Switching to new wildcard matching

Added:
    cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/WildcardMatcherHelper.java   (with props)
Removed:
    cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/WildcardHelper.java
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/util/WildcardHelper.java
Modified:
    cocoon/trunk/blocks/cocoon-portal/cocoon-portal-impl/src/main/java/org/apache/cocoon/portal/tools/service/UserRightsService.java
    cocoon/trunk/blocks/cocoon-scratchpad/cocoon-scratchpad-impl/src/main/java/org/apache/cocoon/components/flow/javascript/fom/JavaScriptAspectWeaver.java
    cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/DefaultClassLoader.java
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/bean/CocoonBean.java
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/CoreUtil.java
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/ConfigReader.java
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/matching/AbstractWildcardMatcher.java
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/matching/helpers/WildcardHelper.java
    cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/util/test/WildcardHelperTestCase.java

Modified: cocoon/trunk/blocks/cocoon-portal/cocoon-portal-impl/src/main/java/org/apache/cocoon/portal/tools/service/UserRightsService.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/blocks/cocoon-portal/cocoon-portal-impl/src/main/java/org/apache/cocoon/portal/tools/service/UserRightsService.java?rev=416650&r1=416649&r2=416650&view=diff
==============================================================================
--- cocoon/trunk/blocks/cocoon-portal/cocoon-portal-impl/src/main/java/org/apache/cocoon/portal/tools/service/UserRightsService.java (original)
+++ cocoon/trunk/blocks/cocoon-portal/cocoon-portal-impl/src/main/java/org/apache/cocoon/portal/tools/service/UserRightsService.java Fri Jun 23 02:22:48 2006
@@ -26,7 +26,7 @@
 import org.apache.cocoon.portal.tools.helper.MultipleRoleMatcher;
 import org.apache.cocoon.portal.tools.helper.RoleMatcher;
 import org.apache.cocoon.portal.tools.helper.SingleRoleMatcher;
-import org.apache.cocoon.util.WildcardHelper;
+import org.apache.cocoon.util.WildcardMatcherHelper;
 import org.apache.excalibur.source.Source;
 
 /**
@@ -135,15 +135,13 @@
 
         // Iterate all userrights
         Iterator iterator = this.userrights.entrySet().iterator();
-        Map.Entry entry;
-        int[] pattern;
         RoleMatcher[] matcher;
         while (iterator.hasNext() && isAllowed) {
-            entry = (Map.Entry)iterator.next();
-            pattern = (int[])entry.getKey();
+            final Map.Entry entry = (Map.Entry)iterator.next();
+            final String pattern = (String)entry.getKey();
 
             // If userright matches try to find a matching role
-            if (WildcardHelper.match(new HashMap(), url, pattern)) {
+            if (WildcardMatcherHelper.match(pattern, url) != null) {
                 matcher = (RoleMatcher[])entry.getValue();
 
                 isAllowed = false;
@@ -167,15 +165,13 @@
 
         // Iterate all userrights
         Iterator iterator = this.userrights.entrySet().iterator();
-        Map.Entry entry;
-        int[] pattern;
         RoleMatcher[] matcher;
         while (iterator.hasNext() && isAllowed) {
-            entry = (Map.Entry)iterator.next();
-            pattern = (int[])entry.getKey();
+            final Map.Entry entry = (Map.Entry)iterator.next();
+            final String pattern = (String)entry.getKey();
 
             // If userright matches try to find a matching role
-            if (WildcardHelper.match(new HashMap(), id, pattern)) {
+            if (WildcardMatcherHelper.match(pattern, id) != null) {
                 matcher = (RoleMatcher[])entry.getValue();
 
                 isAllowed = false;
@@ -202,7 +198,7 @@
         while (iterator.hasNext()) {
             entry = (Map.Entry)iterator.next();
             userrights.put(
-                WildcardHelper.compilePattern((String)entry.getKey()),
+                entry.getKey(),
                 this.buildRoles((String)entry.getValue()));
         }
 

Modified: cocoon/trunk/blocks/cocoon-scratchpad/cocoon-scratchpad-impl/src/main/java/org/apache/cocoon/components/flow/javascript/fom/JavaScriptAspectWeaver.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/blocks/cocoon-scratchpad/cocoon-scratchpad-impl/src/main/java/org/apache/cocoon/components/flow/javascript/fom/JavaScriptAspectWeaver.java?rev=416650&r1=416649&r2=416650&view=diff
==============================================================================
--- cocoon/trunk/blocks/cocoon-scratchpad/cocoon-scratchpad-impl/src/main/java/org/apache/cocoon/components/flow/javascript/fom/JavaScriptAspectWeaver.java (original)
+++ cocoon/trunk/blocks/cocoon-scratchpad/cocoon-scratchpad-impl/src/main/java/org/apache/cocoon/components/flow/javascript/fom/JavaScriptAspectWeaver.java Fri Jun 23 02:22:48 2006
@@ -37,7 +37,7 @@
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.Serviceable;
-import org.apache.cocoon.util.WildcardHelper;
+import org.apache.cocoon.matching.helpers.WildcardHelper;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
 

Modified: cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/DefaultClassLoader.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/DefaultClassLoader.java?rev=416650&r1=416649&r2=416650&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/DefaultClassLoader.java (original)
+++ cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/DefaultClassLoader.java Fri Jun 23 02:22:48 2006
@@ -33,8 +33,8 @@
  */
 public class DefaultClassLoader extends URLClassLoader {
 
-    protected final int[][] includes;
-    protected final int[][] excludes;
+    protected final List includes;
+    protected final List excludes;
 
     /**
      * Alternate constructor to define a parent and initial <code>URL</code>
@@ -50,21 +50,8 @@
      */
     public DefaultClassLoader(final URL[] urls, List includePatterns, List excludePatterns, ClassLoader parent, URLStreamHandlerFactory factory) {
         super(urls, parent, factory);
-        this.includes = compilePatterns(includePatterns);
-        this.excludes = compilePatterns(excludePatterns);
-    }
-
-    private int[][] compilePatterns(List patternConfigs) {
-        if (patternConfigs.size() == 0) {
-            return null;
-        }
-        final int[][] patterns = new int[patternConfigs.size()][];
-
-        for (int i = 0; i < patternConfigs.size(); i++) {
-            patterns[i] = WildcardHelper.compilePattern((String)patternConfigs.get(i));
-        }
-
-        return patterns;
+        this.includes = includePatterns;
+        this.excludes = excludePatterns;
     }
 
     protected boolean tryClassHere(String name) {
@@ -81,8 +68,8 @@
         } else {
             // See if it matches include patterns
             tryHere = false;
-            for (int i = 0; i < this.includes.length; i++) {
-                if (WildcardHelper.match(null, name, includes[i])) {
+            for (int i = 0; i < this.includes.size(); i++) {
+                if (WildcardMatcherHelper.match((String)includes.get(i), name) != null) {
                     tryHere = true;
                     break;
                 }
@@ -91,8 +78,8 @@
         
         // Go through the exclusion list
         if (tryHere && excludes != null) {
-            for (int i = 0; i < this.excludes.length; i++) {
-                if (WildcardHelper.match(null, name, excludes[i])) {
+            for (int i = 0; i < this.excludes.size(); i++) {
+                if (WildcardMatcherHelper.match((String)excludes.get(i), name) != null) {
                     tryHere = false;
                     break;
                 }

Added: cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/WildcardMatcherHelper.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/WildcardMatcherHelper.java?rev=416650&view=auto
==============================================================================
--- cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/WildcardMatcherHelper.java (added)
+++ cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/WildcardMatcherHelper.java Fri Jun 23 02:22:48 2006
@@ -0,0 +1,349 @@
+/*
+ * Copyright 1999-2006 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.classloader;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * This class is an utility class that perform wilcard-patterns matching and isolation.
+ *
+ * @version $Id$
+ */
+public class WildcardMatcherHelper {
+    //~ Static fields/initializers -----------------------------------------------------------------
+
+    /** Default path separator: "/" */
+    public static final char ESC = '\\';
+
+    /** Default path separator: "/" */
+    public static final char PATHSEP = '/';
+
+    /** Default path separator: "/" */
+    public static final char STAR = '*';
+
+    //~ Methods ------------------------------------------------------------------------------------
+
+    /**
+     * Match a pattern agains a string and isolates wildcard replacement into a <code>Map</code>.
+     * <br>
+     * Here is how the matching algorithm works:
+     *
+     * <ul>
+     *   <li>
+     *     The '*' character, meaning that zero or more characters (excluding the path separator '/')
+     *     are to be matched.
+     *   </li>
+     *   <li>
+     *     The '**' sequence, meaning that zero or more characters (including the path separator '/')
+     *     are to be matched.
+     *   </li>
+     *   <li>
+     *     The '\*' sequence is honored as a litteral '*' character, not a wildcard
+     *   </li>
+     * </ul>
+     *
+     * When more than two '*' characters, not separated by another character, are found their value is
+     * considered as '**'.
+     *
+     * @param pat The pattern string.
+     * @param str The string to math agains the pattern
+     *
+     * @return a <code>Map</code> containing the representation of the extracted pattern. The extracted patterns are
+     *         keys in the <code>Map</code> from left to right beginning with "1" for te left most, "2" for the next,
+     *         a.s.o. The key "0" is the string itself. If the return value is null, string does not match to the
+     *         pattern .
+     */
+    public static Map match(final String pat,
+                            final String str) {
+        final Matcher map = new Matcher(pat, str);
+
+        if(map.isMatch()) {
+            return map.getMap();
+        }
+
+        return null;
+    }
+
+    //~ Inner Classes ------------------------------------------------------------------------------
+
+    /**
+     * The private matcher class
+     */
+    private static class Matcher {
+        //~ Instance fields ------------------------------------------------------------------------
+
+        /** The character array of the pattern */
+        private final char[] apat;
+
+        /** The length of the character array of the pattern */
+        private final int lpat;
+
+        /** The character array of the string */
+        private final char[] astr;
+
+        /** The length of the character array of the string */
+        private final int lstr;
+
+        /** The <code>Map</code> to be filled */
+        private Map map = new HashMap();
+
+        /** Whether string matched to pattern */
+        private final boolean matched;
+
+        /** map index */
+        private int idx = 0;
+
+        /** index into pattern */
+        private int ipat = 0;
+
+        /** index into string */
+        private int istr = 0;
+
+        //~ Constructors ---------------------------------------------------------------------------
+
+        /**
+         * Creates a new Matcher object.
+         *
+         * @param pat The pattern
+         * @param str The string
+         */
+        public Matcher(final String pat,
+                       final String str) {
+            apat = pat.toCharArray();
+            lpat = apat.length;
+            astr = str.toCharArray();
+            lstr = astr.length;
+            add(str);
+            matched = match();
+        }
+
+        //~ Methods --------------------------------------------------------------------------------
+
+        /**
+         * DOCUMENT ME!
+         *
+         * @return DOCUMENT ME!
+         */
+        public Map getMap() {
+            return map;
+        }
+
+        /**
+         * Has it matched?
+         *
+         * @return whether it has matched
+         */
+        public boolean isMatch() {
+            return matched;
+        }
+
+        /**
+         * Add a extracted substring to the map
+         *
+         * @param aStr The extracted substring
+         */
+        private void add(final String aStr) {
+            map.put(String.valueOf(idx++), aStr);
+        }
+
+        /**
+         * Scans the pattern and the search string from the end toward the start
+         *
+         * @return wether the pstring matches the pattern
+         */
+        private boolean match() {
+            // scan a common literal suffix
+            scanLiteralPrefix();
+
+            // if we are already at the end of both strings 
+            // than the pattern matched
+            if(ipat >= lpat && istr >= lstr) return true;
+
+            // if hole string has matched the pattern so far and the rest of the pattern only has wildcard(s)
+            // we match too otherwise we clearly don't match
+            if(ipat < lpat && istr >= lstr) {
+                while(ipat < lpat && apat[ipat] == STAR) ipat++;
+
+                if(ipat >= lpat) {
+                    add("");
+
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+
+            // if hole pattern has matched the string so far but the string has more characters left
+            // we don't match
+            if(ipat >= lpat && istr < lstr) return false;
+
+            // if we have not stopped at a wildcard character 
+            // a character doesn't match and thus we do not match at all
+            if(apat[ipat] != STAR) return false;
+
+            // if it is a double (or more) wildcard pattern
+            if(ipat < lpat - 1 && apat[ipat + 1] == STAR) {
+                // skip to first non star charater in the pattern
+                while(++ipat < lpat && apat[ipat] == STAR);
+
+                // if we are at the end of the pattern we've matched and are finish scanning
+                if(ipat >= lpat) {
+                    add(new String(astr, istr, lstr - istr));
+
+                    return true;
+                }
+
+                // Now we need to scan for the end of the literal characters in the pattern
+                final int sipat = ipat; // start position of a literal character used for substring operations
+
+                while(ipat < lpat && (apat[ipat] != STAR || (ipat > 0 && apat[ipat - 1] == ESC))) ipat++;
+
+                // if we reached the end of the pattern just do a string compare with the corresponding part from 
+                // the end of the string
+                if(ipat >= lpat) {
+                    // if the remaining length of the string isn't the same as that found in the pattern 
+                    // we do not match
+                    if(strncmp(apat, sipat, astr, lstr - (lpat - sipat), lpat - sipat)) {
+                        add(new String(astr, istr, lstr - (lpat - sipat) - istr));
+
+                        return true;
+                    }
+
+                    // otherwise we do not match
+                    return false;
+                }
+
+                // Now we need to check whether the litteral substring of the pattern 
+                // is contained in the string somewhere
+                final int l = ipat - sipat;
+                final int sistr = istr;
+
+                while(istr < lstr && ! strncmp(apat, sipat, astr, istr, l)) istr++;
+
+                if(istr >= lstr) return false;
+
+                add(new String(astr, sistr, istr - sistr));
+                istr += l;
+            } else // if it is a single star pattern
+             {
+                // skip the star
+                ++ipat;
+
+                // if we are at the beginning of the pattern we have to check there is not PATH_SEP in string
+                if(ipat >= lpat) {
+                    final int sistr = istr;
+
+                    while(istr < lstr && (astr[istr] != PATHSEP)) istr++;
+
+                    if(istr >= lstr) {
+                        add(new String(astr, sistr, lstr - sistr));
+
+                        return true;
+                    }
+
+                    // otherwise we do not match
+                    return false;
+                }
+
+                // Now we need to search for the start of either a path sparator or another wildcard characters 
+                // in the pattern
+                final int sipat = ipat;
+
+                while(ipat < lpat &&
+                      apat[ipat] != STAR &&
+                      (apat[ipat] != ESC || ipat < lpat - 1 && apat[ipat + 1] != STAR) &&
+                      apat[ipat] != PATHSEP) {
+                    ipat++;
+                }
+
+                // if we reached the end of the pattern just do a String compare with the corresponding part from 
+                // the end of the string
+                if(ipat >= lpat) {
+                    if(strncmp(apat, sipat, astr, lstr - (ipat - sipat), ipat - sipat)) {
+                        add(new String(astr, istr, lstr - (ipat - sipat) - istr)); // TODO: this is wrong
+
+                        return true;
+                    }
+
+                    // otherwise we do not match
+                    return false;
+                }
+
+                // Now we need to check whether the litteral substring of the pattern 
+                // is contained in the string somewhere
+                if(apat[ipat] != PATHSEP) {
+                    ipat--;
+                }
+
+                final int l = ipat- sipat + 1;
+                final int sistr = istr;
+
+                while(istr < lstr && ! strncmp(apat, sipat, astr, istr, l)) istr++;
+
+                if(istr >= lstr) return false;
+
+                add(new String(astr, sistr, istr - sistr));
+                ipat += l;
+                istr += l;
+            }
+
+            return match();
+        }
+
+        /**
+         * Scan a possible common suffix
+         */
+        private void scanLiteralPrefix() {
+            // scan a common literal suffix
+            while(ipat < lpat &&
+                  istr < lstr &&
+                  (apat[ipat] == ESC && ipat < lpat - 1 && apat[ipat + 1] == STAR && apat[++ipat] == astr[istr] ||
+                   apat[ipat] != STAR &&
+                   apat[ipat] == astr[istr])) {
+                ipat++;
+                istr++;
+            }
+        }
+
+        /**
+         * Compare two charater array from  individual offsets
+         *
+         * @param a1 The first character array
+         * @param o1 The offset into the first character array
+         * @param a2 The second character array
+         * @param o2 The offset into the second character array
+         * @param l The length to compare
+         *
+         * @return Whether the all the mentioned characters match each other
+         */
+        private boolean strncmp(final char[] a1,
+                                final int o1,
+                                final char[] a2,
+                                final int o2,
+                                final int l) {
+            if ( o2 < 0 ) {
+                return false;
+            }
+            int i = 0;
+
+            for(i = 0; i < l && o1 + i < a1.length && o2 + i < a2.length && a1[o1 + i] == a2[o2 + i]; i++);
+
+            return i == l;
+        }
+    }
+}

Propchange: cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/WildcardMatcherHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/core/cocoon-bootstrap/src/main/java/org/apache/cocoon/classloader/WildcardMatcherHelper.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/bean/CocoonBean.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/bean/CocoonBean.java?rev=416650&r1=416649&r2=416650&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/bean/CocoonBean.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/bean/CocoonBean.java Fri Jun 23 02:22:48 2006
@@ -23,7 +23,7 @@
 import org.apache.cocoon.components.notification.Notifier;
 import org.apache.cocoon.components.notification.DefaultNotifyingBuilder;
 import org.apache.cocoon.components.notification.Notifying;
-import org.apache.cocoon.util.WildcardHelper;
+import org.apache.cocoon.util.WildcardMatcherHelper;
 import org.apache.commons.lang.SystemUtils;
 
 import org.apache.excalibur.source.ModifiableSource;
@@ -234,13 +234,11 @@
     }
     
     public void addExcludePattern(String pattern) {
-        int preparedPattern[] = WildcardHelper.compilePattern(pattern);
-        excludePatterns.add(preparedPattern);
+        excludePatterns.add(pattern);
     }
 
     public void addIncludePattern(String pattern) {
-        int preparedPattern[] = WildcardHelper.compilePattern(pattern);
-        includePatterns.add(preparedPattern);
+        includePatterns.add(pattern);
     }
 
     public void addIncludeLinkExtension(String extension) {
@@ -636,7 +634,6 @@
     private boolean isIncluded(String uri) {
         boolean included;
         Iterator i;
-        HashMap map = new HashMap();
 
         if (includePatterns.size() == 0) {
             included = true;
@@ -644,8 +641,8 @@
             included = false;
             i = includePatterns.iterator();
             while (i.hasNext()){
-                int pattern[] = (int[])i.next();
-                if (WildcardHelper.match(map, uri, pattern)) {
+                final String pattern = (String)i.next();
+                if (WildcardMatcherHelper.match(pattern, uri) != null) {
                     included=true;
                     break;
                 }
@@ -654,8 +651,8 @@
         if (excludePatterns.size() != 0) {
             i = excludePatterns.iterator();
             while (i.hasNext()) {
-                int pattern[] = (int[])i.next();
-                if (WildcardHelper.match(map, uri, pattern)) {
+                final String pattern = (String)i.next();
+                if (WildcardMatcherHelper.match(pattern, uri) != null) {
                     included=false;
                     break;
                 }

Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/CoreUtil.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/CoreUtil.java?rev=416650&r1=416649&r2=416650&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/CoreUtil.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/CoreUtil.java Fri Jun 23 02:22:48 2006
@@ -713,16 +713,14 @@
 
     /**
      * @param environmentContext
-     * @return
      */
     public static String getWritableContextPath(ServletContext environmentContext) {
         return environmentContext.getRealPath("/");
     }
 
     /**
+     * @param environmentContext 
      * @param knownFile 
-     * @param context 
-     * @return
      */
     public static String getContextUrl(ServletContext environmentContext, String knownFile) {
         String servletContextURL;

Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/ConfigReader.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/ConfigReader.java?rev=416650&r1=416649&r2=416650&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/ConfigReader.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/ConfigReader.java Fri Jun 23 02:22:48 2006
@@ -30,7 +30,7 @@
 import org.apache.cocoon.components.source.SourceUtil;
 import org.apache.cocoon.core.container.util.ConfigurationBuilder;
 import org.apache.cocoon.core.container.util.SimpleSourceResolver;
-import org.apache.cocoon.util.WildcardHelper;
+import org.apache.cocoon.util.WildcardMatcherHelper;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
 import org.apache.excalibur.source.TraversableSource;
@@ -310,10 +310,6 @@
             
         } else {
             final String pattern = includeStatement.getAttribute("pattern", null);
-            int[] parsedPattern = null;
-            if ( pattern != null ) {
-                parsedPattern = WildcardHelper.compilePattern(pattern);
-            }
             Source directory = null;
             try {
                 directory = this.resolver.resolveURI(directoryURI, contextURI, CONTEXT_PARAMETERS);
@@ -322,7 +318,7 @@
                     while ( children.hasNext() ) {
                         final Source s = (Source)children.next();
                         try {
-                            if ( parsedPattern == null || this.match(s.getURI(), parsedPattern)) {
+                            if ( pattern == null || this.match(s.getURI(), pattern)) {
                                 this.loadURI(s, loadedURIs, includeStatement);
                             }
                         } finally {
@@ -376,12 +372,12 @@
         }
     }
 
-    private boolean match(String uri, int[] parsedPattern ) {
+    private boolean match(String uri, String pattern ) {
         int pos = uri.lastIndexOf('/');
         if ( pos != -1 ) {
             uri = uri.substring(pos+1);
         }
-        return WildcardHelper.match(null, uri, parsedPattern);      
+        return (WildcardMatcherHelper.match(pattern, uri) != null);      
     }
 
     protected void handleBeanInclude(final String contextURI,
@@ -414,10 +410,6 @@
 
         } else {
             final String pattern = includeStatement.getAttribute("pattern", null);
-            int[] parsedPattern = null;
-            if (pattern != null) {
-                parsedPattern = WildcardHelper.compilePattern(pattern);
-            }
             Source directory = null;
             try {
                 directory = this.resolver.resolveURI(directoryURI, contextURI, CONTEXT_PARAMETERS);
@@ -427,7 +419,7 @@
                     while (children.hasNext()) {
                         final Source s = (Source) children.next();
                         try {
-                            if (parsedPattern == null || this.match(s.getURI(), parsedPattern)) {
+                            if (pattern == null || this.match(s.getURI(), pattern)) {
                                 this.configInfo.addImport(s.getURI());
                             }
                         } finally {

Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/matching/AbstractWildcardMatcher.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/matching/AbstractWildcardMatcher.java?rev=416650&r1=416649&r2=416650&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/matching/AbstractWildcardMatcher.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/matching/AbstractWildcardMatcher.java Fri Jun 23 02:22:48 2006
@@ -15,13 +15,13 @@
  */
 package org.apache.cocoon.matching;
 
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.avalon.framework.thread.ThreadSafe;
 import org.apache.cocoon.sitemap.PatternException;
 import org.apache.cocoon.sitemap.SitemapParameters;
-import org.apache.cocoon.util.WildcardHelper;
+import org.apache.cocoon.util.WildcardMatcherHelper;
 
-import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -30,39 +30,27 @@
  * @version $Id$
  */
 
-public abstract class AbstractWildcardMatcher extends AbstractPreparableMatcher implements ThreadSafe {
-
-    /**
-     * Compile the pattern in an <code>int[]</code>.
-     */
-    public Object preparePattern(String pattern) {
-        // if pattern is null, return null to allow throwing a located exception in preparedMatch()
-        return pattern == null ? null : WildcardHelper.compilePattern(pattern);
-    }
+public abstract class AbstractWildcardMatcher
+    extends AbstractLogEnabled
+    implements Matcher, ThreadSafe {
 
     /**
      * Match the prepared pattern against the result of {@link #getMatchString(Map, Parameters)}.
+     * @see org.apache.cocoon.matching.AbstractPreparableMatcher#match(java.lang.String, java.util.Map, org.apache.avalon.framework.parameters.Parameters)
      */
-    public Map preparedMatch(Object preparedPattern, Map objectModel, Parameters parameters) throws PatternException {
-
-        if(preparedPattern == null) {
+    public Map match(String pattern, Map objectModel, Parameters parameters) throws PatternException {
+        if (pattern == null) {
             throw new PatternException("A pattern is needed at " +
                     SitemapParameters.getLocation(parameters));
         }
 
-        String match = getMatchString(objectModel, parameters);
+        final String match = this.getMatchString(objectModel, parameters);
 
         if (match == null) {
             return null;
         }
 
-        HashMap map = new HashMap();
-
-        if (WildcardHelper.match(map, match, (int[])preparedPattern)) {
-            return map;
-        } else {
-            return null;
-        }
+        return WildcardMatcherHelper.match(pattern, match);
     }
 
     /**

Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/matching/helpers/WildcardHelper.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/matching/helpers/WildcardHelper.java?rev=416650&r1=416649&r2=416650&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/matching/helpers/WildcardHelper.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/matching/helpers/WildcardHelper.java Fri Jun 23 02:22:48 2006
@@ -1,12 +1,12 @@
 /*
  * Copyright 1999-2005 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.
@@ -20,24 +20,378 @@
 /**
  * This class is an utility class that perform wilcard-patterns matching and
  * isolation.
- * @deprecated This class has moved to the o.a.c.util package.
+ *
+ * @deprecated Use the {@link org.apache.cocoon.util.WildcardMatcherHelper} instead.
  * @version $Id$
  */
 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_END = -5;
+
     /**
-     * @see org.apache.cocoon.util.WildcardHelper#compilePattern(String)
+     * 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 {
-        return org.apache.cocoon.util.WildcardHelper.compilePattern(data);
+
+        // 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_END;
+        return expr;
     }
 
     /**
-     * @see org.apache.cocoon.util.WildcardHelper#match(Map, String, int[])
+     * match a pattern agains a string and isolates wildcard replacement into a
+     * <code>Stack</code>.
      */
-    public static boolean match(Map map, String data, int[] expr) 
+    public static boolean match (Map map, String data, int[] expr) 
     throws NullPointerException {
-        return org.apache.cocoon.util.WildcardHelper.match(map, data, expr);
+        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 offset = -1;
+
+        // The matching count
+        int mcount = 0;
+
+        if ( map != null ) {
+            // 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;
+                }
+            }
+
+            // This code can never be reached, so it's commented out now!
+            // 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 ( buffpos != buff.length && buff[charpos] == '/') {
+                    return false;
+                }
+                // Check that we reached buffer's end
+                // if not, we'll search again!
+                if ( buffpos != buff.length ) {
+                    int startpos = buffpos - (charpos - exprpos);
+                    while ( buffpos != buff.length ) {
+                        if ( exprpos == charpos ) {
+                            return false;
+                        }
+                        buffpos -= (charpos - exprpos);
+                        buffpos++;
+                        offset = indexOfArray (expr, exprpos, charpos, buff, buffpos);
+                        if (offset < 0) {
+                            return false;
+                        }
+                        buffpos = offset + (charpos - exprpos);    
+                    }
+                    // replace value in result map
+                    if (map != null ) {
+                        String oldValue = (String)map.get(Integer.toString(mcount));
+                        map.put (Integer.toString(mcount), oldValue + new String(buff, startpos, offset - startpos));
+                    }
+                }
+                return true;
+            }
+
+            // 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
+            int rsltpos = 0;
+            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++];
+                }
+            }
+
+            if ( map != null ) {
+                map.put(Integer.toString(++mcount),new String (rslt, 0, rsltpos));
+            }
+        }
+    }
+
+    /**
+      * 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);
     }
 }

Modified: cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/util/test/WildcardHelperTestCase.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/util/test/WildcardHelperTestCase.java?rev=416650&r1=416649&r2=416650&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/util/test/WildcardHelperTestCase.java (original)
+++ cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/util/test/WildcardHelperTestCase.java Fri Jun 23 02:22:48 2006
@@ -18,7 +18,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.cocoon.util.WildcardHelper;
+import org.apache.cocoon.matching.helpers.WildcardHelper;
 
 import junit.framework.TestCase;