Merge branch 'release4.16.0'
diff --git a/.gitignore b/.gitignore
index 865d742..3b9d3b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,6 +81,7 @@
 [Dd]ebug*/
 !debugger/
 modules/debugger/classes/
+modules/asc/build/java/classes/
 [Rr]elease*/
 Ankh.NoLoad
 
diff --git a/ApproveSDK.xml b/ApproveSDK.xml
index ef60232..08134b7 100644
--- a/ApproveSDK.xml
+++ b/ApproveSDK.xml
@@ -54,9 +54,10 @@
 	
     <property name="src.rat.report" value="${basedir}/rat-report-src.txt"/>
     <property name="bin.rat.report" value="${basedir}/rat-report-bin.txt"/>
-	<property name="apache.rat.jar" value="apache-rat-0.8.jar" />
-	<property name="apache.rat.tasks.jar" value="apache-rat-tasks-0.8.jar" />
-	<property name="apache.rat.url" value="http://people.apache.org/~aharui/rat" />
+    <property name="apache.rat.jar" value="apache-rat-0.11.jar" />
+    <property name="apache.rat.tasks.jar" value="apache-rat-tasks-0.11.jar" />
+    <property name="apache.rat.url" value="http://search.maven.org/remotecontent?filepath=org/apache/rat/apache-rat/0.11" />
+    <property name="apache.rat.tasks.url" value="http://search.maven.org/remotecontent?filepath=org/apache/rat/apache-rat-tasks/0.11" />
 	   
     <property file="${basedir}/approvesdk.properties"/>
     
@@ -160,12 +161,12 @@
 	</target>
 	
 	<target name="install-rat" depends="install-rat.jar,install-rat.tasks.jar" />
-	<target name="install-rat.jar" unless="apache.rat.found">
-		<get src="${apache.rat.url}/${apache.rat.jar}" dest="${env.ANT_HOME}/lib/${apache.rat.jar}" />
-	</target>
-	<target name="install-rat.tasks.jar" unless="apache.rat.tasks.found">
-		<get src="${apache.rat.url}/${apache.rat.tasks.jar}" dest="${env.ANT_HOME}/lib/${apache.rat.tasks.jar}" />
-	</target>
+    <target name="install-rat.jar" unless="apache.rat.found">
+        <get src="${apache.rat.url}/${apache.rat.jar}" dest="${env.ANT_HOME}/lib/${apache.rat.jar}" />
+    </target>
+    <target name="install-rat.tasks.jar" unless="apache.rat.tasks.found">
+        <get src="${apache.rat.tasks.url}/${apache.rat.tasks.jar}" dest="${env.ANT_HOME}/lib/${apache.rat.tasks.jar}" />
+    </target>
 	
     <target name="rat-taskdef" description="Rat taskdef">
         <typedef resource="org/apache/rat/anttasks/antlib.xml"
@@ -901,7 +902,7 @@
         </rat:report>
     </target>
     
-    <target name="external-jar-folder-dump" >
+    <target name="external-jar-folder-dump" if="isMac">
         <echo>list of folders in external jars.  This may impact LICENSE and NOTICE</echo>
         <antcall target="show-jar-folders" >
             <param name="thisFile" value="lib/external/commons-collections.jar" />
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 885d751..c6ac5da 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -1,6 +1,12 @@
 The following volunteers have contributed code, documentation, testing and/or
 support to the Apache Flex SDK.
 
+Apache Flex SDK 4.16.0
+----------------------
+Alex Harui, Andy Dufilie, Aron Nopanen, Dany Dhondt, Harbs, Judah Frangipane,
+Justin Mclean, Mark Kessler, Maxime Cowez, Mihai Chira, Olaf Krüger, OmPrakash Muppirala,
+Peter Marcoen, Stephan Plath, Sugan Naicker, Tamás Nepusz
+
 Apache Flex SDK 4.15.0
 ----------------------
 Ad Pijnenburg, Aleksey, Alex Harui, Andrey Gorbatov, Andy Dufilie, Andrei Tchijov,
diff --git a/GIT-TEST.txt b/GIT-TEST.txt
index 8209ac9..8755d36 100644
--- a/GIT-TEST.txt
+++ b/GIT-TEST.txt
@@ -1,4 +1,6 @@
-Test by piotrz :)
+Hope that it works and I'll be ready to change the world ;-) [okrueger]
+
+Test by piotrz :)
 junheider is Top Posting this file�people hate this on mailing lists.
 
 Flex committers can use this file to check their svn access.
@@ -82,4 +84,9 @@
 
 ello from Michael Schmalle
 
-Did it work? I won't get my hopes up. (May 30, 2015) -kmg ..
\ No newline at end of file
+Did it work? I won't get my hopes up. (May 30, 2015) -kmg ..
+
+My git commit (yishayw).
+
+First commit (Sept 7 , 2016).
+I wish I was composed entirely of acoustic vibrations. Then I would finally be 'of sound mind and body'. (gregdove)
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
index 650a047..0abfa3a 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
 Apache Flex
-Copyright 2012-2016 The Apache Software Foundation
+Copyright 2012-2017 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/README b/README
index 9e65b3b..0bd9999 100644
--- a/README
+++ b/README
@@ -21,7 +21,7 @@
 
     http://flex.apache.org/
 
-The Apache Flex SDK 4.15 is a follow up release to version 4.14.1. It is
+The Apache Flex SDK 4.16 is a follow up release to version 4.15. It is
 compatible with most code written for the original Adobe Flex 4.6 SDK.
 
 
@@ -120,6 +120,9 @@
 
 Optional: Flex Messaging Common (* 8)         BLAZEDS_HOME
 
+Java Cryptography Extensions
+    (see note (*9))
+
 ---------------------------------------------------------------------
 
 * 1)
@@ -234,6 +237,10 @@
 source should be included in the artifact, so setting BLAZEDS_HOME is not
 required.
 
+* 9)
+The Java Cryptography Extensions (JCE) Unlimited Strength jars are needed in
+order to download 3rd party software. Download and install this from Oracle
+which version you need will depend on your Java version and OS.
 
 Get the source code
 -------------------
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 7d50fe5..5aaadc3 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -1,14 +1,101 @@
+Apache Flex 4.16.0
+==================
+
+New Features
+____________
+FLEX-35122  Update to Font Awesome 4.7
+
+AIR and Flash Player Support
+----------------------------
+- Support Flash Player 21.0, 22.0, 23.0 and 24.0
+- Support for AIR 21.0, 22.0, 23.0 and 24.0
+
+Bug Fixes
+---------
+FLEX-35165  Remove bundling of Apache 1.0 licensed software
+FLEX-35126  DropDownController inside a pop up still listens to MOUSE_DOWN and
+		MOUSE_DOWN_SOMEWHERE after the popup has closed
+FLEX-35125  DropDownList inside a PopUpAnchor doesn't close when another DropDownList
+		is selected
+FLEX-35124  RTE 1009 in DropDownController.systemManager_mouseDownHandler() when inside
+		a PopUpAnchor and other item is removed on click
+FLEX-35123  DOM XSS vulnerability in history.js
+FLEX-35109  falcon compiler's build.xml error
+FLEX-35106  Incorrect date in datefield popup for fr_FR locale
+FLEX-35100  TextFlowLine.recreateTextLine() throws a null object reference error
+FLEX-35099  BusyIndicator has the wrong wrong rotation centre for iOS
+FLEX-35097  How to compile AIR beta 22 with Flex SDK?
+FLEX-35084  Ability to specify FileAttributes at compile time (mxmlc)
+FLEX-35082  moveIndexFindRow doesn't accept integer values
+FLEX-35078  Fatal when SelectionManager tries to reapply selection onto changed textFlow
+FLEX-35056  Pressing escape on s:Alert causes a RangeError when Alert.CANCEL is passed
+		as defaultButtonFlag
+FLEX-35046  Broken icon using FlatSpark ButtonIcon on mobile apps
+FLEX-35045  Flatspark ButtonIcon - icon does not display
+FLEX-35043  Unexpected behaviour of ListCollectionView.itemUpdated() when only one
+		parameter supplied
+FLEX-35042  Mistake in example for Pattern 'O' in ASDoc for DateFormatter.formatString
+FLEX-35039  ListCollectionView.setItemAt places the item in the wrong position if there
+		are duplicate items in the collection
+FLEX-35037  Add ArrayCollection unit tests donated by Justin
+FLEX-35031  HierarchicalCollectionViewCursor cannot find sealed class instance
+FLEX-35028  Error in DataGrid getHeaderRendererAt(-1)
+FLEX-35025  Validator results cannot be intercepted if the value is null
+FLEX-34935  Copy From Word Document And Pasting Into TextRegion Not Working Properly
+FLEX-34926  Misplaced [PercentProxy] metatag in GridColumn
+FLEX-34738  Not delete BusyIndicator
+FLEX-34811  Email validator show allow apostrophe in email address
+FLEX-34698  Flatspark ButtonIcon: Introduce 'iconFontPlacement' style
+FLEX-34391  ScrollableStageText with large y value crashes app
+FLEX-34088  CalloutButton closes when selecting an item in a spark Dropdown
+FLEX-33646  The "required" property on Validator should be a getter/setter
+FLEX-33311  Null pointer fatal in ConstraintLayout when executing Transition on
+		DropDownList
+FLEX-33058  RTE in HierarchicalCollectionViewCursor when a refresh occurs and old cursor
+		had an enumerable property that new cursor item doesn't
+FLEX-31948  When all the columns are invisible, pressing any character Key throws RTE
+FLEX-27509  AdvancedListBase itemMaskFreeList is null
+FLEX-26808  s:DataGrid Drag and Drop of multiple items doesn't work
+FLEX-20313  SelectItem on AdvancedDataGrid use weird code
+
+
+Known Issues
+------------
+
+Adobe Flash Builder Integration
+
+Adobe Flash Builder 4.7 and Adobe Flash Builder 4.6 both contain a bug where,
+when generating the .mxml file for a new project that uses Apache Flex SDK
+4.10.0 or later Spark Application, Flash Builder will incorrectly insert the
+attribute:
+
+    layout="absolute"
+
+This results in a compile error in the new project.  The remedy is to simply
+remove the errant attribute.
+
+The following wiki page has been set up to contain the latest news on Adobe's
+attempt to correct this problem:
+
+    https://cwiki.apache.org/confluence/display/FLEX/Adobe+Flash+Builder+'New+Project'+Bug
+
+Adobe has provided a patch for Flash Builder 4.7 that resolves this issue:
+
+    http://helpx.adobe.com/flash-builder/kb/flex-new-project-issue--.html
+
+
+
 Apache Flex 4.15.0
 ==================
 
 New Features
 ------------
-- FLEX-34837    Full support for sorting on complex fields of DataGrid rows
-- FLEX-34852    Sorting by complex fields in ListCollectionView
-- FLEX-34927    Allow the setting of an arbitrary property on an object via
+FLEX-34837    Full support for sorting on complex fields of DataGrid rows
+FLEX-34852    Sorting by complex fields in ListCollectionView
+FLEX-34927    Allow the setting of an arbitrary property on an object via
                 ObjectUtil
-- FLEX-34941    Allow custom validators to use the triggerEvent
-- FLEX-34945    Validators now able to validate nested properties
+FLEX-34941    Allow custom validators to use the triggerEvent
+FLEX-34945    Validators now able to validate nested properties
 
 AIR and Flash Player Support
 ----------------------------
diff --git a/bin/asc b/bin/asc
index 09c88c6..6ff1dde 100755
--- a/bin/asc
+++ b/bin/asc
@@ -34,7 +34,7 @@
 if [ $OS = "Windows" ]; then
 	# set FLEX_HOME relative to fdb if not set
 	test "$FLEX_HOME" = "" && {
-    	FLEX_HOME=`dirname $0`/..
+    	FLEX_HOME=`dirname "$0"`/..
     	FLEX_HOME=`cygpath -m $FLEX_HOME`
 	}
 
@@ -46,7 +46,7 @@
 if [ $OS = "Unix" ]; then
 	# set FLEX_HOME relative to fdb if not set
 	test "$FLEX_HOME" = "" && {
-    	FLEX_HOME=`dirname $0`/..
+    	FLEX_HOME=`dirname "$0"`/..
 	}
 
 	VMARGS="-ea -Dapplication.home=$FLEX_HOME -Xms32m -Xmx384m"
diff --git a/bin/asdoc b/bin/asdoc
index 0b74986..9f0b2cf 100755
--- a/bin/asdoc
+++ b/bin/asdoc
@@ -42,7 +42,7 @@
 if [ $OS = "Windows" ]; then
     # set FLEX_HOME relative to asdoc if not set
     test "$FLEX_HOME" = "" && {
-        FLEX_HOME=`dirname $0`/..
+        FLEX_HOME=`dirname "$0"`/..
         FLEX_HOME=`cygpath -m $FLEX_HOME`
     }
 
diff --git a/bin/compc b/bin/compc
index 476fd31..ddd014c 100755
--- a/bin/compc
+++ b/bin/compc
@@ -42,7 +42,7 @@
 if [ $OS = "Windows" ]; then
     # set FLEX_HOME relative to compc if not set
     test "$FLEX_HOME" = "" && {
-        FLEX_HOME=`dirname $0`/..
+        FLEX_HOME=`dirname "$0"`/..
         FLEX_HOME=`cygpath -m $FLEX_HOME`
     }
 
diff --git a/bin/copylocale b/bin/copylocale
index c48ed6b..f793b20 100755
--- a/bin/copylocale
+++ b/bin/copylocale
@@ -36,7 +36,7 @@
 if [ $OS = "Windows" ]; then
     # set FLEX_HOME relative to copylocale if not set
     test "$FLEX_HOME" = "" && {
-        FLEX_HOME=`dirname $0`/..
+        FLEX_HOME=`dirname "$0"`/..
         FLEX_HOME=`cygpath -m $FLEX_HOME`
     }
 
diff --git a/bin/digest b/bin/digest
index 055d01b..5cade68 100755
--- a/bin/digest
+++ b/bin/digest
@@ -36,7 +36,7 @@
 if [ $OS = "Windows" ]; then
     # set FLEX_HOME relative to digest if not set
     test "$FLEX_HOME" = "" && {
-        FLEX_HOME=`dirname $0`/..
+        FLEX_HOME=`dirname "$0"`/..
         FLEX_HOME=`cygpath -m $FLEX_HOME`
     }
 
diff --git a/bin/fcsh b/bin/fcsh
index 28ece27..20c4482 100755
--- a/bin/fcsh
+++ b/bin/fcsh
@@ -36,7 +36,7 @@
 if [ $OS = "Windows" ]; then
     # set FLEX_HOME relative to fcsh if not set
     test "$FLEX_HOME" = "" && {
-        FLEX_HOME=`dirname $0`/..
+        FLEX_HOME=`dirname "$0"`/..
         FLEX_HOME=`cygpath -m $FLEX_HOME`
     }
 
diff --git a/bin/fdb b/bin/fdb
index beb415d..b11b962 100755
--- a/bin/fdb
+++ b/bin/fdb
@@ -36,7 +36,7 @@
 if [ $OS = "Windows" ]; then
     # set FLEX_HOME relative to fdb if not set
     test "$FLEX_HOME" = "" && {
-        FLEX_HOME=`dirname $0`/..
+        FLEX_HOME=`dirname "$0"`/..
         FLEX_HOME=`cygpath -m $FLEX_HOME`
     }
 
diff --git a/bin/fontswf b/bin/fontswf
index 8265241..fc5bbae 100755
--- a/bin/fontswf
+++ b/bin/fontswf
@@ -34,7 +34,7 @@
 if [ $OS = "Windows" ]; then
 	# set FLEX_HOME relative to fontswf if not set
 	test "$FLEX_HOME" = "" && {
-	FLEX_HOME=`dirname $0`/..
+	FLEX_HOME=`dirname "$0"`/..
     	FLEX_HOME=`cygpath -m $FLEX_HOME`
 	}
 
@@ -42,7 +42,7 @@
 
 	# set FLEX_HOME relative to fontswf if not set
 	test "$FLEX_HOME" = "" && {
-	FLEX_HOME=`dirname $0`/..
+	FLEX_HOME=`dirname "$0"`/..
 	}
 
 fi
diff --git a/bin/mxmlc b/bin/mxmlc
index 811a41e..6e59b50 100755
--- a/bin/mxmlc
+++ b/bin/mxmlc
@@ -42,7 +42,7 @@
 if [ $OS = "Windows" ]; then
     # set FLEX_HOME relative to mxmlc if not set
     test "$FLEX_HOME" = "" && {
-        FLEX_HOME=`dirname $0`/..
+        FLEX_HOME=`dirname "$0"`/..
         FLEX_HOME=`cygpath -m $FLEX_HOME`
     }
 
diff --git a/bin/optimizer b/bin/optimizer
index e40a4d4..90d1373 100755
--- a/bin/optimizer
+++ b/bin/optimizer
@@ -36,7 +36,7 @@
 if [ $OS = "Windows" ]; then
     # set FLEX_HOME relative to optimizer if not set
     test "$FLEX_HOME" = "" && {
-        FLEX_HOME=`dirname $0`/..
+        FLEX_HOME=`dirname "$0"`/..
         FLEX_HOME=`cygpath -m $FLEX_HOME`
     }
 
diff --git a/bin/swcdepends b/bin/swcdepends
index e4ff00b..bef85d4 100755
--- a/bin/swcdepends
+++ b/bin/swcdepends
@@ -34,7 +34,7 @@
 if [ $OS = "Windows" ]; then
 	# set FLEX_HOME relative to swcdepends if not set
 	test "$FLEX_HOME" = "" && {
-	FLEX_HOME=`dirname $0`/..
+	FLEX_HOME=`dirname "$0"`/..
     	FLEX_HOME=`cygpath -m $FLEX_HOME`
 	}
 
diff --git a/bin/swfdump b/bin/swfdump
index 2529472..cb71172 100755
--- a/bin/swfdump
+++ b/bin/swfdump
@@ -36,7 +36,7 @@
 if [ $OS = "Windows" ]; then
     # set FLEX_HOME relative to swfdump if not set
     test "$FLEX_HOME" = "" && {
-        FLEX_HOME=`dirname $0`/..
+        FLEX_HOME=`dirname "$0"`/..
         FLEX_HOME=`cygpath -m $FLEX_HOME`
     }
 
@@ -44,7 +44,7 @@
 
     # set FLEX_HOME relative to swfdump if not set
     test "$FLEX_HOME" = "" && {
-    FLEX_HOME=`dirname $0`/..
+    FLEX_HOME=`dirname "$0"`/..
     }
 
     check64="`java -version 2>&1 | grep -i 64-Bit`"
diff --git a/build.properties b/build.properties
index c2c7d51..0ba13bb 100644
--- a/build.properties
+++ b/build.properties
@@ -18,8 +18,8 @@
 ################################################################################
 
 # flex-sdk-description values
-release = Apache Flex 4.15.0
-release.version = 4.15.0
+release = Apache Flex 4.16.0
+release.version = 4.16.0
 
 # override on command line with -Dbuild.number=999 or in local.properties
 build.number = 0
diff --git a/build.xml b/build.xml
index 9fd4ac4..66842ec 100644
--- a/build.xml
+++ b/build.xml
@@ -566,7 +566,7 @@
                 <include name="installer.properties/**"/>
                 <include name="CHANGES"/>
                 <include name="LICENSE"/>
-                <include name="licenseParts/*"/>
+                <include name="licenseParts/**"/>
                 <include name="NOTICE"/>
                 <include name="README"/>
                 <include name="RELEASE_NOTES"/>
@@ -1795,7 +1795,7 @@
                 <!-- exclude text files -->
                 <exclude name="CONTRIBUTING"/>
                 <exclude name="CONTRIBUTORS"/>
-                <exclude name="licenseParts/*"/>
+                <exclude name="licenseParts/**"/>
                 <exclude name="modules/thirdparty/batik/lib/**/LICENSE*.txt"/>
                 <exclude name="modules/thirdparty/batik/lib/**/README*.txt"/>
                 <exclude name="frameworks/projects/flatspark/src/flatspark/assets/fonts/**/OFL.txt"/>
diff --git a/flex-sdk-description.xml b/flex-sdk-description.xml
index 6ce6fde..ebda25d 100644
--- a/flex-sdk-description.xml
+++ b/flex-sdk-description.xml
@@ -18,8 +18,8 @@
 
 -->
 <flex-sdk-description>
-<name>Apache Flex 4.15.0 FP18.0 AIR18.0 en_US</name>
-<version>4.15.0</version>
-<build>20151228</build>
+<name>Apache Flex 4.16.0 FP20.0 AIR20.0 en_US</name>
+<version>4.16.0</version>
+<build>20160111</build>
 </flex-sdk-description>
         
diff --git a/flexunit-tests.xml b/flexunit-tests.xml
index 6475956..b09b56c 100644
--- a/flexunit-tests.xml
+++ b/flexunit-tests.xml
@@ -25,7 +25,7 @@
 
   <property name="exit" value="false"/>
   
-  <target name="test" depends="test-check,test-run,test-clean"
+  <target name="test" depends="test-check, test-run, test-clean"
     description="Runs FlexUnit tests"/>
 
   <target name="test-check">
@@ -77,6 +77,7 @@
             toDir="${tests.bin}/report"
             haltonfailure="false"
             verbose="true"
+            debug="true"
             localTrusted="true">
 
       <source dir="${project.root}/src"/>
@@ -85,7 +86,7 @@
         <include name="**/*Tests.as"/>
       </testSource>
 
-      <library dir="${FLEXUNIT_HOME}/FlexUnit4/target"/>
+      <library file="${FLEXUNIT_HOME}/FlexUnit4/target/flexunit-4.3.0-20140410-flex_4.12.0.swc"/>
       <library dir="${FLEXUNIT_HOME}/FlexUnit4CIListener/target"/>
     </flexunit>
   </target>
@@ -96,6 +97,7 @@
             toDir="${tests.bin}/report"
             haltonfailure="false"
             verbose="true"
+            debug="true"
             localTrusted="true">
 
       <source dir="${project.root}/src"/>
@@ -104,7 +106,7 @@
         <include name="**/*Tests.as"/>
       </testSource>
 
-      <library dir="${FLEXUNIT_HOME}/FlexUnit4/target"/>
+      <library file="${FLEXUNIT_HOME}/FlexUnit4/target/flexunit-4.3.0-20140410-flex_4.12.0.swc"/>
       <library dir="${FLEXUNIT_HOME}/FlexUnit4CIListener/target"/>
       <library dir="${project.libs}"/>
     </flexunit>
diff --git a/frameworks/build.xml b/frameworks/build.xml
index c902ec5..500a186 100644
--- a/frameworks/build.xml
+++ b/frameworks/build.xml
@@ -232,6 +232,18 @@
 		<condition property="playerglobal.swfversion" value="31">
 			<equals arg1="${playerglobal.version}" arg2="20.0" />
 		</condition>
+		<condition property="playerglobal.swfversion" value="32">
+			<equals arg1="${playerglobal.version}" arg2="21.0" />
+		</condition>
+		<condition property="playerglobal.swfversion" value="33">
+			<equals arg1="${playerglobal.version}" arg2="22.0" />
+		</condition>
+		<condition property="playerglobal.swfversion" value="34">
+			<equals arg1="${playerglobal.version}" arg2="23.0" />
+		</condition>
+		<condition property="playerglobal.swfversion" value="35">
+			<equals arg1="${playerglobal.version}" arg2="24.0" />
+		</condition>
 	</target>	
 
     <!--
diff --git a/frameworks/downloads.xml b/frameworks/downloads.xml
index 5d09c39..538f142 100644
--- a/frameworks/downloads.xml
+++ b/frameworks/downloads.xml
@@ -32,13 +32,19 @@
     <property name="lib.opt.dir" value="${FLEX_HOME}/lib/external/optional"/>
 
     <property name="flex-deps.dir" value="flex_deps"/>
+    <property name="adobe.afe.url" value="https://sourceforge.net/adobe/flexsdk/code/HEAD/tree/trunk/lib/afe.jar?format=raw"/>
     <property name="adobe.afe.file" value="afe.jar"/>
+    <property name="adobe.aglj40.url" value="https://sourceforge.net/adobe/flexsdk/code/HEAD/tree/trunk/lib/aglj40.jar?format=raw"/>
     <property name="adobe.aglj40.file" value="aglj40.jar"/>
+    <property name="adobe.rideau.url" value="http://sourceforge.net/adobe/flexsdk/code/HEAD/tree/trunk/lib/rideau.jar?format=raw"/>
     <property name="adobe.rideau.file" value="rideau.jar"/>
+    <property name="adobe.flex-fontkit.url" value="http://sourceforge.net/adobe/flexsdk/code/HEAD/tree/trunk/lib/flex-fontkit.jar?format=raw"/>
     <property name="adobe.flex-fontkit.file" value="flex-fontkit.jar"/>
     <property name="pixelbender.url" value="http://www.apache.org/dyn/mirrors/mirrors.cgi" />
     <property name="pixelbender.folder" value="flex/pixelbender/1.0/binaries" />
     <property name="pixelbender.bin.zip" value="apache-flex-sdk-pixel-bender-1.0.0-bin.zip" />
+    <property name="osmf.url" value="https://sourceforge.net/adobe/flexsdk/code/HEAD/tree/trunk/frameworks/libs/OSMF2_0.swc?format=raw" />
+    <property name="swfobject.url" value="https://codeload.github.com/swfobject/swfobject/zip/2.2" />
     
     <property name="adobe.flex.license" value="
         ${line.separator}
@@ -102,12 +108,15 @@
 
     <target name="download-osmf-swc" unless="osmf.swc.exists">
         <mkdir dir="${download.dir}"/>
-        <!-- get src="http://sourceforge.net/projects/osmf.adobe/files/OSMF%202.0%20Release%20%28final%20source%2C%20ASDocs%2C%20pdf%20guides%20and%20release%20notes%29/OSMF.swc/download" 
+        <get src="${osmf.url}"
             dest="${download.dir}/osmf.swc" 
-            verbose="false"/ -->
-        <get src="http://downloads.sourceforge.net/project/osmf.adobe/OSMF%202.0%20Release%20%28final%20source%2C%20ASDocs%2C%20pdf%20guides%20and%20release%20notes%29/OSMF.swc?r=&amp;ts=1381906346&amp;use_mirror=optimate" 
-            dest="${download.dir}/osmf.swc" 
-            verbose="false"/>
+            verbose="false" ignoreerrors="true"/>
+        <antcall target="get-from-cache-if-needed" >
+            <param name="filename" value="osmf.swc" />
+        </antcall>
+        <antcall target="fail-if-not-found" >
+            <param name="filename" value="osmf.swc" />
+        </antcall>
     </target>
     
     <!-- pixelbender files (Version 1.0) -->
@@ -126,6 +135,12 @@
             <param name="file" value="${pixelbender.bin.zip}" />
             <param name="dest" value="${download.dir}/${pixelbender.bin.zip}" />
         </antcall>
+        <antcall target="get-from-cache-if-needed" >
+            <param name="filename" value="${pixelbender.bin.zip}" />
+        </antcall>
+        <antcall target="fail-if-not-found" >
+            <param name="filename" value="${pixelbender.bin.zip}" />
+        </antcall>
         
         <unzip src="${download.dir}/${pixelbender.bin.zip}" dest="${FLEX_HOME}">
             <patternset>
@@ -149,9 +164,16 @@
         description="Copies SWFObject from code.google.com">
         
         <mkdir dir="${download.dir}"/>
-        <get src="https://codeload.github.com/swfobject/swfobject/zip/2.2"
+        <get src="${swfobject.url}"
             dest="${download.dir}/swfobject_2_2.zip" 
-            verbose="false"/>
+            verbose="false" ignoreerrors="true"/>
+        
+        <antcall target="get-from-cache-if-needed" >
+            <param name="filename" value="swfobject_2_2.zip" />
+        </antcall>
+        <antcall target="fail-if-not-found" >
+            <param name="filename" value="swfobject_2_2.zip" />
+        </antcall>
         
         <unzip src="${download.dir}/swfobject_2_2.zip" dest="${FLEX_HOME}/templates/swfobject">
             <patternset>
@@ -160,6 +182,7 @@
             </patternset>
             <flattenmapper />
         </unzip>
+        <antcall target="swfobject-double-check" />
     </target>
 
     <target name="swfobject-clean" description="Deletes templates swfobject code.">
@@ -172,6 +195,24 @@
         </delete>
     </target>
     
+    <target name="have-swfobject" >
+        <condition property="still-no-swfobject">
+            <not>
+                <available file="${FLEX_HOME}/templates/swfobject/swfobject.js" />
+            </not>
+        </condition>
+    </target>
+    
+    <target name="swfobject-double-check" depends="have-swfobject" if="still-no-swfobject" description="some SWFObject zips have a different folder structure so if the first unzip doesn't work, try this one">
+        <unzip src="${download.dir}/swfobject_2_2.zip" dest="${FLEX_HOME}/templates/swfobject">
+            <patternset>
+                <include name="swfobject/expressInstall.swf"/>
+                <include name="swfobject/swfobject.js"/>
+            </patternset>
+            <flattenmapper />
+        </unzip>
+    </target>
+    
     <!-- the copy of swfobject.js that is in javascript/fabridge -->
     <target name="swfobject-fabridge-download" depends="swfobject-download" 
         description="Copies swfobject.js from code.google.com to fabridge">
@@ -274,26 +315,50 @@
 
     <target name="download-afe" unless="adobe.afe.download.exists" >
         <mkdir dir="${download.dir}"/>
-        <get src="http://sourceforge.net/adobe/flexsdk/code/HEAD/tree/trunk/lib/afe.jar?format=raw"
-            dest="${download.dir}/${adobe.afe.file}"/>
+        <get src="${adobe.afe.url}"
+            dest="${download.dir}/${adobe.afe.file}" ignoreerrors="true"/>
+        <antcall target="get-from-cache-if-needed" >
+            <param name="filename" value="${adobe.afe.file}" />
+        </antcall>
+        <antcall target="fail-if-not-found" >
+            <param name="filename" value="${adobe.afe.file}" />
+        </antcall>
     </target>
 
     <target name="download-aglj40" unless="adobe.aglj40.download.exists" >
         <mkdir dir="${download.dir}"/>
-        <get src="http://sourceforge.net/adobe/flexsdk/code/HEAD/tree/trunk/lib/aglj40.jar?format=raw"
-             dest="${download.dir}/${adobe.aglj40.file}"/>
+        <get src="${adobe.aglj40.url}"
+             dest="${download.dir}/${adobe.aglj40.file}" ignoreerrors="true"/>
+         <antcall target="get-from-cache-if-needed" >
+             <param name="filename" value="${adobe.aglj40.file}" />
+         </antcall>
+         <antcall target="fail-if-not-found" >
+             <param name="filename" value="${adobe.aglj40.file}" />
+         </antcall>
     </target>
 
     <target name="download-rideau" unless="adobe.rideau.download.exists" >
         <mkdir dir="${download.dir}"/>
-        <get src="http://sourceforge.net/adobe/flexsdk/code/HEAD/tree/trunk/lib/rideau.jar?format=raw"
-             dest="${download.dir}/${adobe.rideau.file}"/>
+        <get src="${adobe.rideau.url}"
+             dest="${download.dir}/${adobe.rideau.file}" ignoreerrors="true"/>
+         <antcall target="get-from-cache-if-needed" >
+             <param name="filename" value="${adobe.rideau.file}" />
+         </antcall>
+         <antcall target="fail-if-not-found" >
+             <param name="filename" value="${adobe.rideau.file}" />
+         </antcall>
     </target>
 
     <target name="download-flex-fontkit" unless="adobe.flex-fontkit.download.exists" >
         <mkdir dir="${download.dir}"/>
-        <get src="http://sourceforge.net/adobe/flexsdk/code/HEAD/tree/trunk/lib/flex-fontkit.jar?format=raw"
-             dest="${download.dir}/${adobe.flex-fontkit.file}"/>
+        <get src="${adobe.flex-fontkit.url}"
+             dest="${download.dir}/${adobe.flex-fontkit.file}" ignoreerrors="true"/>
+         <antcall target="get-from-cache-if-needed" >
+             <param name="filename" value="${adobe.flex-fontkit.file}" />
+         </antcall>
+         <antcall target="fail-if-not-found" >
+             <param name="filename" value="${adobe.flex-fontkit.file}" />
+         </antcall>
     </target>
 
     <target name="clean-adobe-flex-sdk">
@@ -301,9 +366,13 @@
     </target>
 
     <target name="get_from_mirror">
-        <condition property="usingmirror" value="true">
+        <condition property="mirrorurl" value="true">
             <contains string="${server}" substring="mirrors.cgi" />
         </condition>
+        <antcall target="get_mirror_data" />
+        <condition property="usingmirror">
+            <available file="${basedir}/mirror.json" />
+        </condition>
         <antcall target="download_using_mirror">
             <param name="server" value="${server}" />
             <param name="folder" value="${folder}" />
@@ -318,8 +387,11 @@
         </antcall>
     </target>
     
+    <target name="get_mirror_data" if="mirrorurl">
+        <get src="${server}/${folder}/${file}?asjson=true" verbose="true" dest="${basedir}/mirror.json" ignoreerrors="true"/>
+    </target>
+    
     <target name="download_using_mirror" if="usingmirror">
-        <get src="${server}/${folder}/${file}?asjson=true" verbose="true" dest="${basedir}/mirror.json" />
         <replace file="${basedir}/mirror.json">
             <replacefilter token="{"
             value="" />
@@ -339,11 +411,35 @@
         <property file="${basedir}/mirror.json" />
         <delete file="${basedir}/mirror.json" />
         <echo>Using mirror: ${preferred}</echo>
-        <get src="${preferred}${folder}/${file}" dest="${dest}" />
+        <get src="${preferred}${folder}/${file}" dest="${dest}" ignoreerrors="true" />
     </target>
     
     <target name="download_using_get" unless="usingmirror">
-        <get src="${server}/${folder}/${file}" dest="${dest}" />
+        <get src="${server}/${folder}/${file}" dest="${dest}" ignoreerrors="true"/>
     </target>
 
+    <target name="fail-if-not-found">
+        <fail message="${filename} could not be downloaded or found in cache">
+            <condition>
+                <not>
+                    <available file="${download.dir}/${filename}" />
+                </not>
+            </condition>
+        </fail>
+    </target>
+
+    <target name="double-check-file" >
+        <condition property="still-no-file" value="true">
+            <and>
+                <not>
+                    <available file="${download.dir}/${filename}" />
+                </not>
+                <isset property="env.FLEX_DOWNLOAD_CACHE" />
+            </and>
+        </condition>
+        <echo>Need file: ${still_no_file}</echo>
+    </target>
+    <target name="get-from-cache-if-needed" depends="double-check-file" if="still-no-file">
+        <copy file="${env.FLEX_DOWNLOAD_CACHE}/${filename}" tofile="${download.dir}/${filename}" />
+    </target>
 </project>
diff --git a/frameworks/projects/advancedgrids/src/mx/collections/GroupingCollection2.as b/frameworks/projects/advancedgrids/src/mx/collections/GroupingCollection2.as
index cf7eab7..6ceeac7 100644
--- a/frameworks/projects/advancedgrids/src/mx/collections/GroupingCollection2.as
+++ b/frameworks/projects/advancedgrids/src/mx/collections/GroupingCollection2.as
@@ -1212,8 +1212,6 @@
             // initialize the variables
             initialize();
         
-           
-            
             if ((source as ICollectionView).length == 0)
                 return false;
             
diff --git a/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionView.as b/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionView.as
index 987a684..b3b7258 100644
--- a/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionView.as
+++ b/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionView.as
@@ -390,9 +390,7 @@
      *
      *  @param item The Object that defines the node to look for.
      *
-     *  @param <code>true</code> if the collection contains the item,
-     *
-     *  @return <code>true</code> if the data item is in the collection, 
+     *  @return <code>true</code> if the data item is in the collection,
      *  and <code>false</code> if not.
      *  
      *  @langversion 3.0
diff --git a/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionViewCursor.as b/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionViewCursor.as
index 1f3244d..bf32f07 100644
--- a/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionViewCursor.as
+++ b/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionViewCursor.as
@@ -21,7 +21,6 @@
 {
 
 import flash.events.EventDispatcher;
-import flash.utils.Dictionary;
 
 import mx.collections.errors.ChildItemPendingError;
 import mx.collections.errors.ItemPendingError;
@@ -29,6 +28,7 @@
 import mx.events.CollectionEvent;
 import mx.events.CollectionEventKind;
 import mx.events.FlexEvent;
+import mx.utils.ObjectUtil;
 import mx.utils.UIDUtil;
 
 use namespace mx_internal;
@@ -307,50 +307,38 @@
     //--------------------------------------------------------------------------
     
     /**
-     *  @inheritDoc
-     *  
      *  <p>Note that for this class, the view does not need to be sorted in order to
-     *  call this method.</p>
+     *  call this method. Also, if the item cannot be found, the cursor location is
+     *  left on the last queried object.</p>
+     *
+     *  @inheritDoc
      * 
      *  @langversion 3.0
      *  @playerversion Flash 9
      *  @playerversion AIR 1.1
      *  @productversion Flex 3
      */
-    public function findAny(values:Object):Boolean
+    public function findAny(valuesToMatch:Object):Boolean
     {
         seek(CursorBookmark.FIRST);
         
-        var done:Boolean = false;
-        while (!done)
+        do
         {
-            var o:Object = hierarchicalData.getData(current);
-            
-            var matches:Boolean = true;
-            for (var p:String in values)
-            {
-                if (o[p] != values[p])
-                {
-                    matches = false;
-                    break;
-                }
-            }
-
-            if (matches)
+            if (ObjectUtil.valuesAreSubsetOfObject(valuesToMatch, hierarchicalData.getData(current)))
                 return true;
-
-            done = !moveNext();
         }
+        while(moveNext());
 
         return false;
     }
 
     /**
-     *  @inheritDoc
-     *  
      *  <p>Note that for this class, the view does not need to be sorted in order to
-     *  call this method.</p>
-     *  
+     *  call this method. Also, if the item cannot be found, the cursor location is
+     *  left on the last queried object.</p>
+     *
+     *  @inheritDoc
+     *
      *  @langversion 3.0
      *  @playerversion Flash 9
      *  @playerversion AIR 1.1
@@ -362,40 +350,27 @@
     }
 
     /**
-     *  @inheritDoc
-     *  
      *  <p>Note that for this class, the view does not need to be sorted in order to
-     *  call this method.</p>
+     *  call this method. Also, if the item cannot be found, the cursor location is
+     *  left on the last queried object.</p>
+     *
+     *  @inheritDoc
      *  
      *  @langversion 3.0
      *  @playerversion Flash 9
      *  @playerversion AIR 1.1
      *  @productversion Flex 3
      */
-    public function findLast(values:Object):Boolean
+    public function findLast(valuesToMatch:Object):Boolean
     {
         seek(CursorBookmark.LAST);
         
-        var done:Boolean = false;
-        while (!done)
+        do
         {
-            var o:Object = current; 
-            
-            var matches:Boolean = true;
-            for (var p:String in values)
-            {
-                if (o[p] != values[p])
-                {
-                    matches = false;
-                    break;
-                }
-            }
-            
-            if (matches)
+            if (ObjectUtil.valuesAreSubsetOfObject(valuesToMatch, hierarchicalData.getData(current)))
                 return true;
-
-            done = !movePrevious();
         }
+        while(movePrevious());
 
         return false;
     }
@@ -412,7 +387,7 @@
     public function moveNext():Boolean 
     {
         var currentNode:Object = current;
-        //if there is no currentNode then we cant move forward and must be off the ends
+        //if there is no currentNode then we can't move forward and must be off the ends
         if (currentNode == null) 
             return false; 
         
diff --git a/frameworks/projects/advancedgrids/src/mx/controls/AdvancedDataGridBaseEx.as b/frameworks/projects/advancedgrids/src/mx/controls/AdvancedDataGridBaseEx.as
index b0a1f67..c2a53f3 100644
--- a/frameworks/projects/advancedgrids/src/mx/controls/AdvancedDataGridBaseEx.as
+++ b/frameworks/projects/advancedgrids/src/mx/controls/AdvancedDataGridBaseEx.as
@@ -2798,7 +2798,8 @@
      */
     override public function itemToLabel(data:Object):String
     {
-        return displayableColumns[sortIndex == -1 ? 0 : sortIndex].itemToLabel(data);
+        var column:AdvancedDataGridColumn = displayableColumns[sortIndex == -1 ? 0 : sortIndex];
+        return column ? column.itemToLabel(data) : "";
     }
 
     //--------------------------------------------------------------------------
@@ -2866,7 +2867,7 @@
 
         var n:int = headerInfos ? headerInfos.length : 0;
         var i:int;
-        var k:int= 0;;
+        var k:int= 0;
         
         for ( i = 0; i < n; i++)
         {
@@ -2902,18 +2903,17 @@
     /**
      *  @private
 	 * 
-	 * Note columns may not of been committed at this point.
+	 * Note columns may not have been committed at this point.
      */
     protected function initializeHeaderInfo(columns:Array):Array
     {
-        var newArray:Array = [];
+        var result:Array = [];
         var n:int = columns.length;
         for(var i:int = 0; i < n; i++)
         {
-            var headerInfo:AdvancedDataGridHeaderInfo = new AdvancedDataGridHeaderInfo(columns[i],null,i, 0) ;
-            newArray.push(headerInfo);
+            result.push(new AdvancedDataGridHeaderInfo(columns[i], null, i, 0));
         }
-        return newArray;
+        return result;
     }
 	
 	/**
@@ -5015,8 +5015,6 @@
             actualRowIndex = rowIndex;
         }
 
-        var bm:EdgeMetrics = borderMetrics;
-
         var len:uint = /*(headerItems && headerItems[0]) ? headerItems[0].length :*/ visibleColumns.length;
         var lastColIndex:int = horizontalScrollPosition + len - 1;
 
@@ -5072,7 +5070,7 @@
         {
             var evt:ListEvent = new ListEvent(ListEvent.CHANGE);
             evt.columnIndex = coord.columnIndex;
-            evt.rowIndex = coord.rowIndex;;
+            evt.rowIndex = coord.rowIndex;
             evt.itemRenderer = item;
             dispatchEvent(evt);
         }
@@ -6891,13 +6889,13 @@
      */
     override protected function collectionChangeHandler(event:Event):void
     {
-        //if the iterator is null that indicates we havent been validated yet so we'll bail. 
+        //if the iterator is null that indicates we haven't been validated yet so we'll bail.
         if (iterator == null)
             return;
 
         if (event is CollectionEvent)
         {
-            var ceEvent:CollectionEvent = CollectionEvent(event)
+            var ceEvent:CollectionEvent = CollectionEvent(event);
             if (ceEvent.kind == CollectionEventKind.mx_internal::EXPAND)
             {
                 //we ignore expand in list/tree
@@ -6908,7 +6906,7 @@
                 //this prevents listbase from invalidating the displaylist too early. 
                 event.stopPropagation();
                 //we only want to update the displaylist if an updated item was visible
-                //but dont have a sufficient test for that yet
+                //but don't have a sufficient test for that yet
                 itemsSizeChanged = true;
                 invalidateDisplayList();
             }
@@ -7291,7 +7289,6 @@
 
         var advancedDataGridEvent:AdvancedDataGridEvent;
         var r:IListItemRenderer;
-        var s:Sprite;
         var n:int;
         var i:int;
         var pos:Point;
@@ -8145,8 +8142,6 @@
     {
         var columnName:String = event.dataField;
         var columnNumber:int  = event.columnIndex;
-        var sortFields:Array;
-        var sort:ISort;
 
         if (!sortableColumns || !_columns[columnNumber].sortable)
             return;
diff --git a/frameworks/projects/advancedgrids/src/mx/controls/advancedDataGridClasses/AdvancedDataGridBase.as b/frameworks/projects/advancedgrids/src/mx/controls/advancedDataGridClasses/AdvancedDataGridBase.as
index 4a1b6d2..b662967 100644
--- a/frameworks/projects/advancedgrids/src/mx/controls/advancedDataGridClasses/AdvancedDataGridBase.as
+++ b/frameworks/projects/advancedgrids/src/mx/controls/advancedDataGridClasses/AdvancedDataGridBase.as
@@ -1351,15 +1351,9 @@
      *  @return The newly selected item or <code>null</code> if the selection
      *  has not changed.
      */
-    override protected function moveSelectionVertically(
-        code:uint, shiftKey:Boolean,
-        ctrlKey:Boolean):void
+    override protected function moveSelectionVertically(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void
     {
         var newVerticalScrollPosition:Number;
-        var listItem:IListItemRenderer;
-        var uid:String;
-        var len:int;
-
         showCaret = true;
 
         var rowCount:int = listItems.length;
@@ -1825,18 +1819,15 @@
     /**
      *  @private
      */
-    private function createRow(left:Number,top:Number,right:Number,bottom:Number,more:Boolean):void
+    private function createRow(left:Number, top:Number, right:Number, bottom:Number, more:Boolean):void
     {
         var xx:Number;
-        var ww:Number;
         var hh:Number;
 
         var i:int;
         var n:int;
 
-        var c:AdvancedDataGridColumn;
         var item:IListItemRenderer;
-        var rowData:AdvancedDataGridListData;
         var extraItem:IListItemRenderer;
 
         var bSelected:Boolean = false;
@@ -1877,7 +1868,7 @@
         }
         else
         {
-            // if we've run out of data, we dont make renderers
+            // if we've run out of data, we don't make renderers
             // and we inherit the previous row's height or rowHeight
             // if it is the first row.
             hh = currentRowNum > 1 ? rowInfo[currentRowNum - 1].height : rowHeight;
@@ -1965,9 +1956,8 @@
             }
             catch (e:ItemPendingError)
             {
-                lastSeekPending = new ListBaseSeekPending(CursorBookmark.CURRENT, 0)
-                    e.addResponder(new ItemResponder(seekPendingResultHandler, seekPendingFailureHandler, 
-                                                     lastSeekPending));
+                lastSeekPending = new ListBaseSeekPending(CursorBookmark.CURRENT, 0);
+                e.addResponder(new ItemResponder(seekPendingResultHandler, seekPendingFailureHandler, lastSeekPending));
                 more = false;
                 iteratorValid = false;
             }
@@ -2059,8 +2049,6 @@
      *
      *  @param c The column of the control.
      *
-     *  @param The header item renderer.
-     *
      *  @return The header item renderer.
      * 
      *  
diff --git a/frameworks/projects/advancedgrids/src/mx/controls/listClasses/AdvancedListBase.as b/frameworks/projects/advancedgrids/src/mx/controls/listClasses/AdvancedListBase.as
index d3e150f..a872381 100644
--- a/frameworks/projects/advancedgrids/src/mx/controls/listClasses/AdvancedListBase.as
+++ b/frameworks/projects/advancedgrids/src/mx/controls/listClasses/AdvancedListBase.as
@@ -3986,12 +3986,7 @@
     
     private function makeRowsAndColumnsWithExtraRows(unscaledWidth:Number,unscaledHeight:Number):void
     {
-        var lastPrefixRow:ListRowInfo;
-        var lastOnscreenRow:ListRowInfo;
-        var lastOffscreenRow:ListRowInfo;
-        var onscreenRowIndex:int;
         var pt:Point;
-
         var desiredExtraRowsTop:int = offscreenExtraRows / 2;
         var desiredExtraRowsBottom:int = offscreenExtraRows / 2;
         
@@ -5058,7 +5053,7 @@
         
         clearIndicators();
         
-        visibleData = {}
+        visibleData = {};
         
         makeRowsAndColumns(0, 0, listContent.width, listContent.height, 0, 0);
         
@@ -5236,7 +5231,10 @@
             }
             else if (item && item.mask)
             {
-                itemMaskFreeList.push(item.mask);
+                if(itemMaskFreeList)
+                {
+                    itemMaskFreeList.push(item.mask);
+                }
                 item.mask = null;
             }
         }
@@ -5406,7 +5404,6 @@
         var selectionChange:Boolean = false;
         var placeHolder:CursorBookmark = iterator.bookmark;
         var index:int = itemRendererToIndex(item);
-        var data:Object;
         var uid:String = itemToUID(item.data);
 
         if (!allowMultipleSelection || (!shiftKey && !ctrlKey))
@@ -5513,7 +5510,7 @@
             iterator.seek(placeHolder, 0);
 
             // if user is clicking with ctl key then
-            // seletion gets changed always.
+            // selection gets changed always.
             selectionChange = true;
         }
 
@@ -6001,7 +5998,7 @@
 
             }
             index = indices[0];
-            indices.shift()
+            indices.shift();
 
             var data:Object = collectionIterator.current;
             if (firstTime)
diff --git a/frameworks/projects/advancedgrids/tests/mx/collections/HierarchicalCollectionViewCursor_FindAny_Tests.as b/frameworks/projects/advancedgrids/tests/mx/collections/HierarchicalCollectionViewCursor_FindAny_Tests.as
new file mode 100644
index 0000000..230fa91
--- /dev/null
+++ b/frameworks/projects/advancedgrids/tests/mx/collections/HierarchicalCollectionViewCursor_FindAny_Tests.as
@@ -0,0 +1,510 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.asserts.assertFalse;
+    import org.flexunit.asserts.assertNotNull;
+    import org.flexunit.asserts.assertNull;
+    import org.flexunit.asserts.assertTrue;
+
+    public class HierarchicalCollectionViewCursor_FindAny_Tests
+    {
+        private static const DEPARTMENT_SALES:String = "Sales";
+        private static const DEPARTMENT_DEVELOPMENT:String = "Development";
+        private static const NO_EMPLOYEES_PER_DEPARTMENT:int = 5;
+        private static const NO_DEPARTMENTS:int = 2;
+        private static const NO_EMPLOYEES:int = NO_EMPLOYEES_PER_DEPARTMENT * NO_DEPARTMENTS;
+        private static const _utils:HierarchicalCollectionViewTestUtils = new HierarchicalCollectionViewTestUtils();
+        private static var _collectionView:HierarchicalCollectionView;
+        private static var _sut:HierarchicalCollectionViewCursor;
+        private static var _level0:ArrayCollection;
+        private static var _employeesByID:Array = [];
+
+        [Before]
+        public function setUp():void
+        {
+            _collectionView = createHierarchicalCollectionView(createGroupingCollection(createEmployees()));
+            _level0 = _utils.getRoot(_collectionView) as ArrayCollection;
+            _sut = _collectionView.createCursor() as HierarchicalCollectionViewCursor;
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            _collectionView = null;
+            _sut = null;
+        }
+
+        [Test]
+        public function test_seeking_first_lands_on_development():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            _sut.seek(new CursorBookmark(CursorBookmark.FIRST));
+
+            //then
+            var developmentGroup:Object = _level0.getItemAt(0);
+            assertTrue(developmentGroup.hasOwnProperty("GroupLabel"));
+            assertEquals(DEPARTMENT_DEVELOPMENT, developmentGroup["GroupLabel"]);
+            assertEquals(developmentGroup, _sut.current);
+        }
+
+        [Test]
+        public function test_searching_for_sales_using_anonymous_object_lands_on_sales_group():void
+        {
+            //given
+            var salesIdentifier:Object = {GroupLabel:DEPARTMENT_SALES};
+
+            //when
+            var found:Boolean = _sut.findAny(salesIdentifier);
+
+            //then
+            assertTrue(found);
+
+            var current:Object = _sut.current;
+            assertTrue(current.hasOwnProperty("GroupLabel"));
+            assertEquals(DEPARTMENT_SALES, current["GroupLabel"]);
+        }
+
+        [Test]
+        public function test_searching_for_sales_via_findLast_using_anonymous_object_lands_on_sales_group():void
+        {
+            //given
+            var salesIdentifier:Object = {GroupLabel:DEPARTMENT_SALES};
+
+            //when
+            var found:Boolean = _sut.findLast(salesIdentifier);
+
+            //then
+            assertTrue(found);
+
+            var current:Object = _sut.current;
+            assertTrue(current.hasOwnProperty("GroupLabel"));
+            assertEquals(DEPARTMENT_SALES, current["GroupLabel"]);
+        }
+
+        [Test]
+        public function test_finding_current_leaves_first_unchanged():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+            _sut.seek(new CursorBookmark(CursorBookmark.FIRST));
+
+            //when
+            var found:Boolean = _sut.findAny(_sut.current);
+
+            //then
+            assertTrue(found);
+            assertEquals(_level0.getItemAt(0), _sut.current);
+        }
+
+        [Test] //FLEX-35031
+        public function test_FLEX_35031_finding_current_sealed_class_instance_with_findAny():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+            _sut.seek(new CursorBookmark(CursorBookmark.FIRST));
+            _sut.moveNext(); //an EmployeeVO instance from the "Development" department
+
+            //when
+            var found:Boolean = _sut.findAny(_sut.current);
+
+            //then
+            assertTrue(found);
+            assertTrue(_sut.current is EmployeeVO);
+            assertEquals(DEPARTMENT_DEVELOPMENT, EmployeeVO(_sut.current).department);
+        }
+
+        [Test] //FLEX-35031
+        public function test_FLEX_35031_finding_different_sealed_class_instance_with_findAny():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+            var salesGroup:Object = _level0.getItemAt(1);
+            var salesEmployee:EmployeeVO = salesGroup.children.getItemAt(0) as EmployeeVO;
+            assertEquals(DEPARTMENT_SALES, salesEmployee.department);
+
+            //when
+            var found:Boolean = _sut.findAny(salesEmployee);
+
+            //then
+            assertTrue(found);
+            assertEquals(salesEmployee, _sut.current);
+        }
+
+        [Test] //FLEX-35031
+        public function test_FLEX_35031_finding_different_sealed_class_instance_with_findLast():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+            var developmentGroup:Object = _level0.getItemAt(0);
+            var developmentEmployee:EmployeeVO = developmentGroup.children.getItemAt(0) as EmployeeVO;
+            assertEquals(DEPARTMENT_DEVELOPMENT, developmentEmployee.department);
+
+            //when
+            var found:Boolean = _sut.findLast(developmentEmployee);
+
+            //then
+            assertTrue(found);
+            assertEquals(developmentEmployee, _sut.current);
+        }
+
+        [Test] //FLEX-35031
+        public function test_FLEX_35031_finding_sealed_class_instance_from_current_with_findLast():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+            _sut.seek(new CursorBookmark(CursorBookmark.FIRST));
+            _sut.moveNext(); //an EmployeeVO instance from the "Development" department
+
+            //when
+            var found:Boolean = _sut.findLast(_sut.current);
+
+            //then
+            assertTrue(found);
+            assertTrue(_sut.current is EmployeeVO);
+            assertEquals(DEPARTMENT_DEVELOPMENT, EmployeeVO(_sut.current).department);
+        }
+
+        [Test] //FLEX-33058
+        public function test_FLEX_33058_when_not_found_via_findAny_using_anonymous_object_current_is_null():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            var found:Boolean = _sut.findAny({someProperty:"someValue"});
+
+            //then
+            assertFalse(found);
+            assertEquals(null, _sut.current);
+        }
+
+        [Test] //FLEX-33058
+        public function test_FLEX_33058_when_not_found_via_findLast_using_anonymous_object_current_is_null():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            var found:Boolean = _sut.findLast({someProperty:"someValue"});
+
+            //then
+            assertFalse(found);
+            assertEquals(null, _sut.current);
+        }
+
+        [Test] //FLEX-35031
+        public function test_FLEX_35031_findAny_does_not_fatal_when_trying_to_find_null_and_doesnt_find_it():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            var found:Boolean = _sut.findAny(null);
+
+            //then
+            assertFalse(found);
+            assertEquals(null, _sut.current);
+        }
+
+        [Test] //FLEX-35031
+        public function test_FLEX_35031_findLast_does_not_fatal_when_trying_to_find_null_and_doesnt_find_it():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            var found:Boolean = _sut.findLast(null);
+
+            //then
+            assertFalse(found);
+            assertEquals(null, _sut.current);
+        }
+
+        [Test]
+        public function test_findAny_finds_the_first_item_when_its_argument_is_an_empty_anonymous_object():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            var found:Boolean = _sut.findAny({});
+
+            //then
+            assertTrue(found);
+            assertEquals(_level0.getItemAt(0), _sut.current);
+        }
+
+        [Test]
+        public function test_findLast_finds_the_last_item_when_its_argument_is_an_empty_anonymous_object():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            var found:Boolean = _sut.findLast({});
+
+            //then
+            assertTrue(found);
+            assertEquals(_employeesByID[_employeesByID.length - 1], _sut.current);
+        }
+
+        [Test]
+        public function test_findAny_finds_sealed_class_instance_via_anonymous_object_with_subset_of_properties():void
+        {
+            //given
+            const ID_TO_FIND:int = NO_EMPLOYEES_PER_DEPARTMENT;
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            var found:Boolean = _sut.findAny({department:DEPARTMENT_SALES, uniqueID:ID_TO_FIND});
+
+            //then
+            assertTrue(found);
+            var currentEmployee:EmployeeVO = _sut.current as EmployeeVO;
+            assertNotNull(currentEmployee);
+            assertEquals(DEPARTMENT_SALES, currentEmployee.department);
+            assertEquals(ID_TO_FIND, currentEmployee.uniqueID);
+        }
+
+        [Test]
+        public function test_findAny_finds_sealed_class_instance_via_anonymous_object_with_subset_of_properties_and_string_values_instead_of_int():void
+        {
+            //given
+            const ID_TO_FIND:int = NO_EMPLOYEES_PER_DEPARTMENT;
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            var found:Boolean = _sut.findAny({department:DEPARTMENT_SALES, uniqueID:ID_TO_FIND.toString()});
+
+            //then
+            assertTrue(found);
+            var currentEmployee:EmployeeVO = _sut.current as EmployeeVO;
+            assertNotNull(currentEmployee);
+            assertEquals(DEPARTMENT_SALES, currentEmployee.department);
+            assertEquals(ID_TO_FIND, currentEmployee.uniqueID);
+        }
+
+        [Test]
+        public function test_findLast_finds_sealed_class_instance_via_anonymous_object_with_subset_of_properties():void
+        {
+            //given
+            const ID_TO_FIND:int = 0;
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            var found:Boolean = _sut.findLast({department:DEPARTMENT_DEVELOPMENT, uniqueID:ID_TO_FIND});
+
+            //then
+            assertTrue(found);
+            var currentEmployee:EmployeeVO = _sut.current as EmployeeVO;
+            assertNotNull(currentEmployee);
+            assertEquals(DEPARTMENT_DEVELOPMENT, currentEmployee.department);
+            assertEquals(ID_TO_FIND, currentEmployee.uniqueID);
+        }
+
+        [Test]
+        public function test_findLast_finds_sealed_class_instance_via_anonymous_object_with_subset_of_properties_and_string_values_instead_of_int():void
+        {
+            //given
+            const ID_TO_FIND:int = 0;
+            _utils.openAllNodes(_collectionView);
+
+            //when
+            var found:Boolean = _sut.findLast({department:DEPARTMENT_DEVELOPMENT, uniqueID:ID_TO_FIND.toString()});
+
+            //then
+            assertTrue(found);
+            var currentEmployee:EmployeeVO = _sut.current as EmployeeVO;
+            assertNotNull(currentEmployee);
+            assertEquals(DEPARTMENT_DEVELOPMENT, currentEmployee.department);
+            assertEquals(ID_TO_FIND, currentEmployee.uniqueID);
+        }
+
+        [Test]
+        public function test_findAny_finds_sealed_class_instance_via_dynamic_class_instance_with_subset_of_properties():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+            var lastEmployee:EmployeeVO = _employeesByID[_employeesByID.length - 1];
+
+            //when
+            var found:Boolean = _sut.findLast(new DynamicVO(lastEmployee.name));
+
+            //then
+            assertTrue(found);
+            assertEquals(lastEmployee, _sut.current);
+        }
+
+        [Test]
+        public function test_findLast_finds_sealed_class_instance_via_dynamic_class_instance_with_subset_of_properties():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+            var firstEmployee:EmployeeVO = _employeesByID[0];
+
+            //when
+            var found:Boolean = _sut.findLast(new DynamicVO(firstEmployee.name));
+
+            //then
+            assertTrue(found);
+            assertEquals(firstEmployee, _sut.current);
+        }
+
+        /**
+         * Note that in a perfect world this would work. However, to accomplish this task
+         * we'd need to use <code>flash.utils.describeType()</code> (or
+         * <code>DescribeTypeCache.describeType()</code> or <code>ObjectUtil.getClassInfo()</code>).
+         * But since no usage of findAny(), findFirst() and findLast() in the framework requires
+         * this feature (as they are all about finding items that already exist in the collection),
+         * there's no business case for implementing it.
+         */
+        [Test]
+        public function test_findAny_does_NOT_find_sealed_class_instance_via_other_sealed_class_instance_with_subset_of_properties():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+            var lastEmployee:EmployeeVO = _employeesByID[_employeesByID.length - 1];
+
+            //when
+            var found:Boolean = _sut.findAny(new NamedVO(lastEmployee.name));
+
+            //then
+            assertFalse(found);
+            assertNull(_sut.current);
+        }
+
+        //see the comment for the function above
+        [Test]
+        public function test_findLast_does_NOT_find_sealed_class_instance_via_other_sealed_class_instance_with_subset_of_properties():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+            var firstEmployee:EmployeeVO = _employeesByID[0];
+
+            //when
+            var found:Boolean = _sut.findLast(new NamedVO(firstEmployee.name));
+
+            //then
+            assertFalse(found);
+            assertNull(_sut.current);
+        }
+
+        [Test]
+        public function test_findLast_finds_different_object_to_findFirst_via_anonymous_object_with_subset_of_properties():void
+        {
+            //given
+            _utils.openAllNodes(_collectionView);
+
+            var secondEmployee:EmployeeVO = _employeesByID[1] as EmployeeVO;
+            var secondToLastEmployee:EmployeeVO = _employeesByID[NO_EMPLOYEES - 2] as EmployeeVO;
+
+            const sameName:String = "John";
+
+            //when
+            secondEmployee.name = sameName;
+            secondToLastEmployee.name = sameName;
+
+            var foundFromBeginning:Boolean = _sut.findAny({name:sameName});
+
+            //then
+            assertTrue(foundFromBeginning);
+            assertEquals(secondEmployee, _sut.current);
+
+            //when
+            var foundFromEnd:Boolean = _sut.findLast({name:sameName});
+
+            //then
+            assertTrue(foundFromEnd);
+            assertEquals(secondToLastEmployee, _sut.current);
+        }
+
+        private static function createHierarchicalCollectionView(groupingCollection:GroupingCollection2):HierarchicalCollectionView
+        {
+            return new HierarchicalCollectionView(groupingCollection);
+        }
+
+        private static function createEmployees():ArrayCollection
+        {
+            var result:ArrayCollection = new ArrayCollection();
+            for (var i:int = 0; i < NO_EMPLOYEES_PER_DEPARTMENT * 2; i++)
+            {
+                result.addItem(createEmployee("Emp-" + i, (i < NO_EMPLOYEES_PER_DEPARTMENT ? DEPARTMENT_DEVELOPMENT : DEPARTMENT_SALES), i));
+            }
+
+            return result;
+        }
+
+        private static function createEmployee(name:String, department:String, uniqueID:int):EmployeeVO
+        {
+            var employeeVO:EmployeeVO = new EmployeeVO(name, department, uniqueID);
+            _employeesByID[employeeVO.uniqueID] = employeeVO;
+            return employeeVO;
+        }
+
+        private static function createGroupingCollection(source:ArrayCollection):GroupingCollection2
+        {
+            var collection:GroupingCollection2 = new GroupingCollection2();
+            var grouping:Grouping = new Grouping();
+            grouping.fields = [new GroupingField("department")];
+            collection.grouping = grouping;
+
+            collection.source = source;
+            collection.refresh();
+
+            return collection;
+        }
+    }
+}
+
+class EmployeeVO
+{
+    public var name:String;
+    public var department:String;
+    public var uniqueID:int;
+
+    public function EmployeeVO(name:String, department:String, uniqueID:int)
+    {
+        this.name = name;
+        this.department = department;
+        this.uniqueID = uniqueID;
+    }
+}
+
+class NamedVO
+{
+    public var name:String;
+
+    public function NamedVO(name:String)
+    {
+        this.name = name;
+    }
+}
+
+dynamic class DynamicVO
+{
+    public function DynamicVO(name:String)
+    {
+        this.name = name;
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/advancedgrids/tests/mx/collections/HierarchicalCollectionView_FLEX_34775_Tests.as b/frameworks/projects/advancedgrids/tests/mx/collections/HierarchicalCollectionView_FLEX_34775_Tests.as
index 14bc2a3..b91d114 100644
--- a/frameworks/projects/advancedgrids/tests/mx/collections/HierarchicalCollectionView_FLEX_34775_Tests.as
+++ b/frameworks/projects/advancedgrids/tests/mx/collections/HierarchicalCollectionView_FLEX_34775_Tests.as
@@ -101,7 +101,7 @@
         {
             function filterOutLocationNode(node:DataNode):Boolean {
                 return node && node.label != locationNodeName;
-            };
+            }
 
             const locationNodeName:String = StringUtil.trim(HIERARCHY_STRING.split("\n")[2]);
 
@@ -123,7 +123,7 @@
             assertEquals(1, _sut.length);
         }
 
-        private function attemptNavigation(into:HierarchicalCollectionView):int
+        private static function attemptNavigation(into:HierarchicalCollectionView):int
         {
             var cursor:IViewCursor = into.createCursor();
             var i:int = 0;
diff --git a/frameworks/projects/advancedgrids/tests/mx/controls/FLEX_33058_Tests.as b/frameworks/projects/advancedgrids/tests/mx/controls/FLEX_33058_Tests.as
new file mode 100644
index 0000000..f445433
--- /dev/null
+++ b/frameworks/projects/advancedgrids/tests/mx/controls/FLEX_33058_Tests.as
@@ -0,0 +1,196 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.controls {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+    import flash.events.MouseEvent;
+
+    import mx.collections.ArrayCollection;
+    import mx.collections.Grouping;
+    import mx.collections.GroupingCollection2;
+    import mx.collections.GroupingField;
+    import mx.collections.IHierarchicalCollectionView;
+    import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
+    import mx.controls.advancedDataGridClasses.AdvancedDataGridHeaderRenderer;
+    import mx.events.FlexEvent;
+
+    import org.flexunit.asserts.assertNotNull;
+    import org.flexunit.asserts.assertTrue;
+    import org.flexunit.async.Async;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    public class FLEX_33058_Tests
+    {
+        private static const DEPARTMENT_SALES:String = "Sales";
+        private static const DEPARTMENT_DEVELOPMENT:String = "Development";
+        private static const NO_ITEMS_PER_GRID_HEIGHT:int = 5;
+        private static const NO_ENTER_FRAMES_TO_ALLOW:int = 2;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        private static var _grid:AdvancedDataGrid;
+        private static var _header:AdvancedDataGridHeaderRenderer;
+        private static var _aSalesEmployee:EmployeeVO;
+        private static var noEnterFramesRemaining:int = NaN;
+
+        [Before]
+        public function setUp():void
+        {
+            _grid = new AdvancedDataGrid();
+            _grid.columns = [createNameColumn()];
+            _grid.dataProvider = createGroupingCollection(createEmployees());
+
+            _grid.addEventListener(Event.ADDED, onAdded);
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            _grid.removeEventListener(FlexEvent.ADD, onAdded);
+            _grid = null;
+            _header = null;
+            _aSalesEmployee = null;
+            noEnterFramesRemaining = NaN;
+        }
+
+        [Test(async, timeout=2500)]
+        public function test_sorting_doesnt_throw_fatal():void
+        {
+            //given
+            _grid.height = 50; //exact value is unimportant; can be anything that allows for vertical scroll bars
+
+            //when
+            UIImpersonator.addElement(_grid);
+
+            //then wait a few frames
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, onGridAddedToStage, 800);
+        }
+
+        private function onGridAddedToStage(event:Event, passThroughData:Object):void
+        {
+            //when - expanding the two folders to enable scrolling
+            _grid.expandAll();
+
+            //then - wait a few more frames
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, onGridDrawn, 800);
+        }
+
+        private function onGridDrawn(event:Event, passThroughData:Object):void
+        {
+            //given
+            assertTrue(_grid.maxVerticalScrollPosition > 0);
+
+            //when - scrolling to the "Sales" folder
+            _grid.firstVisibleItem = (_grid.dataProvider as IHierarchicalCollectionView).getParentItem(_aSalesEmployee);
+
+            //then - wait a few more frames
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, onGridSetupComplete, 800);
+        }
+
+        private static function onGridSetupComplete(event:Event, passThroughData:Object):void
+        {
+            //given
+            assertNotNull(_header);
+            assertTrue(_grid.firstVisibleItem.hasOwnProperty("GroupLabel") && _grid.firstVisibleItem["GroupLabel"] == DEPARTMENT_SALES);
+
+            //when - clicking on the column header to sort
+            _header.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, 5, 5));
+            _header.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP, true, false, 5, 5));
+
+            //then - if we get here it means no error has been thrown
+            assertTrue(true);
+        }
+
+        private static function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesRemaining)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+
+        private static function onAdded(event:Event):void
+        {
+            if(event.target is AdvancedDataGridHeaderRenderer)
+                _header = AdvancedDataGridHeaderRenderer(event.target);
+        }
+
+        private static function createEmployees():ArrayCollection
+        {
+            var result:ArrayCollection = new ArrayCollection();
+            for (var i:int = 0; i < NO_ITEMS_PER_GRID_HEIGHT - 1; i++)
+            {
+                result.addItem(createEmployee("Emp-" + DEPARTMENT_DEVELOPMENT + "-" + i, DEPARTMENT_DEVELOPMENT));
+            }
+
+            for (i = 0; i < NO_ITEMS_PER_GRID_HEIGHT - 1; i++)
+            {
+                result.addItem(createEmployee("Emp-" + DEPARTMENT_SALES + "-" + i, DEPARTMENT_SALES));
+            }
+
+            _aSalesEmployee = result.getItemAt(result.length - 1) as EmployeeVO;
+
+            return result;
+        }
+
+        private static function createEmployee(name:String, department:String):EmployeeVO
+        {
+            return new EmployeeVO(name, department);
+        }
+
+        private static function createGroupingCollection(source:ArrayCollection):GroupingCollection2
+        {
+            var collection:GroupingCollection2 = new GroupingCollection2();
+            var grouping:Grouping = new Grouping();
+            grouping.fields = [new GroupingField("department")];
+            collection.grouping = grouping;
+
+            collection.source = source;
+            collection.refresh();
+
+            return collection;
+        }
+
+        private static function createNameColumn():AdvancedDataGridColumn
+        {
+            var nameColumn:AdvancedDataGridColumn = new AdvancedDataGridColumn("nameColumn");
+            nameColumn.dataField = "name";
+            return nameColumn;
+        }
+    }
+}
+
+class EmployeeVO
+{
+    public var name:String;
+    public var department:String;
+
+    public function EmployeeVO(name:String, department:String)
+    {
+        this.name = name;
+        this.department = department;
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/airframework/src/mx/managers/NativeDragManagerImpl.as b/frameworks/projects/airframework/src/mx/managers/NativeDragManagerImpl.as
index 63ea9f2..5e582a0 100644
--- a/frameworks/projects/airframework/src/mx/managers/NativeDragManagerImpl.as
+++ b/frameworks/projects/airframework/src/mx/managers/NativeDragManagerImpl.as
@@ -390,7 +390,7 @@
     {
         if (removeImage)
             _dragImage.removeEventListener(FlexEvent.UPDATE_COMPLETE, initiateDrag);
-        var dragBitmap:BitmapData     
+        var dragBitmap:BitmapData;
         if (_dragImage.width && _dragImage.height)
             dragBitmap = new BitmapData(_dragImage.width, _dragImage.height, true, 0x000000);
         else
diff --git a/frameworks/projects/apache/src/org/apache/flex/collections/VectorCollection.as b/frameworks/projects/apache/src/org/apache/flex/collections/VectorCollection.as
index b3e313b..cdf0dae 100644
--- a/frameworks/projects/apache/src/org/apache/flex/collections/VectorCollection.as
+++ b/frameworks/projects/apache/src/org/apache/flex/collections/VectorCollection.as
@@ -35,7 +35,7 @@
 /**

  *  The VectorCollection class is a wrapper class that exposes a Vector as a collection 

  *  that can be accessed and manipulated using the methods and properties of the 

- *  ICollectionView or IList interfaces. Operations on a ArrayCollection instance modify 

+ *  ICollectionView or IList interfaces. Operations on a VectorCollection instance modify 

  *  the data source; for example, if you use the removeItemAt() method on  

  *  VectorCollection, you remove the item from the underlying Vector.

  */

diff --git a/frameworks/projects/apache/src/org/apache/flex/formatters/PostCodeFormatter.as b/frameworks/projects/apache/src/org/apache/flex/formatters/PostCodeFormatter.as
index 9543d89..22bd8c6 100644
--- a/frameworks/projects/apache/src/org/apache/flex/formatters/PostCodeFormatter.as
+++ b/frameworks/projects/apache/src/org/apache/flex/formatters/PostCodeFormatter.as
@@ -234,8 +234,8 @@
         // Check and add missing (or convert) padding characters

         for each (var format:String in formats)

         {

-            var condensedPostcode:String = condensedFormat(postCode);

-            var condensedFormat:String = condensedFormat(format);

+            var condensedPostcode:String = this.condensedFormat(postCode);

+            var condensedFormat:String = this.condensedFormat(format);

             var char:String;

             var length:int = format.length;

             var condensedErrors:Array;

diff --git a/frameworks/projects/automation_agent/src/mx/automation/AutomationClass.as b/frameworks/projects/automation_agent/src/mx/automation/AutomationClass.as
index c70002f..03496aa 100644
--- a/frameworks/projects/automation_agent/src/mx/automation/AutomationClass.as
+++ b/frameworks/projects/automation_agent/src/mx/automation/AutomationClass.as
@@ -303,7 +303,7 @@
 	 */
 	public function addEvent(m:IAutomationEventDescriptor):void
     {
-        var hash:String = hash(m.eventClassName, m.eventType);
+        var hash:String = AutomationClass.hash(m.eventClassName, m.eventType);
                             
         _event2descriptor[hash] = m;
     }
@@ -328,7 +328,7 @@
         if (event is KeyboardEvent)
             eventType = "keyPress";
         var eventClassName:String = getClassName(event);
-        var hash:String = hash(eventClassName, eventType);
+        var hash:String = AutomationClass.hash(eventClassName, eventType);
         return hash in _event2descriptor ? _event2descriptor[hash] : null;
     }
 
diff --git a/frameworks/projects/experimental/src/spark/components/Alert.as b/frameworks/projects/experimental/src/spark/components/Alert.as
index 61e1324..c944a74 100644
--- a/frameworks/projects/experimental/src/spark/components/Alert.as
+++ b/frameworks/projects/experimental/src/spark/components/Alert.as
@@ -539,7 +539,8 @@
          *  @playerversion Flash 9
          *  @playerversion AIR 1.1
          *  @productversion Flex 3
-         */ public function get defaultButtonFlag():int {
+         */
+	public function get defaultButtonFlag():int {
             return _defaultButtonFlag;
         }
 
@@ -838,7 +839,7 @@
          */
         private function onKeyDown(e:KeyboardEvent):void {
             if (e.charCode == Keyboard.ESCAPE) {
-                removeAlert(identifyButton(_buttons[ _defaultButtonFlag ] as Button));
+                removeAlert(identifyButton(getDefaultButton()));
             }
         }
     }
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/awesome/FontAwesome.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/awesome/FontAwesome.otf
index 3ed7f8b..401ec0f 100644
--- a/frameworks/projects/flatspark/src/flatspark/assets/fonts/awesome/FontAwesome.otf
+++ b/frameworks/projects/flatspark/src/flatspark/assets/fonts/awesome/FontAwesome.otf
Binary files differ
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/ButtonIconSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/ButtonIconSkin.mxml
index f4a71fa..f8859ee 100644
--- a/frameworks/projects/flatspark/src/flatspark/skins/ButtonIconSkin.mxml
+++ b/frameworks/projects/flatspark/src/flatspark/skins/ButtonIconSkin.mxml
@@ -177,7 +177,7 @@
 		<s:Label id="iconFont" color="0xFFFFFF" color.disabled="0xE3E3E3" text="{hostComponent.iconFont}"
 				 textAlign="left" fontFamily="FontAwesome"
 				 maxDisplayedLines="1" includeInLayout="{hostComponent.iconFont != null}"
-				 horizontalCenter="0" verticalCenter="0" verticalAlign="middle">
+				 horizontalCenter="0" verticalCenter="0" verticalAlign="middle" fontWeight="normal">
 		</s:Label>
 		
 		<s:Label id="labelDisplay" color="0xFFFFFF" color.disabled="0xE3E3E3"
diff --git a/frameworks/projects/flatspark/src/flatspark/utils/AwesomeUtils.as b/frameworks/projects/flatspark/src/flatspark/utils/AwesomeUtils.as
index 87cfc06..2218cc5 100644
--- a/frameworks/projects/flatspark/src/flatspark/utils/AwesomeUtils.as
+++ b/frameworks/projects/flatspark/src/flatspark/utils/AwesomeUtils.as
@@ -1,19 +1,17 @@
 /**	
- 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.	
- */
+The MIT License (MIT)
+Copyright (c) 2016 by Dave Gandy
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 
+and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
 
 package flatspark.utils
 {
@@ -26,6 +24,10 @@
 		}
 		
 		public static const fa_500px:String = "\uf26e";
+		public static const fa_address_book:String = "\uf2b9";
+		public static const fa_address_book_o:String = "\uf2ba";
+		public static const fa_address_card:String = "\uf2bb";
+		public static const fa_address_card_o:String = "\uf2bc";
 		public static const fa_adjust:String = "\uf042";
 		public static const fa_adn:String = "\uf170";
 		public static const fa_align_center:String = "\uf037";
@@ -34,6 +36,7 @@
 		public static const fa_align_right:String = "\uf038";
 		public static const fa_amazon:String = "\uf270";
 		public static const fa_ambulance:String = "\uf0f9";
+		public static const fa_american_sign_language_interpreting:String = "\uf2a3";
 		public static const fa_anchor:String = "\uf13d";
 		public static const fa_android:String = "\uf17b";
 		public static const fa_angellist:String = "\uf209";
@@ -64,17 +67,24 @@
 		public static const fa_arrows_alt:String = "\uf0b2";
 		public static const fa_arrows_h:String = "\uf07e";
 		public static const fa_arrows_v:String = "\uf07d";
+		public static const fa_asl_interpreting:String = "\uf2a3";
+		public static const fa_assistive_listening_systems:String = "\uf2a2";
 		public static const fa_asterisk:String = "\uf069";
 		public static const fa_at:String = "\uf1fa";
+		public static const fa_audio_description:String = "\uf29e";
 		public static const fa_automobile:String = "\uf1b9";
 		public static const fa_backward:String = "\uf04a";
 		public static const fa_balance_scale:String = "\uf24e";
 		public static const fa_ban:String = "\uf05e";
+		public static const fa_bandcamp:String = "\uf2d5";
 		public static const fa_bank:String = "\uf19c";
 		public static const fa_bar_chart:String = "\uf080";
 		public static const fa_bar_chart_o:String = "\uf080";
 		public static const fa_barcode:String = "\uf02a";
 		public static const fa_bars:String = "\uf0c9";
+		public static const fa_bath:String = "\uf2cd";
+		public static const fa_bathtub:String = "\uf2cd";
+		public static const fa_battery:String = "\uf240";
 		public static const fa_battery_0:String = "\uf244";
 		public static const fa_battery_1:String = "\uf243";
 		public static const fa_battery_2:String = "\uf242";
@@ -100,6 +110,7 @@
 		public static const fa_bitbucket_square:String = "\uf172";
 		public static const fa_bitcoin:String = "\uf15a";
 		public static const fa_black_tie:String = "\uf27e";
+		public static const fa_blind:String = "\uf29d";
 		public static const fa_bluetooth:String = "\uf293";
 		public static const fa_bluetooth_b:String = "\uf294";
 		public static const fa_bold:String = "\uf032";
@@ -108,6 +119,7 @@
 		public static const fa_book:String = "\uf02d";
 		public static const fa_bookmark:String = "\uf02e";
 		public static const fa_bookmark_o:String = "\uf097";
+		public static const fa_braille:String = "\uf2a1";
 		public static const fa_briefcase:String = "\uf0b1";
 		public static const fa_btc:String = "\uf15a";
 		public static const fa_bug:String = "\uf188";
@@ -210,6 +222,8 @@
 		public static const fa_dashboard:String = "\uf0e4";
 		public static const fa_dashcube:String = "\uf210";
 		public static const fa_database:String = "\uf1c0";
+		public static const fa_deaf:String = "\uf2a4";
+		public static const fa_deafness:String = "\uf2a4";
 		public static const fa_dedent:String = "\uf03b";
 		public static const fa_delicious:String = "\uf1a5";
 		public static const fa_desktop:String = "\uf108";
@@ -220,18 +234,25 @@
 		public static const fa_dot_circle_o:String = "\uf192";
 		public static const fa_download:String = "\uf019";
 		public static const fa_dribbble:String = "\uf17d";
+		public static const fa_drivers_license:String = "\uf2c2";
+		public static const fa_drivers_license_o:String = "\uf2c3";
 		public static const fa_dropbox:String = "\uf16b";
 		public static const fa_drupal:String = "\uf1a9";
 		public static const fa_edge:String = "\uf282";
 		public static const fa_edit:String = "\uf044";
+		public static const fa_eercast:String = "\uf2da";
 		public static const fa_eject:String = "\uf052";
 		public static const fa_ellipsis_h:String = "\uf141";
 		public static const fa_ellipsis_v:String = "\uf142";
 		public static const fa_empire:String = "\uf1d1";
 		public static const fa_envelope:String = "\uf0e0";
 		public static const fa_envelope_o:String = "\uf003";
+		public static const fa_envelope_open:String = "\uf2b6";
+		public static const fa_envelope_open_o:String = "\uf2b7";
 		public static const fa_envelope_square:String = "\uf199";
+		public static const fa_envira:String = "\uf299";
 		public static const fa_eraser:String = "\uf12d";
+		public static const fa_etsy:String = "\uf2d7";
 		public static const fa_eur:String = "\uf153";
 		public static const fa_euro:String = "\uf153";
 		public static const fa_exchange:String = "\uf0ec";
@@ -245,6 +266,7 @@
 		public static const fa_eye:String = "\uf06e";
 		public static const fa_eye_slash:String = "\uf070";
 		public static const fa_eyedropper:String = "\uf1fb";
+		public static const fa_fa:String = "\uf2b4";
 		public static const fa_facebook:String = "\uf09a";
 		public static const fa_facebook_f:String = "\uf09a";
 		public static const fa_facebook_official:String = "\uf230";
@@ -279,6 +301,7 @@
 		public static const fa_fire:String = "\uf06d";
 		public static const fa_fire_extinguisher:String = "\uf134";
 		public static const fa_firefox:String = "\uf269";
+		public static const fa_first_order:String = "\uf2b0";
 		public static const fa_flag:String = "\uf024";
 		public static const fa_flag_checkered:String = "\uf11e";
 		public static const fa_flag_o:String = "\uf11d";
@@ -291,11 +314,13 @@
 		public static const fa_folder_open:String = "\uf07c";
 		public static const fa_folder_open_o:String = "\uf115";
 		public static const fa_font:String = "\uf031";
+		public static const fa_font_awesome:String = "\uf2b4";
 		public static const fa_fonticons:String = "\uf280";
 		public static const fa_fort_awesome:String = "\uf286";
 		public static const fa_forumbee:String = "\uf211";
 		public static const fa_forward:String = "\uf04e";
 		public static const fa_foursquare:String = "\uf180";
+		public static const fa_free_code_camp:String = "\uf2c5";
 		public static const fa_frown_o:String = "\uf119";
 		public static const fa_futbol_o:String = "\uf1e3";
 		public static const fa_gamepad:String = "\uf11b";
@@ -314,15 +339,21 @@
 		public static const fa_github:String = "\uf09b";
 		public static const fa_github_alt:String = "\uf113";
 		public static const fa_github_square:String = "\uf092";
+		public static const fa_gitlab:String = "\uf296";
 		public static const fa_gittip:String = "\uf184";
 		public static const fa_glass:String = "\uf000";
+		public static const fa_glide:String = "\uf2a5";
+		public static const fa_glide_g:String = "\uf2a6";
 		public static const fa_globe:String = "\uf0ac";
 		public static const fa_google:String = "\uf1a0";
 		public static const fa_google_plus:String = "\uf0d5";
+		public static const fa_google_plus_circle:String = "\uf2b3";
+		public static const fa_google_plus_official:String = "\uf2b3";
 		public static const fa_google_plus_square:String = "\uf0d4";
 		public static const fa_google_wallet:String = "\uf1ee";
 		public static const fa_graduation_cap:String = "\uf19d";
 		public static const fa_gratipay:String = "\uf184";
+		public static const fa_grav:String = "\uf2d6";
 		public static const fa_group:String = "\uf0c0";
 		public static const fa_h_square:String = "\uf0fd";
 		public static const fa_hacker_news:String = "\uf1d4";
@@ -339,6 +370,8 @@
 		public static const fa_hand_scissors_o:String = "\uf257";
 		public static const fa_hand_spock_o:String = "\uf259";
 		public static const fa_hand_stop_o:String = "\uf256";
+		public static const fa_handshake_o:String = "\uf2b5";
+		public static const fa_hard_of_hearing:String = "\uf2a4";
 		public static const fa_hashtag:String = "\uf292";
 		public static const fa_hdd_o:String = "\uf0a0";
 		public static const fa_header:String = "\uf1dc";
@@ -361,8 +394,12 @@
 		public static const fa_houzz:String = "\uf27c";
 		public static const fa_html5:String = "\uf13b";
 		public static const fa_i_cursor:String = "\uf246";
+		public static const fa_id_badge:String = "\uf2c1";
+		public static const fa_id_card:String = "\uf2c2";
+		public static const fa_id_card_o:String = "\uf2c3";
 		public static const fa_ils:String = "\uf20b";
 		public static const fa_image:String = "\uf03e";
+		public static const fa_imdb:String = "\uf2d8";
 		public static const fa_inbox:String = "\uf01c";
 		public static const fa_indent:String = "\uf03c";
 		public static const fa_industry:String = "\uf275";
@@ -400,6 +437,7 @@
 		public static const fa_link:String = "\uf0c1";
 		public static const fa_linkedin:String = "\uf0e1";
 		public static const fa_linkedin_square:String = "\uf08c";
+		public static const fa_linode:String = "\uf2b8";
 		public static const fa_linux:String = "\uf17c";
 		public static const fa_list:String = "\uf03a";
 		public static const fa_list_alt:String = "\uf022";
@@ -411,6 +449,7 @@
 		public static const fa_long_arrow_left:String = "\uf177";
 		public static const fa_long_arrow_right:String = "\uf178";
 		public static const fa_long_arrow_up:String = "\uf176";
+		public static const fa_low_vision:String = "\uf2a8";
 		public static const fa_magic:String = "\uf0d0";
 		public static const fa_magnet:String = "\uf076";
 		public static const fa_mail_forward:String = "\uf064";
@@ -431,8 +470,10 @@
 		public static const fa_meanpath:String = "\uf20c";
 		public static const fa_medium:String = "\uf23a";
 		public static const fa_medkit:String = "\uf0fa";
+		public static const fa_meetup:String = "\uf2e0";
 		public static const fa_meh_o:String = "\uf11a";
 		public static const fa_mercury:String = "\uf223";
+		public static const fa_microchip:String = "\uf2db";
 		public static const fa_microphone:String = "\uf130";
 		public static const fa_microphone_slash:String = "\uf131";
 		public static const fa_minus:String = "\uf068";
@@ -482,8 +523,9 @@
 		public static const fa_photo:String = "\uf03e";
 		public static const fa_picture_o:String = "\uf03e";
 		public static const fa_pie_chart:String = "\uf200";
-		public static const fa_pied_piper:String = "\uf1a7";
+		public static const fa_pied_piper:String = "\uf2ae";
 		public static const fa_pied_piper_alt:String = "\uf1a8";
+		public static const fa_pied_piper_pp:String = "\uf1a7";
 		public static const fa_pinterest:String = "\uf0d2";
 		public static const fa_pinterest_p:String = "\uf231";
 		public static const fa_pinterest_square:String = "\uf0d3";
@@ -496,6 +538,7 @@
 		public static const fa_plus_circle:String = "\uf055";
 		public static const fa_plus_square:String = "\uf0fe";
 		public static const fa_plus_square_o:String = "\uf196";
+		public static const fa_podcast:String = "\uf2ce";
 		public static const fa_power_off:String = "\uf011";
 		public static const fa_print:String = "\uf02f";
 		public static const fa_product_hunt:String = "\uf288";
@@ -504,10 +547,13 @@
 		public static const fa_qrcode:String = "\uf029";
 		public static const fa_question:String = "\uf128";
 		public static const fa_question_circle:String = "\uf059";
+		public static const fa_question_circle_o:String = "\uf29c";
+		public static const fa_quora:String = "\uf2c4";
 		public static const fa_quote_left:String = "\uf10d";
 		public static const fa_quote_right:String = "\uf10e";
 		public static const fa_ra:String = "\uf1d0";
 		public static const fa_random:String = "\uf074";
+		public static const fa_ravelry:String = "\uf2d9";
 		public static const fa_rebel:String = "\uf1d0";
 		public static const fa_recycle:String = "\uf1b8";
 		public static const fa_reddit:String = "\uf1a1";
@@ -521,6 +567,7 @@
 		public static const fa_repeat:String = "\uf01e";
 		public static const fa_reply:String = "\uf112";
 		public static const fa_reply_all:String = "\uf122";
+		public static const fa_resistance:String = "\uf1d0";
 		public static const fa_retweet:String = "\uf079";
 		public static const fa_rmb:String = "\uf157";
 		public static const fa_road:String = "\uf018";
@@ -533,6 +580,7 @@
 		public static const fa_rub:String = "\uf158";
 		public static const fa_ruble:String = "\uf158";
 		public static const fa_rupee:String = "\uf156";
+		public static const fa_s15:String = "\uf2cd";
 		public static const fa_safari:String = "\uf267";
 		public static const fa_save:String = "\uf0c7";
 		public static const fa_scissors:String = "\uf0c4";
@@ -557,9 +605,12 @@
 		public static const fa_shopping_bag:String = "\uf290";
 		public static const fa_shopping_basket:String = "\uf291";
 		public static const fa_shopping_cart:String = "\uf07a";
+		public static const fa_shower:String = "\uf2cc";
 		public static const fa_sign_in:String = "\uf090";
+		public static const fa_sign_language:String = "\uf2a7";
 		public static const fa_sign_out:String = "\uf08b";
 		public static const fa_signal:String = "\uf012";
+		public static const fa_signing:String = "\uf2a7";
 		public static const fa_simplybuilt:String = "\uf215";
 		public static const fa_sitemap:String = "\uf0e8";
 		public static const fa_skyatlas:String = "\uf216";
@@ -568,6 +619,10 @@
 		public static const fa_sliders:String = "\uf1de";
 		public static const fa_slideshare:String = "\uf1e7";
 		public static const fa_smile_o:String = "\uf118";
+		public static const fa_snapchat:String = "\uf2ab";
+		public static const fa_snapchat_ghost:String = "\uf2ac";
+		public static const fa_snapchat_square:String = "\uf2ad";
+		public static const fa_snowflake_o:String = "\uf2dc";
 		public static const fa_soccer_ball_o:String = "\uf1e3";
 		public static const fa_sort:String = "\uf0dc";
 		public static const fa_sort_alpha_asc:String = "\uf15d";
@@ -613,6 +668,7 @@
 		public static const fa_subway:String = "\uf239";
 		public static const fa_suitcase:String = "\uf0f2";
 		public static const fa_sun_o:String = "\uf185";
+		public static const fa_superpowers:String = "\uf2dd";
 		public static const fa_superscript:String = "\uf12b";
 		public static const fa_support:String = "\uf1cd";
 		public static const fa_table:String = "\uf0ce";
@@ -622,6 +678,7 @@
 		public static const fa_tags:String = "\uf02c";
 		public static const fa_tasks:String = "\uf0ae";
 		public static const fa_taxi:String = "\uf1ba";
+		public static const fa_telegram:String = "\uf2c6";
 		public static const fa_television:String = "\uf26c";
 		public static const fa_tencent_weibo:String = "\uf1d5";
 		public static const fa_terminal:String = "\uf120";
@@ -630,6 +687,18 @@
 		public static const fa_th:String = "\uf00a";
 		public static const fa_th_large:String = "\uf009";
 		public static const fa_th_list:String = "\uf00b";
+		public static const fa_themeisle:String = "\uf2b2";
+		public static const fa_thermometer:String = "\uf2c7";
+		public static const fa_thermometer_0:String = "\uf2cb";
+		public static const fa_thermometer_1:String = "\uf2ca";
+		public static const fa_thermometer_2:String = "\uf2c9";
+		public static const fa_thermometer_3:String = "\uf2c8";
+		public static const fa_thermometer_4:String = "\uf2c7";
+		public static const fa_thermometer_empty:String = "\uf2cb";
+		public static const fa_thermometer_full:String = "\uf2c7";
+		public static const fa_thermometer_half:String = "\uf2c9";
+		public static const fa_thermometer_quarter:String = "\uf2ca";
+		public static const fa_thermometer_three_quarters:String = "\uf2c8";
 		public static const fa_thumb_tack:String = "\uf08d";
 		public static const fa_thumbs_down:String = "\uf165";
 		public static const fa_thumbs_o_down:String = "\uf088";
@@ -639,6 +708,8 @@
 		public static const fa_times:String = "\uf00d";
 		public static const fa_times_circle:String = "\uf057";
 		public static const fa_times_circle_o:String = "\uf05c";
+		public static const fa_times_rectangle:String = "\uf2d3";
+		public static const fa_times_rectangle_o:String = "\uf2d4";
 		public static const fa_tint:String = "\uf043";
 		public static const fa_toggle_down:String = "\uf150";
 		public static const fa_toggle_left:String = "\uf191";
@@ -669,6 +740,7 @@
 		public static const fa_umbrella:String = "\uf0e9";
 		public static const fa_underline:String = "\uf0cd";
 		public static const fa_undo:String = "\uf0e2";
+		public static const fa_universal_access:String = "\uf29a";
 		public static const fa_university:String = "\uf19c";
 		public static const fa_unlink:String = "\uf127";
 		public static const fa_unlock:String = "\uf09c";
@@ -678,20 +750,28 @@
 		public static const fa_usb:String = "\uf287";
 		public static const fa_usd:String = "\uf155";
 		public static const fa_user:String = "\uf007";
+		public static const fa_user_circle:String = "\uf2bd";
+		public static const fa_user_circle_o:String = "\uf2be";
 		public static const fa_user_md:String = "\uf0f0";
+		public static const fa_user_o:String = "\uf2c0";
 		public static const fa_user_plus:String = "\uf234";
 		public static const fa_user_secret:String = "\uf21b";
 		public static const fa_user_times:String = "\uf235";
 		public static const fa_users:String = "\uf0c0";
+		public static const fa_vcard:String = "\uf2bb";
+		public static const fa_vcard_o:String = "\uf2bc";
 		public static const fa_venus:String = "\uf221";
 		public static const fa_venus_double:String = "\uf226";
 		public static const fa_venus_mars:String = "\uf228";
 		public static const fa_viacoin:String = "\uf237";
+		public static const fa_viadeo:String = "\uf2a9";
+		public static const fa_viadeo_square:String = "\uf2aa";
 		public static const fa_video_camera:String = "\uf03d";
 		public static const fa_vimeo:String = "\uf27d";
 		public static const fa_vimeo_square:String = "\uf194";
 		public static const fa_vine:String = "\uf1ca";
 		public static const fa_vk:String = "\uf189";
+		public static const fa_volume_control_phone:String = "\uf2a0";
 		public static const fa_volume_down:String = "\uf027";
 		public static const fa_volume_off:String = "\uf026";
 		public static const fa_volume_up:String = "\uf028";
@@ -701,11 +781,20 @@
 		public static const fa_weixin:String = "\uf1d7";
 		public static const fa_whatsapp:String = "\uf232";
 		public static const fa_wheelchair:String = "\uf193";
+		public static const fa_wheelchair_alt:String = "\uf29b";
 		public static const fa_wifi:String = "\uf1eb";
 		public static const fa_wikipedia_w:String = "\uf266";
+		public static const fa_window_close:String = "\uf2d3";
+		public static const fa_window_close_o:String = "\uf2d4";
+		public static const fa_window_maximize:String = "\uf2d0";
+		public static const fa_window_minimize:String = "\uf2d1";
+		public static const fa_window_restore:String = "\uf2d2";
 		public static const fa_windows:String = "\uf17a";
 		public static const fa_won:String = "\uf159";
 		public static const fa_wordpress:String = "\uf19a";
+		public static const fa_wpbeginner:String = "\uf297";
+		public static const fa_wpexplorer:String = "\uf2de";
+		public static const fa_wpforms:String = "\uf298";
 		public static const fa_wrench:String = "\uf0ad";
 		public static const fa_xing:String = "\uf168";
 		public static const fa_xing_square:String = "\uf169";
@@ -716,6 +805,7 @@
 		public static const fa_yc_square:String = "\uf1d4";
 		public static const fa_yelp:String = "\uf1e9";
 		public static const fa_yen:String = "\uf157";
+		public static const fa_yoast:String = "\uf2b1";
 		public static const fa_youtube:String = "\uf167";
 		public static const fa_youtube_play:String = "\uf16a";
 		public static const fa_youtube_square:String = "\uf166";
diff --git a/frameworks/projects/framework/manifest.xml b/frameworks/projects/framework/manifest.xml
index ce26f05..06d73e2 100644
--- a/frameworks/projects/framework/manifest.xml
+++ b/frameworks/projects/framework/manifest.xml
@@ -103,6 +103,7 @@
     <component id="Transition" class="mx.states.Transition"/>
     <component id="UIComponent" class="mx.core.UIComponent"/>
     <component id="Validator" class="mx.validators.Validator"/>
+    <component id="VectorUtil" class="mx.utils.VectorUtil"/>
     <component id="XMLListCollection" class="mx.collections.XMLListCollection"/>
     <component id="ZipCodeFormatter" class="mx.formatters.ZipCodeFormatter"/>
     <component id="ZipCodeValidator" class="mx.validators.ZipCodeValidator"/>
diff --git a/frameworks/projects/framework/src/mx/binding/Binding.as b/frameworks/projects/framework/src/mx/binding/Binding.as
index 15bef54..a8c569a 100644
--- a/frameworks/projects/framework/src/mx/binding/Binding.as
+++ b/frameworks/projects/framework/src/mx/binding/Binding.as
@@ -426,7 +426,7 @@
         catch(error:Error)
         {
 			if (error is ItemPendingError) {
-	            error.addResponder(new EvalBindingResponder(this, object));
+	            (error as ItemPendingError).addResponder(new EvalBindingResponder(this, object));
 	            if (BindingManager.debugDestinationStrings[destString])
 	            {
 	                trace("Binding: destString = " + destString + ", error = " + error);
diff --git a/frameworks/projects/framework/src/mx/collections/ArrayList.as b/frameworks/projects/framework/src/mx/collections/ArrayList.as
index c2f1a1b..2a89718 100644
--- a/frameworks/projects/framework/src/mx/collections/ArrayList.as
+++ b/frameworks/projects/framework/src/mx/collections/ArrayList.as
@@ -22,7 +22,6 @@
  
 import flash.events.EventDispatcher;
 import flash.events.IEventDispatcher;
-import flash.system.ApplicationDomain;
 import flash.utils.IDataInput;
 import flash.utils.IDataOutput;
 import flash.utils.IExternalizable;
@@ -621,8 +620,7 @@
                                  oldValue:Object = null, 
                                  newValue:Object = null):void
     {
-        var event:PropertyChangeEvent =
-            new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
+        var event:PropertyChangeEvent = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
         
         event.kind = PropertyChangeEventKind.UPDATE;
         event.source = item;
@@ -660,7 +658,7 @@
     }
     
     /**
-     *  Ensures that only the source property is seralized.
+     *  Ensures that only the source property is serialized.
      *  @private
      */
     public function readExternal(input:IDataInput):void
@@ -749,8 +747,7 @@
         {
             if (hasEventListener(CollectionEvent.COLLECTION_CHANGE))
             {
-                var event:CollectionEvent =
-                    new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+                var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
                 event.kind = kind;
 				if(kind != CollectionEventKind.RESET && kind != CollectionEventKind.REFRESH)
 				    event.items.push(item);
@@ -762,8 +759,7 @@
             if (hasEventListener(PropertyChangeEvent.PROPERTY_CHANGE) && 
                (kind == CollectionEventKind.ADD || kind == CollectionEventKind.REMOVE))
             {
-                var objEvent:PropertyChangeEvent =
-                    new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
+                var objEvent:PropertyChangeEvent = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
                 objEvent.property = location;
                 if (kind == CollectionEventKind.ADD)
                     objEvent.newValue = item;
@@ -815,9 +811,7 @@
     {
         if (item && (item is IEventDispatcher))
         {
-            IEventDispatcher(item).addEventListener(
-                                        PropertyChangeEvent.PROPERTY_CHANGE, 
-                                        itemUpdateHandler, false, 0, true);
+            IEventDispatcher(item).addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, itemUpdateHandler, false, 0, true);
         }
     }
     
@@ -838,12 +832,8 @@
     {
         if (item && item is IEventDispatcher)
         {
-            IEventDispatcher(item).removeEventListener(
-                                        PropertyChangeEvent.PROPERTY_CHANGE, 
-                                        itemUpdateHandler);    
+            IEventDispatcher(item).removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, itemUpdateHandler);
         }
     }
-    
 }
-
 }
diff --git a/frameworks/projects/framework/src/mx/collections/ComplexSortField.as b/frameworks/projects/framework/src/mx/collections/ComplexSortField.as
index eb29649..f651503 100644
--- a/frameworks/projects/framework/src/mx/collections/ComplexSortField.as
+++ b/frameworks/projects/framework/src/mx/collections/ComplexSortField.as
@@ -20,6 +20,8 @@
 package mx.collections {
     import mx.utils.ObjectUtil;
 
+    [Alternative(replacement="spark.collections.ComplexSortField", since="4.15")]
+
     public class ComplexSortField extends SortField implements IComplexSortField
     {
         private var _nameParts:Array;
diff --git a/frameworks/projects/framework/src/mx/collections/CursorBookmark.as b/frameworks/projects/framework/src/mx/collections/CursorBookmark.as
index f14681e..920150b 100644
--- a/frameworks/projects/framework/src/mx/collections/CursorBookmark.as
+++ b/frameworks/projects/framework/src/mx/collections/CursorBookmark.as
@@ -144,13 +144,12 @@
     //--------------------------------------------------------------------------
     
     /**
-     *  Gets the approximate index of the item represented by this bookmark
-     *  in its view. If the item has been paged out, this method could throw an 
-     *  ItemPendingError.
-     *  
-     *  @return The index of the item. If the item is not in the current view, this method returns
-     *  -1. This method also returns -1 if index-based location is not possible.
-     *  
+     *  Classes that extend CursorBookmark override this method to
+     *  return the approximate index of the item represented by this
+     *  bookmark in its view.
+     *
+     *  @return -1
+     *
      *  @langversion 3.0
      *  @playerversion Flash 9
      *  @playerversion AIR 1.1
diff --git a/frameworks/projects/framework/src/mx/collections/IViewCursor.as b/frameworks/projects/framework/src/mx/collections/IViewCursor.as
index 7bae4a4..9bdf61c 100644
--- a/frameworks/projects/framework/src/mx/collections/IViewCursor.as
+++ b/frameworks/projects/framework/src/mx/collections/IViewCursor.as
@@ -166,7 +166,7 @@
     /**
      *  Finds an item with the specified properties within the collection
      *  and positions the cursor to that item.
-     *  If the item can not be found, the cursor location does not change.
+     *  If the item cannot be found, the cursor location does not change.
      *
      *  <p>The <code>findAny()</code> method can only be called on sorted views;
      *  if the view isn't sorted, a <code>CursorError</code> is thrown.</p>
@@ -209,7 +209,7 @@
     /**
      *  Finds the first item with the specified properties within the collection
      *  and positions the cursor to that item.
-     *  If the item can not be found, no cursor location does not change.
+     *  If the item cannot be found, no cursor location does not change.
      *
      *  <p>The <code>findFirst()</code> method can only be called on sorted views;
      *  if the view isn't sorted, a <code>CursorError</code> is thrown.</p>
@@ -227,9 +227,9 @@
      *  performed, an ItemPendingError is thrown.</p>
      *
      *  @param values The search criteria. The values in the Object must be configured as name-value pairs,
-     *  as in an associative array (or be the actual object to search for). The values of the names specified must match properties
-     *  specified in the sort. For example, if properties <code>x</code>, <code>y</code>, and
-     *  <code>z</code> are in the current sort, the values specified should be
+     *  as in an associative array (or be the actual object to search for). The values of the names
+     *  specified must match properties specified in the sort. For example, if properties <code>x</code>,
+     *  <code>y</code>, and <code>z</code> are in the current sort, the values specified should be
      *  <code>{x: <i>x-value</i>, y: <i>y-value</i>, z: <i>z-value</i>}</code>.
      *
      *  @return When all of the data is local this method returns
@@ -250,7 +250,7 @@
     /**
      *  Finds the last item with the specified properties within the collection
      *  and positions the cursor on that item.
-     *  If the item can not be found, the cursor location does not chanage.
+     *  If the item cannot be found, the cursor location does not chanage.
      *
      *  <p>The <code>findLast()</code> method can only be called on sorted views;
      *  if the view isn't sorted, a <code>CursorError</code> is thrown.</p>
@@ -268,9 +268,9 @@
      *  performed, an ItemPendingError is thrown.</p>
      *
      *  @param values The search criteria. The values in the Object must be configured as name-value pairs,
-     *  as in an associative array (or be the actual object to search for). The values of the names specified must match properties
-     *  specified in the sort. For example, if properties <code>x</code>, <code>y</code>, and
-     *  <code>z</code> are in the current sort, the values specified should be
+     *  as in an associative array (or be the actual object to search for). The values of the names
+     *  specified must match properties specified in the sort. For example, if properties <code>x</code>,
+     *  <code>y</code>, and <code>z</code> are in the current sort, the values specified should be
      *  <code>{x: <i>x-value</i>, y: <i>y-value</i>, z: <i>z-value</i>}</code>.
      *
      *  @return When all of the data is local this method returns
diff --git a/frameworks/projects/framework/src/mx/collections/ListCollectionView.as b/frameworks/projects/framework/src/mx/collections/ListCollectionView.as
index 301796b..f03556f 100644
--- a/frameworks/projects/framework/src/mx/collections/ListCollectionView.as
+++ b/frameworks/projects/framework/src/mx/collections/ListCollectionView.as
@@ -89,8 +89,7 @@
  *  @playerversion AIR 1.1
  *  @productversion Flex 3
  */
-public class ListCollectionView extends Proxy
-       implements ICollectionView, IList, IMXMLObject
+public class ListCollectionView extends Proxy implements ICollectionView, IList, IMXMLObject
 {
     include "../core/Version.as";
 
@@ -290,8 +289,7 @@
             var newHasItems:Boolean;
             if (_list)
             {
-                _list.removeEventListener(CollectionEvent.COLLECTION_CHANGE,
-                                          listChangeHandler);
+                _list.removeEventListener(CollectionEvent.COLLECTION_CHANGE, listChangeHandler);
                 oldHasItems = _list.length > 0;
             }
 
@@ -300,8 +298,7 @@
             if (_list)
             {
                 // weak listeners to collections and dataproviders
-                _list.addEventListener(CollectionEvent.COLLECTION_CHANGE,
-                                       listChangeHandler, false, 0, true);
+                _list.addEventListener(CollectionEvent.COLLECTION_CHANGE, listChangeHandler, false, 0, true);
                 newHasItems = _list.length > 0;
             }
 
@@ -1448,7 +1445,7 @@
                 {
                     item = updateInfo.target;
                     //if the target != source that means the update
-                    //happened to some subprop of the item in the collection
+                    //happened to some sub-property of the item in the collection.
                     //if we have a custom comparator this will affect
                     //the sort so for now say we should move but
                     //maybe we could optimize further
@@ -1490,20 +1487,22 @@
                 }
                 else
                 {
+                    var oldOrNewValueSpecified:Boolean = updateInfo.oldValue != null || updateInfo.newValue != null;
+                    var objectReplacedInCollection:Boolean = updateInfo.property == null && oldOrNewValueSpecified;
+                    var somethingUnknownAboutTheObjectChanged:Boolean = updateInfo.property == null && !oldOrNewValueSpecified;
                     updateEntry = {item: item, move: defaultMove, events: [updateInfo],
-                        entireObjectChanged: updateInfo.property == null, oldItem: updateInfo.property == null ? updateInfo.oldValue : null};
+                        undefinedChange:somethingUnknownAboutTheObjectChanged,
+                        objectReplacedWithAnother: objectReplacedInCollection, oldItem: updateInfo.oldValue};
                     updatedItems.push(updateEntry);
                 }
 
-                //if we've already set replace don't unset it
-                //if there's a filterFunction need to go through replace
-                //if there's no property specified for the sort we'll need
-                //to assume we have to replace
-                //if there is a property see if it affects the sort
-                updateEntry.move =
-                    updateEntry.move
+                //if we've already set move don't unset it
+                //if there's a filterFunction need to go through move
+                //if the property affects the sort, we'll need to move
+                updateEntry.move = updateEntry.move
                     || filterFunction != null
-                    || updateEntry.entireObjectChanged
+                    || updateEntry.objectReplacedWithAnother
+                    || updateEntry.undefinedChange
                     || (sort && sort.propertyAffectsSort(String(updateInfo.property)));
             }
 
@@ -1515,11 +1514,11 @@
                 updateEntry = updatedItems[i];
                 if (updateEntry.move)
                 {
-                    if(updateEntry.entireObjectChanged)
+                    if(updateEntry.objectReplacedWithAnother)
                     {
                         removeItemsFromView([updateEntry.oldItem], -1, true);
                     }
-                    moveItemInView(updateEntry.item, updateEntry.item, eventItems);
+                    moveItemInView(updateEntry.item, updateEntry.item != null, eventItems);
                 }
                 else
                 {
@@ -1529,7 +1528,7 @@
 
 			// now go through the updated items and add all events for all 
 			// properties that changed in that item (except for those items
-			// we moved
+			// we moved)
             var temp:Array = [];
             for (var ctr:int = 0; ctr < eventItems.length; ctr++)
                 for (var ctr1:int = 0; ctr1 < updatedItems.length; ctr1++)
@@ -1542,9 +1541,7 @@
 
         if (eventItems.length > 0)
         {
-            
-            var updateEvent:CollectionEvent =
-                new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+            var updateEvent:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
             updateEvent.kind = CollectionEventKind.UPDATE;
             updateEvent.items = eventItems;
             dispatchEvent(updateEvent);
@@ -1654,8 +1651,7 @@
         pendingUpdates = null;
         if (dispatch)
         {
-            var refreshEvent:CollectionEvent =
-                new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+            var refreshEvent:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
             refreshEvent.kind = CollectionEventKind.REFRESH;
             dispatchEvent(refreshEvent);
         }
@@ -1696,8 +1692,7 @@
 
             if (dispatch)
             {
-                var event:CollectionEvent =
-                    new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+                var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
                 event.items.push(item);
                 if (updateEventItems && addLocation == removeLocation && addLocation > -1)
                 {
@@ -1788,8 +1783,7 @@
         }
         if (dispatch && removedItems.length > 0)
         {
-            var event:CollectionEvent =
-                new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+            var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
             event.kind = CollectionEventKind.REMOVE;
             event.location = (!localIndex || removedItems.length == 1)
                 ? removeLocation
@@ -1829,8 +1823,7 @@
         }
         else
         {
-            var event:CollectionEvent =
-                new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+            var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
             event.kind = CollectionEventKind.REPLACE;
             event.location = location;
             event.items = changeEvents;
@@ -1847,8 +1840,7 @@
         internalRefresh(false);
         if (dispatchResetEvent)
         {
-            var event:CollectionEvent =
-                new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+            var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
             event.kind = CollectionEventKind.RESET;
             dispatchEvent(event);
         }
@@ -1902,7 +1894,6 @@
 
 }
 
-import flash.events.Event;
 import flash.events.EventDispatcher;
 
 import mx.collections.*;
@@ -2224,7 +2215,7 @@
      *  @playerversion AIR 1.1
      *  @productversion Flex 3
      */
-     public function findFirst(values:Object):Boolean
+    public function findFirst(values:Object):Boolean
     {
         checkValid();
         var lcView:ListCollectionView = ListCollectionView(view);
@@ -2751,12 +2742,14 @@
     }
 
     /**
-     * Get the approximate index of the item represented by this bookmark
-     * in its view.  If the item has been paged out this may throw an
-     * ItemPendingError.  If the item is not in the current view -1 will be
-     * returned.  This method may also return -1 if index-based location is not
-     * possible.
-     *  
+     *  Gets the approximate index of the item represented by this bookmark
+     *  in its view. If the item has been paged out, this method could throw an
+     *  ItemPendingError.
+     *
+     *  @return The index of the item. If the item is not in the current view,
+     *  this method returns -1. This method also returns -1 if index-based location
+     *  retrieval is not possible.
+     *
      *  @langversion 3.0
      *  @playerversion Flash 9
      *  @playerversion AIR 1.1
diff --git a/frameworks/projects/framework/src/mx/collections/ModifiedCollectionView.as b/frameworks/projects/framework/src/mx/collections/ModifiedCollectionView.as
index c8d98de..d6bc2c8 100644
--- a/frameworks/projects/framework/src/mx/collections/ModifiedCollectionView.as
+++ b/frameworks/projects/framework/src/mx/collections/ModifiedCollectionView.as
@@ -1647,18 +1647,20 @@
         this.internalIndex = internalIndex;
     }
 
-    /**
-     * Get the approximate index of the item represented by this bookmark
-     * in its view.  If the item has been paged out this may throw an
-     * ItemPendingError.  If the item is not in the current view -1 will be
-     * returned.  This method may also return -1 if index-based location is not
-     * possible.
-     *  
-     *  @langversion 3.0
-     *  @playerversion Flash 9
-     *  @playerversion AIR 1.1
-     *  @productversion Flex 3
-     */
+	/**
+	 *  Gets the approximate index of the item represented by this bookmark
+	 *  in its view. If the item has been paged out, this method could throw an
+	 *  ItemPendingError.
+	 *
+	 *  @return The index of the item. If the item is not in the current view,
+	 *  this method returns -1. This method also returns -1 if index-based location
+	 *  retrieval is not possible.
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
     override public function getViewIndex():int
     {
         return view.getBookmarkIndex(this);
diff --git a/frameworks/projects/framework/src/mx/collections/Sort.as b/frameworks/projects/framework/src/mx/collections/Sort.as
index 2859f48..38acab8 100644
--- a/frameworks/projects/framework/src/mx/collections/Sort.as
+++ b/frameworks/projects/framework/src/mx/collections/Sort.as
@@ -95,6 +95,11 @@
  *  sorting for strings.  For this type of sorting please see the 
  *  <code>spark.collections.Sort</code> and 
  *  <code>spark.collections.SortField</code> classes.</p>
+ *
+ *  Note: to prevent problems like
+ *  <a href="https://issues.apache.org/jira/browse/FLEX-34853">FLEX-34853</a>
+ *  it is recommended to use SortField
+ *  instances as immutable objects (by not changing their state).
  * 
  *  @mxml
  *
@@ -568,7 +573,9 @@
      */
     public function propertyAffectsSort(property:String):Boolean
     {
-        if (usingCustomCompareFunction || !fields) return true;
+        if (usingCustomCompareFunction || !fields)
+            return true;
+
         for (var i:int = 0; i < fields.length; i++)
         {
             var field:ISortField = fields[i];
diff --git a/frameworks/projects/framework/src/mx/collections/SortField.as b/frameworks/projects/framework/src/mx/collections/SortField.as
index a465656..824d98d 100644
--- a/frameworks/projects/framework/src/mx/collections/SortField.as
+++ b/frameworks/projects/framework/src/mx/collections/SortField.as
@@ -72,6 +72,11 @@
  *  <code>spark.collections.Sort</code> and
  *  <code>spark.collections.SortField</code> classes.</p>
  *
+ *  Note: to prevent problems like
+ *  <a href="https://issues.apache.org/jira/browse/FLEX-34853">FLEX-34853</a>
+ *  it is recommended to use SortField
+ *  instances as immutable objects (by not changing their state).
+ *
  *  @mxml
  *
  *  <p>The <code>&lt;mx:SortField&gt;</code> tag has the following attributes:</p>
diff --git a/frameworks/projects/framework/src/mx/core/CrossDomainRSLItem.as b/frameworks/projects/framework/src/mx/core/CrossDomainRSLItem.as
index fb8086c..a0b69b8 100644
--- a/frameworks/projects/framework/src/mx/core/CrossDomainRSLItem.as
+++ b/frameworks/projects/framework/src/mx/core/CrossDomainRSLItem.as
@@ -318,7 +318,7 @@
                 // no failover to load, all the rsls have failed to load
                 // report an error.
                  // B Feature: externalize error message
-                var hasFailover:Boolean = hasFailover();
+                var hasFailover:Boolean = this.hasFailover();
                 var rslError:ErrorEvent = new ErrorEvent(RSLEvent.RSL_ERROR);
                 rslError.text = "Flex Error #1001: Digest mismatch with RSL " +
                                 urlRequest.url + 
diff --git a/frameworks/projects/framework/src/mx/core/FlexVersion.as b/frameworks/projects/framework/src/mx/core/FlexVersion.as
index bce991b..08650af 100644
--- a/frameworks/projects/framework/src/mx/core/FlexVersion.as
+++ b/frameworks/projects/framework/src/mx/core/FlexVersion.as
@@ -56,7 +56,21 @@
      *  @playerversion AIR 1.1
      *  @productversion Flex 3
      */
-    public static const CURRENT_VERSION:uint = 0x040F0000;
+    public static const CURRENT_VERSION:uint = 0x04100000;
+	
+		/** 
+	 *  The <code>compatibilityVersion</code> value of Flex 4.16,
+	 *  encoded numerically as a <code>uint</code>.
+	 *  Code can compare this constant against
+	 *  the <code>compatibilityVersion</code>
+	 *  to implement version-specific behavior.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 11
+	 *  @playerversion AIR 3
+	 *  @productversion Apache Flex 4.16
+	 */
+	public static const VERSION_4_16:uint = 0x04100000;
 	
 	/** 
 	 *  The <code>compatibilityVersion</code> value of Flex 4.15,
@@ -68,7 +82,7 @@
 	 *  @langversion 3.0
 	 *  @playerversion Flash 11
 	 *  @playerversion AIR 3
-	 *  @productversion Apache Flex 4.14
+	 *  @productversion Apache Flex 4.15
 	 */
 	public static const VERSION_4_15:uint = 0x040F0000;
 	
diff --git a/frameworks/projects/framework/src/mx/formatters/DateFormatter.as b/frameworks/projects/framework/src/mx/formatters/DateFormatter.as
index 6fba2d1..bbfd5fe 100644
--- a/frameworks/projects/framework/src/mx/formatters/DateFormatter.as
+++ b/frameworks/projects/framework/src/mx/formatters/DateFormatter.as
@@ -599,7 +599,7 @@
      *          <li>O = +7</li>
      *          <li>OO = -08</li>
 	 *          <li>OOO = +4:30</li>
-	 *          <li>OOO = -08:30</li>
+	 *          <li>OOOO = -08:30</li>
      *        </ul></td>
      *    </tr>
 	 *    <tr>
diff --git a/frameworks/projects/framework/src/mx/managers/systemClasses/MarshallingSupport.as b/frameworks/projects/framework/src/mx/managers/systemClasses/MarshallingSupport.as
index 3edd95b..f3b9b80 100644
--- a/frameworks/projects/framework/src/mx/managers/systemClasses/MarshallingSupport.as
+++ b/frameworks/projects/framework/src/mx/managers/systemClasses/MarshallingSupport.as
@@ -869,7 +869,7 @@
 				{
 					for (var i:int = 0; i < n; i++)
 					{
-						var form_i:Object = isRemotePopUp(awm.forms[i]) ? awm.forms[i].window : awm.forms[i];
+						var form_i:Object = MarshallingSupport.isRemotePopUp(awm.forms[i]) ? awm.forms[i].window : awm.forms[i];
 						if (form_i == p)
 						{
 							var j:int = 0;
@@ -904,7 +904,7 @@
 							for (j = 0; j < n; j++)
 							{
 								var f:DisplayObject;
-								var isRemotePopUp:Boolean = isRemotePopUp(awm.forms[j]);
+								var isRemotePopUp:Boolean = MarshallingSupport.isRemotePopUp(awm.forms[j]);
 								if (isRemotePopUp)
 								{
 									if (awm.forms[j].window is String)
diff --git a/frameworks/projects/framework/src/mx/resources/ResourceManagerImpl.as b/frameworks/projects/framework/src/mx/resources/ResourceManagerImpl.as
index 9b56bee..a92a77c 100644
--- a/frameworks/projects/framework/src/mx/resources/ResourceManagerImpl.as
+++ b/frameworks/projects/framework/src/mx/resources/ResourceManagerImpl.as
@@ -530,7 +530,7 @@
 
             if (updateFlag)
                 update();
-        }
+        };
         moduleInfo.addEventListener(ModuleEvent.READY, readyHandler,
                                     false, 0, true);
 
@@ -554,7 +554,7 @@
             {
                 throw new Error(message);
             }
-        }
+        };
         moduleInfo.addEventListener(ModuleEvent.ERROR, errorHandler,
                                     false, 0, true);
 
@@ -576,7 +576,7 @@
 
             // Start loading the module.
             moduleInfo.load(applicationDomain, securityDomain);
-        }
+        };
         timer.addEventListener(TimerEvent.TIMER, timerHandler,
                                false, 0, true);
         timer.start();
@@ -927,8 +927,7 @@
                               parameters:Array = null,
                               locale:String = null):String
     {
-        var resourceBundle:IResourceBundle =
-            findBundle(bundleName, resourceName, locale);
+        var resourceBundle:IResourceBundle = findBundle(bundleName, resourceName, locale);
         if (!resourceBundle)
             return null;
 
@@ -1252,7 +1251,7 @@
     /**
      *  @private
      */
-    public var moduleInfo:IModuleInfo
+    public var moduleInfo:IModuleInfo;
     
     //----------------------------------
     //  readyHandler
diff --git a/frameworks/projects/framework/src/mx/utils/ArrayUtil.as b/frameworks/projects/framework/src/mx/utils/ArrayUtil.as
index c41cccf..5fd30d9 100644
--- a/frameworks/projects/framework/src/mx/utils/ArrayUtil.as
+++ b/frameworks/projects/framework/src/mx/utils/ArrayUtil.as
@@ -107,6 +107,110 @@
 
         return -1;           
     }
+
+    /**
+     *  Checks if the Array instances contain the same values
+     *  against the same indexes, even if in different orders.
+     *
+     *  @param a The first Array instance.
+     *  @param b The second Array instance.
+     *  @param strictEqualityCheck true if we should compare the
+     *  values of the two Arrays using the strict equality
+     *  operator (===) or not (==).
+     *  @return true if the two Arrays contain the same values
+     *  (determined using the strict equality operator) associated
+     *  with the same indexes.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function arraysMatch(a:Array, b:Array, strictEqualityCheck:Boolean = true):Boolean
+    {
+        if(!a || !b)
+            return false;
+
+        if(a.length != b.length)
+            return false;
+
+        var indexesA:Array = ObjectUtil.getEnumerableProperties(a);
+
+        for (var i:int = 0; i < indexesA.length; i++)
+        {
+            var index:String = indexesA[i];
+
+            if(!b.hasOwnProperty(index))
+                return false;
+
+            if(strictEqualityCheck && a[index] !== b[index])
+                return false;
+
+            if(!strictEqualityCheck && a[index] != b[index])
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     *  Checks if the Array instances contain the same values,
+     *  even if in different orders.
+     *
+     *  @param a The first Array instance.
+     *  @param b The second Array instance.
+     *  @param strictEqualityCheck true if we should compare the
+     *  values of the two Arrays using the strict equality
+     *  operator (===) or not (==).
+     *  @return true if the two Arrays contain the same values.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function arrayValuesMatch(a:Array, b:Array, strictEqualityCheck:Boolean = true):Boolean
+    {
+        if(!a || !b)
+            return false;
+
+        var valuesOfA:Array = getArrayValues(a);
+        valuesOfA.sort();
+
+        var valuesOfB:Array = getArrayValues(b);
+        valuesOfB.sort();
+
+        return arraysMatch(valuesOfA, valuesOfB, strictEqualityCheck);
+    }
+
+    /**
+     *  Used to obtain the values in an Array, whether indexed
+     *  or associative.
+     *
+     *  @param value The Array instance.
+     *  @return an indexed Array with the values found in <code>value</code>.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function getArrayValues(value:Array):Array
+    {
+        var result:Array = [];
+
+        if(!value)
+            return result;
+
+        var indexes:Array = ObjectUtil.getEnumerableProperties(value);
+
+        for each(var index:String in indexes)
+        {
+            result.push(value[index]);
+        }
+
+        return result;
+    }
 }
 
 }
diff --git a/frameworks/projects/framework/src/mx/utils/ObjectUtil.as b/frameworks/projects/framework/src/mx/utils/ObjectUtil.as
index 5934878..260d372 100644
--- a/frameworks/projects/framework/src/mx/utils/ObjectUtil.as
+++ b/frameworks/projects/framework/src/mx/utils/ObjectUtil.as
@@ -61,7 +61,7 @@
 
     /**
      *  Compares the Objects and returns an integer value 
-     *  indicating if the first item is less than greater than or equal to
+     *  indicating if the first item is less than, greater than, or equal to
      *  the second item.
      *  This method will recursively compare properties on nested objects and
      *  will return as soon as a non-zero result is found.
@@ -88,7 +88,7 @@
      *  In this case the <code>info</code> property will be turned into a string
      *  when performing the comparison.</p>
      *
-     *  @return Return 0 if a and b are null, NaN, or equal. 
+     *  @return Return 0 if a and b are equal, or both null or NaN.
      *  Return 1 if a is null or greater than b. 
      *  Return -1 if b is null or greater than a. 
      *  
@@ -1110,12 +1110,11 @@
             }
         }
 
-        propertyNames.sort(Array.CASEINSENSITIVE |
-                           (numericIndex ? Array.NUMERIC : 0));
+        propertyNames.sort(Array.CASEINSENSITIVE | (numericIndex ? Array.NUMERIC : 0));
 
         // dictionary keys can be indexed by an object reference
         // there's a possibility that two keys will have the same toString()
-        // so we don't want to remove dupes
+        // so we don't want to remove duplicates
         if (!isDict)
         {
             // for Arrays, etc., on the other hand...
@@ -1174,7 +1173,7 @@
     /**
      *  Returns <code>true</code> if the object is an instance of a dynamic class.
      *
-     *  @param obj The object.
+     *  @param object The object.
      *
      *  @return <code>true</code> if the object is an instance of a dynamic class.
      *  
@@ -1183,24 +1182,92 @@
      *  @playerversion AIR 1.1
      *  @productversion Flex 3
      */
-    public static function isDynamicObject(obj:Object):Boolean
+    public static function isDynamicObject(object:Object):Boolean
     {
         try
         {
             // this test for checking whether an object is dynamic or not is 
             // pretty hacky, but it assumes that no-one actually has a 
             // property defined called "wootHackwoot"
-            obj["wootHackwoot"];
+            object["wootHackwoot"];
         }
         catch (e:Error)
         {
-            // our object isn't from a dynamic class
+            // our object isn't an instance of a dynamic class
             return false;
         }
         return true;
     }
 
     /**
+     *  Returns all the properties defined dynamically on an object.
+     *
+     *  @param object The object to inspect.
+     *
+     *  @return an <code>Array</code> of the enumerable properties of the object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function getEnumerableProperties(object:Object):Array
+    {
+        var result:Array = [];
+
+        if(!isDynamicObject(object))
+            return result;
+
+        for (var property:Object in object)
+            result.push(property);
+
+        return result;
+    }
+
+
+    /**
+     *  Verifies if the first object is dynamic and is a subset of the second object.
+     *
+     *  @param values The values which need to be shared by <code>object</code>
+     *  @param object The object to verify against.
+     *
+     *  @return true if and only if the objects are the same, or if <code>values</code>
+     *  is dynamic and <code>object</code> shares all its properties and values.
+     *  (Even if <code>object</code> contains other properties and values, we still
+     *  consider it a match).
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function valuesAreSubsetOfObject(values:Object, object:Object):Boolean
+    {
+        if(!object && !values)
+            return true;
+
+        if(!object || !values)
+            return false;
+
+        if(object === values)
+            return true;
+
+        var enumerableProperties:Array = ObjectUtil.getEnumerableProperties(values);
+        var matches:Boolean = enumerableProperties.length > 0 || ObjectUtil.isDynamicObject(values);
+
+        for each(var property:String in enumerableProperties)
+        {
+            if (!object.hasOwnProperty(property) || object[property] != values[property])
+            {
+                matches = false;
+                break;
+            }
+        }
+
+        return matches;
+    }
+
+    /**
      *  Returns the value at the end of the property chain <code>path</code>.
      *  If the value cannot be reached due to null links on the chain,
      *  <code>undefined</code> is returned.
diff --git a/frameworks/projects/framework/src/mx/utils/TransformUtil.as b/frameworks/projects/framework/src/mx/utils/TransformUtil.as
index 0274ed2..23fdd64 100644
--- a/frameworks/projects/framework/src/mx/utils/TransformUtil.as
+++ b/frameworks/projects/framework/src/mx/utils/TransformUtil.as
@@ -100,7 +100,7 @@
                                            initLayoutFeatures:Function = null):void
     {
         var needAdvancedLayout:Boolean = (layoutFeatures ||
-                                          needAdvancedLayout(transformCenter,
+                                          TransformUtil.needAdvancedLayout(transformCenter,
                                                              scale,
                                                              rotation,
                                                              translation,
diff --git a/frameworks/projects/framework/src/mx/utils/VectorUtil.as b/frameworks/projects/framework/src/mx/utils/VectorUtil.as
new file mode 100644
index 0000000..c635746
--- /dev/null
+++ b/frameworks/projects/framework/src/mx/utils/VectorUtil.as
@@ -0,0 +1,52 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.utils {
+    public class VectorUtil {
+        /**
+         *  Given a Vector, returns the value of the first item,
+         *  or -1 if there are no items in the Vector;
+         */
+        public static function getFirstItem(v:Vector.<int>):int
+        {
+            return v && v.length ? v[0] : -1;
+        }
+
+        public static function toArrayInt(v:Vector.<int>):Array
+        {
+            return v ? VectorToArray(v) : [];
+        }
+
+        public static function toArrayObject(v:Vector.<Object>):Array
+        {
+            return v ? VectorToArray(v) : [];
+        }
+
+        private static function VectorToArray(v:Object):Array
+        {
+            //this function assumes that v is a Vector!
+            var result:Array = [];
+            for (var i:int = 0; i < v.length; i++)
+            {
+                result.push(v[i]);
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/frameworks/projects/framework/src/mx/validators/EmailValidator.as b/frameworks/projects/framework/src/mx/validators/EmailValidator.as
index 9776db3..69fd688 100644
--- a/frameworks/projects/framework/src/mx/validators/EmailValidator.as
+++ b/frameworks/projects/framework/src/mx/validators/EmailValidator.as
@@ -74,7 +74,7 @@
 	 *  @private
 	 */
 	private static const DISALLOWED_LOCALNAME_CHARS:String =
-								"()<>,;:\\\"[] `~!#$%^&*={}|/?'\t\n\r";
+								"()<>,;:\\\"[] `~!#$%^&*={}|/?\t\n\r";
 	/**
 	 *  @private
 	 */							
diff --git a/frameworks/projects/framework/src/mx/validators/Validator.as b/frameworks/projects/framework/src/mx/validators/Validator.as
index a366608..f526b5b 100644
--- a/frameworks/projects/framework/src/mx/validators/Validator.as
+++ b/frameworks/projects/framework/src/mx/validators/Validator.as
@@ -435,20 +435,30 @@
     //  required
     //----------------------------------
 
+    private var _required:Boolean = true;
+
     [Inspectable(category="General", defaultValue="true")]
-    
+
     /**
-     *  If <code>true</code>, specifies that a missing or empty 
-     *  value causes a validation error. 
-     *  
+     *  If <code>true</code>, specifies that a missing or empty
+     *  value causes a validation error.
+     *
      *  @default true
-     *  
+     *
      *  @langversion 3.0
      *  @playerversion Flash 9
      *  @playerversion AIR 1.1
      *  @productversion Flex 3
      */
-    public var required:Boolean = true;
+    public function get required():Boolean
+    {
+        return _required;
+    }
+
+    public function set required(value:Boolean):void
+    {
+        _required = value;
+    }
     
     //----------------------------------
     //  resourceManager
@@ -909,11 +919,10 @@
         {
             // We assume if value is null and required is false that
             // validation was successful.
-            var resultEvent:ValidationResultEvent = 
-                new ValidationResultEvent(ValidationResultEvent.VALID);
+            var resultEvent:ValidationResultEvent = handleResults(null);
             if (!suppressEvents && _enabled)
             {
-            	dispatchEvent(resultEvent);
+                dispatchEvent(resultEvent);
             }
             return resultEvent; 
         } 
@@ -1070,7 +1079,7 @@
     {
         var resultEvent:ValidationResultEvent;
         
-        if (errorResults.length > 0)
+        if (errorResults != null && errorResults.length > 0)
         {
             resultEvent =
                 new ValidationResultEvent(ValidationResultEvent.INVALID);
@@ -1135,6 +1144,5 @@
     {
         resourcesChanged();
     }
-}   
-
 }
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/binding/utils/BindingUtils_Tests.as b/frameworks/projects/framework/tests/mx/binding/utils/BindingUtils_Tests.as
new file mode 100644
index 0000000..20f472b
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/binding/utils/BindingUtils_Tests.as
@@ -0,0 +1,234 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.binding.utils {
+    import mx.events.PropertyChangeEvent;
+    import mx.events.PropertyChangeEventKind;
+    import mx.utils.ObjectUtil;
+
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.asserts.assertTrue;
+
+    public class BindingUtils_Tests
+    {
+        private static var noTimesAddressBindingTriggered:int;
+        private static var noTimesStreetBindingTriggered:int;
+        private static var noTimesStreetNumberBindingTriggered:int;
+        private static var address:AddressVO;
+        private static var _house:PropertyVO;
+        private static var _streetWatcher:ChangeWatcher;
+        private static var _streetNumberWatcher:ChangeWatcher;
+        private static var _addressWatcher:ChangeWatcher;
+        private static var PROPERTY_CHANGE_EVENT:PropertyChangeEvent;
+        private static var PROPERTY_CHANGE_EVENT_UPDATE:PropertyChangeEvent;
+        private static var PROPERTY_CHANGE_EVENT_UPDATE_CONVENIENCE:PropertyChangeEvent;
+
+        private static const STREET_INITIAL:String = "La Rambla";
+        private static const STREET_OTHER:String = "Champs-Elysées";
+        private static const STREET_NO_INITIAL:int = 23;
+        private static const STREET_NO_OTHER:int = 54;
+
+        [Before]
+        public function setUp():void
+        {
+            noTimesAddressBindingTriggered = 0;
+            noTimesStreetBindingTriggered = 0;
+            noTimesStreetNumberBindingTriggered = 0;
+
+            PROPERTY_CHANGE_EVENT = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
+            PROPERTY_CHANGE_EVENT_UPDATE = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE, false, false, PropertyChangeEventKind.UPDATE);
+            PROPERTY_CHANGE_EVENT_UPDATE_CONVENIENCE = PropertyChangeEvent.createUpdateEvent(null, null, null, null);
+
+            address = new AddressVO(STREET_INITIAL, STREET_NO_INITIAL);
+            _house = new PropertyVO(address, "Jim Tim");
+
+            _addressWatcher = BindingUtils.bindSetter(setAddress, _house, "address", false, false);
+            _streetWatcher = BindingUtils.bindSetter(setStreet, address, "street", false, false);
+            _streetNumberWatcher = BindingUtils.bindSetter(setStreetNumber, address, "number", false, false);
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            _addressWatcher.unwatch();
+            _streetWatcher.unwatch();
+            _streetNumberWatcher.unwatch();
+
+            PROPERTY_CHANGE_EVENT = null;
+            PROPERTY_CHANGE_EVENT_UPDATE = null;
+            PROPERTY_CHANGE_EVENT_UPDATE_CONVENIENCE = null;
+        }
+
+        [Test]
+        public function test_binding_triggered_at_binding_definition():void
+        {
+            //then
+            assertTrue(1, noTimesAddressBindingTriggered);
+            assertTrue(1, noTimesStreetBindingTriggered);
+            assertTrue(1, noTimesStreetNumberBindingTriggered);
+        }
+
+        [Test]
+        public function test_binding_triggered_at_manual_property_change():void
+        {
+            //when
+            address.street = STREET_OTHER;
+            address.number = STREET_NO_OTHER;
+
+            //then
+            assertTrue(2, noTimesStreetBindingTriggered);
+            assertTrue(2, noTimesStreetNumberBindingTriggered);
+        }
+
+        [Test]
+        public function test_binding_not_triggered_at_generic_PropertyChangeEvent_dispatch():void
+        {
+            //when
+            address.dispatchEvent(PROPERTY_CHANGE_EVENT);
+
+            //then
+            assertEquals(1, noTimesAddressBindingTriggered);
+            assertEquals(1, noTimesStreetBindingTriggered);
+            assertEquals(1, noTimesStreetNumberBindingTriggered);
+        }
+
+        [Test]
+        public function test_PropertyChangeEvents_equivalent():void
+        {
+            //when
+            var eventComparison:int = ObjectUtil.compare(PROPERTY_CHANGE_EVENT_UPDATE, PROPERTY_CHANGE_EVENT_UPDATE_CONVENIENCE);
+
+            //then
+            assertEquals(0, eventComparison);
+        }
+
+        [Test]
+        public function test_binding_not_triggered_at_PropertyChangeEvent_UPDATE_dispatch():void
+        {
+            //when
+            address.dispatchEvent(PROPERTY_CHANGE_EVENT_UPDATE);
+
+            //then
+            assertEquals(1, noTimesAddressBindingTriggered);
+            assertEquals(1, noTimesStreetBindingTriggered);
+            assertEquals(1, noTimesStreetNumberBindingTriggered);
+        }
+
+        [Test]
+        public function test_binding_not_triggered_at_PropertyChangeEvent_UPDATE_dispatch_created_with_nulls_in_convenience_method():void
+        {
+            //when
+            address.dispatchEvent(PROPERTY_CHANGE_EVENT_UPDATE_CONVENIENCE);
+
+            //then
+            assertEquals(1, noTimesAddressBindingTriggered);
+            assertEquals(1, noTimesStreetBindingTriggered);
+            assertEquals(1, noTimesStreetNumberBindingTriggered);
+        }
+
+        [Test]
+        public function test_binding_triggered_at_PropertyChangeEvent_UPDATE_dispatch_created_with_expected_values_in_convenience_method():void
+        {
+            //when
+            address.dispatchEvent(PropertyChangeEvent.createUpdateEvent(address, "street", address.street, STREET_OTHER));
+
+            //then
+            assertEquals(1, noTimesAddressBindingTriggered);
+            assertEquals(2, noTimesStreetBindingTriggered);
+            assertEquals(1, noTimesStreetNumberBindingTriggered);
+        }
+
+        [Test]
+        public function test_binding_triggered_at_PropertyChangeEvent_UPDATE_dispatch_created_with_expected_values_except_source():void
+        {
+            //when
+            address.dispatchEvent(PropertyChangeEvent.createUpdateEvent(null, "street", address.street, STREET_OTHER));
+
+            //then
+            assertEquals(1, noTimesAddressBindingTriggered);
+            assertEquals(2, noTimesStreetBindingTriggered);
+            assertEquals(1, noTimesStreetNumberBindingTriggered);
+        }
+
+        [Test]
+        public function test_binding_triggered_at_PropertyChangeEvent_UPDATE_dispatch_created_only_with_property_name():void
+        {
+            //when
+            address.dispatchEvent(PropertyChangeEvent.createUpdateEvent(null, "street", null, null));
+
+            //then
+            assertEquals(1, noTimesAddressBindingTriggered);
+            assertEquals(2, noTimesStreetBindingTriggered);
+            assertEquals(1, noTimesStreetNumberBindingTriggered);
+        }
+
+        [Test]
+        public function test_binding_triggered_at_PropertyChangeEvent_UPDATE_dispatch_created_with_expected_values():void
+        {
+            //when
+            address.dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE, false, false, PropertyChangeEventKind.UPDATE, "street", address.street, STREET_OTHER, address));
+
+            //then
+            assertEquals(1, noTimesAddressBindingTriggered);
+            assertEquals(2, noTimesStreetBindingTriggered);
+            assertEquals(1, noTimesStreetNumberBindingTriggered);
+        }
+
+        private static function setAddress(newAddress:AddressVO):void
+        {
+            noTimesAddressBindingTriggered++;
+        }
+
+        private static function setStreet(newStreet:String):void
+        {
+            noTimesStreetBindingTriggered++;
+        }
+
+        private static function setStreetNumber(newStreetNumber:int):void
+        {
+            noTimesStreetNumberBindingTriggered++;
+        }
+    }
+}
+
+[Bindable]
+class AddressVO
+{
+    public var street:String;
+    public var number:int;
+
+    public function AddressVO(street:String, number:int)
+    {
+        this.street = street;
+        this.number = number;
+    }
+}
+
+[Bindable]
+class PropertyVO
+{
+    public var address:AddressVO;
+    public var ownerName:String;
+
+    public function PropertyVO(address:AddressVO, ownerName:String)
+    {
+        this.address = address;
+        this.ownerName = ownerName;
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/collections/ArrayCollection_AddRemoveNumbers_Tests.as b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_AddRemoveNumbers_Tests.as
new file mode 100644
index 0000000..93d302a
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_AddRemoveNumbers_Tests.as
@@ -0,0 +1,174 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import org.flexunit.asserts.*;
+
+    public class ArrayCollection_AddRemoveNumbers_Tests
+	{	
+		protected var _sut:ArrayCollection;
+		
+		[Before]
+		public function setUp():void
+		{
+			_sut = new ArrayCollection();
+		}
+		
+		[After]
+		public function tearDown():void
+		{
+			_sut = null;
+		}
+		
+		[Test]
+		public function empty():void
+		{
+			//then
+			assertEquals(_sut.length, 0);
+		}
+		
+		[Test]
+		public function addNumbers():void
+		{
+			_sut.addItem(1);
+			assertEquals("Length is not one",  1, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			_sut.addItem(2);
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}
+		
+		[Test]
+		public function addDuplicate():void
+		{
+			addNumbers();
+			_sut.addItem(1);
+			assertEquals("Length is not three",  3, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+			assertEquals("Second element not correct",  1, _sut[2]);
+		}
+		
+		[Test]
+		public function removeDuplicate():void
+		{
+			addNumbers();
+			_sut.addItem(1);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Second element not correct",  1, _sut[1]);
+		}
+		
+		[Test]
+		public function removeAllNumbers():void
+		{
+			addNumbers();
+			_sut.removeAll();
+			assertEquals("Length is not zero",  0, _sut.length);
+		}
+		
+		[Test]
+		public function removeFirstNumbers():void
+		{
+			addNumbers();
+			_sut.removeItemAt(0);
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Length is not one",  1, _sut.length);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not zero",  0, _sut.length);
+		}
+		
+		[Test]
+		public function removeLastNumbers():void
+		{
+			addNumbers();
+			_sut.removeItemAt(1);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Length is not one",  1, _sut.length);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not zero",  0, _sut.length);
+		}
+		
+		[Test]
+		public function removeItemByIndex():void
+		{
+			addNumbers();
+			_sut.removeItemAt(_sut.getItemIndex(1));
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Length is not one",  1, _sut.length);
+			_sut.removeItemAt(_sut.getItemIndex(2));
+			assertEquals("Length is not zero",  0, _sut.length);
+		}
+		
+		[Test]
+		public function outOfRange():void
+		{
+			addNumbers();
+			try {
+				_sut.removeItemAt(-1);
+			}
+			catch (error:Error)
+			{
+				assertTrue("Error not range error", error is RangeError);
+			}
+			assertEquals("Length is not two",  2, _sut.length);
+			try {
+				_sut.removeItemAt(10);
+			}
+			catch (error:Error)
+			{
+				assertTrue("Error not range error", error is RangeError);
+			}
+			assertEquals("Length is not two",  2, _sut.length);
+		}
+		
+		[Test]
+		public function swapItemsTwoThenOne():void
+		{
+			addNumbers();
+			
+			var item1:Number = _sut.getItemAt(0) as Number;
+			var item2:Number = _sut.getItemAt(1) as Number;
+			
+			_sut.setItemAt(item2,0);
+			_sut.setItemAt(item1,1);
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Second element not correct",  1, _sut[1]);
+		}
+		
+		[Test]
+		public function swapItemsOneThenTwo():void
+		{
+			addNumbers();
+
+			var item1:Number = _sut.getItemAt(0) as Number;
+			var item2:Number = _sut.getItemAt(1) as Number;
+			
+			_sut.setItemAt(item1,1);
+			_sut.setItemAt(item2,0);
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Second element not correct",  1, _sut[1]);
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/collections/ArrayCollection_AddRemoveObjects_Tests.as b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_AddRemoveObjects_Tests.as
new file mode 100644
index 0000000..a6ae79d
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_AddRemoveObjects_Tests.as
@@ -0,0 +1,274 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import org.flexunit.asserts.*;
+
+    public class ArrayCollection_AddRemoveObjects_Tests
+	{	
+		private var _sut:ArrayCollection;
+		
+		protected var players:Array = [
+			{team:"TeamOne",jerseyNumber:80,lastName:"PlayerA",firstName:"Aa"},
+			{team:"TeamTwo",jerseyNumber:7, lastName:"PlayerB",firstName:"Bb"},
+			{team:"TeamOne",jerseyNumber:12, lastName:"PlayerC",firstName:"Cc"},
+			{team:"TeamOne",jerseyNumber:21,lastName:"PlayerD",firstName:"Dd"},
+			{team:"TeamThree",jerseyNumber:34, lastName:"PlayerE",firstName:"Ee"},
+			{team:"TeamOne",jerseyNumber:12, lastName:"PlayerF",firstName:"Ff"},
+			{team:"TeamTwo",jerseyNumber:7, lastName:"PlayerG",firstName:"Gg"}
+		];
+		
+		[Before]
+		public function setUp():void
+		{
+			_sut = new ArrayCollection();
+		}
+		
+		[After]
+		public function tearDown():void
+		{
+			_sut = null;
+		}
+		
+		[Test]
+		public function empty():void
+		{
+			assertEquals(_sut.length, 0);
+		}
+		
+		[Test]
+		public function addObjects():void
+		{
+			_sut = new ArrayCollection(players);
+			assertEquals("Length is not seven",  7, _sut.length);
+			assertEquals("First element not correct",  players[0], _sut[0]);
+			assertEquals("Second element not correct",  players[1], _sut[1]);
+			assertEquals("Third element not correct",  players[2], _sut[2]);
+			assertEquals("Fouth element not correct",  players[3], _sut[3]);
+			assertEquals("Fifth element not correct",  players[4], _sut[4]);
+			assertEquals("Sixth element not correct",  players[5], _sut[5]);
+			assertEquals("Seventh element not correct",  players[6], _sut[6]);
+		}
+		
+		[Test]
+		public function addDuplicate():void
+		{
+			addObjects();
+			_sut.addItem(players[0]);
+			assertEquals("Length is not eight",  8, _sut.length);
+			assertEquals("First element not correct",  players[0], _sut[0]);
+			assertEquals("Second element not correct",  players[1], _sut[1]);
+			assertEquals("Third element not correct",  players[2], _sut[2]);
+			assertEquals("Fouth element not correct",  players[3], _sut[3]);
+			assertEquals("Fifth element not correct",  players[4], _sut[4]);
+			assertEquals("Sixth element not correct",  players[5], _sut[5]);
+			assertEquals("Seventh element not correct",  players[6], _sut[6]);
+			assertEquals("Eighth element not correct",  players[0], _sut[7]);
+		}
+		
+		[Test]
+		public function removeDuplicate():void
+		{
+            //given
+			addObjects();
+            var firstPlayer:* = players[0];
+            var secondPlayer:* = players[1];
+            var thirdPlayer:* = players[2];
+            var fourthPlayer:* = players[3];
+            var fifthPlayer:* = players[4];
+            var sixthPlayer:* = players[5];
+            var seventhPlayer:* = players[6];
+
+            //when
+			_sut.addItem(players[0]);
+            _sut.removeItemAt(0);
+            //then
+			assertEquals("Length is not seven",  7, _sut.length);
+            assertEquals("First element not correct",  secondPlayer, _sut[0]);
+            assertEquals("Second element not correct",  thirdPlayer, _sut[1]);
+            assertEquals("Third element not correct",  fourthPlayer, _sut[2]);
+            assertEquals("Fourth element not correct",  fifthPlayer, _sut[3]);
+            assertEquals("Fifth element not correct",  sixthPlayer, _sut[4]);
+            assertEquals("Sixth element not correct",  seventhPlayer, _sut[5]);
+            assertEquals("Seventh element not correct",  firstPlayer, _sut[6]);
+		}
+		
+		[Test]
+		public function removeAllObjects():void
+		{
+			addObjects();
+			_sut.removeAll();
+			assertEquals("Length is not zero",  0, _sut.length);
+		}
+		
+		[Test]
+		public function removeFirstObjects():void
+		{
+            //given
+			addObjects();
+            var secondPlayer:Object = players[1];
+
+            //when
+			_sut.removeItemAt(0);
+
+            //then
+            assertEquals("First element not correct", secondPlayer, _sut[0]);
+			assertEquals("Length is not six", 6, _sut.length);
+
+            //when
+			_sut.removeItemAt(0);
+            //then
+			assertEquals("Length is not five",  5, _sut.length);
+
+            //when
+			_sut.removeItemAt(0);
+            //then
+			assertEquals("Length is not four",  4, _sut.length);
+
+            //when
+			_sut.removeItemAt(0);
+            //then
+			assertEquals("Length is not three",  3, _sut.length);
+
+            //when
+			_sut.removeItemAt(0);
+            //then
+			assertEquals("Length is not two",  2, _sut.length);
+
+            //when
+			_sut.removeItemAt(0);
+            //then
+			assertEquals("Length is not one",  1, _sut.length);
+
+            //when
+			_sut.removeItemAt(0);
+            //then
+			assertEquals("Length is not zero",  0, _sut.length);
+		}
+		
+		[Test]
+		public function removeLastNumbers():void
+		{
+			addObjects();
+			_sut.removeItemAt(6);
+			assertEquals("First element not correct",  players[0], _sut[0]);
+			assertEquals("Length is not six",  6, _sut.length);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not five",  5, _sut.length);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not four",  4, _sut.length);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not three",  3, _sut.length);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not two",  2, _sut.length);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not one",  1, _sut.length);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not zero",  0, _sut.length);
+		}
+		
+		[Test]
+		public function removeItemByIndex():void
+		{
+			//given
+			addObjects();
+            const secondPlayer:Object = players[1];
+            const thirdPlayer:Object = players[2];
+            const fourthPlayer:Object = players[3];
+
+            //when
+			_sut.removeItemAt(_sut.getItemIndex(players[0]));
+
+            //then
+            assertEquals("First element incorrect", secondPlayer, _sut[0]);
+			assertEquals("Length is not six", 6, _sut.length);
+
+            //when
+			_sut.removeItemAt(_sut.getItemIndex(thirdPlayer));
+
+            //then
+			assertEquals("First element not correct", secondPlayer, _sut[0]);
+			assertEquals("Second element not correct", fourthPlayer, _sut[1]);
+			assertEquals("Length is not four", 5, _sut.length);
+		}
+		
+		[Test]
+		public function outOfRange():void
+		{
+			addObjects();
+			try {
+				_sut.removeItemAt(-1);
+			}
+			catch (error:Error)
+			{
+				assertTrue("Error not range error", error is RangeError);
+			}
+			assertEquals("Length is not seven",  7, _sut.length);
+			try {
+				_sut.removeItemAt(10);
+			}
+			catch (error:Error)
+			{
+				assertTrue("Error not range error", error is RangeError);
+			}
+			assertEquals("Length is not seven",  7, _sut.length);
+		}
+		
+		[Test]
+		public function swapItemsTwoThenOne():void
+		{
+            //given
+			addObjects();
+			var item1:Object = _sut.getItemAt(0);
+			var item2:Object = _sut.getItemAt(1);
+            var firstPlayer:* = players[0];
+            var secondPlayer:* = players[1];
+
+            //when
+			_sut.setItemAt(item2,0);
+			_sut.setItemAt(item1,1);
+
+            //then
+			assertEquals("Length is not seven",  7, _sut.length);
+            assertEquals("First element not correct",  secondPlayer, _sut[0]);
+            assertEquals("Second element not correct",  firstPlayer, _sut[1]);
+		}
+		
+		[Test]
+		public function swapItemsOneThenTwo():void
+		{
+            //given
+			addObjects();
+			var item1:Object = _sut.getItemAt(0);
+			var item2:Object = _sut.getItemAt(1);
+            var secondPlayer:Object = players[1];
+            var firstPlayer:Object = players[0];
+
+            //when
+			_sut.setItemAt(item1,1);
+			_sut.setItemAt(item2,0);
+
+            //then
+			assertEquals("Length is not seven",  7, _sut.length);
+            assertEquals("First element not correct",  secondPlayer, _sut[0]);
+            assertEquals("Second element not correct",  firstPlayer, _sut[1]);
+
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/collections/ArrayCollection_AddRemoveStrings_Tests.as b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_AddRemoveStrings_Tests.as
new file mode 100644
index 0000000..0ae1873
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_AddRemoveStrings_Tests.as
@@ -0,0 +1,200 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import org.flexunit.asserts.*;
+
+    public class ArrayCollection_AddRemoveStrings_Tests
+	{	
+		protected var _sut:ArrayCollection;
+		
+		[Before]
+		public function setUp():void
+		{
+			_sut = new ArrayCollection();
+		}
+		
+		[After]
+		public function tearDown():void
+		{
+			_sut = null;
+		}
+		
+		[Test]
+		public function empty():void
+		{
+			assertEquals(0, _sut.length);
+		}
+		
+		[Test]
+		public function addStrings():void
+		{
+			_sut.addItem("A");
+			assertEquals("Length is not one", 1, _sut.length);
+			assertEquals("First element not correct", "A", _sut[0]);
+
+			_sut.addItem("B");
+			assertEquals("Length is not two", 2, _sut.length);
+			assertEquals("Second element not correct", "B", _sut[1]);
+
+			_sut.addItem("D");
+			assertEquals("Length is not three", 3, _sut.length);
+			assertEquals("Second element not correct", "D", _sut[2]);
+
+			_sut.addItem("C");
+			assertEquals("Length is not four", 4, _sut.length);
+			assertEquals("Second element not correct", "C", _sut[3]);
+		}
+		
+		[Test]
+		public function addDuplicate():void
+		{
+            //given
+			addStrings();
+
+            //when
+			_sut.addItem("B");
+
+            //then
+			assertEquals("Length is not five", 5, _sut.length);
+			assertEquals("First element not correct", "A", _sut[0]);
+			assertEquals("Second element not correct", "B", _sut[1]);
+			assertEquals("Second element not correct", "D", _sut[2]);
+			assertEquals("Second element not correct", "C", _sut[3]);
+			assertEquals("Second element not correct", "B", _sut[4]);
+		}
+		
+		[Test]
+		public function removeDuplicate():void
+		{
+            //given
+			addStrings();
+
+            //when
+			_sut.addItem("B");
+			_sut.removeItemAt(1);
+
+            //then
+			assertEquals("Length is not four", 4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "D", _sut[1]);
+			assertEquals("Second element not correct",  "C", _sut[2]);
+			assertEquals("Second element not correct",  "B", _sut[3]);
+		}
+		
+		[Test]
+		public function removeAllStrings():void
+		{
+			addStrings();
+			_sut.removeAll();
+			assertEquals("Length is not zero",  0, _sut.length);
+		}
+		
+		[Test]
+		public function removeFirstStrings():void
+		{
+			addStrings();
+			_sut.removeItemAt(0);
+			assertEquals("First element not correct",  "B", _sut[0]);
+			assertEquals("Length is not three",  3, _sut.length);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not two",  2, _sut.length);
+		}
+		
+		[Test]
+		public function removeLastStrings():void
+		{
+			addStrings();
+			_sut.removeItemAt(1);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Length is not three",  3, _sut.length);
+			_sut.removeItemAt(0);
+			assertEquals("Length is not two",  2, _sut.length);
+		}
+		
+		[Test]
+		public function removeItemByIndex():void
+		{
+			addStrings();
+			_sut.removeItemAt(_sut.getItemIndex("B"));
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Length is not three",  3, _sut.length);
+			_sut.removeItemAt(_sut.getItemIndex("D"));
+			assertEquals("Length is not two",  2, _sut.length);
+		}
+		
+		[Test]
+		public function outOfRange():void
+		{
+			addStrings();
+			try {
+				_sut.removeItemAt(-1);
+			}
+			catch (error:Error)
+			{
+				assertTrue("Error not range error", error is RangeError);
+			}
+			assertEquals("Length is not four", 4, _sut.length);
+			try {
+				_sut.removeItemAt(10);
+			}
+			catch (error:Error)
+			{
+				assertTrue("Error not range error", error is RangeError);
+			}
+			assertEquals("Length is not two", 4, _sut.length);
+		}
+		
+		[Test]
+		public function swapItemsTwoThenOne():void
+		{
+            //given
+			addStrings();
+			var item1:String = _sut.getItemAt(0) as String;
+			var item2:String = _sut.getItemAt(1) as String;
+
+            //when
+			_sut.setItemAt(item2, 0);
+			_sut.setItemAt(item1, 1);
+
+            //then
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "B", _sut[0]);
+			assertEquals("Second element not correct",  "A", _sut[1]);
+		}
+		
+		[Test]
+		public function swapItemsOneThenTwo():void
+		{
+            //given
+			addStrings();
+			var item1:String = _sut.getItemAt(0) as String;
+			var item2:String = _sut.getItemAt(1) as String;
+
+			//when
+			_sut.setItemAt(item1, 1);
+			_sut.setItemAt(item2, 0);
+
+            //then
+			assertEquals("Length is not four", 4, _sut.length);
+			assertEquals("First element not correct",  "B", _sut[0]);
+			assertEquals("Second element not correct",  "A", _sut[1]);
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilerAndSortNumbers_Tests.as b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilerAndSortNumbers_Tests.as
new file mode 100644
index 0000000..18ac40d
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilerAndSortNumbers_Tests.as
@@ -0,0 +1,114 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import org.flexunit.asserts.*;
+
+    public class ArrayCollection_FilerAndSortNumbers_Tests
+	{
+        private var _sut:ArrayCollection;
+		
+		[Before]
+		public function setUp():void
+		{
+			_sut = new ArrayCollection();
+		}
+		
+		[After]
+		public function tearDown():void
+		{
+			_sut = null;
+		}
+		
+		
+		protected function addNumbers():void
+		{
+			_sut.addItem(6);
+			_sut.addItem(2);
+			_sut.addItem(3);
+			_sut.addItem(1);
+			_sut.addItem(5);
+			_sut.addItem(4);
+		}
+		
+		protected function even(object:Object):Boolean
+		{
+			return Number(object) % 2 == 0;
+		}
+		
+		protected function odd(object:Object):Boolean
+		{
+			return Number(object) % 2 == 1;
+		}
+		
+		[Test]
+		public function filterAndSortCombinations():void
+		{
+			addNumbers();
+			_sut.filterFunction = even;
+			_sut.sort = new Sort();
+			_sut.refresh();
+			
+			assertEquals("Length is not three",  3, _sut.length);
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Second element not correct",  4, _sut[1]);
+			assertEquals("Third element not correct",  6, _sut[2]);
+			
+			_sut.filterFunction = odd;
+			_sut.refresh();
+			
+			assertEquals("Length is not three",  3, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  3, _sut[1]);
+			assertEquals("Third element not correct",  5, _sut[2]);
+			
+			_sut.sort = new Sort();
+			_sut.sort.fields = [new SortField(null, false, true, true)];
+			_sut.refresh();
+			
+			assertEquals("Length is not three",  3, _sut.length);
+			assertEquals("First element not correct",  5, _sut[0]);
+			assertEquals("Second element not correct",  3, _sut[1]);
+			assertEquals("Third element not correct",  1, _sut[2]);
+			
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not six",  6, _sut.length);
+			assertEquals("First element not correct",  6, _sut[0]);
+			assertEquals("Second element not correct",  5, _sut[1]);
+			assertEquals("Third element not correct",  4, _sut[2]);
+			assertEquals("Fourth element not correct",  3, _sut[3]);
+			assertEquals("Fith element not correct",  2, _sut[4]);
+			assertEquals("Six element not correct",  1, _sut[5]);
+			
+			_sut.sort = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not six",  6, _sut.length);
+			assertEquals("First element not correct",  6, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+			assertEquals("Third element not correct",  3, _sut[2]);
+			assertEquals("Fourth element not correct",  1, _sut[3]);
+			assertEquals("Fith element not correct",  5, _sut[4]);
+			assertEquals("Six element not correct",  4, _sut[5]);
+		}	
+		
+		
+	}
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilerAndSortStrings_Tests.as b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilerAndSortStrings_Tests.as
new file mode 100644
index 0000000..c4e4a2c
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilerAndSortStrings_Tests.as
@@ -0,0 +1,114 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import org.flexunit.asserts.*;
+
+    public class ArrayCollection_FilerAndSortStrings_Tests
+	{
+        private var _sut:ArrayCollection;
+		
+		[Before]
+		public function setUp():void
+		{
+			_sut = new ArrayCollection();
+		}
+		
+		[After]
+		public function tearDown():void
+		{
+			_sut = null;
+		}
+		
+		
+		protected function addNumbers():void
+		{
+			_sut.addItem(6);
+			_sut.addItem(2);
+			_sut.addItem(3);
+			_sut.addItem(1);
+			_sut.addItem(5);
+			_sut.addItem(4);
+		}
+		
+		protected function even(object:Object):Boolean
+		{
+			return Number(object) % 2 == 0;
+		}
+		
+		protected function odd(object:Object):Boolean
+		{
+			return Number(object) % 2 == 1;
+		}
+		
+		[Test]
+		public function filterAndSortCombinations():void
+		{
+			addNumbers();
+			_sut.filterFunction = even;
+			_sut.sort = new Sort();
+			_sut.refresh();
+			
+			assertEquals("Length is not three",  3, _sut.length);
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Second element not correct",  4, _sut[1]);
+			assertEquals("Third element not correct",  6, _sut[2]);
+			
+			_sut.filterFunction = odd;
+			_sut.refresh();
+			
+			assertEquals("Length is not three",  3, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  3, _sut[1]);
+			assertEquals("Third element not correct",  5, _sut[2]);
+			
+			_sut.sort = new Sort();
+			_sut.sort.fields = [new SortField(null, false, true, true)];
+			_sut.refresh();
+			
+			assertEquals("Length is not three",  3, _sut.length);
+			assertEquals("First element not correct",  5, _sut[0]);
+			assertEquals("Second element not correct",  3, _sut[1]);
+			assertEquals("Third element not correct",  1, _sut[2]);
+			
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not six",  6, _sut.length);
+			assertEquals("First element not correct",  6, _sut[0]);
+			assertEquals("Second element not correct",  5, _sut[1]);
+			assertEquals("Third element not correct",  4, _sut[2]);
+			assertEquals("Fourth element not correct",  3, _sut[3]);
+			assertEquals("Fith element not correct",  2, _sut[4]);
+			assertEquals("Six element not correct",  1, _sut[5]);
+			
+			_sut.sort = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not six",  6, _sut.length);
+			assertEquals("First element not correct",  6, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+			assertEquals("Third element not correct",  3, _sut[2]);
+			assertEquals("Fourth element not correct",  1, _sut[3]);
+			assertEquals("Fith element not correct",  5, _sut[4]);
+			assertEquals("Six element not correct",  4, _sut[5]);
+		}	
+		
+		
+	}
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilterNumbers_Tests.as b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilterNumbers_Tests.as
new file mode 100644
index 0000000..5bacfb9
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilterNumbers_Tests.as
@@ -0,0 +1,315 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import org.flexunit.asserts.*;
+
+    public class ArrayCollection_FilterNumbers_Tests
+	{
+        private var _sut:ArrayCollection;
+		
+		[Before]
+		public function setUp():void
+		{
+			_sut = new ArrayCollection();
+		}
+		
+		[After]
+		public function tearDown():void
+		{
+			_sut = null;
+		}
+		
+		protected function addNumbers():void
+		{
+			_sut.addItem(1);
+			_sut.addItem(2);
+		}
+
+		private static function allIn(object:Object):Boolean
+		{
+			return true;
+		}
+
+		private static function allOut(object:Object):Boolean
+		{
+			return false;
+		}
+
+		private static function isOne(object:Object):Boolean
+		{
+			return object == 1;
+		}
+		
+		[Test]
+		public function nullFilter():void
+		{
+			addNumbers();
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}	
+		
+		[Test]
+		public function trueFilter():void
+		{
+			addNumbers();
+			_sut.filterFunction = allIn;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}
+		
+		[Test]
+		public function falseFilter():void
+		{
+			addNumbers();
+			_sut.filterFunction = allOut;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  0, _sut.length);
+		}
+		
+		
+		[Test]
+		public function filterNoRefresh():void
+		{
+			addNumbers();
+			_sut.filterFunction = allOut;
+			
+			// Filter should not take effect
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}
+		
+		[Test]
+		public function nullFilterNoRefresh():void
+		{
+			addNumbers();
+			_sut.filterFunction = null;
+			
+			// Filter should not take effect
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}
+		
+		[Test]
+		public function filterDoubleRefresh():void
+		{
+			addNumbers();
+			_sut.filterFunction = allOut;
+			_sut.refresh();
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+			
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			// Filter should not take effect
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}
+		
+		// RTEs in Apache Flex 4.9.1
+		[Test]
+		public function filterAddAfterNullNoRefresh():void
+		{
+			addNumbers();
+			
+			_sut.filterFunction = allOut;
+			_sut.refresh();
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+			
+			_sut.filterFunction = null;
+			addNumbers();
+			
+			// Filter should be in effect and first 2 items sorted
+			// item added after are not filtered until refresh called
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+			
+			_sut.refresh();
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+			assertEquals("First element not correct",  1, _sut[2]);
+			assertEquals("Second element not correct",  2, _sut[3]);
+		}
+		
+		[Test]
+		public function filterRemoveAfterNullNoRefresh():void
+		{
+			addNumbers();
+			
+			_sut.filterFunction = allOut;
+			_sut.refresh();
+			_sut.filterFunction = null;
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+			
+			try {
+				_sut.removeItemAt(0);
+			}
+			catch (error:Error)
+			{
+				assertTrue("Error not range error", error is RangeError);
+			}
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+			
+			_sut.refresh();
+			assertEquals("Length is not two",  2, _sut.length);
+		}
+		
+		[Test]
+		public function filterIncludingDuplicates():void
+		{
+			addNumbers();
+			addNumbers();
+			
+			_sut.filterFunction = isOne;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  1, _sut[1]);
+		}
+
+        [Ignore]
+		[Test] //See FLEX-35039
+		public function swapItemsTwoThenOne_reproduces_FLEX_35039():void
+		{
+			//given
+			addNumbers();
+			_sut.filterFunction = allIn;
+			_sut.refresh();
+			
+			var item1:Number = _sut.getItemAt(0) as Number;
+			var item2:Number = _sut.getItemAt(1) as Number;
+
+            //when
+			_sut.setItemAt(item2, 0);
+			_sut.setItemAt(item1, 1);
+
+            //then
+			assertEquals("Length is not two", 2, _sut.length);
+			assertEquals("First element not correct", 2, _sut[0]);
+			assertEquals("Second element not correct", 1, _sut[1]);
+		}
+		
+		[Test]
+		public function swapItemsOneThenTwo():void
+		{
+			addNumbers();
+			_sut.filterFunction = allIn;
+			_sut.refresh();
+			
+			var item1:Number = _sut.getItemAt(0) as Number;
+			var item2:Number = _sut.getItemAt(1) as Number;
+			
+			_sut.setItemAt(item1,1);
+			_sut.setItemAt(item2,0);
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Second element not correct",  1, _sut[1]);
+		}
+		
+		[Test]
+		public function removeAllAfterFiltered():void
+		{
+			addNumbers();
+			_sut.filterFunction = allOut;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  0, _sut.length);
+			
+			_sut.removeAll();
+			
+			assertEquals("Length is not two",  0, _sut.length);
+			
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}
+		
+		[Test]
+		public function removeFilteredItem():void
+		{
+			addNumbers();
+			_sut.filterFunction = isOne;
+			_sut.refresh();
+			
+			assertEquals("Length is not one",  1, _sut.length);
+			
+			_sut.removeItemAt(_sut.getItemIndex(1));
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+			
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  1, _sut.length);
+			assertEquals("First element not correct",  2, _sut[0]);
+		}
+		
+		[Test]
+		public function removeNonFilteredItem():void
+		{
+			addNumbers();
+			_sut.filterFunction = isOne;
+			_sut.refresh();
+			
+			assertEquals("Length is not one",  1, _sut.length);
+			
+			try {
+				// not removed as filter hids it - perhaps it should be removed?
+				_sut.removeItemAt(_sut.getItemIndex(2));
+			}
+			catch (error:Error)
+			{
+				assertTrue("Error not range error", error is RangeError);
+			}
+			
+			assertEquals("Length is not one",  1, _sut.length);
+			
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("First element not correct",  2, _sut[1]);
+		}
+		
+		
+	}
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilterStrings_Tests.as b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilterStrings_Tests.as
new file mode 100644
index 0000000..f61d3ec
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_FilterStrings_Tests.as
@@ -0,0 +1,341 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import org.flexunit.asserts.*;
+
+    public class ArrayCollection_FilterStrings_Tests
+	{
+        private var _sut:ArrayCollection;
+		
+		[Before]
+		public function setUp():void
+		{
+			_sut = new ArrayCollection();
+		}
+		
+		[After]
+		public function tearDown():void
+		{
+			_sut = null;
+		}
+		
+		protected function addStrings():void
+		{
+			_sut.addItem("A");
+			_sut.addItem("B");
+			_sut.addItem("D");
+			_sut.addItem("C");
+		}
+		
+		private static function allIn(object:Object):Boolean
+		{
+			return true;
+		}
+
+		private static function allOut(object:Object):Boolean
+		{
+			return false;
+		}
+
+		private static function isA(object:Object):Boolean
+		{
+			return object == "A";
+		}
+		
+		[Test]
+		public function nullFilter():void
+		{
+			addStrings();
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("Third element not correct",  "D", _sut[2]);
+			assertEquals("Four element not correct",  "C", _sut[3]);
+		}	
+		
+		[Test]
+		public function trueFilter():void
+		{
+			addStrings();
+			_sut.filterFunction = allIn;
+			_sut.refresh();
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("Third element not correct",  "D", _sut[2]);
+			assertEquals("Four element not correct",  "C", _sut[3]);
+		}
+		
+		[Test]
+		public function falseFilter():void
+		{
+			addStrings();
+			_sut.filterFunction = allOut;
+			_sut.refresh();
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+		}
+		
+		
+		[Test]
+		public function filterNoRefresh():void
+		{
+			addStrings();
+			_sut.filterFunction = allOut;
+			
+			// Filter should not take effect
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("Third element not correct",  "D", _sut[2]);
+			assertEquals("Four element not correct",  "C", _sut[3]);
+		}
+		
+		[Test]
+		public function nullFilterNoRefresh():void
+		{
+			addStrings();
+			_sut.filterFunction = null;
+			
+			// Filter should not take effect
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("Third element not correct",  "D", _sut[2]);
+			assertEquals("Four element not correct",  "C", _sut[3]);
+		}
+		
+		[Test]
+		public function filterDoubleRefresh():void
+		{
+			addStrings();
+			_sut.filterFunction = allOut;
+			_sut.refresh();
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+			
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			// Filter should not take effect
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("Third element not correct",  "D", _sut[2]);
+			assertEquals("Four element not correct",  "C", _sut[3]);
+		}
+		
+		// RTEs in Apache Flex 4.9.1
+		[Test]
+		public function filterAddAfterNullNoRefresh():void
+		{
+			addStrings();
+			
+			_sut.filterFunction = allOut;
+			_sut.refresh();
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+			
+			_sut.filterFunction = null;
+			addStrings();
+			
+			// Filter should be in effect and first 2 items sorted
+			// item added after are not filtered until refresh called
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("Third element not correct",  "D", _sut[2]);
+			assertEquals("Four element not correct",  "C", _sut[3]);
+			
+			_sut.refresh();
+			assertEquals("Length is not eight",  8, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("Third element not correct",  "D", _sut[2]);
+			assertEquals("Four element not correct",  "C", _sut[3]);
+			assertEquals("First element not correct",  "A", _sut[4]);
+			assertEquals("Second element not correct",  "B", _sut[5]);
+			assertEquals("Third element not correct",  "D", _sut[6]);
+			assertEquals("Four element not correct",  "C", _sut[7]);
+		}
+		
+		[Test]
+		public function filterRemoveAfterNullNoRefresh():void
+		{
+			addStrings();
+			
+			_sut.filterFunction = allOut;
+			_sut.refresh();
+			_sut.filterFunction = null;
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+			
+			try {
+				_sut.removeItemAt(0);
+			}
+			catch (error:Error)
+			{
+				assertTrue("Error not range error", error is RangeError);
+			}
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+			
+			_sut.refresh();
+			assertEquals("Length is not four",  4, _sut.length);
+		}
+		
+		[Test]
+		public function filterIncludingDuplicates():void
+		{
+			addStrings();
+			addStrings();
+			
+			_sut.filterFunction = isA;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "A", _sut[1]);
+		}
+
+		[Ignore]
+		[Test] //See FLEX-35039
+		public function swapItemsTwoThenOne_reproduces_FLEX_35039():void
+		{
+			//given
+			addStrings();
+			_sut.filterFunction = allIn;
+			_sut.refresh();
+			
+			var item1:String = _sut.getItemAt(0) as String;
+			var item2:String = _sut.getItemAt(1) as String;
+
+            //when
+			_sut.setItemAt(item2,0);
+			_sut.setItemAt(item1,1);
+
+            //then
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  _sut[0], "B");
+			assertEquals("Second element not correct",  _sut[1], "A");
+			assertEquals("Third element not correct",  _sut[2], "D");
+			assertEquals("Four element not correct",  _sut[3], "C");
+		}
+		
+		[Test]
+		public function swapItemsOneThenTwo():void
+		{
+			addStrings();
+			_sut.filterFunction = allIn;
+			_sut.refresh();
+			
+			var item1:String = _sut.getItemAt(0) as String;
+			var item2:String = _sut.getItemAt(1) as String;
+			
+			_sut.setItemAt(item1,1);
+			_sut.setItemAt(item2,0);
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "B", _sut[0]);
+			assertEquals("Second element not correct",  "A", _sut[1]);
+			assertEquals("Third element not correct",  "D", _sut[2]);
+			assertEquals("Four element not correct",  "C", _sut[3]);
+		}
+		
+		[Test]
+		public function removeAllAfterFiltered():void
+		{
+			addStrings();
+			_sut.filterFunction = allOut;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  0, _sut.length);
+			
+			_sut.removeAll();
+			
+			assertEquals("Length is not two",  0, _sut.length);
+			
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("Third element not correct",  "D", _sut[2]);
+			assertEquals("Four element not correct",  "C", _sut[3]);
+		}
+		
+		[Test]
+		public function removeFilteredItem():void
+		{
+			addStrings();
+			_sut.filterFunction = isA;
+			_sut.refresh();
+			
+			assertEquals("Length is not one",  1, _sut.length);
+			
+			_sut.removeItemAt(_sut.getItemIndex("A"));
+			
+			assertEquals("Length is not zero",  0, _sut.length);
+			
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not three",  3, _sut.length);
+			assertEquals("First element not correct",  "B", _sut[0]);
+		}
+		
+		[Test]
+		public function removeNonFilteredItem():void
+		{
+			addStrings();
+			_sut.filterFunction = isA;
+			_sut.refresh();
+			
+			assertEquals("Length is not one",  1, _sut.length);
+			
+			try {
+				// not removed as filter hids it - perhaps it should be removed?
+				_sut.removeItemAt(_sut.getItemIndex("B"));
+			}
+			catch (error:Error)
+			{
+				assertTrue("Error not range error", error is RangeError);
+			}
+			
+			assertEquals("Length is not one",  1, _sut.length);
+			
+			_sut.filterFunction = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("Third element not correct",  "D", _sut[2]);
+			assertEquals("Four element not correct",  "C", _sut[3]);
+		}
+		
+		
+	}
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/collections/ArrayCollection_SortNumbers_Tests.as b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_SortNumbers_Tests.as
new file mode 100644
index 0000000..85f800e
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_SortNumbers_Tests.as
@@ -0,0 +1,212 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import org.flexunit.asserts.*;
+
+    public class ArrayCollection_SortNumbers_Tests
+	{
+        private var _sut:ArrayCollection;
+		
+		[Before]
+		public function setUp():void
+		{
+			_sut = new ArrayCollection();
+		}
+		
+		[After]
+		public function tearDown():void
+		{
+			_sut = null;
+		}
+		
+		protected function addNumbers():void
+		{
+			_sut.addItem(1);
+			_sut.addItem(2);
+		}
+		
+		[Test]
+		public function nullSort():void
+		{
+			addNumbers();
+			_sut.sort = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}	
+		
+		[Test]
+		public function emptySort():void
+		{
+			addNumbers();
+			_sut.sort = new Sort();
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}
+		
+		[Test]
+		public function reverseSort():void
+		{
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField(null, false, true, true)];
+			addNumbers();
+			_sut.sort = sort;
+			_sut.refresh();
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Second element not correct",  1, _sut[1]);
+		}
+		
+		[Test]
+		public function sortNoRefresh():void
+		{
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField(null, false, true, true)];
+			addNumbers();
+			_sut.sort = sort;
+			
+			// Short should not take effect
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}
+		
+		[Test]
+		public function nullSortNoRefresh():void
+		{
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField(null, false, true, true)];
+			addNumbers();
+			_sut.sort = sort;
+			_sut.refresh();
+			_sut.sort = null;
+			
+			// Sort should be in effect
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Second element not correct",  1, _sut[1]);
+			
+			_sut.refresh();
+			
+			// and back to original
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}
+		
+		[Test]
+		public function sortDoubleRefresh():void
+		{
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField(null, false, true, true)];
+			addNumbers();
+			_sut.sort = sort;
+			_sut.refresh();
+			_sut.sort = null;
+			_sut.refresh();
+			
+			// Sort should not be in effect
+			assertEquals("Length is not two",  2, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+		}
+		
+		// RTEs in APache flex 4.9.1
+		[Test]
+		public function sortAddAfterNullNoRefresh():void
+		{
+			addNumbers();
+			
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField(null, false, true, true)];
+			_sut.sort = sort;
+			_sut.refresh();
+			_sut.sort = null;
+			addNumbers();
+			
+			// Sort should be in effect and first 2 items sorted
+			// item added after are not sorted
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Second element not correct",  1, _sut[1]);
+			assertEquals("Third element not correct",  1, _sut[2]);
+			assertEquals("Fourth element not correct",  2, _sut[3]);
+			
+			_sut.refresh();
+			
+			// and back to being unsorted
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+			assertEquals("Third element not correct",  1, _sut[2]);
+			assertEquals("Fourth element not correct",  2, _sut[3]);
+		}
+		
+		// RTEs in Apache Flex 4.9.1
+		[Test]
+		public function sortRemoveAfterNullNoRefresh():void
+		{
+			addNumbers();
+			
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField(null, false, true, true)];
+			_sut.sort = sort;
+			_sut.refresh();
+			_sut.sort = null;
+			
+			assertEquals("Length is not two",  2, _sut.length);
+			
+			_sut.removeItemAt(0); // still sorted so 2 is removed leaving 1
+			assertEquals("Length is not one",  1, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+			
+			_sut.refresh();
+			
+			// still the same
+			assertEquals("Length is not one",  1, _sut.length);
+			assertEquals("First element not correct",  1, _sut[0]);
+		}
+		
+		[Test]
+		public function sortIncludingDuplicates():void
+		{
+			addNumbers();
+			addNumbers();
+			
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField(null, false, true, true)];
+			_sut.sort = sort;
+			_sut.refresh();
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			
+			assertEquals("First element not correct",  2, _sut[0]);
+			assertEquals("Second element not correct",  2, _sut[1]);
+			assertEquals("Third element not correct",  1, _sut[2]);
+			assertEquals("Fourth element not correct",  1, _sut[3]);
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/collections/ArrayCollection_SortStrings_Tests.as b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_SortStrings_Tests.as
new file mode 100644
index 0000000..3f49d52
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/collections/ArrayCollection_SortStrings_Tests.as
@@ -0,0 +1,254 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import org.flexunit.asserts.*;
+
+    public class ArrayCollection_SortStrings_Tests
+	{
+        private var _sut:ArrayCollection;
+		
+		[Before]
+		public function setUp():void
+		{
+			_sut = new ArrayCollection();
+		}
+		
+		[After]
+		public function tearDown():void
+		{
+			_sut = null;
+		}
+		
+		protected function addStrings():void
+		{
+			_sut.addItem("A");
+			_sut.addItem("B");
+			_sut.addItem("D");
+			_sut.addItem("C");
+		}
+		
+		[Test]
+		public function nullSort():void
+		{
+			addStrings();
+			_sut.sort = null;
+			_sut.refresh();
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("First element not correct",  "D", _sut[2]);
+			assertEquals("Second element not correct",  "C", _sut[3]);
+		}	
+		
+		[Test]
+		public function emptySort():void
+		{
+			addStrings();
+			_sut.sort = new Sort();
+			_sut.refresh();
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("First element not correct",  "C", _sut[2]);
+			assertEquals("Second element not correct",  "D", _sut[3]);
+		}
+		
+		[Test]
+		public function reverseSort():void
+		{
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField(null, false, true)];
+			addStrings();
+			_sut.sort = sort;
+			_sut.refresh();
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "D", _sut[0]);
+			assertEquals("Second element not correct",  "C", _sut[1]);
+			assertEquals("First element not correct",  "B", _sut[2]);
+			assertEquals("Second element not correct",  "A", _sut[3]);
+		}
+		
+		[Test]
+		public function forwardSort():void
+		{
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField()];
+			addStrings();
+			_sut.sort = sort;
+			_sut.refresh();
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("First element not correct",  "C", _sut[2]);
+			assertEquals("Second element not correct",  "D", _sut[3]);
+		}
+		
+		[Test]
+		public function sortNoRefresh():void
+		{
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField()];
+			addStrings();
+			_sut.sort = sort;
+			
+			// Short should not take effect
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("First element not correct",  "D", _sut[2]);
+			assertEquals("Second element not correct",  "C", _sut[3]);
+		}
+		
+		[Test]
+		public function nullSortNoRefresh():void
+		{
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField()];
+			addStrings();
+			_sut.sort = sort;
+			_sut.refresh();
+			_sut.sort = null;
+			
+			// Sort should be in effect
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("First element not correct",  "C", _sut[2]);
+			assertEquals("Second element not correct",  "D", _sut[3]);
+			
+			_sut.refresh();
+			
+			// and back to original
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("First element not correct",  "D", _sut[2]);
+			assertEquals("Second element not correct",  "C", _sut[3]);
+		}
+		
+		[Test]
+		public function sortDoubleRefresh():void
+		{
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField()];
+			addStrings();
+			_sut.sort = sort;
+			_sut.refresh();
+			_sut.sort = null;
+			_sut.refresh();
+			
+			// Sort should not be in effect
+			assertEquals("Length is not four",  4, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("First element not correct",  "D", _sut[2]);
+			assertEquals("Second element not correct",  "C", _sut[3]);
+		}
+		
+		// RTEs in APache flex 4.9.1
+		[Test]
+		public function sortAddAfterNullNoRefresh():void
+		{
+			addStrings();
+			
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField()];
+			_sut.sort = sort;
+			_sut.refresh();
+			_sut.sort = null;
+			addStrings();
+			
+			// Sort should be in effect and first 4 items sorted
+			// item added after are not sorted
+			assertEquals("Length is not eight",  8, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("First element not correct",  "C", _sut[2]);
+			assertEquals("Second element not correct",  "D", _sut[3]);
+			assertEquals("First element not correct",  "A", _sut[4]);
+			assertEquals("Second element not correct",  "B", _sut[5]);
+			assertEquals("First element not correct",  "D", _sut[6]);
+			assertEquals("Second element not correct",  "C", _sut[7]);
+			
+			_sut.refresh();
+			
+			// and back to being unsorted
+			assertEquals("Length is not eight",  8, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "B", _sut[1]);
+			assertEquals("First element not correct",  "D", _sut[2]);
+			assertEquals("Second element not correct",  "C", _sut[3]);
+			assertEquals("First element not correct",  "A", _sut[4]);
+			assertEquals("Second element not correct",  "B", _sut[5]);
+			assertEquals("First element not correct",  "D", _sut[6]);
+			assertEquals("Second element not correct",  "C", _sut[7]);
+		}
+		
+		// RTEs in Apache Flex 4.9.1
+		[Test]
+		public function sortRemoveAfterNullNoRefresh():void
+		{
+			addStrings();
+			
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField(null, false, true, true)];
+			_sut.sort = sort;
+			_sut.refresh();
+			_sut.sort = null;
+			
+			assertEquals("Length is not four",  4, _sut.length);
+			
+			_sut.removeItemAt(0); // still sorted so 2 is removed leaving 1
+			assertEquals("Length is not three",  3, _sut.length);
+			assertEquals("First element not correct",  "B", _sut[0]);
+			
+			_sut.refresh();
+			
+			assertEquals("Length is not four",  3, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+		}
+		
+		[Test]
+		public function sortIncludingDuplicates():void
+		{
+			addStrings();
+			addStrings();
+			
+			var sort:Sort = new Sort();			
+			sort.fields = [new SortField()];
+			_sut.sort = sort;
+			_sut.refresh();
+			
+			assertEquals("Length is not eight",  8, _sut.length);
+			assertEquals("First element not correct",  "A", _sut[0]);
+			assertEquals("Second element not correct",  "A", _sut[1]);
+			assertEquals("First element not correct",  "B", _sut[2]);
+			assertEquals("Second element not correct",  "B", _sut[3]);
+			assertEquals("First element not correct",  "C", _sut[4]);
+			assertEquals("Second element not correct",  "C", _sut[5]);
+			assertEquals("First element not correct",  "D", _sut[6]);
+			assertEquals("Second element not correct",  "D", _sut[7]);
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/collections/ListCollectionView_PropertyChangeEvent_Tests.as b/frameworks/projects/framework/tests/mx/collections/ListCollectionView_PropertyChangeEvent_Tests.as
new file mode 100644
index 0000000..012b9de
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/collections/ListCollectionView_PropertyChangeEvent_Tests.as
@@ -0,0 +1,532 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections {
+    import flash.display.DisplayObject;
+    import flash.events.UncaughtErrorEvent;
+
+    import mx.core.FlexGlobals;
+    import mx.events.CollectionEvent;
+    import mx.events.CollectionEventKind;
+    import mx.events.PropertyChangeEvent;
+    import mx.events.PropertyChangeEventKind;
+    import mx.utils.ObjectUtil;
+
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.asserts.assertNull;
+    import org.flexunit.asserts.assertTrue;
+
+    public class ListCollectionView_PropertyChangeEvent_Tests
+    {
+        private static const NO_WORKOUTS:int = 10;
+
+        private static var _sut:ListCollectionView;
+        private static var _firstWorkout:WorkoutVO;
+
+        private static var PROPERTY_CHANGE_EVENT:PropertyChangeEvent;
+        private static var PROPERTY_CHANGE_EVENT_UPDATE:PropertyChangeEvent;
+        private static var PROPERTY_CHANGE_EVENT_UPDATE_CONVENIENCE:PropertyChangeEvent;
+        private static var _noTimesFilterFunctionCalled:int;
+        private static var _lastFilteredObject:Object;
+        private static var _uncaughtError:Error;
+
+        [BeforeClass]
+        public static function setUpBeforeClass():void
+        {
+            if(FlexGlobals.topLevelApplication is DisplayObject)
+                (FlexGlobals.topLevelApplication as DisplayObject).loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, handleUncaughtClientError);
+        }
+
+        [AfterClass]
+        public static function tearDownAfterClass():void
+        {
+            if(FlexGlobals.topLevelApplication is DisplayObject)
+                (FlexGlobals.topLevelApplication as DisplayObject).loaderInfo.uncaughtErrorEvents.removeEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, handleUncaughtClientError);
+        }
+
+        [Before]
+        public function setUp():void
+        {
+            PROPERTY_CHANGE_EVENT = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
+            PROPERTY_CHANGE_EVENT_UPDATE = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE, false, false, PropertyChangeEventKind.UPDATE);
+            PROPERTY_CHANGE_EVENT_UPDATE_CONVENIENCE = PropertyChangeEvent.createUpdateEvent(null, null, null, null);
+
+            _noTimesFilterFunctionCalled = 0;
+
+            InspectableSort.setUp();
+
+            _sut = new ListCollectionView(new ArrayList());
+            _sut.addAll(createWorkouts());
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            _sut = null;
+            _lastFilteredObject = null;
+            _firstWorkout = null;
+
+            PROPERTY_CHANGE_EVENT = null;
+            PROPERTY_CHANGE_EVENT_UPDATE = null;
+            PROPERTY_CHANGE_EVENT_UPDATE_CONVENIENCE = null;
+
+            InspectableSort.tearDown();
+
+            _uncaughtError = null;
+        }
+
+        [Test]
+        public function test_PropertyChangeEvents_equivalent():void
+        {
+            //when
+            var eventComparison:int = ObjectUtil.compare(PROPERTY_CHANGE_EVENT_UPDATE, PROPERTY_CHANGE_EVENT_UPDATE_CONVENIENCE);
+
+            //then
+            assertEquals(0, eventComparison);
+        }
+
+        [Test]
+        public function test_when_collection_item_dispatches_PropertyChangeEvent_item_is_run_through_filter_and_there_is_no_fatal():void
+        {
+            //given
+            _sut.filterFunction = allowAll;
+            _sut.refresh();
+            const positionOfFirstWorkout:int = _sut.getItemIndex(_firstWorkout);
+
+            _noTimesFilterFunctionCalled = 0;
+            _lastFilteredObject = null;
+
+            //when
+            _firstWorkout.dispatchEvent(PROPERTY_CHANGE_EVENT);
+
+            //then - no fatal, and object has been filtered
+            assertEquals(1, _noTimesFilterFunctionCalled);
+            assertEquals(_firstWorkout, _lastFilteredObject);
+            assertEquals(positionOfFirstWorkout, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test]
+        public function test_when_collection_item_changes_item_is_run_through_filter_and_there_is_no_fatal():void
+        {
+            //given
+            _sut.filterFunction = allowAll;
+            _sut.refresh();
+            const positionOfFirstWorkout:int = _sut.getItemIndex(_firstWorkout);
+
+            _noTimesFilterFunctionCalled = 0;
+            _lastFilteredObject = null;
+
+            //when
+            _firstWorkout.duration += 10;
+
+            //then - no fatal, and object has been filtered
+            assertEquals(1, _noTimesFilterFunctionCalled);
+            assertEquals(_firstWorkout, _lastFilteredObject);
+            assertEquals(positionOfFirstWorkout, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test] //FLEX-35043 FLEX-34885
+        public function test_when_collection_item_dispatches_PropertyChangeEvent_null_is_not_removed_from_list():void
+        {
+            //given
+            _sut.addItem(null);
+            _sut.filterFunction = allowAll;
+            _sut.refresh();
+            var positionOfNull:int = _sut.getItemIndex(null);
+            const positionOfFirstWorkout:int = _sut.getItemIndex(_firstWorkout);
+
+            //when
+            _firstWorkout.dispatchEvent(PROPERTY_CHANGE_EVENT);
+
+            //then
+            assertTrue(positionOfNull != -1);
+            assertEquals(positionOfNull, _sut.getItemIndex(null));
+            assertEquals(positionOfFirstWorkout, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test]
+        public function test_when_collection_item_is_changed_null_is_not_removed_from_list():void
+        {
+            //given
+            _sut.addItem(null);
+            _sut.filterFunction = allowAll;
+            _sut.refresh();
+            const positionOfNull:int = _sut.getItemIndex(null);
+            const positionOfFirstWorkout:int = _sut.getItemIndex(_firstWorkout);
+
+            //when
+            _firstWorkout.duration += 10;
+
+            //then
+            assertTrue(positionOfNull != -1);
+            assertEquals(positionOfNull, _sut.getItemIndex(null));
+            assertEquals(positionOfFirstWorkout, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test] //FLEX-35043 FLEX-34885
+        public function test_when_item_is_changed_bypassing_binding_and_collection_notified_of_itemUpdated_with_property_null_is_not_removed_from_list():void
+        {
+            //given
+            _sut.addItem(null);
+            _sut.filterFunction = allowAll;
+            _sut.refresh();
+            const positionOfNull:int = _sut.getItemIndex(null);
+            const positionOfFirstWorkout:int = _sut.getItemIndex(_firstWorkout);
+
+            //when
+            _firstWorkout.setMuscleGroupsWithoutTriggeringBinding("biceps");
+            _sut.itemUpdated(_firstWorkout, "muscleGroups", null, _firstWorkout.muscleGroups);
+
+            //then
+            assertTrue(positionOfNull != -1);
+            assertEquals(positionOfNull, _sut.getItemIndex(null));
+            assertEquals(positionOfFirstWorkout, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test] //FLEX-35043 FLEX-34885
+        public function test_when_item_is_changed_bypassing_binding_and_collection_notified_of_itemUpdated_without_property_null_is_not_removed_from_list():void
+        {
+            //given
+            _sut.addItem(null);
+            _sut.filterFunction = allowAll;
+            _sut.refresh();
+            const positionOfNull:int = _sut.getItemIndex(null);
+            const positionOfFirstWorkout:int = _sut.getItemIndex(_firstWorkout);
+
+            //when
+            _firstWorkout.setMuscleGroupsWithoutTriggeringBinding("biceps");
+            _firstWorkout.setMinAgeWithoutTriggeringBinding(14);
+            _sut.itemUpdated(_firstWorkout);
+
+            //then
+            assertTrue(positionOfNull != -1);
+            assertEquals(positionOfNull, _sut.getItemIndex(null));
+            assertEquals(positionOfFirstWorkout, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test] //FLEX-35043 FLEX-34885
+        public function test_when_collection_item_dispatches_PropertyChangeEvent_with_UPDATE_null_is_not_removed_from_list():void
+        {
+            //given
+            _sut.addItem(null);
+            _sut.filterFunction = allowAll;
+            _sut.refresh();
+            var positionOfNull:int = _sut.getItemIndex(null);
+            const positionOfFirstWorkout:int = _sut.getItemIndex(_firstWorkout);
+
+            //when
+            _firstWorkout.dispatchEvent(PROPERTY_CHANGE_EVENT_UPDATE);
+
+            //then
+            assertTrue(positionOfNull != -1);
+            assertEquals(positionOfNull, _sut.getItemIndex(null));
+            assertEquals(positionOfFirstWorkout, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test]
+        public function test_when_collection_item_dispatches_PropertyChangeEvent_with_correct_property_and_oldValue_null_stays_in_list():void
+        {
+            //given
+            _sut.addItem(null);
+            var sort:InspectableSort = new InspectableSort([new SortField("name")]);
+            _sut.sort = sort;
+            _sut.refresh();
+            const positionOfNull:int = _sut.getItemIndex(null);
+            const positionOfFirstWorkout:int = _sut.getItemIndex(_firstWorkout);
+
+            //when
+            _firstWorkout.dispatchEvent(PropertyChangeEvent.createUpdateEvent(_firstWorkout, "name", _firstWorkout.name, "zzz"));
+
+            //then
+            assertTrue(positionOfNull != -1);
+            assertEquals(positionOfNull, _sut.getItemIndex(null));
+            assertEquals(positionOfFirstWorkout, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test]
+        public function test_when_collection_item_dispatches_PropertyChangeEvent_with_correct_property_and_null_oldValue_null_stays_in_list():void
+        {
+            //given
+            _sut.addItem(null);
+            var sort:InspectableSort = new InspectableSort([new SortField("name")]);
+            _sut.sort = sort;
+            _sut.refresh();
+
+            const positionOfNull:int = _sut.getItemIndex(null);
+            const positionOfFirstWorkout:int = _sut.getItemIndex(_firstWorkout);
+
+            //when
+            _firstWorkout.dispatchEvent(PropertyChangeEvent.createUpdateEvent(_firstWorkout, "name", null, null));
+
+            //then
+            assertTrue(positionOfNull != -1);
+            assertEquals(positionOfNull, _sut.getItemIndex(null));
+            assertEquals(positionOfFirstWorkout, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test] //FLEX-35043 FLEX-34885
+        public function test_when_collection_item_dispatches_PropertyChangeEvent_item_is_added_in_correct_place_based_on_sort_and_there_is_no_fatal():void
+        {
+            //given
+            var sort:InspectableSort = new InspectableSort([new SortField("name")]);
+            _sut.sort = sort;
+            _sut.refresh();
+            const positionOfFirstWorkout:int = _sut.getItemIndex(_firstWorkout);
+
+            //when
+            _firstWorkout.dispatchEvent(PROPERTY_CHANGE_EVENT);
+
+            //then - no fatal, and:
+            //object's correct position has been inspected with Sort
+            assertEquals(_firstWorkout, InspectableSort.lastItemSearchedFor);
+            //and null (PropertyChangeEvent.oldValue) has been sought for when trying to remove it
+            assertEquals(-1, InspectableSort.itemsSearchedFor.indexOf(null));
+            //and it's in the same position
+            assertEquals(positionOfFirstWorkout, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test] //FLEX-35043 FLEX-34885
+        public function test_when_collection_item_dispatches_PropertyChangeEvent_sort_compare_function_not_called_with_null():void
+        {
+            function compareWorkouts(a:Object, b:Object, fields:Array = null):int
+            {
+                if(a.duration > b.duration)
+                    return 1;
+                if(a.duration < b.duration)
+                    return -1;
+
+                return 0;
+            }
+            //given
+            var sort:InspectableSort = new InspectableSort([], compareWorkouts);
+            _sut.sort = sort;
+            _sut.refresh();
+
+            //when
+            _firstWorkout.dispatchEvent(PROPERTY_CHANGE_EVENT);
+
+            //then - no fatal because compareWorkouts was not called with null as an argument
+            assertNull(_uncaughtError);
+        }
+
+        [Test] //FLEX-35043 FLEX-34885
+        public function test_when_collection_notified_of_itemUpdated_without_property_or_oldValue_sort_compare_function_not_called_with_null_and_item_repositioned():void
+        {
+            function orderByDurationDescending(a:Object, b:Object, fields:Array = null):int
+            {
+                if(a.duration > b.duration)
+                    return -1;
+                if(a.duration < b.duration)
+                    return 1;
+
+                return 0;
+            }
+
+            //make sure the workout is on the first position
+            assertEquals("Initial assumption wrong - position", 0, _sut.getItemIndex(_firstWorkout));
+            assertEquals("Initial assumption wrong - duration", 0, _firstWorkout.duration);
+
+            //given
+            var sort:InspectableSort = new InspectableSort([], orderByDurationDescending);
+            _sut.sort = sort;
+            _sut.refresh();
+
+            //then
+            assertEquals("The first item should have the highest duration", NO_WORKOUTS - 1, WorkoutVO(_sut.getItemAt(0)).duration);
+            assertEquals("The first workout should have been moved to the end of the list", _sut.length - 1, _sut.getItemIndex(_firstWorkout));
+
+            //when
+            _firstWorkout.setMuscleGroupsWithoutTriggeringBinding("chest");
+            _firstWorkout.setMinAgeWithoutTriggeringBinding(20);
+            _firstWorkout.setDurationWithoutTriggeringBinding(int.MAX_VALUE);
+            _sut.itemUpdated(_firstWorkout);
+
+            //then
+            // 1. no fatal because compare function was not called with null
+            assertNull(_uncaughtError);
+            // 2. the workout was repositioned because its duration changed
+            assertEquals("The workout should have been moved to the start of the list, as it has the highest duration", 0, _sut.getItemIndex(_firstWorkout));
+        }
+
+        [Test] //FLEX-35043 FLEX-34885
+        public function test_when_collection_of_non_binding_objects_notified_of_itemUpdated_without_property_or_oldValue_item_is_repositioned():void
+        {
+            function onCollectionChange(event:CollectionEvent):void
+            {
+                moveDispatched = event.kind == CollectionEventKind.MOVE;
+            }
+
+            function orderByDurationAscending(a:Object, b:Object, fields:Array = null):int
+            {
+                if(a.duration > b.duration)
+                    return 1;
+                if(a.duration < b.duration)
+                    return -1;
+
+                return 0;
+            }
+
+            //given
+            var moveDispatched:Boolean = false;
+
+            var testWorkout:Object = {duration:10};
+            _sut.removeAll();
+            _sut.addAll(new ArrayList([testWorkout, {duration:20}, {duration:5}]));
+
+            var sortField:SortField = new SortField("duration", false, false, null, SortFieldCompareTypes.NUMERIC);
+            var sort:InspectableSort = new InspectableSort([sortField]);
+            _sut.sort = sort;
+            _sut.refresh();
+
+            _sut.addEventListener(CollectionEvent.COLLECTION_CHANGE, onCollectionChange);
+
+            //then
+            assertEquals("The ten minute workout should be in the second position", 1, _sut.getItemIndex(testWorkout));
+
+            //when
+            testWorkout.duration = int.MAX_VALUE;
+            _sut.itemUpdated(testWorkout);
+
+            //then
+            // 1. no fatal because compare function was not called with null
+            assertNull(_uncaughtError);
+            // 2. the workout was repositioned because its duration changed
+            assertTrue(moveDispatched);
+            assertEquals("The workout should have been moved to the end of the list, as it now has the highest duration", _sut.length - 1, _sut.getItemIndex(testWorkout));
+        }
+
+        private static function allowAll(object:Object):Boolean
+        {
+            _lastFilteredObject = object;
+            _noTimesFilterFunctionCalled++;
+            return true;
+        }
+
+        private static function createWorkouts():IList
+        {
+            var result:ArrayList = new ArrayList();
+            for (var i:int = 0; i < NO_WORKOUTS; i++)
+            {
+                result.addItem(new WorkoutVO("Workout" + i, i));
+            }
+
+            _firstWorkout = result.getItemAt(0) as WorkoutVO;
+
+            return result;
+        }
+
+        private static function handleUncaughtClientError(event:UncaughtErrorEvent):void
+        {
+            _uncaughtError = event.error;
+            event.preventDefault();
+            event.stopImmediatePropagation();
+        }
+    }
+}
+
+import spark.collections.Sort;
+
+[Bindable]
+class WorkoutVO
+{
+    public var name:String;
+    private var _duration:int;
+    private var _muscleGroups:String;
+    private var _minAge:uint;
+
+    public function WorkoutVO(name:String, duration:int)
+    {
+        this.name = name;
+        this._duration = duration;
+    }
+
+    public function get muscleGroups():String
+    {
+        return _muscleGroups;
+    }
+
+    public function set muscleGroups(value:String):void
+    {
+        _muscleGroups = value;
+    }
+
+    public function setMuscleGroupsWithoutTriggeringBinding(groups:String):void
+    {
+        _muscleGroups = groups;
+    }
+
+    public function get minAge():uint
+    {
+        return _minAge;
+    }
+
+    public function set minAge(value:uint):void
+    {
+        _minAge = value;
+    }
+
+    public function setMinAgeWithoutTriggeringBinding(age:uint):void
+    {
+        _minAge = age;
+    }
+
+    public function setDurationWithoutTriggeringBinding(duration:int):void
+    {
+        _duration = duration;
+    }
+
+    public function get duration():int
+    {
+        return _duration;
+    }
+
+    public function set duration(value:int):void
+    {
+        _duration = value;
+    }
+}
+
+class InspectableSort extends Sort
+{
+    public static var lastItemSearchedFor:Object;
+    public static var itemsSearchedFor:Array;
+
+    public function InspectableSort(fields:Array = null, customCompareFunction:Function = null, unique:Boolean = false)
+    {
+        super(fields, customCompareFunction, unique);
+    }
+
+    override public function findItem(items:Array, values:Object, mode:String, returnInsertionIndex:Boolean = false, compareFunction:Function = null):int
+    {
+        lastItemSearchedFor = values;
+        itemsSearchedFor.push(values);
+        return super.findItem(items, values, mode, returnInsertionIndex, compareFunction);
+    }
+
+    public static function setUp():void
+    {
+        itemsSearchedFor = [];
+    }
+
+    public static function tearDown():void
+    {
+        lastItemSearchedFor = null;
+        itemsSearchedFor = null;
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/utils/ArrayUtil_Tests.as b/frameworks/projects/framework/tests/mx/utils/ArrayUtil_Tests.as
new file mode 100644
index 0000000..36c8b84
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/utils/ArrayUtil_Tests.as
@@ -0,0 +1,308 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.utils
+{
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.asserts.assertFalse;
+    import org.flexunit.asserts.assertNotNull;
+    import org.flexunit.asserts.assertTrue;
+
+    public class ArrayUtil_Tests
+    {
+        //--------------------------------------------------------------------------
+        //
+        //  arraysMatch()
+        //
+        //--------------------------------------------------------------------------
+
+        [Test]
+        public function test_array_matches_with_itself():void
+        {
+            //given
+            var array:Array = [1, 2, 3];
+
+            //then
+            assertTrue(ArrayUtil.arraysMatch(array, array));
+        }
+
+        [Test]
+        public function test_empty_arrays_match():void
+        {
+            //then
+            assertTrue(ArrayUtil.arraysMatch([], []));
+        }
+
+        [Test]
+        public function test_arrays_with_same_values_in_different_indexes_dont_match():void
+        {
+            //then
+            assertFalse(ArrayUtil.arraysMatch(["name", "age"], ["age", "name"]));
+        }
+
+        [Test]
+        public function test_arrays_match_when_properties_created_in_different_orders():void
+        {
+            //given
+            var arrayA:Array = [];
+            var arrayB:Array = [];
+
+            //when
+            arrayA["name"] = "AName";
+            arrayA["age"] = 22;
+
+            arrayB["age"] = 22;
+            arrayB["name"] = "AName";
+
+            //then
+            assertTrue(ArrayUtil.arraysMatch(arrayA, arrayB));
+        }
+
+        [Test]
+        public function test_arrays_dont_match_when_indexes_match_but_values_different():void
+        {
+            //given
+            var arrayA:Array = [];
+            var arrayB:Array = [];
+
+            //when
+            arrayA["name"] = "AName";
+            arrayA["age"] = 444;
+
+            arrayB["age"] = 22;
+            arrayB["name"] = "BName";
+
+            //then
+            assertFalse(ArrayUtil.arraysMatch(arrayA, arrayB));
+        }
+
+        [Test]
+        public function test_arrays_dont_match_when_they_have_same_number_of_different_indexes():void
+        {
+            //given
+            var arrayA:Array = [];
+            var arrayB:Array = [];
+
+            //when
+            arrayA["name"] = "AName";
+            arrayA["age"] = 444;
+
+            arrayB["radius"] = "AName";
+            arrayB[9] = 444;
+
+            //then
+            assertFalse(ArrayUtil.arraysMatch(arrayA, arrayB));
+        }
+
+        [Test]
+        public function test_arrays_match_when_indexes_expressed_in_string_and_int():void
+        {
+            //given
+            var arrayA:Array = ["value", "value"];
+            var arrayB:Array = [];
+
+            //when
+            arrayB["0"] = "value";
+            arrayB["1"] = "value";
+
+            //then
+            assertTrue(ArrayUtil.arraysMatch(arrayA, arrayB));
+        }
+
+        [Test]
+        public function test_arrays_dont_match_when_values_expressed_in_string_and_int_if_strict_equality_used():void
+        {
+            //given
+            var arrayA:Array = [];
+            var arrayB:Array = [];
+
+            //when
+            arrayA[3] = 3;
+            arrayA[4] = 4;
+
+            arrayB[3] = "3";
+            arrayB[4] = "4";
+
+            //then
+            assertFalse(ArrayUtil.arraysMatch(arrayA, arrayB, true));
+        }
+
+        [Test]
+        public function test_arrays_match_when_values_expressed_in_string_and_int_if_strict_equality_not_used():void
+        {
+            //given
+            var arrayA:Array = [];
+            var arrayB:Array = [];
+
+            //when
+            arrayA[3] = 3;
+            arrayA[4] = 4;
+
+            arrayB[3] = "3";
+            arrayB[4] = "4";
+
+            //then
+            assertTrue(ArrayUtil.arraysMatch(arrayA, arrayB, false));
+        }
+
+        [Test]
+        public function test_array_and_null_dont_match():void
+        {
+            //then
+            assertFalse(ArrayUtil.arraysMatch([1, 2, 3], null));
+        }
+
+        [Test]
+        public function test_null_and_null_dont_match():void
+        {
+            //then
+            assertFalse(ArrayUtil.arraysMatch(null, null));
+        }
+
+        [Test]
+        public function test_arrays_with_null_in_different_positions_dont_match():void
+        {
+            //then
+            assertFalse(ArrayUtil.arraysMatch([null, 0], [0, null]));
+        }
+
+        //--------------------------------------------------------------------------
+        //
+        //  arrayValuesMatch()
+        //
+        //--------------------------------------------------------------------------
+
+        [Test]
+        public function test_arrays_with_same_values_in_different_indexes_match_in_terms_of_values():void
+        {
+            //then
+            assertTrue(ArrayUtil.arrayValuesMatch(["name", "age"], ["age", "name"]));
+        }
+
+        [Test]
+        public function test_array_values_dont_match_with_null():void
+        {
+            //then
+            assertFalse(ArrayUtil.arrayValuesMatch(["name", "age"], null));
+        }
+
+        [Test]
+        public function test_null_doesnt_match_values_with_array():void
+        {
+            //then
+            assertFalse(ArrayUtil.arrayValuesMatch(null, ["name", "age"]));
+        }
+
+        [Test]
+        public function test_null_and_null_dont_have_matching_values():void
+        {
+            //then
+            assertFalse(ArrayUtil.arrayValuesMatch(null, null));
+        }
+
+        [Test]
+        public function test_array_values_match_although_they_have_different_indexes():void
+        {
+            //given
+            var arrayA:Array = [];
+            var arrayB:Array = [];
+
+            //when
+            arrayA["name"] = "AName";
+            arrayA["age"] = 444;
+
+            arrayB["label"] = "AName";
+            arrayB["spin"] = 444;
+
+            //then
+            assertTrue(ArrayUtil.arrayValuesMatch(arrayA, arrayB));
+        }
+
+        [Test]
+        public function test_array_values_dont_match_although_they_have_same_indexes():void
+        {
+            //given
+            var arrayA:Array = [];
+            var arrayB:Array = [];
+
+            //when
+            arrayA["name"] = "AName";
+            arrayA["age"] = 444;
+
+            arrayB["name"] = "BName";
+            arrayB["age"] = 21;
+
+            //then
+            assertFalse(ArrayUtil.arrayValuesMatch(arrayA, arrayB));
+        }
+
+        [Test]
+        //relevant because the array length is changed when a numeric index is used
+        public function test_array_values_match_even_when_one_of_their_indexes_is_numeric():void
+        {
+            //given
+            var arrayA:Array = [];
+            var arrayB:Array = [];
+
+            //when
+            arrayA["name"] = "AName";
+            arrayA["age"] = 444;
+
+            arrayB["label"] = "AName";
+            arrayB[9] = 444;
+
+            //then
+            assertTrue(ArrayUtil.arrayValuesMatch(arrayA, arrayB));
+        }
+
+
+        //--------------------------------------------------------------------------
+        //
+        //  getArrayValues()
+        //
+        //--------------------------------------------------------------------------
+        [Test]
+        public function test_values_of_null_is_an_empty_array():void
+        {
+            //when
+            var values:Array = ArrayUtil.getArrayValues(null);
+
+            //then
+            assertNotNull(values);
+            assertEquals(0, values.length);
+        }
+
+        [Test]
+        public function test_values_of_array_whose_index_was_set_manually_to_a_number_include_only_that_value():void
+        {
+            //given
+            var array:Array = [];
+            array[2] = "hey";
+
+            //when
+            var values:Array = ArrayUtil.getArrayValues(array);
+
+            //then
+            assertNotNull(values);
+            assertEquals(3, array.length);
+            assertEquals(1, values.length);
+            assertEquals("hey", values[0]);
+        }
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Compare_Tests.as b/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Compare_Tests.as
new file mode 100644
index 0000000..03d7d76
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Compare_Tests.as
@@ -0,0 +1,161 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.utils {
+    import org.flexunit.asserts.assertEquals;
+
+    public class ObjectUtil_Compare_Tests
+    {
+        private static const A_SMALLER_THAN_B:int = -1;
+        private static const A_LARGER_THAN_B:int = 1;
+        private static const A_EQUAL_TO_B:int = 0;
+
+        [Test]
+        public function test_object_is_smaller_when_first_property_smaller_even_if_second_property_larger():void
+        {
+            //given
+            var objectA:Object = {propertyA:1, propertyB:23};
+            var objectB:Object = {propertyA:45, propertyB:2};
+
+            //when
+            var compareResult:int = ObjectUtil.compare(objectA, objectB);
+
+            //then
+            assertEquals(A_SMALLER_THAN_B, compareResult);
+        }
+
+        [Test]
+        public function test_object_is_larger_when_first_property_larger_even_if_second_property_smaller():void
+        {
+            //given
+            var objectA:Object = {propertyA:45, propertyB:2};
+            var objectB:Object = {propertyA:1, propertyB:23};
+
+            //when
+            var compareResult:int = ObjectUtil.compare(objectA, objectB);
+
+            //then
+            assertEquals(A_LARGER_THAN_B, compareResult);
+        }
+
+        [Test]
+        public function test_object_is_smaller_even_when_common_properties_equal_but_missing_extra_properties():void
+        {
+            //given
+            var objectA:Object = {propertyA:45};
+            var objectB:Object = {propertyA:45, propertyB:2};
+
+            //when
+            var compareResult:int = ObjectUtil.compare(objectA, objectB);
+
+            //then
+            assertEquals(A_SMALLER_THAN_B, compareResult);
+        }
+
+        [Test]
+        public function test_object_is_smaller_even_when_common_property_larger_but_missing_extra_properties():void
+        {
+            //given
+            var objectA:Object = {propertyA:46};
+            var objectB:Object = {propertyA:45, propertyB:2};
+
+            //when
+            var compareResult:int = ObjectUtil.compare(objectA, objectB);
+
+            //then
+            assertEquals(A_SMALLER_THAN_B, compareResult);
+        }
+
+        [Test]
+        public function test_sealed_class_instance_larger_than_anonymous_object_with_same_properties_and_same_values():void
+        {
+            //given
+            var objectA:PersonVO = new PersonVO("John", 23);
+            var objectB:Object = {name:"John", age:23};
+
+            //when
+            var compareResult:int = ObjectUtil.compare(objectA, objectB);
+
+            //then
+            assertEquals(A_LARGER_THAN_B, compareResult);
+        }
+
+        [Test]
+        public function test_sealed_class_instance_larger_than_dynamic_class_instance_with_same_properties_and_same_values():void
+        {
+            //given
+            var objectA:PersonVO = new PersonVO("John", 23);
+            var objectB:DynamicPersonVO = new DynamicPersonVO("John", 23);
+
+            //when
+            var compareResult:int = ObjectUtil.compare(objectA, objectB);
+
+            //then
+            assertEquals(A_LARGER_THAN_B, compareResult);
+        }
+
+        [Test]
+        public function test_null_and_undefined_are_seen_equal():void
+        {
+            //given
+            var objectA:Object = {propertyA:45, propertyB:null};
+            var objectB:Object = {propertyA:45, propertyB:undefined};
+
+            //when
+            var compareResult:int = ObjectUtil.compare(objectA, objectB);
+
+            //then
+            assertEquals(A_EQUAL_TO_B, compareResult);
+        }
+
+        [Test]
+        public function test_NaN_seen_larger_than_largest_number():void
+        {
+            //given
+            var objectA:Object = {propertyA:Number.MAX_VALUE};
+            var objectB:Object = {propertyA:NaN};
+
+            //when
+            var compareResult:int = ObjectUtil.compare(objectA, objectB);
+
+            //then
+            assertEquals(A_SMALLER_THAN_B, compareResult);
+        }
+    }
+}
+
+class PersonVO
+{
+    public var name:String;
+    public var age:uint;
+
+    public function PersonVO(name:String, age:uint)
+    {
+        this.name = name;
+        this.age = age;
+    }
+}
+
+dynamic class DynamicPersonVO extends PersonVO
+{
+    public function DynamicPersonVO(name:String, age:uint)
+    {
+        super(name, age);
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Tests.as b/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Tests.as
new file mode 100644
index 0000000..f45de1b
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Tests.as
@@ -0,0 +1,341 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.utils {
+    import flash.utils.Dictionary;
+    import flash.utils.Proxy;
+
+    import org.flexunit.asserts.assertEquals;
+
+    import org.flexunit.asserts.assertFalse;
+    import org.flexunit.asserts.assertTrue;
+
+    public class ObjectUtil_Tests
+    {
+        //--------------------------------------------------------------------------
+        //
+        //  isDynamicObject()
+        //
+        //--------------------------------------------------------------------------
+
+        [Test]
+        public function test_dynamic_class_instance_recognized_as_dynamic_object():void
+        {
+            //then
+            assertTrue(ObjectUtil.isDynamicObject(new DynamicVO("John")));
+        }
+
+        [Test]
+        public function test_anonymous_class_instance_recognized_as_dynamic_object():void
+        {
+            //then
+            assertTrue(ObjectUtil.isDynamicObject({name:"John"}));
+        }
+
+        [Test]
+        public function test_array_instance_recognized_as_dynamic_object():void
+        {
+            //then
+            assertTrue(ObjectUtil.isDynamicObject([]));
+        }
+
+        [Test]
+        public function test_XML_instance_recognized_as_dynamic_object():void
+        {
+            //then
+            assertTrue(ObjectUtil.isDynamicObject(new XML()));
+        }
+
+        [Test]
+        public function test_Proxy_instance_recognized_as_sealed_object_instance():void
+        {
+            //then
+            assertFalse(ObjectUtil.isDynamicObject(new Proxy()));
+        }
+
+        [Test]
+        public function test_ObjectProxy_with_implicit_target_object_instance_recognized_as_dynamic_instance():void
+        {
+            //then
+            assertTrue(ObjectUtil.isDynamicObject(new ObjectProxy()));
+        }
+
+        [Test]
+        public function test_ObjectProxy_with_explicit_target_object_instance_recognized_as_dynamic_instance():void
+        {
+            //then
+            assertTrue(ObjectUtil.isDynamicObject(new ObjectProxy({})));
+        }
+
+        [Test]
+        public function test_dictionary_instance_recognized_as_dynamic_object():void
+        {
+            //then
+            assertTrue(ObjectUtil.isDynamicObject(new Dictionary()));
+        }
+
+        [Test]
+        public function test_sealed_class_instance_recognized_as_non_dynamic_object():void
+        {
+            //then
+            assertFalse(ObjectUtil.isDynamicObject(new NonDynamicVO("John")));
+        }
+
+        [Test]
+        public function test_null_does_not_throw_fatal():void
+        {
+            //then
+            assertFalse(ObjectUtil.isDynamicObject(null));
+        }
+
+        //--------------------------------------------------------------------------
+        //
+        //  getEnumerableProperties()
+        //
+        //--------------------------------------------------------------------------
+
+        [Test]
+        public function test_enumerable_properties_of_anonymous_object():void
+        {
+            //given
+            var object:Object = {name:"John", age:32};
+
+            //when
+            var enumerableProperties:Array = ObjectUtil.getEnumerableProperties(object);
+
+            //then
+            assertTrue(ArrayUtil.arrayValuesMatch(["age", "name"], enumerableProperties));
+        }
+
+        [Test]
+        public function test_enumerable_properties_of_null():void
+        {
+            //when
+            var enumerableProperties:Array = ObjectUtil.getEnumerableProperties(null);
+
+            //then
+            assertEquals(0, enumerableProperties.length);
+        }
+
+        [Test]
+        public function test_enumerable_properties_of_dictionary():void
+        {
+            //given
+            var object:Dictionary = new Dictionary(false);
+            object["name"] = "John";
+            object["age"] = 9;
+
+            //when
+            var enumerableProperties:Array = ObjectUtil.getEnumerableProperties(object);
+
+            //then
+            assertTrue(ArrayUtil.arrayValuesMatch(["age", "name"], enumerableProperties));
+        }
+
+        [Test]
+        public function test_enumerable_properties_of_dynamic_class_instance():void
+        {
+            //given
+            var object:DynamicVO = new DynamicVO("John");
+            object["age"] = 9;
+            object["height"] = 6.1;
+
+            //when
+            var enumerableProperties:Array = ObjectUtil.getEnumerableProperties(object);
+
+            //then
+            assertTrue(ArrayUtil.arrayValuesMatch(["height", "age"], enumerableProperties));
+        }
+
+        [Test]
+        public function test_enumerable_properties_of_associative_array():void
+        {
+            //given
+            var object:Array = [];
+            object["age"] = 9;
+            object["name"] = "John";
+
+            //when
+            var enumerableProperties:Array = ObjectUtil.getEnumerableProperties(object);
+
+            //then
+            assertTrue(ArrayUtil.arrayValuesMatch(["age", "name"], enumerableProperties));
+        }
+
+        [Test]
+        public function test_enumerable_properties_of_indexed_array():void
+        {
+            //given
+            var object:Array = [9, "John"];
+
+            //when
+            var enumerableProperties:Array = ObjectUtil.getEnumerableProperties(object);
+
+            //then
+            assertTrue(ArrayUtil.arrayValuesMatch([0, 1], enumerableProperties));
+        }
+
+        [Test]
+        public function test_enumerable_properties_of_manually_indexed_array():void
+        {
+            //given
+            var object:Array = [];
+            object[3] = 9;
+            object[5] = "John";
+
+            //when
+            var enumerableProperties:Array = ObjectUtil.getEnumerableProperties(object);
+
+            //then
+            assertTrue(ArrayUtil.arrayValuesMatch([3, 5], enumerableProperties));
+        }
+
+        [Test]
+        public function test_enumerable_properties_of_sealed_class_instance():void
+        {
+            //given
+            var object:Object = new NonDynamicVO("John");
+
+            //when
+            var enumerableProperties:Array = ObjectUtil.getEnumerableProperties(object);
+
+            //then
+            assertEquals(0, enumerableProperties.length);
+        }
+
+
+        //--------------------------------------------------------------------------
+        //
+        //  valuesAreSubsetOfObject()
+        //
+        //--------------------------------------------------------------------------
+
+        [Test]
+        public function test_empty_anonymous_object_is_subset_of_empty_anonymous_instance():void
+        {
+            //then
+            assertTrue(ObjectUtil.valuesAreSubsetOfObject({}, {}));
+        }
+
+        [Test]
+        public function test_empty_anonymous_object_is_subset_of_sealed_class_instance():void
+        {
+            //then
+            assertTrue(ObjectUtil.valuesAreSubsetOfObject({}, new NonDynamicVO("John")));
+        }
+
+        [Test]
+        public function test_empty_anonymous_object_is_subset_of_dynamic_class_instance():void
+        {
+            //then
+            assertTrue(ObjectUtil.valuesAreSubsetOfObject({}, new DynamicVO("John")));
+        }
+
+        [Test]
+        public function test_anonymous_object_with_same_name_is_subset_of_similar_dynamic_class_instance():void
+        {
+            //then
+            assertTrue(ObjectUtil.valuesAreSubsetOfObject({name:"John"}, new DynamicVO("John")));
+        }
+
+        [Test]
+        public function test_anonymous_object_with_same_properties_and_values_is_subset_of_similar_dynamic_class_instance_with_one_property_manually_set():void
+        {
+            //given
+            var john:DynamicVO = new DynamicVO("John");
+            john.age = 23;
+            john.height = 6;
+
+            //then
+            assertTrue(ObjectUtil.valuesAreSubsetOfObject({name:"John", age:23}, john));
+        }
+
+        [Test]
+        public function test_anonymous_object_with_different_name_is_not_subset_of_similar_dynamic_class_instance():void
+        {
+            //then
+            assertFalse(ObjectUtil.valuesAreSubsetOfObject({name:"Max"}, new DynamicVO("John")));
+        }
+
+        [Test]
+        public function test_anonymous_object_with_same_name_is_subset_of_similar_sealed_class_instance():void
+        {
+            //then
+            assertTrue(ObjectUtil.valuesAreSubsetOfObject({name:"John"}, new NonDynamicVO("John")));
+        }
+
+        [Test]
+        public function test_anonymous_object_with_different_name_is_not_subset_of_similar_sealed_class_instance():void
+        {
+            //then
+            assertFalse(ObjectUtil.valuesAreSubsetOfObject({name:"Max"}, new NonDynamicVO("John")));
+        }
+
+        [Test]
+        public function test_anonymous_object_with_extra_property_is_not_subset_of_similar_sealed_class_instance():void
+        {
+            //then
+            assertFalse(ObjectUtil.valuesAreSubsetOfObject({name:"Max", age:23}, new NonDynamicVO("John")));
+        }
+
+        [Test]
+        public function test_sealed_object_is_a_subset_of_itself():void
+        {
+            //given
+            var max:NonDynamicVO = new NonDynamicVO("Max");
+
+            //then
+            assertTrue(ObjectUtil.valuesAreSubsetOfObject(max, max));
+        }
+
+        [Test]
+        public function test_sealed_object_is_not_a_subset_of_similar_dynamic_object():void
+        {
+            //then
+            assertFalse(ObjectUtil.valuesAreSubsetOfObject(new NonDynamicVO("Max"), {name:"Max"}));
+        }
+
+        [Test]
+        public function test_sealed_object_is_not_a_subset_of_similar_sealed_object():void
+        {
+            //then
+            assertFalse(ObjectUtil.valuesAreSubsetOfObject(new NonDynamicVO("Max"), new NonDynamicVO("Max")));
+        }
+    }
+}
+
+dynamic class DynamicVO
+{
+    public var name:String;
+
+    public function DynamicVO(name:String)
+    {
+        this.name = name;
+    }
+}
+
+class NonDynamicVO
+{
+    public var name:String;
+
+    public function NonDynamicVO(name:String)
+    {
+        this.name = name;
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/tests/mx/utils/VectorUtilTests.as b/frameworks/projects/framework/tests/mx/utils/VectorUtilTests.as
new file mode 100644
index 0000000..674ec97
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/utils/VectorUtilTests.as
@@ -0,0 +1,152 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.utils {
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.asserts.assertStrictlyEquals;
+    import org.flexunit.asserts.assertTrue;
+
+    public class VectorUtilTests {
+
+        //--------------------------------------------------------------------------
+        //
+        //  getFirstItem()
+        //
+        //--------------------------------------------------------------------------
+        [Test]
+        public function test_empty_vector():void
+        {
+            assertEquals(-1, VectorUtil.getFirstItem(new Vector.<int>()));
+        }
+
+        [Test]
+        public function test_null_parameter():void
+        {
+            assertEquals(-1, VectorUtil.getFirstItem(null));
+        }
+
+        [Test]
+        public function test_vector_with_three_elements():void
+        {
+            //given
+            var vector:Vector.<int> = new Vector.<int>();
+
+            //when
+            vector.push(3, 2, 1);
+
+            //then
+            assertEquals(3, VectorUtil.getFirstItem(vector));
+        }
+
+        [Test]
+        public function test_vector_with_three_elements_using_global_constructor():void
+        {
+            //given
+            var vector:Vector.<int> = new <int>[35, 25, 15];
+
+            //then
+            assertEquals(35, VectorUtil.getFirstItem(vector));
+        }
+
+        [Test]
+        public function test_vector_with_first_element_minus_1():void
+        {
+            //given
+            var vector:Vector.<int> = new <int>[-1, 2, 1];
+
+            //then
+            assertEquals(-1, VectorUtil.getFirstItem(vector));
+        }
+
+        [Test]
+        public function test_null_and_undefined_transformed_into_0():void
+        {
+            //given
+            var vector:Vector.<int> = new <int>[undefined, null, 11];
+
+            //then
+            assertStrictlyEquals(0, vector[0]);
+            assertStrictlyEquals(0, vector[1]);
+            assertEquals(0, VectorUtil.getFirstItem(vector));
+        }
+
+        [Test]
+        public function test_non_integers_floored():void
+        {
+            //given
+            var vector:Vector.<int> = new Vector.<int>();
+
+            //when
+            vector.push(3.74, 2.5);
+
+            //then
+            assertStrictlyEquals(3, vector[0]);
+            assertStrictlyEquals(2, vector[1]);
+            assertEquals(3, VectorUtil.getFirstItem(vector));
+        }
+
+
+        //--------------------------------------------------------------------------
+        //
+        //  toArrayInt()
+        //
+        //--------------------------------------------------------------------------
+        [Test]
+        public function test_toArrayInt_with_different_items():void
+        {
+            //given
+            var vector:Vector.<int> = new <int>[1, 2, 3];
+
+            //then
+            assertTrue(ArrayUtil.arraysMatch([1, 2, 3], VectorUtil.toArrayInt(vector)));
+        }
+
+        [Test]
+        public function test_toArrayInt_with_duplicate_items():void
+        {
+            //given
+            var vector:Vector.<int> = new <int>[2, 2, 3, 1];
+
+            //then
+            assertTrue(ArrayUtil.arraysMatch([2, 2, 3, 1], VectorUtil.toArrayInt(vector)));
+        }
+
+        [Test]
+        public function test_toArrayInt_with_0_items():void
+        {
+            //given
+            var vector:Vector.<int> = new <int>[];
+
+            //when
+            var result:Array = VectorUtil.toArrayInt(vector);
+
+            //then
+            assertEquals(0, result.length);
+        }
+
+        [Test]
+        public function test_toArrayInt_with_null():void
+        {
+            //when
+            var result:Array = VectorUtil.toArrayInt(null);
+
+            //then
+            assertEquals(0, result.length);
+        }
+    }
+}
diff --git a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
index de6cff1..add0356 100644
--- a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
+++ b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
@@ -1628,6 +1628,30 @@
         globalRect.y = Math.floor(Math.min(globalTopLeft.y, globalBottomRight.y));
         globalRect.width = Math.ceil(Math.abs(globalBottomRight.x - globalTopLeft.x));
         globalRect.height = Math.ceil(Math.abs(globalBottomRight.y - globalTopLeft.y));
+		
+		//StageText ViewPort's x and y should be in between -8192 and 8191
+		//Reset x to min of x and stage.stageWidth
+		if(globalRect.x > 0)
+		{
+			globalRect.x = Math.min(globalRect.x, stage.stageWidth);	
+		}
+		else
+		{
+			globalRect.x = Math.max(globalRect.x, 0);
+		}
+		
+		//Reset y to min of y and stage.stageHeight
+		if(globalRect.y > 0)
+		{
+			globalRect.y = Math.min(globalRect.y, stage.stageHeight);	
+		}
+		else
+		{
+			globalRect.y = Math.max(globalRect.y, 0);
+		}
+		
+		globalRect.width = Math.min(globalRect.width, stage.stageWidth);
+		globalRect.height = Math.min(globalRect.height, stage.stageHeight);
 
         return globalRect;
     }
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/BusyIndicatorSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/BusyIndicatorSkin.as
index 805887b..a4fe64f 100644
--- a/frameworks/projects/mobiletheme/src/spark/skins/ios7/BusyIndicatorSkin.as
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/BusyIndicatorSkin.as
@@ -153,6 +153,16 @@
 				symbolColorChanged = true;
 				invalidateDisplayList();
 			}
+			if (styleProp == "styleName") {
+				var value:String = getStyle("styleName");
+				
+				// We're being removed from the stage
+				if (value == null) {
+					stopRotation();
+					busyIndicatorBackground = null;
+					busyIndicator = null;
+				}
+			}
 			super.styleChanged(styleProp);
 		}
 		
@@ -206,15 +216,15 @@
 			event.updateAfterEvent();
 		}
 		
-		private var rotationMatrix:Matrix; 
 		private function rotate(obj:DisplayObject, angle:Number, aroundX:Number, aroundY:Number):void
 		{
-			rotationMatrix = new Matrix();
-			rotationMatrix.translate(-aroundX,-aroundY);
+			var center:Number = Math.min(aroundX, aroundY); // stop wobbling if not square
+			var rotationMatrix:Matrix = new Matrix();
+			rotationMatrix.translate(-center,-center);
 			rotationMatrix.rotate(Math.PI*angle/180);
-			rotationMatrix.translate(aroundX,aroundY);
+			rotationMatrix.translate(center,center);
 			obj.transform.matrix = rotationMatrix;
 		}
 		
 	}
-}
\ No newline at end of file
+}
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/BusyIndicatorSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/BusyIndicatorSkin.as
index 040bf53..f50e327 100644
--- a/frameworks/projects/mobiletheme/src/spark/skins/mobile/BusyIndicatorSkin.as
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/BusyIndicatorSkin.as
@@ -260,7 +260,7 @@
 		 */
 		private function updateSpinner(diameter:Number):void
 		{
-			var isRotating:Boolean = isRotating();
+			var isRotating:Boolean = this.isRotating();
 			
 			if (isRotating)
 				stopRotation();
diff --git a/frameworks/projects/mx/src/mx/containers/utilityClasses/BoxLayout.as b/frameworks/projects/mx/src/mx/containers/utilityClasses/BoxLayout.as
index db31dcd..3fbf0ac 100644
--- a/frameworks/projects/mx/src/mx/containers/utilityClasses/BoxLayout.as
+++ b/frameworks/projects/mx/src/mx/containers/utilityClasses/BoxLayout.as
@@ -88,7 +88,7 @@
 	{
 		var target:Container = super.target;
 
-		var isVertical:Boolean = isVertical();
+		var isVertical:Boolean = this.isVertical();
 
 		var minWidth:Number = 0;
 		var minHeight:Number = 0;
diff --git a/frameworks/projects/mx/src/mx/controls/ComboBox.as b/frameworks/projects/mx/src/mx/controls/ComboBox.as
index 8dec126..582e062 100644
--- a/frameworks/projects/mx/src/mx/controls/ComboBox.as
+++ b/frameworks/projects/mx/src/mx/controls/ComboBox.as
@@ -1388,9 +1388,7 @@
      */
     public function get selectedLabel():String
     {
-        var item:Object = selectedItem;
-
-        return itemToLabel(item);
+        return itemToLabel(selectedItem);
     }
 
     //--------------------------------------------------------------------------
diff --git a/frameworks/projects/mx/src/mx/controls/DataGrid.as b/frameworks/projects/mx/src/mx/controls/DataGrid.as
index 92dca9b..a035e70 100644
--- a/frameworks/projects/mx/src/mx/controls/DataGrid.as
+++ b/frameworks/projects/mx/src/mx/controls/DataGrid.as
@@ -5103,7 +5103,8 @@
      */
     override public function itemToLabel(data:Object):String
     {
-        return _columns[sortIndex == -1 ? 0 : sortIndex].itemToLabel(data);
+        var column:DataGridColumn = _columns[sortIndex == -1 ? 0 : sortIndex];
+        return column ? column.itemToLabel(data) : "";
     }
 
     //--------------------------------------------------------------------------
diff --git a/frameworks/projects/mx/src/mx/controls/DateField.as b/frameworks/projects/mx/src/mx/controls/DateField.as
index 6d45041..fd865b8 100644
--- a/frameworks/projects/mx/src/mx/controls/DateField.as
+++ b/frameworks/projects/mx/src/mx/controls/DateField.as
@@ -51,6 +51,7 @@
 import mx.managers.IFocusManagerComponent;
 import mx.managers.ISystemManager;
 import mx.managers.PopUpManager;
+import mx.resources.Locale;
 import mx.resources.ResourceManager;
 import mx.styles.CSSStyleDeclaration;
 import mx.styles.StyleManager;
@@ -428,6 +429,26 @@
     //
     //--------------------------------------------------------------------------
 
+	/**
+	 * Return the short three letter name of a month.
+	 * In most cases it's the first 3 letters.  
+	 * 
+	 * TODO move short names to resource bundles.
+	 */
+	 protected static function shortMonthName(monthName:String, locale:Locale, monthNames:Array):String
+	 {
+		if (locale && locale.language == "fr") {
+			if (monthName == monthNames[5]) {
+				return "JUN";
+			}
+			else if (monthName == monthNames[6]) {
+				return "JUL";	
+			}
+		}
+		
+		return monthName.substr(0,3);
+	 }
+	 
     /**
      *  Parses a String object that contains a date, and returns a Date
      *  object corresponding to the String.
@@ -475,13 +496,14 @@
 		if (valueString == null || inputFormat == null)
 			return null;
 		
-		var monthNames:Array = ResourceManager.getInstance()
-			.getStringArray("SharedResources", "monthNames");
-		
+		var monthNames:Array = ResourceManager.getInstance().getStringArray("SharedResources", "monthNames");	
 		var noMonths:int = monthNames.length;
+		var locales:Array = ResourceManager.getInstance().localeChain;
+		var locale:Locale = new Locale(locales[0]);
+		
 		for (var i:int = 0; i < noMonths; i++) {
 			valueString = valueString.replace(monthNames[i], (i+1).toString());
-			valueString = valueString.replace(monthNames[i].substr(0,3), (i+1).toString());
+			valueString = valueString.replace(shortMonthName(monthNames[i], locale, monthNames), (i+1).toString());
 		}
 		
 		length = valueString.length;
@@ -674,7 +696,9 @@
 			}
 			else if (fullMask == "MMM")
 			{
-				output += monthNames[value.getMonth()].substr(0,3);
+				var locales:Array = ResourceManager.getInstance().localeChain;
+				var locale:Locale = new Locale(locales[0]);
+				output += shortMonthName(monthNames[value.getMonth()], locale, monthNames);
 			}
 			else if (fullMask == "MMMM")
 			{	
diff --git a/frameworks/projects/mx/src/mx/controls/treeClasses/HierarchicalViewCursor.as b/frameworks/projects/mx/src/mx/controls/treeClasses/HierarchicalViewCursor.as
index 6e2951f..65e9b20 100644
--- a/frameworks/projects/mx/src/mx/controls/treeClasses/HierarchicalViewCursor.as
+++ b/frameworks/projects/mx/src/mx/controls/treeClasses/HierarchicalViewCursor.as
@@ -20,17 +20,16 @@
 package mx.controls.treeClasses
 {
 
-import flash.events.EventDispatcher;
-import flash.utils.Dictionary;
-import mx.collections.CursorBookmark;
-import mx.collections.ICollectionView;
-import mx.collections.IList;
-import mx.collections.IViewCursor;
-import mx.events.CollectionEvent;
-import mx.events.CollectionEventKind;
-import mx.utils.UIDUtil;
+	import flash.events.EventDispatcher;
+	import flash.utils.Dictionary;
 
-[ExcludeClass]
+	import mx.collections.CursorBookmark;
+	import mx.collections.ICollectionView;
+	import mx.collections.IViewCursor;
+	import mx.events.CollectionEvent;
+	import mx.events.CollectionEventKind;
+
+	[ExcludeClass]
 
 /**
  *  @private
@@ -84,11 +83,7 @@
 		modelCursor = model.createCursor();
 		
 		//check to see if the model has more than one top level items
-		if (model.length > 1)
-			more = true;
-		else 
-			more = false;
-			
+		more = model.length > 1;
     }
 
     //--------------------------------------------------------------------------
@@ -787,10 +782,7 @@
     {
 		childNodes = [];
 		modelCursor.seek(CursorBookmark.FIRST, 0);
-		if (model.length > 1)
-			more = true;
-		else
-			more = false;
+		more = model.length > 1;
         currentChildIndex = 0;
         parentNodes = [];
         childIndexStack = [];
@@ -807,7 +799,7 @@
 		childIndexStack = [];
 		_currentDepth = 1;
 		parentNodes = [];
-		var emptyBranch:Boolean = false;
+
 		//first move to the end of the top level collection
 		modelCursor.seek(CursorBookmark.LAST, 0);
 		//if its a branch and open then get children for the last item
@@ -866,7 +858,7 @@
 		var i:int;
 		var n:int;
         var node:Object;
-		var nodeParent:Object
+		var nodeParent:Object;
         var parent:Object;
         var parentStack:Array;
         var parentTable:Dictionary;
diff --git a/frameworks/projects/spark/src/spark/collections/Sort.as b/frameworks/projects/spark/src/spark/collections/Sort.as
index 0f31834..891da49 100644
--- a/frameworks/projects/spark/src/spark/collections/Sort.as
+++ b/frameworks/projects/spark/src/spark/collections/Sort.as
@@ -160,6 +160,11 @@
  *  UIComponent's <code>addStyleClient()</code> method.
  *  </li>
  *  </ul>
+ *
+ *  Note: to prevent problems like
+ *  <a href="https://issues.apache.org/jira/browse/FLEX-34853">FLEX-34853</a>
+ *  it is recommended to use SortField
+ *  instances as immutable objects (by not changing their state).
  *  
  *  @mxml
  *
diff --git a/frameworks/projects/spark/src/spark/collections/SortField.as b/frameworks/projects/spark/src/spark/collections/SortField.as
index 760b725..5b730a2 100644
--- a/frameworks/projects/spark/src/spark/collections/SortField.as
+++ b/frameworks/projects/spark/src/spark/collections/SortField.as
@@ -129,6 +129,11 @@
  *  UIComponent's <code>addStyleClient()</code> method.
  *  </li>
  *  </ul>
+ *
+ *  Note: to prevent problems like
+ *  <a href="https://issues.apache.org/jira/browse/FLEX-34853">FLEX-34853</a>
+ *  it is recommended to use SortField
+ *  instances as immutable objects (by not changing their state).
  *  
  *  @mxml
  *
diff --git a/frameworks/projects/spark/src/spark/components/DataGrid.as b/frameworks/projects/spark/src/spark/components/DataGrid.as
index fb0676f..2c44d22 100644
--- a/frameworks/projects/spark/src/spark/components/DataGrid.as
+++ b/frameworks/projects/spark/src/spark/components/DataGrid.as
@@ -1992,7 +1992,7 @@
      * 
      *  @default null.
      *
-     *  @see #dataField 
+     *  @see spark.components.gridClasses.GridColumn#dataField
      *  @see spark.components.gridClasses.IGridItemEditor
      * 
      *  @langversion 3.0
@@ -2587,7 +2587,7 @@
     }
     
     /**
-     *  @copy spark.components.Grid#invalidateTypicalItem()
+     *  @copy spark.components.Grid#invalidateTypicalItemRenderer()
      *
      *  @langversion 3.0
      *  @playerversion Flash 10
@@ -3710,7 +3710,7 @@
             var f:Function = function(g:Grid):void
             {
                 g.selectedCell = valueCopy;
-            }
+            };
             deferredGridOperations.push(f);
         }
     }    
@@ -3748,7 +3748,7 @@
             var f:Function = function(g:Grid):void
             {
                 g.selectedCells = valueCopy;
-            }
+            };
             deferredGridOperations.push(f);
         }
     }       
@@ -3830,7 +3830,7 @@
             var f:Function = function(g:Grid):void
             {
                 g.selectedIndices = valueCopy;
-            }
+            };
             deferredGridOperations.push(f);
         }
     }    
@@ -3874,7 +3874,7 @@
             var f:Function = function(g:Grid):void
             {
                 g.selectedItem = value;
-            }
+            };
             deferredGridOperations.push(f);
         }
     }    
@@ -3921,7 +3921,7 @@
             var f:Function = function(g:Grid):void
             {
                 g.selectedItems = valueCopy;
-            }
+            };
             deferredGridOperations.push(f);
         }
     }      
@@ -5423,14 +5423,11 @@
         // Cancel so another component doesn't handle this event.
         event.preventDefault(); 
         
-        var selectionChanged:Boolean = false;
-        
         if (event.shiftKey)
         {
             // The shift key-nav key combination extends the selection and 
             // updates the caret.
-            selectionChanged = 
-                extendSelection(newPosition.rowIndex, newPosition.columnIndex);
+            extendSelection(newPosition.rowIndex, newPosition.columnIndex);
         }
         else if (event.ctrlKey)
         {
@@ -5600,6 +5597,8 @@
             grid.hoverColumnIndex = event.columnIndex;
             updateHoverOnRollOver = true;
         }
+
+        removeMouseHandlersForDragStart(event);
     }
     
     /**
@@ -5620,40 +5619,15 @@
         if (rowIndex == -1 || isCellSelection && columnIndex == -1)
             return;
 
-
-        if (event.ctrlKey)
-        {
-            // ctrl-click toggles the selection and updates caret and anchor.
-            if (!toggleSelection(rowIndex, columnIndex))
-                return;
-            
-            grid.anchorRowIndex = rowIndex;
-            grid.anchorColumnIndex = columnIndex;
-        }
-        else
-        {
-            if (event.shiftKey)
-            {
-                // shift-click extends the selection and updates the caret.
-                if  (grid.selectionMode == GridSelectionMode.MULTIPLE_ROWS || grid.selectionMode == GridSelectionMode.MULTIPLE_CELLS)
-                {    
-                    if (!extendSelection(rowIndex, columnIndex))
-                        return;
-                }
-            }
-            else
-            {
-                // click sets the selection and updates the caret and anchor positions.
-                setSelectionAnchorCaret(rowIndex, columnIndex);
-            }
-        }
-
-
         if (dragEnabled && isRowSelectionMode() && selectionContainsIndex(rowIndex))
         {
             pendingSelectionOnMouseUp = true;
         }
-        
+        else
+        {
+            adjustSelection(event, rowIndex, columnIndex);
+        }
+
         // If selection is pending on mouse up then we have just moused down on
         // an item, part of an already commited selection.
         // However if we moused down on an item that's not currently selected,
@@ -5667,14 +5641,14 @@
         mouseDownRowIndex = rowIndex;
         mouseDownColumnIndex = columnIndex;
         
-        var listenForDrag:Boolean = (dragEnabled && 
+        var listenForDrag:Boolean = dragEnabled &&
             getStyle("interactionMode") == InteractionMode.MOUSE && selectedIndices && 
-            this.selectedIndices.indexOf(rowIndex) != -1);
+            this.selectedIndices.indexOf(rowIndex) != -1;
         // Handle any drag gestures that may have been started
         if (listenForDrag)
         {
             // Listen for GRID_MOUSE_DRAG.
-            // The user may have cliked on the item renderer close
+            // The user may have clicked on the item renderer close
             // to the edge of the list, and we still want to start a drag
             // operation if they move out of the list.
             grid.addEventListener(GridEvent.GRID_MOUSE_DRAG, grid_mouseDragHandler);
@@ -5698,6 +5672,30 @@
         
     }
     
+    private function adjustSelection(event:MouseEvent, rowIndex:int, columnIndex:int):void
+    {
+        if (event.ctrlKey)
+        {
+            // ctrl-click toggles the selection and updates caret and anchor.
+            if (!toggleSelection(rowIndex, columnIndex))
+                return;
+
+            grid.anchorRowIndex = rowIndex;
+            grid.anchorColumnIndex = columnIndex;
+        }
+        else if (event.shiftKey)
+        {
+            // shift-click extends the selection and updates the caret.
+            if  (grid.selectionMode == GridSelectionMode.MULTIPLE_ROWS || grid.selectionMode == GridSelectionMode.MULTIPLE_CELLS)
+                extendSelection(rowIndex, columnIndex);
+        }
+        else
+        {
+            // click sets the selection and updates the caret and anchor positions.
+            setSelectionAnchorCaret(rowIndex, columnIndex);
+        }
+    }
+
     /**
      *  @private
      *  Redispatch the grid's "caretChange" event.
@@ -6094,7 +6092,7 @@
      *  a drag-and-drop operation.
      *  Override this method to add other data to the drag source.
      * 
-     *  @param ds The DragSource object to which to add the data.
+     *  @param dragSource The DragSource object to which to add the data.
      *  
      *  @langversion 3.0
      *  @playerversion Flash 11
@@ -6189,40 +6187,11 @@
         }
     }
     
-    private function removeMouseHandlersForDragStart(event:GridEvent):void
+    private function removeMouseHandlersForDragStart(event:MouseEvent):void
     {
         // If dragging failed, but we had a pending selection, commit it here
         if (pendingSelectionOnMouseUp && !DragManager.isDragging)
-        {
-            const rowIndex:int = mouseDownRowIndex;
-            const columnIndex:int = mouseDownColumnIndex;
-            
-            if (event.ctrlKey)
-            {
-                // ctrl-click toggles the selection and updates caret and anchor.
-                if (!toggleSelection(rowIndex, columnIndex))
-                    return;
-                
-                grid.anchorRowIndex = rowIndex;
-                grid.anchorColumnIndex = columnIndex;
-            }
-            else if (event.shiftKey)
-            {
-                // shift-click extends the selection and updates the caret.
-                if  (grid.selectionMode == GridSelectionMode.MULTIPLE_ROWS || 
-                    grid.selectionMode == GridSelectionMode.MULTIPLE_CELLS)
-                {    
-                    if (!extendSelection(rowIndex, columnIndex))
-                        return;
-                }
-            }
-            else
-            {
-                // click sets the selection and updates the caret and anchor 
-                // positions.
-                setSelectionAnchorCaret(rowIndex, columnIndex);
-            }           
-        }
+            adjustSelection(event, mouseDownRowIndex, mouseDownColumnIndex);
         
         // Always clean up the flag, even if currently dragging.
         pendingSelectionOnMouseUp = false;
@@ -6371,8 +6340,8 @@
      *
      *  @param event The DragEvent object.
      * 
-     *  @see spark.layouts.LayoutBase#showDropIndicator
-     *  @see spark.layouts.LayoutBase#hideDropIndicator
+     *  @see spark.layouts.supportClasses.LayoutBase#showDropIndicator
+     *  @see spark.layouts.supportClasses.LayoutBase#hideDropIndicator
      *  
      *  @langversion 3.0
      *  @playerversion Flash 11
@@ -6428,8 +6397,8 @@
      *
      *  @param event The DragEvent object.
      *  
-     *  @see spark.layouts.LayoutBase#showDropIndicator
-     *  @see spark.layouts.LayoutBase#hideDropIndicator
+     *  @see spark.layouts.supportClasses.LayoutBase#showDropIndicator
+     *  @see spark.layouts.supportClasses.LayoutBase#hideDropIndicator
      *  
      *  @langversion 3.0
      *  @playerversion Flash 11
@@ -6479,8 +6448,8 @@
      *
      *  @param event The DragEvent object.
      *  
-     *  @see spark.layouts.LayoutBase#showDropIndicator
-     *  @see spark.layouts.LayoutBase#hideDropIndicator
+     *  @see spark.layouts.supportClasses.LayoutBase#showDropIndicator
+     *  @see spark.layouts.supportClasses.LayoutBase#hideDropIndicator
      *  
      *  @langversion 3.0
      *  @playerversion Flash 11
@@ -6502,25 +6471,7 @@
         // Destroy the dropIndicator instance
         destroyDropIndicator();
     }
-    
-    /**
-     *  @private
-     *  
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
-     */
-    private function touchInteractionStartHandler(event:TouchInteractionEvent):void
-    {
-        // cancel actual selection
-        mouseDownRowIndex = -1;
-        mouseDownColumnIndex = -1;
-        mouseDownObject = null;
-        mouseDownPoint = null;
-        pendingSelectionOnMouseUp = false;
-    }
-    
+
     /**
      *  @private
      *  Handles <code>DragEvent.DRAG_DROP events</code>. This method  hides
diff --git a/frameworks/projects/spark/src/spark/components/DropDownList.as b/frameworks/projects/spark/src/spark/components/DropDownList.as
index 2ada1c1..b6dfa01 100644
--- a/frameworks/projects/spark/src/spark/components/DropDownList.as
+++ b/frameworks/projects/spark/src/spark/components/DropDownList.as
@@ -367,15 +367,13 @@
     {
         if (labelDisplay)
         {
-            if (displayItem == undefined)
-                displayItem = selectedItem;
-            if (displayItem != null && displayItem != undefined)
-                labelDisplay.text = LabelUtil.itemToLabel(displayItem, labelField, labelFunction);
-            else
-                labelDisplay.text = prompt;
-        }   
+              if (displayItem == undefined)
+                  displayItem = selectedItem;
+              if (displayItem != null && displayItem != undefined)
+                  labelDisplay.text = LabelUtil.itemToLabel(displayItem, labelField, labelFunction);
+              else
+                  labelDisplay.text = prompt;
+		}
     }
- 
 }
-
-}
+}
\ No newline at end of file
diff --git a/frameworks/projects/spark/src/spark/components/Grid.as b/frameworks/projects/spark/src/spark/components/Grid.as
index 78b2429..5f9f0cd 100644
--- a/frameworks/projects/spark/src/spark/components/Grid.as
+++ b/frameworks/projects/spark/src/spark/components/Grid.as
@@ -2377,7 +2377,7 @@
             var f:Function = function():void
             {
                 doSetSelectedIndices(valueCopy);
-            }
+            };
             deferredOperations.push(f);  // function f() to be called by commitProperties()
             invalidateProperties();
         }
@@ -4329,7 +4329,7 @@
      *  Create and/or configure this Grid's GridViews.  We're assuming that the
      *  Grid's viewFactory, columns and dataProvider are specified.
 	 * 
-	 *  If GridVeiws are added or removed, a "gridViewsChanged" event is dispatched.
+	 *  If GridViews are added or removed, a "gridViewsChanged" event is dispatched.
      */
     private function configureGridViews():void
     {
@@ -4805,7 +4805,7 @@
             {
                 currentObject = dataProvider.getItemAt(loopingIndex);
 
-                if (currentObject.hasOwnProperty(field) == true && currentObject[field].search(pattern) != -1)
+                if (currentObject.hasOwnProperty(field) == true && pattern.test(currentObject[field]) == true)
                 {
                     return loopingIndex;
                 }
@@ -4862,7 +4862,7 @@
                 //Loop through regex patterns from the values array.
                 for (loopingValuesIndex = 0; loopingValuesIndex < valuesTotal; loopingValuesIndex++)
                 {
-                    if (currentObject[field].search(regexList[loopingValuesIndex]) != -1)
+                    if (regexList[loopingValuesIndex].test(currentObject[field]) == true)
                     {
                         matchedIndices.push(loopingDataProviderIndex);
 
diff --git a/frameworks/projects/spark/src/spark/components/GridColumnHeaderGroup.as b/frameworks/projects/spark/src/spark/components/GridColumnHeaderGroup.as
index bd62162..9d5b81d 100644
--- a/frameworks/projects/spark/src/spark/components/GridColumnHeaderGroup.as
+++ b/frameworks/projects/spark/src/spark/components/GridColumnHeaderGroup.as
@@ -1109,7 +1109,9 @@
         }
         
         const columnIndex:int = (pressSeparatorIndex != -1) ? pressSeparatorIndex : eventColumnIndex;
-        dispatchGridEvent(event, gridEventType, eventHeaderXY, columnIndex);
+	if (columnIndex != -1) {
+        	dispatchGridEvent(event, gridEventType, eventHeaderXY, columnIndex);
+	}
     }
     
     /**
@@ -1327,4 +1329,4 @@
 	}
 	
 }    
-}
\ No newline at end of file
+}
diff --git a/frameworks/projects/spark/src/spark/components/List.as b/frameworks/projects/spark/src/spark/components/List.as
index 63329dc..c457c5b 100644
--- a/frameworks/projects/spark/src/spark/components/List.as
+++ b/frameworks/projects/spark/src/spark/components/List.as
@@ -25,12 +25,10 @@
 import flash.events.Event;
 import flash.events.KeyboardEvent;
 import flash.events.MouseEvent;
-import flash.events.TimerEvent;
 import flash.geom.Point;
 import flash.system.ApplicationDomain;
 import flash.text.TextField;
 import flash.ui.Keyboard;
-import flash.utils.Timer;
 
 import mx.collections.ArrayCollection;
 import mx.collections.IList;
@@ -44,8 +42,6 @@
 import mx.core.ScrollPolicy;
 import mx.core.UIComponentGlobals;
 import mx.core.mx_internal;
-import mx.events.CollectionEvent;
-import mx.events.CollectionEventKind;
 import mx.events.DragEvent;
 import mx.events.FlexEvent;
 import mx.events.SandboxMouseEvent;
@@ -54,7 +50,7 @@
 import mx.managers.IFocusManagerComponent;
 import mx.utils.ObjectUtil;
 import mx.utils.UIDUtil;
-
+import mx.utils.VectorUtil;
 import spark.components.supportClasses.ListBase;
 import spark.core.NavigationUnit;
 import spark.events.IndexChangeEvent;
@@ -937,8 +933,9 @@
     /**
      *  @private
      *  Used internally to specify whether the selectedIndices changed programmatically or due to 
-     *  user interaction. 
-     * 
+     *  user interaction.
+     *
+     *  @param value the new indices.
      *  @param dispatchChangeEvent if true, the component will dispatch a "change" event if the
      *  value has changed. Otherwise, it will dispatch a "valueCommit" event. 
      * 
@@ -1242,7 +1239,7 @@
         }
         // Keep _proposedSelectedIndex in-sync with multiple selection properties. 
         if (!isEmpty(_proposedSelectedIndices))
-            _proposedSelectedIndex = getFirstItemValue(_proposedSelectedIndices); 
+            _proposedSelectedIndex = VectorUtil.getFirstItem(_proposedSelectedIndices);
         
         // need to store changeCaretOnSelection since super.commitSelection() may change it
         var currentChangeCaretOnSelection:Boolean = changeCaretOnSelection;
@@ -1572,19 +1569,6 @@
     
     /**
      *  @private
-     *  Given a Vector, returns the value of the first item, 
-     *  or -1 if there are no items in the Vector; 
-     */
-    private function getFirstItemValue(v:Vector.<int>):int
-    {
-        if (v && v.length > 0)
-            return v[0]; 
-        else 
-            return -1; 
-    }
-    
-    /**
-     *  @private
      *  Returns true if v is null or an empty Vector.
      */
     private function isEmpty(v:Vector.<int>):Boolean
@@ -1877,7 +1861,7 @@
             return;
         
         // Handle the fixup of selection
-        var newIndex:int
+        var newIndex:int;
         if (event.currentTarget is IItemRenderer)
             newIndex = IItemRenderer(event.currentTarget).itemIndex;
         else
@@ -2024,7 +2008,7 @@
                     (mouseDownObject is DisplayObjectContainer && 
                         DisplayObjectContainer(mouseDownObject).contains(event.target as DisplayObject)));
                 
-                // check to make sure they clciked on an item and selection should change
+                // check to make sure they clicked on an item and selection should change
                 if (selectionChange)
                 {
                     // now handle the cases where the item is being selected or de-selected
@@ -2684,7 +2668,7 @@
             // an "caretChange" event to update any bindings and update the 
             // caretIndex backing variable. 
             var oldIndex:Number = caretIndex; 
-            _caretIndex = getFirstItemValue(newInterval);
+            _caretIndex = VectorUtil.getFirstItem(newInterval);
             e = new IndexChangeEvent(IndexChangeEvent.CARET_CHANGE); 
             e.oldIndex = oldIndex; 
             e.newIndex = caretIndex; 
@@ -2706,7 +2690,7 @@
         
         var oldIndices:Vector.<int> = selectedIndices;  
         _selectedIndices = newInterval;
-        _selectedIndex = getFirstItemValue(newInterval);
+        _selectedIndex = VectorUtil.getFirstItem(newInterval);
         // If the selection has actually changed, trigger a pass to 
         // commitProperties where a change event will be 
         // fired to update any bindings to selection properties. 
@@ -2797,7 +2781,7 @@
      */
     mx_internal function findStringLoop(str:String, startIndex:int, stopIndex:int):Number
     {
-        // Try to find the item based on the start and stop indices. 
+        // Try to find the item based on the start and stop indices
         for (startIndex; startIndex != stopIndex; startIndex++)
         {
             var itmStr:String = itemToLabel(dataProvider.getItemAt(startIndex));
@@ -2828,7 +2812,7 @@
         if (isEditableTarget(event.target))
             return;
         
-        var touchMode:Boolean = (getStyle("interactionMode") == InteractionMode.TOUCH);
+        var touchMode:Boolean = getStyle("interactionMode") == InteractionMode.TOUCH;
         
         // 1. Was the space bar hit? or was the enter key hit and we're in 5-way mode
         // Hitting the space bar means the current caret item, 
diff --git a/frameworks/projects/spark/src/spark/components/gridClasses/GridColumn.as b/frameworks/projects/spark/src/spark/components/gridClasses/GridColumn.as
index afb9047..f3812e2 100644
--- a/frameworks/projects/spark/src/spark/components/gridClasses/GridColumn.as
+++ b/frameworks/projects/spark/src/spark/components/gridClasses/GridColumn.as
@@ -1005,6 +1005,7 @@
     private var _width:Number = NaN;
     
     [Bindable("widthChanged")]    
+    [PercentProxy("percentWidth")]
     
     /**
      *  The width of this column in pixels. 
@@ -1151,7 +1152,6 @@
     }
     
     [Inspectable(category="General")]
-    [PercentProxy("percentWidth")]
     
     /**
      *  @private
@@ -1822,4 +1822,4 @@
         }
     }
 }
-}
\ No newline at end of file
+}
diff --git a/frameworks/projects/spark/src/spark/components/gridClasses/GridViewLayout.as b/frameworks/projects/spark/src/spark/components/gridClasses/GridViewLayout.as
index 4dbaf11..9c072b7 100644
--- a/frameworks/projects/spark/src/spark/components/gridClasses/GridViewLayout.as
+++ b/frameworks/projects/spark/src/spark/components/gridClasses/GridViewLayout.as
@@ -685,7 +685,7 @@
         // so it could be seen when the indicator bounds are below the last row.
         // The issue is there may not be any space below the last row and the drop
         // indicator would not be visible if it started at the top of the next cell.
-        if (dropLocation.dropPoint.y > (bounds.top + (bounds.height * 1) / 2))
+        if (dropLocation.dropPoint.y > (bounds.top + bounds.height / 2))
             return new Rectangle(2, bounds.bottom - 2, bounds.width -4, 4);
         
         return new Rectangle(2, Math.max(0, bounds.y - 2), bounds.width - 4, 4);
@@ -708,7 +708,7 @@
         
         clearSelectionIndicators();
         
-        freeGridElement(hoverIndicator)
+        freeGridElement(hoverIndicator);
         hoverIndicator = null;
         
         freeGridElement(caretIndicator);
@@ -844,7 +844,7 @@
             if (vspChanged && hspChanged)
                 reason = "bothScrollPositions";
             else if (vspChanged)
-                reason = "verticalScrollPosition"
+                reason = "verticalScrollPosition";
             else if (hspChanged)
                 reason = "horizontalScrollPosition";
             
@@ -1389,7 +1389,6 @@
             return;  
         
         const columnCount:int = getColumnsLength();
-        const columnGap:int = gridDimensionsView.columnGap;
         const requestedColumnCount:int = grid.requestedColumnCount;  // TBD GridView...
         var measuredColumnCount:int = 0;
         
@@ -1673,7 +1672,7 @@
                 var colWidth:Number = gridDimensionsView.getColumnWidth(colIndex);
                 layoutItemRenderer(renderer, cellX, cellY, colWidth, rowHeight);                
                 
-                var preferredRowHeight:Number = renderer.getPreferredBoundsHeight()
+                var preferredRowHeight:Number = renderer.getPreferredBoundsHeight();
                 gridDimensionsView.setCellHeight(rowIndex, colIndex, preferredRowHeight);
                 cellX += colWidth + colGap;
             }
@@ -2438,9 +2437,6 @@
         return indicator;
     }
 
-    private var mouseXOffset:Number = 0;
-    private var mouseYOffset:Number = 0;
-       
     private function layoutHoverIndicator(layer:GridLayer):void
     {
         const rowIndex:int = gridRowIndexToViewIndex(grid.hoverRowIndex);
diff --git a/frameworks/projects/spark/src/spark/components/supportClasses/ButtonBase.as b/frameworks/projects/spark/src/spark/components/supportClasses/ButtonBase.as
index 26bdf02..df08bdf 100644
--- a/frameworks/projects/spark/src/spark/components/supportClasses/ButtonBase.as
+++ b/frameworks/projects/spark/src/spark/components/supportClasses/ButtonBase.as
@@ -1345,7 +1345,7 @@
                         // There are two possibilities for being here:
                         //    1) mouseCaptured wasn't set to true (meaning this is the first click)
                         //    2) mouseCaptured was true (meaning a click operation hadn't finished 
-                        //       and we find ourselves in here again--perhaps it was a doublet tap).
+                        //       and we find ourselves in here again--perhaps it was a double tap).
                         // In either case, let's make sure that down state shows up for a little bit
                         // before going back to the up state.
                         
diff --git a/frameworks/projects/spark/src/spark/components/supportClasses/DropDownController.as b/frameworks/projects/spark/src/spark/components/supportClasses/DropDownController.as
index 9ac003e..8c7fe08 100644
--- a/frameworks/projects/spark/src/spark/components/supportClasses/DropDownController.as
+++ b/frameworks/projects/spark/src/spark/components/supportClasses/DropDownController.as
@@ -607,14 +607,6 @@
             if (openButton && target && openButton.contains(target))
                 return;
 			
-			// don't close if something just been selected in a DropDownList
-			if (target is IUIComponent)
-			{
-                var document:Object = (target as IUIComponent).document;
-                if (("hostComponent" in document) && document.hostComponent is DropDownList)
-			        return;
-            }
-
             if (hitAreaAdditions != null)
             {
 				var length:int = hitAreaAdditions.length;
diff --git a/frameworks/projects/spark/src/spark/components/supportClasses/ListBase.as b/frameworks/projects/spark/src/spark/components/supportClasses/ListBase.as
index c72d4d5..e700d0d 100644
--- a/frameworks/projects/spark/src/spark/components/supportClasses/ListBase.as
+++ b/frameworks/projects/spark/src/spark/components/supportClasses/ListBase.as
@@ -1311,7 +1311,7 @@
             {
                 currentObject = dataProvider.getItemAt(loopingIndex);
 
-                if (currentObject.hasOwnProperty(field) == true && currentObject[field].search(pattern) != -1)
+                if (currentObject.hasOwnProperty(field) == true && pattern.test(currentObject[field]) == true)
                 {
                     return loopingIndex;
                 }
@@ -1368,7 +1368,7 @@
                 //Loop through regex patterns from the values array.
                 for (loopingValuesIndex = 0; loopingValuesIndex < valuesTotal; loopingValuesIndex++)
                 {
-                    if (currentObject[field].search(regexList[loopingValuesIndex]) != -1)
+                    if (regexList[loopingValuesIndex].test(currentObject[field]) == true)
                     {
                         matchedIndices.push(loopingDataProviderIndex);
 
diff --git a/frameworks/projects/spark/src/spark/components/supportClasses/SkinnableComponent.as b/frameworks/projects/spark/src/spark/components/supportClasses/SkinnableComponent.as
index 2a8c730..2fceebf 100644
--- a/frameworks/projects/spark/src/spark/components/supportClasses/SkinnableComponent.as
+++ b/frameworks/projects/spark/src/spark/components/supportClasses/SkinnableComponent.as
@@ -216,7 +216,7 @@
     
     /**
      *  The instance of the skin class for this component instance. 
-     *  This is a read-only property that gets set automomatically when Flex 
+     *  This is a read-only property that gets set automatically when Flex
      *  calls the <code>attachSkin()</code> method.
      *  
      *  @langversion 3.0
diff --git a/frameworks/projects/spark/src/spark/layouts/ConstraintLayout.as b/frameworks/projects/spark/src/spark/layouts/ConstraintLayout.as
index 64db42d..d698103 100644
--- a/frameworks/projects/spark/src/spark/layouts/ConstraintLayout.as
+++ b/frameworks/projects/spark/src/spark/layouts/ConstraintLayout.as
@@ -83,7 +83,7 @@
  *    and <code>right</code> constraints.</li>
  * 
  *    <li>If the element has both <code>top</code> and <code>bottom</code> constraints, 
- *    it's height is set to be the container's height minus the <code>top</code> 
+ *    it's height is set to be the container's height minus the <code>top</code>
  *    and <code>bottom</code> constraints.</li>
  *
  *    <li>The element is set to its preferred width and/or height.</li>
@@ -96,12 +96,12 @@
  *    the vertical direction such that its <code>baselinePosition</code> (usually the base line
  *    of its first line of text) is aligned with <code>baseline</code> constraint.</li>
  *
- *    <li>If element's <code>top</code> or <code>left</code> constraints 
+ *    <li>If element's <code>top</code> or <code>left</code> constraints
  *    are specified, then the element is
  *    positioned such that the top-left corner of the element's layout bounds is
  *    offset from the top-left corner of the container by the specified values.</li>
  *
- *    <li>If element's <code>bottom</code> or <code>right</code> constraints are specified, 
+ *    <li>If element's <code>bottom</code> or <code>right</code> constraints are specified,
  *    then the element is positioned such that the bottom-right corner 
  *    of the element's layout bounds is
  *    offset from the bottom-right corner of the container by the specified values.</li>
@@ -121,6 +121,10 @@
  */
 public class ConstraintLayout extends LayoutBase
 {
+
+    //See FLEX-33311 for more details on why this is used
+    private var constraintCacheNeeded:int = 0;
+
     //--------------------------------------------------------------------------
     //
     //  Class methods
@@ -1604,7 +1608,9 @@
         var layoutTarget:GroupBase = target;
         if (!layoutTarget)
             return;
-        
+
+        constraintCacheNeeded++;
+
         var count:Number = layoutTarget.numElements;
         var layoutElement:ILayoutElement;
         
@@ -1614,7 +1620,7 @@
         // Populate rowBaselines with baseline information from rows.
         var n:int = _constraintRows.length;
         var row:ConstraintRow;
-        var obj:Object = {};
+
         if (rowBaselines == null)
             rowBaselines = new Vector.<Array>();
         else
@@ -1641,6 +1647,7 @@
         }
         
         this.constraintCache = cache;
+        constraintCacheNeeded--;
     }
     
     /**
@@ -1833,12 +1840,15 @@
      */
     private function clearConstraintCache():void
     {
-        colSpanElements = null;
-        rowSpanElements = null;
-        otherElements = null;
-        rowBaselines = null;
-        rowMaxAscents = null;
-        constraintCache = null;
+        if(!constraintCacheNeeded)
+        {
+            colSpanElements = null;
+            rowSpanElements = null;
+            otherElements = null;
+            rowBaselines = null;
+            rowMaxAscents = null;
+            constraintCache = null;
+        }
     }
 }
 }
diff --git a/frameworks/projects/spark/src/spark/skins/spark/BusyIndicatorSkin.as b/frameworks/projects/spark/src/spark/skins/spark/BusyIndicatorSkin.as
index c1c98e5..b0feef0 100644
--- a/frameworks/projects/spark/src/spark/skins/spark/BusyIndicatorSkin.as
+++ b/frameworks/projects/spark/src/spark/skins/spark/BusyIndicatorSkin.as
@@ -239,6 +239,18 @@
 				symbolColorChanged = true;
 				invalidateDisplayList();
 			}
+			
+			if (styleProp == "styleName") {
+				var value:String = getStyle("styleName");
+				
+				// We're being removed from the stage
+				if (value == null) {
+					stopRotation();
+					busyIndicatorBackground = null;
+					busyIndicator = null;
+				}
+			}
+			
 			super.styleChanged(styleProp);
 		}
 		
@@ -326,16 +338,17 @@
 			event.updateAfterEvent();
 		}
 		
-		private var rotationMatrix:Matrix; 
 		private function rotate(obj:DisplayObject, angle:Number, aroundX:Number, aroundY:Number):void
 		{
-			rotationMatrix = new Matrix();
-			rotationMatrix.translate(-aroundX,-aroundY);
+			var center:Number = Math.min(aroundX, aroundY); // stop wobbling if not square
+			var rotationMatrix:Matrix = new Matrix();
+			rotationMatrix.translate(-center,-center);
 			rotationMatrix.rotate(Math.PI*angle/180);
-			rotationMatrix.translate(aroundX,aroundY);
+			rotationMatrix.translate(center,center);
 			obj.transform.matrix = rotationMatrix;
 		}
 		
 	}
 }
 
+
diff --git a/frameworks/projects/spark/src/spark/utils/LabelUtil.as b/frameworks/projects/spark/src/spark/utils/LabelUtil.as
index 43a9d96..5de7334 100644
--- a/frameworks/projects/spark/src/spark/utils/LabelUtil.as
+++ b/frameworks/projects/spark/src/spark/utils/LabelUtil.as
@@ -70,8 +70,7 @@
      *  @playerversion AIR 1.5
      *  @productversion Flex 4
      */
-    public static function itemToLabel(item:Object, labelField:String=null, 
-        labelFunction:Function=null):String
+    public static function itemToLabel(item:Object, labelField:String = null, labelFunction:Function = null):String
     {
         if (labelFunction != null)
             return labelFunction(item);
@@ -127,4 +126,4 @@
     }
 }
 
-}
+}
\ No newline at end of file
diff --git a/frameworks/projects/spark/src/spark/utils/MouseEventUtil.as b/frameworks/projects/spark/src/spark/utils/MouseEventUtil.as
index 97fc04f..ca6f08c 100644
--- a/frameworks/projects/spark/src/spark/utils/MouseEventUtil.as
+++ b/frameworks/projects/spark/src/spark/utils/MouseEventUtil.as
@@ -118,7 +118,7 @@
                         target.systemManager.deployMouseShields(false);
                         break;
                 }
-            }
+            };
             target.addEventListener(MouseEvent.MOUSE_DOWN, f);
             target.addEventListener("removeHandler", f);
         }    
diff --git a/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_26808_Tests.as b/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_26808_Tests.as
new file mode 100644
index 0000000..1480448
--- /dev/null
+++ b/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_26808_Tests.as
@@ -0,0 +1,324 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 spark.components {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+    import flash.events.MouseEvent;
+
+    import mx.collections.ArrayCollection;
+    import mx.collections.ArrayList;
+    import mx.collections.IList;
+    import mx.collections.ListCollectionView;
+    import mx.utils.ArrayUtil;
+    import mx.utils.VectorUtil;
+
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.asserts.assertFalse;
+    import org.flexunit.asserts.assertNull;
+    import org.flexunit.asserts.assertTrue;
+    import org.flexunit.async.Async;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    import spark.components.gridClasses.GridColumn;
+    import spark.components.gridClasses.GridSelectionMode;
+    import spark.events.GridEvent;
+
+    public class DataGrid_FLEX_26808_Tests
+    {
+        private static const NO_ENTER_FRAMES_TO_ALLOW:int = 2;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+        private static var noEnterFramesRemaining:int = NaN;
+        private var _sut:DataGridInspectable;
+        private var _firstObject:FLEX_26808_VO;
+        private var _secondObject:FLEX_26808_VO;
+
+        [Before]
+        public function setUp():void
+        {
+            _sut = new DataGridInspectable();
+
+            _sut.dragEnabled = true;
+            _sut.selectionMode = GridSelectionMode.MULTIPLE_ROWS;
+            _sut.columns = new ArrayCollection([new GridColumn("name")]);
+            _sut.width = 200;
+            _sut.height = 200;
+
+            const tenObjects:IList = generateVOs(10);
+            _firstObject = tenObjects.getItemAt(0) as FLEX_26808_VO;
+            _secondObject = tenObjects.getItemAt(1) as FLEX_26808_VO;
+            const dataProvider:ListCollectionView = new ListCollectionView(tenObjects);
+            _sut.dataProvider = dataProvider;
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            _sut = null;
+            noEnterFramesRemaining = NaN;
+        }
+
+        [Test(async, timeout=1000)]
+        public function test_ctrl_click_removes_selected_item():void
+        {
+            //when
+            UIImpersonator.addChild(_sut);
+
+            //then
+            assertNull(_sut.selectedItem);
+
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, test_programmatic_selection_and_event_deselection_with_ctrl_click, 800);
+        }
+
+        private function test_programmatic_selection_and_event_deselection_with_ctrl_click(event:Event, passThroughData:Object):void
+        {
+            function onGridMouseDown(event:GridEvent):void
+            {
+                assertEquals(0, event.rowIndex);
+                assertTrue(event.ctrlKey);
+            }
+
+            //when
+            _sut.setSelectedIndex(0);
+
+            //then
+            assertEquals(_firstObject, _sut.selectedItem);
+
+            //given
+            const mouseDown:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, 5, 5, null, true, false, false);
+            const mouseUp:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP, true, false, 5, 5, null, true, false, false);
+            _sut.addEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown);
+
+            //when - Ctrl+Click on first item to deselect it
+            _sut.grid.dispatchEvent(mouseDown);
+            _sut.grid.dispatchEvent(mouseUp);
+
+            //then
+            assertEquals(1, _sut.commitInteractiveSelection_calls);
+            assertNull("The selection should have been removed due to Ctrl+Click!", _sut.selectedItem);
+            _sut.removeEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown);
+        }
+
+        [Test(async, timeout=1000)]
+        public function test_ctrl_click_on_another_item_adds_it_to_selection():void
+        {
+            //when
+            UIImpersonator.addChild(_sut);
+
+            //then
+            assertNull(_sut.selectedItem);
+
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, test_programmatic_selection_and_event_deselection_with_ctrl_click, 800);
+        }
+
+        private function test_manual_multiple_selection_with_ctrl_click(event:Event, passThroughData:Object):void
+        {
+            function onGridMouseDown(event:GridEvent):void
+            {
+                assertTrue("The clicks should only happen on the first and second row!", event.rowIndex == 0 || event.rowIndex == 1);
+                assertTrue("Ctrl key should have been pressed on the second row!", event.rowIndex == 1 ? event.ctrlKey : true);
+            }
+
+            //given
+            const mouseDownOnFirstItem:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, 5, 5, null, false, false, false);
+            const mouseUpOnFirstItem:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP, true, false, 5, 5, null, false, false, false);
+            const mouseDownOnSecondItemWithCtrl:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, 5, _sut.rowHeight + 2, null, false, false, false);
+            const mouseUpOnSecondItemWithCtrl:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP, true, false, 5, _sut.rowHeight + 2, null, false, false, false);
+
+            //when - first click on first row to select it
+            _sut.addEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown);
+            _sut.grid.dispatchEvent(mouseDownOnFirstItem);
+            _sut.grid.dispatchEvent(mouseUpOnFirstItem);
+
+            //then
+            assertEquals(_firstObject, _sut.selectedItem);
+
+            //when - ctrl+click on second item to add it to the selection
+            _sut.grid.dispatchEvent(mouseDownOnSecondItemWithCtrl);
+            _sut.grid.dispatchEvent(mouseUpOnSecondItemWithCtrl);
+
+            //then
+            assertTrue(ArrayUtil.arraysMatch([_firstObject, _secondObject], VectorUtil.toArrayObject(_sut.selectedItems)));
+            _sut.removeEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown);
+        }
+
+        [Test(async, timeout=1000)]
+        public function test_dragging_maintains_programmatically_selected_items():void
+        {
+            //when
+            UIImpersonator.addChild(_sut);
+
+            //then
+            assertNull(_sut.selectedItem);
+
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, test_programmatic_selection_and_dragging, 800);
+        }
+
+        private function test_programmatic_selection_and_dragging(event:Event, passThroughData:Object):void
+        {
+            function onGridMouseDown(event:GridEvent):void
+            {
+                assertEquals(0, event.rowIndex);
+                assertFalse(event.ctrlKey);
+            }
+
+            //when
+            _sut.selectedIndices = new <int>[0, 1];
+
+            //then
+            assertTrue("The first two objects should be selected", ArrayUtil.arraysMatch([_firstObject, _secondObject], VectorUtil.toArrayObject(_sut.selectedItems)));
+
+            //given
+            const mouseDown:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, 5, 5, null, false, false, false);
+            const mouseMove:MouseEvent = new MouseEvent(MouseEvent.MOUSE_MOVE, true, false, 5, 6, null, false, false, false);
+            _sut.addEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown);
+
+            //when - Mouse down and then mouse move to simulate drag
+            _sut.grid.dispatchEvent(mouseDown);
+            _sut.grid.dispatchEvent(mouseMove);
+
+            //then
+            assertTrue(ArrayUtil.arraysMatch([_firstObject, _secondObject], VectorUtil.toArrayObject(_sut.selectedItems)));
+            _sut.removeEventListener(GridEvent.GRID_MOUSE_DOWN, onGridMouseDown);
+        }
+
+        [Test(async, timeout=1300)]
+        public function test_dragging_maintains_manually_selected_items():void
+        {
+            //when
+            UIImpersonator.addChild(_sut);
+
+            //then
+            assertNull(_sut.selectedItem);
+
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, test_programmatic_selection_and_dragging, 1200);
+        }
+
+        private function test_manual_selection_of_two_items_and_dragging(event:Event, passThroughData:Object):void
+        {
+            //given
+            const mouseDown:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false, 5, 5, null, false, false, false);
+            const mouseMove:MouseEvent = new MouseEvent(MouseEvent.MOUSE_MOVE, true, false, 5, 6, null, false, false, false);
+
+            //when
+            test_manual_multiple_selection_with_ctrl_click(event, passThroughData);
+            _sut.grid.dispatchEvent(mouseDown);
+            _sut.grid.dispatchEvent(mouseMove);
+
+            //then
+            assertTrue(ArrayUtil.arraysMatch([_firstObject, _secondObject], VectorUtil.toArrayObject(_sut.selectedItems)));
+        }
+
+        private static function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesRemaining)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+
+        private static function generateVOs(no:int, reverse:Boolean = false):IList
+        {
+            return generateObjects(no, reverse, generateOneObject);
+        }
+
+        private static function generateObjects(no:int, reverse:Boolean, generator:Function):IList
+        {
+            var result:Array = [];
+            for(var i:int = 0; i < no; i++)
+            {
+                result.push(generator(i));
+            }
+
+            if(reverse)
+                result.reverse();
+
+            return new ArrayList(result);
+        }
+
+        private static function generateOneObject(i:Number):FLEX_26808_VO
+        {
+            return new FLEX_26808_VO(i, "Object", "Street");
+        }
+    }
+}
+
+import spark.components.DataGrid;
+import spark.skins.spark.DataGridSkin;
+
+[Bindable]
+class FLEX_26808_VO
+{
+    public var name:String;
+    public var address:FLEX_26808_AddressVO;
+    public var index:Number;
+
+    public function FLEX_26808_VO(index:Number, namePrefix:String, streetPrefix:String)
+    {
+        this.index = index;
+        this.name = namePrefix + index;
+        this.address = new FLEX_26808_AddressVO(streetPrefix + index, Math.floor(index), new Date(2000 + Math.floor(index), Math.floor(index), 1, 0, 0, 0, 1));
+    }
+}
+
+[Bindable]
+class FLEX_26808_AddressVO
+{
+    public var street:String;
+    public var houseNumber:int;
+    public var dateMovedIn:Date;
+
+    public function FLEX_26808_AddressVO(street:String, houseNumber:int, dateMovedIn:Date)
+    {
+        this.street = street;
+        this.houseNumber = houseNumber;
+        this.dateMovedIn = dateMovedIn;
+    }
+}
+
+class DataGridInspectable extends DataGrid
+{
+    public function DataGridInspectable()
+    {
+        super();
+        this.setStyle("skinClass", DataGridSkin);
+    }
+
+    public var commitInteractiveSelection_calls:int = 0;
+
+    override protected function commitInteractiveSelection(selectionEventKind:String,
+                                                           rowIndex:int,
+                                                           columnIndex:int,
+                                                           rowCount:int = 1,
+                                                           columnCount:int = 1):Boolean
+
+    {
+        commitInteractiveSelection_calls++;
+        return super.commitInteractiveSelection(selectionEventKind, rowIndex, columnIndex, rowCount, columnCount);
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_34837_Tests.as b/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_34837_Tests.as
index 5696429..7492f85 100644
--- a/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_34837_Tests.as
+++ b/frameworks/projects/spark/tests/spark/components/DataGrid_FLEX_34837_Tests.as
@@ -37,6 +37,8 @@
         public function setUp():void
         {
             _sut = new DataGrid();
+            _sut.width = 200;
+            _sut.height = 200;
         }
 
         [After]
diff --git a/frameworks/projects/spark/tests/spark/components/DropDownList_FLEX_35126_Tests.as b/frameworks/projects/spark/tests/spark/components/DropDownList_FLEX_35126_Tests.as
new file mode 100644
index 0000000..82ab10e
--- /dev/null
+++ b/frameworks/projects/spark/tests/spark/components/DropDownList_FLEX_35126_Tests.as
@@ -0,0 +1,182 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 spark.components {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+    import flash.events.MouseEvent;
+
+    import mx.events.FlexMouseEvent;
+
+    import org.flexunit.assertThat;
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.asserts.assertFalse;
+    import org.flexunit.asserts.assertTrue;
+    import org.flexunit.async.Async;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    public class DropDownList_FLEX_35126_Tests
+    {
+        private static const NO_ENTER_FRAMES_TO_ALLOW:int = 2;
+        private static var noEnterFramesRemaining:int = NaN;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        private static var _sut:DropDownListInspectable;
+        private static var _dropDownListOnStage:DropDownList;
+        private var _popUp:PopUpAnchor;
+
+        [Before]
+        public function setUp():void
+        {
+            _popUp = new PopUpAnchor();
+            _popUp.displayPopUp = true;
+
+            _sut = new DropDownListInspectable();
+            _sut.addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, onMouseDownOutsidePopup);
+
+            _popUp.popUp = _sut;
+
+            _dropDownListOnStage = new DropDownList();
+        }
+
+        private function onMouseDownOutsidePopup(event:FlexMouseEvent):void
+        {
+            _popUp.displayPopUp = false;
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            _sut = null;
+            _popUp = null;
+            _dropDownListOnStage = null;
+        }
+
+        [Test(async, timeout=1000)]
+        public function test_dropdown_doesnt_close_when_item_selected_from_DropDownList():void
+        {
+            //given
+            _popUp.width = _sut.width = 150;
+            _dropDownListOnStage.x = 200;
+            UIImpersonator.addChild(_popUp);
+            UIImpersonator.addChild(_dropDownListOnStage);
+
+            //then
+            assertTrue(_popUp.displayPopUp);
+            assertThat(isNaN(_sut.dropDownController_.rollOverOpenDelay));
+
+            //when
+            _sut.openButton.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OVER));
+            _sut.openButton.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN));
+
+            //then - wait a frame
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_open_drop_down, 300);
+        }
+
+        private function then_open_drop_down(event:Event, passThroughData:Object):void
+        {
+            //when - MOUSE_UP to signify the lifting of the mouse button
+            _sut.openButton.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));
+
+            //then
+            assertTrue(_sut.isDropDownOpen);
+
+            //when - MOUSE_DOWN on the stage dropDownList
+            _dropDownListOnStage.openButton.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OVER));
+            _dropDownListOnStage.openButton.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN));
+
+            //then - wait a frame
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_select_item_in_drop_down, 300);
+        }
+
+        private function then_select_item_in_drop_down(event:Event, passThroughData:Object):void
+        {
+            //when - MOUSE_UP to signify the lifting of the mouse button
+            _dropDownListOnStage.openButton.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));
+
+            //then
+            assertFalse("PopUpAnchor should be closed", _popUp.displayPopUp);
+            assertTrue(_dropDownListOnStage.isDropDownOpen);
+
+            //when - second click on stage dropdown
+            _dropDownListOnStage.openButton.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OVER));
+            _dropDownListOnStage.openButton.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN));
+
+            //then
+            assertEquals("The DropDownController should have closed the DropDownList at the first click on the other DropDownList, and stopped listening to mouse events", 1, _sut.noReactionsToOutsideClick);
+        }
+
+        private static function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesRemaining)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+    }
+}
+
+import flash.events.Event;
+
+import mx.core.mx_internal;
+
+import spark.components.DropDownList;
+import spark.components.supportClasses.DropDownController;
+import spark.skins.spark.DropDownListSkin;
+
+use namespace mx_internal;
+
+class DropDownListInspectable extends DropDownList
+{
+    public var noReactionsToOutsideClick:int = 0;
+
+    public function DropDownListInspectable()
+    {
+        super();
+        this.setStyle("skinClass", DropDownListSkin);
+        this.dropDownController = new DropDownControllerInspectable();
+        this.dropDownController.addEventListener(DropDownControllerInspectable.REACT_TO_MOUSE_DOWN, onControllerReactedToMouseDown);
+    }
+
+    private function onControllerReactedToMouseDown(event:Event):void
+    {
+        noReactionsToOutsideClick++;
+    }
+
+    public function get dropDownController_():DropDownController
+    {
+        return this.dropDownController;
+    }
+}
+
+class DropDownControllerInspectable extends DropDownController
+{
+    public static const REACT_TO_MOUSE_DOWN:String = "justReactedToMouseDown";
+
+    override mx_internal function systemManager_mouseDownHandler(event:Event):void
+    {
+        super.mx_internal::systemManager_mouseDownHandler(event);
+        dispatchEvent(new Event(REACT_TO_MOUSE_DOWN));
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/spark/tests/spark/components/supportClasses/CalloutButton_FLEX_34088_Tests.as b/frameworks/projects/spark/tests/spark/components/supportClasses/CalloutButton_FLEX_34088_Tests.as
new file mode 100644
index 0000000..d1c68b3
--- /dev/null
+++ b/frameworks/projects/spark/tests/spark/components/supportClasses/CalloutButton_FLEX_34088_Tests.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 spark.components.supportClasses {
+    import flash.display.DisplayObject;
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+    import flash.events.MouseEvent;
+
+    import mx.collections.ArrayCollection;
+
+    import org.flexunit.asserts.assertFalse;
+    import org.flexunit.asserts.assertTrue;
+    import org.flexunit.async.Async;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    import spark.components.CalloutButton;
+    import spark.components.DropDownList;
+
+    public class CalloutButton_FLEX_34088_Tests
+    {
+        private static const NO_ENTER_FRAMES_TO_ALLOW:int = 1;
+        private static var noEnterFramesRemaining:int = NaN;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        private static var _sut:CalloutButton;
+        private static var _dropDownList:DropDownListInspectable;
+
+        [Before]
+        public function setUp():void
+        {
+            _sut = new CalloutButton();
+
+            _dropDownList = new DropDownListInspectable();
+            _dropDownList.dataProvider = new ArrayCollection([{label:"Hello"}, {label:"World"}]);
+            _sut.calloutContent = [_dropDownList];
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            _sut = null;
+        }
+
+        [Test(async, timeout=1000)]
+        public function test_dropdown_doesnt_close_when_item_selected_from_DropDownList():void
+        {
+            //given
+            UIImpersonator.addChild(_sut);
+
+            //when
+            _sut.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OVER));
+            _sut.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN));
+
+            //then - wait a frame
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_open_drop_down, 300);
+        }
+
+        private function then_open_drop_down(event:Event, passThroughData:Object):void
+        {
+            //then
+            assertTrue(_sut.isDropDownOpen);
+
+            //when
+            _dropDownList.openButton.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OVER));
+            _dropDownList.openButton.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN));
+
+            //then - wait a frame
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_select_item_in_drop_down, 300);
+        }
+
+        private function then_select_item_in_drop_down(event:Event, passThroughData:Object):void
+        {
+            //then
+            assertTrue("DropDownList should be open", _dropDownList.isDropDownOpen);
+            assertTrue("DropDownList should be open", _dropDownList.owns(DisplayObject(_dropDownList.lastRenderer)));
+
+            //when
+            _dropDownList.lastRenderer.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN));
+
+            //then - wait a frame
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_assert_callout_still_open, 300);
+        }
+
+        private function then_assert_callout_still_open(event:Event, passThroughData:Object):void
+        {
+            //then
+            assertFalse(_dropDownList.isDropDownOpen);
+            assertTrue("Callout should still be open", _sut.isDropDownOpen);
+        }
+
+        private static function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesRemaining)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+    }
+}
+
+import mx.core.IVisualElement;
+
+import spark.components.DropDownList;
+import spark.events.RendererExistenceEvent;
+import spark.skins.spark.DropDownListSkin;
+
+class DropDownListInspectable extends DropDownList
+{
+    public var lastRenderer:IVisualElement;
+
+    public function DropDownListInspectable()
+    {
+        super();
+        this.setStyle("skinClass", DropDownListSkin);
+    }
+
+    override protected function dataGroup_rendererAddHandler(event:RendererExistenceEvent):void
+    {
+        lastRenderer = event.renderer;
+        super.dataGroup_rendererAddHandler(event);
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/spark/tests/spark/layouts/ConstraintLayout_FLEX_33311_Tests.as b/frameworks/projects/spark/tests/spark/layouts/ConstraintLayout_FLEX_33311_Tests.as
new file mode 100644
index 0000000..2519591
--- /dev/null
+++ b/frameworks/projects/spark/tests/spark/layouts/ConstraintLayout_FLEX_33311_Tests.as
@@ -0,0 +1,139 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 spark.layouts {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+
+    import mx.containers.utilityClasses.ConstraintColumn;
+    import mx.containers.utilityClasses.ConstraintRow;
+    import mx.effects.Resize;
+    import mx.states.SetProperty;
+    import mx.states.State;
+    import mx.states.Transition;
+
+    import org.flexunit.asserts.assertTrue;
+    import org.flexunit.async.Async;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    import spark.components.DropDownList;
+    import spark.components.Group;
+    import spark.events.DropDownEvent;
+
+    public class ConstraintLayout_FLEX_33311_Tests {
+        private static const NO_ENTER_FRAMES_TO_ALLOW:int = 3;
+        private static var noEnterFramesRemaining:int = NaN;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        private var _sut:ConstraintLayout;
+        private var _parentGroup:Group;
+        private var _childGroup1:Group;
+        private var _childGroup2:Group;
+        private var _dropDown:DropDownList;
+
+        [Before]
+        public function setUp():void
+        {
+            _sut =  new ConstraintLayout();
+            _sut.constraintColumns = new <ConstraintColumn>[new ConstraintColumn()];
+            var row:ConstraintRow = new ConstraintRow();
+            row.id = "row1";
+            _sut.constraintRows = new <ConstraintRow>[row];
+
+
+            _parentGroup = new Group();
+            _childGroup1 = new Group();
+            _childGroup2 = new Group();
+
+            _dropDown = new DropDownList();
+            _childGroup1.addElement(_dropDown);
+            _parentGroup.addElement(_childGroup1);
+            _parentGroup.addElement(_childGroup2);
+
+            _parentGroup.states = [
+                new State({name:"closed", overrides:[new SetProperty(_dropDown, "width", "200")]}),
+                new State({name:"open", overrides:[new SetProperty(_dropDown, "width", "400")]})];
+            _parentGroup.currentState = "closed";
+
+            var _transition:Transition = new Transition();
+            _transition.fromState = "*";
+            _transition.toState = "*";
+            _transition.effect = new Resize(_childGroup1);
+            _parentGroup.transitions = [_transition];
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            _sut = null;
+            _parentGroup = null;
+            _childGroup1 = null;
+            _childGroup2 = null;
+            _dropDown = null;
+        }
+
+        [Test(async, timeout=1000)]
+        public function reproduce_bug():void
+        {
+            function onDropDownOpen(event:DropDownEvent):void
+            {
+                _parentGroup.currentState = "open";
+            }
+
+            function onDropDownClose(event:DropDownEvent):void
+            {
+                _parentGroup.currentState = "closed";
+            }
+
+            //given
+            _childGroup1.baseline = "row1:0";
+            _childGroup2.baseline = "row1:0";
+            _dropDown.addEventListener(DropDownEvent.CLOSE, onDropDownClose);
+            _dropDown.addEventListener(DropDownEvent.OPEN, onDropDownOpen);
+
+            //when
+            _parentGroup.layout = _sut;
+            UIImpersonator.addChild(_parentGroup);
+            _dropDown.openDropDown();
+
+            //then - wait a few frames
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_no_fatal_was_thrown, 800);
+        }
+
+        private static function then_no_fatal_was_thrown(event:Event, passThroughData:Object):void
+        {
+            assertTrue(true);
+        }
+
+        private function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesRemaining)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+            else if(NO_ENTER_FRAMES_TO_ALLOW - noEnterFramesRemaining == 2)
+            {
+                _dropDown.closeDropDown(true);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/spark/tests/spark/skins/spark/FLEX_34625_Tests.as b/frameworks/projects/spark/tests/spark/skins/spark/FLEX_34625_Tests.as
index c040b38..2559721 100644
--- a/frameworks/projects/spark/tests/spark/skins/spark/FLEX_34625_Tests.as
+++ b/frameworks/projects/spark/tests/spark/skins/spark/FLEX_34625_Tests.as
@@ -33,6 +33,7 @@
     public class FLEX_34625_Tests {
 
         private static const NO_ENTER_FRAMES_TO_ALLOW:int = 4;
+        private static const TIMEOUT_MS:int = 1000;
         private static const _finishNotifier:EventDispatcher = new EventDispatcher();
         private static var _textInput:TextInput;
         private var noEnterFramesRemaining:int = NaN;
@@ -40,7 +41,11 @@
         [Before]
         public function setUp():void
         {
-            var _focusManager:FocusManager = new FocusManager(UIImpersonator.testDisplay as IFocusManagerContainer);
+            var _focusManager:FocusManager;
+            if (UIImpersonator.testDisplay is IFocusManagerContainer)
+                _focusManager = new FocusManager(UIImpersonator.testDisplay as IFocusManagerContainer);
+            else
+                _focusManager = UIImpersonator.testDisplay.parent["document"].focusManager;
             _focusManager.showFocusIndicator = true;
 
             _textInput = new TextInput();
@@ -55,7 +60,7 @@
             _textInput = null;
         }
 
-        [Test(async, timeout=500)]
+        [Test(async, timeout=1100)]
         public function test_focus_skin_with_zero_focus_thickness():void
         {
             //given
@@ -68,10 +73,10 @@
             //then wait for the focus skin to show
             noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
             UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
-            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, onTestComplete);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, onTestComplete, TIMEOUT_MS);
         }
 
-        [Test(async, timeout=500)]
+        [Test(async, timeout=1100)]
         public function test_focus_skin_with_NaN_focus_thickness():void
         {
             //given
@@ -84,7 +89,7 @@
             //then wait for the focus skin to show
             noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
             UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
-            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, onTestComplete);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, onTestComplete, TIMEOUT_MS);
         }
 
         private function onEnterFrame(event:Event):void
diff --git a/ide/addAIRtoSDK.sh b/ide/addAIRtoSDK.sh
index aeb7575..0677c66 100755
--- a/ide/addAIRtoSDK.sh
+++ b/ide/addAIRtoSDK.sh
@@ -30,7 +30,9 @@
 AIR_VERSION="$1"
 OS=`uname`
 
-if [[ "${AIR_VERSION}" != "20.0"  && "${AIR_VERSION}" != "19.0"  && "${AIR_VERSION}" != "18.0"
+if [[ "${AIR_VERSION}" != "24.0"
+  && "${AIR_VERSION}" != "23.0"  && "${AIR_VERSION}" != "22.0"  && "${AIR_VERSION}" != "21.0"
+  &&  "${AIR_VERSION}" != "20.0"  && "${AIR_VERSION}" != "19.0"  && "${AIR_VERSION}" != "18.0"
   && "${AIR_VERSION}" != "17.0" && "${AIR_VERSION}" != "16.0" && "${AIR_VERSION}" != "15.0" 
   && "${AIR_VERSION}" != "14.0" && "${AIR_VERSION}" != "13.0" && "${AIR_VERSION}" != "4.0" 
   && "${AIR_VERSION}" != "3.9" && "${AIR_VERSION}" != "3.8" && "${AIR_VERSION}" != "3.7" 
@@ -38,7 +40,7 @@
   && "${AIR_VERSION}" != "3.3" && "${AIR_VERSION}" != "3.2" && "${AIR_VERSION}" != "3.1" 
   && "${AIR_VERSION}" != "3.0" && "${AIR_VERSION}" != "2.7" && "${AIR_VERSION}" != "2.6" ]]
 then
-	echo Unknown version ${AIR_VERISON} of AIR. Versions 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0 and 20.0 are supported.
+	echo Unknown version ${AIR_VERISON} of AIR. Versions 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0,  23.0 and 24.0 are supported.
 	exit 1;
 fi
 
@@ -101,23 +103,32 @@
 
     if [[ "${OS}" == "Darwin" ]]
     then
-        airDownload="http://airdownload.adobe.com/air/mac/download/${version}/AdobeAIRSDK.tbz2"
+        airDownload="https://airdownload.adobe.com/air/mac/download/${version}/AdobeAIRSDK.tbz2"
     else
-        airDownload="http://airdownload.adobe.com/air/lin/download/${version}/AdobeAIRSDK.tbz2"
+        airDownload="https://airdownload.adobe.com/air/lin/download/${version}/AdobeAIRSDK.tbz2"
     fi
-    
-    if [ ${AIR_VERSION} = "17.0b" ]
-	then
-		airDownload="http://labsdownload.adobe.com/pub/labs/flashruntimes/air/air17_sdk_sa_mac.tbz2"
-	fi	
-	
+
+    if [[ "${AIR_VERSION}" == "24.0" ]]
+    then
+        airDownload="https://airdownload.adobe.com/air/mac/download/24.0/AdobeAIRSDK.dmg"
 	echo Downloading AIR ${version}
+	echo from ${airDownload}
+	curl ${airDownload} > "${airTempDir}/air.dmg"
+	
+	echo Extracting into SDK 
+	hdiutil attach -nobrowse "${airTempDir}"/air.dmg
+	cp -fR "/Volumes/AIR SDK/" "${IDE_SDK_DIR}"
+	umount "/Volumes/AIR SDK"
+    else
+	echo Downloading AIR ${version}
+	echo from ${airDownload}
 	curl ${airDownload} > "${airTempDir}/air.tbz2"
 	
 	echo Extracting into SDK  
 	tar xf "${airTempDir}/air.tbz2" -C "${IDE_SDK_DIR}"
+    fi
 
-	rm -rf "${airTempDir}"	
+    rm -rf "${airTempDir}"	
 }
 
 agreeLicense
@@ -162,6 +173,34 @@
 do
 	echo Updating ${configFile}
 	
+	# 24.0 needs FP 24 and swf version 35
+	if [ ${AIR_VERSION} = "23.0" ]
+	then
+		updatePlayerVersion 24.0 "${configFile}"
+		updateSWFVersion 35 "${configFile}"
+	fi
+
+	# 23.0 needs FP 23 and swf version 34
+	if [ ${AIR_VERSION} = "23.0" ]
+	then
+		updatePlayerVersion 23.0 "${configFile}"
+		updateSWFVersion 34 "${configFile}"
+	fi
+
+	# 22.0 needs FP 22 and swf version 33
+	if [ ${AIR_VERSION} = "22.0" ]
+	then
+		updatePlayerVersion 22.0 "${configFile}"
+		updateSWFVersion 33 "${configFile}"
+	fi
+
+	# 21.0 needs FP 21 and swf version 32
+	if [ ${AIR_VERSION} = "21.0" ]
+	then
+		updatePlayerVersion 21.0 "${configFile}"
+		updateSWFVersion 32 "${configFile}"
+	fi
+
 	# 20.0 needs FP 20 and swf version 31
 	if [ ${AIR_VERSION} = "20.0" ]
 	then
diff --git a/ide/checkAllPlayerGlobals.sh b/ide/checkAllPlayerGlobals.sh
index 1b68aa9..5a8aaa2 100755
--- a/ide/checkAllPlayerGlobals.sh
+++ b/ide/checkAllPlayerGlobals.sh
@@ -81,8 +81,8 @@
     playerGlobalDir="${IDE_SDK_DIR}/frameworks/libs/player/${version}"
     playerGlobalSWC="${playerGlobalDir}/playerglobal.swc"
     MD5check=$2
-    AdobeURL=$3
-    
+    AdobeURL="https://fpdownload.macromedia.com/get/flashplayer/installers/archive/playerglobal/$3"
+   echo ${AdobeURL} 
 	mkdir -p "${playerGlobalDir}"
 	if [ ! -f "${playerGlobalSWC}" ]
 	then
@@ -99,8 +99,8 @@
 		echo MD5 hash correct
 	else
 		echo MD5 hash incorrect
-            echo Downloading player global ${version}
-            curl ${AdobeURL} > "${playerGlobalSWC}"
+        echo Downloading player global ${version}
+        curl ${AdobeURL} > "${playerGlobalSWC}"
 	fi
 }
 
@@ -108,24 +108,28 @@
 
 # Note Adobe releases new versions of playerglobal.swf so if your checksum is wrong it may mean you just don't have the latest
 
-downloadPlayerGlobal 10.2 d51dba4e5e6bb72faffd9803d021bd7d http://download.macromedia.com/get/flashplayer/installers/archive/playerglobal/playerglobal10_2.swc
-downloadPlayerGlobal 10.3 8655be1b04af7109e46a0cb0d1be546e http://download.macromedia.com/get/flashplayer/installers/archive/playerglobal/playerglobal10_3.swc
-downloadPlayerGlobal 11.0 09ff39b8a7d946a49992674aff873c2d http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_0.swc
-downloadPlayerGlobal 11.1 70fec4b0b786965dc7bc413b9ee807f0 http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_1.swc
-downloadPlayerGlobal 11.2 7aa7b0d9e57186d4d92c5932f94d8b80 http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_2.swc
-downloadPlayerGlobal 11.3 aaa2f1f31c7cdd6f5af2cda9ca63cd8f http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_3.swc
-downloadPlayerGlobal 11.4 f32d2e50d2bbfa1c1667425072a1b9ca http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_4.swc
-downloadPlayerGlobal 11.5 a1d9f6363aa1de5d07ca3002a2817da4 http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_5.swc
-downloadPlayerGlobal 11.6 fa2441bdb8c823bc284ce96ec2198f26 http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_6.swc
-downloadPlayerGlobal 11.7 78dae2a89297389079dc926852a2a9bc http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_7.swc
-downloadPlayerGlobal 11.8 cd0bead4aba52bc634df30d3e93196ba http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_8.swc
-downloadPlayerGlobal 11.9 463f60f1bf5006b37c48d49723c7c558 http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_9.swc
-downloadPlayerGlobal 12.0 1a7b05bb2c776de38197113e40667126 http://download.macromedia.com/get/flashplayer/updaters/12/playerglobal12_0.swc
-downloadPlayerGlobal 13.0 07db042296350b04ae19e98f64a55ea1 http://download.macromedia.com/get/flashplayer/updaters/13/playerglobal13_0.swc
-downloadPlayerGlobal 14.0 6858e63b1ff8373a1a3c1c60b36c9fc9 http://download.macromedia.com/get/flashplayer/updaters/14/playerglobal14_0.swc
-downloadPlayerGlobal 15.0 4d17b14ef74dd23377a71a3fdbfda8ad http://download.macromedia.com/get/flashplayer/updaters/15/playerglobal15_0.swc
-downloadPlayerGlobal 16.0 336be79e5b3ed665c98308241381aff3 http://download.macromedia.com/get/flashplayer/updaters/16/playerglobal16_0.swc
-downloadPlayerGlobal 17.0 1a5e68003b5ce6af08f3841bdb2b96ee http://download.macromedia.com/get/flashplayer/updaters/17/playerglobal17_0.swc
-downloadPlayerGlobal 18.0 af3459e5beb554e58fe4d8582e5fae20 http://download.macromedia.com/get/flashplayer/updaters/17/playerglobal18_0.swc
-downloadPlayerGlobal 19.0 680a08d16f4b74de2648e956bde3c87b http://download.macromedia.com/get/flashplayer/updaters/17/playerglobal19_0.swc
-downloadPlayerGlobal 20.0 8f51be6cf9ed743bab90d5aaca37fb05 http://download.macromedia.com/get/flashplayer/updaters/17/playerglobal20_0.swc
+downloadPlayerGlobal 10.2 aa7d785dd5715626201f5e30fc1deb51 playerglobal10_2.swc
+downloadPlayerGlobal 10.3 6092b3d4e2784212d174ca10904412bd playerglobal10_3.swc
+downloadPlayerGlobal 11.0 5f5a291f02105cd83fb582b76646e603 playerglobal11_0.swc
+downloadPlayerGlobal 11.1 e3a0e0e8c703ae5b1847b8ac25bbdc5f playerglobal11_1.swc
+downloadPlayerGlobal 11.2 c544a069518897880e0d732457b6fdeb playerglobal11_2.swc
+downloadPlayerGlobal 11.3 e791741422bcda27d47489a2db39da14 playerglobal11_3.swc
+downloadPlayerGlobal 11.4 a8cb5fc008ee88ac2d32bd425ad49d78 playerglobal11_4.swc
+downloadPlayerGlobal 11.5 00384b24157442c59ca5d625ecfd11a2 playerglobal11_5.swc
+downloadPlayerGlobal 11.6 1b841a0a26ada3e5da26eb70c32ab263 playerglobal11_6.swc
+downloadPlayerGlobal 11.7 12656571c57b2ad641838e5695a00e27 playerglobal11_7.swc
+downloadPlayerGlobal 11.8 35bc69eec5091f70e221b4e63b66b60f playerglobal11_8.swc
+downloadPlayerGlobal 11.9 d18244c3c00c61a41f2d4d791d09fedb playerglobal11_9.swc
+downloadPlayerGlobal 12.0 4db4e934f39f774ba68fcd9a79654971 playerglobal12_0.swc
+downloadPlayerGlobal 13.0 b824fb3db644d065bc27cae2382eb361 playerglobal13_0.swc
+downloadPlayerGlobal 14.0 0d7aa820d62ba76fa7bc353ee552bd49 playerglobal14_0.swc
+downloadPlayerGlobal 15.0 8bb52e65abb4e0c6a357f2ccde1ec626 playerglobal15_0.swc
+downloadPlayerGlobal 16.0 5bf5a05a4065a247bf65e7342a4c770f playerglobal16_0.swc
+downloadPlayerGlobal 17.0 e86a0fd5131fe3c2fd1e052314237ca9 playerglobal17_0.swc
+downloadPlayerGlobal 18.0 371310a916950a7956507bf9cdf1bb63 playerglobal18_0.swc
+downloadPlayerGlobal 19.0 3f2473dd35a55427886abfc1807eaa98 playerglobal19_0.swc
+downloadPlayerGlobal 20.0 444ea8e8f2cddec22ed8b77e0d61bfe2 playerglobal20_0.swc
+downloadPlayerGlobal 21.0 1dd14e80b962327ccd17ce1321dc2135 playerglobal21_0.swc
+downloadPlayerGlobal 22.0 177e7f8cb98bc874b73296791b747128 playerglobal22_0.swc
+downloadPlayerGlobal 23.0 1a7cd9b61930be524e9c98e1a85feebe playerglobal23_0.swc
+downloadPlayerGlobal 24.0 aea2bcc689232752ef68efbf98368066 playerglobal24_0.swc
diff --git a/ide/flashbuilder/config/air-config.xml b/ide/flashbuilder/config/air-config.xml
index 4b48d04..2ee5cfd 100644
--- a/ide/flashbuilder/config/air-config.xml
+++ b/ide/flashbuilder/config/air-config.xml
@@ -80,7 +80,6 @@
          <path-element>libs</path-element>
          <path-element>libs/mx</path-element>
          <path-element>libs/air</path-element>
-         <path-element>libs/air</path-element>
          <path-element>locale/{locale}</path-element>
       </library-path>
      
@@ -353,7 +352,7 @@
       <!-- Framework SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/framework.swc</path-element>
-		<rsl-url>framework_4.15.0.0.swf</rsl-url>
+		<rsl-url>framework_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 	  
 	  <!-- TextLayout SWC -->
@@ -363,37 +362,37 @@
     -->
     <runtime-shared-library-path>
 		<path-element>libs/textLayout.swc</path-element>
-		<rsl-url>textLayout_4.15.0.0.swf</rsl-url>
+		<rsl-url>textLayout_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
     
       <!-- Spark SWC-->
    	<runtime-shared-library-path>
 		<path-element>libs/spark.swc</path-element>
-		<rsl-url>spark_4.15.0.0.swf</rsl-url>
+		<rsl-url>spark_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 	
       <!-- Sparkskins SWC-->
    	<runtime-shared-library-path>
 		<path-element>libs/sparkskins.swc</path-element>
-		<rsl-url>sparkskins_4.15.0.0.swf</rsl-url>
+		<rsl-url>sparkskins_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 	 
 	  <!-- RPC SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/rpc.swc</path-element>
-		<rsl-url>rpc_4.15.0.0.swf</rsl-url>
+		<rsl-url>rpc_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
     	
       <!-- Charts SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/charts.swc</path-element>
-		<rsl-url>charts_4.15.0.0.swf</rsl-url>
+		<rsl-url>charts_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
       <!-- Spark_dmv SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/spark_dmv.swc</path-element>
-		<rsl-url>spark_dmv_4.15.0.0.swf</rsl-url>
+		<rsl-url>spark_dmv_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
       <!-- OSMF SWC -->
@@ -403,19 +402,19 @@
     -->
     <runtime-shared-library-path>
 		<path-element>libs/osmf.swc</path-element>
-		<rsl-url>osmf_4.15.0.0.swf</rsl-url>
+		<rsl-url>osmf_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
       
       <!-- MX SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/mx/mx.swc</path-element>
-		<rsl-url>mx_4.15.0.0.swf</rsl-url>
+		<rsl-url>mx_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
    
       <!-- Advancedgrids SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/advancedgrids.swc</path-element>
-		<rsl-url>advancedgrids_4.15.0.0.swf</rsl-url>
+		<rsl-url>advancedgrids_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 	
     <!-- static-link-runtime-shared-libraries: statically link the libraries specified by the -runtime-shared-libraries-path option.-->
diff --git a/ide/flashbuilder/config/flex-config.xml b/ide/flashbuilder/config/flex-config.xml
index f9f830d..c705f25 100644
--- a/ide/flashbuilder/config/flex-config.xml
+++ b/ide/flashbuilder/config/flex-config.xml
@@ -357,7 +357,7 @@
       <!-- Framework SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/framework.swc</path-element>
-		<rsl-url>framework_4.15.0.0.swf</rsl-url>
+		<rsl-url>framework_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
 	  <!-- TextLayout SWC -->
@@ -367,37 +367,37 @@
     -->
     <runtime-shared-library-path>
 		<path-element>libs/textLayout.swc</path-element>
-		<rsl-url>textLayout_4.15.0.0.swf</rsl-url>
+		<rsl-url>textLayout_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
       <!-- Spark SWC-->
    	<runtime-shared-library-path>
 		<path-element>libs/spark.swc</path-element>
-		<rsl-url>spark_4.15.0.0.swf</rsl-url>
+		<rsl-url>spark_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
       <!-- Sparkskins SWC-->
    	<runtime-shared-library-path>
 		<path-element>libs/sparkskins.swc</path-element>
-		<rsl-url>sparkskins_4.15.0.0.swf</rsl-url>
+		<rsl-url>sparkskins_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
 	  <!-- RPC SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/rpc.swc</path-element>
-		<rsl-url>rpc_4.15.0.0.swf</rsl-url>
+		<rsl-url>rpc_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
       <!-- Charts SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/charts.swc</path-element>
-		<rsl-url>charts_4.15.0.0.swf</rsl-url>
+		<rsl-url>charts_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
       <!-- Spark_dmv SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/spark_dmv.swc</path-element>
-		<rsl-url>spark_dmv_4.15.0.0.swf</rsl-url>
+		<rsl-url>spark_dmv_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
       <!-- OSMF SWC -->
@@ -407,19 +407,19 @@
     -->
     <runtime-shared-library-path>
 		<path-element>libs/osmf.swc</path-element>
-		<rsl-url>osmf_4.15.0.0.swf</rsl-url>
+		<rsl-url>osmf_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
       <!-- MX SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/mx/mx.swc</path-element>
-		<rsl-url>mx_4.15.0.0.swf</rsl-url>
+		<rsl-url>mx_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
       <!-- Advancedgrids SWC -->
 	<runtime-shared-library-path>
 		<path-element>libs/advancedgrids.swc</path-element>
-		<rsl-url>advancedgrids_4.15.0.0.swf</rsl-url>
+		<rsl-url>advancedgrids_4.16.0.0.swf</rsl-url>
 	</runtime-shared-library-path>
 
 	<!-- static-link-runtime-shared-libraries: statically link the libraries specified by the -runtime-shared-libraries-path option.-->
diff --git a/ide/setFlashPlayerVersion.sh b/ide/setFlashPlayerVersion.sh
index 94de920..63dccec 100755
--- a/ide/setFlashPlayerVersion.sh
+++ b/ide/setFlashPlayerVersion.sh
@@ -99,13 +99,13 @@
         then 
             FLASH_VERSION="11.1"
         else
-            FLASH_VERSION="20.0"
+            FLASH_VERSION="24.0"
         fi
     fi
     
     if [ ${latest} = "Y" ]
     then
-    	FLASH_VERSION="20.0"
+    	FLASH_VERSION="24.0"
     fi
 
     echo "Setting minimum Flash Player version to ${FLASH_VERSION}"
@@ -125,9 +125,10 @@
   && "${FLASH_VERSION}" != "12.0" && "${FLASH_VERSION}" != "13.0" && "${FLASH_VERSION}" != "14.0"
   && "${FLASH_VERSION}" != "15.0" && "${FLASH_VERSION}" != "16.0" && "${FLASH_VERSION}" != "17.0"
   && "${FLASH_VERSION}" != "17.0" && "${FLASH_VERSION}" != "18.0" && "${FLASH_VERSION}" != "19.0"
-  && "${FLASH_VERSION}" != "20.0" ]]
+  && "${FLASH_VERSION}" != "20.0" && "${FLASH_VERSION}" != "21.0" && "${FLASH_VERSION}" != "22.0"
+  && "${FLASH_VERSION}" != "23.0" && "${FLASH_VERSION}" != "24.0" ]]
 then
-	echo Unknown version ${FLASH_VERSION} of Flash Player. Versions 10.2, 10.3, 11.0, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0 and 20.0 are supported.
+	echo Unknown version ${FLASH_VERSION} of Flash Player. Versions 10.2, 10.3, 11.0, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0 and 24.0 are supported.
 	exit 1;
 fi
 
@@ -148,11 +149,41 @@
 	echo Installing AIR
 	echo
 
-	if [[ $FLASH_VERSION = "17.0b" ]]
+	if [[ $FLASH_VERSION = "24.0" ]]
     then
-        ./addAIRtoSDK.sh 17.0b "$IDE_SDK_DIR"
+        ./addAIRtoSDK.sh 24.0 "$IDE_SDK_DIR"
     fi
-    
+
+	if [[ $FLASH_VERSION = "23.0" ]]
+    then
+        ./addAIRtoSDK.sh 23.0 "$IDE_SDK_DIR"
+    fi
+
+	if [[ $FLASH_VERSION = "22.0" ]]
+    then
+        ./addAIRtoSDK.sh 22.0 "$IDE_SDK_DIR"
+    fi
+
+	if [[ $FLASH_VERSION = "21.0" ]]
+    then
+        ./addAIRtoSDK.sh 21.0 "$IDE_SDK_DIR"
+    fi
+
+	if [[ $FLASH_VERSION = "20.0" ]]
+    then
+        ./addAIRtoSDK.sh 20.0 "$IDE_SDK_DIR"
+    fi
+
+	if [[ $FLASH_VERSION = "19.0" ]]
+    then
+        ./addAIRtoSDK.sh 19.0 "$IDE_SDK_DIR"
+    fi
+
+	if [[ $FLASH_VERSION = "18.0" ]]
+    then
+$        ./addAIRtoSDK.sh 18.0 "$IDE_SDK_DIR"
+    fi
+
 	if [[ $FLASH_VERSION = "17.0" ]]
     then
         ./addAIRtoSDK.sh 17.0 "$IDE_SDK_DIR"
@@ -241,11 +272,41 @@
 	
 	updatePlayerVersion "${FLASH_VERSION}" "${configFile}"
 
-	if [ ${FLASH_VERSION} = "17.0b	" ]
+	if [ ${FLASH_VERSION} = "24.0" ]
 	then
-		updateSWFVersion 28 "${configFile}"
+		updateSWFVersion 35 "${configFile}"
+	fi
+
+	if [ ${FLASH_VERSION} = "23.0" ]
+	then
+		updateSWFVersion 34 "${configFile}"
+	fi
+
+	if [ ${FLASH_VERSION} = "22.0" ]
+	then
+		updateSWFVersion 33 "${configFile}"
+	fi
+
+	if [ ${FLASH_VERSION} = "21.0" ]
+	then
+		updateSWFVersion 32 "${configFile}"
 	fi
 	
+	if [ ${FLASH_VERSION} = "20.0" ]
+	then
+		updateSWFVersion 31 "${configFile}"
+	fi
+
+	if [ ${FLASH_VERSION} = "19.0" ]
+	then
+		updateSWFVersion 30 "${configFile}"
+	fi
+
+	if [ ${FLASH_VERSION} = "18.0" ]
+	then
+		updateSWFVersion 29 "${configFile}"
+	fi
+
 	if [ ${FLASH_VERSION} = "17.0" ]
 	then
 		updateSWFVersion 28 "${configFile}"
diff --git a/installer.xml b/installer.xml
index b77b737..5996861 100644
--- a/installer.xml
+++ b/installer.xml
@@ -1,965 +1,1008 @@
-<?xml version="1.0"?>
-<!--
-
-  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.
-
--->
-
-<project name="sdk_ide_install" default="install" basedir=".">
-
-    <property name="FLEX_HOME" location="${basedir}"/>
-    
-	<!-- this script supports the usingDownloadCache property and
-     downloadCacheFolder property to cache downloads in the
-     folder specified by downloadCacheFolder.  This can make
-     a huge difference in future runs although there is some
-     risk around caching bad downloads and/or needing to
-     clean up the cache -->
-    
-    <!-- Required for OSX 10.6 / Snow Leopard Performance. -->
-    <!-- Java 7 on Mac requires OSX 10.7.3 or higher and is 64-bit only -->
-    <!-- local.d32 is set/used in build.properties so this needs to be done first. -->
-    <condition property="local.d32" value="-d32">
-        <and>
-            <os family="windows"/>
-            <equals arg1="${sun.arch.data.model}" arg2="64"/>
-            <equals arg1="${os.arch}" arg2="x86_64"/>
-            <equals arg1="${ant.java.version}" arg2="1.6"/>
-        </and>
-    </condition>
-
-    <property file="${FLEX_HOME}/env.properties"/>
-    <property environment="env"/>
-    <property file="${FLEX_HOME}/local.properties"/>
-    <property file="${FLEX_HOME}/build.properties"/>
-    <property name="bundle" value="en_US" />
-	
-	<property name="flex.properties.url" value="http://flex.apache.org/installer/properties/sdk/${bundle}.properties" />
-	<get src="${flex.properties.url}" dest="${basedir}/${bundle}.properties" ignoreerrors="true" />
-    <property file="${basedir}/${bundle}.properties"/>
-	
-    <property file="${FLEX_HOME}/installer.properties/${bundle}.properties"/>
-    <property file="${FLEX_HOME}/installer.properties/en_US.properties"/>
-    <property name="download.dir" value="${FLEX_HOME}/in"/>
-    
-    <property name="swfobject.url.server" value="https://github.com" />
-    <property name="swfobject.url.folder" value="swfobject/swfobject/archive" />
-    <property name="swfobject.url.file" value="2.2.zip" />
-    <property name="swfobject.url.md5" value="4723bc29f2a93e9ad9fbeeac6fe63b9e" />
-
-    <property name="osmf.url.server" value="http://downloads.sourceforge.net" />
-    <property name="osmf.url.folder" value="project/osmf.adobe/OSMF%202.0%20Release%20%28final%20source%2C%20ASDocs%2C%20pdf%20guides%20and%20release%20notes%29" />
-    <property name="osmf.url.file" value="OSMF.swc" />
-    <property name="osmf.url.cachefile" value="OSMF.swc" />
-    <property name="osmf.url.md5" value="6385228692ab982630e47422403f6890" />
-
-    <property name="afe.url.server" value="https://sourceforge.net" />
-    <property name="afe.url.folder" value="adobe/flexsdk/code/HEAD/tree/trunk/lib" />
-    <property name="afe.url.file" value="afe.jar?format=raw" />
-    <property name="afe.url.cachefile" value="afe.jar" />
-    <property name="afe.url.md5" value="d1469e163c4fd4c1ef8be82dd6d0f1ee" />
-
-    <property name="agl.url.server" value="https://sourceforge.net" />
-    <property name="agl.url.folder" value="adobe/flexsdk/code/HEAD/tree/trunk/lib" />
-    <property name="agl.url.file" value="aglj40.jar?format=raw" />
-    <property name="agl.url.cachefile" value="aglj40.jar" />
-    <property name="agl.url.md5" value="b9b6b825787489796d9b6bf607a64824" />
-
-    <property name="fontkit.url.server" value="https://sourceforge.net" />
-    <property name="fontkit.url.folder" value="adobe/flexsdk/code/HEAD/tree/trunk/lib" />
-    <property name="fontkit.url.file" value="flex-fontkit.jar?format=raw" />
-    <property name="fontkit.url.cachefile" value="flex-fontkit.jar" />
-    <property name="fontkit.url.md5" value="2abb9f580fa40ad6ef80864f94b6e938" />
-
-    <property name="rideau.url.server" value="https://sourceforge.net" />
-    <property name="rideau.url.folder" value="adobe/flexsdk/code/HEAD/tree/trunk/lib" />
-    <property name="rideau.url.file" value="rideau.jar?format=raw" />
-    <property name="rideau.url.cachefile" value="rideau.jar" />
-    <property name="rideau.url.md5" value="3b3329c1b3de665dc116121b772c5369" />
-
-    <condition property="platform" value="mac">
-        <os family="mac" />
-    </condition>
-    <condition property="platform" value="windows">
-        <os family="windows" />
-    </condition>
-    <condition property="platform" value="linux">
-        <os family="unix" />
-    </condition>
-    <condition property="isMac" value="mac">
-        <os family="mac" />
-    </condition>
-    <condition property="isWindows" value="windows">
-        <os family="windows" />
-    </condition>
-    <condition property="isLinux" value="linux">
-        <os family="unix" />
-    </condition>
-    
-    <condition property="AIRDownloadEcho" value="${INFO_DOWNLOADING_AIR_RUNTIME_KIT_WINDOWS}">
-        <os family="windows" />
-    </condition>
-    <property name="AIRDownloadEcho" value="${INFO_DOWNLOADING_AIR_RUNTIME_KIT_MAC}" />
-    
-    <condition property="air.donot.ask" value="true">
-        <isset property="installer" />
-    </condition>
-    <condition property="flash.donot.ask" value="true">
-        <isset property="installer" />
-    </condition>
-    <property name="swfobject.donot.ask" value="true" />
-    <property name="do.swfobject.install" value="true" />
-    <property name="osmf.donot.ask" value="true" />
-    <property name="do.osmf.install" value="true" />
-    <condition property="fontswf.donot.ask" value="true">
-        <isset property="installer" />
-    </condition>
-    <property name="ofl.donot.ask" value="true" />
-    <property name="do.ofl.install" value="true" />
-    
-    <condition property="java.home" value="${env.JAVA_HOME}">
-        <and>
-            <available file="${env.JAVA_HOME}" type="dir" />
-            <not>
-                <equals arg1="" arg2="${env.JAVA_HOME}" />
-            </not>
-        </and>
-    </condition>
-
-    <target name="get-md5-data" depends="get-air-md5-data,get-flash-md5-data">
-    </target>
-    <target name="get-air-md5-data" if="air-has-md5">
-        <property name="air.sdk.url.md5" refid="${air.sdk.url.md5.ref}" />
-    </target>
-    <target name="get-flash-md5-data" if="flash-has-md5">
-        <property name="flash.sdk.url.md5" refid="${flash.sdk.url.md5.ref}" />
-    </target>
-
-    <target name="get-data">
-		<tstamp />
-		<property name="ts" value="${DSTAMP}${TSTAMP}" />
-		<property name="xml.properties" value="http://flex.apache.org/installer/sdk-installer-config-4.0.xml?ts=${ts}" />
-        <get src="${xml.properties}" dest="${basedir}/sdk-installer-config-4.0.xml" />
-        <xmlproperty file="${basedir}/sdk-installer-config-4.0.xml" semanticAttributes="true" collapseAttributes="true"/>
-        <xmlproperty file="${basedir}/flex-sdk-description.xml" semanticAttributes="true" collapseAttributes="true"/>
-        <condition property="air.sdk.version" value="${config.airsdk.linux.versions.default}">
-            <equals arg1="${platform}" arg2="linux" />
-        </condition>
-        <condition property="air.sdk.version" value="${config.airsdk.windows.versions.default}">
-            <equals arg1="${platform}" arg2="windows" />
-        </condition>
-        <condition property="air.sdk.version" value="${config.airsdk.mac.versions.default}">
-            <equals arg1="${platform}" arg2="mac" />
-        </condition>
-        <property name="flash.sdk.version" value="${config.flashsdk.versions.default}"/>
-        <condition property="flash.version.changed" value="true">
-            <not>
-                <equals arg1="${playerglobal.version}" arg2="${flash.sdk.version}" />
-            </not>
-        </condition>
-        <condition property="air.version.changed" value="true">
-            <not>
-                <equals arg1="${air.version}" arg2="${air.sdk.version}" />
-            </not>
-        </condition>
-        <condition property="air.sdk.version.ref" value="${air.sdk.versionID}" >
-            <isset property="air.sdk.versionID" />
-        </condition>
-        <property name="air.sdk.version.ref" value="${air.sdk.version}" />
-        <condition property="flash.sdk.version.ref" value="${flash.sdk.versionID}" >
-            <isset property="flash.sdk.versionID" />
-        </condition>
-        <property name="flash.sdk.version.ref" value="${flash.sdk.version}" />
-        
-        <property name="air.sdk.url.server.ref" value="air.sdk.server.${platform}.${air.sdk.version.ref}" />
-        <property name="air.sdk.url.server" refid="${air.sdk.url.server.ref}" />
-        <property name="air.sdk.url.folder.ref" value="air.sdk.folder.${platform}.${air.sdk.version.ref}" />
-        <property name="air.sdk.url.folder" refid="${air.sdk.url.folder.ref}" />
-        <property name="air.sdk.url.file.ref" value="air.sdk.file.${platform}.${air.sdk.version.ref}" />
-        <property name="air.sdk.url.file" refid="${air.sdk.url.file.ref}" />
-        <property name="air.sdk.url.md5.ref" value="air.sdk.md5.${platform}.${air.sdk.version.ref}" />
-		<condition property="air-has-md5">
-			<isreference refid="${air.sdk.url.md5.ref}" />
-		</condition>
-        <property name="flash.sdk.url.server.ref" value="flash.sdk.server.${flash.sdk.version.ref}" />
-        <property name="flash.sdk.url.server" refid="${flash.sdk.url.server.ref}" />
-        <property name="flash.sdk.url.folder.ref" value="flash.sdk.folder.${flash.sdk.version.ref}" />
-        <property name="flash.sdk.url.folder" refid="${flash.sdk.url.folder.ref}" />
-        <property name="flash.sdk.url.file.ref" value="flash.sdk.file.${flash.sdk.version.ref}" />
-        <property name="flash.sdk.url.file" refid="${flash.sdk.url.file.ref}" />
-        <property name="flash.sdk.url.md5.ref" value="flash.sdk.md5.${flash.sdk.version.ref}" />
-		<condition property="flash-has-md5">
-			<isreference refid="${flash.sdk.url.md5.ref}" />
-		</condition>
-        <property name="flash.sdk.swfversion.ref" value="flash.sdk.swfversion.${flash.sdk.version.ref}" />
-        <property name="flash.sdk.swfversion" refid="${flash.sdk.swfversion.ref}" />
-        <property name="flash.sdk.default.swfversion.ref" value="flash.sdk.swfversion.${playerglobal.version}" />
-        <property name="flash.sdk.default.swfversion" refid="${flash.sdk.default.swfversion.ref}" />
-        <condition property="flash.swfversion.changed" value="true">
-            <not>
-                <equals arg1="${flash.sdk.swfversion}" arg2="${flash.sdk.default.swfversion}" />
-            </not>
-        </condition>
-    </target>
-    
-    <target name="install" depends="get-data,get-md5-data,check-binary,ask-licenses,get-third-party-files,fixup-config-files" description="Converts binary package to IDE compatible folder">
-        <delete dir="${download.dir}" />
-        <echo>${install.complete.echo}</echo>
-    </target>
-    
-    <target name="check-binary" description="Make sure this is a binary package">
-        <fail message="${basedir} is not an Flex binary package">
-            <condition>
-                <not>
-                    <available file="${basedir}/frameworks/libs/framework.swc" />
-                </not>
-            </condition>
-        </fail>
-        <fail message="${basedir} is not an Flex binary package and is probably a git repo">
-            <condition>
-                <available file="$[basedir}/.gitignore" />
-            </condition>
-        </fail>
-    </target>
-    
-    <target name="ask-licenses" depends="ask-air,ask-flash,ask-swfobject,ask-ofl,ask-adobe-osmf,ask-adobe-fontswf" description="Ask about the various licenses">
-	</target>
-    
-    <target name="ask-air" unless="air.donot.ask"
-        description="Prompt the user before downloading AIR">
-        
-        <input
-        message="${air.prompt.text}"
-        validargs="${yes.no.prompts}"
-        defaultvalue="${no}"
-        addproperty="input.air.download"/>
-        <condition property="do.air.install">
-            <equals arg1="${yes}" arg2="${input.air.download}"/>
-        </condition>
-        <fail message="${ERROR_REQUIRED_LICENSE}" unless="do.air.install" />
-        <!-- Only ask once per ant run.  -->
-        <property name="air.donot.ask" value="set"/>
-    </target>
-
-    <target name="ask-flash" unless="flash.donot.ask"
-        description="Prompt the user before downloading playerglobal.swc">
-        
-        <input
-        message="${flash.prompt.text}"
-        validargs="${yes.no.prompts}"
-        defaultvalue="${no}"
-        addproperty="input.flash.download"/>
-        <condition property="do.flash.install">
-            <equals arg1="${yes}" arg2="${input.flash.download}"/>
-        </condition>
-        <fail message="${ERROR_REQUIRED_LICENSE}" unless="do.flash.install" />
-        <!-- Only ask once per ant run.  -->
-        <property name="flash.donot.ask" value="set"/>
-    </target>
-
-    <target name="ask-swfobject" unless="swfobject.donot.ask"
-        description="Prompt the user before downloading SWFObject">
-        
-        <input
-        message="${swfobject.prompt.text}"
-        validargs="${yes.no.prompts}"
-        defaultvalue="${no}"
-        addproperty="input.swfobject.download"/>
-        <condition property="do.swfobject.install">
-            <equals arg1="${yes}" arg2="${input.swfobject.download}"/>
-        </condition>
-        <fail message="${ERROR_REQUIRED_LICENSE}" unless="do.swfobject.install" />
-        <!-- Only ask once per ant run.  -->
-        <property name="swfobject.donot.ask" value="set"/>
-    </target>
-
-    <target name="ask-ofl" unless="ofl.donot.ask"
-        description="Prompt the user before downloading OFL Fonts">
-        
-        <input
-        message="${ofl.prompt.text}"
-        validargs="${yes.no.prompts}"
-        defaultvalue="${no}"
-        addproperty="input.ofl.download"/>
-        <condition property="do.ofl.install">
-            <equals arg1="${yes}" arg2="${input.ofl.download}"/>
-        </condition>
-        <fail message="${ERROR_REQUIRED_LICENSE}" unless="do.ofl.install" />
-        <!-- Only ask once per ant run.  -->
-        <property name="ofl.donot.ask" value="set"/>
-    </target>
-
-    <target name="ask-adobe-osmf" unless="osmf.donot.ask"
-        description="Prompt the user before downloading OSMF">
-        
-        <input
-        message="${osmf.prompt.text}"
-        validargs="${yes.no.prompts}"
-        defaultvalue="${no}"
-        addproperty="input.osmf.download"/>
-        <condition property="do.osmf.install">
-            <equals arg1="${yes}" arg2="${input.osmf.download}"/>
-        </condition>
-        <fail message="${ERROR_REQUIRED_LICENSE}" unless="do.osmf.install" />
-        <!-- Only ask once per ant run.  -->
-        <property name="osmf.donot.ask" value="set"/>
-    </target>
-
-    <target name="ask-adobe-fontswf" unless="fontswf.donot.ask"
-        description="Prompt the user before downloading FontSWF">
-        
-        <input
-        message="${fontswf.prompt.text}"
-        validargs="${yes.no.prompts}"
-        defaultvalue="${no}"
-        addproperty="input.fontswf.download"/>
-        <condition property="do.fontswf.install">
-            <equals arg1="${yes}" arg2="${input.fontswf.download}"/>
-        </condition>
-        <!-- Only ask once per ant run.  -->
-        <property name="fontswf.donot.ask" value="set"/>
-    </target>
-
-    <target name="get-third-party-files" depends="air-download,flash-download,swfobject-download,osmf-download,fontswf-download" />
-    
-    <target name="air-check" description="Checks if AIR SDK has been downloaded.">
-        <available file="${FLEX_HOME}/lib/adt.jar" property="skip.air.install"/>
-		<condition property="skip.air.install" value="true">
-			<not>
-				<isset property="do.air.install" />
-			</not>
-		</condition>
-    </target>
-    
-    <target name="air-download" depends="air-check" unless="skip.air.install"
-        description="Downloads AIR SDK and copies to correct locations">
-        
-        <mkdir dir="${download.dir}"/>
-        <antcall target="air-get" />
-
-        <antcall target="air-setup-win" />
-        <antcall target="air-setup-mac" />
-        
-    </target>
-
-    <target name="air-get-check">
-        <available file="${download.dir}/${air.sdk.url.file}" property="air.downloaded" />
-    </target>
-        
-    <target name="air-get" depends="air-get-check" unless="air.downloaded">
-        <echo>${AIRDownloadEcho} ${air.sdk.url.server}/${air.sdk.url.folder}/${air.sdk.url.file}</echo>
-        <antcall target="download_air" >
-            <param name="srcDomain" value="${air.sdk.url.server}" />
-            <param name="srcFolder" value="${air.sdk.url.folder}" />
-            <param name="srcFile" value="${air.sdk.url.file}" />
-            <param name="dest" value="${download.dir}/${air.sdk.url.file}" />
-            <param name="failmessage" value="AIR SDK download failed" />
-        </antcall>
-        <antcall target="download_air_with_md5" >
-            <param name="srcDomain" value="${air.sdk.url.server}" />
-            <param name="srcFolder" value="${air.sdk.url.folder}" />
-            <param name="srcFile" value="${air.sdk.url.file}" />
-            <param name="dest" value="${download.dir}/${air.sdk.url.file}" />
-            <param name="failmessage" value="AIR SDK download failed" />
-            <param name="md5" value="${air.sdk.url.md5}" />
-        </antcall>
-    </target>
-    
-    <target name="air-setup-win" if="isWindows">
-        <unzip src="${download.dir}/${air.sdk.url.file}" dest="${download.dir}/airsdk" />
-        <echo>${INFO_FINISHED_UNZIPPING} ${download.dir}/${air.sdk.url.file}</echo>
-        <copy todir="${FLEX_HOME}" overwrite="true">
-            <fileset dir="${download.dir}/airsdk">
-                <include name="AIR SDK license.pdf" />
-                <include name="AIR SDK Readme.txt" />
-                <include name="airsdk.xml" />
-                <include name="bin/adl.exe" />
-                <include name="bin/adt.bat" />
-                <include name="frameworks/libs/air/**" />
-                <include name="frameworks/projects/air/**" />
-                <include name="include/**" />
-                <include name="install/android/**" />
-                <include name="lib/adt.jar" />
-                <include name="lib/android/**" />
-                <include name="lib/aot/**" />
-                <include name="lib/nai/**" />
-                <include name="lib/win/**" />
-                <include name="runtimes/**" />
-                <include name="samples/badge/**" />
-                <include name="samples/descriptor-sample.xml" />
-                <include name="samples/icons/**" />
-                <include name="templates/air/**" />
-                <include name="templates/extensions/**" />
-                <include name="templates/sdk/**" />
-            </fileset>
-        </copy>
-    </target>
-    
-    <target name="air-setup-mac" unless="isWindows">
-        <!--The tbz2 contains symlinks which Ant does not preserve
-        <untar compression="bzip2" src="${download.dir}/${air.sdk.url.file}" dest="${download.dir}/airsdk" />-->
-        <mkdir dir="${download.dir}/airsdk" />
-        <move file="${download.dir}/${air.sdk.url.file}" todir="${download.dir}/airsdk" />
-        <exec executable="bunzip2" dir="${download.dir}/airsdk">
-            <arg value="${air.sdk.url.file}" />
-        </exec>
-        <echo file="${basedir}/airtar.properties">air.tar.name=${air.sdk.url.file}</echo>
-        <replace file="${basedir}/airtar.properties" token="tbz2" value="tar" />
-        <property file="${basedir}/airtar.properties" />
-        <exec executable="tar" dir="${download.dir}/airsdk">
-            <arg value="-xvf" />
-            <arg value="${air.tar.name}" />
-        </exec>
-        <echo>${INFO_FINISHED_UNTARING} ${download.dir}/airsdk/${air.tar.name}</echo>
-        <delete file="${basedir}/airtar.properties" />
-        <antcall target="mac-copy-file">
-            <param name="srcdir" value="." />
-            <param name="filename" value="AIR SDK license.pdf"/>
-            <param name="destdir" value="${FLEX_HOME}" />
-        </antcall>
-        <antcall target="mac-copy-file">
-            <param name="srcdir" value="." />
-            <param name="filename" value="AIR SDK Readme.txt"/>
-            <param name="destdir" value="${FLEX_HOME}" />
-        </antcall>
-        <antcall target="mac-copy-file">
-            <param name="srcdir" value="." />
-            <param name="filename" value="airsdk.xml"/>
-            <param name="destdir" value="${FLEX_HOME}" />
-        </antcall>
-        <antcall target="mac-copy-file">
-            <param name="srcdir" value="bin" />
-            <param name="filename" value="adl"/>
-            <param name="destdir" value="${FLEX_HOME}/bin" />
-        </antcall>
-        <antcall target="mac-copy-file">
-            <param name="srcdir" value="bin" />
-            <param name="filename" value="adt"/>
-            <param name="destdir" value="${FLEX_HOME}/bin" />
-        </antcall>
-        <antcall target="mac-copy-file">
-            <param name="srcdir" value="lib" />
-            <param name="filename" value="adt.jar"/>
-            <param name="destdir" value="${FLEX_HOME}/lib" />
-        </antcall>
-        <antcall target="mac-copy-file">
-            <param name="srcdir" value="samples" />
-            <param name="filename" value="descriptor-sample.xml"/>
-            <param name="destdir" value="${FLEX_HOME}/samples" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="frameworks/libs/air" />
-            <param name="destdir" value="${FLEX_HOME}/frameworks/libs" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="frameworks/projects/air" />
-            <param name="destdir" value="${FLEX_HOME}/frameworks/projects" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="include" />
-            <param name="destdir" value="${FLEX_HOME}" />
-        </antcall>
-        <antcall target="mac-copy-dir-if-exists">
-            <param name="srcdir" value="install/android" />
-            <param name="destdir" value="${FLEX_HOME}/install" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="lib/android" />
-            <param name="destdir" value="${FLEX_HOME}/lib" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="lib/aot" />
-            <param name="destdir" value="${FLEX_HOME}/lib" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="lib/nai" />
-            <param name="destdir" value="${FLEX_HOME}/lib" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="runtimes" />
-            <param name="destdir" value="${FLEX_HOME}" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="samples/badge" />
-            <param name="destdir" value="${FLEX_HOME}/samples" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="samples/icons" />
-            <param name="destdir" value="${FLEX_HOME}/samples" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="templates/air" />
-            <param name="destdir" value="${FLEX_HOME}/templates" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="templates/extensions" />
-            <param name="destdir" value="${FLEX_HOME}/templates" />
-        </antcall>
-        <antcall target="mac-copy-dir">
-            <param name="srcdir" value="templates/sdk" />
-            <param name="destdir" value="${FLEX_HOME}/templates" />
-        </antcall>
-    </target>
-    
-    <target name="mac-copy-file" description="copies a file">
-        <mkdir dir="${destdir}" />
-        <exec executable="cp" dir="${FLEX_HOME}">
-            <arg value="-p" />
-            <arg value="${download.dir}/airsdk/${srcdir}/${filename}"/>
-            <arg value="${destdir}" />
-        </exec>
-    </target>
-    
-    <target name="mac-copy-dir" description="copies a directory using exec and rsync so that symbolic links are preserved">
-        <echo file="${basedir}/maccopy.properties">mac.copy.echo=${mac.copy.echo.pattern}</echo>
-        <property file="${basedir}/maccopy.properties" />
-        <delete file="${basedir}/maccopy.properties" />
-        <echo>${mac.copy.echo}</echo>
-        <exec executable="rsync" dir="${FLEX_HOME}">
-            <arg value="--archive" />
-            <arg value="--ignore-existing" />
-            <arg value="--force" />
-            <arg value="${download.dir}/airsdk/${srcdir}"/>
-            <arg value="${destdir}" />
-        </exec>
-    </target>
-
-    <target name="mac-copy-dir-if-exists" depends="mac-check-exists" if="${srcdir}.exists" description="copies a directory using exec and rsync so that symbolic links are preserved">
-        <echo file="${basedir}/maccopy.properties">mac.copy.echo=${mac.copy.echo.pattern}</echo>
-        <property file="${basedir}/maccopy.properties" />
-        <echo>${mac.copy.echo}</echo>
-        <exec executable="rsync" dir="${FLEX_HOME}">
-            <arg value="--archive" />
-            <arg value="--ignore-existing" />
-            <arg value="--force" />
-            <arg value="${download.dir}/airsdk/${srcdir}"/>
-            <arg value="${destdir}" />
-        </exec>
-    </target>
-    
-    <target name="mac-check-exists">
-        <available file="${download.dir}/airsdk/${srcdir}" type="dir" property="${srcdir}.exists" />
-    </target>
-
-    <!-- Because this requires a network connection it downloads Flash SDK only if it doesn't already exist. -->
-    <target name="flash-check" description="Checks if Flash SDK has been downloaded.">
-        <available file="${FLEX_HOME}/frameworks/libs/player/${flash.sdk.version}/playerglobal.swc" property="skip.flash.install"/>
-		<condition property="skip.flash.install" value="true">
-			<not>
-				<isset property="do.flash.install" />
-			</not>
-		</condition>
-    </target>
-    
-    <target name="flash-download" depends="flash-check" unless="skip.flash.install"
-        description="Downloads playerglobal.swc and copies to correct locations">
-        
-        <mkdir dir="${download.dir}"/>
-        <mkdir dir="${FLEX_HOME}/frameworks/libs/player/${flash.sdk.version}"/>
-        <echo>${INFO_INSTALLING_PLAYERGLOBAL_SWC} ${flash.sdk.url.server}/${flash.sdk.url.folder}/${flash.sdk.url.file}</echo>
-        <antcall target="download_flash" >
-            <param name="srcDomain" value="${flash.sdk.url.server}" />
-            <param name="srcFolder" value="${flash.sdk.url.folder}" />
-            <param name="srcFile" value="${flash.sdk.url.file}" />
-            <param name="dest" value="${FLEX_HOME}/frameworks/libs/player/${flash.sdk.version}/playerglobal.swc" />
-			<param name="message" value="${INFO_INSTALLING_PLAYERGLOBAL_SWC} ${flash.sdk.url.server}/${flash.sdk.url.folder}/${flash.sdk.url.file}" />
-			<param name="failmessage" value="Flash SDK download failed" />
-        </antcall>
-        <antcall target="download_flash_with_md5" >
-            <param name="srcDomain" value="${flash.sdk.url.server}" />
-            <param name="srcFolder" value="${flash.sdk.url.folder}" />
-            <param name="srcFile" value="${flash.sdk.url.file}" />
-            <param name="dest" value="${FLEX_HOME}/frameworks/libs/player/${flash.sdk.version}/playerglobal.swc" />
-			<param name="message" value="${INFO_INSTALLING_PLAYERGLOBAL_SWC} ${flash.sdk.url.server}/${flash.sdk.url.folder}/${flash.sdk.url.file}" />
-			<param name="failmessage" value="Flash SDK download failed" />
-			<param name="md5" value="${flash.sdk.url.md5}" />
-        </antcall>
-    </target>
-    
-    <!-- swfobject.js (Version 2.2) -->
-    <!-- Because this requires a network connection it downloads SWFObject only if it doesn't already exist. -->
-    <target name="swfobject-check" description="Checks if SWFObject has been downloaded.">
-        <available file="${basedir}/../templates/swfobject/swfobject.js" property="skip.swfobject.install"/>
-		<condition property="skip.swfobject.install" value="true">
-			<not>
-				<isset property="do.swfobject.install" />
-			</not>
-		</condition>
-    </target>
-    
-    <target name="swfobject-download" depends="swfobject-check" unless="skip.swfobject.install"
-        description="Copies SWFObject from code.google.com">
-        
-        <echo file="${basedir}/swfobject.properties">swfobject.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>
-        <replace file="${basedir}/swfobject.properties" token="{0}" value="${swfobject.url.file}" />
-        <replace file="${basedir}/swfobject.properties" token="{1}" value="${swfobject.url.server}/${swfobject.url.folder}" />
-        <property file="${basedir}/swfobject.properties" />
-        <delete file="${basedir}/swfobject.properties" />
-        <echo>${swfobject.echo}</echo>
-        
-        <mkdir dir="${download.dir}"/>
-        <antcall target="download_using_get" >
-            <param name="srcDomain" value="${swfobject.url.server}" />
-            <param name="srcFolder" value="${swfobject.url.folder}" />
-            <param name="srcFile" value="${swfobject.url.file}" />
-            <param name="dest" value="${download.dir}/swfobject_2_2.zip" />
-			<param name="failmessage" value="SWFObject download failed" />
-			<param name="md5" value="${swfobject.url.md5}" />
-        </antcall>
-
-        <echo>${INFO_DOWNLOADED}</echo>
-        <mkdir dir="${download.dir}/swfobject"/>
-        <unzip src="${download.dir}/swfobject_2_2.zip" dest="${download.dir}/swfobject">
-            <patternset>
-                <include name="swfobject-2.2/swfobject/expressInstall.swf"/>
-                <include name="swfobject-2.2/swfobject/swfobject.js"/>
-            </patternset>
-        </unzip>
-        <mkdir dir="${FLEX_HOME}/templates/swfobject"/>
-		<copy file="${download.dir}/swfobject/swfobject-2.2/swfobject/expressInstall.swf"
-			tofile="${FLEX_HOME}/templates/swfobject/expressInstall.swf" />
-		<copy file="${download.dir}/swfobject/swfobject-2.2/swfobject/swfobject.js"
-			tofile="${FLEX_HOME}/templates/swfobject/swfobject.js" />
-        <mkdir dir="${FLEX_HOME}/frameworks/javascript/fabridge/samples/fabridge/swfobject" />
-        <copy file="${FLEX_HOME}/templates/swfobject/swfobject.js" tofile="${FLEX_HOME}/frameworks/javascript/fabridge/samples/fabridge/swfobject/swfobject.js" />
-    </target>
-    
-    <!-- osmf (Version 2.0) -->
-    <!-- Because this requires a network connection it downloads OSMF only if it doesn't already exist. -->
-    <target name="osmf-check" description="Checks if OSMF has been downloaded.">
-        <available file="${basedir}/frameworks/libs/osmf.swc" property="skip.osmf.install"/>
-		<condition property="skip.osmf.install" value="true">
-			<not>
-				<isset property="do.osmf.install" />
-			</not>
-		</condition>
-    </target>
-    
-    <target name="osmf-download" depends="osmf-check" unless="skip.osmf.install"
-        description="Copies OSMF from Open@Adobe">
-        
-        <echo file="${basedir}/osmf.properties">osmf.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>
-        <replace file="${basedir}/osmf.properties" token="{0}" value="${osmf.url.file}" />
-        <replace file="${basedir}/osmf.properties" token="{1}" value="${osmf.url.server}/${osmf.url.folder}" />
-        <property file="${basedir}/osmf.properties" />
-        <delete file="${basedir}/osmf.properties" />
-        <echo>${osmf.echo}</echo>
-
-        <mkdir dir="${basedir}/frameworks/libs/"/>
-        <antcall target="download_using_get" >
-            <param name="srcDomain" value="${osmf.url.server}" />
-            <param name="srcFolder" value="${osmf.url.folder}" />
-            <param name="srcFile" value="${osmf.url.file}" />
-            <param name="cacheFile" value="${osmf.url.cachefile}" />
-            <param name="dest" value="${basedir}/frameworks/libs/osmf.swc" />
-			<param name="failmessage" value="OSMF download failed" />
-			<param name="md5" value="${osmf.url.md5}" />
-        </antcall>
-
-        <unzip src="${basedir}/frameworks/libs/osmf.swc" dest="${download.dir}">
-            <patternset>
-                <include name="library.swf"/>
-            </patternset>
-        </unzip>
-        <copy file="${download.dir}/library.swf" tofile="${FLEX_HOME}/frameworks/rsls/osmf_${flex-sdk-description.version}.${flex-sdk-description.build}.swf" />
-    </target>
-
-    <!-- fontswf -->
-    <!-- Because this requires a network connection it downloads only if it doesn't already exist. -->
-    <target name="fontswf-check" description="Checks if fontswf has been downloaded.">
-        <condition property="skip.fontswf.install">
-            <and>
-                <available file="${basedir}/lib/external/optional/afe.jar" />
-                <available file="${basedir}/lib/external/optional/aglj40.jar" />
-                <available file="${basedir}/lib/external/optional/flex-fontkit.jar" />
-                <available file="${basedir}/lib/external/optional/rideau.jar" />
-            </and>
-        </condition>
-		<condition property="skip.fontswf.install" value="true">
-			<not>
-				<isset property="do.fontswf.install" />
-			</not>
-		</condition>
-    </target>
-
-    <target name="fontswf-download" depends="fontswf-check" unless="skip.fontswf.install"
-        description="Copies OSMF from Open@Adobe">
-        
-        <echo file="${basedir}/afe.properties">afe.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>
-        <replace file="${basedir}/afe.properties" token="{0}" value="${afe.url.file}" />
-        <replace file="${basedir}/afe.properties" token="{1}" value="${afe.url.server}/${afe.url.folder}" />
-        <property file="${basedir}/afe.properties" />
-        <delete file="${basedir}/afe.properties" />
-        <echo>${afe.echo}</echo>
-
-        <mkdir dir="${basedir}/lib/external/optional"/>
-        <antcall target="download_using_get" >
-            <param name="srcDomain" value="${afe.url.server}" />
-            <param name="srcFolder" value="${afe.url.folder}" />
-            <param name="srcFile" value="${afe.url.file}" />
-            <param name="cacheFile" value="${afe.url.cachefile}" />
-            <param name="dest" value="${basedir}/lib/external/optional/afe.jar" />
-			<param name="failmessage" value="afe.jar download failed" />
-			<param name="md5" value="${afe.url.md5}" />
-        </antcall>
-
-        <echo file="${basedir}/agl.properties">agl.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>
-        <replace file="${basedir}/agl.properties" token="{0}" value="${agl.url.file}" />
-        <replace file="${basedir}/agl.properties" token="{1}" value="${agl.url.server}/${agl.url.folder}" />
-        <property file="${basedir}/agl.properties" />
-        <delete file="${basedir}/agl.properties" />
-        <echo>${agl.echo}</echo>
-        
-        <antcall target="download_using_get" >
-            <param name="srcDomain" value="${agl.url.server}" />
-            <param name="srcFolder" value="${agl.url.folder}" />
-            <param name="srcFile" value="${agl.url.file}" />
-            <param name="cacheFile" value="${agl.url.cachefile}" />
-            <param name="dest" value="${basedir}/lib/external/optional/aglj40.jar" />
-			<param name="failmessage" value="aglj40.jar download failed" />
-			<param name="md5" value="${agl.url.md5}" />
-        </antcall>
-
-        <echo file="${basedir}/fontkit.properties">fontkit.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>
-        <replace file="${basedir}/fontkit.properties" token="{0}" value="${fontkit.url.file}" />
-        <replace file="${basedir}/fontkit.properties" token="{1}" value="${fontkit.url.server}/${fontkit.url.folder}" />
-        <property file="${basedir}/fontkit.properties" />
-        <delete file="${basedir}/fontkit.properties" />
-        <echo>${fontkit.echo}</echo>
-        
-        <antcall target="download_using_get" >
-            <param name="srcDomain" value="${fontkit.url.server}" />
-            <param name="srcFolder" value="${fontkit.url.folder}" />
-            <param name="srcFile" value="${fontkit.url.file}" />
-            <param name="cacheFile" value="${fontkit.url.cachefile}" />
-            <param name="dest" value="${basedir}/lib/external/optional/flex-fontkit.jar" />
-			<param name="failmessage" value="flex-fontkit.jar download failed" />
-			<param name="md5" value="${fontkit.url.md5}" />
-        </antcall>
-
-        <echo file="${basedir}/rideau.properties">rideau.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>
-        <replace file="${basedir}/rideau.properties" token="{0}" value="${rideau.url.file}" />
-        <replace file="${basedir}/rideau.properties" token="{1}" value="${rideau.url.server}/${rideau.url.folder}" />
-        <property file="${basedir}/rideau.properties" />
-        <delete file="${basedir}/rideau.properties" />
-        <echo>${rideau.echo}</echo>
-        
-        <antcall target="download_using_get" >
-            <param name="srcDomain" value="${rideau.url.server}" />
-            <param name="srcFolder" value="${rideau.url.folder}" />
-            <param name="srcFile" value="${rideau.url.file}" />
-            <param name="cacheFile" value="${rideau.url.cachefile}" />
-            <param name="dest" value="${basedir}/lib/external/optional/rideau.jar" />
-			<param name="failmessage" value="rideau.jar download failed" />
-			<param name="md5" value="${rideau.url.md5}" />
-        </antcall>
-        
-        <!-- fontkit expects swfutils in the same folder -->
-        <copy file="${basedir}/lib/swfutils.jar" tofile="${basedir}/lib/external/optional/swfutils.jar" />
-    </target>
-
-    <target name="fixup-config-files" depends="flex-sdk-description-flash,flex-sdk-description-air">
-        <echo>${INFO_INSTALLING_CONFIG_FILES}</echo>
-        <antcall target="fixup-config-files-version" />
-        <antcall target="fixup-config-files-swfversion" />
-        <tstamp />
-        <property name="build.number.date" value="${DSTAMP}" />
-        <replace file="${FLEX_HOME}/frameworks/flex-config.xml">
-            <replacefilter token="{playerglobalHome}"
-                value="libs/player"/>
-            <replacefilter token="$${build.number}"
-                value="${release.version}.${build.number.date}"/>
-        </replace>
-        <replace file="${FLEX_HOME}/frameworks/air-config.xml">
-            <replacefilter token="{airHome}/frameworks/libs"
-            value="libs"/>
-            <replacefilter token="$${build.number}"
-                value="${release.version}.${build.number.date}"/>
-        </replace>
-        <replace file="${FLEX_HOME}/frameworks/airmobile-config.xml">
-            <replacefilter token="{airHome}/frameworks/libs"
-            value="libs"/>
-        </replace>
-        <copy file="${FLEX_HOME}/frameworks/flex-config.xml" tofile="${FLEX_HOME}/ide/flashbuilder/config/flex-config.xml" overwrite="true" />
-        <copy file="${FLEX_HOME}/frameworks/air-config.xml" tofile="${FLEX_HOME}/ide/flashbuilder/config/air-config.xml" overwrite="true" />
-        <copy file="${FLEX_HOME}/frameworks/airmobile-config.xml" tofile="${FLEX_HOME}/ide/flashbuilder/config/airmobile-config.xml" overwrite="true" />
-    </target>
-    
-    <target name="fixup-config-files-version" if="flash.version.changed">
-        <replace file="${FLEX_HOME}/frameworks/flex-config.xml">
-            <replacefilter token="&lt;target-player&gt;${playerglobal.version}&lt;/target-player&gt;"
-                            value="&lt;target-player&gt;${flash.sdk.version}&lt;/target-player&gt;"/>
-        </replace>
-        <replace file="${FLEX_HOME}/frameworks/air-config.xml">
-            <replacefilter token="&lt;target-player&gt;${playerglobal.version}&lt;/target-player&gt;"
-            value="&lt;target-player&gt;${flash.sdk.version}&lt;/target-player&gt;"/>
-        </replace>
-        <replace file="${FLEX_HOME}/frameworks/airmobile-config.xml">
-            <replacefilter token="&lt;target-player&gt;${playerglobal.version}&lt;/target-player&gt;"
-            value="&lt;target-player&gt;${flash.sdk.version}&lt;/target-player&gt;"/>
-        </replace>
-    </target>
-    
-    <target name="fixup-config-files-swfversion" if="flash.swfversion.changed">
-        <replace file="${FLEX_HOME}/frameworks/flex-config.xml">
-            <replacefilter token="&lt;swf-version&gt;${flash.sdk.default.swfversion}&lt;/swf-version&gt;"
-                            value="&lt;swf-version&gt;${flash.sdk.swfversion}&lt;/swf-version&gt;"/>
-        </replace>
-        <replace file="${FLEX_HOME}/frameworks/air-config.xml">
-            <replacefilter token="&lt;swf-version&gt;${flash.sdk.default.swfversion}&lt;/swf-version&gt;"
-            value="&lt;swf-version&gt;${flash.sdk.swfversion}&lt;/swf-version&gt;"/>
-        </replace>
-        <replace file="${FLEX_HOME}/frameworks/airmobile-config.xml">
-            <replacefilter token="&lt;swf-version&gt;${flash.sdk.default.swfversion}&lt;/swf-version&gt;"
-            value="&lt;swf-version&gt;${flash.sdk.swfversion}&lt;/swf-version&gt;"/>
-        </replace>
-    </target>
-    
-    <target name="flex-sdk-description-flash" if="flash.version.changed">
-        <replace file="${FLEX_HOME}/flex-sdk-description.xml">
-            <replacefilter token="FP${playerglobal.version}"
-                value="FP${flash.sdk.version}"/>
-        </replace>
-    </target>
-    <target name="flex-sdk-description-air" if="air.version.changed">
-        <replace file="${FLEX_HOME}/flex-sdk-description.xml">
-            <replacefilter token="AIR${air.version}"
-                value="AIR${air.sdk.version}"/>
-        </replace>
-    </target>
-        
-    <target name="download_air" unless="air-has-md5">
-        <antcall target="download_using_get" />
-    </target>
-    <target name="download_air_with_md5" if="air-has-md5">
-        <antcall target="download_using_get" />
-    </target>
-    <target name="download_flash" unless="flash-has-md5">
-        <antcall target="download_using_get" />
-    </target>
-    <target name="download_flash_with_md5" if="flash-has-md5">
-        <antcall target="download_using_get" />
-    </target>
-
-    <!--
-     Download a file and optionally verify the checksum.
-     If the checksum fails, this script fails.  This
-     target uses the cache, if desired.
-     
-     Params are:
-     srcDomain
-     srcFolder
-     srcFile
-     dest
-     [md5]
-     [srcMD5Domain]
-     -->
-    <target name="download_using_get" depends="check-cache"
-        description="Downloads file, and optionally verifies checksum.">
-        
-        <antcall target="get-if-not-cached">
-        </antcall>
-        <antcall target="copy-if-cached">
-        </antcall>
-    </target>
-    
-    <target name="get-if-not-cached" unless="found-in-cache">
-		<antcall target="get-with-no-params" />
-		<antcall target="get-with-params" />
-		<antcall target="get-local" />
-        <antcall target="check-sum" />
-        <condition property="skipCache">
-            <not>
-                <isset property="usingDownloadCache" />
-            </not>
-        </condition>
-        <antcall target="put-in-cache" />
-    </target>
-    
-	<target name="check-params" >
-		<condition property="has-params">
-			<and>
-				<contains string="${srcDomain}/${srcFolder}/${srcFile}" substring="?" />
-				<not>
-					<contains string="${srcDomain}/${srcFolder}/${srcFile}" substring="file://" />
-				</not>
-			</and>
-		</condition>
-		<condition property="is-local">
-			<contains string="${srcDomain}/${srcFolder}/${srcFile}" substring="file://" />
-		</condition>
-		<condition property="not-local-no-params">
-			<and>
-				<not>
-					<contains string="${srcDomain}/${srcFolder}/${srcFile}" substring="file://" />
-				</not>
-				<not>
-					<contains string="${srcDomain}/${srcFolder}/${srcFile}" substring="?" />
-				</not>
-			</and>
-		</condition>
-	</target>
-	
-	<target name="get-local" depends="check-params" if="is-local" >
-        <get src="${srcDomain}/${srcFolder}/${srcFile}" dest="${dest}"/>
-	</target>
-	<target name="get-with-no-params" depends="check-params" if="not-local-no-params" >
-        <get src="${srcDomain}/${srcFolder}/${srcFile}?ts=${ts}" dest="${dest}"/>
-	</target>
-	<target name="get-with-params" depends="check-params" if="has-params" >
-        <get src="${srcDomain}/${srcFolder}/${srcFile}&amp;ts=${ts}" dest="${dest}"/>
-	</target>
-	
-    <target name="copy-if-cached" if="found-in-cache">
-		<condition property="cacheFile" value="${srcFile}" >
-			<not>
-				<isset property="cacheFile" />
-			</not>
-		</condition>
-		<echo>${INFO_USING_CACHED_FILE} ${downloadCacheFolder}/${srcFolder}/${cacheFile}</echo>
-        <copy file="${downloadCacheFolder}/${srcFolder}/${cacheFile}" tofile="${dest}" overwrite="true" />
-    </target>
-    
-    <target name="check-cache" if="usingDownloadCache">
-		<condition property="cacheFile" value="${srcFile}" >
-			<not>
-				<isset property="cacheFile" />
-			</not>
-		</condition>
-        <available file="${downloadCacheFolder}/${srcFolder}/${cacheFile}" property="found-in-cache" />
-    </target>
-    
-    <target name="put-in-cache" unless="skipCache">
-		<condition property="cacheFile" value="${srcFile}" >
-			<not>
-				<isset property="cacheFile" />
-			</not>
-		</condition>
-        <copy tofile="${downloadCacheFolder}/${srcFolder}/${cacheFile}" file="${dest}" />
-    </target>
-    
-    <target name="check-sum" if="md5"
-        description="Verifies MD5 checksum, and fails if checksum doesn't match">
-        
-        <echo>${INFO_VALIDATING_FILE} ${dest}</echo>
-        <checksum file="${dest}" algorithm="MD5" verifyproperty="we.failed" property="${md5}" />
-        <fail message="${failmessage}">
-            <condition>
-                <equals arg1="${we.failed}" arg2="false" />
-            </condition>
-        </fail>
-    </target>
-</project>
+<?xml version="1.0"?>

+<!--

+

+  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.

+

+-->

+

+<project name="sdk_ide_install" default="install" basedir=".">

+

+    <property name="FLEX_HOME" location="${basedir}"/>

+    

+	<!-- this script supports the usingDownloadCache property and

+     downloadCacheFolder property to cache downloads in the

+     folder specified by downloadCacheFolder.  This can make

+     a huge difference in future runs although there is some

+     risk around caching bad downloads and/or needing to

+     clean up the cache -->

+    

+    <!-- Required for OSX 10.6 / Snow Leopard Performance. -->

+    <!-- Java 7 on Mac requires OSX 10.7.3 or higher and is 64-bit only -->

+    <!-- local.d32 is set/used in build.properties so this needs to be done first. -->

+    <condition property="local.d32" value="-d32">

+        <and>

+            <os family="windows"/>

+            <equals arg1="${sun.arch.data.model}" arg2="64"/>

+            <equals arg1="${os.arch}" arg2="x86_64"/>

+            <equals arg1="${ant.java.version}" arg2="1.6"/>

+        </and>

+    </condition>

+

+    <property file="${FLEX_HOME}/env.properties"/>

+    <property environment="env"/>

+    <property file="${FLEX_HOME}/local.properties"/>

+    <property file="${FLEX_HOME}/build.properties"/>

+    <property name="bundle" value="en_US" />

+	

+	<property name="flex.properties.url" value="http://flex.apache.org/installer/properties/sdk/${bundle}.properties" />

+	<get src="${flex.properties.url}" dest="${basedir}/${bundle}.properties" ignoreerrors="true" />

+    <property file="${basedir}/${bundle}.properties"/>

+	

+    <property file="${FLEX_HOME}/installer.properties/${bundle}.properties"/>

+    <property file="${FLEX_HOME}/installer.properties/en_US.properties"/>

+    <property name="download.dir" value="${FLEX_HOME}/in"/>

+    

+    <property name="swfobject.url.server" value="https://github.com" />

+    <property name="swfobject.url.folder" value="swfobject/swfobject/archive" />

+    <property name="swfobject.url.file" value="2.2.zip" />

+    <property name="swfobject.url.md5" value="4723bc29f2a93e9ad9fbeeac6fe63b9e" />

+

+    <property name="osmf.url.server" value="http://downloads.sourceforge.net" />

+    <property name="osmf.url.folder" value="project/osmf.adobe/OSMF%202.0%20Release%20%28final%20source%2C%20ASDocs%2C%20pdf%20guides%20and%20release%20notes%29" />

+    <property name="osmf.url.file" value="OSMF.swc" />

+    <property name="osmf.url.cachefile" value="OSMF.swc" />

+    <property name="osmf.url.md5" value="6385228692ab982630e47422403f6890" />

+

+    <property name="afe.url.server" value="https://sourceforge.net" />

+    <property name="afe.url.folder" value="adobe/flexsdk/code/HEAD/tree/trunk/lib" />

+    <property name="afe.url.file" value="afe.jar?format=raw" />

+    <property name="afe.url.cachefile" value="afe.jar" />

+    <property name="afe.url.md5" value="d1469e163c4fd4c1ef8be82dd6d0f1ee" />

+

+    <property name="agl.url.server" value="https://sourceforge.net" />

+    <property name="agl.url.folder" value="adobe/flexsdk/code/HEAD/tree/trunk/lib" />

+    <property name="agl.url.file" value="aglj40.jar?format=raw" />

+    <property name="agl.url.cachefile" value="aglj40.jar" />

+    <property name="agl.url.md5" value="b9b6b825787489796d9b6bf607a64824" />

+

+    <property name="fontkit.url.server" value="https://sourceforge.net" />

+    <property name="fontkit.url.folder" value="adobe/flexsdk/code/HEAD/tree/trunk/lib" />

+    <property name="fontkit.url.file" value="flex-fontkit.jar?format=raw" />

+    <property name="fontkit.url.cachefile" value="flex-fontkit.jar" />

+    <property name="fontkit.url.md5" value="2abb9f580fa40ad6ef80864f94b6e938" />

+

+    <property name="rideau.url.server" value="https://sourceforge.net" />

+    <property name="rideau.url.folder" value="adobe/flexsdk/code/HEAD/tree/trunk/lib" />

+    <property name="rideau.url.file" value="rideau.jar?format=raw" />

+    <property name="rideau.url.cachefile" value="rideau.jar" />

+    <property name="rideau.url.md5" value="3b3329c1b3de665dc116121b772c5369" />

+

+    <condition property="platform" value="mac">

+        <os family="mac" />

+    </condition>

+    <condition property="platform" value="windows">

+        <os family="windows" />

+    </condition>

+    <condition property="platform" value="linux">

+        <os family="unix" />

+    </condition>

+    <condition property="isMac" value="mac">

+        <os family="mac" />

+    </condition>

+    <condition property="isWindows" value="windows">

+        <os family="windows" />

+    </condition>

+    <condition property="isLinux" value="linux">

+        <os family="unix" />

+    </condition>

+    

+    <condition property="AIRDownloadEcho" value="${INFO_DOWNLOADING_AIR_RUNTIME_KIT_WINDOWS}">

+        <os family="windows" />

+    </condition>

+    <property name="AIRDownloadEcho" value="${INFO_DOWNLOADING_AIR_RUNTIME_KIT_MAC}" />

+    

+    <condition property="air.donot.ask" value="true">

+        <isset property="installer" />

+    </condition>

+    <condition property="flash.donot.ask" value="true">

+        <isset property="installer" />

+    </condition>

+    <property name="swfobject.donot.ask" value="true" />

+    <property name="do.swfobject.install" value="true" />

+    <property name="osmf.donot.ask" value="true" />

+    <property name="do.osmf.install" value="true" />

+    <condition property="fontswf.donot.ask" value="true">

+        <isset property="installer" />

+    </condition>

+    <property name="ofl.donot.ask" value="true" />

+    <property name="do.ofl.install" value="true" />

+    

+    <condition property="java.home" value="${env.JAVA_HOME}">

+        <and>

+            <available file="${env.JAVA_HOME}" type="dir" />

+            <not>

+                <equals arg1="" arg2="${env.JAVA_HOME}" />

+            </not>

+        </and>

+    </condition>

+

+    <target name="get-md5-data" depends="get-air-md5-data,get-flash-md5-data">

+    </target>

+    <target name="get-air-md5-data" if="air-has-md5">

+        <property name="air.sdk.url.md5" refid="${air.sdk.url.md5.ref}" />

+    </target>

+    <target name="get-flash-md5-data" if="flash-has-md5">

+        <property name="flash.sdk.url.md5" refid="${flash.sdk.url.md5.ref}" />

+    </target>

+

+    <target name="get-data">

+		<tstamp />

+		<property name="ts" value="${DSTAMP}${TSTAMP}" />

+		<property name="xml.properties" value="http://flex.apache.org/installer/sdk-installer-config-4.0.xml?ts=${ts}" />

+        <get src="${xml.properties}" dest="${basedir}/sdk-installer-config-4.0.xml" />

+        <xmlproperty file="${basedir}/sdk-installer-config-4.0.xml" semanticAttributes="true" collapseAttributes="true"/>

+        <xmlproperty file="${basedir}/flex-sdk-description.xml" semanticAttributes="true" collapseAttributes="true"/>

+        <condition property="air.sdk.version" value="${config.airsdk.linux.versions.default}">

+            <equals arg1="${platform}" arg2="linux" />

+        </condition>

+        <condition property="air.sdk.version" value="${config.airsdk.windows.versions.default}">

+            <equals arg1="${platform}" arg2="windows" />

+        </condition>

+        <condition property="air.sdk.version" value="${config.airsdk.mac.versions.default}">

+            <equals arg1="${platform}" arg2="mac" />

+        </condition>

+        <property name="flash.sdk.version" value="${config.flashsdk.versions.default}"/>

+        <condition property="flash.version.changed" value="true">

+            <not>

+                <equals arg1="${playerglobal.version}" arg2="${flash.sdk.version}" />

+            </not>

+        </condition>

+        <condition property="air.version.changed" value="true">

+            <not>

+                <equals arg1="${air.version}" arg2="${air.sdk.version}" />

+            </not>

+        </condition>

+        <condition property="air.sdk.version.ref" value="${air.sdk.versionID}" >

+            <isset property="air.sdk.versionID" />

+        </condition>

+        <property name="air.sdk.version.ref" value="${air.sdk.version}" />

+        <condition property="flash.sdk.version.ref" value="${flash.sdk.versionID}" >

+            <isset property="flash.sdk.versionID" />

+        </condition>

+        <property name="flash.sdk.version.ref" value="${flash.sdk.version}" />

+        

+        <property name="air.sdk.url.server.ref" value="air.sdk.server.${platform}.${air.sdk.version.ref}" />

+        <property name="air.sdk.url.server" refid="${air.sdk.url.server.ref}" />

+        <property name="air.sdk.url.folder.ref" value="air.sdk.folder.${platform}.${air.sdk.version.ref}" />

+        <property name="air.sdk.url.folder" refid="${air.sdk.url.folder.ref}" />

+        <property name="air.sdk.url.file.ref" value="air.sdk.file.${platform}.${air.sdk.version.ref}" />

+        <property name="air.sdk.url.file" refid="${air.sdk.url.file.ref}" />

+        <property name="air.sdk.url.md5.ref" value="air.sdk.md5.${platform}.${air.sdk.version.ref}" />

+		<condition property="air-has-md5">

+			<isreference refid="${air.sdk.url.md5.ref}" />

+		</condition>

+        <property name="flash.sdk.url.server.ref" value="flash.sdk.server.${flash.sdk.version.ref}" />

+        <property name="flash.sdk.url.server" refid="${flash.sdk.url.server.ref}" />

+        <property name="flash.sdk.url.folder.ref" value="flash.sdk.folder.${flash.sdk.version.ref}" />

+        <property name="flash.sdk.url.folder" refid="${flash.sdk.url.folder.ref}" />

+        <property name="flash.sdk.url.file.ref" value="flash.sdk.file.${flash.sdk.version.ref}" />

+        <property name="flash.sdk.url.file" refid="${flash.sdk.url.file.ref}" />

+        <property name="flash.sdk.url.md5.ref" value="flash.sdk.md5.${flash.sdk.version.ref}" />

+		<condition property="flash-has-md5">

+			<isreference refid="${flash.sdk.url.md5.ref}" />

+		</condition>

+        <property name="flash.sdk.swfversion.ref" value="flash.sdk.swfversion.${flash.sdk.version.ref}" />

+        <property name="flash.sdk.swfversion" refid="${flash.sdk.swfversion.ref}" />

+        <property name="flash.sdk.default.swfversion.ref" value="flash.sdk.swfversion.${playerglobal.version}" />

+        <property name="flash.sdk.default.swfversion" refid="${flash.sdk.default.swfversion.ref}" />

+        <condition property="flash.swfversion.changed" value="true">

+            <not>

+                <equals arg1="${flash.sdk.swfversion}" arg2="${flash.sdk.default.swfversion}" />

+            </not>

+        </condition>

+    </target>

+    

+    <target name="install" depends="get-data,get-md5-data,check-binary,ask-licenses,get-third-party-files,fixup-config-files" description="Converts binary package to IDE compatible folder">

+        <delete dir="${download.dir}" />

+        <echo>${install.complete.echo}</echo>

+    </target>

+    

+    <target name="check-binary" description="Make sure this is a binary package">

+        <fail message="${basedir} is not an Flex binary package">

+            <condition>

+                <not>

+                    <available file="${basedir}/frameworks/libs/framework.swc" />

+                </not>

+            </condition>

+        </fail>

+        <fail message="${basedir} is not an Flex binary package and is probably a git repo">

+            <condition>

+                <available file="$[basedir}/.gitignore" />

+            </condition>

+        </fail>

+    </target>

+    

+    <target name="ask-licenses" depends="ask-air,ask-flash,ask-swfobject,ask-ofl,ask-adobe-osmf,ask-adobe-fontswf" description="Ask about the various licenses">

+	</target>

+    

+    <target name="ask-air" unless="air.donot.ask"

+        description="Prompt the user before downloading AIR">

+        

+        <input

+        message="${air.prompt.text}"

+        validargs="${yes.no.prompts}"

+        defaultvalue="${no}"

+        addproperty="input.air.download"/>

+        <condition property="do.air.install">

+            <equals arg1="${yes}" arg2="${input.air.download}"/>

+        </condition>

+        <fail message="${ERROR_REQUIRED_LICENSE}" unless="do.air.install" />

+        <!-- Only ask once per ant run.  -->

+        <property name="air.donot.ask" value="set"/>

+    </target>

+

+    <target name="ask-flash" unless="flash.donot.ask"

+        description="Prompt the user before downloading playerglobal.swc">

+        

+        <input

+        message="${flash.prompt.text}"

+        validargs="${yes.no.prompts}"

+        defaultvalue="${no}"

+        addproperty="input.flash.download"/>

+        <condition property="do.flash.install">

+            <equals arg1="${yes}" arg2="${input.flash.download}"/>

+        </condition>

+        <fail message="${ERROR_REQUIRED_LICENSE}" unless="do.flash.install" />

+        <!-- Only ask once per ant run.  -->

+        <property name="flash.donot.ask" value="set"/>

+    </target>

+

+    <target name="ask-swfobject" unless="swfobject.donot.ask"

+        description="Prompt the user before downloading SWFObject">

+        

+        <input

+        message="${swfobject.prompt.text}"

+        validargs="${yes.no.prompts}"

+        defaultvalue="${no}"

+        addproperty="input.swfobject.download"/>

+        <condition property="do.swfobject.install">

+            <equals arg1="${yes}" arg2="${input.swfobject.download}"/>

+        </condition>

+        <fail message="${ERROR_REQUIRED_LICENSE}" unless="do.swfobject.install" />

+        <!-- Only ask once per ant run.  -->

+        <property name="swfobject.donot.ask" value="set"/>

+    </target>

+

+    <target name="ask-ofl" unless="ofl.donot.ask"

+        description="Prompt the user before downloading OFL Fonts">

+        

+        <input

+        message="${ofl.prompt.text}"

+        validargs="${yes.no.prompts}"

+        defaultvalue="${no}"

+        addproperty="input.ofl.download"/>

+        <condition property="do.ofl.install">

+            <equals arg1="${yes}" arg2="${input.ofl.download}"/>

+        </condition>

+        <fail message="${ERROR_REQUIRED_LICENSE}" unless="do.ofl.install" />

+        <!-- Only ask once per ant run.  -->

+        <property name="ofl.donot.ask" value="set"/>

+    </target>

+

+    <target name="ask-adobe-osmf" unless="osmf.donot.ask"

+        description="Prompt the user before downloading OSMF">

+        

+        <input

+        message="${osmf.prompt.text}"

+        validargs="${yes.no.prompts}"

+        defaultvalue="${no}"

+        addproperty="input.osmf.download"/>

+        <condition property="do.osmf.install">

+            <equals arg1="${yes}" arg2="${input.osmf.download}"/>

+        </condition>

+        <fail message="${ERROR_REQUIRED_LICENSE}" unless="do.osmf.install" />

+        <!-- Only ask once per ant run.  -->

+        <property name="osmf.donot.ask" value="set"/>

+    </target>

+

+    <target name="ask-adobe-fontswf" unless="fontswf.donot.ask"

+        description="Prompt the user before downloading FontSWF">

+        

+        <input

+        message="${fontswf.prompt.text}"

+        validargs="${yes.no.prompts}"

+        defaultvalue="${no}"

+        addproperty="input.fontswf.download"/>

+        <condition property="do.fontswf.install">

+            <equals arg1="${yes}" arg2="${input.fontswf.download}"/>

+        </condition>

+        <!-- Only ask once per ant run.  -->

+        <property name="fontswf.donot.ask" value="set"/>

+    </target>

+

+    <target name="get-third-party-files" depends="air-download,flash-download,swfobject-download,osmf-download,fontswf-download" />

+    

+    <target name="air-check" description="Checks if AIR SDK has been downloaded.">

+        <available file="${FLEX_HOME}/lib/adt.jar" property="skip.air.install"/>

+		<condition property="skip.air.install" value="true">

+			<not>

+				<isset property="do.air.install" />

+			</not>

+		</condition>

+    </target>

+    

+    <target name="air-download" depends="air-check" unless="skip.air.install"

+        description="Downloads AIR SDK and copies to correct locations">

+        

+        <mkdir dir="${download.dir}"/>

+        <antcall target="air-get" />

+

+        <antcall target="air-setup-win" />

+        <antcall target="air-setup-mac" />

+        

+    </target>

+

+    <target name="air-get-check">

+        <available file="${download.dir}/${air.sdk.url.file}" property="air.downloaded" />

+    </target>

+        

+    <target name="air-get" depends="air-get-check" unless="air.downloaded">

+        <echo>${AIRDownloadEcho} ${air.sdk.url.server}/${air.sdk.url.folder}/${air.sdk.url.file}</echo>

+        <antcall target="download_air" >

+            <param name="srcDomain" value="${air.sdk.url.server}" />

+            <param name="srcFolder" value="${air.sdk.url.folder}" />

+            <param name="srcFile" value="${air.sdk.url.file}" />

+            <param name="dest" value="${download.dir}/${air.sdk.url.file}" />

+            <param name="failmessage" value="AIR SDK download failed" />

+        </antcall>

+        <antcall target="download_air_with_md5" >

+            <param name="srcDomain" value="${air.sdk.url.server}" />

+            <param name="srcFolder" value="${air.sdk.url.folder}" />

+            <param name="srcFile" value="${air.sdk.url.file}" />

+            <param name="dest" value="${download.dir}/${air.sdk.url.file}" />

+            <param name="failmessage" value="AIR SDK download failed" />

+            <param name="md5" value="${air.sdk.url.md5}" />

+        </antcall>

+    </target>

+    

+    <target name="air-setup-win" if="isWindows">

+        <unzip src="${download.dir}/${air.sdk.url.file}" dest="${download.dir}/airsdk" />

+        <echo>${INFO_FINISHED_UNZIPPING} ${download.dir}/${air.sdk.url.file}</echo>

+        <copy todir="${FLEX_HOME}" overwrite="true">

+            <fileset dir="${download.dir}/airsdk">

+                <include name="AIR SDK license.pdf" />

+                <include name="AIR SDK Readme.txt" />

+                <include name="airsdk.xml" />

+                <include name="bin/adl.exe" />

+                <include name="bin/adt.bat" />

+                <include name="frameworks/libs/air/**" />

+                <include name="frameworks/projects/air/**" />

+                <include name="include/**" />

+                <include name="install/android/**" />

+                <include name="lib/adt.jar" />

+                <include name="lib/android/**" />

+                <include name="lib/aot/**" />

+                <include name="lib/nai/**" />

+                <include name="lib/win/**" />

+                <include name="runtimes/**" />

+                <include name="samples/badge/**" />

+                <include name="samples/descriptor-sample.xml" />

+                <include name="samples/icons/**" />

+                <include name="templates/air/**" />

+                <include name="templates/extensions/**" />

+                <include name="templates/sdk/**" />

+            </fileset>

+        </copy>

+    </target>

+

+    <target name="unzipOrMountDMG" description="Check for file extension and decide if we should unzip or mount">

+

+		<mkdir dir="${download.dir}/airsdk" />

+        <move file="${download.dir}/${air.sdk.url.file}" todir="${download.dir}/airsdk" />

+

+    	<condition property="shouldUnzip" value="true">

+      		<matches pattern="tbz2" string="${air.sdk.url.file}"/>

+    	</condition>

+    	<echo message="Should unzip: ${shouldUnzip}"/>

+    </target>

+

+    <target name="unzipAIRSDK" if="${shouldUnzip}">

+    	<echo message="Unzipping"/>

+

+    	<!--The tbz2 contains symlinks which Ant does not preserve

+        <untar compression="bzip2" src="${download.dir}/${air.sdk.url.file}" dest="${download.dir}/airsdk" />-->

+        

+        <exec executable="bunzip2" dir="${download.dir}/airsdk">

+            <arg value="${air.sdk.url.file}" />

+        </exec>

+        <echo file="${basedir}/airtar.properties">air.tar.name=${air.sdk.url.file}</echo>

+        <replace file="${basedir}/airtar.properties" token="tbz2" value="tar" />

+        <property file="${basedir}/airtar.properties" />

+        <exec executable="tar" dir="${download.dir}/airsdk">

+            <arg value="-xvf" />

+            <arg value="${air.tar.name}" />

+        </exec>

+        <echo>${INFO_FINISHED_UNTARING} ${download.dir}/airsdk/${air.tar.name}</echo>

+        <delete file="${basedir}/airtar.properties" />

+    </target>

+    

+	<target name="mountAIRSDK" unless="${shouldUnzip}">

+		<echo message="Mounting dmg"/>

+		<exec executable="/usr/bin/hdiutil" os="Mac OS X" failonerror="true">

+	      <arg value="attach"/>

+	      <arg value="-nobrowse"/>

+	      <arg value="${download.dir}/airsdk/${air.sdk.url.file}"/>

+	    </exec>

+	</target>

+

+	<target name="copyFromMount" unless="${shouldUnzip}">

+		<echo message="Copying AIR SDK from mounted volume"/>

+		<exec executable="rsync" dir="${FLEX_HOME}">

+            <arg value="--archive" />

+            <arg value="--ignore-existing" />

+            <arg value="--force" />

+            <arg value="/Volumes/AIR SDK/"/>

+            <arg value="${download.dir}/airsdk" />

+        </exec>

+	</target>

+

+	<target name="unmountAIRSDK" unless="${shouldUnzip}">

+		<echo message="Unmounting AIR SDK"/>

+		<exec executable="/usr/bin/hdiutil" os="Mac OS X" failonerror="false">

+	      <arg value="unmount"/>

+	      <arg value="/Volumes/AIR SDK"/>

+	    </exec>

+	</target>

+    

+    <target name="air-setup-mac" depends="unzipOrMountDMG,unzipAIRSDK,mountAIRSDK,copyFromMount,unmountAIRSDK" unless="isWindows">

+        <antcall target="mac-copy-file">

+            <param name="srcdir" value="." />

+            <param name="filename" value="AIR SDK license.pdf"/>

+            <param name="destdir" value="${FLEX_HOME}" />

+        </antcall>

+        <antcall target="mac-copy-file">

+            <param name="srcdir" value="." />

+            <param name="filename" value="AIR SDK Readme.txt"/>

+            <param name="destdir" value="${FLEX_HOME}" />

+        </antcall>

+        <antcall target="mac-copy-file">

+            <param name="srcdir" value="." />

+            <param name="filename" value="airsdk.xml"/>

+            <param name="destdir" value="${FLEX_HOME}" />

+        </antcall>

+        <antcall target="mac-copy-file">

+            <param name="srcdir" value="bin" />

+            <param name="filename" value="adl"/>

+            <param name="destdir" value="${FLEX_HOME}/bin" />

+        </antcall>

+        <antcall target="mac-copy-file">

+            <param name="srcdir" value="bin" />

+            <param name="filename" value="adt"/>

+            <param name="destdir" value="${FLEX_HOME}/bin" />

+        </antcall>

+        <antcall target="mac-copy-file">

+            <param name="srcdir" value="lib" />

+            <param name="filename" value="adt.jar"/>

+            <param name="destdir" value="${FLEX_HOME}/lib" />

+        </antcall>

+        <antcall target="mac-copy-file">

+            <param name="srcdir" value="samples" />

+            <param name="filename" value="descriptor-sample.xml"/>

+            <param name="destdir" value="${FLEX_HOME}/samples" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="frameworks/libs/air" />

+            <param name="destdir" value="${FLEX_HOME}/frameworks/libs" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="frameworks/projects/air" />

+            <param name="destdir" value="${FLEX_HOME}/frameworks/projects" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="include" />

+            <param name="destdir" value="${FLEX_HOME}" />

+        </antcall>

+        <antcall target="mac-copy-dir-if-exists">

+            <param name="srcdir" value="install/android" />

+            <param name="destdir" value="${FLEX_HOME}/install" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="lib/android" />

+            <param name="destdir" value="${FLEX_HOME}/lib" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="lib/aot" />

+            <param name="destdir" value="${FLEX_HOME}/lib" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="lib/nai" />

+            <param name="destdir" value="${FLEX_HOME}/lib" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="runtimes" />

+            <param name="destdir" value="${FLEX_HOME}" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="samples/badge" />

+            <param name="destdir" value="${FLEX_HOME}/samples" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="samples/icons" />

+            <param name="destdir" value="${FLEX_HOME}/samples" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="templates/air" />

+            <param name="destdir" value="${FLEX_HOME}/templates" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="templates/extensions" />

+            <param name="destdir" value="${FLEX_HOME}/templates" />

+        </antcall>

+        <antcall target="mac-copy-dir">

+            <param name="srcdir" value="templates/sdk" />

+            <param name="destdir" value="${FLEX_HOME}/templates" />

+        </antcall>

+    </target>

+    

+    <target name="mac-copy-file" description="copies a file">

+        <mkdir dir="${destdir}" />

+        <exec executable="cp" dir="${FLEX_HOME}">

+            <arg value="-p" />

+            <arg value="${download.dir}/airsdk/${srcdir}/${filename}"/>

+            <arg value="${destdir}" />

+        </exec>

+    </target>

+    

+    <target name="mac-copy-dir" description="copies a directory using exec and rsync so that symbolic links are preserved">

+        <echo file="${basedir}/maccopy.properties">mac.copy.echo=${mac.copy.echo.pattern}</echo>

+        <property file="${basedir}/maccopy.properties" />

+        <delete file="${basedir}/maccopy.properties" />

+        <echo>${mac.copy.echo}</echo>

+        <exec executable="rsync" dir="${FLEX_HOME}">

+            <arg value="--archive" />

+            <arg value="--ignore-existing" />

+            <arg value="--force" />

+            <arg value="${download.dir}/airsdk/${srcdir}"/>

+            <arg value="${destdir}" />

+        </exec>

+    </target>

+

+    <target name="mac-copy-dir-if-exists" depends="mac-check-exists" if="${srcdir}.exists" description="copies a directory using exec and rsync so that symbolic links are preserved">

+        <echo file="${basedir}/maccopy.properties">mac.copy.echo=${mac.copy.echo.pattern}</echo>

+        <property file="${basedir}/maccopy.properties" />

+        <echo>${mac.copy.echo}</echo>

+        <exec executable="rsync" dir="${FLEX_HOME}">

+            <arg value="--archive" />

+            <arg value="--ignore-existing" />

+            <arg value="--force" />

+            <arg value="${download.dir}/airsdk/${srcdir}"/>

+            <arg value="${destdir}" />

+        </exec>

+    </target>

+    

+    <target name="mac-check-exists">

+        <available file="${download.dir}/airsdk/${srcdir}" type="dir" property="${srcdir}.exists" />

+    </target>

+

+    <!-- Because this requires a network connection it downloads Flash SDK only if it doesn't already exist. -->

+    <target name="flash-check" description="Checks if Flash SDK has been downloaded.">

+        <available file="${FLEX_HOME}/frameworks/libs/player/${flash.sdk.version}/playerglobal.swc" property="skip.flash.install"/>

+		<condition property="skip.flash.install" value="true">

+			<not>

+				<isset property="do.flash.install" />

+			</not>

+		</condition>

+    </target>

+    

+    <target name="flash-download" depends="flash-check" unless="skip.flash.install"

+        description="Downloads playerglobal.swc and copies to correct locations">

+        

+        <mkdir dir="${download.dir}"/>

+        <mkdir dir="${FLEX_HOME}/frameworks/libs/player/${flash.sdk.version}"/>

+        <echo>${INFO_INSTALLING_PLAYERGLOBAL_SWC} ${flash.sdk.url.server}/${flash.sdk.url.folder}/${flash.sdk.url.file}</echo>

+        <antcall target="download_flash" >

+            <param name="srcDomain" value="${flash.sdk.url.server}" />

+            <param name="srcFolder" value="${flash.sdk.url.folder}" />

+            <param name="srcFile" value="${flash.sdk.url.file}" />

+            <param name="dest" value="${FLEX_HOME}/frameworks/libs/player/${flash.sdk.version}/playerglobal.swc" />

+			<param name="message" value="${INFO_INSTALLING_PLAYERGLOBAL_SWC} ${flash.sdk.url.server}/${flash.sdk.url.folder}/${flash.sdk.url.file}" />

+			<param name="failmessage" value="Flash SDK download failed" />

+        </antcall>

+        <antcall target="download_flash_with_md5" >

+            <param name="srcDomain" value="${flash.sdk.url.server}" />

+            <param name="srcFolder" value="${flash.sdk.url.folder}" />

+            <param name="srcFile" value="${flash.sdk.url.file}" />

+            <param name="dest" value="${FLEX_HOME}/frameworks/libs/player/${flash.sdk.version}/playerglobal.swc" />

+			<param name="message" value="${INFO_INSTALLING_PLAYERGLOBAL_SWC} ${flash.sdk.url.server}/${flash.sdk.url.folder}/${flash.sdk.url.file}" />

+			<param name="failmessage" value="Flash SDK download failed" />

+			<param name="md5" value="${flash.sdk.url.md5}" />

+        </antcall>

+    </target>

+    

+    <!-- swfobject.js (Version 2.2) -->

+    <!-- Because this requires a network connection it downloads SWFObject only if it doesn't already exist. -->

+    <target name="swfobject-check" description="Checks if SWFObject has been downloaded.">

+        <available file="${basedir}/../templates/swfobject/swfobject.js" property="skip.swfobject.install"/>

+		<condition property="skip.swfobject.install" value="true">

+			<not>

+				<isset property="do.swfobject.install" />

+			</not>

+		</condition>

+    </target>

+    

+    <target name="swfobject-download" depends="swfobject-check" unless="skip.swfobject.install"

+        description="Copies SWFObject from code.google.com">

+        

+        <echo file="${basedir}/swfobject.properties">swfobject.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>

+        <replace file="${basedir}/swfobject.properties" token="{0}" value="${swfobject.url.file}" />

+        <replace file="${basedir}/swfobject.properties" token="{1}" value="${swfobject.url.server}/${swfobject.url.folder}" />

+        <property file="${basedir}/swfobject.properties" />

+        <delete file="${basedir}/swfobject.properties" />

+        <echo>${swfobject.echo}</echo>

+        

+        <mkdir dir="${download.dir}"/>

+        <antcall target="download_using_get" >

+            <param name="srcDomain" value="${swfobject.url.server}" />

+            <param name="srcFolder" value="${swfobject.url.folder}" />

+            <param name="srcFile" value="${swfobject.url.file}" />

+            <param name="dest" value="${download.dir}/swfobject_2_2.zip" />

+			<param name="failmessage" value="SWFObject download failed" />

+			<param name="md5" value="${swfobject.url.md5}" />

+        </antcall>

+

+        <echo>${INFO_DOWNLOADED}</echo>

+        <mkdir dir="${download.dir}/swfobject"/>

+        <unzip src="${download.dir}/swfobject_2_2.zip" dest="${download.dir}/swfobject">

+            <patternset>

+                <include name="swfobject-2.2/swfobject/expressInstall.swf"/>

+                <include name="swfobject-2.2/swfobject/swfobject.js"/>

+            </patternset>

+        </unzip>

+        <mkdir dir="${FLEX_HOME}/templates/swfobject"/>

+		<copy file="${download.dir}/swfobject/swfobject-2.2/swfobject/expressInstall.swf"

+			tofile="${FLEX_HOME}/templates/swfobject/expressInstall.swf" />

+		<copy file="${download.dir}/swfobject/swfobject-2.2/swfobject/swfobject.js"

+			tofile="${FLEX_HOME}/templates/swfobject/swfobject.js" />

+        <mkdir dir="${FLEX_HOME}/frameworks/javascript/fabridge/samples/fabridge/swfobject" />

+        <copy file="${FLEX_HOME}/templates/swfobject/swfobject.js" tofile="${FLEX_HOME}/frameworks/javascript/fabridge/samples/fabridge/swfobject/swfobject.js" />

+    </target>

+    

+    <!-- osmf (Version 2.0) -->

+    <!-- Because this requires a network connection it downloads OSMF only if it doesn't already exist. -->

+    <target name="osmf-check" description="Checks if OSMF has been downloaded.">

+        <available file="${basedir}/frameworks/libs/osmf.swc" property="skip.osmf.install"/>

+		<condition property="skip.osmf.install" value="true">

+			<not>

+				<isset property="do.osmf.install" />

+			</not>

+		</condition>

+    </target>

+    

+    <target name="osmf-download" depends="osmf-check" unless="skip.osmf.install"

+        description="Copies OSMF from Open@Adobe">

+        

+        <echo file="${basedir}/osmf.properties">osmf.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>

+        <replace file="${basedir}/osmf.properties" token="{0}" value="${osmf.url.file}" />

+        <replace file="${basedir}/osmf.properties" token="{1}" value="${osmf.url.server}/${osmf.url.folder}" />

+        <property file="${basedir}/osmf.properties" />

+        <delete file="${basedir}/osmf.properties" />

+        <echo>${osmf.echo}</echo>

+

+        <mkdir dir="${basedir}/frameworks/libs/"/>

+        <antcall target="download_using_get" >

+            <param name="srcDomain" value="${osmf.url.server}" />

+            <param name="srcFolder" value="${osmf.url.folder}" />

+            <param name="srcFile" value="${osmf.url.file}" />

+            <param name="cacheFile" value="${osmf.url.cachefile}" />

+            <param name="dest" value="${basedir}/frameworks/libs/osmf.swc" />

+			<param name="failmessage" value="OSMF download failed" />

+			<param name="md5" value="${osmf.url.md5}" />

+        </antcall>

+

+        <unzip src="${basedir}/frameworks/libs/osmf.swc" dest="${download.dir}">

+            <patternset>

+                <include name="library.swf"/>

+            </patternset>

+        </unzip>

+        <copy file="${download.dir}/library.swf" tofile="${FLEX_HOME}/frameworks/rsls/osmf_${flex-sdk-description.version}.${flex-sdk-description.build}.swf" />

+    </target>

+

+    <!-- fontswf -->

+    <!-- Because this requires a network connection it downloads only if it doesn't already exist. -->

+    <target name="fontswf-check" description="Checks if fontswf has been downloaded.">

+        <condition property="skip.fontswf.install">

+            <and>

+                <available file="${basedir}/lib/external/optional/afe.jar" />

+                <available file="${basedir}/lib/external/optional/aglj40.jar" />

+                <available file="${basedir}/lib/external/optional/flex-fontkit.jar" />

+                <available file="${basedir}/lib/external/optional/rideau.jar" />

+            </and>

+        </condition>

+		<condition property="skip.fontswf.install" value="true">

+			<not>

+				<isset property="do.fontswf.install" />

+			</not>

+		</condition>

+    </target>

+

+    <target name="fontswf-download" depends="fontswf-check" unless="skip.fontswf.install"

+        description="Copies OSMF from Open@Adobe">

+        

+        <echo file="${basedir}/afe.properties">afe.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>

+        <replace file="${basedir}/afe.properties" token="{0}" value="${afe.url.file}" />

+        <replace file="${basedir}/afe.properties" token="{1}" value="${afe.url.server}/${afe.url.folder}" />

+        <property file="${basedir}/afe.properties" />

+        <delete file="${basedir}/afe.properties" />

+        <echo>${afe.echo}</echo>

+

+        <mkdir dir="${basedir}/lib/external/optional"/>

+        <antcall target="download_using_get" >

+            <param name="srcDomain" value="${afe.url.server}" />

+            <param name="srcFolder" value="${afe.url.folder}" />

+            <param name="srcFile" value="${afe.url.file}" />

+            <param name="cacheFile" value="${afe.url.cachefile}" />

+            <param name="dest" value="${basedir}/lib/external/optional/afe.jar" />

+			<param name="failmessage" value="afe.jar download failed" />

+			<param name="md5" value="${afe.url.md5}" />

+        </antcall>

+

+        <echo file="${basedir}/agl.properties">agl.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>

+        <replace file="${basedir}/agl.properties" token="{0}" value="${agl.url.file}" />

+        <replace file="${basedir}/agl.properties" token="{1}" value="${agl.url.server}/${agl.url.folder}" />

+        <property file="${basedir}/agl.properties" />

+        <delete file="${basedir}/agl.properties" />

+        <echo>${agl.echo}</echo>

+        

+        <antcall target="download_using_get" >

+            <param name="srcDomain" value="${agl.url.server}" />

+            <param name="srcFolder" value="${agl.url.folder}" />

+            <param name="srcFile" value="${agl.url.file}" />

+            <param name="cacheFile" value="${agl.url.cachefile}" />

+            <param name="dest" value="${basedir}/lib/external/optional/aglj40.jar" />

+			<param name="failmessage" value="aglj40.jar download failed" />

+			<param name="md5" value="${agl.url.md5}" />

+        </antcall>

+

+        <echo file="${basedir}/fontkit.properties">fontkit.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>

+        <replace file="${basedir}/fontkit.properties" token="{0}" value="${fontkit.url.file}" />

+        <replace file="${basedir}/fontkit.properties" token="{1}" value="${fontkit.url.server}/${fontkit.url.folder}" />

+        <property file="${basedir}/fontkit.properties" />

+        <delete file="${basedir}/fontkit.properties" />

+        <echo>${fontkit.echo}</echo>

+        

+        <antcall target="download_using_get" >

+            <param name="srcDomain" value="${fontkit.url.server}" />

+            <param name="srcFolder" value="${fontkit.url.folder}" />

+            <param name="srcFile" value="${fontkit.url.file}" />

+            <param name="cacheFile" value="${fontkit.url.cachefile}" />

+            <param name="dest" value="${basedir}/lib/external/optional/flex-fontkit.jar" />

+			<param name="failmessage" value="flex-fontkit.jar download failed" />

+			<param name="md5" value="${fontkit.url.md5}" />

+        </antcall>

+

+        <echo file="${basedir}/rideau.properties">rideau.echo=${INFO_DOWNLOADING_FILE_FROM}</echo>

+        <replace file="${basedir}/rideau.properties" token="{0}" value="${rideau.url.file}" />

+        <replace file="${basedir}/rideau.properties" token="{1}" value="${rideau.url.server}/${rideau.url.folder}" />

+        <property file="${basedir}/rideau.properties" />

+        <delete file="${basedir}/rideau.properties" />

+        <echo>${rideau.echo}</echo>

+        

+        <antcall target="download_using_get" >

+            <param name="srcDomain" value="${rideau.url.server}" />

+            <param name="srcFolder" value="${rideau.url.folder}" />

+            <param name="srcFile" value="${rideau.url.file}" />

+            <param name="cacheFile" value="${rideau.url.cachefile}" />

+            <param name="dest" value="${basedir}/lib/external/optional/rideau.jar" />

+			<param name="failmessage" value="rideau.jar download failed" />

+			<param name="md5" value="${rideau.url.md5}" />

+        </antcall>

+        

+        <!-- fontkit expects swfutils in the same folder -->

+        <copy file="${basedir}/lib/swfutils.jar" tofile="${basedir}/lib/external/optional/swfutils.jar" />

+    </target>

+

+    <target name="fixup-config-files" depends="flex-sdk-description-flash,flex-sdk-description-air">

+        <echo>${INFO_INSTALLING_CONFIG_FILES}</echo>

+        <antcall target="fixup-config-files-version" />

+        <antcall target="fixup-config-files-swfversion" />

+        <tstamp />

+        <property name="build.number.date" value="${DSTAMP}" />

+        <replace file="${FLEX_HOME}/frameworks/flex-config.xml">

+            <replacefilter token="{playerglobalHome}"

+                value="libs/player"/>

+            <replacefilter token="$${build.number}"

+                value="${release.version}.${build.number.date}"/>

+        </replace>

+        <replace file="${FLEX_HOME}/frameworks/air-config.xml">

+            <replacefilter token="{airHome}/frameworks/libs"

+            value="libs"/>

+            <replacefilter token="$${build.number}"

+                value="${release.version}.${build.number.date}"/>

+        </replace>

+        <replace file="${FLEX_HOME}/frameworks/airmobile-config.xml">

+            <replacefilter token="{airHome}/frameworks/libs"

+            value="libs"/>

+        </replace>

+        <copy file="${FLEX_HOME}/frameworks/flex-config.xml" tofile="${FLEX_HOME}/ide/flashbuilder/config/flex-config.xml" overwrite="true" />

+        <copy file="${FLEX_HOME}/frameworks/air-config.xml" tofile="${FLEX_HOME}/ide/flashbuilder/config/air-config.xml" overwrite="true" />

+        <copy file="${FLEX_HOME}/frameworks/airmobile-config.xml" tofile="${FLEX_HOME}/ide/flashbuilder/config/airmobile-config.xml" overwrite="true" />

+    </target>

+    

+    <target name="fixup-config-files-version" if="flash.version.changed">

+        <replace file="${FLEX_HOME}/frameworks/flex-config.xml">

+            <replacefilter token="&lt;target-player&gt;${playerglobal.version}&lt;/target-player&gt;"

+                            value="&lt;target-player&gt;${flash.sdk.version}&lt;/target-player&gt;"/>

+        </replace>

+        <replace file="${FLEX_HOME}/frameworks/air-config.xml">

+            <replacefilter token="&lt;target-player&gt;${playerglobal.version}&lt;/target-player&gt;"

+            value="&lt;target-player&gt;${flash.sdk.version}&lt;/target-player&gt;"/>

+        </replace>

+        <replace file="${FLEX_HOME}/frameworks/airmobile-config.xml">

+            <replacefilter token="&lt;target-player&gt;${playerglobal.version}&lt;/target-player&gt;"

+            value="&lt;target-player&gt;${flash.sdk.version}&lt;/target-player&gt;"/>

+        </replace>

+    </target>

+    

+    <target name="fixup-config-files-swfversion" if="flash.swfversion.changed">

+        <replace file="${FLEX_HOME}/frameworks/flex-config.xml">

+            <replacefilter token="&lt;swf-version&gt;${flash.sdk.default.swfversion}&lt;/swf-version&gt;"

+                            value="&lt;swf-version&gt;${flash.sdk.swfversion}&lt;/swf-version&gt;"/>

+        </replace>

+        <replace file="${FLEX_HOME}/frameworks/air-config.xml">

+            <replacefilter token="&lt;swf-version&gt;${flash.sdk.default.swfversion}&lt;/swf-version&gt;"

+            value="&lt;swf-version&gt;${flash.sdk.swfversion}&lt;/swf-version&gt;"/>

+        </replace>

+        <replace file="${FLEX_HOME}/frameworks/airmobile-config.xml">

+            <replacefilter token="&lt;swf-version&gt;${flash.sdk.default.swfversion}&lt;/swf-version&gt;"

+            value="&lt;swf-version&gt;${flash.sdk.swfversion}&lt;/swf-version&gt;"/>

+        </replace>

+    </target>

+    

+    <target name="flex-sdk-description-flash" if="flash.version.changed">

+        <replace file="${FLEX_HOME}/flex-sdk-description.xml">

+            <replacefilter token="FP${playerglobal.version}"

+                value="FP${flash.sdk.version}"/>

+        </replace>

+    </target>

+    <target name="flex-sdk-description-air" if="air.version.changed">

+        <replace file="${FLEX_HOME}/flex-sdk-description.xml">

+            <replacefilter token="AIR${air.version}"

+                value="AIR${air.sdk.version}"/>

+        </replace>

+    </target>

+        

+    <target name="download_air" unless="air-has-md5">

+        <antcall target="download_using_get" />

+    </target>

+    <target name="download_air_with_md5" if="air-has-md5">

+        <antcall target="download_using_get" />

+    </target>

+    <target name="download_flash" unless="flash-has-md5">

+        <antcall target="download_using_get" />

+    </target>

+    <target name="download_flash_with_md5" if="flash-has-md5">

+        <antcall target="download_using_get" />

+    </target>

+

+    <!--

+     Download a file and optionally verify the checksum.

+     If the checksum fails, this script fails.  This

+     target uses the cache, if desired.

+     

+     Params are:

+     srcDomain

+     srcFolder

+     srcFile

+     dest

+     [md5]

+     [srcMD5Domain]

+     -->

+    <target name="download_using_get" depends="check-cache"

+        description="Downloads file, and optionally verifies checksum.">

+        

+        <antcall target="get-if-not-cached">

+        </antcall>

+        <antcall target="copy-if-cached">

+        </antcall>

+    </target>

+    

+    <target name="get-if-not-cached" unless="found-in-cache">

+		<antcall target="get-with-no-params" />

+		<antcall target="get-with-params" />

+		<antcall target="get-local" />

+        <antcall target="check-sum" />

+        <condition property="skipCache">

+            <not>

+                <isset property="usingDownloadCache" />

+            </not>

+        </condition>

+        <antcall target="put-in-cache" />

+    </target>

+    

+	<target name="check-params" >

+		<condition property="has-params">

+			<and>

+				<contains string="${srcDomain}/${srcFolder}/${srcFile}" substring="?" />

+				<not>

+					<contains string="${srcDomain}/${srcFolder}/${srcFile}" substring="file://" />

+				</not>

+			</and>

+		</condition>

+		<condition property="is-local">

+			<contains string="${srcDomain}/${srcFolder}/${srcFile}" substring="file://" />

+		</condition>

+		<condition property="not-local-no-params">

+			<and>

+				<not>

+					<contains string="${srcDomain}/${srcFolder}/${srcFile}" substring="file://" />

+				</not>

+				<not>

+					<contains string="${srcDomain}/${srcFolder}/${srcFile}" substring="?" />

+				</not>

+			</and>

+		</condition>

+	</target>

+	

+	<target name="get-local" depends="check-params" if="is-local" >

+        <get src="${srcDomain}/${srcFolder}/${srcFile}" dest="${dest}"/>

+	</target>

+	<target name="get-with-no-params" depends="check-params" if="not-local-no-params" >

+        <get src="${srcDomain}/${srcFolder}/${srcFile}?ts=${ts}" dest="${dest}"/>

+	</target>

+	<target name="get-with-params" depends="check-params" if="has-params" >

+        <get src="${srcDomain}/${srcFolder}/${srcFile}&amp;ts=${ts}" dest="${dest}"/>

+	</target>

+	

+    <target name="copy-if-cached" if="found-in-cache">

+		<condition property="cacheFile" value="${srcFile}" >

+			<not>

+				<isset property="cacheFile" />

+			</not>

+		</condition>

+		<echo>${INFO_USING_CACHED_FILE} ${downloadCacheFolder}/${srcFolder}/${cacheFile}</echo>

+        <copy file="${downloadCacheFolder}/${srcFolder}/${cacheFile}" tofile="${dest}" overwrite="true" />

+    </target>

+    

+    <target name="check-cache" if="usingDownloadCache">

+		<condition property="cacheFile" value="${srcFile}" >

+			<not>

+				<isset property="cacheFile" />

+			</not>

+		</condition>

+        <available file="${downloadCacheFolder}/${srcFolder}/${cacheFile}" property="found-in-cache" />

+    </target>

+    

+    <target name="put-in-cache" unless="skipCache">

+		<condition property="cacheFile" value="${srcFile}" >

+			<not>

+				<isset property="cacheFile" />

+			</not>

+		</condition>

+        <copy tofile="${downloadCacheFolder}/${srcFolder}/${cacheFile}" file="${dest}" />

+    </target>

+    

+    <target name="check-sum" if="md5"

+        description="Verifies MD5 checksum, and fails if checksum doesn't match">

+        

+        <echo>${INFO_VALIDATING_FILE} ${dest}</echo>

+        <checksum file="${dest}" algorithm="MD5" verifyproperty="we.failed" property="${md5}" />

+        <fail message="${failmessage}">

+            <condition>

+                <equals arg1="${we.failed}" arg2="false" />

+            </condition>

+        </fail>

+    </target>

+</project>

diff --git a/licenseParts/NOTICE.asc b/licenseParts/NOTICE.asc
index 1c55ec9..e53dfe0 100644
--- a/licenseParts/NOTICE.asc
+++ b/licenseParts/NOTICE.asc
@@ -1,5 +1,5 @@
 Apache Flex
-Copyright 2012-2016 The Apache Software Foundation
+Copyright 2012-2017 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/licenseParts/NOTICE.base b/licenseParts/NOTICE.base
index d89968c..c9e609e 100644
--- a/licenseParts/NOTICE.base
+++ b/licenseParts/NOTICE.base
@@ -1,5 +1,5 @@
 Apache Flex
-Copyright 2012-2016 The Apache Software Foundation
+Copyright 2012-2017 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/licenseParts/NOTICE.pb b/licenseParts/NOTICE.pb
index 0ac5a3a..ae5b56a 100644
--- a/licenseParts/NOTICE.pb
+++ b/licenseParts/NOTICE.pb
@@ -1,5 +1,5 @@
 Apache Flex
-Copyright 2012-2016 The Apache Software Foundation
+Copyright 2012-2017 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/licenseParts/saxon9-NOTICES/APACHE-ANT.txt b/licenseParts/saxon9-NOTICES/APACHE-ANT.txt
new file mode 100644
index 0000000..f80fc57
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/APACHE-ANT.txt
@@ -0,0 +1,13 @@
+Apache Ant
+Copyright 1999-2006 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+This product includes also software developed by :
+  - the W3C consortium (http://www.w3c.org) ,
+  - the SAX project (http://www.saxproject.org)
+
+The <sync> task is based on code Copyright (c) 2002, Landmark
+Graphics Corp that has been kindly donated to the Apache Software
+Foundation.
diff --git a/licenseParts/saxon9-NOTICES/APACHE-RESOLVER.txt b/licenseParts/saxon9-NOTICES/APACHE-RESOLVER.txt
new file mode 100644
index 0000000..cf064e3
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/APACHE-RESOLVER.txt
@@ -0,0 +1,9 @@
+Apache XML Commons Resolver
+Copyright 2006 The Apache Software Foundation.
+
+This product includes software developed at
+The Apache Software Foundation http://www.apache.org/
+
+Portions of this code are derived from classes placed in the
+public domain by Arbortext on 10 Apr 2000. See:
+http://www.arbortext.com/customer_support/updates_and_technical_notes/catalogs/docs/README.htm
diff --git a/licenseParts/saxon9-NOTICES/APACHE-XERCES.txt b/licenseParts/saxon9-NOTICES/APACHE-XERCES.txt
new file mode 100644
index 0000000..602c753
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/APACHE-XERCES.txt
@@ -0,0 +1,17 @@
+   =========================================================================
+   ==  NOTICE file corresponding to section 4(d) of the Apache License,   ==
+   ==  Version 2.0, in this case for the Apache Xerces Java distribution. ==
+   =========================================================================
+
+   Apache Xerces Java
+   Copyright 1999-2006 The Apache Software Foundation
+
+   This product includes software developed at
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Portions of this software were originally based on the following:
+     - software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
+     - software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
+     - voluntary contributions made by Paul Eng on behalf of the 
+       Apache Software Foundation that were originally developed at iClick, Inc.,
+       software copyright (c) 1999.
\ No newline at end of file
diff --git a/licenseParts/saxon9-NOTICES/CERN.txt b/licenseParts/saxon9-NOTICES/CERN.txt
new file mode 100644
index 0000000..23a43ea
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/CERN.txt
@@ -0,0 +1,7 @@
+Copyright © 1999 CERN - European Organization for Nuclear Research.<br/><br/>
+
+Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose
+is hereby granted without fee, provided that the above copyright notice appear in all copies and
+that both that copyright notice and this permission notice appear in supporting documentation.
+CERN makes no representations about the suitability of this software for any purpose.
+It is provided "as is" without expressed or implied warranty.
\ No newline at end of file
diff --git a/licenseParts/saxon9-NOTICES/FRIJTERS.txt b/licenseParts/saxon9-NOTICES/FRIJTERS.txt
new file mode 100644
index 0000000..827e26a
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/FRIJTERS.txt
@@ -0,0 +1,22 @@
+Copyright (C) 2002-2007 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+  
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+  
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+     
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+     
+  3. This notice may not be removed or altered from any source distribution.
+  
+  Jeroen Frijters
+  jeroen@frijters.net
diff --git a/licenseParts/saxon9-NOTICES/GPL+CLASSPATH.txt b/licenseParts/saxon9-NOTICES/GPL+CLASSPATH.txt
new file mode 100644
index 0000000..eeab58c
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/GPL+CLASSPATH.txt
@@ -0,0 +1,347 @@
+The GNU General Public License (GPL)
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it.  By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.  This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it.  (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price.  Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights.  These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for
+a fee, you must give the recipients all the rights that you have.  You must
+make sure that they, too, receive or can get the source code.  And you must
+show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software.  If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents.  We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License.  The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language.  (Hereinafter, translation is included
+without limitation in the term "modification".) Each licensee is addressed as
+"you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope.  The act of running the Program is
+not restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program).  Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such modifications
+or work under the terms of Section 1 above, provided that you also meet all of
+these conditions:
+
+    a) You must cause the modified files to carry prominent notices stating
+    that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in whole or
+    in part contains or is derived from the Program or any part thereof, to be
+    licensed as a whole at no charge to all third parties under the terms of
+    this License.
+
+    c) If the modified program normally reads commands interactively when run,
+    you must cause it, when started running for such interactive use in the
+    most ordinary way, to print or display an announcement including an
+    appropriate copyright notice and a notice that there is no warranty (or
+    else, saying that you provide a warranty) and that users may redistribute
+    the program under these conditions, and telling the user how to view a copy
+    of this License.  (Exception: if the Program itself is interactive but does
+    not normally print such an announcement, your work based on the Program is
+    not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License, and
+its terms, do not apply to those sections when you distribute them as separate
+works.  But when you distribute the same sections as part of a whole which is a
+work based on the Program, the distribution of the whole must be on the terms
+of this License, whose permissions for other licensees extend to the entire
+whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable source
+    code, which must be distributed under the terms of Sections 1 and 2 above
+    on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three years, to
+    give any third party, for a charge no more than your cost of physically
+    performing source distribution, a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of Sections 1
+    and 2 above on a medium customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer to
+    distribute corresponding source code.  (This alternative is allowed only
+    for noncommercial distribution and only if you received the program in
+    object code or executable form with such an offer, in accord with
+    Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it.  For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and installation
+of the executable.  However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License.  Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License.  However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works.  These actions are prohibited by law if you do not
+accept this License.  Therefore, by modifying or distributing the Program (or
+any work based on the Program), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to
+copy, distribute or modify the Program subject to these terms and conditions.
+You may not impose any further restrictions on the recipients' exercise of the
+rights granted herein.  You are not responsible for enforcing compliance by
+third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License.  If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices.  Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded.  In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time.  Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems
+or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software Foundation.
+If the Program does not specify a version number of this License, you may
+choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission.  For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
+PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible
+use to the public, the best way to achieve this is to make it free software
+which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program.  It is safest to attach
+them to the start of each source file to most effectively convey the exclusion
+of warranty; and each file should have at least the "copyright" line and a
+pointer to where the full notice is found.
+
+    One line to give the program's name and a brief idea of what it does.
+
+    Copyright (C) <year> <name of author>
+
+    This program is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation; either version 2 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc., 59
+    Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when it
+starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
+    with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free
+    software, and you are welcome to redistribute it under certain conditions;
+    type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may be
+called something other than 'show w' and 'show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.  Here
+is a sample; alter the names:
+
+    Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+    'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+    signature of Ty Coon, 1 April 1989
+
+    Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General Public
+License instead of this License.
+
+
+"CLASSPATH" EXCEPTION TO THE GPL
+
+Certain source files distributed by Sun Microsystems, Inc.  are subject to
+the following clarification and special exception to the GPL, but only where
+Sun has expressly included in the particular source file's header the words
+"Sun designates this particular file as subject to the "Classpath" exception
+as provided by Sun in the LICENSE file that accompanied this code."
+
+    Linking this library statically or dynamically with other modules is making
+    a combined work based on this library.  Thus, the terms and conditions of
+    the GNU General Public License cover the whole combination.
+
+    As a special exception, the copyright holders of this library give you
+    permission to link this library with independent modules to produce an
+    executable, regardless of the license terms of these independent modules,
+    and to copy and distribute the resulting executable under terms of your
+    choice, provided that you also meet, for each linked independent module,
+    the terms and conditions of the license of that module.  An independent
+    module is a module which is not derived from or based on this library.  If
+    you modify this library, you may extend this exception to your version of
+    the library, but you are not obligated to do so.  If you do not wish to do
+    so, delete this exception statement from your version.
diff --git a/licenseParts/saxon9-NOTICES/JAMESCLARK.txt b/licenseParts/saxon9-NOTICES/JAMESCLARK.txt
new file mode 100644
index 0000000..36b9918
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/JAMESCLARK.txt
@@ -0,0 +1,25 @@
+Copyright (c) 1998, 1999 James Clark
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL JAMES CLARK BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of James Clark shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from James Clark.
diff --git a/licenseParts/saxon9-NOTICES/LEGAL.txt b/licenseParts/saxon9-NOTICES/LEGAL.txt
new file mode 100644
index 0000000..8e2a59b
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/LEGAL.txt
@@ -0,0 +1,33 @@
+LEGAL NOTICE
+
+This notice is issued to fulfil the requirements of the Mozilla Public License version 1.0 ("MPL 1.0")
+sections 3.4(a) and 3.6. MPL 1.0 can be found at http://www.mozilla.org/MPL/MPL-1.0.html. 
+
+Section 3.4(a) of MPL 1.0 states that any third party intellectual property rights in particular 
+functionality or code must be notified in a text file named LEGAL that is issued with the source code. Saxon 
+includes a number of such third party components, and the relevant claims are included in notices included
+in the same directory as this notice. Although MPL 1.0 requires this notice to be included only with source
+code, some of the third parties may also require notices to be included with executable code. Therefore, Saxon
+executable code must not be distributed separately from this notice and all the accompanying third
+party notices. The term "Distribution" here includes making the code available for download, and its 
+inclusion in download repositories such as Maven.
+
+Section 3.6 of MPL 1.0 states:
+
+You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have 
+been met for that Covered Code, and if You include a notice stating that the Source Code version of 
+the Covered Code is available under the terms of this License, including a description of how and 
+where You have fulfilled the obligations of Section 3.2.
+
+Section 3.2 requires the Source Code of Covered Code to be made available via an accepted Electronic
+Distribution Mechanism.
+
+The Source Code version of the Covered Code (that is, the source code of Saxon-B) is available under the 
+terms of the Mozilla Public License version 1.0, and may be obtained from the Subversion repository 
+for the Saxon project on SourceForge, at https://sourceforge.net/svn/?group_id=29872. 
+The precise version of the Subversion source for a particular Saxon maintenance release can be 
+determined by referring to the release notes for the particular release in the SourceForge download area.
+
+Note that MPL 1.0 requires that any modifications to this source code must be made available under the terms
+of the MPL "to anyone to whom you made an executable version available". As a courtesy, it is also requested 
+that you make such modifications available to Saxonica Limited.
\ No newline at end of file
diff --git a/licenseParts/saxon9-NOTICES/LICENSE.txt b/licenseParts/saxon9-NOTICES/LICENSE.txt
new file mode 100644
index 0000000..331abb1
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/LICENSE.txt
@@ -0,0 +1,15 @@
+The contents of these file are subject to the Mozilla Public License Version 1.0 (the "License"); 
+you may not use these files except in compliance with the License. You may obtain a copy of the 
+License at http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS" basis, 
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
+specific language governing rights and limitations under the License.
+
+The Original Code is all Saxon modules labelled with a notice referring to this license.
+
+The Initial Developer of the Original Code is Michael Kay, except where otherwise specified in an individual module.
+
+Portions created by other named contributors are copyright as identified in the relevant module. All Rights Reserved.
+
+Contributor(s) are listed in the documentation: see notices/contributors. 
\ No newline at end of file
diff --git a/licenseParts/saxon9-NOTICES/THAI.txt b/licenseParts/saxon9-NOTICES/THAI.txt
new file mode 100644
index 0000000..3fe0aaa
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/THAI.txt
@@ -0,0 +1,31 @@
+Copyright (c) 2001-2003 Thai Open Source Software Center Ltd
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    Neither the name of the Thai Open Source Software Center Ltd nor
+    the names of its contributors may be used to endorse or promote
+    products derived from this software without specific prior written
+    permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/licenseParts/saxon9-NOTICES/UNICODE.txt b/licenseParts/saxon9-NOTICES/UNICODE.txt
new file mode 100644
index 0000000..54afc82
--- /dev/null
+++ b/licenseParts/saxon9-NOTICES/UNICODE.txt
@@ -0,0 +1,29 @@
+COPYRIGHT AND PERMISSION NOTICE
+Copyright © 1991-2007 Unicode, Inc. All rights reserved. Distributed under the Terms of Use 
+in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode 
+data files and any associated documentation (the "Data Files") or Unicode software and any 
+associated documentation (the "Software") to deal in the Data Files or Software without 
+restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+and/or sell copies of the Data Files or Software, and to permit persons to whom the Data Files or 
+Software are furnished to do so, provided that (a) the above copyright notice(s) and this 
+permission notice appear with all copies of the Data Files or Software, (b) both the above 
+copyright notice(s) and this permission notice appear in associated documentation, and 
+(c) there is clear notice in each modified Data File or in the Software as well as in the 
+documentation associated with the Data File(s) or Software that the data or software has 
+been modified.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE 
+BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA 
+FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not be used 
+in advertising or otherwise to promote the sale, use or other dealings in these 
+Data Files or Software without prior written authorization of the copyright holder.
diff --git a/modules/asc/src/java/macromedia/asc/embedding/Main.java b/modules/asc/src/java/macromedia/asc/embedding/Main.java
index 0ea60ee..c67841c 100644
--- a/modules/asc/src/java/macromedia/asc/embedding/Main.java
+++ b/modules/asc/src/java/macromedia/asc/embedding/Main.java
@@ -387,7 +387,7 @@
 		{
 			System.out.println("ActionScript 3.0 for AVM+");
 			System.out.println("version " + Version.getVersion() + " build "+ Version.getBuild());
-			System.out.println("Copyright 2016 The Apache Software Foundation");
+			System.out.println("Copyright 2017 The Apache Software Foundation");
 			System.out.println("All rights reserved\n");
 			System.out.println("Usage:");
 			System.out.println("  asc {-AS3|-ES|-d|-f|-h|-i|-import <filename>|-in <filename>|-m|-p}* filespec");
diff --git a/modules/asc/src/java/macromedia/asc/embedding/Shell.java b/modules/asc/src/java/macromedia/asc/embedding/Shell.java
index 0f6b73a..0dec83a 100644
--- a/modules/asc/src/java/macromedia/asc/embedding/Shell.java
+++ b/modules/asc/src/java/macromedia/asc/embedding/Shell.java
@@ -587,7 +587,7 @@
 	private static void intro()
 	{
 		System.out.println("Actionscript compiler SHell (ash)");
-		System.out.println("Copyright 2016 The Apache Software Foundation");
+		System.out.println("Copyright 2017 The Apache Software Foundation");
 		System.out.println("");
 	}
 
diff --git a/modules/asc/src/java/macromedia/asc/embedding/SwfMaker.java b/modules/asc/src/java/macromedia/asc/embedding/SwfMaker.java
index c7cff7f..961d703 100644
--- a/modules/asc/src/java/macromedia/asc/embedding/SwfMaker.java
+++ b/modules/asc/src/java/macromedia/asc/embedding/SwfMaker.java
@@ -40,6 +40,8 @@
 	public static final int swfFlagsNoCrossdomainCache  = 0x00000004;  // do not add this SWF to the Asset Cache
 	public static final int swfFlagsAS3                 = 0x00000008;  // this SWF contains AVM+ bytecodes
 	public static final int swfFlagsHasMetadata         = 0x00000010;  // this SWF contains stagMetadata somewhere
+    public static final int swfFlagsBrokerLocalConnection = 0x00004000;  // broker local connections
+    public static final int swfFlagsBrokerProductManager = 0x00008000;  // broker product manager
 	// (this is not relevant to the player, but is relevant to search engines)
 	public static final int kDefaultSwfFlags            = 0x00000000;   // these flags are assumed when no stagFileAttributes is present
 
@@ -229,6 +231,8 @@
 		String className = null;
 		int width, height, fps = 12;
         int useNetwork=0;
+        int brokerLocalConnection=0;
+        int brokerProductManager=0;
 
         boolean debug = false;
 		int dAt = options.indexOf(",-g");
@@ -243,6 +247,16 @@
             useNetwork=swfFlagsUseNetwork;
             options = options.substring(0, dAt) + options.substring(dAt+12);
         }
+        dAt = options.indexOf(",-brokerLocalConnection");
+        if (dAt>-1) {
+            brokerLocalConnection=swfFlagsBrokerLocalConnection;
+            options = options.substring(0, dAt) + options.substring(dAt+23);
+        }
+        dAt = options.indexOf(",-brokerProductManager");
+        if (dAt>-1) {
+            brokerProductManager=swfFlagsBrokerProductManager;
+            options = options.substring(0, dAt) + options.substring(dAt+22);
+        }
 
         StringTokenizer tokenizer = new StringTokenizer(options, ",");
 		switch (tokenizer.countTokens())
@@ -282,7 +296,7 @@
 		PutWord(1);       // # of frames  SDD ### Change to sensicle number
 
 		StartTag(stagFileAttributes, false);
-		PutDWord(swfFlagsAS3|useNetwork);
+		PutDWord(swfFlagsAS3|useNetwork|brokerLocalConnection|brokerProductManager);
 		FinishTag();
 
 		if (debug)
diff --git a/modules/compiler/src/java/flex2/compiler/common/Configuration.java b/modules/compiler/src/java/flex2/compiler/common/Configuration.java
index 9c89347..dfc2906 100644
--- a/modules/compiler/src/java/flex2/compiler/common/Configuration.java
+++ b/modules/compiler/src/java/flex2/compiler/common/Configuration.java
@@ -1167,6 +1167,38 @@
         this.useNetwork = b;
     }
 
+    //
+    // 'broker-local-connection' option
+    //
+    
+    private boolean brokerLocalConnection;
+    
+    public boolean brokerLocalConnection()
+    {
+        return brokerLocalConnection;
+    }
+    
+    public void cfgBrokerLocalConnection( ConfigurationValue cv, boolean b)
+    {
+        this.brokerLocalConnection = b;
+    }
+    
+    //
+    // 'broker-product-manager' option
+    //
+    
+    private boolean brokerProductManager;
+    
+    public boolean brokerProductManager()
+    {
+        return brokerProductManager;
+    }
+    
+    public void cfgBrokerProductManager( ConfigurationValue cv, boolean b)
+    {
+        this.brokerProductManager = b;
+    }
+    
     
 
 	/**
diff --git a/modules/compiler/src/java/flex2/linker/LinkerConfiguration.java b/modules/compiler/src/java/flex2/linker/LinkerConfiguration.java
index 28dd782..75adf5c 100644
--- a/modules/compiler/src/java/flex2/linker/LinkerConfiguration.java
+++ b/modules/compiler/src/java/flex2/linker/LinkerConfiguration.java
@@ -47,6 +47,10 @@
 
 	boolean useNetwork();
 
+    boolean brokerLocalConnection();
+    
+    boolean brokerProductManager();
+    
 	boolean lazyInit();
 
     boolean scriptLimitsSet();
diff --git a/modules/compiler/src/java/flex2/linker/SimpleMovie.java b/modules/compiler/src/java/flex2/linker/SimpleMovie.java
index fe59138..8a0f138 100644
--- a/modules/compiler/src/java/flex2/linker/SimpleMovie.java
+++ b/modules/compiler/src/java/flex2/linker/SimpleMovie.java
@@ -128,6 +128,16 @@
 	            fileAttributes.actionScript3 = (version >= 9);
             }
             
+            if (configuration.brokerLocalConnection())
+            {
+                fileAttributes.brokerLocalConnection = true;
+            }
+            
+            if (configuration.brokerProductManager())
+            {
+                fileAttributes.brokerProductManager = true;
+            }
+            
             if (configuration.getAdvancedTelemetry()) {
             	enableTelemetry.enabled = true;
             }
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_da.properties b/modules/compiler/src/java/flex2/tools/ASDoc_da.properties
index aa0fdf7..ea7cca6 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_da.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_da.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=Dokumentationen er oprettet i ${location}
 ValidationMessage=Der blev fundet tekst med forkert format. Der er flere oplysninger i ${file}.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_de.properties b/modules/compiler/src/java/flex2/tools/ASDoc_de.properties
index 2cf7653..59303a3 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_de.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_de.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=Dokumentation wurde erstellt unter: ${location}
 ValidationMessage=Gefundener nicht wohlgeformter Text. Zu Details siehe ${file}.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_en.properties b/modules/compiler/src/java/flex2/tools/ASDoc_en.properties
index fb1cf7f..c823aba 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_en.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_en.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=Documentation was created in ${location}
 ValidationMessage=Encountered not well-formed text. Please see ${file} for details.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_es.properties b/modules/compiler/src/java/flex2/tools/ASDoc_es.properties
index 65fa11a..9b98c5f 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_es.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_es.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=La documentaci\u00f3n se cre\u00f3 en ${location}
 ValidationMessage=Se ha encontrado texto con formato incorrecto. Consulte ${file} para ver los detalles.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_fi.properties b/modules/compiler/src/java/flex2/tools/ASDoc_fi.properties
index b94bec0..6520248 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_fi.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_fi.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=Dokumentaatio luotiin hakemistoon ${location}
 ValidationMessage=Kohdattiin teksti, jota ei ole muodostettu hyvin. Katso lis\u00e4tietoja tiedostosta ${file}.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_fr.properties b/modules/compiler/src/java/flex2/tools/ASDoc_fr.properties
index 9933414..e84dbe0 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_fr.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_fr.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=La documentation a \u00e9t\u00e9 cr\u00e9\u00e9e sous ${location}.
 ValidationMessage=Texte incorrectement mis en forme rencontr\u00e9. Veuillez consulter ${file} pour plus de d\u00e9tails.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_it.properties b/modules/compiler/src/java/flex2/tools/ASDoc_it.properties
index a6bb88e..f0d0c20 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_it.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_it.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=La documentazione \u00e8 stata creata in ${location}
 ValidationMessage=Rilevato testo non ben formato. Vedere ${file} per ulteriori dettagli.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_ja.properties b/modules/compiler/src/java/flex2/tools/ASDoc_ja.properties
index 3a778c4..b790734 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_ja.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_ja.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306f ${location} \u306b\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f
 ValidationMessage=\u9069\u683c\u306a\u5f62\u5f0f\u3067\u306a\u3044\u30c6\u30ad\u30b9\u30c8\u304c\u691c\u51fa\u3055\u308c\u307e\u3057\u305f\u3002\u8a73\u7d30\u306b\u3064\u3044\u3066\u306f\u3001${file} \u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_ko.properties b/modules/compiler/src/java/flex2/tools/ASDoc_ko.properties
index 1f7dfab..bb4e30e 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_ko.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_ko.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=${location}\uc5d0\uc11c \uc791\uc131\ub41c \ubb38\uc11c
 ValidationMessage=\uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ud615\uc2dd\uc758 \ud14d\uc2a4\ud2b8\uc785\ub2c8\ub2e4. \uc790\uc138\ud55c \ub0b4\uc6a9\uc740 ${file}\uc744(\ub97c) \ucc38\uc870\ud558\uc2ed\uc2dc\uc624.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_nb.properties b/modules/compiler/src/java/flex2/tools/ASDoc_nb.properties
index e149dd2..53bebcf 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_nb.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_nb.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=Dokumentasjon ble opprettet i ${location}
 ValidationMessage=Fant tekst som ikke er godt utformet. Se i ${file} hvis du vil vite mer.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_nl.properties b/modules/compiler/src/java/flex2/tools/ASDoc_nl.properties
index 023c4e3..d89845a 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_nl.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_nl.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=Documentatie is gemaakt in ${location}
 ValidationMessage=Onjuist opgemaakte tekst aangetroffen. Zie ${file} voor details.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_pt.properties b/modules/compiler/src/java/flex2/tools/ASDoc_pt.properties
index da6e452..fe3ef58 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_pt.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_pt.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=A documenta\u00e7\u00e3o foi criada em ${location}
 ValidationMessage=Foi encontrado um texto que n\u00e3o est\u00e1 bem-formado. Para obter detalhes, consulte ${file}.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_ru.properties b/modules/compiler/src/java/flex2/tools/ASDoc_ru.properties
index 3088bdb..1f124bd 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_ru.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_ru.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0430 \u0432 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0438 ${location}
 ValidationMessage=\u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442. \u0421\u043c. \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0432 \u0444\u0430\u0439\u043b\u0435 ${file}.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_sv.properties b/modules/compiler/src/java/flex2/tools/ASDoc_sv.properties
index 3482ce1..f70417a 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_sv.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_sv.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=Dokumentationen har skapats i ${location}
 ValidationMessage=Felaktigt formaterad text uppt\u00e4cktes. Mer information finns i ${file}.
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_zh_CN.properties b/modules/compiler/src/java/flex2/tools/ASDoc_zh_CN.properties
index fde9b8a..e40b158 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_zh_CN.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_zh_CN.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=\u6587\u6863\u521b\u5efa\u5728\u201c${location}\u201d\u4e2d
 ValidationMessage=\u9047\u5230\u683c\u5f0f\u9519\u8bef\u7684\u6587\u672c\u3002\u6709\u5173\u8be6\u7ec6\u4fe1\u606f\uff0c\u8bf7\u53c2\u9605 ${file}\u3002
diff --git a/modules/compiler/src/java/flex2/tools/ASDoc_zh_TW.properties b/modules/compiler/src/java/flex2/tools/ASDoc_zh_TW.properties
index 9ff24b4..7a8eb5c 100644
--- a/modules/compiler/src/java/flex2/tools/ASDoc_zh_TW.properties
+++ b/modules/compiler/src/java/flex2/tools/ASDoc_zh_TW.properties
@@ -18,6 +18,6 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of ASDoc
-StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex ASDoc \n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 OutputMessage=\u6587\u4ef6\u5efa\u7acb\u65bc\u201c${location}\u201d
 ValidationMessage=\u9047\u5230\u683c\u5f0f\u4e0d\u6b63\u78ba\u7684\u6587\u5b57\u3002\u8acb\u53c3\u95b1 ${file} \u4ee5\u7372\u53d6\u8a73\u7d30\u8cc7\u8a0a\u3002
diff --git a/modules/compiler/src/java/flex2/tools/Compc_da.properties b/modules/compiler/src/java/flex2/tools/Compc_da.properties
index 592ca1c..6c18e8c 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_da.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_da.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} er opdateret og skal ikke bygges igen.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_de.properties b/modules/compiler/src/java/flex2/tools/Compc_de.properties
index 426546f..d4b6f70 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_de.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_de.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} ist auf dem aktuellen Stand und muss nicht neu erstellt werden.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_en.properties b/modules/compiler/src/java/flex2/tools/Compc_en.properties
index db2111a..8b93a71 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_en.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_en.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} is up-to-date and does not have to be rebuilt.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_es.properties b/modules/compiler/src/java/flex2/tools/Compc_es.properties
index b2d6e99..cd025d2 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_es.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_es.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} est\u00e1 actualizado y no necesita ser reconstruido.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_fi.properties b/modules/compiler/src/java/flex2/tools/Compc_fi.properties
index 5c1864e..84da670 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_fi.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_fi.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} on ajan tasalla, eik\u00e4 sit\u00e4 tarvitse muodostaa uudelleen.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_fr.properties b/modules/compiler/src/java/flex2/tools/Compc_fr.properties
index ae55317..5c41752 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_fr.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_fr.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} est \u00e0 jour et n'a pas besoin d'\u00eatre r\u00e9g\u00e9n\u00e9r\u00e9.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_it.properties b/modules/compiler/src/java/flex2/tools/Compc_it.properties
index 6218a1c..6a5143a 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_it.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_it.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} \u00e8 aggiornato e non \u00e8 necessario rigenerarlo.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_ja.properties b/modules/compiler/src/java/flex2/tools/Compc_ja.properties
index 9d541c1..60f59b1 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_ja.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_ja.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} \u306f\u6700\u65b0\u3067\u3059\u3002\u30ea\u30d3\u30eb\u30c9\u3059\u308b\u5fc5\u8981\u306f\u3042\u308a\u307e\u305b\u3093\u3002
diff --git a/modules/compiler/src/java/flex2/tools/Compc_ko.properties b/modules/compiler/src/java/flex2/tools/Compc_ko.properties
index d4a5a8a..cf591d6 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_ko.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_ko.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name}\uc740(\ub294) \ucd5c\uc2e0 \ubc84\uc804\uc774\ubbc0\ub85c \ub2e4\uc2dc \ube4c\ub4dc\ud560 \ud544\uc694\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_nb.properties b/modules/compiler/src/java/flex2/tools/Compc_nb.properties
index 3f99439..1898f9e 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_nb.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_nb.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} er oppdatert og trenger ikke \u00e5 bygges p\u00e5 nytt.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_nl.properties b/modules/compiler/src/java/flex2/tools/Compc_nl.properties
index b818bca..518d247 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_nl.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_nl.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} is up-to-date en hoeft niet opnieuw te worden gemaakt.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_pt.properties b/modules/compiler/src/java/flex2/tools/Compc_pt.properties
index 211c748..cd13a23 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_pt.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_pt.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${name} est\u00e1 atualizado e n\u00e3o \u00e9 preciso recri\u00e1-lo.
diff --git a/modules/compiler/src/java/flex2/tools/Compc_ru.properties b/modules/compiler/src/java/flex2/tools/Compc_ru.properties
index c9b7873..5b3d7f2 100644
--- a/modules/compiler/src/java/flex2/tools/Compc_ru.properties
+++ b/modules/compiler/src/java/flex2/tools/Compc_ru.properties
@@ -18,5 +18,5 @@
 ################################################################################
 
 # localization strings for messages defined as inner classes of Compc
-StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2016 The Apache Software Foundation.\n
+StartMessage=Apache Flex compc (Component Compiler)\n${buildMessage}\nCopyright 2017 The Apache Software Foundation.\n
 NoUpdateMessage=${n