Transferred from the Adobe Open Source Subversion Repository

Revision: 18543
Author:   rfrishbe@adobe.com
Date:     2010-11-11T21:39:53.401769Z

Log Message:
-----------
Making some PARB changes around down state support and InteractionStateDetector.  ItemRendererInteractionStateDetector has been renamed to InteractionStateDetector.  down state is now applicable in mouse interactionMode.  downColor defaults to undefined, and is only set in the mobiletheme--this way it won't break the mouse interaction case.

Fixing up ItemRenderer transitions.  Added a new method, invalidateRendererState().  We now don't transition immediately to the state when the selected, hovered, etc.. properties get set, but we wait until validation.

QE notes:
Doc notes:
Bugs: SDK-28482
Reviewer: Eric Day, Glenn
Tests run: checkintests, mustella DataGroup, List, ListDND
Is noteworthy for integration: No

Modified Paths:
--------------
<path kind="file" copyfrom-path="/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/supportClasses/ItemRendererInteractionStateDetector.as" copyfrom-rev="18476" action="A">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/supportClasses/InteractionStateDetector.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/Scroller.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/SparkClasses.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/SkinnableContainer.as</path>
<path kind="file" action="D">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/supportClasses/ItemRendererInteractionStateDetector.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/mobilecomponents/src/spark/components/MobileItemRenderer.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/mobiletheme/defaults.css</path>
<path kind="file" action="A">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/supportClasses/InteractionState.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/List.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/skins/spark/DefaultItemRenderer.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/framework/defaults.css</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/wireframe/src/spark/skins/wireframe/DefaultItemRenderer.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/supportClasses/ItemRenderer.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/supportClasses/GroupBase.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/wireframe/defaults.css</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1289263 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/wireframe/src/spark/skins/wireframe/DefaultItemRenderer.as
+++ frameworks/projects/wireframe/src/spark/skins/wireframe/DefaultItemRenderer.as
@@ -26,7 +26,8 @@

 import spark.components.IItemRenderer;
 import spark.components.Label;
-import spark.components.supportClasses.ItemRendererInteractionStateDetector;
+import spark.components.supportClasses.InteractionState;
+import spark.components.supportClasses.InteractionStateDetector;
 import spark.components.supportClasses.TextBase;

 use namespace mx_internal;
@@ -75,11 +76,16 @@
 [Style(name="alternatingItemColors", type="Array", arrayType="uint", format="Color", inherit="yes", theme="spark")]

 /**
- *  Color of the background of an item renderer when it is pressed down.
+ *  Color of the background of an item renderer when it is being pressed down.
+ *
+ *
If downColor is set to undefined,
+ *  downColor is not used.

  *
- *
This style is only applicable in touch interactionMode.

- *
- *  @default #CCCCCC
+ *
The default value in the
+ *  spark theme is undefined.  The default value in the
+ *  mobile theme is 0xB2B2B2.

+ *
+ *  @default undefined
  *
  *  @langversion 3.0
  *  @playerversion Flash 10.1
@@ -173,8 +179,8 @@
     {
         super();

-        itemRendererInteractionStateDetector = new ItemRendererInteractionStateDetector(this);
-        itemRendererInteractionStateDetector.addEventListener(Event.CHANGE, itemRendererInteractionStateDetector_changeHandler);
+        interactionStateDetector = new InteractionStateDetector(this);
+        interactionStateDetector.addEventListener(Event.CHANGE, interactionStateDetector_changeHandler);
     }

     //--------------------------------------------------------------------------
@@ -193,7 +199,7 @@
      *  @private
      *  Helper class to help determine when we are in the hovered or down state
      */
-    private var itemRendererInteractionStateDetector:ItemRendererInteractionStateDetector;
+    private var interactionStateDetector:InteractionStateDetector;

     //--------------------------------------------------------------------------
     //
@@ -489,11 +495,13 @@

         var backgroundColor:uint;
         var drawBackground:Boolean = true;
-        if (itemRendererInteractionStateDetector.down)
-            backgroundColor = getStyle("downColor");
+        var downColor:* = getStyle("downColor");
+
+        if (interactionStateDetector.state == InteractionState.DOWN && downColor !== undefined)
+            backgroundColor = downColor;
         else if (selected)
             backgroundColor = getStyle("selectionColor");
-        else if (itemRendererInteractionStateDetector.hovered)
+        else if (interactionStateDetector.state == InteractionState.OVER)
             backgroundColor = getStyle("rollOverColor");
         else
         {
@@ -550,7 +558,7 @@
     /**
      *  @private
      */
-    private function itemRendererInteractionStateDetector_changeHandler(event:Event):void
+    private function interactionStateDetector_changeHandler(event:Event):void
     {
         invalidateDisplayList();
     }


Pen cursor no longer shows up while mousing already-linked dest port

--- src/LevelStates/LevelState.as
+++ src/LevelStates/LevelState.as
@@ -902,8 +902,11 @@

 			if (blocMoused)
 				return Cursor.GRAB;
-			if (level.canDrawWires && findMousedCarrier())
-				return Cursor.PEN;
+			if (level.canDrawWires) {
+				var carrier:Carrier = findMousedCarrier();
+				if (carrier && (carrier.isSource() || !carrier.getSource()))
+					return Cursor.PEN;
+			}
 			return null;
 		}


Transferred from the Adobe Open Source Subversion Repository

Revision: 23246
Author:   cframpto@adobe.com
Date:     2011-12-20T17:40:08.069454Z

Log Message:
-----------
Rollback 23243.  If comment followed header it was stripped as well.

Modified Paths:
--------------
2361 paths were modified

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1290577 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/advancedgrids/src/mx/olap/IOLAPSet.as
+++ frameworks/projects/advancedgrids/src/mx/olap/IOLAPSet.as
@@ -1,3 +1,13 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  ADOBE SYSTEMS INCORPORATED
+//  Copyright 2009 Adobe Systems Incorporated
+//  All Rights Reserved.
+//
+//  NOTICE: Adobe permits you to use, modify, and distribute this file
+//  in accordance with the terms of the license agreement accompanying it.
+//
+////////////////////////////////////////////////////////////////////////////////

 package mx.olap
 {


Added support for 480dpi

Added support for 480dpi

--- frameworks/projects/framework/src/mx/utils/DensityUtil.as
+++ frameworks/projects/framework/src/mx/utils/DensityUtil.as
@@ -86,8 +86,8 @@
     public static function getDPIScale(sourceDPI:Number, targetDPI:Number):Number
     {
         // Unknown dpi returns NaN
-        if ((sourceDPI != DPIClassification.DPI_160 && sourceDPI != DPIClassification.DPI_240 && sourceDPI != DPIClassification.DPI_320) ||
-            (targetDPI != DPIClassification.DPI_160 && targetDPI != DPIClassification.DPI_240 && targetDPI != DPIClassification.DPI_320))
+        if ((sourceDPI != DPIClassification.DPI_160 && sourceDPI != DPIClassification.DPI_240 && sourceDPI != DPIClassification.DPI_320 && sourceDPI != DPIClassification.DPI_480) ||
+            (targetDPI != DPIClassification.DPI_160 && targetDPI != DPIClassification.DPI_240 && targetDPI != DPIClassification.DPI_320 && targetDPI != DPIClassification.DPI_480))
         {
             return NaN;
         }


Transferred from the Adobe Open Source Subversion Repository

Revision: 4611
Author:   chaase@adobe.com
Date:     2009-01-22T00:30:21.783682Z

Log Message:
-----------
Various bug fixes in effects, mostly in the area of seeking, auto-reversing, and shader transitions.

QE Notes: None
Doc Notes: None
Bugs: sdk-17783, sdk-18767, sdk-18759, sdk-18461, sdk-18309, sdk-18013, sdk-18688
Reviewer: Jason
Tests: checkintests, Mustella: Effects, gumbo/effects, ListDataEffects

Modified Paths:
--------------
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/mx/effects/SetAction.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/UnconstrainItemAction.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/EffectInstance.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/AddChildAction.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/effectClasses/ParallelInstance.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/Effect.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/Parallel.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/SetPropertyAction.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/RemoveChildAction.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/mx/effects/effectClasses/FxAnimateInstance.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/mx/effects/effectClasses/FxAnimateShaderTransitionInstance.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/mx/effects/FxAnimateShaderTransition.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/mx/effects/Animation.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/AddItemAction.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/effectClasses/SequenceInstance.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/SetStyleAction.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/RemoveItemAction.as</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1269399 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/mx/src/mx/effects/RemoveItemAction.as
+++ frameworks/projects/mx/src/mx/effects/RemoveItemAction.as
@@ -77,7 +77,7 @@
     public function RemoveItemAction(target:Object = null)
     {
         super(target);
-
+        duration = 0;
         instanceClass = RemoveItemActionInstance;
     }


Transferred from the Adobe Open Source Subversion Repository

Revision: 23247
Author:   cframpto@adobe.com
Date:     2011-12-20T19:21:13.134833Z

Log Message:
-----------
Remove ADOBE SYSTEMS license and replace with Apache license in headers - frameworks.  A 2nd pass will be needed to get the files not handled up by the scripts.

Modified Paths:
--------------
4959 paths were modified

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1269471 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/mx/src/mx/effects/easing/Quadratic.as
+++ frameworks/projects/mx/src/mx/effects/easing/Quadratic.as
@@ -1,11 +1,19 @@
 ////////////////////////////////////////////////////////////////////////////////
 //
-//  ADOBE SYSTEMS INCORPORATED
-//  Copyright 2004-2007 Adobe Systems Incorporated
-//  All Rights Reserved.
+//  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
 //
-//  NOTICE: Adobe permits you to use, modify, and distribute this file
-//  in accordance with the terms of the license agreement accompanying it.
+//      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.
 //
 ////////////////////////////////////////////////////////////////////////////////


FLEX-34712 bug fix

FLEX-34712 bug fix

Popup is positioned incorrectly when called by systemManager_resizeHandler because calculatePopUpPosition()'s x or y may not be correct at that moment. Delaying the code call via callLater() solved the problem and allows the open popup to snap to its new position after device screen is rotated.

--- frameworks/projects/spark/src/spark/components/Callout.as
+++ frameworks/projects/spark/src/spark/components/Callout.as
@@ -1683,19 +1683,26 @@
      */
     private function systemManager_resizeHandler(event:Event):void
     {
-        // Remove explicit settings if due to Resize effect
-        softKeyboardEffectResetExplicitSize();
-
-        // Screen resize might require a new arrow direction and callout position
-        invalidatePosition();
-
-        if (!isSoftKeyboardEffectActive)
-        {
-            // Force validation and use new screen size only if the keyboard
-            // effect is not active. The stage dimensions may be invalid while
-            // the soft keyboard is active. See SDK-31860.
-            validateNow();
-        }
+    	//callLater() solves bug FLEX-34712 only affecting device and not found on simulator
+    	//where calculatePopUpPosition()'s correct x or y may not be immediately available
+        callLater(
+            function():void
+            {
+                // Remove explicit settings if due to Resize effect
+                softKeyboardEffectResetExplicitSize();
+
+                // Screen resize might require a new arrow direction and callout position
+                invalidatePosition();
+
+                if (!isSoftKeyboardEffectActive)
+                {
+                    // Force validation and use new screen size only if the keyboard
+                    // effect is not active. The stage dimensions may be invalid while
+                    // the soft keyboard is active. See SDK-31860.
+                    validateNow();
+                }
+            }
+        );
     }
 }
-}+}


Transferred from the Adobe Open Source Subversion Repository

Revision: 7939
Author:   jszeto@adobe.com
Date:     2009-06-18T00:10:15.473790Z

Log Message:
-----------
Slider PARB Changes

•  remove dataTipOriginalPosition
•  remove dataTipInstance
•  positionDataTip() -> updateDataTip(dataTipInstance:IDataRenderer, initialPosition:Point)

QE Notes: None
Doc Notes: None
Bugs: None
Reviewer: Evtim

Modified Paths:
--------------
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/VSlider.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/asdoc/en_US/spark/components/examples/HSliderExample.mxml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/HSlider.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/supportClasses/Slider.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/asdoc/en_US/spark/components/examples/NumericStepperExample.mxml</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1279353 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/spark/src/spark/components/HSlider.as
+++ frameworks/projects/spark/src/spark/components/HSlider.as
@@ -15,6 +15,8 @@
 import flash.display.DisplayObject;
 import flash.geom.Point;
 import flash.geom.Rectangle;
+
+import mx.core.IDataRenderer;

 import spark.components.supportClasses.Slider;

@@ -63,7 +65,7 @@
     // Methods
     //
     //--------------------------------------------------------------------------
-
+
     /**
      *  @private
      */
@@ -71,12 +73,12 @@
     {
         if (!thumb || !track)
             return 0;
-
+
         var range:Number = maximum - minimum;
         var thumbRange:Number = track.getLayoutBoundsWidth() - thumb.getLayoutBoundsWidth();
         return minimum + ((thumbRange != 0) ? (x / thumbRange) * range : 0);
     }
-
+
     /**
      *  @private
      */
@@ -84,25 +86,27 @@
     {
         if (!thumb || !track)
             return;
-
+
         var thumbRange:Number = track.getLayoutBoundsWidth() - thumb.getLayoutBoundsWidth();
         var range:Number = maximum - minimum;
         var thumbPos:Number = (range > 0) ? ((pendingValue - minimum) / range) * thumbRange : 0;
         thumb.setLayoutBoundsPosition(Math.round(track.getLayoutBoundsX() + thumbPos), thumb.getLayoutBoundsY());
     }
-
+

     /**
      *  @private
+     *  TODO (jszeto) Update this to also use the ILayoutElement API
      */
-    override protected function positionDataTip():void
+    override protected function updateDataTip(dataTipInstance:IDataRenderer, initialPosition:Point):void
     {
     	var tipAsDisplayObject:DisplayObject = dataTipInstance as DisplayObject;

     	if (tipAsDisplayObject && thumb)
     	{
-			var relX:Number = thumb.x - (tipAsDisplayObject.width - thumb.width) / 2;
-	        var o:Point = new Point(relX, dataTipOriginalPosition.y);
+			var relX:Number = thumb.getLayoutBoundsX() -
+								(tipAsDisplayObject.width - thumb.getLayoutBoundsWidth()) / 2;
+	        var o:Point = new Point(relX, initialPosition.y);
 	        var r:Point = localToGlobal(o);

 			// Get the screen bounds


Transferred from the Adobe Open Source Subversion Repository

Revision: 3509
Author:   jimurphy@adobe.com
Date:     2008-10-07T18:19:17.646255Z

Log Message:
-----------
Rename of flex -> mx.

For compatibility reasons it was decided that the new functionality remain integrated with the old framework, although we will continue to build two separate SWCs, one with primarily existing framework classes, and one with new Flex 4 classes. This change removes duplicate names from the Flex 4 framework to avoid class name overlapping with the old framework code.  The naming overlap consists of two major areas:  New Components, and New Effects

Modified Paths:
--------------
386 paths were modified

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1285669 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/spark/src/spark/primitives/Graphic.as
+++ frameworks/projects/spark/src/spark/primitives/Graphic.as
@@ -9,11 +9,11 @@
 //
 ////////////////////////////////////////////////////////////////////////////////

-package flex.graphics
+package mx.graphics
 {

 import mx.events.PropertyChangeEvent;
-import flex.core.Group;
+import mx.components.Group;

 //--------------------------------------
 //  Events


Transferred from the Adobe Open Source Subversion Repository

Revision: 20742
Author:   smgilson@adobe.com
Date:     2011-03-09T21:46:11.224420Z

Log Message:
-----------
Merge 20732 - asdoc updates

QE notes:
Doc notes:
Bugs:
Reviewer:
Tests run:
Is noteworthy for integration:

Modified Paths:
--------------
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/MovieClipSWFLoader.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/framework/src/mx/formatters/SwitchSymbolFormatter.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/mx/src/mx/controls/ComboBox.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/flash-integration/src/mx/flash/UIMovieClip.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/framework/src/mx/states/State.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/IEffect.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/mx/src/mx/effects/effectClasses/UnconstrainItemActionInstance.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/mx/src/mx/controls/ColorPicker.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/flash-integration/src/mx/flash/ContainerMovieClip.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/airframework/src/mx/controls/FlexNativeMenu.as</path>
<path kind="dir" action="M">/private/flex/sdk/trunk</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/effectClasses/CompositeEffectInstance.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/framework/src/mx/effects/CompositeEffect.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/mx/src/mx/controls/TextInput.as</path>
<path kind="file" action="M">/private/flex/sdk/trunk/frameworks/projects/spark/src/mx/controls/MXFTETextInput.as</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1260240 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/framework/src/mx/effects/IEffect.as
+++ frameworks/projects/framework/src/mx/effects/IEffect.as
@@ -500,6 +500,8 @@
     /**
      *  Removes event listeners from an instance
      *  and removes it from the list of instances.
+     *
+     *  @param instance The effect instance.
      *
      *  @langversion 3.0
      *  @playerversion Flash 9


Transferred from the Adobe Open Source Subversion Repository

Revision: 23243
Author:   cframpto@adobe.com
Date:     2011-12-20T00:59:57.384047Z

Log Message:
-----------
In frameworks, remove Adobe headers from all files except xml/mxml file types.  There are also a few .txt files that are license files that I didn't touch yet.

Modified Paths:
--------------
2361 paths were modified

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1267675 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/mx/src/mx/containers/HDividedBox.as
+++ frameworks/projects/mx/src/mx/containers/HDividedBox.as
@@ -1,13 +1,3 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-//  ADOBE SYSTEMS INCORPORATED
-//  Copyright 2003-2007 Adobe Systems Incorporated
-//  All Rights Reserved.
-//
-//  NOTICE: Adobe permits you to use, modify, and distribute this file
-//  in accordance with the terms of the license agreement accompanying it.
-//
-////////////////////////////////////////////////////////////////////////////////

 package mx.containers
 {


Split the function of receiving the socket data in two. Easier to override in classes extending and replacing the socket, such as TLSSocket.

--- src/org/igniterealtime/xiff/core/XMPPConnection.as
+++ src/org/igniterealtime/xiff/core/XMPPConnection.as
@@ -513,7 +513,7 @@
 		}

 		/**
-		 *
+		 *
 		 * @param	resultIQ
 		 */
 		protected function changePassword_result( resultIQ:IQ ):void
@@ -531,7 +531,7 @@
 		}

 		/**
-		 *
+		 *
 		 * @param	resultIQ
 		 */
 		protected function getRegistrationFields_result( resultIQ:IQ ):void
@@ -701,7 +701,7 @@
 		}

 		/**
-		 *
+		 *
 		 * @param	node The feature containing starttls tag.
 		 */
 		protected function handleStreamTLS( node:XMLNode ):void
@@ -747,7 +747,7 @@
 			{
 				dispatchError("SASL missing", "The server is not configured to support any available SASL mechanisms", "SASL", -1);
 			}
-			else
+			else
 			{
 				auth = new authClass(this);
 			}
@@ -925,8 +925,17 @@
 		{
 			var bytedata:ByteArray = new ByteArray();
 			// The default value of 0 causes all available data to be read.
-			socket.readBytes(bytedata);
-
+			socket.readBytes( bytedata );
+			parseDataReceived( bytedata );
+		}
+
+		/**
+		 * Parses the data which the socket just received.
+		 * Used to simplify the overrides from classes extending this one.
+		 * @param	bytedata
+		 */
+		protected function parseDataReceived( bytedata:ByteArray ):void
+		{
 			// Increase the incoming data counter.
 			_incomingBytes += bytedata.length;

@@ -935,12 +944,12 @@
 				bytedata.uncompress();
 			}
 			bytedata.position = 0;
-			var data:String = bytedata.readUTFBytes(bytedata.length);
+			var data:String = bytedata.readUTFBytes( bytedata.length );

 			var rawXML:String = _incompleteRawXML + data;

 			var rawData:ByteArray = new ByteArray();
-			rawData.writeUTFBytes(rawXML);
+			rawData.writeUTFBytes( rawXML );

 			// data comign in could also be parts of base64 encoded stuff.

@@ -1099,7 +1108,7 @@
 			{
 				sendXML(auth.request); // XMLNode
 			}
-			else
+			else
 			{
 				// We did not have a suitable auth method for this connection.
 			}


Transferred from the Adobe Open Source Subversion Repository

Revision: 4815
Author:   matamel@adobe.com
Date:     2009-02-03T18:47:12.905037Z

Log Message:
-----------
Feature: Client side load balancing.
QA: Yes
Doc: Yes
Checkintests: Pass
Reviewer: Seth

Details: Added client side code for client side load balancing as described in 2 tier messaging spec.

Modified Paths:
--------------
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/rpc/src/mx/messaging/Channel.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/rpc/src/mx/messaging/config/ServerConfig.as</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1273445 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/rpc/src/mx/messaging/Channel.as
+++ frameworks/projects/rpc/src/mx/messaging/Channel.as
@@ -15,8 +15,8 @@
 import flash.errors.IllegalOperationError;
 import flash.events.EventDispatcher;
 import flash.events.TimerEvent;
+import flash.utils.Timer;
 import flash.utils.getDefinitionByName;
-import flash.utils.Timer;

 import mx.collections.ArrayCollection;
 import mx.core.IMXMLObject;
@@ -56,21 +56,21 @@

 /**
  *  Dispatched after the channel has faulted.
- *
+ *
  *  @eventType mx.messaging.events.ChannelFaultEvent.FAULT
  */
 [Event(name="channelFault", type="mx.messaging.events.ChannelFaultEvent")]

 /**
  *  Dispatched when a channel receives a message from its endpoint.
- *
+ *
  *  @eventType mx.messaging.events.MessageEvent.MESSAGE
  */
 [Event(name="message", type="mx.messaging.events.MessageEvent")]

 /**
  *  Dispatched when a property of the channel changes.
- *
+ *
  *  @eventType mx.events.PropertyChangeEvent.PROPERTY_CHANGE
  */
 [Event(name="propertyChange", type="mx.events.PropertyChangeEvent")]
@@ -81,13 +81,13 @@
  *  The Channel class is the base message channel class that all channels in the messaging
  *  system must extend.
  *
- *
Channels are specific protocol-based conduits for messages sent between
+ *
Channels are specific protocol-based conduits for messages sent between
  *  MessageAgents and remote destinations.
  *  Preconfigured channels are obtained within the framework using the
  *  ServerConfig.getChannel() method.
  *  You can create a Channel directly using the new operator and
  *  add it to a ChannelSet directly.

- *
+ *
  *

  *  Channels represent a physical connection to a remote endpoint.
  *  Channels are shared across destinations by default.
@@ -103,32 +103,47 @@
 {
     //--------------------------------------------------------------------------
     //
+    // Private Static Constants
+    //
+    //--------------------------------------------------------------------------
+
+    private static const CLIENT_LOAD_BALANCING:String = "client-load-balancing"
+    private static const CONNECT_TIMEOUT_SECONDS:String = "connect-timeout-seconds";
+    private static const ENABLE_SMALL_MESSAGES:String = "enable-small-messages";
+    private static const FALSE:String = "false";
+    private static const RECORD_MESSAGE_TIMES:String = "record-message-times";
+    private static const RECORD_MESSAGE_SIZES:String = "record-message-sizes";
+    private static const SERIALIZATION:String = "serialization";
+    private static const TRUE:String = "true";
+
+    //--------------------------------------------------------------------------
+    //
     // Constructor
-    //
-    //--------------------------------------------------------------------------
-
-	/**
-	 *  Constructs an instance of a generic Channel that connects to the
-	 *  specified endpoint URI.
-     *
-	 *  Note: The Channel type should not be constructed directly. Instead
-	 *  create instances of protocol specific subclasses such as RTMPChannel or
-	 *  AMFChannel.
-     *
-	 *  @param id The id of this channel.
-	 *
-	 *  @param uri The endpoint URI for this channel.
-	 */
-	public function Channel(id:String = null, uri:String = null)
-	{
-		super();
-
-		_log = Log.getLogger("mx.messaging.Channel");
-		_failoverIndex = -1;
-	    this.id = id;
-		_primaryURI = uri;
-		this.uri = uri; // Current URI
-	}
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructs an instance of a generic Channel that connects to the
+     *  specified endpoint URI.
+     *
+     *  Note: The Channel type should not be constructed directly. Instead
+     *  create instances of protocol specific subclasses such as RTMPChannel or
+     *  AMFChannel.
+     *
+     *  @param id The id of this channel.
+     *
+     *  @param uri The endpoint URI for this channel.
+     */
+    public function Channel(id:String = null, uri:String = null)
+    {
+        super();
+
+        _log = Log.getLogger("mx.messaging.Channel");
+        _failoverIndex = -1;
+        this.id = id;
+        _primaryURI = uri;
+        this.uri = uri; // Current URI
+    }

     /**
      * @private
@@ -137,24 +152,24 @@
     {
         this.id = id;
     }
-
+
     //--------------------------------------------------------------------------
     //
     // Variables
-    //
-    //--------------------------------------------------------------------------
-
-	/**
-	 *  @private
-	 *  Used to prevent multiple logouts.
-	 */
-	mx_internal var authenticating:Boolean;
-
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     *  Used to prevent multiple logouts.
+     */
+    mx_internal var authenticating:Boolean;
+
     /**
      *  @private
      *  The credentials string that is passed via a CommandMessage to the server when the
      *  Channel connects. Channels inherit the credentials of connected ChannelSets that
-     *  inherit their credentials from connected MessageAgents.
+     *  inherit their credentials from connected MessageAgents.
      *  MessageAgent.setCredentials(username, password) is generally used
      *  to set credentials.
      */
@@ -168,12 +183,12 @@
      */
     public var enableSmallMessages:Boolean = true;

-	/**
-	 *  @private
-	 *  Provides access to a logger for this channel.
-	 */
-	protected var _log:ILogger;
-
+    /**
+     *  @private
+     *  Provides access to a logger for this channel.
+     */
+    protected var _log:ILogger;
+
     /**
      *  @private
      *  Flag indicating whether the Channel is in the process of connecting.
@@ -184,20 +199,20 @@
      *  @private
      *  Timer to track connect timeouts.
      */
-    private var _connectTimer:Timer;
-
-	/**
-	 *  @private
-	 *  Current index into failover URIs during a failover attempt.
-	 *  When not failing over, this variable is reset to a sentinal
-	 *  value of -1.
-	 */
-	private var _failoverIndex:int;
+    private var _connectTimer:Timer;
+
+    /**
+     *  @private
+     *  Current index into failover URIs during a failover attempt.
+     *  When not failing over, this variable is reset to a sentinal
+     *  value of -1.
+     */
+    private var _failoverIndex:int;

     /**
      * @private
      * Flag indicating whether the endpoint has been calculated from the uri.
-     */
+     */
     private var _isEndpointCalculated:Boolean;

     /**
@@ -213,21 +228,21 @@
      *  Flag indicating whether this Channel owns the wait guard for managing initial connect attempts.
      */
     private var _ownsWaitGuard:Boolean;
-
+
     /**
      *  @private
      *  Indicates whether the Channel was previously connected successfully. Used for pinned reconnect
      *  attempts before trying failover options.
      */
     private var _previouslyConnected:Boolean;
-
-	/**
-	 *  @private
-	 *  Primary URI; the initial URI for this channel.
-	 */
-	private var _primaryURI:String
-
-	/**
+
+    /**
+     *  @private
+     *  Primary URI; the initial URI for this channel.
+     */
+    private var _primaryURI:String
+
+    /**
      *  @private
      *  Used for pinned reconnect attempts.
      */
@@ -239,34 +254,34 @@
     /**
      *  @private
      */
-    private var resourceManager:IResourceManager = ResourceManager.getInstance();
-
-	//--------------------------------------------------------------------------
+    private var resourceManager:IResourceManager = ResourceManager.getInstance();
+
+    //--------------------------------------------------------------------------
     //
     // Properties
-    //
-    //--------------------------------------------------------------------------
-
-	//----------------------------------
-	//  channelSets
-	//----------------------------------
-
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  channelSets
+    //----------------------------------
+
     /**
      *  @private
      */
     private var _channelSets:Array = [];
-
+
     /**
      *  Provides access to the ChannelSets connected to the Channel.
      */
     public function get channelSets():Array
     {
-        return _channelSets;
-    }
-
-	//----------------------------------
-	//  connected
-	//----------------------------------
+        return _channelSets;
+    }
+
+    //----------------------------------
+    //  connected
+    //----------------------------------

     /**
      *  @private
@@ -274,103 +289,103 @@
     private var _connected:Boolean = false;

     [Bindable(event="propertyChange")]
-	/**
-	 *  Indicates whether this channel has established a connection to the
-	 *  remote destination.
-	 */
-	public function get connected():Boolean
-	{
-	    return _connected;
-	}
-
-	/**
-	 *  @private
-	 */
-	protected function setConnected(value:Boolean):void
-	{
-	    if (_connected != value)
-	    {
-	        if (_connected)
-	           _previouslyConnected = true;
-
-	        var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "connected", _connected, value)
-	        _connected = value;
-	        dispatchEvent(event);
-	        if (!value)
-	            setAuthenticated(false);
-        }
-	}
-
-	//----------------------------------
-	//  connectTimeout
-	//----------------------------------
-
-    /**
-	 *  @private
-	 */
-	private var _connectTimeout:int = -1;
-
-	/**
-     *  Provides access to the connect timeout in seconds for the channel.
-     *  A value of 0 or below indicates that a connect attempt will never
+    /**
+     *  Indicates whether this channel has established a connection to the
+     *  remote destination.
+     */
+    public function get connected():Boolean
+    {
+        return _connected;
+    }
+
+    /**
+     *  @private
+     */
+    protected function setConnected(value:Boolean):void
+    {
+        if (_connected != value)
+        {
+            if (_connected)
+               _previouslyConnected = true;
+
+            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "connected", _connected, value)
+            _connected = value;
+            dispatchEvent(event);
+            if (!value)
+                setAuthenticated(false);
+        }
+    }
+
+    //----------------------------------
+    //  connectTimeout
+    //----------------------------------
+
+    /**
+     *  @private
+     */
+    private var _connectTimeout:int = -1;
+
+    /**
+     *  Provides access to the connect timeout in seconds for the channel.
+     *  A value of 0 or below indicates that a connect attempt will never
      *  be timed out on the client.
      *  For channels that are configured to failover, this value is the total
      *  time to wait for a connection to be established.
-     *  It is not reset for each failover URI that the channel may attempt
+     *  It is not reset for each failover URI that the channel may attempt
      *  to connect to.
-     */
+     */
     public function get connectTimeout():int
     {
         return _connectTimeout;
     }
-
-	/**
-	 *  @private
-	 */
-	public function set connectTimeout(value:int):void
-	{
-	    _connectTimeout = value;
-    }
-
-	//----------------------------------
-	//  endpoint
-	//----------------------------------
-
-    /**
-     *  @private
-     */
-	private var _endpoint:String;
-
-	/**
-	 *  Provides access to the endpoint for this channel.
-	 *  This value is calculated based on the value of the uri
-	 *  property.
-	 */
-	public function get endpoint():String
-	{
-	    if (!_isEndpointCalculated)
-    	    calculateEndpoint();
-	    return _endpoint;
-	}
-
-	//----------------------------------
-	//  loginAfterDisconnect
-	//----------------------------------
-
-    /**
-     *  @private
-     */
-    protected var _loginAfterDisconnect:Boolean = false;
-
+
+    /**
+     *  @private
+     */
+    public function set connectTimeout(value:int):void
+    {
+        _connectTimeout = value;
+    }
+
+    //----------------------------------
+    //  endpoint
+    //----------------------------------
+
+    /**
+     *  @private
+     */
+    private var _endpoint:String;
+
+    /**
+     *  Provides access to the endpoint for this channel.
+     *  This value is calculated based on the value of the uri
+     *  property.
+     */
+    public function get endpoint():String
+    {
+        if (!_isEndpointCalculated)
+            calculateEndpoint();
+        return _endpoint;
+    }
+
+    //----------------------------------
+    //  loginAfterDisconnect
+    //----------------------------------
+
+    /**
+     *  @private
+     */
+    protected var _loginAfterDisconnect:Boolean = false;
+
     mx_internal function get loginAfterDisconnect():Boolean
     {
-    	return _loginAfterDisconnect;
-    }
-
-	//----------------------------------
-	//  recordMessageTimes
-	//----------------------------------
-
+        return _loginAfterDisconnect;
+    }
+
+    //----------------------------------
+    //  recordMessageTimes
+    //----------------------------------
+
     /**
      * @private
      */
@@ -378,17 +393,17 @@

     /**
      * Channel property determines the level of performance information injection - whether
-     * we inject timestamps or not.
+     * we inject timestamps or not.
      */
     public function get recordMessageTimes():Boolean
     {
-    	return _recordMessageTimes;
-    }
-
-	//----------------------------------
-	//  recordMessageSizes
-	//----------------------------------
-
+        return _recordMessageTimes;
+    }
+
+    //----------------------------------
+    //  recordMessageSizes
+    //----------------------------------
+
     /**
      * @private
      */
@@ -397,20 +412,20 @@
     /**
      * Channel property determines the level of performance information injection - whether
      * we inject message sizes or not.
-     */
+     */
     public function get recordMessageSizes():Boolean
     {
-    	return _recordMessageSizes;
-    }
-
-	//----------------------------------
-	//  reconnecting
-	//----------------------------------
-
-	/**
-	 *  @private
-	 */
-	private var _reconnecting:Boolean = false;
+        return _recordMessageSizes;
+    }
+
+    //----------------------------------
+    //  reconnecting
+    //----------------------------------
+
+    /**
+     *  @private
+     */
+    private var _reconnecting:Boolean = false;

     [Bindable(event="propertyChange")]
     /**
@@ -421,111 +436,111 @@
     {
         return _reconnecting;
     }
-
+
     private function setReconnecting(value:Boolean):void
     {
         if (_reconnecting != value)
-	    {
-	        var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "reconnecting", _reconnecting, value);
-	        _reconnecting = value;
-	        dispatchEvent(event);
-        }
-    }
-
-	//----------------------------------
-	//  failoverURIs
-	//----------------------------------
-
-	/**
-	 *  @private
-	 */
-	private var _failoverURIs:Array;
-
-	/**
+        {
+            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "reconnecting", _reconnecting, value);
+            _reconnecting = value;
+            dispatchEvent(event);
+        }
+    }
+
+    //----------------------------------
+    //  failoverURIs
+    //----------------------------------
+
+    /**
+     *  @private
+     */
+    private var _failoverURIs:Array;
+
+    /**
      *  Provides access to the set of endpoint URIs that this channel can
-	 *  attempt to failover to if the endpoint is clustered.
-     */
+     *  attempt to failover to if the endpoint is clustered.
+     */
     public function get failoverURIs():Array
     {
         return (_failoverURIs != null) ? _failoverURIs : [];
     }
-
-	/**
-	 *  @private
-	 */
-	public function set failoverURIs(value:Array):void
-	{
-	    if (value != null)
-	    {
-	        _failoverURIs = value;
-	        _failoverIndex = -1; // Reset the index, because URIs have changed
-	    }
-    }
-
-	//----------------------------------
-	//  id
-	//----------------------------------
-
-	/**
-	 *  @private
-	 */
-	private var _id:String;
-
-	/**
-	 *  Provides access to the id of this channel.
-	 */
-	public function get id():String
-	{
-	    return _id;
-	}
-
-	public function set id(value:String):void
-	{
-	    if (_id != value)
-	        _id = value;
-	}
-
-	//----------------------------------
-	//  authenticated
-	//----------------------------------
+
+    /**
+     *  @private
+     */
+    public function set failoverURIs(value:Array):void
+    {
+        if (value != null)
+        {
+            _failoverURIs = value;
+            _failoverIndex = -1; // Reset the index, because URIs have changed
+        }
+    }
+
+    //----------------------------------
+    //  id
+    //----------------------------------
+
+    /**
+     *  @private
+     */
+    private var _id:String;
+
+    /**
+     *  Provides access to the id of this channel.
+     */
+    public function get id():String
+    {
+        return _id;
+    }
+
+    public function set id(value:String):void
+    {
+        if (_id != value)
+            _id = value;
+    }
+
+    //----------------------------------
+    //  authenticated
+    //----------------------------------

     private var _authenticated:Boolean = false;
-
+
     [Bindable(event="propertyChange")]
-	/**
-	 *  Indicates if this channel is authenticated.
-     */
-	public function get authenticated():Boolean
-	{
-	    return _authenticated;
-	}
-
-	mx_internal function setAuthenticated(value:Boolean):void
-	{
-	    if (value != _authenticated)
-	    {
-	        var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "authenticated", _authenticated, value);
-	        _authenticated = value;
-
-	        var cs:ChannelSet;
-	        for (var i:int = 0; i < _channelSets.length; i++)
-	        {
-	            cs = ChannelSet(_channelSets[i]);
-	            cs.mx_internal::setAuthenticated(authenticated, credentials)
-	        }
-
-	        dispatchEvent(event);
-	    }
-	}
-
-	//----------------------------------
-	//  protocol
-	//----------------------------------
+    /**
+     *  Indicates if this channel is authenticated.
+     */
+    public function get authenticated():Boolean
+    {
+        return _authenticated;
+    }
+
+    mx_internal function setAuthenticated(value:Boolean):void
+    {
+        if (value != _authenticated)
+        {
+            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "authenticated", _authenticated, value);
+            _authenticated = value;
+
+            var cs:ChannelSet;
+            for (var i:int = 0; i < _channelSets.length; i++)
+            {
+                cs = ChannelSet(_channelSets[i]);
+                cs.mx_internal::setAuthenticated(authenticated, credentials)
+            }
+
+            dispatchEvent(event);
+        }
+    }
+
+    //----------------------------------
+    //  protocol
+    //----------------------------------

     /**
      *  Provides access to the protocol that the channel uses.
      *
-     *
Note: Subclasses of Channel must override this method and return
+     *
Note: Subclasses of Channel must override this method and return
      *  a string that represents their supported protocol.
      *  Examples of supported protocol strings are "rtmp", "http" or "https".
      *

@@ -534,12 +549,12 @@
     {
         throw new IllegalOperationError("Channel subclasses must override "
             + "the get function for 'protocol' to return the proper protocol "
-            + "string.");
-    }
-
-	//----------------------------------
-	//  realtime
-	//----------------------------------
+            + "string.");
+    }
+
+    //----------------------------------
+    //  realtime
+    //----------------------------------

     /**
      *  @private
@@ -549,45 +564,45 @@
     {
         return false;
     }
-
-	//----------------------------------
-	//  requestTimeout
-	//----------------------------------
-
-    /**
-	 *  @private
-	 */
-	private var _requestTimeout:int = -1;
-
-	/**
-     *  Provides access to the default request timeout in seconds for the
-     *  channel. A value of 0 or below indicates that outbound requests will
+
+    //----------------------------------
+    //  requestTimeout
+    //----------------------------------
+
+    /**
+     *  @private
+     */
+    private var _requestTimeout:int = -1;
+
+    /**
+     *  Provides access to the default request timeout in seconds for the
+     *  channel. A value of 0 or below indicates that outbound requests will
      *  never be timed out on the client.
-     *
Request timeouts are most useful for RPC style messaging that
+     *
Request timeouts are most useful for RPC style messaging that
      *  requires a response from the remote destination.

-     */
+     */
     public function get requestTimeout():int
     {
         return _requestTimeout;
     }
-
-	/**
-	 *  @private
-	 */
-	public function set requestTimeout(value:int):void
-	{
-	    _requestTimeout = value;
+
+    /**
+     *  @private
+     */
+    public function set requestTimeout(value:int):void
+    {
+        _requestTimeout = value;
     }

     //----------------------------------
     //  shouldBeConnected
     //----------------------------------
-
-    /**
-     *  @private
+
+    /**
+     *  @private
      */
     private var _shouldBeConnected:Boolean;
-
+
     /**
      *  Indicates whether this channel should be connected to its endpoint.
      *  This flag is used to control when fail over should be attempted and when disconnect
@@ -598,55 +613,55 @@
         return _shouldBeConnected;
     }

-	//----------------------------------
-	//  uri
-	//----------------------------------
-
-	/**
-     *  @private
-     */
-	private var _uri:String;
-
-	/**
-	 *  Provides access to the URI used to create the whole endpoint URI for this channel.
-	 *  The URI can be a partial path, in which case the full endpoint URI is computed as necessary.
-	 */
-	public function get uri():String
-	{
-	    return _uri;
-	}
+    //----------------------------------
+    //  uri
+    //----------------------------------
+
+    /**
+     *  @private
+     */
+    private var _uri:String;
+
+    /**
+     *  Provides access to the URI used to create the whole endpoint URI for this channel.
+     *  The URI can be a partial path, in which case the full endpoint URI is computed as necessary.
+     */
+    public function get uri():String
+    {
+        return _uri;
+    }

     public function set uri(value:String):void
     {
         if (value != null)
         {
             _uri = value;
-            calculateEndpoint();
-        }
-    }
-
-	/**
-	 * @private
-	 * This alternate property for an endpoint URL is provided to match the
-	 * endpoint configuration attribute "url". This property is
-	 * equivalent to the uri property.
-	 */
-	public function get url():String
-	{
-	    return uri;
-	}
+            calculateEndpoint();
+        }
+    }

     /**
      * @private
+     * This alternate property for an endpoint URL is provided to match the
+     * endpoint configuration attribute "url". This property is
+     * equivalent to the uri property.
+     */
+    public function get url():String
+    {
+        return uri;
+    }
+
+    /**
+     * @private
      */
     public function set url(value:String):void
     {
         uri = value;
     }

-	//----------------------------------
-	//  useSmallMessages
-	//----------------------------------
+    //----------------------------------
+    //  useSmallMessages
+    //----------------------------------

     /**
      * @private
@@ -676,7 +691,7 @@
     //--------------------------------------------------------------------------
     //
     // Methods
-    //
+    //
     //--------------------------------------------------------------------------

     /**
@@ -696,60 +711,96 @@
      *  </channel>
      *

      */
-	public function applySettings(settings:XML):void
-	{
-	    if (Log.isInfo())
-	        _log.info("'{0}' channel settings are:\n{1}", id, settings);
-	    // Process connect-timeout-seconds property.
-	    if (settings.properties.length())
+    public function applySettings(settings:XML):void
+    {
+        if (Log.isInfo())
+            _log.info("'{0}' channel settings are:\n{1}", id, settings);
+
+        if (settings.properties.length() != 0)
         {
             var props:XML = settings.properties[0];
-            if (props["connect-timeout-seconds"].length())
-                connectTimeout = props["connect-timeout-seconds"].toString();
-           	if (props["record-message-times"].length())
-           		_recordMessageTimes = props["record-message-times"].toString()=="true";
-           	if (props["record-message-sizes"].length())
-           		_recordMessageSizes = props["record-message-sizes"].toString()=="true";
-            var serializationProps:XMLList = props["serialization"];
-           	if (serializationProps.length() > 0)
-           	{
-           	    if (serializationProps["enable-small-messages"].toString()=="false")
-           		    enableSmallMessages = false;
-           	}
-        }
-	}
-
-	/**
-	 *  Connects the ChannelSet to the Channel. If the Channel has not yet
-	 *  connected to its endpoint, it attempts to do so.
-	 *  Channel subclasses must override the internalConnect()
-	 *  method, and call the connectSuccess() method once the
-	 *  underlying connection is established.
-	 *
-	 *  @param channelSet The ChannelSet to connect to the Channel.
-	 */
-	final public function connect(channelSet:ChannelSet):void
-	{
-	    var exists:Boolean = false;
-		var n:int = _channelSets.length;
-		for (var i:int = 0; i < _channelSets.length; i++)
+
+            applyClientLoadBalancingSettings(props);
+            if (props[CONNECT_TIMEOUT_SECONDS].length() != 0)
+                connectTimeout = props[CONNECT_TIMEOUT_SECONDS].toString();
+            if (props[RECORD_MESSAGE_TIMES].length() != 0)
+                _recordMessageTimes = props[RECORD_MESSAGE_TIMES].toString() == TRUE;
+            if (props[RECORD_MESSAGE_SIZES].length() != 0)
+                _recordMessageSizes = props[RECORD_MESSAGE_SIZES].toString()== TRUE;
+            var serializationProps:XMLList = props[SERIALIZATION];
+            if (serializationProps.length() != 0 && serializationProps[ENABLE_SMALL_MESSAGES].toString()== FALSE)
+                enableSmallMessages = false;
+        }
+    }
+
+    /**
+     *  Applies the client load balancing urls if they exists. It randomly picks
+     *  a url from the set of client load balancing urls and sets it as the channel's
+     *  main url; then it assigns the rest of the urls as the failoverURIs
+     *  of the channel.
+     *
+     *  @param props The properties section of the XML fragment of the services-config.xml
+     *  file for this channel.
+     */
+    protected function applyClientLoadBalancingSettings(props:XML):void
+    {
+        var clientLoadBalancingProps:XMLList = props[CLIENT_LOAD_BALANCING];
+        if (clientLoadBalancingProps.length() == 0)
+            return;
+
+        var urlCount:int = clientLoadBalancingProps.url.length();
+        if (urlCount == 0)
+            return;
+
+        // Add urls to an array, so they can be shuffled.
+        var urls:Array = new Array();
+        for each (var url:XML in clientLoadBalancingProps.url)
+            urls.push(url.toString());
+
+        shuffle(urls);
+
+        // Select the first url as the main url.
+        if (Log.isInfo())
+            _log.info("'{0}' channel picked {1} as its main url.", id, urls[0]);
+        this.url = urls[0];
+
+        // Assign the rest of the urls as failoverUris.
+        var failoverURIs:Array = urls.slice(1);
+        if (failoverURIs.length > 0)
+            this.failoverURIs = failoverURIs;
+    }
+
+    /**
+     *  Connects the ChannelSet to the Channel. If the Channel has not yet
+     *  connected to its endpoint, it attempts to do so.
+     *  Channel subclasses must override the internalConnect()
+     *  method, and call the connectSuccess() method once the
+     *  underlying connection is established.
+     *
+     *  @param channelSet The ChannelSet to connect to the Channel.
+     */
+    final public function connect(channelSet:ChannelSet):void
+    {
+        var exists:Boolean = false;
+        var n:int = _channelSets.length;
+        for (var i:int = 0; i < _channelSets.length; i++)
         {
             if (_channelSets[i] == channelSet)
             {
                 exists = true;
-                break;
+                break;
             }
         }
-
-		_shouldBeConnected = true;
-		if (!exists)
-		{
-			_channelSets.push(channelSet);
-			// Wire up ChannelSet's channel event listeners.
-	        addEventListener(ChannelEvent.CONNECT, channelSet.channelConnectHandler);
-	        addEventListener(ChannelEvent.DISCONNECT, channelSet.channelDisconnectHandler);
-	        addEventListener(ChannelFaultEvent.FAULT, channelSet.channelFaultHandler);
-        }
+
+        _shouldBeConnected = true;
+        if (!exists)
+        {
+            _channelSets.push(channelSet);
+            // Wire up ChannelSet's channel event listeners.
+            addEventListener(ChannelEvent.CONNECT, channelSet.channelConnectHandler);
+            addEventListener(ChannelEvent.DISCONNECT, channelSet.channelDisconnectHandler);
+            addEventListener(ChannelFaultEvent.FAULT, channelSet.channelFaultHandler);
+        }
         // If we are already connected, notify the ChannelSet. Otherwise connect
         // if necessary.
         if (connected)
@@ -757,9 +808,9 @@
             channelSet.channelConnectHandler(ChannelEvent.createEvent(ChannelEvent.CONNECT, this, false, false, connected));
         }
         else if (!_connecting)
-        {
+        {
             _connecting = true;
-
+
             // If a connect timeout is defined, start the corresponding timer.
             if (connectTimeout > 0)
             {
@@ -767,7 +818,7 @@
                 _connectTimer.addEventListener(TimerEvent.TIMER, connectTimeoutHandler);
                 _connectTimer.start();
             }
-
+
             // We have to prevent a race between multipe Channel instances attempting to connect concurrently
             // at application startup. We detect this situation by testing whether the FlexClient Id has been assigned or not.
             if (FlexClient.getInstance().id == null)
@@ -785,7 +836,7 @@
                 {
                     // This Channel should wait to attempt to connect.
                     flexClient.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, flexClientWaitHandler);
-                }
+                }
             }
             else
             {
@@ -793,49 +844,49 @@
                 internalConnect();
             }
         }
-	}
-
-	/**
-	 *  Disconnects the ChannelSet from the Channel. If the Channel is connected
-	 *  to its endpoint and it has no more connected ChannelSets it will
-	 *  internally disconnect.
-	 *
-	 *
Channel subclasses need to override the
-	 *  internalDisconnect() method, and call the
-	 *  disconnectSuccess() method when the underlying connection
-	 *  has been terminated.

-	 *
-	 *  @param channelSet The ChannelSet to disconnect from the Channel.
-	 */
-	final public function disconnect(channelSet:ChannelSet):void
-	{
-	    // If we own the wait guard for initial Channel connects release it.
-	    // This will only be true if this Channel is the first to attempt to connect
-	    // but its connect attempt is still pending when disconnect() is invoked.
-	    if (_ownsWaitGuard)
-	    {
-	        _ownsWaitGuard = false;
-	        FlexClient.getInstance().waitForFlexClientId = false; // Allow other Channels to connect.
-	    }
-
-	    // Disconnect the channelSet.
-	    var i:int = channelSet != null ? _channelSets.indexOf(channelSet) : -1;
+    }
+
+    /**
+     *  Disconnects the ChannelSet from the Channel. If the Channel is connected
+     *  to its endpoint and it has no more connected ChannelSets it will
+     *  internally disconnect.
+     *
+     *
Channel subclasses need to override the
+     *  internalDisconnect() method, and call the
+     *  disconnectSuccess() method when the underlying connection
+     *  has been terminated.

+     *
+     *  @param channelSet The ChannelSet to disconnect from the Channel.
+     */
+    final public function disconnect(channelSet:ChannelSet):void
+    {
+        // If we own the wait guard for initial Channel connects release it.
+        // This will only be true if this Channel is the first to attempt to connect
+        // but its connect attempt is still pending when disconnect() is invoked.
+        if (_ownsWaitGuard)
+        {
+            _ownsWaitGuard = false;
+            FlexClient.getInstance().waitForFlexClientId = false; // Allow other Channels to connect.
+        }
+
+        // Disconnect the channelSet.
+        var i:int = channelSet != null ? _channelSets.indexOf(channelSet) : -1;
         if (i != -1)
         {
             _channelSets.splice(i, 1);
             // Remove the ChannelSet as a listener to this Channel.
             removeEventListener(ChannelEvent.CONNECT, channelSet.channelConnectHandler, false);
-            removeEventListener(ChannelEvent.DISCONNECT, channelSet.channelDisconnectHandler, false);
+            removeEventListener(ChannelEvent.DISCONNECT, channelSet.channelDisconnectHandler, false);
             removeEventListener(ChannelFaultEvent.FAULT, channelSet.channelFaultHandler, false);
-
-            // Notify the ChannelSet of the disconnect.
-            if (connected)
-            {
+
+            // Notify the ChannelSet of the disconnect.
+            if (connected)
+            {
                 channelSet.channelDisconnectHandler(ChannelEvent.createEvent(ChannelEvent.DISCONNECT, this, false));
             }
-
-    	    // Shut down the underlying connection if this Channel has no more
-    	    // ChannelSets using it.
+
+            // Shut down the underlying connection if this Channel has no more
+            // ChannelSets using it.
             if (_channelSets.length == 0)
             {
                 _shouldBeConnected = false;
@@ -843,18 +894,18 @@
                     internalDisconnect();
             }
         }
-	}
-
-	/**
-	 *  Sends a CommandMessage to the server to logout if the Channel is connected.
-	 *  Current credentials are cleared.
-	 *
-	 *  @param agent The MessageAgent to logout.
-	 */
-	public function logout(agent:MessageAgent):void
+    }
+
+    /**
+     *  Sends a CommandMessage to the server to logout if the Channel is connected.
+     *  Current credentials are cleared.
+     *
+     *  @param agent The MessageAgent to logout.
+     */
+    public function logout(agent:MessageAgent):void
     {
         if ((connected && authenticated && credentials) || (authenticating && credentials))
-        {
+        {
             var msg:CommandMessage = new CommandMessage();
             msg.operation = CommandMessage.LOGOUT_OPERATION;
             internalSend(new AuthenticationMessageResponder(agent, msg, this, _log));
@@ -863,95 +914,95 @@
         credentials = null;
     }

-	/**
-	 *  Sends the specified message to its target destination.
-	 *  Subclasses must override the internalSend() method to
-	 *  perform the actual send.
-     *
-	 *  @param agent The MessageAgent that is sending the message.
-	 *
-	 *  @param message The Message to send.
-	 *
-	 *  @throws mx.messaging.errors.InvalidDestinationError If neither the MessageAgent nor the
-	 *                                  message specify a destination.
-	 */
-	public function send(agent:MessageAgent, message:IMessage):void
-	{
+    /**
+     *  Sends the specified message to its target destination.
+     *  Subclasses must override the internalSend() method to
+     *  perform the actual send.
+     *
+     *  @param agent The MessageAgent that is sending the message.
+     *
+     *  @param message The Message to send.
+     *
+     *  @throws mx.messaging.errors.InvalidDestinationError If neither the MessageAgent nor the
+     *                                  message specify a destination.
+     */
+    public function send(agent:MessageAgent, message:IMessage):void
+    {
         // Set the destination header of the message if it is not already set.
         if (message.destination.length == 0)
         {
             if (agent.destination.length == 0)
-			{
-				var msg:String = resourceManager.getString(
-					"messaging", "noDestinationSpecified");
+            {
+                var msg:String = resourceManager.getString(
+                    "messaging", "noDestinationSpecified");
                 throw new InvalidDestinationError(msg);
-			}
+            }
             message.destination = agent.destination;
         }

         if (Log.isDebug())
             _log.debug("'{0}' channel sending message:\n{1}", id, message.toString());

-        // Tag the message with a header indicating the Channel/Endpoint used for transport.
+        // Tag the message with a header indicating the Channel/Endpoint used for transport.
         message.headers[AbstractMessage.ENDPOINT_HEADER] = id;

         var responder:MessageResponder = getMessageResponder(agent, message);
         initializeRequestTimeout(responder);
         internalSend(responder);
-	}
-
-	/**
-	 *  Sets the credentials to the specified value.
-	 *  If the credentials are non-null and the Channel is connected, this method also
-	 *  sends a CommandMessage to the server to login using the credentials.
-	 *
-	 *  @param credentials The credentials string.
-	 *  @param agent The MessageAgent to login, that will handle the login result.
+    }
+
+    /**
+     *  Sets the credentials to the specified value.
+     *  If the credentials are non-null and the Channel is connected, this method also
+     *  sends a CommandMessage to the server to login using the credentials.
+     *
+     *  @param credentials The credentials string.
+     *  @param agent The MessageAgent to login, that will handle the login result.
      *  @param charset The character set encoding used while encoding the
      *  credentials. The default is null, which implies the legacy charset of
      *  ISO-Latin-1.
-	 *
-	 *  @throws flash.errors.IllegalOperationError in two situations; if credentials
-	 *  have already been set and an authentication is in progress with the remote
-	 *  detination, or if authenticated and the credentials specified don't match
-	 *  the currently authenticated credentials.
-	 */
-	public function setCredentials(credentials:String, agent:MessageAgent=null, charset:String=null):void
-	{
-	    var changedCreds:Boolean = this.credentials !== credentials;
-
-	    if (authenticating && changedCreds)
-	        throw new IllegalOperationError("Credentials cannot be set while authenticating or logging out.");
-
-	    if (authenticated && changedCreds)
-	        throw new IllegalOperationError("Credentials cannot be set when already authenticated. Logout must be performed before changing credentials.");
-
-	    this.credentials = credentials;
-	    if (connected && changedCreds && credentials != null)
-	    {
+     *
+     *  @throws flash.errors.IllegalOperationError in two situations; if credentials
+     *  have already been set and an authentication is in progress with the remote
+     *  detination, or if authenticated and the credentials specified don't match
+     *  the currently authenticated credentials.
+     */
+    public function setCredentials(credentials:String, agent:MessageAgent=null, charset:String=null):void
+    {
+        var changedCreds:Boolean = this.credentials !== credentials;
+
+        if (authenticating && changedCreds)
+            throw new IllegalOperationError("Credentials cannot be set while authenticating or logging out.");
+
+        if (authenticated && changedCreds)
+            throw new IllegalOperationError("Credentials cannot be set when already authenticated. Logout must be performed before changing credentials.");
+
+        this.credentials = credentials;
+        if (connected && changedCreds && credentials != null)
+        {
             authenticating = true;
-	        var msg:CommandMessage = new CommandMessage();
-	        msg.operation = CommandMessage.LOGIN_OPERATION;
-	        msg.body = credentials;
-	        if (charset != null)
-	            msg.headers[CommandMessage.CREDENTIALS_CHARSET_HEADER] = charset;
-    	    internalSend(new AuthenticationMessageResponder(agent, msg, this, _log));
-	    }
-	}
-
-    /**
-     * @private
+            var msg:CommandMessage = new CommandMessage();
+            msg.operation = CommandMessage.LOGIN_OPERATION;
+            msg.body = credentials;
+            if (charset != null)
+                msg.headers[CommandMessage.CREDENTIALS_CHARSET_HEADER] = charset;
+            internalSend(new AuthenticationMessageResponder(agent, msg, this, _log));
+        }
+    }
+
+    /**
+     * @private
      * Should we record any performance metrics
-     */
+     */
     public function get mpiEnabled():Boolean
     {
-    	return _recordMessageSizes || _recordMessageTimes;
-    }
+        return _recordMessageSizes || _recordMessageTimes;
+    }

     //--------------------------------------------------------------------------
     //
     // Internal Methods
-    //
+    //
     //--------------------------------------------------------------------------

     /**
@@ -966,186 +1017,186 @@

     /**
      *  @private
-     *  This is a hook for ChannelSet (not a MessageAgent) to send requests for
-     *  clustered endpoints for a clustered destination and provide its own
-     *  custom responder, rather than relying on the generic responders used by
+     *  This is a hook for ChannelSet (not a MessageAgent) to send requests for
+     *  clustered endpoints for a clustered destination and provide its own
+     *  custom responder, rather than relying on the generic responders used by
      *  Channel implemenations.
-     *
+     *
      *  @param msgResp The message responder to use for the cluster request response.
      */
-	mx_internal function sendClusterRequest(msgResp:MessageResponder):void
-	{
-	    internalSend(msgResp);
-	}
+    mx_internal function sendClusterRequest(msgResp:MessageResponder):void
+    {
+        internalSend(msgResp);
+    }

     //--------------------------------------------------------------------------
     //
     // Protected Methods
-    //
-    //--------------------------------------------------------------------------
-
-	/**
-	 *  Processes a failed internal connect and dispatches the
-	 *  FAULT event for the channel.
-	 *  If the Channel has failoverURI values, it will
-	 *  attempt to reconnect automatically by trying these URI values in order until
-	 *  a connection is established or the available values are exhausted.
-	 *
-	 *  @param event The ChannelFaultEvent for the failed connect.
-	 */
-	protected function connectFailed(event:ChannelFaultEvent):void
-	{
-	    shutdownConnectTimer();
-	    setConnected(false);
-
-	    if (Log.isError())
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Processes a failed internal connect and dispatches the
+     *  FAULT event for the channel.
+     *  If the Channel has failoverURI values, it will
+     *  attempt to reconnect automatically by trying these URI values in order until
+     *  a connection is established or the available values are exhausted.
+     *
+     *  @param event The ChannelFaultEvent for the failed connect.
+     */
+    protected function connectFailed(event:ChannelFaultEvent):void
+    {
+        shutdownConnectTimer();
+        setConnected(false);
+
+        if (Log.isError())
             _log.error("'{0}' channel connect failed.", id);
-
+
         if (!event.rejected && shouldAttemptFailover())
         {
             _connecting = true;
-	        failover();
+            failover();
         }
         else // Not attempting failover.
         {
-    	    connectCleanup();
-        }
-
+            connectCleanup();
+        }
+
         if (reconnecting)
             event.reconnecting = true;
         dispatchEvent(event);
-	}
-
-	/**
-	 *  Processes a successful internal connect and dispatches the
-	 *  CONNECT event for the Channel.
-	 */
-	protected function connectSuccess():void
-	{
-	    shutdownConnectTimer();
-
+    }
+
+    /**
+     *  Processes a successful internal connect and dispatches the
+     *  CONNECT event for the Channel.
+     */
+    protected function connectSuccess():void
+    {
+        shutdownConnectTimer();
+
         // If there were any attached agents that needed configuration they
         // should be reset.
         if (ServerConfig.fetchedConfig(endpoint))
         {
-    		for (var i:int = 0; i < channelSets.length; i++)
+            for (var i:int = 0; i < channelSets.length; i++)
             {
                 var messageAgents:Array = ChannelSet(channelSets[i]).messageAgents;
                 for (var j:int = 0; j < messageAgents.length; j++)
-				{
+                {
                     messageAgents[j].needsConfig = false;
-				}
+                }
             }
         }
-
-	    setConnected(true);
-	    _failoverIndex = -1;
-
-	    if (Log.isInfo())
-	        _log.info("'{0}' channel is connected.", id);
-
-	    dispatchEvent(ChannelEvent.createEvent(ChannelEvent.CONNECT, this, reconnecting));
-
+
+        setConnected(true);
+        _failoverIndex = -1;
+
+        if (Log.isInfo())
+            _log.info("'{0}' channel is connected.", id);
+
+        dispatchEvent(ChannelEvent.createEvent(ChannelEvent.CONNECT, this, reconnecting));
+
         connectCleanup();
-	}
-
-	/**
-	 *  Handles a connect timeout by dispatching a ChannelFaultEvent.
-	 *  Subtypes may overide this to shutdown the current connect attempt but must
-	 *  call super.connectTimeoutHandler(event).
-	 *
-	 *  @param event The timer event indicating that the connect timeout has been reached.
-	 */
-	protected function connectTimeoutHandler(event:TimerEvent):void
-	{
-	    shutdownConnectTimer();
-	    if (!connected)
-	    {
-    	    _shouldBeConnected = false;
-    	    var errorText:String = resourceManager.getString(
-				"messaging", "connectTimedOut");
-    	    var faultEvent:ChannelFaultEvent = ChannelFaultEvent.createEvent(this, false, "Channel.Connect.Failed", "error", errorText);
-    	    connectFailed(faultEvent);
-    	}
-	}
-
-	/**
-	 *  Processes a successful internal disconnect and dispatches the
-	 *  DISCONNECT event for the Channel.
-	 *  If the disconnect is due to a network failure and the Channel has
-	 *  failoverURI values, it will attempt to reconnect automatically
-	 *  by trying these URI values in order until a connection is established or the
-	 *  available values are exhausted.
-	 *
-	 *  @param rejected True if the disconnect should skip any
-	 *         failover processing that would otherwise be attempted; false
-	 *         if failover processing should be allowed to run.
-	 */
-	protected function disconnectSuccess(rejected:Boolean = false):void
-	{
-	    setConnected(false);
-
+    }
+
+    /**
+     *  Handles a connect timeout by dispatching a ChannelFaultEvent.
+     *  Subtypes may overide this to shutdown the current connect attempt but must
+     *  call super.connectTimeoutHandler(event).
+     *
+     *  @param event The timer event indicating that the connect timeout has been reached.
+     */
+    protected function connectTimeoutHandler(event:TimerEvent):void
+    {
+        shutdownConnectTimer();
+        if (!connected)
+        {
+            _shouldBeConnected = false;
+            var errorText:String = resourceManager.getString(
+                "messaging", "connectTimedOut");
+            var faultEvent:ChannelFaultEvent = ChannelFaultEvent.createEvent(this, false, "Channel.Connect.Failed", "error", errorText);
+            connectFailed(faultEvent);
+        }
+    }
+
+    /**
+     *  Processes a successful internal disconnect and dispatches the
+     *  DISCONNECT event for the Channel.
+     *  If the disconnect is due to a network failure and the Channel has
+     *  failoverURI values, it will attempt to reconnect automatically
+     *  by trying these URI values in order until a connection is established or the
+     *  available values are exhausted.
+     *
+     *  @param rejected True if the disconnect should skip any
+     *         failover processing that would otherwise be attempted; false
+     *         if failover processing should be allowed to run.
+     */
+    protected function disconnectSuccess(rejected:Boolean = false):void
+    {
+        setConnected(false);
+
         if (Log.isInfo())
-		    _log.info("'{0}' channel disconnected.", id);
-
-		if (!rejected && shouldAttemptFailover())
-		{
-		    _connecting = true;
-	        failover();
-	    }
-	    else
-	    {
-	        connectCleanup();
-	    }
-
-		dispatchEvent(ChannelEvent.createEvent(ChannelEvent.DISCONNECT, this,
-		                                    reconnecting, rejected));
-	}
-
-	/**
-	 *  Processes a failed internal disconnect and dispatches the
-	 *  FAULT event for the channel.
-	 *
-	 *  @param event The ChannelFaultEvent for the failed disconnect.
-	 */
-	protected function disconnectFailed(event:ChannelFaultEvent):void
-	{
-	    _connecting = false;
-	    setConnected(false);
-
-	    if (Log.isError())
-	        _log.error("'{0}' channel disconnect failed.", id);
-
-	    if (reconnecting)
-	    {
-	        resetToPrimaryURI();
-	        event.reconnecting = false;
-	    }
-	    dispatchEvent(event);
-	}
-
-	/**
-	 *  Handles a change to the guard condition for managing initial Channel connect for the application.
-	 *  When this is invoked it means that this Channel is waiting to attempt to connect.
-	 *
-	 *  @param event The PropertyChangeEvent dispatched by the FlexClient singleton.
-	 */
-	protected function flexClientWaitHandler(event:PropertyChangeEvent):void
-	{
-	    if (event.property == "waitForFlexClientId")
-	    {
-	        var flexClient:FlexClient = event.source as FlexClient;
-	        if (flexClient.waitForFlexClientId == false) // The wait is over, claim it and attempt to connect.
-	        {
-	            flexClient.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, flexClientWaitHandler);
-	            flexClient.waitForFlexClientId = true;
-	            // This will cause other Channels to wait to attempt to connect.
+            _log.info("'{0}' channel disconnected.", id);
+
+        if (!rejected && shouldAttemptFailover())
+        {
+            _connecting = true;
+            failover();
+        }
+        else
+        {
+            connectCleanup();
+        }
+
+        dispatchEvent(ChannelEvent.createEvent(ChannelEvent.DISCONNECT, this,
+                                            reconnecting, rejected));
+    }
+
+    /**
+     *  Processes a failed internal disconnect and dispatches the
+     *  FAULT event for the channel.
+     *
+     *  @param event The ChannelFaultEvent for the failed disconnect.
+     */
+    protected function disconnectFailed(event:ChannelFaultEvent):void
+    {
+        _connecting = false;
+        setConnected(false);
+
+        if (Log.isError())
+            _log.error("'{0}' channel disconnect failed.", id);
+
+        if (reconnecting)
+        {
+            resetToPrimaryURI();
+            event.reconnecting = false;
+        }
+        dispatchEvent(event);
+    }
+
+    /**
+     *  Handles a change to the guard condition for managing initial Channel connect for the application.
+     *  When this is invoked it means that this Channel is waiting to attempt to connect.
+     *
+     *  @param event The PropertyChangeEvent dispatched by the FlexClient singleton.
+     */
+    protected function flexClientWaitHandler(event:PropertyChangeEvent):void
+    {
+        if (event.property == "waitForFlexClientId")
+        {
+            var flexClient:FlexClient = event.source as FlexClient;
+            if (flexClient.waitForFlexClientId == false) // The wait is over, claim it and attempt to connect.
+            {
+                flexClient.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, flexClientWaitHandler);
+                flexClient.waitForFlexClientId = true;
+                // This will cause other Channels to wait to attempt to connect.
                 // This Channel can continue its attempt.
                 _ownsWaitGuard = true;
-	            internalConnect();
-	        }
-	    }
-	}
+                internalConnect();
+            }
+        }
+    }

     /**
      *  Returns the appropriate MessageResponder for the Channel's
@@ -1153,15 +1204,15 @@
      *  Must be overridden.
      *
      *  @param agent The MessageAgent sending the message.
-     *
+     *
      *  @param message The Message to send.
-     *
+     *
      *  @return The MessageResponder to handle the result or fault.
-     *
+     *
      *  @throws flash.errors.IllegalOperationError If the Channel subclass does not override
      *                                this method.
      */
-    protected function getMessageResponder(agent:MessageAgent,
+    protected function getMessageResponder(agent:MessageAgent,
                                             message:IMessage):MessageResponder
     {
         throw new IllegalOperationError("Channel subclasses must override "
@@ -1175,19 +1226,19 @@
     protected function internalConnect():void {}

     /**
-     *  Disconnects the Channel from its endpoint.
+     *  Disconnects the Channel from its endpoint.
      *  Must be overridden.
-     *
+     *
      *  @param rejected True if the disconnect was due to a connection rejection or timeout
-     * 					and reconnection should not be attempted automatically; otherwise false.
+     * 					and reconnection should not be attempted automatically; otherwise false.
      */
     protected function internalDisconnect(rejected:Boolean = false):void {}
-
+
     /**
      *  Sends the Message out over the Channel and routes the response to the
      *  responder.
      *  Must be overridden.
-     *
+     *
      *  @param messageResponder The MessageResponder to handle the response.
      */
     protected function internalSend(messageResponder:MessageResponder):void {}
@@ -1205,7 +1256,7 @@
     /**
      *  @private
      *  Utility method used to assign the FlexClient Id value to outbound messages.
-     *
+     *
      *  @param message The message to set the FlexClient Id on.
      */
     protected function setFlexClientIdOnMessage(message:IMessage):void
@@ -1218,11 +1269,11 @@
     //--------------------------------------------------------------------------
     //
     // Private Methods
-    //
-    //--------------------------------------------------------------------------
-
-    /**
-     *  @private
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
      *  This method calculates the endpoint value based on the current
      *  uri.
      */
@@ -1243,12 +1294,12 @@

         if (!URLUtil.hasUnresolvableTokens())
         {
-            _isEndpointCalculated = false;
+            _isEndpointCalculated = false;
             return;
         }
-
+
         uriCopy = URLUtil.replaceTokens(uriCopy);
-
+
         // Now, check for a final protocol after relative URLs and tokens
         // have been replaced
         proto = URLUtil.getProtocol(uriCopy);
@@ -1259,19 +1310,19 @@
             _endpoint = protocol + ":" + uriCopy;

         _isEndpointCalculated = true;
-
+
         if (Log.isInfo())
-            _log.info("'{0}' channel endpoint set to {1}", id, _endpoint);
-    }
-
-    /**
-     *  @private
-     *  Initializes the request timeout for this message if the outbound message
-     *  defines a REQUEST_TIMEOUT_HEADER value.
-     *  If this header is not set and the default requestTimeout for the
-     *  channel is greater than 0, the channel default is used.
+            _log.info("'{0}' channel endpoint set to {1}", id, _endpoint);
+    }
+
+    /**
+     *  @private
+     *  Initializes the request timeout for this message if the outbound message
+     *  defines a REQUEST_TIMEOUT_HEADER value.
+     *  If this header is not set and the default requestTimeout for the
+     *  channel is greater than 0, the channel default is used.
      *  Otherwise, no request timeout is enforced on the client.
-     *
+     *
      *  @param messageResponder The MessageResponder to handle the response and monitor the outbound
      *                          request for a timeout.
      */
@@ -1285,26 +1336,26 @@
         }
         else if (requestTimeout > 0) // Use the channel default.
         {
-            messageResponder.startRequestTimeout(requestTimeout);
-        }
-    }
-
+            messageResponder.startRequestTimeout(requestTimeout);
+        }
+    }
+
     /**
      *  @private
      *  Convenience method to test whether the Channel should attempt to
      *  failover.
-     *
+     *
      *  @return true if the Channel should try to failover;
      *          otherwise false.
      */
     private function shouldAttemptFailover():Boolean
     {
-        return (_shouldBeConnected &&
+        return (_shouldBeConnected &&
                    (_previouslyConnected ||
-                   (reliableReconnectDuration != -1) ||
-                   ((_failoverURIs != null) &&  (_failoverURIs.length > 0))));
-    }
-
+                   (reliableReconnectDuration != -1) ||
+                   ((_failoverURIs != null) &&  (_failoverURIs.length > 0))));
+    }
+
     /**
      *  @private
      *  This method attempts to fail the Channel over to the next available URI.
@@ -1314,17 +1365,17 @@
         // Potentially enter reliable reconnect loop.
         if (_previouslyConnected)
         {
-            _previouslyConnected = false;
-
+            _previouslyConnected = false;
+
             var acs:Class = null;
             try
             {
                 acs = getDefinitionByName("mx.messaging.AdvancedChannelSet") as Class;
-            }
+            }
             catch (ignore:Error) {}
-            var duration:int = -1;
+            var duration:int = -1;
             if (acs != null)
-            {
+            {
                 for each (var channelSet:ChannelSet in channelSets)
                 {
                     if (channelSet is acs)
@@ -1332,10 +1383,10 @@
                         var d:int = (channelSet as acs)["reliableReconnectDuration"];
                         if (d > duration)
                             duration = d;
-                    }
+                    }
                 }
             }
-
+
             if (duration != -1)
             {
                 setReconnecting(true);
@@ -1345,64 +1396,64 @@
                 return; // Exit early.
             }
         }
-
+
         // Potentially continue reliable reconnect loop.
         if (reliableReconnectDuration != -1)
         {
             _reliableReconnectLastTimestamp = new Date().valueOf();
-            var remaining:Number = reliableReconnectDuration - (_reliableReconnectLastTimestamp - _reliableReconnectBeginTimestamp);
+            var remaining:Number = reliableReconnectDuration - (_reliableReconnectLastTimestamp - _reliableReconnectBeginTimestamp);
             if (remaining > 0)
-            {
+            {
                 // Apply exponential backoff.
                 var delay:int = 1000; // 1 second.
                 delay << ++_reliableReconnectAttempts;
                 if (delay < remaining)
                 {
                     new AsyncDispatcher(reconnect, null, delay);
-                    return; // Exit early.
+                    return; // Exit early.
                 }
             }
             // At this point the reliable reconnect duration has been exhausted.
             reliableReconnectCleanup();
         }
-
+
         // General failover handling.
         ++_failoverIndex;
         if ((_failoverIndex + 1) <= failoverURIs.length)
         {
-	        setReconnecting(true);
+            setReconnecting(true);
             uri = failoverURIs[_failoverIndex];
-
+
             if (Log.isInfo())
             {
-		        _log.info("'{0}' channel attempting to connect to {1}.", id, endpoint);
+                _log.info("'{0}' channel attempting to connect to {1}.", id, endpoint);
             }
             // NetConnection based channels may have their underlying resources
             // GC'ed at the end of the execution of the handler that has
-            // invoked this method, which means that the results of a call to
-            // internalConnect() for these channels may magically vanish once
-            // the handler exits.
+            // invoked this method, which means that the results of a call to
+            // internalConnect() for these channels may magically vanish once
+            // the handler exits.
             // A timer introduces a slight delay in the reconnect attempt to
-            // give the handler time to finish executing, at which point the
-            // internals of a NetConnection channel will be stable and we can
+            // give the handler time to finish executing, at which point the
+            // internals of a NetConnection channel will be stable and we can
             // attempt to connect successfully.
-            // This timer is applied to all channels but the impact is small
-            // enough and the failover scenario rare enough that special casing
-            // this for only NetConnection channels is more trouble than it's
-            // worth.
-            new AsyncDispatcher(reconnect, null, 1);
+            // This timer is applied to all channels but the impact is small
+            // enough and the failover scenario rare enough that special casing
+            // this for only NetConnection channels is more trouble than it's
+            // worth.
+            new AsyncDispatcher(reconnect, null, 1);
         }
         else
         {
             if (Log.isInfo())
             {
-		        _log.info("'{0}' channel has exhausted failover options and has reset to its primary endpoint.", id);
-		    }
+                _log.info("'{0}' channel has exhausted failover options and has reset to its primary endpoint.", id);
+            }
             // Nothing left to failover to; reset to primary.
-            resetToPrimaryURI();
-        }
-    }
-
+            resetToPrimaryURI();
+        }
+    }
+
     /**
      *  @private
      *  Cleanup following a connect or failover attempt.
@@ -1415,18 +1466,18 @@
             _ownsWaitGuard = false;
             FlexClient.getInstance().waitForFlexClientId = false; // Allow other Channels to connect.
         }
-
+
         _connecting = false;
-
+
         setReconnecting(false); // Ensure the reconnecting flag is turned off; failover is not being attempted.
-
+
         reliableReconnectCleanup();
     }
-
-    /**
-     *  @private
-     *  This method is invoked by a timer from failover() and it works around a
-     *  reconnect issue with NetConnection based channels by invoking
+
+    /**
+     *  @private
+     *  This method is invoked by a timer from failover() and it works around a
+     *  reconnect issue with NetConnection based channels by invoking
      *  internalConnect() after a slight delay.
      */
     private function reconnect(event:TimerEvent=null):void
@@ -1445,7 +1496,7 @@
         _reliableReconnectLastTimestamp = 0;
         _reliableReconnectAttempts = 0;
     }
-
+
     /**
      *  @private
      *  This method resets the channel back to its primary URI after
@@ -1458,7 +1509,26 @@
         uri = _primaryURI;
         _failoverIndex = -1;
     }
-
+
+    /**
+     *  @private
+     *  Shuffles the array.
+     */
+    private function shuffle(elements:Array):void
+    {
+        var length:int = elements.length;
+        for(var i:int=0; i < length; i++)
+        {
+            var index:int = Math.floor(Math.random()* length);
+            if (index != i)
+            {
+                var temp:Object = elements[i];
+                elements[i] = elements[index];
+                elements[index] = temp;
+            }
+        }
+    }
+
     /**
      *  @private
      *  Shuts down and nulls out the connect timer.
@@ -1469,26 +1539,26 @@
         {
             _connectTimer.stop();
             _connectTimer.removeEventListener(TimerEvent.TIMER, connectTimeoutHandler);
-    	    _connectTimer = null;
+            _connectTimer = null;
         }
     }

     //--------------------------------------------------------------------------
     //
     // Static Constants
-    //
+    //
     //--------------------------------------------------------------------------

     /**
      * @private
      */
     public static const SMALL_MESSAGES_FEATURE:String = "small_messages";
-
+
     /**
      *  @private
      *  Creates a compile time dependency on ArrayCollection to ensure
      *  it is present for response data containing collections.
-     */
+     */
     private static const dep:ArrayCollection = null;
 }

@@ -1497,7 +1567,7 @@
 //------------------------------------------------------------------------------
 //
 // Private Classes
-//
+//
 //------------------------------------------------------------------------------

 import mx.core.mx_internal;
@@ -1519,40 +1589,40 @@
  */
 class AuthenticationMessageResponder extends MessageResponder
 {
-	//--------------------------------------------------------------------------
-	//
-	// Constructor
-	//
-	//--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    //
+    // Constructor
+    //
+    //--------------------------------------------------------------------------

     public function AuthenticationMessageResponder(agent:MessageAgent,
                                 message:IMessage, channel:Channel, log:ILogger)
     {
-	    super(agent, message, channel);
-	    _log = log;
-    }
-
-	//--------------------------------------------------------------------------
-	//
-	// Variables
-	//
-	//--------------------------------------------------------------------------
-
+        super(agent, message, channel);
+        _log = log;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    //
+    //--------------------------------------------------------------------------
+
     /**
      *  @private
      *  Reference to the logger for the associated Channel.
      */
     private var _log:ILogger;
-
+
     //--------------------------------------------------------------------------
     //
     // Methods
-    //
+    //
     //--------------------------------------------------------------------------

     /**
      *  Handles an authentication result.
-     *
+     *
      *  @param msg The result Message.
      */
     override protected function resultHandler(msg:IMessage):void
@@ -1562,7 +1632,7 @@
         if (cmd.operation == CommandMessage.LOGIN_OPERATION)
         {
             if (Log.isDebug())
-                _log.debug("Login successful");
+                _log.debug("Login successful");

             // we want to set the authenticated property last as it will dispatch
             // an event in this case and handler code shouldn't get called
@@ -1573,24 +1643,24 @@
         {
             if (Log.isDebug())
                 _log.debug("Logout successful");
-
+
             channel.mx_internal::setAuthenticated(false);
         }
     }

     /**
      *  Handles an authentication failure.
-     *
+     *
      *  @param msg The failure Message.
      */
     override protected function statusHandler(msg:IMessage):void
     {
         var cmd:CommandMessage = CommandMessage(message);
-
+
         if (Log.isDebug())
         {
-            _log.debug("{1} failure: {0}", msg.toString(),
-                        cmd.operation == CommandMessage.LOGIN_OPERATION ? "Login" : "Logout");
+            _log.debug("{1} failure: {0}", msg.toString(),
+                        cmd.operation == CommandMessage.LOGIN_OPERATION ? "Login" : "Logout");
         }

         channel.mx_internal::authenticating = false;
@@ -1603,11 +1673,11 @@
         else
         {
             var errMsg:ErrorMessage = ErrorMessage(msg);
-            var channelFault:ChannelFaultEvent =
-                                        ChannelFaultEvent.createEvent(channel, false,
-                                        "Channel.Authentication.Error", "warn",
+            var channelFault:ChannelFaultEvent =
+                                        ChannelFaultEvent.createEvent(channel, false,
+                                        "Channel.Authentication.Error", "warn",
                                         errMsg.faultString);
-            channelFault.rootCause = errMsg;
+            channelFault.rootCause = errMsg;
             channel.dispatchEvent(channelFault);
         }
     }