Merge "Original upload of the glob library"
diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..fb50116
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3826f65
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+bin
+*~
+*.bak
+Thumbs.db
+*.class
+*.DS_Store
diff --git a/.project b/.project
new file mode 100644
index 0000000..342bc23
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>ant-glob</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..4089edf
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Only compile source java files in this lib.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_RESOURCE_DIRS := src
+
+LOCAL_MODULE := ant-glob
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/MODULE_LICENSE_APL b/MODULE_LICENSE_APL
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APL
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..cdf6ff8
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,272 @@
+/*
+ *                                 Apache License
+ *                           Version 2.0, January 2004
+ *                        http://www.apache.org/licenses/
+ *
+ *   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+ *
+ *   1. Definitions.
+ *
+ *      "License" shall mean the terms and conditions for use, reproduction,
+ *      and distribution as defined by Sections 1 through 9 of this document.
+ *
+ *      "Licensor" shall mean the copyright owner or entity authorized by
+ *      the copyright owner that is granting the License.
+ *
+ *      "Legal Entity" shall mean the union of the acting entity and all
+ *      other entities that control, are controlled by, or are under common
+ *      control with that entity. For the purposes of this definition,
+ *      "control" means (i) the power, direct or indirect, to cause the
+ *      direction or management of such entity, whether by contract or
+ *      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ *      outstanding shares, or (iii) beneficial ownership of such entity.
+ *
+ *      "You" (or "Your") shall mean an individual or Legal Entity
+ *      exercising permissions granted by this License.
+ *
+ *      "Source" form shall mean the preferred form for making modifications,
+ *      including but not limited to software source code, documentation
+ *      source, and configuration files.
+ *
+ *      "Object" form shall mean any form resulting from mechanical
+ *      transformation or translation of a Source form, including but
+ *      not limited to compiled object code, generated documentation,
+ *      and conversions to other media types.
+ *
+ *      "Work" shall mean the work of authorship, whether in Source or
+ *      Object form, made available under the License, as indicated by a
+ *      copyright notice that is included in or attached to the work
+ *      (an example is provided in the Appendix below).
+ *
+ *      "Derivative Works" shall mean any work, whether in Source or Object
+ *      form, that is based on (or derived from) the Work and for which the
+ *      editorial revisions, annotations, elaborations, or other modifications
+ *      represent, as a whole, an original work of authorship. For the purposes
+ *      of this License, Derivative Works shall not include works that remain
+ *      separable from, or merely link (or bind by name) to the interfaces of,
+ *      the Work and Derivative Works thereof.
+ *
+ *      "Contribution" shall mean any work of authorship, including
+ *      the original version of the Work and any modifications or additions
+ *      to that Work or Derivative Works thereof, that is intentionally
+ *      submitted to Licensor for inclusion in the Work by the copyright owner
+ *      or by an individual or Legal Entity authorized to submit on behalf of
+ *      the copyright owner. For the purposes of this definition, "submitted"
+ *      means any form of electronic, verbal, or written communication sent
+ *      to the Licensor or its representatives, including but not limited to
+ *      communication on electronic mailing lists, source code control systems,
+ *      and issue tracking systems that are managed by, or on behalf of, the
+ *      Licensor for the purpose of discussing and improving the Work, but
+ *      excluding communication that is conspicuously marked or otherwise
+ *      designated in writing by the copyright owner as "Not a Contribution."
+ *
+ *      "Contributor" shall mean Licensor and any individual or Legal Entity
+ *      on behalf of whom a Contribution has been received by Licensor and
+ *      subsequently incorporated within the Work.
+ *
+ *   2. Grant of Copyright License. Subject to the terms and conditions of
+ *      this License, each Contributor hereby grants to You a perpetual,
+ *      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ *      copyright license to reproduce, prepare Derivative Works of,
+ *      publicly display, publicly perform, sublicense, and distribute the
+ *      Work and such Derivative Works in Source or Object form.
+ *
+ *   3. Grant of Patent License. Subject to the terms and conditions of
+ *      this License, each Contributor hereby grants to You a perpetual,
+ *      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ *      (except as stated in this section) patent license to make, have made,
+ *      use, offer to sell, sell, import, and otherwise transfer the Work,
+ *      where such license applies only to those patent claims licensable
+ *      by such Contributor that are necessarily infringed by their
+ *      Contribution(s) alone or by combination of their Contribution(s)
+ *      with the Work to which such Contribution(s) was submitted. If You
+ *      institute patent litigation against any entity (including a
+ *      cross-claim or counterclaim in a lawsuit) alleging that the Work
+ *      or a Contribution incorporated within the Work constitutes direct
+ *      or contributory patent infringement, then any patent licenses
+ *      granted to You under this License for that Work shall terminate
+ *      as of the date such litigation is filed.
+ *
+ *   4. Redistribution. You may reproduce and distribute copies of the
+ *      Work or Derivative Works thereof in any medium, with or without
+ *      modifications, and in Source or Object form, provided that You
+ *      meet the following conditions:
+ *
+ *      (a) You must give any other recipients of the Work or
+ *          Derivative Works a copy of this License; and
+ *
+ *      (b) You must cause any modified files to carry prominent notices
+ *          stating that You changed the files; and
+ *
+ *      (c) You must retain, in the Source form of any Derivative Works
+ *          that You distribute, all copyright, patent, trademark, and
+ *          attribution notices from the Source form of the Work,
+ *          excluding those notices that do not pertain to any part of
+ *          the Derivative Works; and
+ *
+ *      (d) If the Work includes a "NOTICE" text file as part of its
+ *          distribution, then any Derivative Works that You distribute must
+ *          include a readable copy of the attribution notices contained
+ *          within such NOTICE file, excluding those notices that do not
+ *          pertain to any part of the Derivative Works, in at least one
+ *          of the following places: within a NOTICE text file distributed
+ *          as part of the Derivative Works; within the Source form or
+ *          documentation, if provided along with the Derivative Works; or,
+ *          within a display generated by the Derivative Works, if and
+ *          wherever such third-party notices normally appear. The contents
+ *          of the NOTICE file are for informational purposes only and
+ *          do not modify the License. You may add Your own attribution
+ *          notices within Derivative Works that You distribute, alongside
+ *          or as an addendum to the NOTICE text from the Work, provided
+ *          that such additional attribution notices cannot be construed
+ *          as modifying the License.
+ *
+ *      You may add Your own copyright statement to Your modifications and
+ *      may provide additional or different license terms and conditions
+ *      for use, reproduction, or distribution of Your modifications, or
+ *      for any such Derivative Works as a whole, provided Your use,
+ *      reproduction, and distribution of the Work otherwise complies with
+ *      the conditions stated in this License.
+ *
+ *   5. Submission of Contributions. Unless You explicitly state otherwise,
+ *      any Contribution intentionally submitted for inclusion in the Work
+ *      by You to the Licensor shall be under the terms and conditions of
+ *      this License, without any additional terms or conditions.
+ *      Notwithstanding the above, nothing herein shall supersede or modify
+ *      the terms of any separate license agreement you may have executed
+ *      with Licensor regarding such Contributions.
+ *
+ *   6. Trademarks. This License does not grant permission to use the trade
+ *      names, trademarks, service marks, or product names of the Licensor,
+ *      except as required for reasonable and customary use in describing the
+ *      origin of the Work and reproducing the content of the NOTICE file.
+ *
+ *   7. Disclaimer of Warranty. Unless required by applicable law or
+ *      agreed to in writing, Licensor provides the Work (and each
+ *      Contributor provides its Contributions) on an "AS IS" BASIS,
+ *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *      implied, including, without limitation, any warranties or conditions
+ *      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ *      PARTICULAR PURPOSE. You are solely responsible for determining the
+ *      appropriateness of using or redistributing the Work and assume any
+ *      risks associated with Your exercise of permissions under this License.
+ *
+ *   8. Limitation of Liability. In no event and under no legal theory,
+ *      whether in tort (including negligence), contract, or otherwise,
+ *      unless required by applicable law (such as deliberate and grossly
+ *      negligent acts) or agreed to in writing, shall any Contributor be
+ *      liable to You for damages, including any direct, indirect, special,
+ *      incidental, or consequential damages of any character arising as a
+ *      result of this License or out of the use or inability to use the
+ *      Work (including but not limited to damages for loss of goodwill,
+ *      work stoppage, computer failure or malfunction, or any and all
+ *      other commercial damages or losses), even if such Contributor
+ *      has been advised of the possibility of such damages.
+ *
+ *   9. Accepting Warranty or Additional Liability. While redistributing
+ *      the Work or Derivative Works thereof, You may choose to offer,
+ *      and charge a fee for, acceptance of support, warranty, indemnity,
+ *      or other liability obligations and/or rights consistent with this
+ *      License. However, in accepting such obligations, You may act only
+ *      on Your own behalf and on Your sole responsibility, not on behalf
+ *      of any other Contributor, and only if You agree to indemnify,
+ *      defend, and hold each Contributor harmless for any liability
+ *      incurred by, or claims asserted against, such Contributor by reason
+ *      of your accepting any such warranty or additional liability.
+ *
+ *   END OF TERMS AND CONDITIONS
+ *
+ *   APPENDIX: How to apply the Apache License to your work.
+ *
+ *      To apply the Apache License to your work, attach the following
+ *      boilerplate notice, with the fields enclosed by brackets "[]"
+ *      replaced with your own identifying information. (Don't include
+ *      the brackets!)  The text should be enclosed in the appropriate
+ *      comment syntax for the file format. We also recommend that a
+ *      file or class name and description of purpose be included on the
+ *      same "printed page" as the copyright notice for easier
+ *      identification within third-party archives.
+ *
+ *   Copyright [yyyy] [name of copyright owner]
+ *
+ *   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.
+ */
+
+W3C® SOFTWARE NOTICE AND LICENSE
+http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+This work (and included software, documentation such as READMEs, or other
+related items) is being provided by the copyright holders under the following
+license. By obtaining, using and/or copying this work, you (the licensee) agree
+that you have read, understood, and will comply with the following terms and
+conditions.
+
+Permission to copy, modify, and distribute this software and its documentation,
+with or without modification, for any purpose and without fee or royalty is
+hereby granted, provided that you include the following on ALL copies of the
+software and documentation or portions thereof, including modifications:
+
+  1. The full text of this NOTICE in a location viewable to users of the
+     redistributed or derivative work. 
+  2. Any pre-existing intellectual property disclaimers, notices, or terms
+     and conditions. If none exist, the W3C Software Short Notice should be
+     included (hypertext is preferred, text is permitted) within the body
+     of any redistributed or derivative code.
+  3. Notice of any changes or modifications to the files, including the date
+     changes were made. (We recommend you provide URIs to the location from
+     which the code is derived.)
+     
+THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE
+NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
+THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
+PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+
+COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
+
+The name and trademarks of copyright holders may NOT be used in advertising or
+publicity pertaining to the software without specific, written prior permission.
+Title to copyright in this software and any associated documentation will at
+all times remain with copyright holders.
+
+____________________________________
+
+This formulation of W3C's notice and license became active on December 31 2002.
+This version removes the copyright ownership notice such that this license can
+be used with materials other than those owned by the W3C, reflects that ERCIM
+is now a host of the W3C, includes references to this specific dated version of
+the license, and removes the ambiguous grant of "use". Otherwise, this version
+is the same as the previous version and is written so as to preserve the Free
+Software Foundation's assessment of GPL compatibility and OSI's certification
+under the Open Source Definition. Please see our Copyright FAQ for common
+questions about using materials from our site, including specific terms and
+conditions for packages like libwww, Amaya, and Jigsaw. Other questions about
+this notice can be directed to site-policy@w3.org.
+ 
+Joseph Reagle <site-policy@w3.org> 
+
+This license came from: http://www.megginson.com/SAX/copying.html
+  However please note future versions of SAX may be covered 
+  under http://saxproject.org/?selected=pd
+
+SAX2 is Free!
+
+I hereby abandon any property rights to SAX 2.0 (the Simple API for
+XML), and release all of the SAX 2.0 source code, compiled code, and
+documentation contained in this distribution into the Public Domain.
+SAX comes with NO WARRANTY or guarantee of fitness for any
+purpose.
+
+David Megginson, david@megginson.com
+2000-05-05
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..3e26409
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,27 @@
+Ant Glob support
+
+Apache Ant
+Copyright 1999-2012 The Apache Software Foundation
+-------------------------------------
+
+This project is a fork of a subset of Ant 1.8.3:
+http://ant.apache.com/
+
+Specifically, it contains the subset of Ant related to matching glob patterns
+to paths
+
+The fork was modified as follows:
+* Started with version 1.8.3
+
+* Extracted
+    org.apache.tools.ant.types.selectors.SelectorUtils
+  and then everything it transitively references that was truly needed:
+    org.apache.tools.ant.util.FileUtils,
+    org.apache.tools.ant.taskdefs.condition.Condition,
+    org.apache.tools.ant.taskdefs.condition.OS,
+    org.apache.tools.ant.BuildException
+
+* FileUtils was pruned to keep only 2 methods, which brought OS (which
+  brought Condition). In turn this brought in BuildException which was trimmed
+  up a bit (removing references to Location)
+
diff --git a/src/org/apache/tools/ant/BuildException.java b/src/org/apache/tools/ant/BuildException.java
new file mode 100644
index 0000000..f547cd7
--- /dev/null
+++ b/src/org/apache/tools/ant/BuildException.java
@@ -0,0 +1,79 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.tools.ant;
+
+/**
+ * Signals an error condition during a build
+ */
+public class BuildException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructs a build exception with no descriptive information.
+     */
+    public BuildException() {
+        super();
+    }
+
+    /**
+     * Constructs an exception with the given descriptive message.
+     *
+     * @param message A description of or information about the exception.
+     *            Should not be <code>null</code>.
+     */
+    public BuildException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs an exception with the given message and exception as
+     * a root cause.
+     *
+     * @param message A description of or information about the exception.
+     *            Should not be <code>null</code> unless a cause is specified.
+     * @param cause The exception that might have caused this one.
+     *              May be <code>null</code>.
+     */
+    public BuildException(String message, Throwable cause) {
+        super(message);
+        initCause(cause);
+    }
+
+    /**
+     * Constructs an exception with the given exception as a root cause.
+     *
+     * @param cause The exception that might have caused this one.
+     *              Should not be <code>null</code>.
+     */
+    public BuildException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Returns the nested exception, if any.
+     *
+     * @return the nested exception, or <code>null</code> if no
+     *         exception is associated with this one
+     * @deprecated Use {@link #getCause} instead.
+     */
+    @Deprecated
+    public Throwable getException() {
+        return getCause();
+    }
+}
diff --git a/src/org/apache/tools/ant/taskdefs/condition/Condition.java b/src/org/apache/tools/ant/taskdefs/condition/Condition.java
new file mode 100644
index 0000000..62adbf3
--- /dev/null
+++ b/src/org/apache/tools/ant/taskdefs/condition/Condition.java
@@ -0,0 +1,35 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.tools.ant.taskdefs.condition;
+
+import org.apache.tools.ant.BuildException;
+
+/**
+ * Interface for conditions to use inside the &lt;condition&gt; task.
+ *
+ */
+public interface Condition {
+    /**
+     * Is this condition true?
+     * @return true if the condition is true
+     * @exception BuildException if an error occurs
+     */
+    boolean eval() throws BuildException;
+}
+
diff --git a/src/org/apache/tools/ant/taskdefs/condition/Os.java b/src/org/apache/tools/ant/taskdefs/condition/Os.java
new file mode 100644
index 0000000..4e90e35
--- /dev/null
+++ b/src/org/apache/tools/ant/taskdefs/condition/Os.java
@@ -0,0 +1,322 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.tools.ant.taskdefs.condition;
+
+import org.apache.tools.ant.BuildException;
+
+import java.util.Locale;
+
+/**
+ * Condition that tests the OS type.
+ *
+ * @since Ant 1.4
+ */
+public class Os implements Condition {
+    private static final String OS_NAME =
+        System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
+    private static final String OS_ARCH =
+        System.getProperty("os.arch").toLowerCase(Locale.ENGLISH);
+    private static final String OS_VERSION =
+        System.getProperty("os.version").toLowerCase(Locale.ENGLISH);
+    private static final String PATH_SEP =
+        System.getProperty("path.separator");
+
+    /**
+     * OS family to look for
+     */
+    private String family;
+    /**
+     * Name of OS
+     */
+    private String name;
+    /**
+     * version of OS
+     */
+    private String version;
+    /**
+     * OS architecture
+     */
+    private String arch;
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_WINDOWS = "windows";
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_9X = "win9x";
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_NT = "winnt";
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_OS2 = "os/2";
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_NETWARE = "netware";
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_DOS = "dos";
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_MAC = "mac";
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_TANDEM = "tandem";
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_UNIX = "unix";
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_VMS = "openvms";
+    /**
+     * OS family that can be tested for. {@value}
+     */
+    public static final String FAMILY_ZOS = "z/os";
+    /** OS family that can be tested for. {@value} */
+    public static final String FAMILY_OS400 = "os/400";
+
+    /**
+     * OpenJDK is reported to call MacOS X "Darwin"
+     * @see https://issues.apache.org/bugzilla/show_bug.cgi?id=44889
+     * @see https://issues.apache.org/jira/browse/HADOOP-3318
+     */
+    private static final String DARWIN = "darwin";
+
+    /**
+     * Default constructor
+     *
+     */
+    public Os() {
+        //default
+    }
+
+    /**
+     * Constructor that sets the family attribute
+     * @param family a String value
+     */
+    public Os(String family) {
+        setFamily(family);
+    }
+
+    /**
+     * Sets the desired OS family type
+     *
+     * @param f      The OS family type desired<br />
+     *               Possible values:<br />
+     *               <ul>
+     *               <li>dos</li>
+     *               <li>mac</li>
+     *               <li>netware</li>
+     *               <li>os/2</li>
+     *               <li>tandem</li>
+     *               <li>unix</li>
+     *               <li>windows</li>
+     *               <li>win9x</li>
+     *               <li>z/os</li>
+     *               <li>os/400</li>
+     *               </ul>
+     */
+    public void setFamily(String f) {
+        family = f.toLowerCase(Locale.ENGLISH);
+    }
+
+    /**
+     * Sets the desired OS name
+     *
+     * @param name   The OS name
+     */
+    public void setName(String name) {
+        this.name = name.toLowerCase(Locale.ENGLISH);
+    }
+
+    /**
+     * Sets the desired OS architecture
+     *
+     * @param arch   The OS architecture
+     */
+    public void setArch(String arch) {
+        this.arch = arch.toLowerCase(Locale.ENGLISH);
+    }
+
+    /**
+     * Sets the desired OS version
+     *
+     * @param version   The OS version
+     */
+    public void setVersion(String version) {
+        this.version = version.toLowerCase(Locale.ENGLISH);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the type of
+     * that set in setFamily.
+     * @return true if the os matches.
+     * @throws BuildException if there is an error.
+     * @see Os#setFamily(String)
+     */
+    @Override
+    public boolean eval() throws BuildException {
+        return isOs(family, name, arch, version);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the
+     * given OS family.
+     * @param family the family to check for
+     * @return true if the OS matches
+     * @since 1.5
+     */
+    public static boolean isFamily(String family) {
+        return isOs(family, null, null, null);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the
+     * given OS name.
+     *
+     * @param name the OS name to check for
+     * @return true if the OS matches
+     * @since 1.7
+     */
+    public static boolean isName(String name) {
+        return isOs(null, name, null, null);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the
+     * given OS architecture.
+     *
+     * @param arch the OS architecture to check for
+     * @return true if the OS matches
+     * @since 1.7
+     */
+    public static boolean isArch(String arch) {
+        return isOs(null, null, arch, null);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the
+     * given OS version.
+     *
+     * @param version the OS version to check for
+     * @return true if the OS matches
+     * @since 1.7
+     */
+    public static boolean isVersion(String version) {
+        return isOs(null, null, null, version);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the
+     * given OS family, name, architecture and version
+     *
+     * @param family   The OS family
+     * @param name   The OS name
+     * @param arch   The OS architecture
+     * @param version   The OS version
+     * @return true if the OS matches
+     * @since 1.7
+     */
+    public static boolean isOs(String family, String name, String arch,
+                               String version) {
+        boolean retValue = false;
+
+        if (family != null || name != null || arch != null
+            || version != null) {
+
+            boolean isFamily = true;
+            boolean isName = true;
+            boolean isArch = true;
+            boolean isVersion = true;
+
+            if (family != null) {
+
+                //windows probing logic relies on the word 'windows' in
+                //the OS
+                boolean isWindows = OS_NAME.indexOf(FAMILY_WINDOWS) > -1;
+                boolean is9x = false;
+                boolean isNT = false;
+                if (isWindows) {
+                    //there are only four 9x platforms that we look for
+                    is9x = (OS_NAME.indexOf("95") >= 0
+                            || OS_NAME.indexOf("98") >= 0
+                            || OS_NAME.indexOf("me") >= 0
+                            //wince isn't really 9x, but crippled enough to
+                            //be a muchness. Ant doesnt run on CE, anyway.
+                            || OS_NAME.indexOf("ce") >= 0);
+                    isNT = !is9x;
+                }
+                if (family.equals(FAMILY_WINDOWS)) {
+                    isFamily = isWindows;
+                } else if (family.equals(FAMILY_9X)) {
+                    isFamily = isWindows && is9x;
+                } else if (family.equals(FAMILY_NT)) {
+                    isFamily = isWindows && isNT;
+                } else if (family.equals(FAMILY_OS2)) {
+                    isFamily = OS_NAME.indexOf(FAMILY_OS2) > -1;
+                } else if (family.equals(FAMILY_NETWARE)) {
+                    isFamily = OS_NAME.indexOf(FAMILY_NETWARE) > -1;
+                } else if (family.equals(FAMILY_DOS)) {
+                    isFamily = PATH_SEP.equals(";") && !isFamily(FAMILY_NETWARE);
+                } else if (family.equals(FAMILY_MAC)) {
+                    isFamily = OS_NAME.indexOf(FAMILY_MAC) > -1
+                        || OS_NAME.indexOf(DARWIN) > -1;
+                } else if (family.equals(FAMILY_TANDEM)) {
+                    isFamily = OS_NAME.indexOf("nonstop_kernel") > -1;
+                } else if (family.equals(FAMILY_UNIX)) {
+                    isFamily = PATH_SEP.equals(":")
+                        && !isFamily(FAMILY_VMS)
+                        && (!isFamily(FAMILY_MAC) || OS_NAME.endsWith("x")
+                            || OS_NAME.indexOf(DARWIN) > -1);
+                } else if (family.equals(FAMILY_ZOS)) {
+                    isFamily = OS_NAME.indexOf(FAMILY_ZOS) > -1
+                        || OS_NAME.indexOf("os/390") > -1;
+                } else if (family.equals(FAMILY_OS400)) {
+                    isFamily = OS_NAME.indexOf(FAMILY_OS400) > -1;
+                } else if (family.equals(FAMILY_VMS)) {
+                    isFamily = OS_NAME.indexOf(FAMILY_VMS) > -1;
+                } else {
+                    throw new BuildException(
+                        "Don\'t know how to detect os family \""
+                        + family + "\"");
+                }
+            }
+            if (name != null) {
+                isName = name.equals(OS_NAME);
+            }
+            if (arch != null) {
+                isArch = arch.equals(OS_ARCH);
+            }
+            if (version != null) {
+                isVersion = version.equals(OS_VERSION);
+            }
+            retValue = isFamily && isName && isArch && isVersion;
+        }
+        return retValue;
+    }
+}
diff --git a/src/org/apache/tools/ant/types/selectors/SelectorUtils.java b/src/org/apache/tools/ant/types/selectors/SelectorUtils.java
new file mode 100644
index 0000000..388d4d5
--- /dev/null
+++ b/src/org/apache/tools/ant/types/selectors/SelectorUtils.java
@@ -0,0 +1,647 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.tools.ant.types.selectors;
+
+import org.apache.tools.ant.util.FileUtils;
+
+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>
+ *
+ * @since 1.5
+ */
+public final class SelectorUtils {
+
+    /**
+     * The pattern that matches an arbitrary number of directories.
+     * @since Ant 1.8.0
+     */
+    public static final String DEEP_TREE_MATCH = "**";
+
+    private static final SelectorUtils instance = new SelectorUtils();
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
+    /**
+     * Private Constructor
+     */
+    private SelectorUtils() {
+    }
+
+    /**
+     * Retrieves the instance of the Singleton.
+     * @return singleton instance
+     */
+    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;
+        }
+
+        String[] patDirs = tokenizePathAsArray(pattern);
+        String[] strDirs = tokenizePathAsArray(str);
+        return matchPatternStart(patDirs, strDirs, isCaseSensitive);
+    }
+
+
+    /**
+     * 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 patDirs The tokenized pattern to match against. Must not be
+     *                <code>null</code>.
+     * @param strDirs The tokenized path to match. 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 "**".
+     */
+    static boolean matchPatternStart(String[] patDirs, String[] strDirs,
+                                     boolean isCaseSensitive) {
+        int patIdxStart = 0;
+        int patIdxEnd = patDirs.length - 1;
+        int strIdxStart = 0;
+        int strIdxEnd = strDirs.length - 1;
+
+        // up to first '**'
+        while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
+            String patDir = patDirs[patIdxStart];
+            if (patDir.equals(DEEP_TREE_MATCH)) {
+                break;
+            }
+            if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) {
+                return false;
+            }
+            patIdxStart++;
+            strIdxStart++;
+        }
+
+        // CheckStyle:SimplifyBooleanReturnCheck OFF
+        // Check turned off as the code needs the comments for the various
+        // code paths.
+        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.
+     *
+     * If you need to call this method multiple times with the same
+     * pattern you should rather use TokenizedPath
+     *
+     * @see TokenizedPath
+     *
+     * @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) {
+        String[] patDirs = tokenizePathAsArray(pattern);
+        return matchPath(patDirs, tokenizePathAsArray(str), true);
+    }
+
+    /**
+     * Tests whether or not a given path matches a given pattern.
+     *
+     * If you need to call this method multiple times with the same
+     * pattern you should rather use TokenizedPattern
+     *
+     * @see TokenizedPattern
+     *
+     * @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) {
+        String[] patDirs = tokenizePathAsArray(pattern);
+        return matchPath(patDirs, tokenizePathAsArray(str), isCaseSensitive);
+    }
+
+    /**
+     * Core implementation of matchPath.  It is isolated so that it
+     * can be called from TokenizedPattern.
+     */
+    static boolean matchPath(String[] tokenizedPattern, String[] strDirs,
+                             boolean isCaseSensitive) {
+        int patIdxStart = 0;
+        int patIdxEnd = tokenizedPattern.length - 1;
+        int strIdxStart = 0;
+        int strIdxEnd = strDirs.length - 1;
+
+        // up to first '**'
+        while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
+            String patDir = tokenizedPattern[patIdxStart];
+            if (patDir.equals(DEEP_TREE_MATCH)) {
+                break;
+            }
+            if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) {
+                return false;
+            }
+            patIdxStart++;
+            strIdxStart++;
+        }
+        if (strIdxStart > strIdxEnd) {
+            // String is exhausted
+            for (int i = patIdxStart; i <= patIdxEnd; i++) {
+                if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
+                    return false;
+                }
+            }
+            return true;
+        } else {
+            if (patIdxStart > patIdxEnd) {
+                // String not exhausted, but pattern is. Failure.
+                return false;
+            }
+        }
+
+        // up to last '**'
+        while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
+            String patDir = tokenizedPattern[patIdxEnd];
+            if (patDir.equals(DEEP_TREE_MATCH)) {
+                break;
+            }
+            if (!match(patDir, strDirs[strIdxEnd], isCaseSensitive)) {
+                return false;
+            }
+            patIdxEnd--;
+            strIdxEnd--;
+        }
+        if (strIdxStart > strIdxEnd) {
+            // String is exhausted
+            for (int i = patIdxStart; i <= patIdxEnd; i++) {
+                if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
+            int patIdxTmp = -1;
+            for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
+                if (tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
+                    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 = tokenizedPattern[patIdxStart + j + 1];
+                                String subStr = strDirs[strIdxStart + i + j];
+                                if (!match(subPat, subStr, isCaseSensitive)) {
+                                    continue strLoop;
+                                }
+                            }
+
+                            foundIdx = strIdxStart + i;
+                            break;
+                        }
+
+            if (foundIdx == -1) {
+                return false;
+            }
+
+            patIdxStart = patIdxTmp;
+            strIdxStart = foundIdx + patLength;
+        }
+
+        for (int i = patIdxStart; i <= patIdxEnd; i++) {
+            if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
+                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 caseSensitive 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 caseSensitive) {
+        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 (different(caseSensitive, ch, 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 (true) {
+            ch = patArr[patIdxStart];
+            if (ch == '*' || strIdxStart > strIdxEnd) {
+                break;
+            }
+            if (ch != '?') {
+                if (different(caseSensitive, ch, 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.
+            return allStars(patArr, patIdxStart, patIdxEnd);
+        }
+
+        // Process characters after last star
+        while (true) {
+            ch = patArr[patIdxEnd];
+            if (ch == '*' || strIdxStart > strIdxEnd) {
+                break;
+            }
+            if (ch != '?') {
+                if (different(caseSensitive, ch, 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.
+            return allStars(patArr, patIdxStart, patIdxEnd);
+        }
+
+        // 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 (different(caseSensitive, ch,
+                                      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.
+        return allStars(patArr, patIdxStart, patIdxEnd);
+    }
+
+    private static boolean allStars(char[] chars, int start, int end) {
+        for (int i = start; i <= end; ++i) {
+            if (chars[i] != '*') {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static boolean different(
+        boolean caseSensitive, char ch, char other) {
+        return caseSensitive
+            ? ch != other
+            : Character.toUpperCase(ch) != Character.toUpperCase(other);
+    }
+
+    /**
+     * 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
+     */
+    @SuppressWarnings("rawtypes")
+    public static Vector tokenizePath (String path) {
+        return tokenizePath(path, File.separator);
+    }
+
+    /**
+     * Breaks a path up into a Vector of path elements, tokenizing on
+     *
+     * @param path Path to tokenize. Must not be <code>null</code>.
+     * @param separator the separator against which to tokenize.
+     *
+     * @return a Vector of path elements from the tokenized path
+     * @since Ant 1.6
+     */
+    @SuppressWarnings({
+            "rawtypes", "unchecked"
+    })
+    public static Vector tokenizePath (String path, String separator) {
+        Vector ret = new Vector();
+        if (FileUtils.isAbsolutePath(path)) {
+            String[] s = FILE_UTILS.dissect(path);
+            ret.add(s[0]);
+            path = s[1];
+        }
+        StringTokenizer st = new StringTokenizer(path, separator);
+        while (st.hasMoreTokens()) {
+            ret.addElement(st.nextToken());
+        }
+        return ret;
+    }
+
+    /**
+     * Same as {@link #tokenizePath tokenizePath} but hopefully faster.
+     */
+    /*package*/ static String[] tokenizePathAsArray(String path) {
+        String root = null;
+        if (FileUtils.isAbsolutePath(path)) {
+            String[] s = FILE_UTILS.dissect(path);
+            root = s[0];
+            path = s[1];
+        }
+        char sep = File.separatorChar;
+        int start = 0;
+        int len = path.length();
+        int count = 0;
+        for (int pos = 0; pos < len; pos++) {
+            if (path.charAt(pos) == sep) {
+                if (pos != start) {
+                    count++;
+                }
+                start = pos + 1;
+            }
+        }
+        if (len != start) {
+            count++;
+        }
+        String[] l = new String[count + ((root == null) ? 0 : 1)];
+
+        if (root != null) {
+            l[0] = root;
+            count = 1;
+        } else {
+            count = 0;
+        }
+        start = 0;
+        for (int pos = 0; pos < len; pos++) {
+            if (path.charAt(pos) == sep) {
+                if (pos != start) {
+                    String tok = path.substring(start, pos);
+                    l[count++] = tok;
+                }
+                start = pos + 1;
+            }
+        }
+        if (len != start) {
+            String tok = path.substring(start);
+            l[count/*++*/] = tok;
+        }
+        return l;
+    }
+
+    /**
+     * 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();
+    }
+
+    /**
+     * Tests if a string contains stars or question marks
+     * @param input a String which one wants to test for containing wildcard
+     * @return true if the string contains at least a star or a question mark
+     */
+    public static boolean hasWildcards(String input) {
+        return (input.indexOf('*') != -1 || input.indexOf('?') != -1);
+    }
+}
+
diff --git a/src/org/apache/tools/ant/util/FileUtils.java b/src/org/apache/tools/ant/util/FileUtils.java
new file mode 100644
index 0000000..2774a17
--- /dev/null
+++ b/src/org/apache/tools/ant/util/FileUtils.java
@@ -0,0 +1,189 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.tools.ant.util;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.condition.Os;
+
+import java.io.File;
+import java.util.Random;
+
+/**
+ * This class also encapsulates methods which allow Files to be
+ * referred to using abstract path names which are translated to native
+ * system file paths at runtime as well as copying files or setting
+ * their last modification time.
+ *
+ */
+public class FileUtils {
+    private static final int DELETE_RETRY_SLEEP_MILLIS = 10;
+    private static final int EXPAND_SPACE = 50;
+    private static final FileUtils PRIMARY_INSTANCE = new FileUtils();
+
+    //get some non-crypto-grade randomness from various places.
+    private static Random rand = new Random(System.currentTimeMillis()
+            + Runtime.getRuntime().freeMemory());
+
+    private static final boolean ON_NETWARE = Os.isFamily("netware");
+    private static final boolean ON_DOS = Os.isFamily("dos");
+    private static final boolean ON_WIN9X = Os.isFamily("win9x");
+    private static final boolean ON_WINDOWS = Os.isFamily("windows");
+
+    static final int BUF_SIZE = 8192;
+
+
+    /**
+     * The granularity of timestamps under FAT.
+     */
+    public static final long FAT_FILE_TIMESTAMP_GRANULARITY = 2000;
+
+    /**
+     * The granularity of timestamps under Unix.
+     */
+    public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000;
+
+    /**
+     * The granularity of timestamps under the NT File System.
+     * NTFS has a granularity of 100 nanoseconds, which is less
+     * than 1 millisecond, so we round this up to 1 millisecond.
+     */
+    public static final long NTFS_FILE_TIMESTAMP_GRANULARITY = 1;
+
+    /**
+     * A one item cache for fromUri.
+     * fromUri is called for each element when parseing ant build
+     * files. It is a costly operation. This just caches the result
+     * of the last call.
+     */
+    private Object cacheFromUriLock = new Object();
+    private String cacheFromUriRequest = null;
+    private String cacheFromUriResponse = null;
+
+    /**
+     * Factory method.
+     *
+     * @return a new instance of FileUtils.
+     * @deprecated since 1.7.
+     *             Use getFileUtils instead,
+     * FileUtils do not have state.
+     */
+    @Deprecated
+    public static FileUtils newFileUtils() {
+        return new FileUtils();
+    }
+
+    /**
+     * Method to retrieve The FileUtils, which is shared by all users of this
+     * method.
+     * @return an instance of FileUtils.
+     * @since Ant 1.6.3
+     */
+    public static FileUtils getFileUtils() {
+        return PRIMARY_INSTANCE;
+    }
+
+    /**
+     * Empty constructor.
+     */
+    protected FileUtils() {
+    }
+
+    /**
+     * Verifies that the specified filename represents an absolute path.
+     * Differs from new java.io.File("filename").isAbsolute() in that a path
+     * beginning with a double file separator--signifying a Windows UNC--must
+     * at minimum match "\\a\b" to be considered an absolute path.
+     * @param filename the filename to be checked.
+     * @return true if the filename represents an absolute path.
+     * @throws java.lang.NullPointerException if filename is null.
+     * @since Ant 1.6.3
+     */
+    public static boolean isAbsolutePath(String filename) {
+        int len = filename.length();
+        if (len == 0) {
+            return false;
+        }
+        char sep = File.separatorChar;
+        filename = filename.replace('/', sep).replace('\\', sep);
+        char c = filename.charAt(0);
+        if (!(ON_DOS || ON_NETWARE)) {
+            return (c == sep);
+        }
+        if (c == sep) {
+            // CheckStyle:MagicNumber OFF
+            if (!(ON_DOS && len > 4 && filename.charAt(1) == sep)) {
+                return false;
+            }
+            // CheckStyle:MagicNumber ON
+            int nextsep = filename.indexOf(sep, 2);
+            return nextsep > 2 && nextsep + 1 < len;
+        }
+        int colon = filename.indexOf(':');
+        return (Character.isLetter(c) && colon == 1
+                && filename.length() > 2 && filename.charAt(2) == sep)
+                || (ON_NETWARE && colon > 0);
+    }
+
+    /**
+     * Dissect the specified absolute path.
+     * @param path the path to dissect.
+     * @return String[] {root, remaining path}.
+     * @throws java.lang.NullPointerException if path is null.
+     * @since Ant 1.7
+     */
+    public String[] dissect(String path) {
+        char sep = File.separatorChar;
+        path = path.replace('/', sep).replace('\\', sep);
+
+        // make sure we are dealing with an absolute path
+        if (!isAbsolutePath(path)) {
+            throw new BuildException(path + " is not an absolute path");
+        }
+        String root = null;
+        int colon = path.indexOf(':');
+        if (colon > 0 && (ON_DOS || ON_NETWARE)) {
+
+            int next = colon + 1;
+            root = path.substring(0, next);
+            char[] ca = path.toCharArray();
+            root += sep;
+            //remove the initial separator; the root has it.
+            next = (ca[next] == sep) ? next + 1 : next;
+
+            StringBuffer sbPath = new StringBuffer();
+            // Eliminate consecutive slashes after the drive spec:
+            for (int i = next; i < ca.length; i++) {
+                if (ca[i] != sep || ca[i - 1] != sep) {
+                    sbPath.append(ca[i]);
+                }
+            }
+            path = sbPath.toString();
+        } else if (path.length() > 1 && path.charAt(1) == sep) {
+            // UNC drive
+            int nextsep = path.indexOf(sep, 2);
+            nextsep = path.indexOf(sep, nextsep + 1);
+            root = (nextsep > 2) ? path.substring(0, nextsep + 1) : path;
+            path = path.substring(root.length());
+        } else {
+            root = File.separator;
+            path = path.substring(1);
+        }
+        return new String[] {root, path};
+    }
+
+}