You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by jv...@apache.org on 2006/04/18 15:59:34 UTC

svn commit: r394946 [3/4] - in /maven/components/trunk/maven-core-it-verifier/src/main/java/org: apache/maven/it/ codehaus/plexus/util/

Added: maven/components/trunk/maven-core-it-verifier/src/main/java/org/codehaus/plexus/util/SelectorUtils.java
URL: http://svn.apache.org/viewcvs/maven/components/trunk/maven-core-it-verifier/src/main/java/org/codehaus/plexus/util/SelectorUtils.java?rev=394946&view=auto
==============================================================================
--- maven/components/trunk/maven-core-it-verifier/src/main/java/org/codehaus/plexus/util/SelectorUtils.java (added)
+++ maven/components/trunk/maven-core-it-verifier/src/main/java/org/codehaus/plexus/util/SelectorUtils.java Tue Apr 18 06:59:22 2006
@@ -0,0 +1,672 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 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.codehaus.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "Ant" 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 codehaus@codehaus.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.codehaus.org/>.
+ */
+
+package org.codehaus.plexus.util;
+
+import java.io.File;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * <p>This is a utility class used by selectors and DirectoryScanner. The
+ * functionality more properly belongs just to selectors, but unfortunately
+ * DirectoryScanner exposed these as protected methods. Thus we have to
+ * support any subclasses of DirectoryScanner that may access these methods.
+ * </p>
+ * <p>This is a Singleton.</p>
+ *
+ * @author Arnout J. Kuiper
+ * <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
+ * @author Magesh Umasankar
+ * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
+ * @since 1.5
+ */
+public final class SelectorUtils
+{
+
+    private static SelectorUtils instance = new SelectorUtils();
+
+    /**
+     * Private Constructor
+     */
+    private SelectorUtils()
+    {
+    }
+
+    /**
+     * Retrieves the manager of the Singleton.
+     */
+    public static SelectorUtils getInstance()
+    {
+        return instance;
+    }
+
+    /**
+     * Tests whether or not a given path matches the start of a given
+     * pattern up to the first "**".
+     * <p>
+     * This is not a general purpose test and should only be used if you
+     * can live with false positives. For example, <code>pattern=**\a</code>
+     * and <code>str=b</code> will yield <code>true</code>.
+     *
+     * @param pattern The pattern to match against. Must not be
+     *                <code>null</code>.
+     * @param str     The path to match, as a String. Must not be
+     *                <code>null</code>.
+     *
+     * @return whether or not a given path matches the start of a given
+     * pattern up to the first "**".
+     */
+    public static boolean matchPatternStart( String pattern, String str )
+    {
+        return matchPatternStart( pattern, str, true );
+    }
+
+    /**
+     * Tests whether or not a given path matches the start of a given
+     * pattern up to the first "**".
+     * <p>
+     * This is not a general purpose test and should only be used if you
+     * can live with false positives. For example, <code>pattern=**\a</code>
+     * and <code>str=b</code> will yield <code>true</code>.
+     *
+     * @param pattern The pattern to match against. Must not be
+     *                <code>null</code>.
+     * @param str     The path to match, as a String. Must not be
+     *                <code>null</code>.
+     * @param isCaseSensitive Whether or not matching should be performed
+     *                        case sensitively.
+     *
+     * @return whether or not a given path matches the start of a given
+     * pattern up to the first "**".
+     */
+    public static boolean matchPatternStart( String pattern, String str,
+                                             boolean isCaseSensitive )
+    {
+        // When str starts with a File.separator, pattern has to start with a
+        // File.separator.
+        // When pattern starts with a File.separator, str has to start with a
+        // File.separator.
+        if ( str.startsWith( File.separator ) !=
+            pattern.startsWith( File.separator ) )
+        {
+            return false;
+        }
+
+        Vector patDirs = tokenizePath( pattern );
+        Vector strDirs = tokenizePath( str );
+
+        int patIdxStart = 0;
+        int patIdxEnd = patDirs.size() - 1;
+        int strIdxStart = 0;
+        int strIdxEnd = strDirs.size() - 1;
+
+        // up to first '**'
+        while ( patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd )
+        {
+            String patDir = (String) patDirs.elementAt( patIdxStart );
+            if ( patDir.equals( "**" ) )
+            {
+                break;
+            }
+            if ( !match( patDir, (String) strDirs.elementAt( strIdxStart ),
+                         isCaseSensitive ) )
+            {
+                return false;
+            }
+            patIdxStart++;
+            strIdxStart++;
+        }
+
+        if ( strIdxStart > strIdxEnd )
+        {
+            // String is exhausted
+            return true;
+        }
+        else if ( patIdxStart > patIdxEnd )
+        {
+            // String not exhausted, but pattern is. Failure.
+            return false;
+        }
+        else
+        {
+            // pattern now holds ** while string is not exhausted
+            // this will generate false positives but we can live with that.
+            return true;
+        }
+    }
+
+    /**
+     * Tests whether or not a given path matches a given pattern.
+     *
+     * @param pattern The pattern to match against. Must not be
+     *                <code>null</code>.
+     * @param str     The path to match, as a String. Must not be
+     *                <code>null</code>.
+     *
+     * @return <code>true</code> if the pattern matches against the string,
+     *         or <code>false</code> otherwise.
+     */
+    public static boolean matchPath( String pattern, String str )
+    {
+        return matchPath( pattern, str, true );
+    }
+
+    /**
+     * Tests whether or not a given path matches a given pattern.
+     *
+     * @param pattern The pattern to match against. Must not be
+     *                <code>null</code>.
+     * @param str     The path to match, as a String. Must not be
+     *                <code>null</code>.
+     * @param isCaseSensitive Whether or not matching should be performed
+     *                        case sensitively.
+     *
+     * @return <code>true</code> if the pattern matches against the string,
+     *         or <code>false</code> otherwise.
+     */
+    public static boolean matchPath( String pattern, String str,
+                                     boolean isCaseSensitive )
+    {
+        // When str starts with a File.separator, pattern has to start with a
+        // File.separator.
+        // When pattern starts with a File.separator, str has to start with a
+        // File.separator.
+        if ( str.startsWith( File.separator ) !=
+            pattern.startsWith( File.separator ) )
+        {
+            return false;
+        }
+
+        Vector patDirs = tokenizePath( pattern );
+        Vector strDirs = tokenizePath( str );
+
+        int patIdxStart = 0;
+        int patIdxEnd = patDirs.size() - 1;
+        int strIdxStart = 0;
+        int strIdxEnd = strDirs.size() - 1;
+
+        // up to first '**'
+        while ( patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd )
+        {
+            String patDir = (String) patDirs.elementAt( patIdxStart );
+            if ( patDir.equals( "**" ) )
+            {
+                break;
+            }
+            if ( !match( patDir, (String) strDirs.elementAt( strIdxStart ),
+                         isCaseSensitive ) )
+            {
+                patDirs = null;
+                strDirs = null;
+                return false;
+            }
+            patIdxStart++;
+            strIdxStart++;
+        }
+        if ( strIdxStart > strIdxEnd )
+        {
+            // String is exhausted
+            for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+            {
+                if ( !patDirs.elementAt( i ).equals( "**" ) )
+                {
+                    patDirs = null;
+                    strDirs = null;
+                    return false;
+                }
+            }
+            return true;
+        }
+        else
+        {
+            if ( patIdxStart > patIdxEnd )
+            {
+                // String not exhausted, but pattern is. Failure.
+                patDirs = null;
+                strDirs = null;
+                return false;
+            }
+        }
+
+        // up to last '**'
+        while ( patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd )
+        {
+            String patDir = (String) patDirs.elementAt( patIdxEnd );
+            if ( patDir.equals( "**" ) )
+            {
+                break;
+            }
+            if ( !match( patDir, (String) strDirs.elementAt( strIdxEnd ),
+                         isCaseSensitive ) )
+            {
+                patDirs = null;
+                strDirs = null;
+                return false;
+            }
+            patIdxEnd--;
+            strIdxEnd--;
+        }
+        if ( strIdxStart > strIdxEnd )
+        {
+            // String is exhausted
+            for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+            {
+                if ( !patDirs.elementAt( i ).equals( "**" ) )
+                {
+                    patDirs = null;
+                    strDirs = null;
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        while ( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd )
+        {
+            int patIdxTmp = -1;
+            for ( int i = patIdxStart + 1; i <= patIdxEnd; i++ )
+            {
+                if ( patDirs.elementAt( i ).equals( "**" ) )
+                {
+                    patIdxTmp = i;
+                    break;
+                }
+            }
+            if ( patIdxTmp == patIdxStart + 1 )
+            {
+                // '**/**' situation, so skip one
+                patIdxStart++;
+                continue;
+            }
+            // Find the pattern between padIdxStart & padIdxTmp in str between
+            // strIdxStart & strIdxEnd
+            int patLength = ( patIdxTmp - patIdxStart - 1 );
+            int strLength = ( strIdxEnd - strIdxStart + 1 );
+            int foundIdx = -1;
+            strLoop:
+                        for ( int i = 0; i <= strLength - patLength; i++ )
+                        {
+                            for ( int j = 0; j < patLength; j++ )
+                            {
+                                String subPat = (String) patDirs.elementAt( patIdxStart + j + 1 );
+                                String subStr = (String) strDirs.elementAt( strIdxStart + i + j );
+                                if ( !match( subPat, subStr, isCaseSensitive ) )
+                                {
+                                    continue strLoop;
+                                }
+                            }
+
+                            foundIdx = strIdxStart + i;
+                            break;
+                        }
+
+            if ( foundIdx == -1 )
+            {
+                patDirs = null;
+                strDirs = null;
+                return false;
+            }
+
+            patIdxStart = patIdxTmp;
+            strIdxStart = foundIdx + patLength;
+        }
+
+        for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+        {
+            if ( !patDirs.elementAt( i ).equals( "**" ) )
+            {
+                patDirs = null;
+                strDirs = null;
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Tests whether or not a string matches against a pattern.
+     * The pattern may contain two special characters:<br>
+     * '*' means zero or more characters<br>
+     * '?' means one and only one character
+     *
+     * @param pattern The pattern to match against.
+     *                Must not be <code>null</code>.
+     * @param str     The string which must be matched against the pattern.
+     *                Must not be <code>null</code>.
+     *
+     * @return <code>true</code> if the string matches against the pattern,
+     *         or <code>false</code> otherwise.
+     */
+    public static boolean match( String pattern, String str )
+    {
+        return match( pattern, str, true );
+    }
+
+    /**
+     * Tests whether or not a string matches against a pattern.
+     * The pattern may contain two special characters:<br>
+     * '*' means zero or more characters<br>
+     * '?' means one and only one character
+     *
+     * @param pattern The pattern to match against.
+     *                Must not be <code>null</code>.
+     * @param str     The string which must be matched against the pattern.
+     *                Must not be <code>null</code>.
+     * @param isCaseSensitive Whether or not matching should be performed
+     *                        case sensitively.
+     *
+     *
+     * @return <code>true</code> if the string matches against the pattern,
+     *         or <code>false</code> otherwise.
+     */
+    public static boolean match( String pattern, String str,
+                                 boolean isCaseSensitive )
+    {
+        char[] patArr = pattern.toCharArray();
+        char[] strArr = str.toCharArray();
+        int patIdxStart = 0;
+        int patIdxEnd = patArr.length - 1;
+        int strIdxStart = 0;
+        int strIdxEnd = strArr.length - 1;
+        char ch;
+
+        boolean containsStar = false;
+        for ( int i = 0; i < patArr.length; i++ )
+        {
+            if ( patArr[i] == '*' )
+            {
+                containsStar = true;
+                break;
+            }
+        }
+
+        if ( !containsStar )
+        {
+            // No '*'s, so we make a shortcut
+            if ( patIdxEnd != strIdxEnd )
+            {
+                return false; // Pattern and string do not have the same size
+            }
+            for ( int i = 0; i <= patIdxEnd; i++ )
+            {
+                ch = patArr[i];
+                if ( ch != '?' )
+                {
+                    if ( isCaseSensitive && ch != strArr[i] )
+                    {
+                        return false;// Character mismatch
+                    }
+                    if ( !isCaseSensitive && Character.toUpperCase( ch ) !=
+                        Character.toUpperCase( strArr[i] ) )
+                    {
+                        return false; // Character mismatch
+                    }
+                }
+            }
+            return true; // String matches against pattern
+        }
+
+        if ( patIdxEnd == 0 )
+        {
+            return true; // Pattern contains only '*', which matches anything
+        }
+
+        // Process characters before first star
+        while ( ( ch = patArr[patIdxStart] ) != '*' && strIdxStart <= strIdxEnd )
+        {
+            if ( ch != '?' )
+            {
+                if ( isCaseSensitive && ch != strArr[strIdxStart] )
+                {
+                    return false;// Character mismatch
+                }
+                if ( !isCaseSensitive && Character.toUpperCase( ch ) !=
+                    Character.toUpperCase( strArr[strIdxStart] ) )
+                {
+                    return false;// Character mismatch
+                }
+            }
+            patIdxStart++;
+            strIdxStart++;
+        }
+        if ( strIdxStart > strIdxEnd )
+        {
+            // All characters in the string are used. Check if only '*'s are
+            // left in the pattern. If so, we succeeded. Otherwise failure.
+            for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+            {
+                if ( patArr[i] != '*' )
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // Process characters after last star
+        while ( ( ch = patArr[patIdxEnd] ) != '*' && strIdxStart <= strIdxEnd )
+        {
+            if ( ch != '?' )
+            {
+                if ( isCaseSensitive && ch != strArr[strIdxEnd] )
+                {
+                    return false;// Character mismatch
+                }
+                if ( !isCaseSensitive && Character.toUpperCase( ch ) !=
+                    Character.toUpperCase( strArr[strIdxEnd] ) )
+                {
+                    return false;// Character mismatch
+                }
+            }
+            patIdxEnd--;
+            strIdxEnd--;
+        }
+        if ( strIdxStart > strIdxEnd )
+        {
+            // All characters in the string are used. Check if only '*'s are
+            // left in the pattern. If so, we succeeded. Otherwise failure.
+            for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+            {
+                if ( patArr[i] != '*' )
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // process pattern between stars. padIdxStart and patIdxEnd point
+        // always to a '*'.
+        while ( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd )
+        {
+            int patIdxTmp = -1;
+            for ( int i = patIdxStart + 1; i <= patIdxEnd; i++ )
+            {
+                if ( patArr[i] == '*' )
+                {
+                    patIdxTmp = i;
+                    break;
+                }
+            }
+            if ( patIdxTmp == patIdxStart + 1 )
+            {
+                // Two stars next to each other, skip the first one.
+                patIdxStart++;
+                continue;
+            }
+            // Find the pattern between padIdxStart & padIdxTmp in str between
+            // strIdxStart & strIdxEnd
+            int patLength = ( patIdxTmp - patIdxStart - 1 );
+            int strLength = ( strIdxEnd - strIdxStart + 1 );
+            int foundIdx = -1;
+            strLoop:
+            for ( int i = 0; i <= strLength - patLength; i++ )
+            {
+                for ( int j = 0; j < patLength; j++ )
+                {
+                    ch = patArr[patIdxStart + j + 1];
+                    if ( ch != '?' )
+                    {
+                        if ( isCaseSensitive && ch != strArr[strIdxStart + i + j] )
+                        {
+                            continue strLoop;
+                        }
+                        if ( !isCaseSensitive && Character.toUpperCase( ch ) !=
+                            Character.toUpperCase( strArr[strIdxStart + i + j] ) )
+                        {
+                            continue strLoop;
+                        }
+                    }
+                }
+
+                foundIdx = strIdxStart + i;
+                break;
+            }
+
+            if ( foundIdx == -1 )
+            {
+                return false;
+            }
+
+            patIdxStart = patIdxTmp;
+            strIdxStart = foundIdx + patLength;
+        }
+
+        // All characters in the string are used. Check if only '*'s are left
+        // in the pattern. If so, we succeeded. Otherwise failure.
+        for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+        {
+            if ( patArr[i] != '*' )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Breaks a path up into a Vector of path elements, tokenizing on
+     * <code>File.separator</code>.
+     *
+     * @param path Path to tokenize. Must not be <code>null</code>.
+     *
+     * @return a Vector of path elements from the tokenized path
+     */
+    public static Vector tokenizePath( String path )
+    {
+        Vector ret = new Vector();
+        StringTokenizer st = new StringTokenizer( path, File.separator );
+        while ( st.hasMoreTokens() )
+        {
+            ret.addElement( st.nextToken() );
+        }
+        return ret;
+    }
+
+
+    /**
+     * Returns dependency information on these two files. If src has been
+     * modified later than target, it returns true. If target doesn't exist,
+     * it likewise returns true. Otherwise, target is newer than src and
+     * is not out of date, thus the method returns false. It also returns
+     * false if the src file doesn't even exist, since how could the
+     * target then be out of date.
+     *
+     * @param src the original file
+     * @param target the file being compared against
+     * @param granularity the amount in seconds of slack we will give in
+     *        determining out of dateness
+     * @return whether the target is out of date
+     */
+    public static boolean isOutOfDate( File src, File target, int granularity )
+    {
+        if ( !src.exists() )
+        {
+            return false;
+        }
+        if ( !target.exists() )
+        {
+            return true;
+        }
+        if ( ( src.lastModified() - granularity ) > target.lastModified() )
+        {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * "Flattens" a string by removing all whitespace (space, tab, linefeed,
+     * carriage return, and formfeed). This uses StringTokenizer and the
+     * default set of tokens as documented in the single arguement constructor.
+     *
+     * @param input a String to remove all whitespace.
+     * @return a String that has had all whitespace removed.
+     */
+    public static String removeWhitespace( String input )
+    {
+        StringBuffer result = new StringBuffer();
+        if ( input != null )
+        {
+            StringTokenizer st = new StringTokenizer( input );
+            while ( st.hasMoreTokens() )
+            {
+                result.append( st.nextToken() );
+            }
+        }
+        return result.toString();
+    }
+}

Propchange: maven/components/trunk/maven-core-it-verifier/src/main/java/org/codehaus/plexus/util/SelectorUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/components/trunk/maven-core-it-verifier/src/main/java/org/codehaus/plexus/util/SelectorUtils.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"