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;