You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2013/12/10 00:30:03 UTC

[01/14] git commit: [flex-utilities] [refs/heads/develop] - added Available task

Updated Branches:
  refs/heads/develop 2cc92bf16 -> 1d9886ddb


added Available task


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/26b6f4ca
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/26b6f4ca
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/26b6f4ca

Branch: refs/heads/develop
Commit: 26b6f4ca61cff6edcbe04f6437aceb627466d772
Parents: c2f4d93
Author: Alex Harui <ah...@apache.org>
Authored: Sat Dec 7 21:49:08 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Sat Dec 7 21:50:43 2013 -0800

----------------------------------------------------------------------
 .../src/org/apache/flex/ant/tags/Available.as   | 83 ++++++++++++++++++++
 1 file changed, 83 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/26b6f4ca/ant_on_air/src/org/apache/flex/ant/tags/Available.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Available.as b/ant_on_air/src/org/apache/flex/ant/tags/Available.as
new file mode 100644
index 0000000..e3abf87
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Available.as
@@ -0,0 +1,83 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags
+{
+    import flash.filesystem.File;
+    
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.supportClasses.IValueTagHandler;
+    import org.apache.flex.ant.tags.supportClasses.TaskHandler;
+    
+    [Mixin]
+    public class Available extends TaskHandler implements IValueTagHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["available"] = Available;
+        }
+
+        public function Available()
+        {
+            super();
+        }
+        
+        private var _file:String;
+        private var _type:String;
+        private var _property:String;
+        private var _value:String;
+        
+        public function get value():Object
+        {
+            if (_file == null) return false;
+            
+            var file:File = new File(_file);
+            if (!file.exists)
+                return false;
+            
+            if (_type == "dir" && !file.isDirectory)
+                return false;
+            
+            return true;
+        }
+
+        override public function execute():Boolean
+        {
+            super.execute();
+            if (value)
+                if (!context.hasOwnProperty(_property))
+                    context[_property] = _value;
+            return true;
+        }
+        
+        override protected function processAttribute(name:String, value:String):void
+        {
+            if (name == "file")
+                _file = value;
+            else if (name == "type")
+                _type = value;
+            if (name == "property")
+                _property = value;
+            if (name == "value")
+                _value = value;
+        }
+        
+    }
+}
\ No newline at end of file


[14/14] git commit: [flex-utilities] [refs/heads/develop] - add support for failonerror and reporting failures

Posted by ah...@apache.org.
add support for failonerror and reporting failures


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/1d9886dd
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/1d9886dd
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/1d9886dd

Branch: refs/heads/develop
Commit: 1d9886ddbd2dc91c94ce9190a8a408a2e9990ee5
Parents: a8ab9e1
Author: Alex Harui <ah...@apache.org>
Authored: Mon Dec 9 15:27:45 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Mon Dec 9 15:27:45 2013 -0800

----------------------------------------------------------------------
 ant_on_air/src/org/apache/flex/ant/Ant.as       |  5 +++-
 .../src/org/apache/flex/ant/tags/Condition.as   | 12 ++++++--
 .../src/org/apache/flex/ant/tags/Project.as     | 28 ++++++++++++++++++-
 .../src/org/apache/flex/ant/tags/Target.as      |  9 ++++++
 .../tags/supportClasses/FileSetTaskHandler.as   | 22 +++++++++++----
 .../flex/ant/tags/supportClasses/TaskHandler.as | 10 +++++++
 ant_on_air/tests/TestTarget.as                  |  6 ++++
 ant_on_air/tests/test.xml                       | 29 ++++++++++++++++++++
 8 files changed, 111 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/1d9886dd/ant_on_air/src/org/apache/flex/ant/Ant.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/Ant.as b/ant_on_air/src/org/apache/flex/ant/Ant.as
index 0f487a3..7476daf 100644
--- a/ant_on_air/src/org/apache/flex/ant/Ant.as
+++ b/ant_on_air/src/org/apache/flex/ant/Ant.as
@@ -48,9 +48,12 @@ package org.apache.flex.ant
         private var file:File;
         
         /**
-         *   Open a file, read the XML and create ITagHandlers for every tag
+         *   Open a file, read the XML, create ITagHandlers for every tag, then process them.
+         *   When finished, check the project's status property.  If it is true then all
+         *   tasks completed successfully
          *   @param file File The file to open.
          *   @param context Object An object containing an optional targets property listing the targets to run.
+         *   @return true if XML file was processed synchronously.  If false, then add listener for Event.COMPLETE.
          */
         public function processXMLFile(file:File, context:Object = null):Boolean
         {

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/1d9886dd/ant_on_air/src/org/apache/flex/ant/tags/Condition.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Condition.as b/ant_on_air/src/org/apache/flex/ant/tags/Condition.as
index 7f94d8f..814811d 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/Condition.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Condition.as
@@ -46,19 +46,25 @@ package org.apache.flex.ant.tags
             // if the property is not already set
             if (_property && _value != null && !context.hasOwnProperty(_property))
             {
-                // get the value from the children
-                var val:Object = IValueTagHandler(getChildAt(0)).value;
+                var val:Object = computedValue;
                 if (val == "true" || val == true)
                 {
                     // set it if we should
                     if (_value != null)
                         val = _value;
                     context[_property] = val;
-                }
+                }            
             }
             return true;
         }
 
+        public function get computedValue():Object
+        {
+            // get the value from the children
+            var val:Object = IValueTagHandler(getChildAt(0)).value;
+            return val;
+        }
+        
         private var _property:String;
         private var _value:Object;
         

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/1d9886dd/ant_on_air/src/org/apache/flex/ant/tags/Project.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Project.as b/ant_on_air/src/org/apache/flex/ant/tags/Project.as
index 5136f55..22435f4 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/Project.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Project.as
@@ -52,6 +52,13 @@ package org.apache.flex.ant.tags
         {
         }
         
+        /**
+         *  true if tasks completed successfully.
+         *  Do not monitor this property to determine if the project is done executing.
+         *  This property is set to true and a failing task sets it to false.
+         */
+        public var status:Boolean;
+        
         override public function init(xml:XML, context:Object, xmlProcessor:XMLTagProcessor):void
         {
             context.project = this;
@@ -87,6 +94,8 @@ package org.apache.flex.ant.tags
 
         override public function execute():Boolean
         {
+            status = true;
+            
             if (context.targets == null)
                 context.targets == _defaultTarget;
             
@@ -100,6 +109,12 @@ package org.apache.flex.ant.tags
         
         private function executeChildren():Boolean
         {
+            if (!status)
+            {
+                dispatchEvent(new Event(Event.COMPLETE));
+                return true;                
+            }
+            
             if (current == numChildren)
                 return executeTargets();
             
@@ -116,6 +131,11 @@ package org.apache.flex.ant.tags
                         task.addEventListener(Event.COMPLETE, childCompleteHandler);
                         return false;
                     }
+                    if (!status)
+                    {
+                        dispatchEvent(new Event(Event.COMPLETE));
+                        return true;                                        
+                    }
                 }
             }
             return executeTargets();
@@ -127,7 +147,13 @@ package org.apache.flex.ant.tags
             {
                 var targetName:String = targets.shift();
                 if (!executeTarget(targetName))
-                    return false;                
+                    return false;
+                if (!status)
+                {
+                    dispatchEvent(new Event(Event.COMPLETE));
+                    return true;
+                }
+                    
             }
             if (targets.length == 0)
                 dispatchEvent(new Event(Event.COMPLETE));

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/1d9886dd/ant_on_air/src/org/apache/flex/ant/tags/Target.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Target.as b/ant_on_air/src/org/apache/flex/ant/tags/Target.as
index df47ffa..0504237 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/Target.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Target.as
@@ -111,6 +111,8 @@ package org.apache.flex.ant.tags
         
         private function continueOnToSteps():Boolean
         {
+            if (!Ant.project.status)
+                return true;
             ant.processChildren(xml, context, this);
             return processSteps();
         }
@@ -133,6 +135,8 @@ package org.apache.flex.ant.tags
                     step.addEventListener(Event.COMPLETE, completeHandler);
                     return false;
                 }
+                if (!Ant.project.status)
+                    return true;
             }
             dispatchEvent(new Event(Event.COMPLETE));
             return true;
@@ -140,6 +144,11 @@ package org.apache.flex.ant.tags
 
         private function completeHandler(event:Event):void
         {
+            if (!Ant.project.status)
+            {
+                dispatchEvent(new Event(Event.COMPLETE));
+                return;                
+            }
             processSteps();
         }
     }

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/1d9886dd/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
index c0320a8..21ffc9b 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
@@ -20,6 +20,7 @@ package org.apache.flex.ant.tags.supportClasses
 {
     import flash.filesystem.File;
     
+    import org.apache.flex.ant.Ant;
     import org.apache.flex.ant.tags.FileSet;
     
     /**
@@ -46,13 +47,24 @@ package org.apache.flex.ant.tags.supportClasses
                 var fs:FileSet = getChildAt(i) as FileSet;
                 if (fs)
                 {
-                    var list:Vector.<String> = fs.value as Vector.<String>;
-                    if (list)
+                    try
                     {
-                        var dir:File = new File(fs.dir);
-                        for each (var fileName:String in list)
+                        var list:Vector.<String> = fs.value as Vector.<String>;
+                        if (list)
                         {
-                            actOnFile(dir.nativePath, fileName);
+                            var dir:File = new File(fs.dir);
+                            for each (var fileName:String in list)
+                            {
+                                actOnFile(dir.nativePath, fileName);
+                            }
+                        }
+                    }
+                    catch (e:Error)
+                    {
+                        if (failonerror)
+                        {
+                            Ant.project.status = false;
+                            return true;
                         }
                     }
                 }

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/1d9886dd/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TaskHandler.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TaskHandler.as b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TaskHandler.as
index 910753e..d5fdcba 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TaskHandler.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TaskHandler.as
@@ -28,6 +28,8 @@ package org.apache.flex.ant.tags.supportClasses
         {
         }
         
+        public var failonerror:Boolean = true
+        
         /**
          *  Do the work.
          *  TaskHandlers lazily create their children so
@@ -39,5 +41,13 @@ package org.apache.flex.ant.tags.supportClasses
             ant.processChildren(this.xml, context, this);
             return true;
         }
+        
+        override protected function processAttribute(name:String, value:String):void
+        {
+            if (name == "failonerror")
+                failonerror = value == "true";
+            else
+                super.processAttribute(name, value);
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/1d9886dd/ant_on_air/tests/TestTarget.as
----------------------------------------------------------------------
diff --git a/ant_on_air/tests/TestTarget.as b/ant_on_air/tests/TestTarget.as
index 722986a..2570c20 100644
--- a/ant_on_air/tests/TestTarget.as
+++ b/ant_on_air/tests/TestTarget.as
@@ -28,11 +28,13 @@ package
     import org.apache.flex.ant.tags.Copy; Copy.init(null);
     import org.apache.flex.ant.tags.Delete; Delete.init(null);
     import org.apache.flex.ant.tags.Echo; Echo.init(null);
+    import org.apache.flex.ant.tags.Fail; Fail.init(null);
     import org.apache.flex.ant.tags.FileSet; FileSet.init(null);
     import org.apache.flex.ant.tags.FileSetExclude; FileSetExclude.init(null);
     import org.apache.flex.ant.tags.FileSetInclude; FileSetInclude.init(null);
     import org.apache.flex.ant.tags.IsSet; IsSet.init(null);
     import org.apache.flex.ant.tags.Mkdir; Mkdir.init(null);
+    import org.apache.flex.ant.tags.Not; Not.init(null);
     import org.apache.flex.ant.tags.OS; OS.init(null);
     import org.apache.flex.ant.tags.Project; Project.init(null);
     import org.apache.flex.ant.tags.Property; Property.init(null);
@@ -54,6 +56,10 @@ package
         
         private function completeHandler(event:Event):void
         {
+            if (Ant.project.status)
+                trace("SUCCESS!");
+            else
+                trace("FAILURE!");
             NativeApplication.nativeApplication.exit();
         }
         

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/1d9886dd/ant_on_air/tests/test.xml
----------------------------------------------------------------------
diff --git a/ant_on_air/tests/test.xml b/ant_on_air/tests/test.xml
index 8114225..df33ee7 100644
--- a/ant_on_air/tests/test.xml
+++ b/ant_on_air/tests/test.xml
@@ -48,6 +48,13 @@
         <mkdir dir="${basedir}/temp" />
         <copy file="${basedir}/test.xml" toFile="${basedir}/temp/copied.xml" />
         <available file="${basedir}/temp/copied.xml" property="copied.doesnt.exist" value="got copied" />
+        <fail message="test.xml was not copied to temp/copied.xml">
+            <condition>
+                <not>
+                    <available file="${basedir}/temp/copied.xml" />
+                </not>
+            </condition>
+        </fail>
         <echo>copied ${copied.doesnt.exist}.  Should say: got copied</echo>
         <copy toDir="${basedir}/temp">
             <fileset dir="${basedir}/../src">
@@ -56,14 +63,36 @@
             </fileset>
         </copy>
         <available file="${basedir}/temp/org/apache/flex/ant/Ant.as" property="ant.doesnt.exist" value="got copied" />
+        <fail message="Ant.as was copied to temp">
+            <condition>
+                <available file="${basedir}/temp/org/apache/flex/ant/Ant.as" />
+            </condition>
+        </fail>
         <echo>Ant.as ${ant.doesnt.exist}. Should NOT say: got copied</echo>
         <available file="${basedir}/temp/org/apache/flex/ant/tags/Project.as" property="project.doesnt.exist" value="got copied" />
+        <fail message="Project.as was not copied to temp">
+            <condition>
+                <not>
+                    <available file="${basedir}/temp/org/apache/flex/ant/tags/Project.as" />
+                </not>
+            </condition>
+        </fail>
         <echo>Project.as ${project.doesnt.exist}. Should say: got copied</echo>
         <delete file="${basedir}/temp/copied.xml" />
         <available file="${basedir}/temp/copied.xml" property="copied.doesnt.exist.after.delete" value="didn't get deleted" />
+        <fail message="temp/copied.xml was not deleted">
+            <condition>
+                <available file="${basedir}/temp/copied.xml" />
+            </condition>
+        </fail>
         <echo>copied.xml ${copied.doesnt.exist.after.delete}. Should NOT say: didn't get deleted</echo>
         <delete dir="${basedir}/temp" />
         <available file="${basedir}/temp/org/apache/flex/ant/tags/Project.as" property="project.doesnt.exist.after.delete" value="didn't get deleted" />
+        <fail message="temp/copied.xml was not deleted">
+            <condition>
+                <available file="${basedir}/temp/org/apache/flex/ant/tags/Project.as" />
+            </condition>
+        </fail>
         <echo>Project.as ${project.doesnt.exist.after.delete}. Should NOT say: didn't get deleted</echo>
 	</target>
 


[04/14] port DirectoryScanner from Ant code base and hook up FileSet to it

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/TokenizedPath.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/TokenizedPath.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/TokenizedPath.as
new file mode 100644
index 0000000..f9dc3d2
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/TokenizedPath.as
@@ -0,0 +1,221 @@
+/*
+*  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.flex.ant.tags.filesetClasses
+{
+    import flash.filesystem.File;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.filesetClasses.FileUtils;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.BuildException;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.IOException;
+    
+    /**
+     * Ported from org.apache.tools.ant.types.selectors.TokenizedPath.java on 12/3/13;
+     * Container for a path that has been split into its components.
+     * @since 1.8.0
+     */
+    public class TokenizedPath {
+        
+        /**
+         * Instance that holds no tokens at all.
+         */
+        public static const EMPTY_PATH:TokenizedPath =
+            new TokenizedPath("").init("", new Vector.<String>());
+        
+        /** Helper. */
+        private static const FILE_UTILS:FileUtils = FileUtils.getFileUtils();
+        /** Helper. */
+        /** iterations for case-sensitive scanning. */
+        private static const CS_SCAN_ONLY:Vector.<Boolean> = new Vector.<Boolean>([true]);
+        /** iterations for non-case-sensitive scanning. */
+        private static const CS_THEN_NON_CS:Vector.<Boolean> = new Vector.<Boolean>([true, false]);
+        
+        private var path:String;
+        private var tokenizedPath:Vector.<String>;
+        
+        /**
+         * Initialize the TokenizedPath by parsing it. 
+         * @param path The path to tokenize. Must not be
+         *                <code>null</code>.
+         */
+        public function TokenizedPath(path:String) {
+            init(path, SelectorUtils.tokenizePathAsArray(path));
+        }
+        
+        /**
+         * Creates a new path as a child of another path.
+         *
+         * @param parent the parent path
+         * @param child the child, must not contain the file separator
+         */
+        public function initAsChild(parent:TokenizedPath, child:String):TokenizedPath {
+            if (parent.path.length > 0
+                && parent.path.charAt(parent.path.length - 1)
+                != File.separator) {
+                path = parent.path + File.separator + child;
+            } else {
+                path = parent.path + child;
+            }
+            tokenizedPath = parent.tokenizedPath.slice();
+            tokenizedPath.push(child);
+            return this;
+        }
+        
+        /* package */ public function init(path:String, tokens:Vector.<String>):TokenizedPath {
+            this.path = path;
+            this.tokenizedPath = tokens;
+            return this;
+        }
+        
+        /**
+         * @return The original path String
+         */
+        public function toString():String {
+            return path;
+        }
+        
+        /**
+         * The depth (or length) of a path.
+         */
+        public function depth():int {
+            return tokenizedPath.length;
+        }
+        
+        /* package */ public function getTokens():Vector.<String> {
+            return tokenizedPath;
+        }
+        
+        /**
+         * From <code>base</code> traverse the filesystem in order to find
+         * a file that matches the given name.
+         *
+         * @param base base File (dir).
+         * @param cs whether to scan case-sensitively.
+         * @return File object that points to the file in question or null.
+         */
+        public function findFile(base:File, cs:Boolean):File {
+            var tokens:Vector.<String> = tokenizedPath;
+            if (FileUtils.isAbsolutePath(path)) {
+                if (base == null) {
+                    var s:Vector.<String> = FILE_UTILS.dissect(path);
+                    base = new File(s[0]);
+                    tokens = SelectorUtils.tokenizePathAsArray(s[1]);
+                } else {
+                    var f:File = FILE_UTILS.normalize(path);
+                    var n:String = FILE_UTILS.removeLeadingPath(base, f);
+                    if (n == f.nativePath) {
+                        //removing base from path yields no change; path
+                        //not child of base
+                        return null;
+                    }
+                    tokens = SelectorUtils.tokenizePathAsArray(n);
+                }
+            }
+            return TokenizedPath.findFile(base, tokens, cs);
+        }
+        
+
+        /**
+         * Do we have to traverse a symlink when trying to reach path from
+         * basedir?
+         * @param base base File (dir).
+         */
+        public function isSymlink(base:File):Boolean {
+            for (var i:int = 0; i < tokenizedPath.length; i++) {
+                try {
+                    if ((base != null
+                        && new File(base.nativePath + File.separator + tokenizedPath[i]).isSymbolicLink)
+                        ||
+                        (base == null
+                            && new File(tokenizedPath[i]).isSymbolicLink)
+                    ) {
+                        return true;
+                    }
+                    base = new File(base + File.separator + tokenizedPath[i]);
+                } catch (ioe:IOException) {
+                    var msg:String = "IOException caught while checking "
+                        + "for links, couldn't get canonical path!";
+                    // will be caught and redirected to Ant's logging system
+                    Ant.ant.output(msg);
+                }
+            }
+            return false;
+        }
+        
+        /**
+         * true if the original paths are equal.
+         */
+        public function equals(o:Object):Boolean {
+            return o is TokenizedPath
+            && path == TokenizedPath(o).path;
+        }
+
+        /**
+         * From <code>base</code> traverse the filesystem in order to find
+         * a file that matches the given stack of names.
+         *
+         * @param base base File (dir) - must not be null.
+         * @param pathElements array of path elements (dirs...file).
+         * @param cs whether to scan case-sensitively.
+         * @return File object that points to the file in question or null.
+         */
+        private static function findFile(base:File, pathElements:Vector.<String>,
+            cs:Boolean):File {
+                for (var current:int = 0; current < pathElements.length; current++) {
+                    if (!base.isDirectory) {
+                        return null;
+                    }
+                    var arr:Array = base.getDirectoryListing();
+                    var arr2:Array = [];
+                    for each (var f:File in arr)
+                    arr2.push(f.nativePath);
+                    var files:Vector.<String> = Vector.<String>(arr2);
+                    if (files == null) {
+                        throw new BuildException("IO error scanning directory "
+                            + base.nativePath);
+                    }
+                    var found:Boolean = false;
+                    var matchCase:Vector.<Boolean> = cs ? CS_SCAN_ONLY : CS_THEN_NON_CS;
+                    for (var i:int = 0; !found && i < matchCase.length; i++) {
+                        for (var j:int = 0; !found && j < files.length; j++) {
+                            if (matchCase[i]
+                                ? files[j] == pathElements[current]
+                                : files[j].toUpperCase() == pathElements[current].toUpperCase()) {
+                                base = new File(base.nativePath + File.separator + files[j]);
+                                found = true;
+                            }
+                        }
+                    }
+                    if (!found) {
+                        return null;
+                    }
+                }
+                return pathElements.length == 0 && !base.isDirectory ? null : base;
+            }
+
+        /**
+         * Creates a TokenizedPattern from the same tokens that make up
+         * this path.
+         */
+        public function toPattern():TokenizedPattern {
+            return new TokenizedPattern(path).init(path, tokenizedPath); 
+        }
+        
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/TokenizedPattern.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/TokenizedPattern.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/TokenizedPattern.as
new file mode 100644
index 0000000..3055dbb
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/TokenizedPattern.as
@@ -0,0 +1,173 @@
+/*
+*  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.flex.ant.tags.filesetClasses
+{
+    import flash.filesystem.File;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.IllegalStateException;
+    
+    /**
+     * Ported from org.apache.tools.ant.types.selector.TokenizedPattern.java on 12/3/13. 
+     * Provides reusable path pattern matching.  PathPattern is preferable
+     * to equivalent SelectorUtils methods if you need to execute multiple
+     * matching with the same pattern because here the pattern itself will
+     * be parsed only once.
+     * @see SelectorUtils#matchPath(String, String)
+     * @see SelectorUtils#matchPath(String, String, boolean)
+     * @since 1.8.0
+     */
+    public class TokenizedPattern {
+        
+        /**
+         * Instance that holds no tokens at all.
+         */
+        public static const EMPTY_PATTERN:TokenizedPattern =
+            new TokenizedPattern("").init("", new Vector.<String>());
+        
+        private var pattern:String;
+        private var tokenizedPattern:Vector.<String>;
+        
+        /**
+         * Initialize the PathPattern by parsing it.
+         * @param pattern The pattern to match against. Must not be
+         *                <code>null</code>.
+         */
+        public function TokenizedPattern(pattern:String) {
+            init(pattern, SelectorUtils.tokenizePathAsArray(pattern));
+        }
+        
+        public function init(pattern:String, tokens:Vector.<String>):TokenizedPattern {
+            this.pattern = pattern;
+            this.tokenizedPattern = tokens;
+            return this;
+        }
+        
+        /**
+         * Tests whether or not a given path matches a given pattern.
+         *
+         * @param path    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 function matchPath(path:TokenizedPath, isCaseSensitive:Boolean):Boolean {
+            return SelectorUtils.matchPathVectors(tokenizedPattern, path.getTokens(),
+                isCaseSensitive);
+        }
+        
+        /**
+         * Tests whether or not this pattern matches the start of
+         * a path.
+         */
+        public function matchStartOf(path:TokenizedPath,
+            caseSensitive:Boolean):Boolean {
+                return SelectorUtils.matchPatternStartVectors(tokenizedPattern,
+                    path.getTokens(), caseSensitive);
+            }
+        
+        /**
+         * @return The pattern String
+         */
+        public function toString():String {
+            return pattern;
+        }
+        
+        public function getPattern():String {
+            return pattern;
+        }
+        
+        /**
+         * true if the original patterns are equal.
+         */
+        public function equals(o:Object):Boolean {
+            return o is TokenizedPattern
+            && pattern == TokenizedPattern(o).pattern;
+        }
+        
+        /**
+         * The depth (or length) of a pattern.
+         */
+        public function depth():int {
+            return tokenizedPattern.length;
+        }
+        
+        /**
+         * Does the tokenized pattern contain the given string?
+         */
+        public function containsPattern(pat:String):Boolean {
+            for (var i:int = 0; i < tokenizedPattern.length; i++) {
+                if (tokenizedPattern[i] == pat) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        /**
+         * Returns a new TokenizedPath where all tokens of this pattern to
+         * the right containing wildcards have been removed
+         * @return the leftmost part of the pattern without wildcards
+         */
+        public function rtrimWildcardTokens():TokenizedPath {
+            var sb:String = "";
+            var newLen:int = 0;
+            for (; newLen < tokenizedPattern.length; newLen++) {
+                if (SelectorUtils.hasWildcards(tokenizedPattern[newLen])) {
+                    break;
+                }
+                if (newLen > 0
+                    && sb.charAt(sb.length - 1) != File.separator) {
+                    sb += File.separator;
+                }
+                sb += tokenizedPattern[newLen];
+            }
+            if (newLen == 0) {
+                return TokenizedPath.EMPTY_PATH;
+            }
+            var newPats:Vector.<String> = tokenizedPattern.slice(0, newLen);
+            return new TokenizedPath("").init(sb, newPats);
+        }
+        
+        /**
+         * true if the last token equals the given string.
+         */
+        public function endsWith(s:String):Boolean {
+            return tokenizedPattern.length > 0
+                && tokenizedPattern[tokenizedPattern.length - 1] ==  s;
+        }
+        
+        /**
+         * Returns a new pattern without the last token of this pattern.
+         */
+        public function withoutLastToken():TokenizedPattern {
+            if (tokenizedPattern.length == 0) {
+                throw new IllegalStateException("cant strip a token from nothing");
+            } else if (tokenizedPattern.length == 1) {
+                return EMPTY_PATTERN;
+            } else {
+                var toStrip:String = tokenizedPattern[tokenizedPattern.length - 1];
+                var index:int = pattern.lastIndexOf(toStrip);
+                var tokens:Vector.<String> = tokenizedPattern.slice(0, tokenizedPattern.length - 1);
+                return new TokenizedPattern("").init(pattern.substring(0, index), tokens);
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/BuildException.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/BuildException.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/BuildException.as
new file mode 100644
index 0000000..6be2bc5
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/BuildException.as
@@ -0,0 +1,28 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags.filesetClasses.exceptions
+{
+    public class BuildException extends Error
+    {
+        public function BuildException(message:String)
+        {
+            super(message);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/IOException.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/IOException.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/IOException.as
new file mode 100644
index 0000000..0eb329d
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/IOException.as
@@ -0,0 +1,28 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags.filesetClasses.exceptions
+{
+    public class IOException extends Error
+    {
+        public function IOException(message:String)
+        {
+            super(message);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/IllegalStateException.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/IllegalStateException.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/IllegalStateException.as
new file mode 100644
index 0000000..5d00f7f
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/IllegalStateException.as
@@ -0,0 +1,28 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags.filesetClasses.exceptions
+{
+    public class IllegalStateException extends Error
+    {
+        public function IllegalStateException(message:String)
+        {
+            super(message);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/UnsupportedOperationException.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/UnsupportedOperationException.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/UnsupportedOperationException.as
new file mode 100644
index 0000000..b885fac
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/exceptions/UnsupportedOperationException.as
@@ -0,0 +1,28 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags.filesetClasses.exceptions
+{
+    public class UnsupportedOperationException extends Error
+    {
+        public function UnsupportedOperationException()
+        {
+            super("UnsupportedOperationException");
+        }
+    }
+}
\ No newline at end of file


[11/14] git commit: [flex-utilities] [refs/heads/develop] - add mkdir and delete tasks

Posted by ah...@apache.org.
add mkdir and delete tasks


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/a4728f76
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/a4728f76
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/a4728f76

Branch: refs/heads/develop
Commit: a4728f7629ddda6778a41e7c3cb655e61f759b44
Parents: 00bf3f9
Author: Alex Harui <ah...@apache.org>
Authored: Mon Dec 9 14:01:26 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Mon Dec 9 14:01:26 2013 -0800

----------------------------------------------------------------------
 ant_on_air/src/AntClasses.as                    |  2 +
 .../src/org/apache/flex/ant/tags/Delete.as      | 88 ++++++++++++++++++++
 .../src/org/apache/flex/ant/tags/Mkdir.as       | 60 +++++++++++++
 3 files changed, 150 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a4728f76/ant_on_air/src/AntClasses.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/AntClasses.as b/ant_on_air/src/AntClasses.as
index 3180f70..cc869ea 100644
--- a/ant_on_air/src/AntClasses.as
+++ b/ant_on_air/src/AntClasses.as
@@ -27,11 +27,13 @@ package
             import org.apache.flex.ant.tags.Available; Available;
             import org.apache.flex.ant.tags.Condition; Condition;
             import org.apache.flex.ant.tags.Copy; Copy;
+            import org.apache.flex.ant.tags.Delete; Delete;
             import org.apache.flex.ant.tags.Echo; Echo;
             import org.apache.flex.ant.tags.FileSet; FileSet;
             import org.apache.flex.ant.tags.FileSetExclude; FileSetExclude;
             import org.apache.flex.ant.tags.FileSetInclude; FileSetInclude;
             import org.apache.flex.ant.tags.IsSet; IsSet;
+            import org.apache.flex.ant.tags.Mkdir; Mkdir;
             import org.apache.flex.ant.tags.OS; OS;
             import org.apache.flex.ant.tags.Property; Property;
         }

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a4728f76/ant_on_air/src/org/apache/flex/ant/tags/Delete.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Delete.as b/ant_on_air/src/org/apache/flex/ant/tags/Delete.as
new file mode 100644
index 0000000..40f697a
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Delete.as
@@ -0,0 +1,88 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags
+{
+    import flash.filesystem.File;
+    
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.supportClasses.FileSetTaskHandler;
+    
+    [Mixin]
+    public class Delete extends FileSetTaskHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["delete"] = Delete;
+        }
+
+        public function Delete()
+        {
+            super();
+        }
+        
+        private var fileName:String;
+        private var dirName:String;
+        
+        override protected function processAttribute(name:String, value:String):void
+        {
+            if (name == "file")
+                fileName = value;
+            else if (name == "dir")
+                dirName = value;
+            else
+                super.processAttribute(name, value);
+        }
+
+        override protected function actOnFile(dir:String, fileName:String):void
+        {
+            var srcName:String;
+            if (dir)
+                srcName = dir + File.separator + fileName;
+            else
+                srcName = fileName;
+            var delFile:File = File.applicationDirectory.resolvePath(srcName);
+            if (delFile.isDirectory)
+                delFile.deleteDirectory(true);
+            else
+                delFile.deleteFile();
+        }
+        
+        override public function execute():Boolean
+        {
+            var retVal:Boolean = super.execute();
+            if (numChildren > 0)
+                return retVal;
+            
+            if (fileName)
+            {
+                var delFile:File = File.applicationDirectory.resolvePath(fileName);
+                delFile.deleteFile();
+            }
+            else if (dirName)
+            {
+                var delDir:File = File.applicationDirectory.resolvePath(dirName);
+                delDir.deleteDirectory(true);
+            }            
+            return true;
+        }
+        
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a4728f76/ant_on_air/src/org/apache/flex/ant/tags/Mkdir.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Mkdir.as b/ant_on_air/src/org/apache/flex/ant/tags/Mkdir.as
new file mode 100644
index 0000000..111b0aa
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Mkdir.as
@@ -0,0 +1,60 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags
+{
+    import flash.filesystem.File;
+    
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.supportClasses.TaskHandler;
+    
+    [Mixin]
+    public class Mkdir extends TaskHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["mkdir"] = Mkdir;
+        }
+
+        public function Mkdir()
+        {
+            super();
+        }
+        
+        private var _dir:String;
+        
+        override public function execute():Boolean
+        {
+            super.execute();
+            
+            var dir:File = new File(_dir);
+            dir.createDirectory();
+            
+            return true;
+        }
+        
+        override protected function processAttribute(name:String, value:String):void
+        {
+            if (name == "dir")
+                _dir = value;
+       }
+        
+    }
+}
\ No newline at end of file


[13/14] git commit: [flex-utilities] [refs/heads/develop] - add and tags

Posted by ah...@apache.org.
add <not> and <fail> tags


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/a8ab9e14
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/a8ab9e14
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/a8ab9e14

Branch: refs/heads/develop
Commit: a8ab9e1404e1e4da98050d67ca0e9a0d49f4ac9d
Parents: 3a3f232
Author: Alex Harui <ah...@apache.org>
Authored: Mon Dec 9 15:26:53 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Mon Dec 9 15:26:53 2013 -0800

----------------------------------------------------------------------
 ant_on_air/src/AntClasses.as                    |  2 +
 ant_on_air/src/org/apache/flex/ant/tags/Fail.as | 78 ++++++++++++++++++++
 ant_on_air/src/org/apache/flex/ant/tags/Not.as  | 56 ++++++++++++++
 3 files changed, 136 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a8ab9e14/ant_on_air/src/AntClasses.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/AntClasses.as b/ant_on_air/src/AntClasses.as
index cc869ea..4e7491c 100644
--- a/ant_on_air/src/AntClasses.as
+++ b/ant_on_air/src/AntClasses.as
@@ -29,11 +29,13 @@ package
             import org.apache.flex.ant.tags.Copy; Copy;
             import org.apache.flex.ant.tags.Delete; Delete;
             import org.apache.flex.ant.tags.Echo; Echo;
+            import org.apache.flex.ant.tags.Fail; Fail;
             import org.apache.flex.ant.tags.FileSet; FileSet;
             import org.apache.flex.ant.tags.FileSetExclude; FileSetExclude;
             import org.apache.flex.ant.tags.FileSetInclude; FileSetInclude;
             import org.apache.flex.ant.tags.IsSet; IsSet;
             import org.apache.flex.ant.tags.Mkdir; Mkdir;
+            import org.apache.flex.ant.tags.Not; Not;
             import org.apache.flex.ant.tags.OS; OS;
             import org.apache.flex.ant.tags.Property; Property;
         }

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a8ab9e14/ant_on_air/src/org/apache/flex/ant/tags/Fail.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Fail.as b/ant_on_air/src/org/apache/flex/ant/tags/Fail.as
new file mode 100644
index 0000000..1016b62
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Fail.as
@@ -0,0 +1,78 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags
+{
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.supportClasses.IValueTagHandler;
+    import org.apache.flex.ant.tags.supportClasses.TaskHandler;
+    import org.apache.flex.xml.ITextTagHandler;
+    
+    [Mixin]
+    public class Fail extends TaskHandler implements ITextTagHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["fail"] = Fail;
+        }
+
+        public function Fail()
+        {
+            super();
+        }
+        
+        private var text:String;
+        
+        public function setText(text:String):void
+        {
+            this.text = text;    
+        }
+        
+        override protected function processAttribute(name:String, value:String):void
+        {
+            if (name == "message")
+                text = value;
+            else
+                super.processAttribute(name, value);
+        }
+
+        override public function execute():Boolean
+        {
+            super.execute();
+            if (numChildren == 1)
+            {
+                var child:Condition = getChildAt(0) as Condition;
+                if (child)
+                {
+                    child.execute();
+                    var val:Object = child.computedValue;
+                    if (!(val == "true" || val == true))
+                    {
+                        return true;
+                    }
+                }
+            }
+            if (text)
+                ant.output(ant.getValue(text, context));
+            Ant.project.status = false;
+            return true;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a8ab9e14/ant_on_air/src/org/apache/flex/ant/tags/Not.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Not.as b/ant_on_air/src/org/apache/flex/ant/tags/Not.as
new file mode 100644
index 0000000..3ea0b7e
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Not.as
@@ -0,0 +1,56 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags
+{
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.supportClasses.IValueTagHandler;
+    import org.apache.flex.ant.tags.supportClasses.ParentTagHandler;
+    
+    [Mixin]
+    public class Not extends ParentTagHandler implements IValueTagHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["not"] = Not;
+        }
+
+        public function Not()
+        {
+            super();
+        }
+        
+        public function get value():Object
+        {
+            ant.processChildren(xml, context, this);
+            if (numChildren == 1)
+            {
+                var value:IValueTagHandler = getChildAt(0) as IValueTagHandler;
+                // get the value from the children
+                var val:Object = IValueTagHandler(value).value;
+                if (!(val == "true" || val == true))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+}
\ No newline at end of file


[07/14] git commit: [flex-utilities] [refs/heads/develop] - port DirectoryScanner from Ant code base and hook up FileSet to it

Posted by ah...@apache.org.
port DirectoryScanner from Ant code base and hook up FileSet to it


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/3a58a60e
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/3a58a60e
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/3a58a60e

Branch: refs/heads/develop
Commit: 3a58a60e9ad01f5bdf26806bd17f92c409fb360d
Parents: 2cc92bf
Author: Alex Harui <ah...@apache.org>
Authored: Sat Dec 7 21:46:49 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Sat Dec 7 21:50:43 2013 -0800

----------------------------------------------------------------------
 .../src/org/apache/flex/ant/tags/FileSet.as     |   86 +
 .../org/apache/flex/ant/tags/FileSetExclude.as  |   40 +
 .../org/apache/flex/ant/tags/FileSetInclude.as  |   40 +
 .../flex/ant/tags/filesetClasses/Character.as   |   34 +
 .../ant/tags/filesetClasses/CollectionUtils.as  |   41 +
 .../flex/ant/tags/filesetClasses/DataType.as    |  330 ++++
 .../ant/tags/filesetClasses/DirectoryScanner.as | 1764 ++++++++++++++++++
 .../ant/tags/filesetClasses/FileProvider.as     |   27 +
 .../ant/tags/filesetClasses/FileResource.as     |  146 ++
 .../ant/tags/filesetClasses/FileSelector.as     |   27 +
 .../flex/ant/tags/filesetClasses/FileUtils.as   |  657 +++++++
 .../ant/tags/filesetClasses/PathTokenizer.as    |  118 ++
 .../flex/ant/tags/filesetClasses/Reference.as   |  106 ++
 .../flex/ant/tags/filesetClasses/Resource.as    |  349 ++++
 .../ant/tags/filesetClasses/SelectorUtils.as    |  638 +++++++
 .../ant/tags/filesetClasses/StringTokenizer.as  |   68 +
 .../ant/tags/filesetClasses/TokenizedPath.as    |  221 +++
 .../ant/tags/filesetClasses/TokenizedPattern.as |  173 ++
 .../filesetClasses/exceptions/BuildException.as |   28 +
 .../filesetClasses/exceptions/IOException.as    |   28 +
 .../exceptions/IllegalStateException.as         |   28 +
 .../exceptions/UnsupportedOperationException.as |   28 +
 22 files changed, 4977 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as b/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as
new file mode 100644
index 0000000..4a01395
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as
@@ -0,0 +1,86 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags
+{
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.filesetClasses.DirectoryScanner;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.BuildException;
+    import org.apache.flex.ant.tags.supportClasses.IValueTagHandler;
+    import org.apache.flex.ant.tags.supportClasses.NamedTagHandler;
+    import org.apache.flex.ant.tags.supportClasses.ParentTagHandler;
+    
+    [Mixin]
+    public class FileSet extends ParentTagHandler implements IValueTagHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["fileset"] = FileSet;
+        }
+
+        public function FileSet()
+        {
+            super();
+        }
+        
+        private var _dir:String;
+        
+        public function get dir():String
+        {
+            return _dir;
+        }
+        
+        private var _value:Vector.<String>;
+        
+        public function get value():Object
+        {
+            if (_value) return _value;
+            
+            var ds:DirectoryScanner = new DirectoryScanner();
+            var n:int = numChildren;
+            var includes:Vector.<String> = new Vector.<String>();
+            var excludes:Vector.<String> = new Vector.<String>();
+            for (var i:int = 0; i < n; i++)
+            {
+                var tag:NamedTagHandler = getChildAt(i) as NamedTagHandler;
+                if (tag is FileSetInclude)
+                    includes.push(tag.name);
+                else if (tag is FileSetExclude)
+                    excludes.push(tag.name);
+                else
+                    throw new BuildException("Unsupported Tag at index " + i);
+            }
+            ds.setIncludes(includes);
+            ds.setExcludes(excludes);
+            if (_dir != null)
+                ds.setBasedir(_dir);
+            ds.scan();
+            _value = ds.getIncludedFiles();
+            return _value;
+        }
+        
+        override protected function processAttribute(name:String, value:String):void
+        {
+            if (name == "dir")
+                _dir = value;
+        }
+        
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/FileSetExclude.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/FileSetExclude.as b/ant_on_air/src/org/apache/flex/ant/tags/FileSetExclude.as
new file mode 100644
index 0000000..e2c0f02
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/FileSetExclude.as
@@ -0,0 +1,40 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags
+{
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.supportClasses.NamedTagHandler;
+    
+    [Mixin]
+    public class FileSetExclude extends NamedTagHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["exclude"] = FileSetExclude;
+        }
+
+        public function FileSetExclude()
+        {
+            super();
+        }
+                
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/FileSetInclude.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/FileSetInclude.as b/ant_on_air/src/org/apache/flex/ant/tags/FileSetInclude.as
new file mode 100644
index 0000000..8c6f98f
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/FileSetInclude.as
@@ -0,0 +1,40 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags
+{
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.supportClasses.NamedTagHandler;
+    
+    [Mixin]
+    public class FileSetInclude extends NamedTagHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["include"] = FileSetInclude;
+        }
+
+        public function FileSetInclude()
+        {
+            super();
+        }
+                
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Character.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Character.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Character.as
new file mode 100644
index 0000000..d2b6b87
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Character.as
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags.filesetClasses
+{
+    public class Character
+    {
+        public function Character()
+        {
+            super();
+        }
+        
+        public static function isLetter(c:String):Boolean
+        {
+            return "a" <= c && c <= "z" ||
+                "A" <= c && c <= "Z";
+        }        
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/CollectionUtils.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/CollectionUtils.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/CollectionUtils.as
new file mode 100644
index 0000000..0717a4e
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/CollectionUtils.as
@@ -0,0 +1,41 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags.filesetClasses
+{
+    public class CollectionUtils
+    {
+        public function CollectionUtils()
+        {
+            super();
+        }
+        
+        private static var target:String;
+        
+        private static function callback(item:String, index:int, list:Vector.<String>):Boolean
+        {
+            return CollectionUtils.target == item;
+        }
+        
+        public static function frequency(list:Vector.<String>, c:String):int
+        {
+            target = c;
+            return list.filter(callback).length;
+        }        
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DataType.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DataType.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DataType.as
new file mode 100644
index 0000000..1efa665
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DataType.as
@@ -0,0 +1,330 @@
+/*
+*  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.flex.ant.tags.filesetClasses
+{
+    import flash.system.ApplicationDomain;
+    import flash.utils.getQualifiedClassName;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.Project;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.BuildException;
+    
+    /**
+     * Ported from org.apache.tools.ant.types.DataType.java on 12/3/13 
+     * Base class for those classes that can appear inside the build file
+     * as stand alone data types.
+     *
+     * <p>This class handles the common description attribute and provides
+     * a default implementation for reference handling and checking for
+     * circular references that is appropriate for types that can not be
+     * nested inside elements of the same type (i.e. &lt;patternset&gt;
+     * but not &lt;path&gt;).</p>
+     *
+     */
+    public class DataType 
+    {
+        // CheckStyle:VisibilityModifier OFF
+        
+        /**
+         * Value to the refid attribute.
+         *
+         * @deprecated since 1.7.
+         *             The user should not be directly referencing
+         *             variable. Please use {@link #getRefid} instead.
+         */
+        protected var ref:Reference;
+        
+        /**
+         * Are we sure we don't hold circular references?
+         *
+         * <p>Subclasses are responsible for setting this value to false
+         * if we'd need to investigate this condition (usually because a
+         * child element has been added that is a subclass of
+         * DataType).</p>
+         *
+         * @deprecated since 1.7.
+         *             The user should not be directly referencing
+         *             variable. Please use {@link #setChecked} or
+         *             {@link #isChecked} instead.
+         */
+        protected var checked:Boolean = true;
+        // CheckStyle:VisibilityModifier ON
+        
+        /**
+         * Has the refid attribute of this element been set?
+         * @return true if the refid attribute has been set
+         */
+        public function isReference():Boolean  
+        {
+            return ref != null;
+        }
+        
+        /**
+         * Set the value of the refid attribute.
+         *
+         * <p>Subclasses may need to check whether any other attributes
+         * have been set as well or child elements have been created and
+         * thus override this method. if they do the must call
+         * <code>super.setRefid</code>.</p>
+         * @param ref the reference to use
+         */
+        public function setRefid(ref:Reference):void
+        {
+            this.ref = ref;
+            checked = false;
+        }
+        
+        /**
+         * Gets as descriptive as possible a name used for this datatype instance.
+         * @return <code>String</code> name.
+         */
+        protected function getDataTypeName():String
+        {
+            return "DataType";
+        }
+                
+        /**
+         * Check to see whether any DataType we hold references to is
+         * included in the Stack (which holds all DataType instances that
+         * directly or indirectly reference this instance, including this
+         * instance itself).
+         *
+         * <p>If one is included, throw a BuildException created by {@link
+         * #circularReference circularReference}.</p>
+         *
+         * <p>This implementation is appropriate only for a DataType that
+         * cannot hold other DataTypes as children.</p>
+         *
+         * <p>The general contract of this method is that it shouldn't do
+         * anything if {@link #checked <code>checked</code>} is true and
+         * set it to true on exit.</p>
+         * @param stack the stack of references to check.
+         * @param project the project to use to dereference the references.
+         * @throws BuildException on error.
+         */
+        protected function dieOnCircularReference(stack:Vector.<String> = null, project:Project = null):void
+        {
+            if (!project)
+                project = Ant.project;
+            
+            if (!stack)
+                stack = new Vector.<String>();
+            
+            if (checked || !isReference()) {
+                return;
+            }
+            var o:Object = ref.getReferencedObject(project);
+            
+            if (o is DataType) {                
+                if (stack.indexOf(o) != -1) {
+                    throw circularReference();
+                } else {
+                    stack.push(o);
+                    DataType(o).dieOnCircularReference(Vector.<String>([id]), project);
+                    stack.pop();
+                }
+            }
+            checked = true;
+        }
+        
+        /**
+         * Allow DataTypes outside org.apache.tools.ant.types to indirectly call
+         * dieOnCircularReference on nested DataTypes.
+         * @param dt the DataType to check.
+         * @param stk the stack of references to check.
+         * @param p the project to use to dereference the references.
+         * @throws BuildException on error.
+         * @since Ant 1.7
+         */
+        public static function invokeCircularReferenceCheck(dt:DataType, stk:Vector.<String>,
+             p:Project):void 
+        {
+                dt.dieOnCircularReference(stk, p);
+        }
+        
+        /**
+         * Allow DataTypes outside org.apache.tools.ant.types to indirectly call
+         * dieOnCircularReference on nested DataTypes.
+         *
+         * <p>Pushes dt on the stack, runs dieOnCircularReference and pops
+         * it again.</p>
+         * @param dt the DataType to check.
+         * @param stk the stack of references to check.
+         * @param p the project to use to dereference the references.
+         * @throws BuildException on error.
+         * @since Ant 1.8.0
+         */
+        public static function pushAndInvokeCircularReferenceCheck(dt:DataType,
+            stk:Vector.<String>,
+            p:Project):void 
+        {
+                stk.push(dt);
+                dt.dieOnCircularReference(stk, p);
+                stk.pop();
+        }
+        
+        /**
+         * Performs the check for circular references and returns the
+         * referenced object.
+         * @param p the Ant Project instance against which to resolve references.
+         * @return the dereferenced object.
+         * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
+         * @since Ant 1.7
+         */
+        protected function getCheckedRef(p:Project = null):Object 
+        {
+            if (!p)
+                p = Ant.project;
+            return getCheckedRefActual(Class(ApplicationDomain.currentDomain.getDefinition(getQualifiedClassName(this))), 
+                    getDataTypeName(), p);
+        }
+
+        /**
+         * Performs the check for circular references and returns the
+         * referenced object.  This version allows the fallback Project instance to be specified.
+         * @param requiredClass the class that this reference should be a subclass of.
+         * @param dataTypeName  the name of the datatype that the reference should be
+         *                      (error message use only).
+         * @param project       the fallback Project instance for dereferencing.
+         * @return the dereferenced object.
+         * @throws BuildException if the reference is invalid (circular ref, wrong class, etc),
+         *                        or if <code>project</code> is <code>null</code>.
+         * @since Ant 1.7
+         */
+        protected function getCheckedRefActual(requiredClass:Class,
+            dataTypeName:String, project:Project):Object {
+                if (project == null) {
+                    throw new BuildException("No Project specified");
+                }
+                dieOnCircularReference(null, project);
+                var o:Object = ref.getReferencedObject(project);
+                var oClass:Class = ApplicationDomain.currentDomain.getDefinition(getQualifiedClassName(o)) as Class;
+                if (!(requiredClass is oClass)) {
+                    Ant.log("Class " + oClass + " is not a subclass of " + requiredClass,
+                        Project.MSG_VERBOSE);
+                    var msg:String = ref.getRefId() + " doesn\'t denote a " + dataTypeName;
+                    throw new BuildException(msg);
+                }
+                return o;
+            }
+
+        /**
+         * Creates an exception that indicates that refid has to be the
+         * only attribute if it is set.
+         * @return the exception to throw
+         */
+        protected function tooManyAttributes():BuildException 
+        {
+            return new BuildException("You must not specify more than one "
+                + "attribute when using refid");
+        }
+        
+        /**
+         * Creates an exception that indicates that this XML element must
+         * not have child elements if the refid attribute is set.
+         * @return the exception to throw
+         */
+        protected function noChildrenAllowed():BuildException 
+        {
+            return new BuildException("You must not specify nested elements "
+                + "when using refid");
+        }
+        
+        /**
+         * Creates an exception that indicates the user has generated a
+         * loop of data types referencing each other.
+         * @return the exception to throw
+         */
+        protected function circularReference():BuildException
+        {
+            return new BuildException("This data type contains a circular "
+                + "reference.");
+        }
+        
+        /**
+         * The flag that is used to indicate that circular references have been checked.
+         * @return true if circular references have been checked
+         */
+        protected function isChecked():Boolean 
+        {
+            return checked;
+        }
+        
+        /**
+         * Set the flag that is used to indicate that circular references have been checked.
+         * @param checked if true, if circular references have been checked
+         */
+        protected function setChecked(checked:Boolean):void 
+        {
+            this.checked = checked;
+        }
+        
+        /**
+         * get the reference set on this object
+         * @return the reference or null
+         */
+        public function getRefid():Reference 
+        {
+            return ref;
+        }
+        
+        /**
+         * check that it is ok to set attributes, i.e that no reference is defined
+         * @since Ant 1.6
+         * @throws BuildException if not allowed
+         */
+        protected function checkAttributesAllowed():void  
+        {
+            if (isReference()) {
+                throw tooManyAttributes();
+            }
+        }
+        
+        /**
+         * check that it is ok to add children, i.e that no reference is defined
+         * @since Ant 1.6
+         * @throws BuildException if not allowed
+         */
+        protected function checkChildrenAllowed():void 
+        {
+            if (isReference()) {
+                throw noChildrenAllowed();
+            }
+        }
+        
+        /**
+         * Basic DataType toString().
+         * @return this DataType formatted as a String.
+         */
+        public function toString():String {
+            var d:String = getDescription();
+            return d == null ? getDataTypeName() : getDataTypeName() + " " + d;
+        }
+        
+        /**
+         * Basic description
+         */
+        public function getDescription():String
+        {
+            return null;
+        }
+        
+        public var id:String;
+    }
+}   


[08/14] git commit: [flex-utilities] [refs/heads/develop] - handle async tasks

Posted by ah...@apache.org.
handle async tasks


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/eef49ca0
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/eef49ca0
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/eef49ca0

Branch: refs/heads/develop
Commit: eef49ca0156b92510a55c49b473d8fc440b559c5
Parents: 26b6f4c
Author: Alex Harui <ah...@apache.org>
Authored: Sat Dec 7 21:49:43 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Sat Dec 7 21:50:44 2013 -0800

----------------------------------------------------------------------
 ant_on_air/src/AntClasses.as                    |   5 +
 ant_on_air/src/org/apache/flex/ant/Ant.as       |  45 +++-----
 .../src/org/apache/flex/ant/tags/Condition.as   |  13 +--
 ant_on_air/src/org/apache/flex/ant/tags/Echo.as |   3 +-
 .../src/org/apache/flex/ant/tags/Project.as     | 113 ++++++++++++++++---
 .../src/org/apache/flex/ant/tags/Property.as    |  59 ++++++----
 .../src/org/apache/flex/ant/tags/Target.as      |  75 +++++++++---
 .../flex/ant/tags/supportClasses/TagHandler.as  |   6 +-
 .../flex/ant/tags/supportClasses/TaskHandler.as |   3 +-
 .../src/org/apache/flex/xml/XMLTagProcessor.as  |   4 +-
 ant_on_air/tests/TestTarget.as                  |  11 +-
 11 files changed, 241 insertions(+), 96 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/src/AntClasses.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/AntClasses.as b/ant_on_air/src/AntClasses.as
index 44a09c0..3180f70 100644
--- a/ant_on_air/src/AntClasses.as
+++ b/ant_on_air/src/AntClasses.as
@@ -24,8 +24,13 @@ package
         {
             import org.apache.flex.ant.Ant; Ant;
             import org.apache.flex.ant.tags.Project; Project;
+            import org.apache.flex.ant.tags.Available; Available;
             import org.apache.flex.ant.tags.Condition; Condition;
+            import org.apache.flex.ant.tags.Copy; Copy;
             import org.apache.flex.ant.tags.Echo; Echo;
+            import org.apache.flex.ant.tags.FileSet; FileSet;
+            import org.apache.flex.ant.tags.FileSetExclude; FileSetExclude;
+            import org.apache.flex.ant.tags.FileSetInclude; FileSetInclude;
             import org.apache.flex.ant.tags.IsSet; IsSet;
             import org.apache.flex.ant.tags.OS; OS;
             import org.apache.flex.ant.tags.Property; Property;

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/src/org/apache/flex/ant/Ant.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/Ant.as b/ant_on_air/src/org/apache/flex/ant/Ant.as
index af2f1f5..0f487a3 100644
--- a/ant_on_air/src/org/apache/flex/ant/Ant.as
+++ b/ant_on_air/src/org/apache/flex/ant/Ant.as
@@ -19,6 +19,7 @@
 package org.apache.flex.ant
 {
     
+    import flash.events.Event;
     import flash.filesystem.File;
     import flash.filesystem.FileMode;
     import flash.filesystem.FileStream;
@@ -37,6 +38,7 @@ package org.apache.flex.ant
         public function Ant()
         {
             super();
+            ant = this;
         }
         
         /**
@@ -50,7 +52,7 @@ package org.apache.flex.ant
          *   @param file File The file to open.
          *   @param context Object An object containing an optional targets property listing the targets to run.
          */
-        public function processXMLFile(file:File, context:Object = null):void
+        public function processXMLFile(file:File, context:Object = null):Boolean
         {
             this.file = file;
             var fs:FileStream = new FileStream();
@@ -64,39 +66,26 @@ package org.apache.flex.ant
                 context = {};
             this.context = context;
             var project:Project = processXMLTag(xml, context) as Project;
-            if (waiting == 0)
-                project.execute();
-            else
-                this.project = project;
+            Ant.project = project;
+            if (!project.execute())
+            {
+                project.addEventListener(Event.COMPLETE, completeHandler);
+                return false;                
+            }
+            return true;
         }
     
         private var context:Object;
-        private var project:Project;
-        
-        private var _waiting:int = 0;
-        
-        /**
-         *  A flag used to defer execution if
-         *  waiting on something async like loading
-         *  environment variables.
-         */
-        public function get waiting():int
+        public static var ant:Ant;
+        public static var project:Project;
+        public static function log(msg:String, level:int):void
         {
-            return _waiting;
+            ant.output(msg);
         }
-        
-        /**
-         *  @private
-         */
-        public function set waiting(value:int):void
+                
+        private function completeHandler(event:Event):void
         {
-            if (value >= 0)
-                _waiting = value;
-            
-            if (value == 0)
-                if (project)
-                    project.execute()
-                        
+            dispatchEvent(event);
         }
         
         /**

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/src/org/apache/flex/ant/tags/Condition.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Condition.as b/ant_on_air/src/org/apache/flex/ant/tags/Condition.as
index 87df06d..7f94d8f 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/Condition.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Condition.as
@@ -22,12 +22,12 @@ package org.apache.flex.ant.tags
     
     import org.apache.flex.ant.Ant;
     import org.apache.flex.ant.tags.supportClasses.IValueTagHandler;
-    import org.apache.flex.ant.tags.supportClasses.ParentTagHandler;
+    import org.apache.flex.ant.tags.supportClasses.TaskHandler;
     import org.apache.flex.xml.XMLTagProcessor;
     
     [Mixin]
 
-    public class Condition extends ParentTagHandler
+    public class Condition extends TaskHandler
     {
         public static function init(mf:IFlexModuleFactory):void
         {
@@ -39,12 +39,10 @@ package org.apache.flex.ant.tags
             super();
         }
         
-        override public function init(xml:XML, context:Object, xmlProcessor:XMLTagProcessor):void
+        override public function execute():Boolean
         {
-            // process attributes
-            super.init(xml, context, xmlProcessor);
-            // create child nodes
-            ant.processChildren(xml, context, this);
+            super.execute();
+            
             // if the property is not already set
             if (_property && _value != null && !context.hasOwnProperty(_property))
             {
@@ -58,6 +56,7 @@ package org.apache.flex.ant.tags
                     context[_property] = val;
                 }
             }
+            return true;
         }
 
         private var _property:String;

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/src/org/apache/flex/ant/tags/Echo.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Echo.as b/ant_on_air/src/org/apache/flex/ant/tags/Echo.as
index fa43d73..d20e991 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/Echo.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Echo.as
@@ -52,10 +52,11 @@ package org.apache.flex.ant.tags
                 super.processAttribute(name, value);
         }
 
-        override public function execute():void
+        override public function execute():Boolean
         {
             super.execute();
             ant.output(ant.getValue(text, context));
+            return true;
         }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/src/org/apache/flex/ant/tags/Project.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Project.as b/ant_on_air/src/org/apache/flex/ant/tags/Project.as
index 368f335..5136f55 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/Project.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Project.as
@@ -18,10 +18,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.flex.ant.tags
 {
+    import flash.events.Event;
+    
     import mx.core.IFlexModuleFactory;
     import mx.utils.StringUtil;
     
     import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.filesetClasses.Reference;
     import org.apache.flex.ant.tags.supportClasses.TaskHandler;
     import org.apache.flex.xml.ITagHandler;
     import org.apache.flex.xml.XMLTagProcessor;
@@ -29,6 +32,17 @@ package org.apache.flex.ant.tags
     [Mixin]
     public class Project extends TaskHandler
     {
+        /** Message priority of &quot;error&quot;. */
+        public static const MSG_ERR:int = 0;
+        /** Message priority of &quot;warning&quot;. */
+        public static const MSG_WARN:int = 1;
+        /** Message priority of &quot;information&quot;. */
+        public static const MSG_INFO:int = 2;
+        /** Message priority of &quot;verbose&quot;. */
+        public static const MSG_VERBOSE:int = 3;
+        /** Message priority of &quot;debug&quot;. */
+        public static const MSG_DEBUG:int = 4;
+        
         public static function init(mf:IFlexModuleFactory):void
         {
             Ant.antTagProcessors["project"] = Project;
@@ -59,6 +73,8 @@ package org.apache.flex.ant.tags
             return _defaultTarget;
         }
         
+        private var targets:Array;
+        
         override protected function processAttribute(name:String, value:String):void
         {
             if (name == "basedir")
@@ -69,23 +85,57 @@ package org.apache.flex.ant.tags
                 super.processAttribute(name, value);
         }
 
-        override public function execute():void
+        override public function execute():Boolean
         {
-            if (context.target == null)
-                context.target == _defaultTarget;
+            if (context.targets == null)
+                context.targets == _defaultTarget;
             
-            var targets:Array;
-            var targetList:String = context.targets;
-            if (targetList.indexOf(',') != -1)
-                targets = targetList.split(",");
-            else
-                targets = [ targetList ];
+            targets = context.targets.split(",");
+            
+            // execute all children in order except for targets
+            return executeChildren();
+        }
+        
+        private var current:int = 0;
+        
+        private function executeChildren():Boolean
+        {
+            if (current == numChildren)
+                return executeTargets();
+            
+            while (current < numChildren)
+            {
+                var child:ITagHandler = getChildAt(current++);
+                if (child is Target)
+                    continue;
+                if (child is TaskHandler)
+                {
+                    var task:TaskHandler = TaskHandler(child);
+                    if (!task.execute())
+                    {
+                        task.addEventListener(Event.COMPLETE, childCompleteHandler);
+                        return false;
+                    }
+                }
+            }
+            return executeTargets();
+        }
+        
+        private function executeTargets():Boolean
+        {
+            while (targets.length > 0)
+            {
+                var targetName:String = targets.shift();
+                if (!executeTarget(targetName))
+                    return false;                
+            }
+            if (targets.length == 0)
+                dispatchEvent(new Event(Event.COMPLETE));
             
-            for each (var target:String in targets)
-                executeTarget(target);
+            return true;
         }
         
-        public function executeTarget(targetName:String):void
+        public function getTarget(targetName:String):Target
         {
             targetName = StringUtil.trim(targetName);
             var n:int = numChildren;
@@ -97,15 +147,48 @@ package org.apache.flex.ant.tags
                     var t:Target = child as Target;
                     if (t.name == targetName)
                     {
-                        t.execute();
-                        return;
+                        return t;
                     }
                 }
             }
-            
             trace("missing target: ", targetName);
             throw new Error("missing target: " + targetName);
+            return null;            
+        }
+        
+        public function executeTarget(targetName:String):Boolean
+        {
+            var t:Target = getTarget(targetName);
+            if (!t.execute())
+            {
+                t.addEventListener(Event.COMPLETE, completeHandler);
+                return false;
+            }
+            return true;
+        }
+        
+        private function completeHandler(event:Event):void
+        {
+            executeTargets();
+        }
+        
+        private function childCompleteHandler(event:Event):void
+        {
+            executeChildren();
+        }
+        
+        private var references:Object = {};
+        
+        public function addReference(referenceName:String, value:Object):void
+        {
+            references[referenceName] = value;
+        }
+        public function getReference(referenceName:String):Reference
+        {
+            if (references.hasOwnProperty(referenceName))
+                return references[referenceName];
             
+            return null;
         }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/src/org/apache/flex/ant/tags/Property.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Property.as b/ant_on_air/src/org/apache/flex/ant/tags/Property.as
index 35b899b..a5097cc 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/Property.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Property.as
@@ -18,13 +18,14 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.flex.ant.tags
 {
-    import flash.filesystem.File;
-    import flash.filesystem.FileMode;
-    import flash.filesystem.FileStream;
     import flash.desktop.NativeProcess;
     import flash.desktop.NativeProcessStartupInfo;
+    import flash.events.Event;
     import flash.events.NativeProcessExitEvent;
     import flash.events.ProgressEvent;
+    import flash.filesystem.File;
+    import flash.filesystem.FileMode;
+    import flash.filesystem.FileStream;
     import flash.system.Capabilities;
     import flash.utils.IDataInput;
     
@@ -32,11 +33,11 @@ package org.apache.flex.ant.tags
     import mx.utils.StringUtil;
     
     import org.apache.flex.ant.Ant;
-    import org.apache.flex.ant.tags.supportClasses.NamedTagHandler;
+    import org.apache.flex.ant.tags.supportClasses.TaskHandler;
     import org.apache.flex.xml.XMLTagProcessor;
     
     [Mixin]
-    public class Property extends NamedTagHandler
+    public class Property extends TaskHandler
     {
         public static function init(mf:IFlexModuleFactory):void
         {
@@ -50,19 +51,14 @@ package org.apache.flex.ant.tags
         override public function init(xml:XML, context:Object, xmlProcessor:XMLTagProcessor):void
         {
             super.init(xml, context, xmlProcessor);
-            if (name && value && !context.hasOwnProperty(name))
-                context[name] = value;
         }
         
-        private var fileName:String;
-        private var value:String;
-        private var envPrefix:String;
-        
-        override protected function processAttribute(name:String, value:String):void
+        override public function execute():Boolean
         {
-            if (name == "file")
+            if (name && value && !context.hasOwnProperty(name))
+                context[name] = value;
+            else if (fileName != null)
             {
-                fileName = ant.getValue(value, context);
                 var f:File = new File(fileName);
                 var fs:FileStream = new FileStream();
                 fs.open(f, FileMode.READ);
@@ -76,17 +72,36 @@ package org.apache.flex.ant.tags
                         var key:String = StringUtil.trim(parts[0]);
                         var val:String;
                         if (parts.length == 2)
-                           val = parts[1];
+                            val = parts[1];
                         else
                         {
                             parts.shift();
                             val = parts.join("=");
                         }
-                        context[key] = val;
+                        if (!context.hasOwnProperty(key))
+                            context[key] = val;
                     }
-                        
+                    
                 }
-                fs.close();
+                fs.close();                
+            }
+            else if (envPrefix != null)
+            {
+                requestEnvironmentVariables();
+                return false;
+            }
+            return true;
+        }
+        
+        private var fileName:String;
+        private var value:String;
+        private var envPrefix:String;
+        
+        override protected function processAttribute(name:String, value:String):void
+        {
+            if (name == "file")
+            {
+                fileName = ant.getValue(value, context);
             }
             else if (name == "value")
             {
@@ -95,8 +110,6 @@ package org.apache.flex.ant.tags
             else if (name == "environment")
             {
                 envPrefix = value;
-                ant.waiting++;
-                requestEnvironmentVariables();
             }
             else
                 super.processAttribute(name, value);
@@ -129,6 +142,7 @@ package org.apache.flex.ant.tags
          
         private function exitHandler(event:NativeProcessExitEvent):void
         {
+            dispatchEvent(new Event(Event.COMPLETE));
         }
 
         private function onOutputErrorData(event:ProgressEvent):void 
@@ -136,7 +150,6 @@ package org.apache.flex.ant.tags
             var stdError:IDataInput = process.standardError; 
             var data:String = stdError.readUTFBytes(process.standardError.bytesAvailable); 
             trace("Got Error Output: ", data); 
-            ant.waiting--;
         }
         
         private function onOutputData(event:ProgressEvent):void 
@@ -163,10 +176,10 @@ package org.apache.flex.ant.tags
                         parts.shift();
                         val = parts.join("=");
                     }
-                    context[key] = val;
+                    if (!context.hasOwnProperty(key))
+                        context[key] = val;
                 }
             }
-            ant.waiting--;
         }
 
     } 

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/src/org/apache/flex/ant/tags/Target.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Target.as b/ant_on_air/src/org/apache/flex/ant/tags/Target.as
index 146942f..df47ffa 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/Target.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Target.as
@@ -18,6 +18,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.flex.ant.tags
 {
+    import flash.events.Event;
+    
     import mx.core.IFlexModuleFactory;
     
     import org.apache.flex.ant.Ant;
@@ -66,32 +68,79 @@ package org.apache.flex.ant.tags
             context.currentTarget = this;
         }
         
-        private function processDepends():void
+        private var dependsList:Array;
+        
+        private function processDepends():Boolean
         {
-            if (!_depends)
-                return;
+            if (dependsList.length == 0)
+            {
+                continueOnToSteps();
+                return true;
+            }
+
+            while (dependsList.length > 0)
+            {
+                var depend:String = dependsList.shift();
+                var t:Target = project.getTarget(depend);
+                if (!t.execute())
+                {
+                    t.addEventListener(Event.COMPLETE, dependCompleteHandler);
+                    return false;
+                }
+            }
             
-            var dependsList:Array = _depends.split(",");
-            for each (var d:String in dependsList)
-                project.executeTarget(d);
+            return continueOnToSteps();
         }
         
-        override public function execute():void
+        private function dependCompleteHandler(event:Event):void
         {
             processDepends();
+        }
+        
+        override public function execute():Boolean
+        {
+            if (_depends)
+            {
+                dependsList = _depends.split(",");
+                if (!processDepends())
+                    return false;
+            }
+            
+            return continueOnToSteps();
+        }
+        
+        private function continueOnToSteps():Boolean
+        {
             ant.processChildren(xml, context, this);
-            processSteps();
+            return processSteps();
         }
         
-        private function processSteps():void
+        private var current:int = 0;
+        
+        private function processSteps():Boolean
         {
-            var n:int = numChildren;
-            for (var i:int = 0; i < n; i++)
+            if (current == numChildren)
             {
-                var step:TaskHandler = getChildAt(i) as TaskHandler;
-                step.execute();
+                dispatchEvent(new Event(Event.COMPLETE));
+                return true;
             }
+            
+            while (current < numChildren)
+            {
+                var step:TaskHandler = getChildAt(current++) as TaskHandler;
+                if (!step.execute())
+                {
+                    step.addEventListener(Event.COMPLETE, completeHandler);
+                    return false;
+                }
+            }
+            dispatchEvent(new Event(Event.COMPLETE));
+            return true;
         }
 
+        private function completeHandler(event:Event):void
+        {
+            processSteps();
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TagHandler.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TagHandler.as b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TagHandler.as
index 28db76f..70c215d 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TagHandler.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TagHandler.as
@@ -18,14 +18,16 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.flex.ant.tags.supportClasses
 {
-    import org.apache.flex.xml.XMLTagProcessor;
+    import flash.events.EventDispatcher;
+    
     import org.apache.flex.ant.Ant;
     import org.apache.flex.xml.ITagHandler;
+    import org.apache.flex.xml.XMLTagProcessor;
     
     /**
      *   The lowest-level base class for ITagHandlers for Ant.
      */
-    public class TagHandler implements ITagHandler
+    public class TagHandler extends EventDispatcher implements ITagHandler
     {
         /**
          *  Constructor

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TaskHandler.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TaskHandler.as b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TaskHandler.as
index 6ddccfb..910753e 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TaskHandler.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TaskHandler.as
@@ -34,9 +34,10 @@ package org.apache.flex.ant.tags.supportClasses
          *  super.execute() should be called before
          *  doing any real work. 
          */
-        public function execute():void
+        public function execute():Boolean
         {
             ant.processChildren(this.xml, context, this);
+            return true;
         }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/src/org/apache/flex/xml/XMLTagProcessor.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/xml/XMLTagProcessor.as b/ant_on_air/src/org/apache/flex/xml/XMLTagProcessor.as
index fc7bdfd..a666f7c 100644
--- a/ant_on_air/src/org/apache/flex/xml/XMLTagProcessor.as
+++ b/ant_on_air/src/org/apache/flex/xml/XMLTagProcessor.as
@@ -18,10 +18,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.flex.xml
 {
+    import flash.events.EventDispatcher;
+
     /**
      *  Base class for processing XML Tags 
      */
-    public class XMLTagProcessor
+    public class XMLTagProcessor extends EventDispatcher
     {
         /**
          *  Constructor

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/eef49ca0/ant_on_air/tests/TestTarget.as
----------------------------------------------------------------------
diff --git a/ant_on_air/tests/TestTarget.as b/ant_on_air/tests/TestTarget.as
index c541b9b..1235d41 100644
--- a/ant_on_air/tests/TestTarget.as
+++ b/ant_on_air/tests/TestTarget.as
@@ -39,14 +39,15 @@ package
             var context:Object = { targets: "test" };
             var file:File = File.applicationDirectory;
             file = file.resolvePath("test.xml");
-            ant.processXMLFile(file, context);
-            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
+            if (!ant.processXMLFile(file, context))
+                ant.addEventListener(Event.COMPLETE, completeHandler);
+            else
+                completeHandler(null);
         }
         
-        private function enterFrameHandler(event:Event):void
+        private function completeHandler(event:Event):void
         {
-            if (ant.waiting == 0)
-                NativeApplication.nativeApplication.exit();
+            NativeApplication.nativeApplication.exit();
         }
         
         private var ant:Ant;


[12/14] git commit: [flex-utilities] [refs/heads/develop] - get basic filesets to copy

Posted by ah...@apache.org.
get basic filesets to copy


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/3a3f2326
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/3a3f2326
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/3a3f2326

Branch: refs/heads/develop
Commit: 3a3f2326070cadf1cd6b6c14f1a916d74b0ce9df
Parents: a4728f7
Author: Alex Harui <ah...@apache.org>
Authored: Mon Dec 9 14:01:53 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Mon Dec 9 14:01:53 2013 -0800

----------------------------------------------------------------------
 ant_on_air/src/org/apache/flex/ant/tags/Copy.as | 36 +++++++--
 .../src/org/apache/flex/ant/tags/FileSet.as     |  1 +
 .../ant/tags/filesetClasses/DirectoryScanner.as | 77 ++++++++++----------
 .../flex/ant/tags/filesetClasses/FileUtils.as   |  8 +-
 .../ant/tags/filesetClasses/StringTokenizer.as  | 18 +++--
 .../tags/supportClasses/FileSetTaskHandler.as   |  5 +-
 ant_on_air/tests/TestTarget.as                  |  7 ++
 ant_on_air/tests/test.xml                       | 20 +++++
 8 files changed, 117 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a3f2326/ant_on_air/src/org/apache/flex/ant/tags/Copy.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Copy.as b/ant_on_air/src/org/apache/flex/ant/tags/Copy.as
index 4bdb0cc..3636ad0 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/Copy.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Copy.as
@@ -18,6 +18,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.flex.ant.tags
 {
+    import flash.filesystem.File;
+    
     import mx.core.IFlexModuleFactory;
     
     import org.apache.flex.ant.Ant;
@@ -46,7 +48,7 @@ package org.apache.flex.ant.tags
             if (name == "file")
                 fileName = value;
             else if (name == "toFile")
-                toFileName == value;
+                toFileName = value;
             else if (name == "toDir")
                 toDirName = value;
             else if (name == "overwrite")
@@ -57,17 +59,37 @@ package org.apache.flex.ant.tags
 
         override protected function actOnFile(dir:String, fileName:String):void
         {
+            var srcName:String;
+            if (dir)
+                srcName = dir + File.separator + fileName;
+            else
+                srcName = fileName;
+            var srcFile:File = File.applicationDirectory.resolvePath(srcName);
             
+            var destName:String;
+            if (toDirName)
+                destName = toDirName + File.separator + fileName;
+            else
+                destName = toFileName;
+            var destFile:File = File.applicationDirectory.resolvePath(destName);
+                
+            srcFile.copyTo(destFile, overwrite);
         }
         
-        /**
-         *  Do the work.
-         *  TaskHandlers lazily create their children so
-         *  super.execute() should be called before
-         *  doing any real work. 
-         */
         override public function execute():Boolean
         {
+            var retVal:Boolean = super.execute();
+            if (numChildren > 0)
+                return retVal;
+            
+            var srcFile:File = File.applicationDirectory.resolvePath(fileName);
+            var destFile:File = File.applicationDirectory.resolvePath(toFileName);;
+            //var destDir:File = destFile.parent;
+            //var resolveName:String = destFile.nativePath.substr(destFile.nativePath.lastIndexOf(File.separator) + 1);
+            //destDir.resolvePath(resolveName);
+            
+            
+            srcFile.copyTo(destFile, overwrite);
             return true;
         }
     }

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a3f2326/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as b/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as
index 4a01395..c6fb109 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/FileSet.as
@@ -53,6 +53,7 @@ package org.apache.flex.ant.tags
         {
             if (_value) return _value;
             
+            ant.processChildren(xml, context, this);
             var ds:DirectoryScanner = new DirectoryScanner();
             var n:int = numChildren;
             var includes:Vector.<String> = new Vector.<String>();

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a3f2326/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DirectoryScanner.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DirectoryScanner.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DirectoryScanner.as
index e6f1927..379bb6c 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DirectoryScanner.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DirectoryScanner.as
@@ -526,11 +526,14 @@ package org.apache.flex.ant.tags.filesetClasses
          * @since Ant 1.6
          */
         public static function resetDefaultExcludes():Vector.<String> {
-                defaultExcludes.length = 0;
+                var arr:Vector.<String> = defaultExcludes;
+                if (!arr)
+                    arr = new Vector.<String>();
+                arr.length = 0;
                 for (var i:int = 0; i < DEFAULTEXCLUDES.length; i++) {
-                    defaultExcludes.push(DEFAULTEXCLUDES[i]);
+                    arr.push(DEFAULTEXCLUDES[i]);
                 }
-                return defaultExcludes;
+                return arr;
         }
         
         /**
@@ -819,6 +822,8 @@ package org.apache.flex.ant.tags.filesetClasses
                     excludes = nullExcludes ? null : excludes;
             } catch (ex:IOException) {
                 throw new BuildException(ex.message);
+            } catch (e:Error) {
+                throw new BuildException(e.message);
             } finally {
                 basedir = savedBase;
             }
@@ -843,14 +848,14 @@ package org.apache.flex.ant.tags.filesetClasses
                         pattern;
                 }
             }
-            for each (var entry:Dictionary in includeNonPatterns.entrySet()) {
+            for each (var entry:Object in includeNonPatterns) {
                 for (var p:String in entry)
                 {
                     pattern = p;
                     break;
                 }
                 if (!shouldSkipPattern(pattern)) {
-                    newroots[entry.getValue()] = pattern;
+                    newroots[entry[pattern]] = pattern;
                 }
             }
             
@@ -870,13 +875,9 @@ package org.apache.flex.ant.tags.filesetClasses
                 }
                 // only scan directories that can include matched files or
                 // directories
-                for each (entry in newroots.entrySet()) {
+                for (entry in newroots) {
                     var currentPath:TokenizedPath;
-                    for (p in entry)
-                    {
-                        currentPath = p as TokenizedPath;
-                        break;
-                    }
+                    currentPath = entry as TokenizedPath;
                     var currentelement:String = currentPath.toString();
                     if (basedir == null
                         && !FileUtils.isAbsolutePath(currentelement)) {
@@ -895,7 +896,7 @@ package org.apache.flex.ant.tags.filesetClasses
                                 ? myCanonFile.nativePath
                                 : FILE_UTILS.removeLeadingPath(canonBase,
                                     myCanonFile);
-                            if (!path == currentelement) {
+                            if (path != currentelement) {
                                 myfile = currentPath.findFile(basedir, true);
                                 if (myfile != null && basedir != null) {
                                     currentelement = FILE_UTILS.removeLeadingPath(
@@ -941,10 +942,7 @@ package org.apache.flex.ant.tags.filesetClasses
                             }
                         } else {
                             var originalpattern:String;
-                            for (var q:* in entry)
-                            {
-                                originalpattern = entry[q];
-                            }
+                                originalpattern = newroots[entry] as String;
                             var included:Boolean = isCaseSensitive()
                                 ? originalpattern == currentelement
                                 : originalpattern.toUpperCase() == currentelement.toUpperCase();
@@ -1089,21 +1087,21 @@ package org.apache.flex.ant.tags.filesetClasses
             if (dir == null) {
                 throw new BuildException("dir must not be null.");
             }
-            var arr:Array = dir.getDirectoryListing();
+            else if (!dir.exists) {
+                throw new BuildException(dir + DOES_NOT_EXIST_POSTFIX);
+            } else if (!dir.isDirectory) {
+                throw new BuildException(dir + " is not a directory.");
+            }
+            try {
+                var arr:Array = dir.getDirectoryListing();                
+            } catch (e:Error) {
+                throw new BuildException("IO error scanning directory '"
+                    + dir.nativePath + "'");
+            }
             var arr2:Array = [];
             for each (var f:File in arr)
-                arr2.push(f.nativePath);
+                arr2.push(f.name);
             var newfiles:Vector.<String> = Vector.<String>(arr2);;
-            if (newfiles == null) {
-                if (!dir.exists) {
-                    throw new BuildException(dir + DOES_NOT_EXIST_POSTFIX);
-                } else if (!dir.isDirectory) {
-                    throw new BuildException(dir + " is not a directory.");
-                } else {
-                    throw new BuildException("IO error scanning directory '"
-                        + dir.nativePath + "'");
-                }
-            }
             _scandir(dir, path, fast, newfiles, new Vector.<String>());
         }
         
@@ -1150,11 +1148,16 @@ package org.apache.flex.ant.tags.filesetClasses
                     name = vpath + newfiles[i];
                     var newPath:TokenizedPath = new TokenizedPath("").initAsChild(path, newfiles[i]);
                     file = new File(dir.nativePath + File.separator + newfiles[i]);
-                    var arr:Array = file.getDirectoryListing();
+                    var arr:Array = null;
                     var arr2:Array = [];
-                    for each (var f:File in arr)
-                        arr2.push(f.nativePath);
-                    var children:Vector.<String> = Vector.<String>(arr2);
+                    var children:Vector.<String> = null;
+                    if (file.isDirectory)
+                    {
+                        arr = file.getDirectoryListing();
+                        for each (var f:File in arr)
+                            arr2.push(f.name);
+                        children = Vector.<String>(arr2);
+                    }
                     if (children == null || (children.length == 0 && !file.isDirectory)) {
                         if (isIncludedPath(newPath)) {
                             accountForIncludedFile(newPath, file);
@@ -1272,8 +1275,8 @@ package org.apache.flex.ant.tags.filesetClasses
             ensureNonPatternSetsReady();
             
             if (isCaseSensitive()
-                ? includeNonPatterns.containsKey(path.toString())
-                : includeNonPatterns.containsKey(path.toString().toUpperCase())) {
+                ? includeNonPatterns.hasOwnProperty(path.toString())
+                : includeNonPatterns.hasOwnProperty(path.toString().toUpperCase())) {
                 return true;
             }
             for (var i:int = 0; i < includePatterns.length; i++) {
@@ -1668,8 +1671,8 @@ package org.apache.flex.ant.tags.filesetClasses
          * @since Ant 1.6
          */
         private function clearCaches():void {
-            includeNonPatterns.clear();
-            excludeNonPatterns.clear();
+            includeNonPatterns = {};
+            excludeNonPatterns = {};
             includePatterns = null;
             excludePatterns = null;
             areNonPatternSetsReady = false;
@@ -1698,7 +1701,7 @@ package org.apache.flex.ant.tags.filesetClasses
          * @since Ant 1.8.0
          */
         private function fillNonPatternSet(map:Object, patterns:Vector.<String>):Vector.<TokenizedPattern> {
-            var al:Vector.<TokenizedPattern> = new Vector.<TokenizedPattern>(patterns.length);
+            var al:Vector.<TokenizedPattern> = new Vector.<TokenizedPattern>();
             for (var i:int = 0; i < patterns.length; i++) {
                 if (!SelectorUtils.hasWildcards(patterns[i])) {
                     var s:String = isCaseSensitive()

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a3f2326/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileUtils.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileUtils.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileUtils.as
index d0409ca..146b972 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileUtils.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileUtils.as
@@ -175,7 +175,7 @@ package org.apache.flex.ant.tags.filesetClasses
             var sep:String = File.separator;
             filename = filename.replace(/\//g, sep).replace(/\\/g, sep);
             var c:String = filename.charAt(0);
-            if (ON_DOS)
+            if (!ON_DOS)
                 return (c == sep);
             
             if (c == sep) {
@@ -258,7 +258,7 @@ package org.apache.flex.ant.tags.filesetClasses
                     continue;
                 }
                 if (".." == thisToken) {
-                    if (s.size() < 2) {
+                    if (s.length < 2) {
                         // Cannot resolve it, so skip it.
                         return new File(path);
                     }
@@ -268,14 +268,14 @@ package org.apache.flex.ant.tags.filesetClasses
                 }
             }
             var sb:String = "";
-            var size:int = s.size();
+            var size:int = s.length;
             for (var i:int = 0; i < size; i++) {
                 if (i > 1) {
                     // not before the filesystem root and not after it, since root
                     // already contains one
                     sb += File.separator;
                 }
-                sb += s.elementAt(i);
+                sb += s[i];
             }
             return new File(sb);
         }

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a3f2326/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/StringTokenizer.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/StringTokenizer.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/StringTokenizer.as
index fcd97ba..02ddff5 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/StringTokenizer.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/StringTokenizer.as
@@ -27,29 +27,35 @@ package org.apache.flex.ant.tags.filesetClasses
             var c1:int = 0;
             var c2:int = 0;
             var n:int = s.length;
-            while (c1 < n)
+            while (c2 < n)
             {
                 var c:String = s.charAt(c2);
                 if (delims.indexOf(c) != -1)
                 {
-                    tokens.push(s.substring(c1, c2 - 1));
+                    tokens.push(s.substring(c1, c2));
                     c1 = c2;
-                    while (c1 < n)
+                    while (c2 < n)
                     {
                         c = s.charAt(c2);
                         if (delims.indexOf(c) == -1)
                         {
                             if (returnDelims)
-                            {
-                                tokens.push(s.substring(c1, c2 - 1))
-                            }
+                                tokens.push(s.substring(c1, c2))
                             c1 = c2;
                             break;
                         }
+                        c2++;
+                    }
+                    if (returnDelims && c1 < c2)
+                    {
+                        tokens.push(s.substring(c1, c2));
+                        c1 = c2;
                     }
                 }
                 c2++;
             }
+            if (c1 < n)
+                tokens.push(s.substring(c1))
         }
         
         private var tokens:Vector.<String>;

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a3f2326/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
index c399e52..c0320a8 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
@@ -18,6 +18,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.flex.ant.tags.supportClasses
 {
+    import flash.filesystem.File;
+    
     import org.apache.flex.ant.tags.FileSet;
     
     /**
@@ -47,9 +49,10 @@ package org.apache.flex.ant.tags.supportClasses
                     var list:Vector.<String> = fs.value as Vector.<String>;
                     if (list)
                     {
+                        var dir:File = new File(fs.dir);
                         for each (var fileName:String in list)
                         {
-                            actOnFile(fs.dir, fileName);
+                            actOnFile(dir.nativePath, fileName);
                         }
                     }
                 }

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a3f2326/ant_on_air/tests/TestTarget.as
----------------------------------------------------------------------
diff --git a/ant_on_air/tests/TestTarget.as b/ant_on_air/tests/TestTarget.as
index 1235d41..722986a 100644
--- a/ant_on_air/tests/TestTarget.as
+++ b/ant_on_air/tests/TestTarget.as
@@ -23,9 +23,16 @@ package
     import flash.events.Event;
     import flash.filesystem.File;
     import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.Available; Available.init(null);
     import org.apache.flex.ant.tags.Condition; Condition.init(null);
+    import org.apache.flex.ant.tags.Copy; Copy.init(null);
+    import org.apache.flex.ant.tags.Delete; Delete.init(null);
     import org.apache.flex.ant.tags.Echo; Echo.init(null);
+    import org.apache.flex.ant.tags.FileSet; FileSet.init(null);
+    import org.apache.flex.ant.tags.FileSetExclude; FileSetExclude.init(null);
+    import org.apache.flex.ant.tags.FileSetInclude; FileSetInclude.init(null);
     import org.apache.flex.ant.tags.IsSet; IsSet.init(null);
+    import org.apache.flex.ant.tags.Mkdir; Mkdir.init(null);
     import org.apache.flex.ant.tags.OS; OS.init(null);
     import org.apache.flex.ant.tags.Project; Project.init(null);
     import org.apache.flex.ant.tags.Property; Property.init(null);

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a3f2326/ant_on_air/tests/test.xml
----------------------------------------------------------------------
diff --git a/ant_on_air/tests/test.xml b/ant_on_air/tests/test.xml
index 5d55451..8114225 100644
--- a/ant_on_air/tests/test.xml
+++ b/ant_on_air/tests/test.xml
@@ -45,6 +45,26 @@
 
 	<target name="test">
 		<echo>FLEX_HOME is ${FLEX_HOME}. DEBUG is ${DEBUG_FLAG}. The OS is ${theOS}</echo>
+        <mkdir dir="${basedir}/temp" />
+        <copy file="${basedir}/test.xml" toFile="${basedir}/temp/copied.xml" />
+        <available file="${basedir}/temp/copied.xml" property="copied.doesnt.exist" value="got copied" />
+        <echo>copied ${copied.doesnt.exist}.  Should say: got copied</echo>
+        <copy toDir="${basedir}/temp">
+            <fileset dir="${basedir}/../src">
+                <include name="**/**" />
+                <exclude name="**/Ant.as" />
+            </fileset>
+        </copy>
+        <available file="${basedir}/temp/org/apache/flex/ant/Ant.as" property="ant.doesnt.exist" value="got copied" />
+        <echo>Ant.as ${ant.doesnt.exist}. Should NOT say: got copied</echo>
+        <available file="${basedir}/temp/org/apache/flex/ant/tags/Project.as" property="project.doesnt.exist" value="got copied" />
+        <echo>Project.as ${project.doesnt.exist}. Should say: got copied</echo>
+        <delete file="${basedir}/temp/copied.xml" />
+        <available file="${basedir}/temp/copied.xml" property="copied.doesnt.exist.after.delete" value="didn't get deleted" />
+        <echo>copied.xml ${copied.doesnt.exist.after.delete}. Should NOT say: didn't get deleted</echo>
+        <delete dir="${basedir}/temp" />
+        <available file="${basedir}/temp/org/apache/flex/ant/tags/Project.as" property="project.doesnt.exist.after.delete" value="didn't get deleted" />
+        <echo>Project.as ${project.doesnt.exist.after.delete}. Should NOT say: didn't get deleted</echo>
 	</target>
 
     <target name="build" depends="init,compile"


[06/14] port DirectoryScanner from Ant code base and hook up FileSet to it

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DirectoryScanner.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DirectoryScanner.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DirectoryScanner.as
new file mode 100644
index 0000000..e6f1927
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/DirectoryScanner.as
@@ -0,0 +1,1764 @@
+/*
+*  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.flex.ant.tags.filesetClasses
+{
+    import flash.filesystem.File;
+    import flash.utils.Dictionary;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.filesetClasses.Resource;
+    import org.apache.flex.ant.tags.filesetClasses.SelectorUtils;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.BuildException;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.IOException;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.IllegalStateException;
+    
+    /**
+     * Ported from org.apache.tools.ant.DirectoryScanner.java on 12/3/13.
+     * Class for scanning a directory for files/directories which match certain
+     * criteria.
+     * <p>
+     * These criteria consist of selectors and patterns which have been specified.
+     * With the selectors you can select which files you want to have included.
+     * Files which are not selected are excluded. With patterns you can include
+     * or exclude files based on their filename.
+     * <p>
+     * The idea is simple. A given directory is recursively scanned for all files
+     * and directories. Each file/directory is matched against a set of selectors,
+     * including special support for matching against filenames with include and
+     * and exclude patterns. Only files/directories which match at least one
+     * pattern of the include pattern list or other file selector, and don't match
+     * any pattern of the exclude pattern list or fail to match against a required
+     * selector will be placed in the list of files/directories found.
+     * <p>
+     * When no list of include patterns is supplied, "**" will be used, which
+     * means that everything will be matched. When no list of exclude patterns is
+     * supplied, an empty list is used, such that nothing will be excluded. When
+     * no selectors are supplied, none are applied.
+     * <p>
+     * The filename pattern matching is done as follows:
+     * The name to be matched is split up in path segments. A path segment is the
+     * name of a directory or file, which is bounded by
+     * <code>File.separator</code> ('/' under UNIX, '\' under Windows).
+     * For example, "abc/def/ghi/xyz.java" is split up in the segments "abc",
+     * "def","ghi" and "xyz.java".
+     * The same is done for the pattern against which should be matched.
+     * <p>
+     * The segments of the name and the pattern are then matched against each
+     * other. When '**' is used for a path segment in the pattern, it matches
+     * zero or more path segments of the name.
+     * <p>
+     * There is a special case regarding the use of <code>File.separator</code>s
+     * at the beginning of the pattern and the string to match:<br>
+     * When a pattern starts with a <code>File.separator</code>, the string
+     * to match must also start with a <code>File.separator</code>.
+     * When a pattern does not start with a <code>File.separator</code>, the
+     * string to match may not start with a <code>File.separator</code>.
+     * When one of these rules is not obeyed, the string will not
+     * match.
+     * <p>
+     * When a name path segment is matched against a pattern path segment, the
+     * following special characters can be used:<br>
+     * '*' matches zero or more characters<br>
+     * '?' matches one character.
+     * <p>
+     * Examples:
+     * <p>
+     * "**\*.class" matches all .class files/dirs in a directory tree.
+     * <p>
+     * "test\a??.java" matches all files/dirs which start with an 'a', then two
+     * more characters and then ".java", in a directory called test.
+     * <p>
+     * "**" matches everything in a directory tree.
+     * <p>
+     * "**\test\**\XYZ*" matches all files/dirs which start with "XYZ" and where
+     * there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123").
+     * <p>
+     * Case sensitivity may be turned off if necessary. By default, it is
+     * turned on.
+     * <p>
+     * Example of usage:
+     * <pre>
+     *   String[] includes = {"**\\*.class"};
+     *   String[] excludes = {"modules\\*\\**"};
+     *   ds.setIncludes(includes);
+     *   ds.setExcludes(excludes);
+     *   ds.setBasedir(new File("test"));
+     *   ds.setCaseSensitive(true);
+     *   ds.scan();
+     *
+     *   System.out.println("FILES:");
+     *   String[] files = ds.getIncludedFiles();
+     *   for (int i = 0; i < files.length; i++) {
+     *     System.out.println(files[i]);
+     *   }
+     * </pre>
+     * This will scan a directory called test for .class files, but excludes all
+     * files in all proper subdirectories of a directory called "modules"
+     *
+     */
+    public class DirectoryScanner
+        /* implements FileScanner, SelectorScanner, ResourceFactory*/ {
+        
+        /**
+         * Patterns which should be excluded by default.
+         *
+         * <p>Note that you can now add patterns to the list of default
+         * excludes.  Added patterns will not become part of this array
+         * that has only been kept around for backwards compatibility
+         * reasons.</p>
+         *
+         * @deprecated since 1.6.x.
+         *             Use the {@link #getDefaultExcludes getDefaultExcludes}
+         *             method instead.
+         */
+        protected static const DEFAULTEXCLUDES:Vector.<String> = Vector.<String>([
+            // Miscellaneous typical temporary files
+            SelectorUtils.DEEP_TREE_MATCH + "/*~",
+                SelectorUtils.DEEP_TREE_MATCH + "/#*#",
+                SelectorUtils.DEEP_TREE_MATCH + "/.#*",
+                SelectorUtils.DEEP_TREE_MATCH + "/%*%",
+                SelectorUtils.DEEP_TREE_MATCH + "/._*",
+                
+                // CVS
+                SelectorUtils.DEEP_TREE_MATCH + "/CVS",
+                SelectorUtils.DEEP_TREE_MATCH + "/CVS/" + SelectorUtils.DEEP_TREE_MATCH,
+                SelectorUtils.DEEP_TREE_MATCH + "/.cvsignore",
+                
+                // SCCS
+                SelectorUtils.DEEP_TREE_MATCH + "/SCCS",
+                SelectorUtils.DEEP_TREE_MATCH + "/SCCS/" + SelectorUtils.DEEP_TREE_MATCH,
+                
+                // Visual SourceSafe
+                SelectorUtils.DEEP_TREE_MATCH + "/vssver.scc",
+                
+                // Subversion
+                SelectorUtils.DEEP_TREE_MATCH + "/.svn",
+                SelectorUtils.DEEP_TREE_MATCH + "/.svn/" + SelectorUtils.DEEP_TREE_MATCH,
+                
+                // Git
+                SelectorUtils.DEEP_TREE_MATCH + "/.git",
+                SelectorUtils.DEEP_TREE_MATCH + "/.git/" + SelectorUtils.DEEP_TREE_MATCH,
+                SelectorUtils.DEEP_TREE_MATCH + "/.gitattributes",
+                SelectorUtils.DEEP_TREE_MATCH + "/.gitignore",
+                SelectorUtils.DEEP_TREE_MATCH + "/.gitmodules",
+                
+                // Mercurial
+                SelectorUtils.DEEP_TREE_MATCH + "/.hg",
+                SelectorUtils.DEEP_TREE_MATCH + "/.hg/" + SelectorUtils.DEEP_TREE_MATCH,
+                SelectorUtils.DEEP_TREE_MATCH + "/.hgignore",
+                SelectorUtils.DEEP_TREE_MATCH + "/.hgsub",
+                SelectorUtils.DEEP_TREE_MATCH + "/.hgsubstate",
+                SelectorUtils.DEEP_TREE_MATCH + "/.hgtags",
+                
+                // Bazaar
+                SelectorUtils.DEEP_TREE_MATCH + "/.bzr",
+                SelectorUtils.DEEP_TREE_MATCH + "/.bzr/" + SelectorUtils.DEEP_TREE_MATCH,
+                SelectorUtils.DEEP_TREE_MATCH + "/.bzrignore",
+                
+                // Mac
+                SelectorUtils.DEEP_TREE_MATCH + "/.DS_Store"
+        ]);
+        
+        /**
+         * default value for {@link #maxLevelsOfSymlinks maxLevelsOfSymlinks}
+         * @since Ant 1.8.0
+         */
+        public static const MAX_LEVELS_OF_SYMLINKS:int = 5;
+        /**
+         * The end of the exception message if something that should be
+         * there doesn't exist.
+         */
+        public static const DOES_NOT_EXIST_POSTFIX:String = " does not exist.";
+        
+        /** Helper. */
+        private static const FILE_UTILS:FileUtils = FileUtils.getFileUtils();
+        
+        /**
+         * Patterns which should be excluded by default.
+         *
+         * @see #addDefaultExcludes()
+         */
+        private static const defaultExcludes:Vector.<String> = resetDefaultExcludes();
+        
+        // CheckStyle:VisibilityModifier OFF - bc
+        
+        /** The base directory to be scanned. */
+        protected var basedir:File;
+        
+        /** The patterns for the files to be included. */
+        protected var includes:Vector.<String>;
+        
+        /** The patterns for the files to be excluded. */
+        protected var excludes:Vector.<String>;
+        
+        /** Selectors that will filter which files are in our candidate list. */
+        protected var selectors:Vector.<FileSelector> = null;
+        
+        /**
+         * The files which matched at least one include and no excludes
+         * and were selected.
+         */
+        protected var filesIncluded:Vector.<String>;
+        
+        /** The files which did not match any includes or selectors. */
+        protected var filesNotIncluded:Vector.<String>;
+        
+        /**
+         * The files which matched at least one include and at least
+         * one exclude.
+         */
+        protected var filesExcluded:Vector.<String>;
+        
+        /**
+         * The directories which matched at least one include and no excludes
+         * and were selected.
+         */
+        protected var dirsIncluded:Vector.<String>;
+        
+        /** The directories which were found and did not match any includes. */
+        protected var dirsNotIncluded:Vector.<String>;
+        
+        /**
+         * The directories which matched at least one include and at least one
+         * exclude.
+         */
+        protected var dirsExcluded:Vector.<String>;
+        
+        /**
+         * The files which matched at least one include and no excludes and
+         * which a selector discarded.
+         */
+        protected var filesDeselected:Vector.<String>;
+        
+        /**
+         * The directories which matched at least one include and no excludes
+         * but which a selector discarded.
+         */
+        protected var dirsDeselected:Vector.<String>;
+        
+        /** Whether or not our results were built by a slow scan. */
+        protected var haveSlowResults:Boolean = false;
+        
+        /**
+         * Whether or not the file system should be treated as a case sensitive
+         * one.
+         */
+        protected var _isCaseSensitive:Boolean = true;
+        
+        /**
+         * Whether a missing base directory is an error.
+         * @since Ant 1.7.1
+         */
+        protected var errorOnMissingDir:Boolean = true;
+        
+        /**
+         * Whether or not symbolic links should be followed.
+         *
+         * @since Ant 1.5
+         */
+        private var followSymlinks:Boolean = true;
+        
+        /** Whether or not everything tested so far has been included. */
+        protected var everythingIncluded:Boolean = true;
+        
+        // CheckStyle:VisibilityModifier ON
+        
+        /**
+         * List of all scanned directories.
+         *
+         * @since Ant 1.6
+         */
+        private var scannedDirs:Vector.<String> = new Vector.<String>();
+        
+        /**
+         * Map of all include patterns that are full file names and don't
+         * contain any wildcards.
+         *
+         * <p>Maps pattern string to TokenizedPath.</p>
+         *
+         * <p>If this instance is not case sensitive, the file names get
+         * turned to upper case.</p>
+         *
+         * <p>Gets lazily initialized on the first invocation of
+         * isIncluded or isExcluded and cleared at the end of the scan
+         * method (cleared in clearCaches, actually).</p>
+         *
+         * @since Ant 1.8.0
+         */
+        private var includeNonPatterns:Object = {}; //new HashMap<String, TokenizedPath>();
+        
+        /**
+         * Map of all exclude patterns that are full file names and don't
+         * contain any wildcards.
+         *
+         * <p>Maps pattern string to TokenizedPath.</p>
+         *
+         * <p>If this instance is not case sensitive, the file names get
+         * turned to upper case.</p>
+         *
+         * <p>Gets lazily initialized on the first invocation of
+         * isIncluded or isExcluded and cleared at the end of the scan
+         * method (cleared in clearCaches, actually).</p>
+         *
+         * @since Ant 1.8.0
+         */
+        private var excludeNonPatterns:Object = {}; //new HashMap<String, TokenizedPath>();
+        
+        /**
+         * Array of all include patterns that contain wildcards.
+         *
+         * <p>Gets lazily initialized on the first invocation of
+         * isIncluded or isExcluded and cleared at the end of the scan
+         * method (cleared in clearCaches, actually).</p>
+         */
+        private var includePatterns:Vector.<TokenizedPattern>;
+        
+        /**
+         * Array of all exclude patterns that contain wildcards.
+         *
+         * <p>Gets lazily initialized on the first invocation of
+         * isIncluded or isExcluded and cleared at the end of the scan
+         * method (cleared in clearCaches, actually).</p>
+         */
+        private var excludePatterns:Vector.<TokenizedPattern>;
+        
+        /**
+         * Have the non-pattern sets and pattern arrays for in- and
+         * excludes been initialized?
+         *
+         * @since Ant 1.6.3
+         */
+        private var areNonPatternSetsReady:Boolean = false;
+        
+        /**
+         * Scanning flag.
+         *
+         * @since Ant 1.6.3
+         */
+        private var scanning:Boolean = false;
+        
+        /**
+         * Scanning lock.
+         *
+         * @since Ant 1.6.3
+         */
+        private var scanLock:Object = new Object();
+        
+        /**
+         * Slow scanning flag.
+         *
+         * @since Ant 1.6.3
+         */
+        private var slowScanning:Boolean = false;
+        
+        /**
+         * Slow scanning lock.
+         *
+         * @since Ant 1.6.3
+         */
+        private var slowScanLock:Object = new Object();
+        
+        /**
+         * Exception thrown during scan.
+         *
+         * @since Ant 1.6.3
+         */
+        private var illegal:IllegalStateException = null;
+        
+        /**
+         * The maximum number of times a symbolic link may be followed
+         * during a scan.
+         *
+         * @since Ant 1.8.0
+         */
+        private var maxLevelsOfSymlinks:int = MAX_LEVELS_OF_SYMLINKS;
+        
+        
+        /**
+         * Absolute paths of all symlinks that haven't been followed but
+         * would have been if followsymlinks had been true or
+         * maxLevelsOfSymlinks had been higher.
+         *
+         * @since Ant 1.8.0
+         */
+        private var notFollowedSymlinks:Vector.<String> = new Vector.<String>();
+        
+        /**
+         * Sole constructor.
+         */
+        public function DirectoryScanner() {
+        }
+                
+        /**
+         * Test 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 "**".
+         */
+        protected static function matchPatternStart(pattern:String, str:String,
+            isCaseSensitive:Boolean = true):Boolean {
+                return SelectorUtils.matchPatternStart(pattern, str, isCaseSensitive);
+            }
+                
+        /**
+         * Test 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.
+         */
+        protected static function matchPath(pattern:String, str:String,
+            isCaseSensitive:Boolean = true):Boolean {
+                return SelectorUtils.matchPath(pattern, str, isCaseSensitive);
+            }
+        
+        /**
+         * Test 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.
+         */
+        protected static function match(pattern:String, str:String,
+            isCaseSensitive:Boolean = true):Boolean{
+                return SelectorUtils.match(pattern, str, isCaseSensitive);
+            }
+        
+        
+        /**
+         * Get the list of patterns that should be excluded by default.
+         *
+         * @return An array of <code>String</code> based on the current
+         *         contents of the <code>defaultExcludes</code>
+         *         <code>Set</code>.
+         *
+         * @since Ant 1.6
+         */
+        public static function getDefaultExcludes():Vector.<String> {
+                return defaultExcludes.slice();
+        }
+        
+        /**
+         * Add a pattern to the default excludes unless it is already a
+         * default exclude.
+         *
+         * @param s   A string to add as an exclude pattern.
+         * @return    <code>true</code> if the string was added;
+         *            <code>false</code> if it already existed.
+         *
+         * @since Ant 1.6
+         */
+        public static function addDefaultExclude(s:String):Boolean {
+            if (defaultExcludes.indexOf(s) == -1)
+            {
+                defaultExcludes.push(s);
+                return true;
+            }
+            return false;
+        }
+        
+        /**
+         * Remove a string if it is a default exclude.
+         *
+         * @param s   The string to attempt to remove.
+         * @return    <code>true</code> if <code>s</code> was a default
+         *            exclude (and thus was removed);
+         *            <code>false</code> if <code>s</code> was not
+         *            in the default excludes list to begin with.
+         *
+         * @since Ant 1.6
+         */
+        public static function removeDefaultExclude(s:String):Boolean {
+            var index:int = defaultExcludes.indexOf(s);
+            if (index == -1)
+                return false;
+            defaultExcludes.splice(index, 1);
+            return true;
+        }
+        
+        /**
+         * Go back to the hardwired default exclude patterns.
+         *
+         * @since Ant 1.6
+         */
+        public static function resetDefaultExcludes():Vector.<String> {
+                defaultExcludes.length = 0;
+                for (var i:int = 0; i < DEFAULTEXCLUDES.length; i++) {
+                    defaultExcludes.push(DEFAULTEXCLUDES[i]);
+                }
+                return defaultExcludes;
+        }
+        
+        /**
+         * Set the base directory to be scanned. This is the directory which is
+         * scanned recursively. All '/' and '\' characters are replaced by
+         * <code>File.separatorChar</code>, so the separator used need not match
+         * <code>File.separatorChar</code>.
+         *
+         * @param basedir The base directory to scan.
+         */
+        public function setBasedir(basedir:Object):void {
+            if (basedir is File)
+                setBasedirFile(basedir as File);
+            else
+                setBasedirFile(basedir == null ? null
+                    : new File(basedir.replace('/', File.separator).replace(
+                    '\\', File.separator)));
+        }
+        
+        /**
+         * Set the base directory to be scanned. This is the directory which is
+         * scanned recursively.
+         *
+         * @param basedir The base directory for scanning.
+         */
+        public function setBasedirFile(basedir:File):void {
+            this.basedir = basedir;
+        }
+
+        /**
+         * Return the base directory to be scanned.
+         * This is the directory which is scanned recursively.
+         *
+         * @return the base directory to be scanned.
+         */
+        public function getBasedir():File {
+            return basedir;
+        }
+        
+        /**
+         * Find out whether include exclude patterns are matched in a
+         * case sensitive way.
+         * @return whether or not the scanning is case sensitive.
+         * @since Ant 1.6
+         */
+        public function isCaseSensitive():Boolean {
+            return _isCaseSensitive;
+        }
+        
+        /**
+         * Set whether or not include and exclude patterns are matched
+         * in a case sensitive way.
+         *
+         * @param isCaseSensitive whether or not the file system should be
+         *                        regarded as a case sensitive one.
+         */
+        public function setCaseSensitive(isCaseSensitive:Boolean):void {
+            _isCaseSensitive = isCaseSensitive;
+        }
+        
+        /**
+         * Sets whether or not a missing base directory is an error
+         *
+         * @param errorOnMissingDir whether or not a missing base directory
+         *                        is an error
+         * @since Ant 1.7.1
+         */
+        public function setErrorOnMissingDir(errorOnMissingDir:Boolean):void {
+            this.errorOnMissingDir = errorOnMissingDir;
+        }
+        
+        /**
+         * Get whether or not a DirectoryScanner follows symbolic links.
+         *
+         * @return flag indicating whether symbolic links should be followed.
+         *
+         * @since Ant 1.6
+         */
+        public function isFollowSymlinks():Boolean {
+            return followSymlinks;
+        }
+        
+        /**
+         * Set whether or not symbolic links should be followed.
+         *
+         * @param followSymlinks whether or not symbolic links should be followed.
+         */
+        public function setFollowSymlinks(followSymlinks:Boolean):void {
+            this.followSymlinks = followSymlinks;
+        }
+        
+        /**
+         * The maximum number of times a symbolic link may be followed
+         * during a scan.
+         *
+         * @since Ant 1.8.0
+         */
+        public function setMaxLevelsOfSymlinks(max:int):void {
+            maxLevelsOfSymlinks = max;
+        }
+        
+        /**
+         * Set the list of include patterns to use. All '/' and '\' characters
+         * are replaced by <code>File.separator</code>, so the separator used
+         * need not match <code>File.separator</code>.
+         * <p>
+         * When a pattern ends with a '/' or '\', "**" is appended.
+         *
+         * @param includes A list of include patterns.
+         *                 May be <code>null</code>, indicating that all files
+         *                 should be included. If a non-<code>null</code>
+         *                 list is given, all elements must be
+         *                 non-<code>null</code>.
+         */
+        public function setIncludes(includes:Vector.<String>):void {
+            if (includes == null) {
+                this.includes = null;
+            } else {
+                this.includes = new Vector.<String>(includes.length);
+                for (var i:int = 0; i < includes.length; i++) {
+                    this.includes[i] = normalizePattern(includes[i]);
+                }
+            }
+        }
+        
+        /**
+         * Set the list of exclude patterns to use. All '/' and '\' characters
+         * are replaced by <code>File.separator</code>, so the separator used
+         * need not match <code>File.separator</code>.
+         * <p>
+         * When a pattern ends with a '/' or '\', "**" is appended.
+         *
+         * @param excludes A list of exclude patterns.
+         *                 May be <code>null</code>, indicating that no files
+         *                 should be excluded. If a non-<code>null</code> list is
+         *                 given, all elements must be non-<code>null</code>.
+         */
+        public function setExcludes(excludes:Vector.<String>):void {
+            if (excludes == null) {
+                this.excludes = null;
+            } else {
+                this.excludes = new Vector.<String>(excludes.length);
+                for (var i:int = 0; i < excludes.length; i++) {
+                    this.excludes[i] = normalizePattern(excludes[i]);
+                }
+            }
+        }
+        
+        /**
+         * Add to the list of exclude patterns to use. All '/' and '\'
+         * characters are replaced by <code>File.separator</code>, so
+         * the separator used need not match <code>File.separator</code>.
+         * <p>
+         * When a pattern ends with a '/' or '\', "**" is appended.
+         *
+         * @param excludes A list of exclude patterns.
+         *                 May be <code>null</code>, in which case the
+         *                 exclude patterns don't get changed at all.
+         *
+         * @since Ant 1.6.3
+         */
+        public function addExcludes(excludes:Vector.<String>):void {
+            if (excludes != null && excludes.length > 0) {
+                if (this.excludes != null && this.excludes.length > 0) {
+                    var tmp:Vector.<String> = this.excludes.slice();
+                    for (var i:int = 0; i < excludes.length; i++) {
+                        tmp.push(
+                            normalizePattern(excludes[i]));
+                    }
+                    this.excludes = tmp;
+                } else {
+                    setExcludes(excludes);
+                }
+            }
+        }
+        
+        /**
+         * All '/' and '\' characters are replaced by
+         * <code>File.separator</code>, so the separator used need not
+         * match <code>File.separator</code>.
+         *
+         * <p> When a pattern ends with a '/' or '\', "**" is appended.
+         *
+         * @since Ant 1.6.3
+         */
+        private function normalizePattern(p:String):String {
+            var pattern:String = p.replace(/\//g, File.separator)
+                .replace(/\\/g, File.separator);
+            if (pattern.charAt(pattern.length - 1) == File.separator) {
+                pattern += SelectorUtils.DEEP_TREE_MATCH;
+            }
+            return pattern;
+        }
+        
+        /**
+         * Set the selectors that will select the filelist.
+         *
+         * @param selectors specifies the selectors to be invoked on a scan.
+         */
+        public function setSelectors(selectors:Vector.<FileSelector>):void {
+            this.selectors = selectors;
+        }
+        
+        /**
+         * Return whether or not the scanner has included all the files or
+         * directories it has come across so far.
+         *
+         * @return <code>true</code> if all files and directories which have
+         *         been found so far have been included.
+         */
+        public function isEverythingIncluded():Boolean {
+            return everythingIncluded;
+        }
+        
+        /**
+         * Scan for files which match at least one include pattern and don't match
+         * any exclude patterns. If there are selectors then the files must pass
+         * muster there, as well.  Scans under basedir, if set; otherwise the
+         * include patterns without leading wildcards specify the absolute paths of
+         * the files that may be included.
+         *
+         * @exception IllegalStateException if the base directory was set
+         *            incorrectly (i.e. if it doesn't exist or isn't a directory).
+         */
+        public function scan():void 
+        {
+            var savedBase:File = basedir;
+            try {
+                    illegal = null;
+                    clearResults();
+                    
+                    // set in/excludes to reasonable defaults if needed:
+                    var nullIncludes:Boolean = (includes == null);
+                    includes = nullIncludes
+                        ? Vector.<String>([SelectorUtils.DEEP_TREE_MATCH]) : includes;
+                    var nullExcludes:Boolean = (excludes == null);
+                    excludes = nullExcludes ? new Vector.<String>(0) : excludes;
+                    
+                    if (basedir != null && !followSymlinks
+                        && basedir.isSymbolicLink) {
+                        notFollowedSymlinks.push(basedir.nativePath);
+                        basedir = null;
+                    }
+                    
+                    if (basedir == null) {
+                        // if no basedir and no includes, nothing to do:
+                        if (nullIncludes) {
+                            return;
+                        }
+                    } else {
+                        if (!basedir.exists) {
+                            if (errorOnMissingDir) {
+                                illegal = new IllegalStateException("basedir "
+                                    + basedir
+                                    + DOES_NOT_EXIST_POSTFIX);
+                            } else {
+                                // Nothing to do - basedir does not exist
+                                return;
+                            }
+                        } else if (!basedir.isDirectory) {
+                            illegal = new IllegalStateException("basedir "
+                                + basedir
+                                + " is not a"
+                                + " directory.");
+                        }
+                        if (illegal != null) {
+                            throw illegal;
+                        }
+                    }
+                    if (isIncludedPath(TokenizedPath.EMPTY_PATH)) {
+                        if (!isExcludedPath(TokenizedPath.EMPTY_PATH)) {
+                            if (isSelected("", basedir)) {
+                                dirsIncluded.push("");
+                            } else {
+                                dirsDeselected.push("");
+                            }
+                        } else {
+                            dirsExcluded.push("");
+                        }
+                    } else {
+                        dirsNotIncluded.push("");
+                    }
+                    checkIncludePatterns();
+                    clearCaches();
+                    includes = nullIncludes ? null : includes;
+                    excludes = nullExcludes ? null : excludes;
+            } catch (ex:IOException) {
+                throw new BuildException(ex.message);
+            } finally {
+                basedir = savedBase;
+            }
+        }
+        
+        /**
+         * This routine is actually checking all the include patterns in
+         * order to avoid scanning everything under base dir.
+         * @since Ant 1.6
+         */
+        private function checkIncludePatterns():void 
+        {
+            ensureNonPatternSetsReady();
+            var newroots:Dictionary = new Dictionary();
+            
+            // put in the newroots map the include patterns without
+            // wildcard tokens
+            for (var i:int = 0; i < includePatterns.length; i++) {
+                var pattern:String = includePatterns[i].toString();
+                if (!shouldSkipPattern(pattern)) {
+                    newroots[includePatterns[i].rtrimWildcardTokens()] =
+                        pattern;
+                }
+            }
+            for each (var entry:Dictionary in includeNonPatterns.entrySet()) {
+                for (var p:String in entry)
+                {
+                    pattern = p;
+                    break;
+                }
+                if (!shouldSkipPattern(pattern)) {
+                    newroots[entry.getValue()] = pattern;
+                }
+            }
+            
+            if (newroots.hasOwnProperty(TokenizedPath.EMPTY_PATH)
+                && basedir != null) {
+                // we are going to scan everything anyway
+                scandir(basedir, "", true);
+            } else {
+                var canonBase:File = null;
+                if (basedir != null) {
+                    try {
+                        canonBase = new File(basedir.nativePath);
+                        canonBase.canonicalize();
+                    } catch (ex:IOException) {
+                        throw new BuildException(ex.message);
+                    }
+                }
+                // only scan directories that can include matched files or
+                // directories
+                for each (entry in newroots.entrySet()) {
+                    var currentPath:TokenizedPath;
+                    for (p in entry)
+                    {
+                        currentPath = p as TokenizedPath;
+                        break;
+                    }
+                    var currentelement:String = currentPath.toString();
+                    if (basedir == null
+                        && !FileUtils.isAbsolutePath(currentelement)) {
+                        continue;
+                    }
+                    var myfile:File = new File(basedir.nativePath + File.separator + currentelement);
+                    
+                    if (myfile.exists) {
+                        // may be on a case insensitive file system.  We want
+                        // the results to show what's really on the disk, so
+                        // we need to double check.
+                        try {
+                            var myCanonFile:File = new File(myfile.nativePath);
+                            myCanonFile.canonicalize();
+                            var path:String = (basedir == null)
+                                ? myCanonFile.nativePath
+                                : FILE_UTILS.removeLeadingPath(canonBase,
+                                    myCanonFile);
+                            if (!path == currentelement) {
+                                myfile = currentPath.findFile(basedir, true);
+                                if (myfile != null && basedir != null) {
+                                    currentelement = FILE_UTILS.removeLeadingPath(
+                                        basedir, myfile);
+                                    if (!currentPath.toString()
+                                        == currentelement) {
+                                        currentPath =
+                                            new TokenizedPath(currentelement);
+                                    }
+                                }
+                            }
+                        } catch (ex:IOException) {
+                            throw new BuildException(ex.message);
+                        }
+                    }
+                    
+                    if ((myfile == null || !myfile.exists) && !isCaseSensitive()) {
+                        var f:File = currentPath.findFile(basedir, false);
+                        if (f != null && f.exists) {
+                            // adapt currentelement to the case we've
+                            // actually found
+                            currentelement = (basedir == null)
+                                ? f.nativePath
+                                : FILE_UTILS.removeLeadingPath(basedir, f);
+                            myfile = f;
+                            currentPath = new TokenizedPath(currentelement);
+                        }
+                    }
+                    
+                    if (myfile != null && myfile.exists) {
+                        if (!followSymlinks && currentPath.isSymlink(basedir)) {
+                            if (!isExcludedPath(currentPath)) {
+                                notFollowedSymlinks.push(myfile.nativePath);
+                            }
+                            continue;
+                        }
+                        if (myfile.isDirectory) {
+                            if (isIncludedPath(currentPath)
+                                && currentelement.length > 0) {
+                                accountForIncludedDir(currentPath, myfile, true);
+                            }  else {
+                                scandirTokenizedPath(myfile, currentPath, true);
+                            }
+                        } else {
+                            var originalpattern:String;
+                            for (var q:* in entry)
+                            {
+                                originalpattern = entry[q];
+                            }
+                            var included:Boolean = isCaseSensitive()
+                                ? originalpattern == currentelement
+                                : originalpattern.toUpperCase() == currentelement.toUpperCase();
+                            if (included) {
+                                accountForIncludedFile(currentPath, myfile);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        
+        /**
+         * true if the pattern specifies a relative path without basedir
+         * or an absolute path not inside basedir.
+         *
+         * @since Ant 1.8.0
+         */
+        private function shouldSkipPattern(pattern:String):Boolean {
+            if (FileUtils.isAbsolutePath(pattern)) {
+                //skip abs. paths not under basedir, if set:
+                if (basedir != null
+                    && !SelectorUtils.matchPatternStart(pattern,
+                        basedir.nativePath,
+                        isCaseSensitive())) {
+                    return true;
+                }
+            } else if (basedir == null) {
+                //skip non-abs. paths if basedir == null:
+                return true;
+            }
+            return false;
+        }
+        
+        /**
+         * Clear the result caches for a scan.
+         */
+        protected function clearResults():void {
+            filesIncluded    = new Vector.<String>();
+            filesNotIncluded = new Vector.<String>();
+            filesExcluded    = new Vector.<String>();
+            filesDeselected  = new Vector.<String>();
+            dirsIncluded     = new Vector.<String>();
+            dirsNotIncluded  = new Vector.<String>();
+            dirsExcluded     = new Vector.<String>();
+            dirsDeselected   = new Vector.<String>();
+            everythingIncluded = (basedir != null);
+            scannedDirs.length = 0;
+            notFollowedSymlinks.length = 0;
+        }
+        
+        /**
+         * Top level invocation for a slow scan. A slow scan builds up a full
+         * list of excluded/included files/directories, whereas a fast scan
+         * will only have full results for included files, as it ignores
+         * directories which can't possibly hold any included files/directories.
+         * <p>
+         * Returns immediately if a slow scan has already been completed.
+         */
+        protected function slowScan():void 
+        {
+            try {
+                    // set in/excludes to reasonable defaults if needed:
+                    var nullIncludes:Boolean = (includes == null);
+                    includes = nullIncludes
+                        ? Vector.<String>([SelectorUtils.DEEP_TREE_MATCH]) : includes;
+                    var nullExcludes:Boolean = (excludes == null);
+                    excludes = nullExcludes ? new Vector.<String>(0) : excludes;
+                    
+                    var excl:Vector.<String> = dirsExcluded.slice();
+                    
+                    var notIncl:Vector.<String> = dirsNotIncluded.slice();
+                    
+                    ensureNonPatternSetsReady();
+                    
+                    processSlowScan(excl);
+                    processSlowScan(notIncl);
+                    clearCaches();
+                    includes = nullIncludes ? null : includes;
+                    excludes = nullExcludes ? null : excludes;
+            } finally {
+                    haveSlowResults = true;
+                    slowScanning = false;
+                    slowScanLock.notifyAll();
+            }
+        }
+        
+        private function processSlowScan(arr:Vector.<String>):void {
+            for (var i:int = 0; i < arr.length; i++) {
+                var path:TokenizedPath  = new TokenizedPath(arr[i]);
+                if (!couldHoldIncludedPath(path) || contentsExcluded(path)) {
+                    scandirTokenizedPath(new File(basedir.nativePath + File.separator + arr[i]), path, false);
+                }
+            }
+        }
+        
+        /**
+         * Scan the given directory for files and directories. Found files and
+         * directories are placed in their respective collections, based on the
+         * matching of includes, excludes, and the selectors.  When a directory
+         * is found, it is scanned recursively.
+         *
+         * @param dir   The directory to scan. Must not be <code>null</code>.
+         * @param vpath The path relative to the base directory (needed to
+         *              prevent problems with an absolute path when using
+         *              dir). Must not be <code>null</code>.
+         * @param fast  Whether or not this call is part of a fast scan.
+         *
+         * @see #filesIncluded
+         * @see #filesNotIncluded
+         * @see #filesExcluded
+         * @see #dirsIncluded
+         * @see #dirsNotIncluded
+         * @see #dirsExcluded
+         * @see #slowScan
+         */
+        protected function scandir(dir:File, vpath:String, fast:Boolean):void {
+            scandirTokenizedPath(dir, new TokenizedPath(vpath), fast);
+        }
+        
+        /**
+         * Scan the given directory for files and directories. Found files and
+         * directories are placed in their respective collections, based on the
+         * matching of includes, excludes, and the selectors.  When a directory
+         * is found, it is scanned recursively.
+         *
+         * @param dir   The directory to scan. Must not be <code>null</code>.
+         * @param path The path relative to the base directory (needed to
+         *              prevent problems with an absolute path when using
+         *              dir). Must not be <code>null</code>.
+         * @param fast  Whether or not this call is part of a fast scan.
+         *
+         * @see #filesIncluded
+         * @see #filesNotIncluded
+         * @see #filesExcluded
+         * @see #dirsIncluded
+         * @see #dirsNotIncluded
+         * @see #dirsExcluded
+         * @see #slowScan
+         */
+        private function scandirTokenizedPath(dir:File, path:TokenizedPath, fast:Boolean):void {
+            if (dir == null) {
+                throw new BuildException("dir must not be null.");
+            }
+            var arr:Array = dir.getDirectoryListing();
+            var arr2:Array = [];
+            for each (var f:File in arr)
+                arr2.push(f.nativePath);
+            var newfiles:Vector.<String> = Vector.<String>(arr2);;
+            if (newfiles == null) {
+                if (!dir.exists) {
+                    throw new BuildException(dir + DOES_NOT_EXIST_POSTFIX);
+                } else if (!dir.isDirectory) {
+                    throw new BuildException(dir + " is not a directory.");
+                } else {
+                    throw new BuildException("IO error scanning directory '"
+                        + dir.nativePath + "'");
+                }
+            }
+            _scandir(dir, path, fast, newfiles, new Vector.<String>());
+        }
+        
+        private function _scandir(dir:File, path:TokenizedPath, fast:Boolean,
+            newfiles:Vector.<String>, directoryNamesFollowed:Vector.<String>):void {
+                var vpath:String = path.toString();
+                if (vpath.length > 0 && vpath.charAt(vpath.length - 1) != File.separator) {
+                    vpath += File.separator;
+                }
+                
+                // avoid double scanning of directories, can only happen in fast mode
+                if (fast && hasBeenScanned(vpath)) {
+                    return;
+                }
+                if (!followSymlinks) {
+                    var noLinks:Vector.<String> = new Vector.<String>();
+                    for (i = 0; i < newfiles.length; i++) {
+                        try {
+                            if (new File(dir + File.separator + newfiles[i]).isSymbolicLink) {
+                                var name:String = vpath + newfiles[i];
+                                var file:File = new File(dir.nativePath + File.separator + newfiles[i]);
+                                (file.isDirectory
+                                    ? dirsExcluded : filesExcluded).push(name);
+                                if (!isExcluded(name)) {
+                                    notFollowedSymlinks.push(file.nativePath);
+                                }
+                            } else {
+                                noLinks.push(newfiles[i]);
+                            }
+                        } catch (ioe:IOException) {
+                            var msg:String = "IOException caught while checking "
+                                + "for links, couldn't get canonical path!";
+                            // will be caught and redirected to Ant's logging system
+                            Ant.ant.output(msg);
+                            noLinks.push(newfiles[i]);
+                        }
+                    }
+                    newfiles = noLinks.slice();
+                } else {
+                    directoryNamesFollowed.unshift(dir.nativePath);
+                }
+                
+                for (var i:int = 0; i < newfiles.length; i++) {
+                    name = vpath + newfiles[i];
+                    var newPath:TokenizedPath = new TokenizedPath("").initAsChild(path, newfiles[i]);
+                    file = new File(dir.nativePath + File.separator + newfiles[i]);
+                    var arr:Array = file.getDirectoryListing();
+                    var arr2:Array = [];
+                    for each (var f:File in arr)
+                        arr2.push(f.nativePath);
+                    var children:Vector.<String> = Vector.<String>(arr2);
+                    if (children == null || (children.length == 0 && !file.isDirectory)) {
+                        if (isIncludedPath(newPath)) {
+                            accountForIncludedFile(newPath, file);
+                        } else {
+                            everythingIncluded = false;
+                            filesNotIncluded.push(name);
+                        }
+                    } else { // dir
+                        
+                        if (followSymlinks
+                            && causesIllegalSymlinkLoop(newfiles[i], dir,
+                                directoryNamesFollowed)) {
+                            // will be caught and redirected to Ant's logging system
+                            Ant.ant.output("skipping symbolic link "
+                                + file.nativePath
+                                + " -- too many levels of symbolic"
+                                + " links.");
+                            notFollowedSymlinks.push(file.nativePath);
+                            continue;
+                        }
+                        
+                        if (isIncludedPath(newPath)) {
+                            accountForIncludedDir(newPath, file, fast, children,
+                                directoryNamesFollowed);
+                        } else {
+                            everythingIncluded = false;
+                            dirsNotIncluded.push(name);
+                            if (fast && couldHoldIncludedPath(newPath)
+                                && !contentsExcluded(newPath)) {
+                                _scandir(file, newPath, fast, children,
+                                    directoryNamesFollowed);
+                            }
+                        }
+                        if (!fast) {
+                            _scandir(file, newPath, fast, children, directoryNamesFollowed);
+                        }
+                    }
+                }
+                
+                if (followSymlinks) {
+                    directoryNamesFollowed.shift();
+                }
+            }
+        
+        /**
+         * Process included file.
+         * @param name  path of the file relative to the directory of the FileSet.
+         * @param file  included File.
+         */
+        private function accountForIncludedFile(name:TokenizedPath, file:File):void {
+            processIncluded(name, file, filesIncluded, filesExcluded,
+                filesDeselected);
+        }
+        
+        /**
+         * Process included directory.
+         * @param name path of the directory relative to the directory of
+         *             the FileSet.
+         * @param file directory as File.
+         * @param fast whether to perform fast scans.
+         */
+        private function accountForIncludedDir(name:TokenizedPath,
+            file:File, fast:Boolean,
+            children:Vector.<String> = null,
+            directoryNamesFollowed:Vector.<String> = null):void {
+                processIncluded(name, file, dirsIncluded, dirsExcluded, dirsDeselected);
+                if (fast && couldHoldIncludedPath(name) && !contentsExcluded(name)) {
+                    _scandir(file, name, fast, children, directoryNamesFollowed);
+                }
+            }
+        
+        private function processIncluded(path:TokenizedPath,
+            file:File, inc:Vector.<String>, exc:Vector.<String>,
+            des:Vector.<String>):void {
+                var name:String = path.toString();
+                if (inc.indexOf(name) != -1 || 
+                    exc.indexOf(name) != -1 || 
+                    des.indexOf(name) != -1) {
+                    return;
+                }
+                
+                var included:Boolean = false;
+                if (isExcludedPath(path)) {
+                    exc.push(name);
+                } else if (isSelected(name, file)) {
+                    included = true;
+                    inc.push(name);
+                } else {
+                    des.push(name);
+                }
+                everythingIncluded = everythingIncluded || included;
+            }
+        
+        /**
+         * Test whether or not a name matches against at least one include
+         * pattern.
+         *
+         * @param name The name to match. Must not be <code>null</code>.
+         * @return <code>true</code> when the name matches against at least one
+         *         include pattern, or <code>false</code> otherwise.
+         */
+        protected function isIncluded(name:String):Boolean {
+            return isIncludedPath(new TokenizedPath(name));
+        }
+        
+        /**
+         * Test whether or not a name matches against at least one include
+         * pattern.
+         *
+         * @param name The name to match. Must not be <code>null</code>.
+         * @return <code>true</code> when the name matches against at least one
+         *         include pattern, or <code>false</code> otherwise.
+         */
+        private function isIncludedPath(path:TokenizedPath):Boolean {
+            ensureNonPatternSetsReady();
+            
+            if (isCaseSensitive()
+                ? includeNonPatterns.containsKey(path.toString())
+                : includeNonPatterns.containsKey(path.toString().toUpperCase())) {
+                return true;
+            }
+            for (var i:int = 0; i < includePatterns.length; i++) {
+                if (includePatterns[i].matchPath(path, isCaseSensitive())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        /**
+         * Test whether or not a name matches the start of at least one include
+         * pattern.
+         *
+         * @param name The name to match. Must not be <code>null</code>.
+         * @return <code>true</code> when the name matches against the start of at
+         *         least one include pattern, or <code>false</code> otherwise.
+         */
+        protected function couldHoldIncluded(name:String):Boolean {
+            return couldHoldIncludedPath(new TokenizedPath(name));
+        }
+        
+        /**
+         * Test whether or not a name matches the start of at least one include
+         * pattern.
+         *
+         * @param tokenizedName The name to match. Must not be <code>null</code>.
+         * @return <code>true</code> when the name matches against the start of at
+         *         least one include pattern, or <code>false</code> otherwise.
+         */
+        private function couldHoldIncludedPath(tokenizedName:TokenizedPath):Boolean {
+            for (var i:int = 0; i < includePatterns.length; i++) {
+                if (couldHoldIncludedWithIncludes(tokenizedName, includePatterns[i])) {
+                    return true;
+                }
+            }
+            for each (var iter:TokenizedPath in includeNonPatterns) {
+                if (couldHoldIncludedWithIncludes(tokenizedName,
+                    iter.toPattern())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        /**
+         * Test whether or not a name matches the start of the given
+         * include pattern.
+         *
+         * @param tokenizedName The name to match. Must not be <code>null</code>.
+         * @return <code>true</code> when the name matches against the start of the
+         *         include pattern, or <code>false</code> otherwise.
+         */
+        private function couldHoldIncludedWithIncludes(tokenizedName:TokenizedPath,
+            tokenizedInclude:TokenizedPattern):Boolean {
+                return tokenizedInclude.matchStartOf(tokenizedName, isCaseSensitive())
+                    && isMorePowerfulThanExcludes(tokenizedName.toString())
+                    && isDeeper(tokenizedInclude, tokenizedName);
+            }
+        
+        /**
+         * Verify that a pattern specifies files deeper
+         * than the level of the specified file.
+         * @param pattern the pattern to check.
+         * @param name the name to check.
+         * @return whether the pattern is deeper than the name.
+         * @since Ant 1.6.3
+         */
+        private function isDeeper(pattern:TokenizedPattern, name:TokenizedPath):Boolean {
+            return pattern.containsPattern(SelectorUtils.DEEP_TREE_MATCH)
+                || pattern.depth() > name.depth();
+        }
+        
+        /**
+         *  Find out whether one particular include pattern is more powerful
+         *  than all the excludes.
+         *  Note:  the power comparison is based on the length of the include pattern
+         *  and of the exclude patterns without the wildcards.
+         *  Ideally the comparison should be done based on the depth
+         *  of the match; that is to say how many file separators have been matched
+         *  before the first ** or the end of the pattern.
+         *
+         *  IMPORTANT : this function should return false "with care".
+         *
+         *  @param name the relative path to test.
+         *  @return true if there is no exclude pattern more powerful than
+         *  this include pattern.
+         *  @since Ant 1.6
+         */
+        private function isMorePowerfulThanExcludes(name:String):Boolean {
+            const soughtexclude:String  =
+                name + File.separator + SelectorUtils.DEEP_TREE_MATCH;
+            for (var counter:int = 0; counter < excludePatterns.length; counter++) {
+                if (excludePatterns[counter].toString() == soughtexclude)  {
+                    return false;
+                }
+            }
+            return true;
+        }
+        
+        /**
+         * Test whether all contents of the specified directory must be excluded.
+         * @param path the path to check.
+         * @return whether all the specified directory's contents are excluded.
+         */
+        /* package */ private function contentsExcluded(path:TokenizedPath):Boolean {
+            for (var i:int = 0; i < excludePatterns.length; i++) {
+                if (excludePatterns[i].endsWith(SelectorUtils.DEEP_TREE_MATCH)
+                    && excludePatterns[i].withoutLastToken()
+                    .matchPath(path, isCaseSensitive())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        /**
+         * Test whether or not a name matches against at least one exclude
+         * pattern.
+         *
+         * @param name The name to match. Must not be <code>null</code>.
+         * @return <code>true</code> when the name matches against at least one
+         *         exclude pattern, or <code>false</code> otherwise.
+         */
+        protected function isExcluded(name:String):Boolean {
+            return isExcludedPath(new TokenizedPath(name));
+        }
+        
+        /**
+         * Test whether or not a name matches against at least one exclude
+         * pattern.
+         *
+         * @param name The name to match. Must not be <code>null</code>.
+         * @return <code>true</code> when the name matches against at least one
+         *         exclude pattern, or <code>false</code> otherwise.
+         */
+        private function isExcludedPath(name:TokenizedPath):Boolean {
+            ensureNonPatternSetsReady();
+            
+            if (isCaseSensitive()
+                ? excludeNonPatterns.hasOwnProperty(name.toString())
+                : excludeNonPatterns.hasOwnProperty(name.toString().toUpperCase())) {
+                return true;
+            }
+            for (var i:int = 0; i < excludePatterns.length; i++) {
+                if (excludePatterns[i].matchPath(name, isCaseSensitive())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        /**
+         * Test whether a file should be selected.
+         *
+         * @param name the filename to check for selecting.
+         * @param file the java.io.File object for this filename.
+         * @return <code>false</code> when the selectors says that the file
+         *         should not be selected, <code>true</code> otherwise.
+         */
+        protected function isSelected(name:String, file:File):Boolean {
+            if (selectors != null) {
+                for (var i:int = 0; i < selectors.length; i++) {
+                    if (!selectors[i].isSelected(basedir, name, file)) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        
+        /**
+         * Return the names of the files which matched at least one of the
+         * include patterns and none of the exclude patterns.
+         * The names are relative to the base directory.
+         *
+         * @return the names of the files which matched at least one of the
+         *         include patterns and none of the exclude patterns.
+         */
+        public function getIncludedFiles():Vector.<String> {
+            var files:Vector.<String>;
+                files = filesIncluded.slice();
+            files.sort(0);
+            return files;
+        }
+        
+        /**
+         * Return the count of included files.
+         * @return <code>int</code>.
+         * @since Ant 1.6.3
+         */
+        public function getIncludedFilesCount():int {
+            if (filesIncluded == null) {
+                throw new IllegalStateException("Must call scan() first");
+            }
+            return filesIncluded.length;
+        }
+        
+        /**
+         * Return the names of the files which matched none of the include
+         * patterns. The names are relative to the base directory. This involves
+         * performing a slow scan if one has not already been completed.
+         *
+         * @return the names of the files which matched none of the include
+         *         patterns.
+         *
+         * @see #slowScan
+         */
+        public function getNotIncludedFiles():Vector.<String> {
+            slowScan();
+            var files:Vector.<String> = filesNotIncluded.slice();
+            return files;
+        }
+        
+        /**
+         * Return the names of the files which matched at least one of the
+         * include patterns and at least one of the exclude patterns.
+         * The names are relative to the base directory. This involves
+         * performing a slow scan if one has not already been completed.
+         *
+         * @return the names of the files which matched at least one of the
+         *         include patterns and at least one of the exclude patterns.
+         *
+         * @see #slowScan
+         */
+        public function getExcludedFiles():Vector.<String> {
+            slowScan();
+            var files:Vector.<String> = filesExcluded.slice();
+            return files;
+        }
+        
+        /**
+         * <p>Return the names of the files which were selected out and
+         * therefore not ultimately included.</p>
+         *
+         * <p>The names are relative to the base directory. This involves
+         * performing a slow scan if one has not already been completed.</p>
+         *
+         * @return the names of the files which were deselected.
+         *
+         * @see #slowScan
+         */
+        public function getDeselectedFiles():Vector.<String> {
+            slowScan();
+            var files:Vector.<String> = filesDeselected.slice();
+            return files;
+        }
+        
+        /**
+         * Return the names of the directories which matched at least one of the
+         * include patterns and none of the exclude patterns.
+         * The names are relative to the base directory.
+         *
+         * @return the names of the directories which matched at least one of the
+         * include patterns and none of the exclude patterns.
+         */
+        public function getIncludedDirectories():Vector.<String> {
+            var directories:Vector.<String>;
+                directories = dirsIncluded.slice();
+            directories.sort(0);
+            return directories;
+        }
+        
+        /**
+         * Return the count of included directories.
+         * @return <code>int</code>.
+         * @since Ant 1.6.3
+         */
+        public function getIncludedDirsCount():int {
+            if (dirsIncluded == null) {
+                throw new IllegalStateException("Must call scan() first");
+            }
+            return dirsIncluded.length;
+        }
+        
+        /**
+         * Return the names of the directories which matched none of the include
+         * patterns. The names are relative to the base directory. This involves
+         * performing a slow scan if one has not already been completed.
+         *
+         * @return the names of the directories which matched none of the include
+         * patterns.
+         *
+         * @see #slowScan
+         */
+        public function getNotIncludedDirectories():Vector.<String> {
+            slowScan();
+            var directories:Vector.<String> = dirsNotIncluded.slice();
+            return directories;
+        }
+        
+        /**
+         * Return the names of the directories which matched at least one of the
+         * include patterns and at least one of the exclude patterns.
+         * The names are relative to the base directory. This involves
+         * performing a slow scan if one has not already been completed.
+         *
+         * @return the names of the directories which matched at least one of the
+         * include patterns and at least one of the exclude patterns.
+         *
+         * @see #slowScan
+         */
+        public function getExcludedDirectories():Vector.<String> {
+            slowScan();
+            var directories:Vector.<String> = dirsExcluded.slice();
+            return directories;
+        }
+        
+        /**
+         * <p>Return the names of the directories which were selected out and
+         * therefore not ultimately included.</p>
+         *
+         * <p>The names are relative to the base directory. This involves
+         * performing a slow scan if one has not already been completed.</p>
+         *
+         * @return the names of the directories which were deselected.
+         *
+         * @see #slowScan
+         */
+        public function getDeselectedDirectories():Vector.<String> {
+            slowScan();
+            var directories:Vector.<String> = dirsDeselected.slice();
+            return directories;
+        }
+        
+        /**
+         * Absolute paths of all symbolic links that haven't been followed
+         * but would have been followed had followsymlinks been true or
+         * maxLevelsOfSymlinks been bigger.
+         *
+         * @since Ant 1.8.0
+         */
+        public function getNotFollowedSymlinks():Vector.<String> {
+            var links:Vector.<String>;
+                links = notFollowedSymlinks.slice();
+            links.sort(0);
+            return links;
+        }
+        
+        /**
+         * Add default exclusions to the current exclusions set.
+         */
+        public function addDefaultExcludes():void 
+        {
+            var excludesLength:int = excludes == null ? 0 : excludes.length;
+            var newExcludes:Vector.<String>;
+            var defaultExcludesTemp:Vector.<String> = getDefaultExcludes();
+            newExcludes = defaultExcludesTemp.slice();
+            for (var i:int = 0; i < defaultExcludesTemp.length; i++) {
+                newExcludes.push(
+                    defaultExcludesTemp[i].replace(/\//g, File.separator)
+                    .replace(/\\/g, File.separator));
+            }
+            excludes = newExcludes;
+        }
+        
+        /**
+         * Get the named resource.
+         * @param name path name of the file relative to the dir attribute.
+         *
+         * @return the resource with the given name.
+         * @since Ant 1.5.2
+         */
+        public function getResource(name:String):Resource {
+            return new FileResource(basedir, name);
+        }
+        
+        /**
+         * Has the directory with the given path relative to the base
+         * directory already been scanned?
+         *
+         * <p>Registers the given directory as scanned as a side effect.</p>
+         *
+         * @since Ant 1.6
+         */
+        private function hasBeenScanned(vpath:String):Boolean {
+            return !scannedDirs.push(vpath);
+        }
+        
+        /**
+         * This method is of interest for testing purposes.  The returned
+         * Set is live and should not be modified.
+         * @return the Set of relative directory names that have been scanned.
+         */
+        /* package-private */private function getScannedDirs():Vector.<String> {
+            return scannedDirs;
+        }
+        
+        /**
+         * Clear internal caches.
+         *
+         * @since Ant 1.6
+         */
+        private function clearCaches():void {
+            includeNonPatterns.clear();
+            excludeNonPatterns.clear();
+            includePatterns = null;
+            excludePatterns = null;
+            areNonPatternSetsReady = false;
+        }
+        
+        /**
+         * Ensure that the in|exclude &quot;patterns&quot;
+         * have been properly divided up.
+         *
+         * @since Ant 1.6.3
+         */
+        /* package */private function ensureNonPatternSetsReady():void {
+            if (!areNonPatternSetsReady) {
+                includePatterns = fillNonPatternSet(includeNonPatterns, includes);
+                excludePatterns = fillNonPatternSet(excludeNonPatterns, excludes);
+                areNonPatternSetsReady = true;
+            }
+        }
+        
+        /**
+         * Add all patterns that are not real patterns (do not contain
+         * wildcards) to the set and returns the real patterns.
+         *
+         * @param map Map to populate.
+         * @param patterns String[] of patterns.
+         * @since Ant 1.8.0
+         */
+        private function fillNonPatternSet(map:Object, patterns:Vector.<String>):Vector.<TokenizedPattern> {
+            var al:Vector.<TokenizedPattern> = new Vector.<TokenizedPattern>(patterns.length);
+            for (var i:int = 0; i < patterns.length; i++) {
+                if (!SelectorUtils.hasWildcards(patterns[i])) {
+                    var s:String = isCaseSensitive()
+                        ? patterns[i] : patterns[i].toUpperCase();
+                    map[s] = new TokenizedPath(s);
+                } else {
+                    al.push(new TokenizedPattern(patterns[i]));
+                }
+            }
+            return al;
+        }
+        
+        /**
+         * Would following the given directory cause a loop of symbolic
+         * links deeper than allowed?
+         *
+         * <p>Can only happen if the given directory has been seen at
+         * least more often than allowed during the current scan and it is
+         * a symbolic link and enough other occurences of the same name
+         * higher up are symbolic links that point to the same place.</p>
+         *
+         * @since Ant 1.8.0
+         */
+        private function causesIllegalSymlinkLoop(dirName:String, parent:File,
+            directoryNamesFollowed:Vector.<String>):Boolean {
+                try {
+                    if (directoryNamesFollowed.length >= maxLevelsOfSymlinks
+                        && CollectionUtils.frequency(directoryNamesFollowed, dirName)
+                        >= maxLevelsOfSymlinks
+                        && new File(parent.nativePath + File.separator + dirName).isSymbolicLink) {
+                        
+                        var files:Vector.<String> = new Vector.<String>();
+                        var f:File = FILE_UTILS.resolveFile(parent, dirName);
+                        f.canonicalize();
+                        var target:String = f.nativePath;
+                        files.push(target);
+                        
+                        var relPath:String = "";
+                        for each (var dir:String in directoryNamesFollowed) {
+                            relPath += "../";
+                            if (dirName == dir) {
+                                f = FILE_UTILS.resolveFile(parent, relPath + dir);
+                                f.canonicalize();
+                                files.push(f.nativePath);
+                                if (files.length > maxLevelsOfSymlinks
+                                    && CollectionUtils.frequency(files, target)
+                                    > maxLevelsOfSymlinks) {
+                                    return true;
+                                }
+                            }
+                        }
+                        
+                    }
+                    return false;
+                } catch (ex:IOException) {
+                    throw new BuildException("Caught error while checking for"
+                        + " symbolic links" + ex.message);
+                }
+                return false;
+            }
+        
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileProvider.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileProvider.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileProvider.as
new file mode 100644
index 0000000..e8a4773
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileProvider.as
@@ -0,0 +1,27 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags.filesetClasses
+{
+    import flash.filesystem.File;
+    
+    public interface FileProvider
+    {
+        function getFile():File;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileResource.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileResource.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileResource.as
new file mode 100644
index 0000000..3d00d27
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileResource.as
@@ -0,0 +1,146 @@
+/*
+*  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.flex.ant.tags.filesetClasses
+{
+    import flash.filesystem.File;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.BuildException;
+    
+    /**
+     * Ported from org.apache.tools.ant.types.Resource.java on 12/3/13. 
+     * Describes a "File-like" resource (File, ZipEntry, etc.).
+     *
+     * This class is meant to be used by classes needing to record path
+     * and date/time information about a file, a zip entry or some similar
+     * resource (URL, archive in a version control repository, ...).
+     *
+     * @since Ant 1.5.2
+     * @see org.apache.tools.ant.types.resources.Touchable
+     */
+    public class FileResource extends Resource implements FileProvider
+    {
+        private static const FILE_UTILS:FileUtils = FileUtils.getFileUtils();
+
+        private var file:File;
+        private var baseDir:File;
+
+        /**
+         * Construct a new FileResource using the specified basedir and relative name.
+         * @param b      the basedir as File.
+         * @param name   the relative filename.
+         */
+        public function FileResource(b:File, name:String) {
+            super(name);
+            this.baseDir = b;
+            this.file = FILE_UTILS.resolveFile(b, name);
+        }
+
+        /**
+         * Set the File for this FileResource.
+         * @param f the File to be represented.
+         */
+        public function setFile(f:File):void {
+            checkAttributesAllowed();
+            file = f;
+            if (f != null && (getBaseDir() == null || !FILE_UTILS.isLeadingPath(getBaseDir(), f))) {
+                setBaseDir(f.parent);
+            }
+        }
+        
+        /**
+         * Get the file represented by this FileResource.
+         * @return the File.
+         */
+        public function getFile():File {
+            if (isReference()) {
+                return FileResource(getCheckedRef()).getFile();
+            }
+            dieOnCircularReference();
+                if (file == null) {
+                    //try to resolve file set via basedir/name property setters:
+                    var d:File = getBaseDir();
+                    var n:String = super.getName();
+                    if (n != null) {
+                        setFile(FILE_UTILS.resolveFile(d, n));
+                    }
+                }
+            return file;
+        }
+        
+        /**
+         * Set the basedir for this FileResource.
+         * @param b the basedir as File.
+         */
+        public function setBaseDir(b:File):void {
+            checkAttributesAllowed();
+            baseDir = b;
+        }
+        
+        /**
+         * Return the basedir to which the name is relative.
+         * @return the basedir as File.
+         */
+        public function getBaseDir():File {
+            if (isReference()) {
+                return FileResource(getCheckedRef()).getBaseDir();
+            }
+            dieOnCircularReference();
+            return baseDir;
+        }
+        
+        /**
+         * Overrides the super version.
+         * @param r the Reference to set.
+         */
+        override public function setRefid(r:Reference):void {
+            if (file != null || baseDir != null) {
+                throw tooManyAttributes();
+            }
+            super.setRefid(r);
+        }
+        
+        /**
+         * Get the name of this FileResource.  If the basedir is set,
+         * the name will be relative to that.  Otherwise the basename
+         * only will be returned.
+         * @return the name of this resource.
+         */
+        override public function getName():String {
+            if (isReference()) {
+                return Resource(getCheckedRef()).getName();
+            }
+            var b:File = getBaseDir();
+            return b == null ? getNotNullFile().name
+                : FILE_UTILS.removeLeadingPath(b, getNotNullFile());
+        }
+
+        /**
+         * Get the file represented by this FileResource, ensuring it is not null.
+         * @return the not-null File.
+         * @throws BuildException if file is null.
+         */
+        protected function getNotNullFile():File {
+            if (getFile() == null) {
+                throw new BuildException("file attribute is null!");
+            }
+            dieOnCircularReference();
+            return getFile();
+        }
+        
+
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileSelector.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileSelector.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileSelector.as
new file mode 100644
index 0000000..92c9376
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileSelector.as
@@ -0,0 +1,27 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags.filesetClasses
+{
+    import flash.filesystem.File;
+            
+    public interface FileSelector
+    {
+        function isSelected(base:File, name:String, file:File):Boolean;
+   }
+}
\ No newline at end of file


[10/14] git commit: [flex-utilities] [refs/heads/develop] - do token replacement on all attributes

Posted by ah...@apache.org.
do token replacement on all attributes


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/00bf3f95
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/00bf3f95
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/00bf3f95

Branch: refs/heads/develop
Commit: 00bf3f958cd78d6cc0e80c3961abc9579fd86edb
Parents: 1f7c230
Author: Alex Harui <ah...@apache.org>
Authored: Mon Dec 9 14:00:12 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Mon Dec 9 14:00:12 2013 -0800

----------------------------------------------------------------------
 ant_on_air/src/org/apache/flex/ant/tags/Property.as              | 4 ++--
 .../src/org/apache/flex/ant/tags/supportClasses/TagHandler.as    | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/00bf3f95/ant_on_air/src/org/apache/flex/ant/tags/Property.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Property.as b/ant_on_air/src/org/apache/flex/ant/tags/Property.as
index a5097cc..73fb2c1 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/Property.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Property.as
@@ -101,11 +101,11 @@ package org.apache.flex.ant.tags
         {
             if (name == "file")
             {
-                fileName = ant.getValue(value, context);
+                fileName = value;
             }
             else if (name == "value")
             {
-                this.value = ant.getValue(value, context);
+                this.value = value;
             }
             else if (name == "environment")
             {

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/00bf3f95/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TagHandler.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TagHandler.as b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TagHandler.as
index 70c215d..3b3b1d2 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TagHandler.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/TagHandler.as
@@ -71,7 +71,7 @@ package org.apache.flex.ant.tags.supportClasses
         {
             var n:int = xmlList.length();
             for (var i:int = 0; i < n; i++)
-                processAttribute(xmlList[i].name().toString(), xmlList[i].toString());
+                processAttribute(xmlList[i].name().toString(), ant.getValue(xmlList[i].toString(), context));
         }
         
         /**


[09/14] git commit: [flex-utilities] [refs/heads/develop] - if no children were created, return 0

Posted by ah...@apache.org.
if no children were created, return 0


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/1f7c230b
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/1f7c230b
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/1f7c230b

Branch: refs/heads/develop
Commit: 1f7c230ba1db90edb58736e1e5c61ef3efe3d6f4
Parents: eef49ca
Author: Alex Harui <ah...@apache.org>
Authored: Mon Dec 9 13:58:59 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Mon Dec 9 13:58:59 2013 -0800

----------------------------------------------------------------------
 .../org/apache/flex/ant/tags/supportClasses/ParentTagHandler.as    | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/1f7c230b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/ParentTagHandler.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/ParentTagHandler.as b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/ParentTagHandler.as
index f6c2941..81e6cc3 100644
--- a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/ParentTagHandler.as
+++ b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/ParentTagHandler.as
@@ -44,6 +44,8 @@ package org.apache.flex.ant.tags.supportClasses
         
         public function get numChildren():int
         {
+            if (!children) return 0;
+            
             return children.length;
         }
     }


[05/14] port DirectoryScanner from Ant code base and hook up FileSet to it

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileUtils.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileUtils.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileUtils.as
new file mode 100644
index 0000000..d0409ca
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/FileUtils.as
@@ -0,0 +1,657 @@
+/*
+*  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.flex.ant.tags.filesetClasses
+{
+    import flash.filesystem.File;
+    import flash.system.Capabilities;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.BuildException;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.IOException;
+    
+    /**
+     * Ported from org.apache.tools.ant.util on 12/3/13.  File copying
+     * was removed.  So was tempfile, newfile, readfully and contentEquals.
+     * 
+     * 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 const PRIMARY_INSTANCE:FileUtils = new FileUtils();
+                
+        private static const ON_WINDOWS:Boolean = Capabilities.os.indexOf("Win") != -1;
+        private static const ON_DOS:Boolean = Capabilities.os.indexOf("Win") != -1;
+                
+        /**
+         * The granularity of timestamps under Unix.
+         */
+        public static const UNIX_FILE_TIMESTAMP_GRANULARITY:int = 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 const NTFS_FILE_TIMESTAMP_GRANULARITY:int = 1;
+                
+        /**
+         * 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 function getFileUtils():FileUtils {
+            return PRIMARY_INSTANCE;
+        }
+        
+        /**
+         * Empty constructor.
+         */
+        public function FileUtils() {
+        }
+        
+        /**
+         * Get the URL for a file taking into account # characters.
+         *
+         * @param file the file whose URL representation is required.
+         * @return The FileURL value.
+         * @throws MalformedURLException if the URL representation cannot be
+         *      formed.
+        public URL getFileURL(File file) throws MalformedURLException {
+            return new URL(file.toURI().toASCIIString());
+        }
+         */
+                
+        /**
+         * Calls File.setLastModified(long time). Originally written to
+         * to dynamically bind to that call on Java1.2+.
+         *
+         * @param file the file whose modified time is to be set
+         * @param time the time to which the last modified time is to be set.
+         *             if this is -1, the current time is used.
+         */
+        public function setFileLastModified(file:File, time:Number):void {
+            throw new Error("not supported in AIR");
+        }
+        
+        /**
+         * Interpret the filename as a file relative to the given file
+         * unless the filename already represents an absolute filename.
+         * Differs from <code>new File(file, filename)</code> in that
+         * the resulting File's path will always be a normalized,
+         * absolute pathname.  Also, if it is determined that
+         * <code>filename</code> is context-relative, <code>file</code>
+         * will be discarded and the reference will be resolved using
+         * available context/state information about the filesystem.
+         *
+         * @param file the "reference" file for relative paths. This
+         * instance must be an absolute file and must not contain
+         * &quot;./&quot; or &quot;../&quot; sequences (same for \ instead
+         * of /).  If it is null, this call is equivalent to
+         * <code>new java.io.File(filename).getAbsoluteFile()</code>.
+         *
+         * @param filename a file name.
+         *
+         * @return an absolute file.
+         * @throws java.lang.NullPointerException if filename is null.
+         */
+        public function resolveFile(file:File, filename:String):File {
+            if (!isAbsolutePath(filename)) {
+                var sep:String = File.separator;
+                filename = filename.replace(/\//g, sep).replace(/\\/g, sep);
+                if (isContextRelativePath(filename)) {
+                    file = null;
+                    // on cygwin, our current directory can be a UNC;
+                    // assume user.dir is absolute or all hell breaks loose...
+                    var udir:String = File.userDirectory.nativePath;
+                    if (filename.charAt(0) == sep && udir.charAt(0) == sep) {
+                        filename = dissect(udir)[0] + filename.substring(1);
+                    }
+                }
+                filename = new File(file.nativePath + File.separator + filename).nativePath;
+            }
+            return normalize(filename);
+        }
+        
+        /**
+         * On DOS and NetWare, the evaluation of certain file
+         * specifications is context-dependent.  These are filenames
+         * beginning with a single separator (relative to current root directory)
+         * and filenames with a drive specification and no intervening separator
+         * (relative to current directory of the specified root).
+         * @param filename the filename to evaluate.
+         * @return true if the filename is relative to system context.
+         * @throws java.lang.NullPointerException if filename is null.
+         * @since Ant 1.7
+         */
+        public static function isContextRelativePath(filename:String):Boolean {
+            if (!ON_DOS || filename.length == 0) {
+                return false;
+            }
+            var sep:String = File.separator;
+            filename = filename.replace(/\//g, sep).replace(/\\/g, sep);
+            var c:String = filename.charAt(0);
+            var len:int = filename.length;
+            return (c == sep && (len == 1 || filename.charAt(1) != sep))
+            || (Character.isLetter(c) && len > 1
+                && filename.indexOf(':') == 1
+                && (len == 2 || filename.charAt(2) != sep));
+        }
+        
+                
+        /**
+         * 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 function isAbsolutePath(filename:String):Boolean {
+            var len:int = filename.length;
+            if (len == 0) {
+                return false;
+            }
+            var sep:String = File.separator;
+            filename = filename.replace(/\//g, sep).replace(/\\/g, sep);
+            var c:String = filename.charAt(0);
+            if (ON_DOS)
+                return (c == sep);
+            
+            if (c == sep) {
+                // CheckStyle:MagicNumber OFF
+                if (!(ON_DOS && len > 4 && filename.charAt(1) == sep)) {
+                    return false;
+                }
+                // CheckStyle:MagicNumber ON
+                var nextsep:int = filename.indexOf(sep, 2);
+                return nextsep > 2 && nextsep + 1 < len;
+            }
+            var colon:int = filename.indexOf(':');
+            return (Character.isLetter(c) && colon == 1
+                && filename.length > 2 && filename.charAt(2) == sep);
+        }
+        
+        /**
+         * Translate a path into its native (platform specific) format.
+         * <p>
+         * This method uses PathTokenizer to separate the input path
+         * into its components. This handles DOS style paths in a relatively
+         * sensible way. The file separators are then converted to their platform
+         * specific versions.
+         *
+         * @param toProcess The path to be translated.
+         *                  May be <code>null</code>.
+         *
+         * @return the native version of the specified path or
+         *         an empty string if the path is <code>null</code> or empty.
+         *
+         * @since ant 1.7
+         * @see PathTokenizer
+         */
+        public static function translatePath(toProcess:String):String {
+            if (toProcess == null || toProcess.length == 0) {
+                return "";
+            }
+            var path:String = "";
+            var tokenizer:PathTokenizer = new PathTokenizer(toProcess);
+            while (tokenizer.hasMoreTokens()) {
+                var pathComponent:String = tokenizer.nextToken();
+                pathComponent = pathComponent.replace(/\//g, File.separator);
+                pathComponent = pathComponent.replace(/\\/g, File.separator);
+                if (path.length != 0) {
+                    path += File.separator;
+                }
+                path += pathComponent;
+            }
+            return path;
+        }
+        
+        /**
+         * &quot;Normalize&quot; the given absolute path.
+         *
+         * <p>This includes:
+         * <ul>
+         *   <li>Uppercase the drive letter if there is one.</li>
+         *   <li>Remove redundant slashes after the drive spec.</li>
+         *   <li>Resolve all ./, .\, ../ and ..\ sequences.</li>
+         *   <li>DOS style paths that start with a drive letter will have
+         *     \ as the separator.</li>
+         * </ul>
+         * Unlike {@link File#getCanonicalPath()} this method
+         * specifically does not resolve symbolic links.
+         *
+         * @param path the path to be normalized.
+         * @return the normalized version of the path.
+         *
+         * @throws java.lang.NullPointerException if path is null.
+         */
+        public function normalize(path:String):File {
+            var s:Array = new Array();
+            var dissect:Vector.<String> = dissect(path);
+            s.push(dissect[0]);
+            
+            var tok:StringTokenizer = new StringTokenizer(dissect[1], File.separator);
+            while (tok.hasMoreTokens()) {
+                var thisToken:String = tok.nextToken();
+                if ("." == thisToken) {
+                    continue;
+                }
+                if (".." == thisToken) {
+                    if (s.size() < 2) {
+                        // Cannot resolve it, so skip it.
+                        return new File(path);
+                    }
+                    s.pop();
+                } else { // plain component
+                    s.push(thisToken);
+                }
+            }
+            var sb:String = "";
+            var size:int = s.size();
+            for (var i:int = 0; i < size; i++) {
+                if (i > 1) {
+                    // not before the filesystem root and not after it, since root
+                    // already contains one
+                    sb += File.separator;
+                }
+                sb += s.elementAt(i);
+            }
+            return new File(sb);
+        }
+        
+        /**
+         * 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 function dissect(path:String):Vector.<String> {
+            var sep:String = File.separator;
+            path = path.replace(/\//g, sep).replace(/\\/g, sep);
+            
+            // make sure we are dealing with an absolute path
+            if (!isAbsolutePath(path)) {
+                throw new BuildException(path + " is not an absolute path");
+            }
+            var root:String = null;
+            var colon:int = path.indexOf(':');
+            if (colon > 0 && ON_DOS) {
+                
+                var next:int = colon + 1;
+                root = path.substring(0, next);
+                var ca:Vector.<String> = Vector.<String>(path.split());
+                root += sep;
+                //remove the initial separator; the root has it.
+                next = (ca[next] == sep) ? next + 1 : next;
+                
+                var sbPath:String = "";
+                // Eliminate consecutive slashes after the drive spec:
+                for (var i:int = next; i < ca.length; i++) {
+                    if (ca[i] != sep || ca[i - 1] != sep) {
+                        sbPath += ca[i];
+                    }
+                }
+                path = sbPath;
+            } else if (path.length > 1 && path.charAt(1) == sep) {
+                // UNC drive
+                var nextsep:int = 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 Vector.<String>([root, path]);
+        }
+        
+       
+        /**
+         * This was originally an emulation of {@link File#getParentFile} for JDK 1.1, but it is now
+         * implemented using that method (Ant 1.6.3 onwards).
+         *
+         * @param f the file whose parent is required.
+         * @return the given file's parent, or null if the file does not have a parent.
+         * @since 1.10
+         * @deprecated since 1.7. Just use {@link File#getParentFile} directly.
+         */
+        public function getParentFile(f:File):File {
+            return (f == null) ? null : f.parent;
+        }
+        
+        /**
+         * Checks whether a given file is a symbolic link.
+         *
+         * <p>It doesn't really test for symbolic links but whether the
+         * canonical and absolute paths of the file are identical--this
+         * may lead to false positives on some platforms.</p>
+         *
+         * @param parent the parent directory of the file to test
+         * @param name the name of the file to test.
+         *
+         * @return true if the file is a symbolic link.
+         * @throws IOException on error.
+         * @since Ant 1.5
+         * @deprecated use SymbolicLinkUtils instead
+         */
+        public function isSymbolicLink(parent:File, name:String):Boolean
+        {
+            if (parent == null) {
+                return new File(name).isSymbolicLink;
+            }
+            return new File(parent.nativePath + File.separator + name).isSymbolicLink;
+        }
+        
+        /**
+         * Removes a leading path from a second path.
+         *
+         * @param leading The leading path, must not be null, must be absolute.
+         * @param path The path to remove from, must not be null, must be absolute.
+         *
+         * @return path's normalized absolute if it doesn't start with
+         * leading; path's path with leading's path removed otherwise.
+         *
+         * @since Ant 1.5
+         */
+        public function removeLeadingPath(leading:File, path:File):String {
+            var l:String = normalize(leading.nativePath).nativePath;
+            var p:String = normalize(path.nativePath).nativePath;
+            if (l == p) {
+                return "";
+            }
+            // ensure that l ends with a /
+            // so we never think /foo was a parent directory of /foobar
+            if (l.charAt(l.length - 1) != File.separator) {
+                l += File.separator;
+            }
+            return (p.indexOf(l) == 0) ? p.substring(l.length) : p;
+        }
+        
+        /**
+         * Learn whether one path "leads" another.
+         * @param leading The leading path, must not be null, must be absolute.
+         * @param path The path to remove from, must not be null, must be absolute.
+         * @return true if path starts with leading; false otherwise.
+         * @since Ant 1.7
+         */
+        public function isLeadingPath(leading:File, path:File):Boolean {
+            var l:String = normalize(leading.nativePath).nativePath;
+            var p:String = normalize(path.nativePath).nativePath;
+            if (l == p) {
+                return true;
+            }
+            // ensure that l ends with a /
+            // so we never think /foo was a parent directory of /foobar
+            if (l.charAt(l.length - 1) != File.separator) {
+                l += File.separator;
+            }
+            return p.indexOf(l) == 0;
+        }
+        
+        /**
+         * Compares two filenames.
+         *
+         * <p>Unlike java.io.File#equals this method will try to compare
+         * the absolute paths and &quot;normalize&quot; the filenames
+         * before comparing them.</p>
+         *
+         * @param f1 the file whose name is to be compared.
+         * @param f2 the other file whose name is to be compared.
+         *
+         * @return true if the file are for the same file.
+         *
+         * @since Ant 1.5.3
+         */
+        public function fileNameEquals(f1:File, f2:File):Boolean {
+            return normalize(f1.nativePath).nativePath ==
+                normalize(f2.nativePath).nativePath;
+        }
+        
+        /**
+         * Are the two File instances pointing to the same object on the
+         * file system?
+         * @since Ant 1.8.2
+         */
+        public function areSame(f1:File, f2:File):Boolean {
+            if (f1 == null && f2 == null) {
+                return true;
+            }
+            if (f1 == null || f2 == null) {
+                return false;
+            }
+            var f1Normalized:File = normalize(f1.nativePath);
+            var f2Normalized:File = normalize(f2.nativePath);
+            if (f1Normalized.nativePath == f2Normalized.nativePath)
+                return true;
+            f1Normalized.canonicalize();
+            f2Normalized.canonicalize();
+            return f1Normalized.nativePath == f2Normalized.nativePath;
+        }
+        
+        /**
+         * Renames a file, even if that involves crossing file system boundaries.
+         *
+         * <p>This will remove <code>to</code> (if it exists), ensure that
+         * <code>to</code>'s parent directory exists and move
+         * <code>from</code>, which involves deleting <code>from</code> as
+         * well.</p>
+         *
+         * @param from the file to move.
+         * @param to the new file name.
+         *
+         * @throws IOException if anything bad happens during this
+         * process.  Note that <code>to</code> may have been deleted
+         * already when this happens.
+         *
+         * @since Ant 1.6
+         */
+        public function rename(from:File, to:File):void {
+            // identical logic lives in Move.renameFile():
+            from.canonicalize()
+            from = normalize(from.nativePath);
+            to = normalize(to.nativePath);
+            if (!from.exists) {
+                Ant.ant.output("Cannot rename nonexistent file " + from);
+                return;
+            }
+            if (from.nativePath == to.nativePath) {
+                Ant.ant.output("Rename of " + from + " to " + to + " is a no-op.");
+                return;
+            }
+            if (to.exists)
+                to.deleteFile();
+            if (to.exists && !(areSame(from, to))) {
+                throw new IOException("Failed to delete " + to + " while trying to rename " + from);
+            }
+            var parent:File = to.parent;
+            if (parent != null && !parent.exists && !parent.createDirectory()) {
+                throw new IOException("Failed to create directory " + parent
+                    + " while trying to rename " + from);
+            }
+            if (!from.moveTo(to)) {
+                from.copyTo(to);
+                from.deleteFile();
+                if (from.exists) {
+                    throw new IOException("Failed to delete " + from + " while trying to rename it.");
+                }
+            }
+        }
+        
+        /**
+         * Get the granularity of file timestamps. The choice is made based on OS, which is
+         * incorrect--it should really be by filesystem. We do not have an easy way to probe for file
+         * systems, however, so this heuristic gives us a decent default.
+         *
+         * @return the difference, in milliseconds, which two file timestamps must have in order for the
+         *         two files to be considered to have different timestamps.
+         */
+        public function getFileTimestampGranularity():Number {
+            if (ON_WINDOWS) {
+                return NTFS_FILE_TIMESTAMP_GRANULARITY;
+            }
+            return UNIX_FILE_TIMESTAMP_GRANULARITY;
+        }
+        
+        
+        /**
+         * Returns true if the source is older than the dest.
+         * If the dest file does not exist, then the test returns false; it is
+         * implicitly not up do date.
+         * @param source source file (should be the older).
+         * @param dest dest file (should be the newer).
+         * @param granularity an offset added to the source time.
+         * @return true if the source is older than the dest after accounting
+         *              for granularity.
+         * @since Ant 1.6.3
+         */
+        public function isUpToDate(source:File, dest:File, granularity:Object = null):Boolean {
+            if (granularity == null)
+                granularity = getFileTimestampGranularity();
+            //do a check for the destination file existing
+            if (!dest.exists) {
+                //if it does not, then the file is not up to date.
+                return false;
+            }
+            var sourceTime:Date = source.modificationDate;
+            var destTime:Date = dest.modificationDate;
+            return isUpToDateDate(sourceTime.time, destTime.time, granularity as Number);
+        }
+        
+        /**
+         * Compare two timestamps for being up to date using
+         * the specified granularity.
+         *
+         * @param sourceTime timestamp of source file.
+         * @param destTime timestamp of dest file.
+         * @param granularity os/filesys granularity.
+         * @return true if the dest file is considered up to date.
+         */
+        public function isUpToDateDate(sourceTime:Number, destTime:Number, granularity:Number = NaN):Boolean {
+            if (isNaN(granularity))
+                granularity = getFileTimestampGranularity();
+            return destTime != -1 && destTime >= sourceTime + granularity;
+        }
+                
+        
+        /**
+         * Calculates the relative path between two files.
+         * <p>
+         * Implementation note:<br/> This function may throw an IOException if an I/O error occurs
+         * because its use of the canonical pathname may require filesystem queries.
+         * </p>
+         *
+         * @param fromFile the <code>File</code> to calculate the path from
+         * @param toFile the <code>File</code> to calculate the path to
+         * @return the relative path between the files
+         * @throws Exception for undocumented reasons
+         * @see File#getCanonicalPath()
+         *
+         * @since Ant 1.7
+         */
+        public static function getRelativePath(fromFile:File, toFile:File):String {
+            fromFile.canonicalize();
+            toFile.canonicalize();
+            var fromPath:String = fromFile.nativePath;
+            var toPath:String = toFile.nativePath;
+            
+            // build the path stack info to compare
+            var fromPathStack:Vector.<String> = getPathStack(fromPath);
+            var toPathStack:Vector.<String> = getPathStack(toPath);
+            
+            if (0 < toPathStack.length && 0 < fromPathStack.length) {
+                if (!fromPathStack[0] == toPathStack[0]) {
+                    // not the same device (would be "" on Linux/Unix)
+                    
+                    return getPath(toPathStack);
+                }
+            } else {
+                // no comparison possible
+                return getPath(toPathStack);
+            }
+            
+            var minLength:int = Math.min(fromPathStack.length, toPathStack.length);
+            var same:int = 1; // Used outside the for loop
+            
+            // get index of parts which are equal
+            for (;
+                same < minLength && fromPathStack[same] == toPathStack[same];
+                same++) {
+                // Do nothing
+            }
+            
+            var relativePathStack:Vector.<String> = new Vector.<String>();
+            
+            // if "from" part is longer, fill it up with ".."
+            // to reach path which is equal to both paths
+            for (var i:int = same; i < fromPathStack.length; i++) {
+                relativePathStack.push("..");
+            }
+            
+            // fill it up path with parts which were not equal
+            for (i = same; i < toPathStack.length; i++) {
+                relativePathStack.push(toPathStack[i]);
+            }
+            
+            return getPath(relativePathStack);
+        }
+        
+        /**
+         * Gets all names of the path as an array of <code>String</code>s.
+         *
+         * @param path to get names from
+         * @return <code>String</code>s, never <code>null</code>
+         *
+         * @since Ant 1.7
+         */
+        public static function getPathStack(path:String):Vector.<String> {
+            var normalizedPath:String = path.replace(new RegExp(File.separator, "g"), '/');
+            
+            return Vector.<String>(normalizedPath.split("/"));
+        }
+        
+        /**
+         * Gets path from a <code>List</code> of <code>String</code>s.
+         *
+         * @param pathStack <code>List</code> of <code>String</code>s to be concated as a path.
+         * @param separatorChar <code>char</code> to be used as separator between names in path
+         * @return <code>String</code>, never <code>null</code>
+         *
+         * @since Ant 1.7
+         */
+        public static function getPath(pathStack:Vector.<String>, separatorChar:String = "/"):String {
+            var buffer:String = ""
+            
+            if (pathStack.length) {
+                buffer += pathStack.shift();
+            }
+            while (pathStack.length) {
+                buffer += separatorChar;
+                buffer += pathStack.shift();
+            }
+            return buffer;
+        }
+        
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/PathTokenizer.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/PathTokenizer.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/PathTokenizer.as
new file mode 100644
index 0000000..3e04911
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/PathTokenizer.as
@@ -0,0 +1,118 @@
+/*
+*  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.flex.ant.tags.filesetClasses
+{        
+    import flash.system.Capabilities;
+    
+    import mx.utils.StringUtil;
+    
+        /**
+         * Ported from org.apache.tools.ant.PathTokenizer.java on 12/3/13. 
+         * A Path tokenizer takes a path and returns the components that make up
+         * that path.
+         *
+         * The path can use path separators of either ':' or ';' and file separators
+         * of either '/' or '\'.
+         *
+         */
+        public class PathTokenizer {
+            /**
+             * A tokenizer to break the string up based on the ':' or ';' separators.
+             */
+            private var tokenizer:StringTokenizer;
+            
+            /**
+             * A String which stores any path components which have been read ahead
+             * due to DOS filesystem compensation.
+             */
+            private var lookahead:String = null;
+            
+            /**
+             * Flag to indicate whether or not we are running on a platform with a
+             * DOS style filesystem
+             */
+            private var dosStyleFilesystem:Boolean;
+            
+            /**
+             * Constructs a path tokenizer for the specified path.
+             *
+             * @param path The path to tokenize. Must not be <code>null</code>.
+             */
+            public function PathTokenizer(path:String) {
+                // on Windows and Unix, we can ignore delimiters and still have
+                // enough information to tokenize correctly.
+                tokenizer = new StringTokenizer(path, ":;", false);
+                dosStyleFilesystem = Capabilities.os.indexOf("Win") != -1;
+            }
+            
+            /**
+             * Tests if there are more path elements available from this tokenizer's
+             * path. If this method returns <code>true</code>, then a subsequent call
+             * to nextToken will successfully return a token.
+             *
+             * @return <code>true</code> if and only if there is at least one token
+             * in the string after the current position; <code>false</code> otherwise.
+             */
+            public function hasMoreTokens():Boolean {
+                if (lookahead != null) {
+                    return true;
+                }
+                
+                return tokenizer.hasMoreTokens();
+            }
+            
+            /**
+             * Returns the next path element from this tokenizer.
+             *
+             * @return the next path element from this tokenizer.
+             *
+             * @exception NoSuchElementException if there are no more elements in this
+             *            tokenizer's path.
+             */
+            public function nextToken():String {
+                var token:String = null;
+                if (lookahead != null) {
+                    token = lookahead;
+                    lookahead = null;
+                } else {
+                    token = StringUtil.trim(tokenizer.nextToken());
+                }
+                
+                if (token.length == 1 && Character.isLetter(token.charAt(0))
+                    && dosStyleFilesystem
+                    && tokenizer.hasMoreTokens()) {
+                    // we are on a dos style system so this path could be a drive
+                    // spec. We look at the next token
+                    var nextToken:String = StringUtil.trim(tokenizer.nextToken());
+                    if (nextToken.indexOf("\\") == 0 || nextToken.indexOf("/") == 0) {
+                        // we know we are on a DOS style platform and the next path
+                        // starts with a slash or backslash, so we know this is a
+                        // drive spec
+                        token += ":" + nextToken;
+                    } else {
+                        // store the token just read for next time
+                        lookahead = nextToken;
+                    }
+                }
+                return token;
+            }
+        }
+        
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Reference.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Reference.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Reference.as
new file mode 100644
index 0000000..1e9ce09
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Reference.as
@@ -0,0 +1,106 @@
+/*
+*  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.flex.ant.tags.filesetClasses
+{
+    import org.apache.flex.ant.tags.Project;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.BuildException;
+
+    /**
+     * Ported from org.apache.tools.ant.types.Reference.java on 12/3/13. 
+     * Class to hold a reference to another object in the project.
+     *
+     */
+    public class Reference {
+    
+        private var refid:String;
+        private var project:Project;
+    
+        /**
+         * Create a reference to a named ID in a particular project.
+         * @param p the project this reference is associated with
+         * @param id the name of this reference
+         * @since Ant 1.6.3
+         */
+        public function Reference(p:Project, id:String) {
+            setRefId(id);
+            setProject(p);
+        }
+    
+        /**
+         * Set the reference id. Should not normally be necessary;
+         * use {@link Reference#Reference(Project, String)}.
+         * @param id the reference id to use
+         */
+        public function setRefId(id:String):void {
+            refid = id;
+        }
+    
+        /**
+         * Get the reference id of this reference.
+         * @return the reference id
+         */
+        public function getRefId():String {
+            return refid;
+        }
+    
+        /**
+         * Set the associated project. Should not normally be necessary;
+         * use {@link Reference#Reference(Project,String)}.
+         * @param p the project to use
+         * @since Ant 1.6.3
+         */
+        public function setProject(p:Project):void {
+            this.project = p;
+        }
+    
+        /**
+         * Get the associated project, if any; may be null.
+         * @return the associated project
+         * @since Ant 1.6.3
+         */
+        public function getProject():Project {
+            return project;
+        }
+    
+        /**
+         * Resolve the reference, using the associated project if
+         * it set, otherwise use the passed in project.
+         * @param fallback the fallback project to use if the project attribute of
+         *                 reference is not set.
+         * @return the dereferenced object.
+         * @throws BuildException if the reference cannot be dereferenced.
+         */
+        public function getReferencedObject(fallback:Project = null):Object {
+            if (refid == null) {
+                throw new BuildException("No reference specified");
+            }
+            if (fallback == null)
+            {
+                if (project == null) {
+                    throw new BuildException("No project set on reference to " + refid);
+                }
+            }    
+            
+            var o:Object = project == null ? fallback.getReference(refid) : project.getReference(refid);
+            if (o == null) {
+                throw new BuildException("Reference " + refid + " not found.");
+            }
+            return o;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Resource.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Resource.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Resource.as
new file mode 100644
index 0000000..0ea7b85
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/Resource.as
@@ -0,0 +1,349 @@
+/*
+*  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.flex.ant.tags.filesetClasses
+{
+    import flash.filesystem.FileStream;
+    import org.apache.flex.ant.tags.filesetClasses.exceptions.UnsupportedOperationException;
+    
+    /**
+     * Ported from org.apache.tools.ant.types.Resource.java on 12/3/13. 
+     * Describes a "File-like" resource (File, ZipEntry, etc.).
+     *
+     * This class is meant to be used by classes needing to record path
+     * and date/time information about a file, a zip entry or some similar
+     * resource (URL, archive in a version control repository, ...).
+     *
+     * @since Ant 1.5.2
+     * @see org.apache.tools.ant.types.resources.Touchable
+     */
+    public class Resource extends DataType
+    {
+        
+        /** Constant unknown size */
+        public static const UNKNOWN_SIZE:int = -1;
+        
+        /** Constant unknown datetime for getLastModified */
+        public static const UNKNOWN_DATETIME:int = 0;
+                
+        private var name:String;
+        private var exists:Boolean = true;
+        private var lastmodified:Number;
+        private var directory:Boolean;
+        private var _size:int;
+        private var nameSet:Boolean;
+        private var existsSet:Boolean;
+        private var lastmodifiedSet:Boolean;
+        private var directorySet:Boolean;
+        private var sizeSet:Boolean;
+        
+        
+        /**
+         * Sets the name, lastmodified flag, exists flag, directory flag, and size.
+         *
+         * @param name relative path of the resource.  Expects
+         * &quot;/&quot; to be used as the directory separator.
+         * @param exists if true the resource exists
+         * @param lastmodified the last modification time of the resource
+         * @param directory    if true, this resource is a directory
+         * @param size the size of this resource.
+         */
+        public function Resource(name:String, exists:Boolean  = false, lastmodified:Number = NaN, 
+                            directory:Boolean = false, size:int = UNKNOWN_SIZE) {
+            this.name = name;
+            setName(name);
+            setExists(exists);
+            setLastModified(lastmodified);
+            setDirectory(directory);
+            setSize(size);
+        }
+        
+        /**
+         * Name attribute will contain the path of a file relative to the
+         * root directory of its fileset or the recorded path of a zip
+         * entry.
+         *
+         * <p>example for a file with fullpath /var/opt/adm/resource.txt
+         * in a file set with root dir /var/opt it will be
+         * adm/resource.txt.</p>
+         *
+         * <p>&quot;/&quot; will be used as the directory separator.</p>
+         * @return the name of this resource.
+         */
+        public function getName():String  
+        {
+            return isReference() ? Resource(getCheckedRef()).getName() : name;
+        }
+        
+        /**
+         * Set the name of this Resource.
+         * @param name relative path of the resource.  Expects
+         * &quot;/&quot; to be used as the directory separator.
+         */
+        public function setName(name:String):void 
+        {
+            checkAttributesAllowed();
+            this.name = name;
+            nameSet = true;
+        }
+        
+        /**
+         * The exists attribute tells whether a resource exists.
+         * @return true if this resource exists.
+         */
+        public function isExists():Boolean 
+        {
+            if (isReference()) {
+                return Resource(getCheckedRef()).isExists();
+            }
+            //default true:
+            return exists;
+        }
+        
+        /**
+         * Set the exists attribute.
+         * @param exists if true, this resource exists.
+         */
+        public function setExists(exists:Boolean):void 
+        {
+            checkAttributesAllowed();
+            this.exists = exists;
+            existsSet = true;
+        }
+        
+        /**
+         * Tells the modification time in milliseconds since 01.01.1970 (the "epoch").
+         *
+         * @return the modification time, if that is meaningful
+         *            (e.g. for a file resource which exists);
+         *         0 if the resource does not exist, to mirror the behavior
+         *         of {@link java.io.File#lastModified};
+         *         or 0 if the notion of modification time is meaningless for this class
+         *           of resource (e.g. an inline string)
+         */
+        public function getLastModified():Number
+        {
+            if (isReference()) {
+                return Resource(getCheckedRef()).getLastModified();
+            }
+            if (!isExists() || !lastmodifiedSet) {
+                return UNKNOWN_DATETIME;
+            }
+            var result:Number = lastmodified;
+            return result < UNKNOWN_DATETIME ? UNKNOWN_DATETIME : result;
+        }
+        
+        /**
+         * Set the last modification attribute.
+         * @param lastmodified the modification time in milliseconds since 01.01.1970.
+         */
+        public function setLastModified(lastmodified:Number):void 
+        {
+            checkAttributesAllowed();
+            this.lastmodified = lastmodified;
+            lastmodifiedSet = true;
+        }
+        
+        /**
+         * Tells if the resource is a directory.
+         * @return boolean flag indicating if the resource is a directory.
+         */
+        public function isDirectory():Boolean 
+        {
+            if (isReference()) {
+                return Resource(getCheckedRef()).isDirectory();
+            }
+            //default false:
+            return directory;
+        }
+        
+        /**
+         * Set the directory attribute.
+         * @param directory if true, this resource is a directory.
+         */
+        public function setDirectory(directory:Boolean):void
+        {
+            checkAttributesAllowed();
+            this.directory = directory;
+            directorySet = true;
+        }
+        
+        /**
+         * Set the size of this Resource.
+         * @param size the size, as a long.
+         * @since Ant 1.6.3
+         */
+        public function setSize(size:int):void 
+        {
+            checkAttributesAllowed();
+            _size = size > UNKNOWN_SIZE ? size : UNKNOWN_SIZE;
+            sizeSet = true;
+        }
+        
+        /**
+         * Get the size of this Resource.
+         * @return the size, as a long, 0 if the Resource does not exist (for
+         *         compatibility with java.io.File), or UNKNOWN_SIZE if not known.
+         * @since Ant 1.6.3
+         */
+        public function getSize():int 
+        {
+            if (isReference()) {
+                return Resource(getCheckedRef()).getSize();
+            }
+            return isExists()
+            ? (sizeSet ? _size : UNKNOWN_SIZE)
+                : 0;
+        }
+                
+        /**
+         * Delegates to a comparison of names.
+         * @param other the object to compare to.
+         * @return a negative integer, zero, or a positive integer as this Resource
+         *         is less than, equal to, or greater than the specified Resource.
+         * @since Ant 1.6
+         */
+        public function compareTo(other:Resource):int {
+            if (isReference()) {
+                return Resource(getCheckedRef()).compareTo(other);
+            }
+            return toString().localeCompare(other.toString());
+        }
+        
+        /**
+         * Implement basic Resource equality.
+         * @param other the object to check against.
+         * @return true if the specified Object is equal to this Resource.
+         * @since Ant 1.7
+         */
+        public function equals(other:Object):Boolean {
+            if (isReference()) {
+                return getCheckedRef().equals(other);
+            }
+            return compareTo(Resource(other)) == 0;
+        }
+               
+        /**
+         * Get an InputStream for the Resource.
+         * @return an InputStream containing this Resource's content.
+         * @throws IOException if unable to provide the content of this
+         *         Resource as a stream.
+         * @throws UnsupportedOperationException if InputStreams are not
+         *         supported for this Resource type.
+         * @since Ant 1.7
+         */
+        public function getInputStream():FileStream
+        {
+            if (isReference()) {
+                return Resource(getCheckedRef()).getInputStream();
+            }
+            throw new UnsupportedOperationException();
+        }
+        
+        /**
+         * Get an OutputStream for the Resource.
+         * @return an OutputStream to which content can be written.
+         * @throws IOException if unable to provide the content of this
+         *         Resource as a stream.
+         * @throws UnsupportedOperationException if OutputStreams are not
+         *         supported for this Resource type.
+         * @since Ant 1.7
+         */
+        public function getOutputStream():FileStream
+        {
+            if (isReference()) {
+                return Resource(getCheckedRef()).getOutputStream();
+            }
+            throw new UnsupportedOperationException();
+        }
+        
+        /**
+         * Fulfill the ResourceCollection contract.
+         * @return an Iterator of Resources.
+         * @since Ant 1.7
+         */
+        public function iterator():Vector.<Resource> 
+        {
+            return isReference() ? Resource(getCheckedRef()).iterator()
+            : Vector.<Resource>([this]);
+        }
+        
+        /**
+         * Fulfill the ResourceCollection contract.
+         * @return the size of this ResourceCollection.
+         * @since Ant 1.7
+         */
+        public function size():int {
+            return isReference() ? Resource(getCheckedRef()).size() : 1;
+        }
+        
+        /**
+         * Fulfill the ResourceCollection contract.
+         * @return whether this Resource is a FileProvider.
+         * @since Ant 1.7
+         */
+        public function isFilesystemOnly():Boolean 
+        {
+            return (isReference() && Resource(getCheckedRef()).isFilesystemOnly())
+            || this is FileProvider;
+                }
+        
+        /**
+         * Get the string representation of this Resource.
+         * @return this Resource formatted as a String.
+         * @since Ant 1.7
+         */
+        override public function toString():String 
+        {
+            if (isReference()) {
+                return getCheckedRef().toString();
+            }
+            var n:String = getName();
+            return n == null ? "(anonymous)" : n;
+        }
+        
+        /**
+         * Get a long String representation of this Resource.
+         * This typically should be the value of <code>toString()</code>
+         * prefixed by a type description.
+         * @return this Resource formatted as a long String.
+         * @since Ant 1.7
+         */
+        public function toLongString():String 
+        {
+            return isReference() ? Resource(getCheckedRef()).toLongString()
+            : getDataTypeName() + " \"" + toString() + '"';
+        }
+        
+        /**
+         * Overrides the base version.
+         * @param r the Reference to set.
+         */
+        override public function setRefid(r:Reference):void 
+        {
+            if (nameSet
+                || existsSet
+                || lastmodifiedSet
+                || directorySet
+                || sizeSet) {
+                throw tooManyAttributes();
+            }
+            super.setRefid(r);
+        }
+        
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/SelectorUtils.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/SelectorUtils.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/SelectorUtils.as
new file mode 100644
index 0000000..b1d3056
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/SelectorUtils.as
@@ -0,0 +1,638 @@
+/*
+*  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.flex.ant.tags.filesetClasses
+{
+    import flash.filesystem.File;
+    
+    /**
+     * Ported from org.apache.tools.ant.types.selectors.SelectorUtils.java on 12/03/13.
+     * <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 const DEEP_TREE_MATCH:String = "**";
+        
+        private static const instance:SelectorUtils = new SelectorUtils();
+        private static const FILE_UTILS:FileUtils = FileUtils.getFileUtils();
+        
+        /**
+         * Private Constructor
+         */
+        public function SelectorUtils() {
+        }
+        
+        /**
+         * Retrieves the instance of the Singleton.
+         * @return singleton instance
+         */
+        public static function getInstance():SelectorUtils {
+            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>.
+         * @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 function matchPatternStart(pattern:String, str:String,
+            isCaseSensitive:Boolean = true):Boolean  
+        {
+                // 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.indexOf(File.separator) == 0
+                    != pattern.indexOf(File.separator) == 0) {
+                    return false;
+                }
+                
+                var patDirs:Vector.<String> = tokenizePathAsArray(pattern);
+                var strDirs:Vector.<String> = tokenizePathAsArray(str);
+                return matchPatternStartVectors(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 "**".
+         */
+        public static function matchPatternStartVectors(patDirs:Vector.<String>, 
+            strDirs:Vector.<String>,
+            isCaseSensitive:Boolean):Boolean {
+                var patIdxStart:int = 0;
+                var patIdxEnd:int = patDirs.length - 1;
+                var strIdxStart:int = 0;
+                var strIdxEnd:int = strDirs.length - 1;
+                
+                // up to first '**'
+                while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
+                    var patDir:String = patDirs[patIdxStart];
+                    if (patDir == 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 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 function matchPath(pattern:String, str:String,
+            isCaseSensitive:Boolean = true):Boolean
+        {
+            var patDirs:Vector.<String> = tokenizePathAsArray(pattern);
+            return matchPathVectors(patDirs, tokenizePathAsArray(str), isCaseSensitive);
+        }
+        
+        /**
+         * Core implementation of matchPath.  It is isolated so that it
+         * can be called from TokenizedPattern.
+         */
+        public static function matchPathVectors(tokenizedPattern:Vector.<String>, 
+            strDirs:Vector.<String>,
+            isCaseSensitive:Boolean):Boolean 
+        {
+                var patIdxStart:int = 0;
+                var patIdxEnd:int = tokenizedPattern.length - 1;
+                var strIdxStart:int = 0;
+                var strIdxEnd:int = strDirs.length - 1;
+                
+                // up to first '**'
+                while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
+                    var patDir:String = tokenizedPattern[patIdxStart];
+                    if (patDir == DEEP_TREE_MATCH) {
+                        break;
+                    }
+                    if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) {
+                        return false;
+                    }
+                    patIdxStart++;
+                    strIdxStart++;
+                }
+                if (strIdxStart > strIdxEnd) {
+                    // String is exhausted
+                    for (i = patIdxStart; i <= patIdxEnd; i++) {
+                        if (tokenizedPattern[i] != 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) {
+                    patDir = tokenizedPattern[patIdxEnd];
+                    if (patDir == DEEP_TREE_MATCH) {
+                        break;
+                    }
+                    if (!match(patDir, strDirs[strIdxEnd], isCaseSensitive)) {
+                        return false;
+                    }
+                    patIdxEnd--;
+                    strIdxEnd--;
+                }
+                if (strIdxStart > strIdxEnd) {
+                    // String is exhausted
+                    for (i = patIdxStart; i <= patIdxEnd; i++) {
+                        if (!tokenizedPattern[i] == DEEP_TREE_MATCH) {
+                            return false;
+                        }
+                    }
+                    return true;
+                }
+                
+                while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
+                    var patIdxTmp:int = -1;
+                    for (i = patIdxStart + 1; i <= patIdxEnd; i++) {
+                        if (tokenizedPattern[i] ==  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
+                    var patLength:int = (patIdxTmp - patIdxStart - 1);
+                    var strLength:int = (strIdxEnd - strIdxStart + 1);
+                    var foundIdx:int = -1;
+                    strLoop:
+                    for (i = 0; i <= strLength - patLength; i++) {
+                        for (var j:int = 0; j < patLength; j++) {
+                            var subPat:String = tokenizedPattern[patIdxStart + j + 1];
+                            var subStr:String = 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 (var i:int = patIdxStart; i <= patIdxEnd; i++) {
+                    if (!tokenizedPattern[i] == 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>.
+         * @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 function match(pattern:String, str:String,
+            caseSensitive:Boolean = true):Boolean 
+        {
+                var patArr:Vector.<String> = Vector.<String>(pattern.split());
+                var strArr:Vector.<String> = Vector.<String>(str.split());
+                var patIdxStart:int = 0;
+                var patIdxEnd:int = patArr.length - 1;
+                var strIdxStart:int = 0;
+                var strIdxEnd:int = strArr.length - 1;
+                var ch:String;
+                
+                var containsStar:Boolean = false;
+                for (var i:int = 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 (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) {
+                    var patIdxTmp:int = -1;
+                    for (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
+                    var patLength:int = (patIdxTmp - patIdxStart - 1);
+                    var strLength:int = (strIdxEnd - strIdxStart + 1);
+                    var foundIdx:int = -1;
+                    strLoop:
+                    for (i  = 0; i <= strLength - patLength; i++) {
+                        for (var j:int = 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 function allStars(chars:Vector.<String>, start:int, end:int):Boolean 
+        {
+            for (var i:int = start; i <= end; ++i) {
+                if (chars[i] != '*') {
+                    return false;
+                }
+            }
+            return true;
+        }
+        
+        private static function different(
+            caseSensitive:Boolean, ch:String, other:String):Boolean 
+        {
+                return caseSensitive
+                ? ch != other
+                    : ch.toUpperCase() != other.toUpperCase();
+        }
+                    
+            /**
+             * 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
+             */
+            public static function tokenizePath(path:String, 
+                         separator:String = null):Vector.<String>  
+            {
+                if (separator == null)
+                    separator = File.separator;
+                
+                var ret:Vector.<String> = new Vector.<String>();
+                if (FileUtils.isAbsolutePath(path)) {
+                    var s:Vector.<String> = FILE_UTILS.dissect(path);
+                    ret.push(s[0]);
+                    path = s[1];
+                }
+                var st:StringTokenizer = new StringTokenizer(path, separator);
+                while (st.hasMoreTokens()) {
+                    ret.push(st.nextToken());
+                }
+                return ret;
+            }
+                
+                /**
+                 * Same as {@link #tokenizePath tokenizePath} but hopefully faster.
+                 */
+                /*package*/public static function tokenizePathAsArray(path:String):Vector.<String> 
+                {
+                    var root:String = null;
+                    if (FileUtils.isAbsolutePath(path)) {
+                        var s:Vector.<String> = FILE_UTILS.dissect(path);
+                        root = s[0];
+                        path = s[1];
+                    }
+                    var sep:String = File.separator;
+                    var start:int = 0;
+                    var len:int = path.length;
+                    var count:int = 0;
+                    for (var pos:int = 0; pos < len; pos++) {
+                        if (path.charAt(pos) == sep) {
+                            if (pos != start) {
+                                count++;
+                            }
+                            start = pos + 1;
+                        }
+                    }
+                    if (len != start) {
+                        count++;
+                    }
+                    var l:Vector.<String> = Vector.<String>(new Array(count + ((root == null) ? 0 : 1)));
+                    
+                    if (root != null) {
+                        l[0] = root;
+                        count = 1;
+                    } else {
+                        count = 0;
+                    }
+                    start = 0;
+                    for (pos = 0; pos < len; pos++) {
+                        if (path.charAt(pos) == sep) {
+                            if (pos != start) {
+                                var tok:String = path.substring(start, pos);
+                                l[count++] = tok;
+                            }
+                            start = pos + 1;
+                        }
+                    }
+                    if (len != start) {
+                        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
+         */
+        private static function isOutOfDateFile(src:File, target:File, granularity:int):Boolean {
+            if (!src.exists) {
+                return false;
+            }
+            if (!target.exists) {
+                return true;
+            }
+            if ((src.modificationDate.time - granularity) > target.modificationDate.time) {
+                return true;
+            }
+            return false;
+        }
+        
+        /**
+         * Returns dependency information on these two resources. 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 resource
+         * @param target the resource being compared against
+         * @param granularity the int amount in seconds of slack we will give in
+         *        determining out of dateness
+         * @return whether the target is out of date
+         */
+        public static function isOutOfDate(src:Object, target:Object,
+            granularity:int):Boolean {
+                if (src is File)
+                    return isOutOfDateFile(src as File, target as File, granularity);
+                return isOutOfDateResource(src as Resource, target as Resource, granularity);
+            }
+        
+        /**
+         * Returns dependency information on these two resources. 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 resource
+         * @param target the resource being compared against
+         * @param granularity the long amount in seconds of slack we will give in
+         *        determining out of dateness
+         * @return whether the target is out of date
+         */
+        private static function isOutOfDateResource(src:Resource, target:Resource,
+                                           granularity:int):Boolean {
+            var sourceLastModified:Number = src.getLastModified();
+            var targetLastModified:Number = target.getLastModified();
+            return src.isExists()
+                && (sourceLastModified == Resource.UNKNOWN_DATETIME
+                    || targetLastModified == Resource.UNKNOWN_DATETIME
+                    || (sourceLastModified - granularity) > targetLastModified);
+        }
+        
+        /**
+         * "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 argument constructor.
+         *
+         * @param input a String to remove all whitespace.
+         * @return a String that has had all whitespace removed.
+         */
+        public static function removeWhitespace(input:String):String {
+            var result:String = "";
+            if (input != null) {
+                var st:StringTokenizer = new StringTokenizer(input);
+                while (st.hasMoreTokens()) {
+                    result += st.nextToken();
+                }
+            }
+            return result;
+        }
+        
+        /**
+         * 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 function hasWildcards(input:String):Boolean {
+            return (input.indexOf('*') != -1 || input.indexOf('?') != -1);
+        }
+        
+        /**
+         * removes from a pattern all tokens to the right containing wildcards
+         * @param input the input string
+         * @return the leftmost part of the pattern without wildcards
+         */
+        public static function rtrimWildcardTokens(input:String):String {
+            return new TokenizedPattern(input).rtrimWildcardTokens().toString();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/3a58a60e/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/StringTokenizer.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/StringTokenizer.as b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/StringTokenizer.as
new file mode 100644
index 0000000..fcd97ba
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/filesetClasses/StringTokenizer.as
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags.filesetClasses
+{
+    // an approximation of the Java StringTokenizer
+    public class StringTokenizer
+    {
+        public function StringTokenizer(s:String, delims:String = "\t\r\n\f", returnDelims:Boolean = false)
+        {
+            tokens = new Vector.<String>();
+            var c1:int = 0;
+            var c2:int = 0;
+            var n:int = s.length;
+            while (c1 < n)
+            {
+                var c:String = s.charAt(c2);
+                if (delims.indexOf(c) != -1)
+                {
+                    tokens.push(s.substring(c1, c2 - 1));
+                    c1 = c2;
+                    while (c1 < n)
+                    {
+                        c = s.charAt(c2);
+                        if (delims.indexOf(c) == -1)
+                        {
+                            if (returnDelims)
+                            {
+                                tokens.push(s.substring(c1, c2 - 1))
+                            }
+                            c1 = c2;
+                            break;
+                        }
+                    }
+                }
+                c2++;
+            }
+        }
+        
+        private var tokens:Vector.<String>;
+        private var index:int = 0;
+        
+        public function hasMoreTokens():Boolean
+        {
+            return index < tokens.length;    
+        }
+        
+        public function nextToken():String
+        {
+            return tokens[index++];
+        }
+    }
+}
\ No newline at end of file


[03/14] git commit: [flex-utilities] [refs/heads/develop] - create base class for FileSet handling tasks

Posted by ah...@apache.org.
create base class for FileSet handling tasks


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/7f8af60c
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/7f8af60c
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/7f8af60c

Branch: refs/heads/develop
Commit: 7f8af60cdd2d8b9cb2108994678571b0a221c396
Parents: 3a58a60
Author: Alex Harui <ah...@apache.org>
Authored: Sat Dec 7 21:47:41 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Sat Dec 7 21:50:43 2013 -0800

----------------------------------------------------------------------
 .../tags/supportClasses/FileSetTaskHandler.as   | 65 ++++++++++++++++++++
 1 file changed, 65 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/7f8af60c/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
new file mode 100644
index 0000000..c399e52
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/supportClasses/FileSetTaskHandler.as
@@ -0,0 +1,65 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags.supportClasses
+{
+    import org.apache.flex.ant.tags.FileSet;
+    
+    /**
+     *  The base class for ITagHandlers that do work with filesets
+     */
+    public class FileSetTaskHandler extends TaskHandler
+    {
+        public function FileSetTaskHandler()
+        {
+        }
+        
+        /**
+         *  Do the work.
+         *  TaskHandlers lazily create their children so
+         *  super.execute() should be called before
+         *  doing any real work. 
+         */
+        override public function execute():Boolean
+        {
+            ant.processChildren(this.xml, context, this);
+            var n:int = numChildren;
+            for (var i:int = 0; i < n; i++)
+            {
+                var fs:FileSet = getChildAt(i) as FileSet;
+                if (fs)
+                {
+                    var list:Vector.<String> = fs.value as Vector.<String>;
+                    if (list)
+                    {
+                        for each (var fileName:String in list)
+                        {
+                            actOnFile(fs.dir, fileName);
+                        }
+                    }
+                }
+            }
+            return true;
+        }
+        
+        protected function actOnFile(dir:String, fileName:String):void
+        {
+            
+        }
+    }
+}
\ No newline at end of file


[02/14] git commit: [flex-utilities] [refs/heads/develop] - place holder for Copy task

Posted by ah...@apache.org.
place holder for Copy task


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/c2f4d939
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/c2f4d939
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/c2f4d939

Branch: refs/heads/develop
Commit: c2f4d939b358435b103c1758c9ee229b5f87f92b
Parents: 7f8af60
Author: Alex Harui <ah...@apache.org>
Authored: Sat Dec 7 21:48:34 2013 -0800
Committer: Alex Harui <ah...@apache.org>
Committed: Sat Dec 7 21:50:43 2013 -0800

----------------------------------------------------------------------
 ant_on_air/src/org/apache/flex/ant/tags/Copy.as | 74 ++++++++++++++++++++
 1 file changed, 74 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/c2f4d939/ant_on_air/src/org/apache/flex/ant/tags/Copy.as
----------------------------------------------------------------------
diff --git a/ant_on_air/src/org/apache/flex/ant/tags/Copy.as b/ant_on_air/src/org/apache/flex/ant/tags/Copy.as
new file mode 100644
index 0000000..4bdb0cc
--- /dev/null
+++ b/ant_on_air/src/org/apache/flex/ant/tags/Copy.as
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.flex.ant.tags
+{
+    import mx.core.IFlexModuleFactory;
+    
+    import org.apache.flex.ant.Ant;
+    import org.apache.flex.ant.tags.supportClasses.FileSetTaskHandler;
+    
+    [Mixin]
+    public class Copy extends FileSetTaskHandler
+    {
+        public static function init(mf:IFlexModuleFactory):void
+        {
+            Ant.antTagProcessors["copy"] = Copy;
+        }
+
+        public function Copy()
+        {
+            super();
+        }
+        
+        private var fileName:String;
+        private var toFileName:String;
+        private var toDirName:String;
+        private var overwrite:Boolean;
+        
+        override protected function processAttribute(name:String, value:String):void
+        {
+            if (name == "file")
+                fileName = value;
+            else if (name == "toFile")
+                toFileName == value;
+            else if (name == "toDir")
+                toDirName = value;
+            else if (name == "overwrite")
+                overwrite = value == "true";
+            else
+                super.processAttribute(name, value);
+        }
+
+        override protected function actOnFile(dir:String, fileName:String):void
+        {
+            
+        }
+        
+        /**
+         *  Do the work.
+         *  TaskHandlers lazily create their children so
+         *  super.execute() should be called before
+         *  doing any real work. 
+         */
+        override public function execute():Boolean
+        {
+            return true;
+        }
+    }
+}
\ No newline at end of file