/*
* Copyright (c) 2015 Snowplow Analytics Ltd. All rights reserved.
*
* This program is licensed to you under the Apache License Version 2.0,
* and you may not use this file except in compliance with the Apache License Version 2.0.
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the Apache License Version 2.0 is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/

package com.snowplowanalytics.snowplow.tracker.emitter
{
	import com.adobe.net.URI;
	import com.snowplowanalytics.snowplow.tracker.Constants;
	import com.snowplowanalytics.snowplow.tracker.Util;
	import com.snowplowanalytics.snowplow.tracker.event.EmitterEvent;
	import com.snowplowanalytics.snowplow.tracker.payload.IPayload;
	import com.snowplowanalytics.snowplow.tracker.payload.SchemaPayload;

	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;

	public class Emitter extends EventDispatcher
	{
		private var _uri:URI;
		private var _buffer:Array = [];

		protected var bufferSize:int = BufferOption.DEFAULT;
		protected var httpMethod:String = URLRequestMethod.GET;

		/**
		 * Create an Emitter instance with a collector URL and HttpMethod to send requests.
		 * @param URI The collector URL. Don't include "http://" - this is done automatically.
		 * @param httpMethod The HTTP request method. If GET, BufferOption is set to Instant.
		 * @param successCallback The callback function to handle success cases when sending events.
		 * @param errorCallback The callback function to handle error cases when sending events.
		 */
		public function Emitter(uri:String, httpMethod:String = "get") {
			if (httpMethod == URLRequestMethod.GET) {
				_uri = new URI("http://" + uri + "/i");
			} else { // POST
				_uri = new URI("http://" + uri + "/" + Constants.PROTOCOL_VENDOR + "/" + Constants.PROTOCOL_VERSION);
			}

			this.httpMethod = httpMethod;
		}

		/**
		 * Sets whether the buffer should send events instantly or after the buffer has reached
		 * it's limit. By default, this is set to BufferOption Default.
		 * @param option Set the BufferOption enum to Instant send events upon creation.
		 */
		public function setBufferSize(option:int):void {
			this.bufferSize = option;
		}

		/**
		 * Add event payloads to the emitter's buffer
		 * @param payload Payload to be added
		 */
		public function addToBuffer(payload:IPayload):void {
			_buffer.push(payload);
			if (_buffer.length == bufferSize)
				flushBuffer();
		}

		/**
		 * Sends all events in the buffer to the collector.
		 */
		public function checkBufferComplete(successCount:int, totalCount:int, totalPayloads:int, unsentPayloads:Array):void {
			if (totalCount == totalPayloads)
			{
				if (unsentPayloads.length == 0)
				{
					dispatchEvent(new EmitterEvent(EmitterEvent.SUCCESS, successCount));
				}
				else
				{
					dispatchEvent(new EmitterEvent(EmitterEvent.FAILURE, successCount, unsentPayloads, "Not all items in buffer were sent"));
				}
			}
		}

		/**
		 * Sends all events in the buffer to the collector.
		 */
		public function flushBuffer():void {
			if (_buffer.length == 0) {
				trace("Buffer is empty, exiting flush operation.");
				return;
			}

			if (httpMethod == URLRequestMethod.GET) {
				var successCount:int = 0;
				var totalCount:int = 0;
				var totalPayloads:int = _buffer.length;
				var unsentPayloads:Array = [];

				for each (var getPayload:IPayload in _buffer) {
					sendGetData(getPayload,
						function onGetSuccess (data:*):void {
							successCount++;
							totalCount++;
							checkBufferComplete(successCount, totalCount, totalPayloads, unsentPayloads);
						},
						function onGetError ():void {
							totalCount++;
							unsentPayloads.push(payload);
							checkBufferComplete(successCount, totalCount, totalPayloads, unsentPayloads);
						}
					);
				}
			} else if (httpMethod == URLRequestMethod.POST) {
				var unsentPayload:Array = [];

				var postPayload:SchemaPayload = new SchemaPayload();
				postPayload.setSchema(Constants.SCHEMA_PAYLOAD_DATA);

				var eventMaps:Array = [];
				for each (var payload:IPayload in _buffer) {
					eventMaps.push(payload.getMap());
				}

				postPayload.setData(eventMaps);

				sendPostData(postPayload,
					function onPostSuccess (data:*):void
					{
						dispatchEvent(new EmitterEvent(EmitterEvent.SUCCESS, _buffer.length));
					},
					function onPostError (event:Event):void
					{
						unsentPayload.push(postPayload);
						dispatchEvent(new EmitterEvent(EmitterEvent.FAILURE, 0, unsentPayloads, event.toString()));
					}
				);
			}

			// Empties current buffer
			Util.clearArray(_buffer);
		}

		protected function sendPostData(payload:IPayload, successCallback:Function, errorCallback:Function):void
		{
			Util.getResponse(_uri.toString(),
				successCallback,
				errorCallback,
				URLRequestMethod.POST,
				payload.toString());
		}

		protected function sendGetData(payload:IPayload, successCallback:Function, errorCallback:Function):void
		{
			var hashMap:Object = payload.getMap();
			_uri.setQueryByMap(hashMap);

			Util.getResponse(_uri.toString(),
				successCallback,
				errorCallback);
		}
	}
}

/*
* Copyright (c) 2015 Snowplow Analytics Ltd. All rights reserved.
*
* This program is licensed to you under the Apache License Version 2.0,
* and you may not use this file except in compliance with the Apache License Version 2.0.
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the Apache License Version 2.0 is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/

package com.snowplowanalytics.snowplow.tracker.emitter
{
	import com.adobe.net.URI;
	import com.snowplowanalytics.snowplow.tracker.Constants;
	import com.snowplowanalytics.snowplow.tracker.Util;
	import com.snowplowanalytics.snowplow.tracker.event.EmitterEvent;
	import com.snowplowanalytics.snowplow.tracker.payload.IPayload;
	import com.snowplowanalytics.snowplow.tracker.payload.SchemaPayload;

	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;

	public class Emitter extends EventDispatcher
	{
		private var _uri:URI;
		private var _buffer:Array = [];

		protected var bufferSize:int = BufferOption.DEFAULT;
		protected var httpMethod:String = URLRequestMethod.GET;

		/**
		 * Create an Emitter instance with a collector URL and HttpMethod to send requests.
		 * @param URI The collector URL. Don't include "http://" - this is done automatically.
		 * @param httpMethod The HTTP request method. If GET, BufferOption is set to Instant.
		 * @param successCallback The callback function to handle success cases when sending events.
		 * @param errorCallback The callback function to handle error cases when sending events.
		 */
		public function Emitter(uri:String, httpMethod:String = URLRequestMethod.GET) {
			if (httpMethod == URLRequestMethod.GET) {
				_uri = new URI("http://" + uri + "/i");
			} else { // POST
				_uri = new URI("http://" + uri + "/" + Constants.PROTOCOL_VENDOR + "/" + Constants.PROTOCOL_VERSION);
			}

			this.httpMethod = httpMethod;
		}

		/**
		 * Sets whether the buffer should send events instantly or after the buffer has reached
		 * it's limit. By default, this is set to BufferOption Default.
		 * @param option Set the BufferOption enum to Instant send events upon creation.
		 */
		public function setBufferSize(option:int):void {
			this.bufferSize = option;
		}

		/**
		 * Add event payloads to the emitter's buffer
		 * @param payload Payload to be added
		 */
		public function addToBuffer(payload:IPayload):void {
			_buffer.push(payload);
			if (_buffer.length == bufferSize)
				flushBuffer();
		}

		/**
		 * Sends all events in the buffer to the collector.
		 */
		public function checkBufferComplete(successCount:int, totalCount:int, totalPayloads:int, unsentPayloads:Array):void {
			if (totalCount == totalPayloads)
			{
				if (unsentPayloads.length == 0)
				{
					dispatchEvent(new EmitterEvent(EmitterEvent.SUCCESS, successCount));
				}
				else
				{
					dispatchEvent(new EmitterEvent(EmitterEvent.FAILURE, successCount, unsentPayloads, "Not all items in buffer were sent"));
				}
			}
		}

		/**
		 * Sends all events in the buffer to the collector.
		 */
		public function flushBuffer():void {
			if (_buffer.length == 0) {
				trace("Buffer is empty, exiting flush operation.");
				return;
			}

			if (httpMethod == URLRequestMethod.GET) {
				var successCount:int = 0;
				var totalCount:int = 0;
				var totalPayloads:int = _buffer.length;
				var unsentPayloads:Array = [];

				for each (var getPayload:IPayload in _buffer) {
					sendGetData(getPayload,
						function onGetSuccess (data:*):void {
							successCount++;
							totalCount++;
							checkBufferComplete(successCount, totalCount, totalPayloads, unsentPayloads);
						},
						function onGetError ():void {
							totalCount++;
							unsentPayloads.push(payload);
							checkBufferComplete(successCount, totalCount, totalPayloads, unsentPayloads);
						}
					);
				}
			} else if (httpMethod == URLRequestMethod.POST) {
				var unsentPayload:Array = [];

				var postPayload:SchemaPayload = new SchemaPayload();
				postPayload.setSchema(Constants.SCHEMA_PAYLOAD_DATA);

				var eventMaps:Array = [];
				for each (var payload:IPayload in _buffer) {
					eventMaps.push(payload.getMap());
				}

				postPayload.setData(eventMaps);

				sendPostData(postPayload,
					function onPostSuccess (data:*):void
					{
						dispatchEvent(new EmitterEvent(EmitterEvent.SUCCESS, _buffer.length));
					},
					function onPostError (event:Event):void
					{
						unsentPayload.push(postPayload);
						dispatchEvent(new EmitterEvent(EmitterEvent.FAILURE, 0, unsentPayloads, event.toString()));
					}
				);
			}

			// Empties current buffer
			Util.clearArray(_buffer);
		}

		protected function sendPostData(payload:IPayload, successCallback:Function, errorCallback:Function):void
		{
			Util.getResponse(_uri.toString(),
				successCallback,
				errorCallback,
				URLRequestMethod.POST,
				payload.toString());
		}

		protected function sendGetData(payload:IPayload, successCallback:Function, errorCallback:Function):void
		{
			var hashMap:Object = payload.getMap();
			_uri.setQueryByMap(hashMap);

			Util.getResponse(_uri.toString(),
				successCallback,
				errorCallback);
		}
	}
}

Use constant in constructor params

Use constant in constructor params


// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2011  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
package com.kaltura.delegates {

	import com.kaltura.KalturaClient;
	import com.kaltura.config.IKalturaConfig;
	import com.kaltura.config.KalturaConfig;
	import com.kaltura.core.KClassFactory;
	import com.kaltura.encryption.MD5;
	import com.kaltura.errors.KalturaError;
	import com.kaltura.events.KalturaEvent;
	import com.kaltura.net.KalturaCall;

	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.net.FileReference;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.utils.Timer;
	import flash.utils.getDefinitionByName;

	public class WebDelegateBase extends EventDispatcher implements IKalturaCallDelegate {

		public static var CONNECT_TIME:int = 120000; //120 secs
		public static var LOAD_TIME:int = 120000; //120 secs

		protected var connectTimer:Timer;
		protected var loadTimer:Timer;

		protected var _call:KalturaCall;
		protected var _config:KalturaConfig;

		protected var loader:URLLoader;
		protected var fileRef:FileReference;

		//Setters & getters
		public function get call():KalturaCall {
			return _call;
		}

		public function set call(newVal:KalturaCall):void {
			_call = newVal;
		}

		public function get config():IKalturaConfig {
			return _config;
		}

		public function set config(newVal:IKalturaConfig):void {
			_config = newVal as KalturaConfig;
		}

		public function WebDelegateBase(call:KalturaCall = null, config:KalturaConfig = null) {
			this.call = call;
			this.config = config;
			if (!call)
				return; //maybe a multi request
			if (call.useTimeout) {
				connectTimer = new Timer(CONNECT_TIME, 1);
				connectTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onConnectTimeout);

				loadTimer = new Timer(LOAD_TIME, 1);
				loadTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onLoadTimeOut);
			}
			execute();
		}

		public function close():void {
			try {
				loader.close();
			}
			catch (e:*) {
			}

			if (call.useTimeout) {
				connectTimer.stop();
				loadTimer.stop();
			}
		}

		protected function onConnectTimeout(event:TimerEvent):void {
			var kError:KalturaError = new KalturaError();
			kError.errorCode = "CONNECTION_TIMEOUT";
			kError.errorMsg = "Connection Timeout: " + CONNECT_TIME / 1000 + " sec with no post command from kaltura client.";
			_call.handleError(kError);
			dispatchEvent(new KalturaEvent(KalturaEvent.FAILED, false, false, false, null, kError));

			loadTimer.stop();
			close();
		}

		protected function onLoadTimeOut(event:TimerEvent):void {
			connectTimer.stop();

			close();

			var kError:KalturaError = new KalturaError();
			kError.errorCode = "POST_TIMEOUT";
			kError.errorMsg = "Post Timeout: " + LOAD_TIME / 1000 + " sec with no post result.";
			_call.handleError(kError);
			dispatchEvent(new KalturaEvent(KalturaEvent.FAILED, false, false, false, null, kError));
		}

		protected function execute():void {
			if (call == null) {
				throw new Error('No call defined.');
			}
			post(); //post the call
		}

		/**
		* Helper function for sending the call straight to the server
		*/
		protected function post():void {

			addOptionalArguments();

			formatRequest();

			sendRequest();

			if (call.useTimeout) {
				connectTimer.start();
			}
		}

		protected function formatRequest():void {
			//The configuration is stronger then the args
			if (_config.partnerId != null && _call.args["partnerId"] == -1)
				_call.setRequestArgument("partnerId", _config.partnerId);

			if (_config.ks != null)
				_call.setRequestArgument("ks", _config.ks);

			if (_config.clientTag != null)
				_call.setRequestArgument("clientTag", _config.clientTag);

			_call.setRequestArgument("ignoreNull", _config.ignoreNull);
			_call.setRequestArgument("apiVersion", KalturaClient.API_VERSION);

			//Create signature hash.
			//call.setRequestArgument("kalsig", getMD5Checksum(call));
		}

		protected function getMD5Checksum(call:KalturaCall):String {
			var props:Array = new Array();
			for (var arg:String in call.args)
				props.push(arg);

			props.sort();

			var s:String = "";
			for each (var prop:String in props) {

				if ( call.args[prop] )
					s += prop +  call.args[prop];
			}

			return MD5.encrypt(s);
		}

		protected function sendRequest():void {

			//construct the loader
			createURLLoader();

			//Create signature hash.
			var kalsig:String = getMD5Checksum(call);

			//create the service request for normal calls
			var url:String = _config.protocol + _config.domain + "/" + _config.srvUrl + "?service=" + call.service + "&action=" + call.action + "&kalsig=" + kalsig;;

			if (_call.method == URLRequestMethod.GET)
				url += "&";

			var req:URLRequest = new URLRequest(url);
			req.contentType = "application/x-www-form-urlencoded";
			req.method = call.method;
			req.data = call.args;

			loader.dataFormat = URLLoaderDataFormat.TEXT;
			loader.load(req);
		}

		protected function createURLLoader():void {
			loader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onDataComplete);
			loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, onHTTPStatus);
			loader.addEventListener(IOErrorEvent.IO_ERROR, onError);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
			loader.addEventListener(Event.OPEN, onOpen);
		}

		protected function onHTTPStatus(event:HTTPStatusEvent):void {
		}

		protected function onOpen(event:Event):void {
			if (call.useTimeout) {
				connectTimer.stop();
				loadTimer.start();
			}
		}

		protected function addOptionalArguments():void {
			//add optional args here
		}

		// Event Handlers

		/**
		 * try to process received data.
		 * if procesing failed, let call handle the processing error
		 * @param event load complete event
		 */
		protected function onDataComplete(event:Event):void {
			try {
				handleResult(XML(event.target.data));
			}
			catch (e:Error) {
				var kErr:KalturaError = new KalturaError();
				kErr.errorCode = String(e.errorID);
				kErr.errorMsg = e.message;
				_call.handleError(kErr);
			}
		}

		/**
		 * handle io or security error events from the loader.
		 * create relevant KalturaError, let the call process it.
		 * @param event
		 */
		protected function onError(event:ErrorEvent):void {
			clean();
			var kError:KalturaError = createKalturaError(event, loader.data);

			if (!kError) {
				kError = new KalturaError();
				kError.errorMsg = event.text;
				kError.errorCode = event.type; 	// either IOErrorEvent.IO_ERROR or SecurityErrorEvent.SECURITY_ERROR
			}

			call.handleError(kError);

			dispatchEvent(new KalturaEvent(KalturaEvent.FAILED, false, false, false, null, kError));
		}

		/**
		 * parse the server's response and let the call process it.
		 * @param result  server's response
		 */
		protected function handleResult(result:XML):void {
			clean();

			var error:KalturaError = validateKalturaResponse(result);

			if (error == null) {
				var digestedResult:Object = parse(result);
				call.handleResult(digestedResult);
			}
			else {
				call.handleError(error);
			}
		}

		/**
		* stop timers and clean event listeners
		 */
		protected function clean():void {
			if (call.useTimeout) {
				connectTimer.stop();
				loadTimer.stop();
			}

			if (loader == null) {
				return;
			}

			loader.removeEventListener(Event.COMPLETE, onDataComplete);
			loader.removeEventListener(IOErrorEvent.IO_ERROR, onError);
			loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
			loader.removeEventListener(Event.OPEN, onOpen);
		}

		/**
		* create the correct object and populate it with the given values. if the needed class is not found
		 * in the file, a generic object is created with attributes matching the XML attributes.
		* Override this parssing function in the specific delegate to create the correct object.
		* @param   result      instance attributes
		* @return an instance of the class declared by the given XML.
		* */
		public function parse(result:XML):* {
			//by defualt create the response object
			var cls:Class;
			try {
				cls = getDefinitionByName('com.kaltura.vo.' + result.result.objectType) as Class;
			}
			catch (e:Error) {
				cls = Object;
			}
			var obj:* = (new KClassFactory(cls)).newInstanceFromXML(result.result);
			return obj;
		}

		/**
		 * If the result string holds an error, return a KalturaError object with
		 * relevant values. <br/>
		 * Overide this to create validation object and fill it.
		 * @param result  the string returned from the server.
		 * @return  matching error object
		 */
		protected function validateKalturaResponse(result:String):KalturaError {
			var kError:KalturaError = null;
			var xml:XML = XML(result);
			if (xml.result.hasOwnProperty('error')
				&& xml.result.error.hasOwnProperty('code')
				&& xml.result.error.hasOwnProperty('message')) {

				kError = new KalturaError();
				kError.errorCode = String(xml.result.error.code);
				kError.errorMsg = xml.result.error.message;
				dispatchEvent(new KalturaEvent(KalturaEvent.FAILED, false, false, false, null, kError));
			}

			return kError;
		}

		/**
		 * create error object and fill it with relevant details
		 * @param event
		 * @param loaderData
		 * @return detailed KalturaError to be processed
		 */
		protected function createKalturaError(event:ErrorEvent, loaderData:*):KalturaError {
			var ke:KalturaError = new KalturaError();
			ke.errorMsg = event.text;
			ke.errorCode = event.type;
			return ke;
		}

		/**
		* create the url that is used for serve actions
		* @param call    the KalturaCall that defines the required parameters
		 * @return URLRequest with relevant parameters
		* */
		public function getServeUrl(call:KalturaCall):URLRequest {
			var url:String = _config.protocol + _config.domain + "/" + _config.srvUrl + "?service=" + call.service + "&action=" + call.action;
			for (var key:String in call.args) {
				url += "&" + key + "=" + call.args[key];
			}
			var req:URLRequest = new URLRequest(url);
			req.contentType = "application/x-www-form-urlencoded";
			req.method = call.method;
//          req.data = call.args;
			return req;
		}

	}
}

// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2011  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
package com.kaltura.delegates {

	import com.kaltura.KalturaClient;
	import com.kaltura.config.IKalturaConfig;
	import com.kaltura.config.KalturaConfig;
	import com.kaltura.core.KClassFactory;
	import com.kaltura.encryption.MD5;
	import com.kaltura.errors.KalturaError;
	import com.kaltura.events.KalturaEvent;
	import com.kaltura.net.KalturaCall;

	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.net.FileReference;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.utils.Timer;
	import flash.utils.getDefinitionByName;

	public class WebDelegateBase extends EventDispatcher implements IKalturaCallDelegate {

		public static var CONNECT_TIME:int = 120000; //120 secs
		public static var LOAD_TIME:int = 120000; //120 secs

		protected var connectTimer:Timer;
		protected var loadTimer:Timer;

		protected var _call:KalturaCall;
		protected var _config:KalturaConfig;

		protected var loader:URLLoader;
		protected var fileRef:FileReference;

		//Setters & getters
		public function get call():KalturaCall {
			return _call;
		}

		public function set call(newVal:KalturaCall):void {
			_call = newVal;
		}

		public function get config():IKalturaConfig {
			return _config;
		}

		public function set config(newVal:IKalturaConfig):void {
			_config = newVal as KalturaConfig;
		}

		public function WebDelegateBase(call:KalturaCall = null, config:KalturaConfig = null) {
			this.call = call;
			this.config = config;
			if (!call)
				return; //maybe a multi request
			if (call.useTimeout) {
				connectTimer = new Timer(CONNECT_TIME, 1);
				connectTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onConnectTimeout);

				loadTimer = new Timer(LOAD_TIME, 1);
				loadTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onLoadTimeOut);
			}
			execute();
		}

		public function close():void {
			try {
				loader.close();
			}
			catch (e:*) {
			}

			if (call.useTimeout) {
				connectTimer.stop();
				loadTimer.stop();
			}
		}

		protected function onConnectTimeout(event:TimerEvent):void {
			var kError:KalturaError = new KalturaError();
			kError.errorCode = "CONNECTION_TIMEOUT";
			kError.errorMsg = "Connection Timeout: " + CONNECT_TIME / 1000 + " sec with no post command from kaltura client.";
			_call.handleError(kError);
			dispatchEvent(new KalturaEvent(KalturaEvent.FAILED, false, false, false, null, kError));

			loadTimer.stop();
			close();
		}

		protected function onLoadTimeOut(event:TimerEvent):void {
			connectTimer.stop();

			close();

			var kError:KalturaError = new KalturaError();
			kError.errorCode = "POST_TIMEOUT";
			kError.errorMsg = "Post Timeout: " + LOAD_TIME / 1000 + " sec with no post result.";
			_call.handleError(kError);
			dispatchEvent(new KalturaEvent(KalturaEvent.FAILED, false, false, false, null, kError));
		}

		protected function execute():void {
			if (call == null) {
				throw new Error('No call defined.');
			}
			post(); //post the call
		}

		/**
		* Helper function for sending the call straight to the server
		*/
		protected function post():void {

			addOptionalArguments();

			formatRequest();

			sendRequest();

			if (call.useTimeout) {
				connectTimer.start();
			}
		}

		protected function formatRequest():void {
			//The configuration is stronger then the args
			if (_config.partnerId != null && (!_call.args["partnerId"] || _call.args["partnerId"]==-1))
				_call.setRequestArgument("partnerId", _config.partnerId);

			if (_config.ks != null)
				_call.setRequestArgument("ks", _config.ks);

			if (_config.clientTag != null)
				_call.setRequestArgument("clientTag", _config.clientTag);

			_call.setRequestArgument("ignoreNull", _config.ignoreNull);
			_call.setRequestArgument("apiVersion", KalturaClient.API_VERSION);

			//Create signature hash.
			//call.setRequestArgument("kalsig", getMD5Checksum(call));
		}

		protected function getMD5Checksum(call:KalturaCall):String {
			var props:Array = new Array();
			for (var arg:String in call.args)
				props.push(arg);

			props.sort();

			var s:String = "";
			for each (var prop:String in props) {

				if ( call.args[prop] )
					s += prop +  call.args[prop];
			}

			return MD5.encrypt(s);
		}

		protected function sendRequest():void {

			//construct the loader
			createURLLoader();

			//Create signature hash.
			var kalsig:String = getMD5Checksum(call);

			//create the service request for normal calls
			var url:String = _config.protocol + _config.domain + "/" + _config.srvUrl + "?service=" + call.service + "&action=" + call.action + "&kalsig=" + kalsig;;

			if (_call.method == URLRequestMethod.GET)
				url += "&";

			var req:URLRequest = new URLRequest(url);
			req.contentType = "application/x-www-form-urlencoded";
			req.method = call.method;
			req.data = call.args;

			loader.dataFormat = URLLoaderDataFormat.TEXT;
			loader.load(req);
		}

		protected function createURLLoader():void {
			loader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onDataComplete);
			loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, onHTTPStatus);
			loader.addEventListener(IOErrorEvent.IO_ERROR, onError);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
			loader.addEventListener(Event.OPEN, onOpen);
		}

		protected function onHTTPStatus(event:HTTPStatusEvent):void {
		}

		protected function onOpen(event:Event):void {
			if (call.useTimeout) {
				connectTimer.stop();
				loadTimer.start();
			}
		}

		protected function addOptionalArguments():void {
			//add optional args here
		}

		// Event Handlers

		/**
		 * try to process received data.
		 * if procesing failed, let call handle the processing error
		 * @param event load complete event
		 */
		protected function onDataComplete(event:Event):void {
			try {
				handleResult(XML(event.target.data));
			}
			catch (e:Error) {
				var kErr:KalturaError = new KalturaError();
				kErr.errorCode = String(e.errorID);
				kErr.errorMsg = e.message;
				_call.handleError(kErr);
			}
		}

		/**
		 * handle io or security error events from the loader.
		 * create relevant KalturaError, let the call process it.
		 * @param event
		 */
		protected function onError(event:ErrorEvent):void {
			clean();
			var kError:KalturaError = createKalturaError(event, loader.data);

			if (!kError) {
				kError = new KalturaError();
				kError.errorMsg = event.text;
				kError.errorCode = event.type; 	// either IOErrorEvent.IO_ERROR or SecurityErrorEvent.SECURITY_ERROR
			}

			call.handleError(kError);

			dispatchEvent(new KalturaEvent(KalturaEvent.FAILED, false, false, false, null, kError));
		}

		/**
		 * parse the server's response and let the call process it.
		 * @param result  server's response
		 */
		protected function handleResult(result:XML):void {
			clean();

			var error:KalturaError = validateKalturaResponse(result);

			if (error == null) {
				var digestedResult:Object = parse(result);
				call.handleResult(digestedResult);
			}
			else {
				call.handleError(error);
			}
		}

		/**
		* stop timers and clean event listeners
		 */
		protected function clean():void {
			if (call.useTimeout) {
				connectTimer.stop();
				loadTimer.stop();
			}

			if (loader == null) {
				return;
			}

			loader.removeEventListener(Event.COMPLETE, onDataComplete);
			loader.removeEventListener(IOErrorEvent.IO_ERROR, onError);
			loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
			loader.removeEventListener(Event.OPEN, onOpen);
		}

		/**
		* create the correct object and populate it with the given values. if the needed class is not found
		 * in the file, a generic object is created with attributes matching the XML attributes.
		* Override this parssing function in the specific delegate to create the correct object.
		* @param   result      instance attributes
		* @return an instance of the class declared by the given XML.
		* */
		public function parse(result:XML):* {
			//by defualt create the response object
			var cls:Class;
			try {
				cls = getDefinitionByName('com.kaltura.vo.' + result.result.objectType) as Class;
			}
			catch (e:Error) {
				cls = Object;
			}
			var obj:* = (new KClassFactory(cls)).newInstanceFromXML(result.result);
			return obj;
		}

		/**
		 * If the result string holds an error, return a KalturaError object with
		 * relevant values. <br/>
		 * Overide this to create validation object and fill it.
		 * @param result  the string returned from the server.
		 * @return  matching error object
		 */
		protected function validateKalturaResponse(result:String):KalturaError {
			var kError:KalturaError = null;
			var xml:XML = XML(result);
			if (xml.result.hasOwnProperty('error')
				&& xml.result.error.hasOwnProperty('code')
				&& xml.result.error.hasOwnProperty('message')) {

				kError = new KalturaError();
				kError.errorCode = String(xml.result.error.code);
				kError.errorMsg = xml.result.error.message;
				dispatchEvent(new KalturaEvent(KalturaEvent.FAILED, false, false, false, null, kError));
			}

			return kError;
		}

		/**
		 * create error object and fill it with relevant details
		 * @param event
		 * @param loaderData
		 * @return detailed KalturaError to be processed
		 */
		protected function createKalturaError(event:ErrorEvent, loaderData:*):KalturaError {
			var ke:KalturaError = new KalturaError();
			ke.errorMsg = event.text;
			ke.errorCode = event.type;
			return ke;
		}

		/**
		* create the url that is used for serve actions
		* @param call    the KalturaCall that defines the required parameters
		 * @return URLRequest with relevant parameters
		* */
		public function getServeUrl(call:KalturaCall):URLRequest {
			var url:String = _config.protocol + _config.domain + "/" + _config.srvUrl + "?service=" + call.service + "&action=" + call.action;
			for (var key:String in call.args) {
				url += "&" + key + "=" + call.args[key];
			}
			var req:URLRequest = new URLRequest(url);
			req.contentType = "application/x-www-form-urlencoded";
			req.method = call.method;
//          req.data = call.args;
			return req;
		}

	}
}

Fix client code to send partnerId from client config by default. Fix By Michal.


////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008-2013 Esri. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package com.esri.builder.controllers.supportClasses
{

import com.esri.builder.supportClasses.LogUtil;

import flash.events.StatusEvent;
import flash.net.LocalConnection;

import mx.logging.ILogger;
import mx.logging.Log;

public final class LocalConnectionDelegate
{
    private static const LOG:ILogger = LogUtil.createLogger(LocalConnectionDelegate);
    private static const CONNECTION_NAME:String = '_flexViewer';

    private var _localConnection:LocalConnection;

    private function get localConnection():LocalConnection
    {
        if (_localConnection === null)
        {
            if (Log.isDebug())
            {
                LOG.debug("Acquiring local connection");
            }

            _localConnection = new LocalConnection();
            _localConnection.addEventListener(StatusEvent.STATUS, localConnection_statusHandler);
        }
        return _localConnection;
    }

    private function localConnection_statusHandler(event:StatusEvent):void
    {
        if (event.level == "error")
        {
            if (Log.isDebug())
            {
                LOG.debug("Call failed: {0}", event.toString());
            }
        }
    }

    public function setTitles(title:String, subtitle:String):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending titles changes: title {0} - subtitle {1}", title, subtitle);
        }

        callViewerMethod('setTitles', title, subtitle);
    }

    private function callViewerMethod(methodName:String, ... values):void
    {
        try
        {
            //use Function#apply to avoid passing rest argument as Array
            localConnection.send.apply(null, [ CONNECTION_NAME, methodName ].concat(values));
        }
        catch (error:Error)
        {
            if (Log.isDebug())
            {
                LOG.debug("Call to Viewer method {0} failed: {1}", methodName, error);
            }
        }
    }

    public function setLogo(value:String):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending logo changes {0}", value);
        }

        callViewerMethod('setLogo', value);
    }

    public function setTextColor(value:uint):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending text color changes {0}", value);
        }

        callViewerMethod('setTextColor', value);
    }

    public function setBackgroundColor(value:uint):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending background color changes {0}", value);
        }

        callViewerMethod('setBackgroundColor', value);
    }

    public function setRolloverColor(value:uint):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending rollover color changes {0}", value);
        }

        callViewerMethod('setRolloverColor', value);
    }

    public function setSelectionColor(value:uint):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending selection color changes {0}", value);
        }

        callViewerMethod('setSelectionColor', value);
    }

    public function setTitleColor(value:uint):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending title color changes {0}", value);
        }

        callViewerMethod('setTitleColor', value);
    }

    public function setLocale(localeChain:String):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending locale changes {0}", localeChain);
        }

        callViewerMethod('setLocale', localeChain);
    }

    public function setFontName(value:String):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending font name changes {0}", value);
        }

        callViewerMethod('setFontName', value);
    }

    public function setAppTitleFontName(value:String):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending app title font name changes {0}", value);
        }

        callViewerMethod('setAppTitleFontName', value);
    }

    public function setSubTitleFontName(value:String):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending subtitle font name changes {0}", value);
        }

        callViewerMethod('setSubTitleFontName', value);
    }

    public function setAlpha(value:Number):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending alpha changes {0}", value);
        }

        callViewerMethod('setAlpha', value);
    }

    public function setPredefinedStyles(value:Object):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Sending predefined changes {0}", value);
        }

        callViewerMethod('setPredefinedStyles', value);
    }
}
}

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008-2013 Esri. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package com.esri.builder.controllers.supportClasses
{

import com.esri.builder.supportClasses.LogUtil;

import flash.events.StatusEvent;
import flash.net.LocalConnection;

import mx.logging.ILogger;
import mx.logging.Log;

public final class LocalConnectionDelegate
{
    private static const LOG:ILogger = LogUtil.createLogger(LocalConnectionDelegate);
    private static const CONNECTION_NAME:String = '_flexViewer';

    private var _localConnection:LocalConnection;

    private function get localConnection():LocalConnection
    {
        if (_localConnection === null)
        {
            if (Log.isDebug())
            {
                LOG.debug("Acquiring local connection");
            }

            _localConnection = new LocalConnection();
            _localConnection.addEventListener(StatusEvent.STATUS, localConnection_statusHandler);
        }
        return _localConnection;
    }

    private function localConnection_statusHandler(event:StatusEvent):void
    {
        if (event.level == "error")
        {
            if (Log.isDebug())
            {
                LOG.debug("Call failed: {0}", event.toString());
            }
        }
    }

    public function setTitles(title:String, subtitle:String):void
    {
        callViewerMethod('setTitles', title, subtitle);
    }

    private function callViewerMethod(methodName:String, ... values):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Calling Viewer method: {0} with the following arguments: {1}", methodName, values);
        }

        try
        {
            //use Function#apply to avoid passing rest argument as Array
            localConnection.send.apply(null, [ CONNECTION_NAME, methodName ].concat(values));
        }
        catch (error:Error)
        {
            if (Log.isDebug())
            {
                LOG.debug("Call to method {0} failed: {1}", methodName, error);
            }
        }
    }

    public function setLogo(value:String):void
    {
        callViewerMethod('setLogo', value);
    }

    public function setTextColor(value:uint):void
    {
        callViewerMethod('setTextColor', value);
    }

    public function setBackgroundColor(value:uint):void
    {
        callViewerMethod('setBackgroundColor', value);
    }

    public function setRolloverColor(value:uint):void
    {
        callViewerMethod('setRolloverColor', value);
    }

    public function setSelectionColor(value:uint):void
    {
        callViewerMethod('setSelectionColor', value);
    }

    public function setTitleColor(value:uint):void
    {
        callViewerMethod('setTitleColor', value);
    }

    public function setLocale(localeChain:String):void
    {
        callViewerMethod('setLocale', localeChain);
    }

    public function setFontName(value:String):void
    {
        callViewerMethod('setFontName', value);
    }

    public function setAppTitleFontName(value:String):void
    {
        callViewerMethod('setAppTitleFontName', value);
    }

    public function setSubTitleFontName(value:String):void
    {
        callViewerMethod('setSubTitleFontName', value);
    }

    public function setAlpha(value:Number):void
    {
        callViewerMethod('setAlpha', value);
    }

    public function setPredefinedStyles(value:Object):void
    {
        callViewerMethod('setPredefinedStyles', value);
    }
}
}

Generalize method call log messages.

Generalize method call log messages.


////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package
{

/**
 *  @private
 *  This class is used to link additional classes into rpc.swc
 *  beyond those that are found by dependecy analysis starting
 *  from the classes specified in manifest.xml.
 */
internal class GraphicsClasses
{

	import org.apache.flex.svg.GraphicContainer; GraphicContainer;
	import org.apache.flex.svg.GraphicShape; GraphicShape;
	import org.apache.flex.svg.Rect; Rect;
	import org.apache.flex.svg.Ellipse; Ellipse;
	import org.apache.flex.svg.Circle; Circle;
	import org.apache.flex.svg.Path; Path;
	import org.apache.flex.graphics.SolidColor; SolidColor;
	import org.apache.flex.graphics.SolidColorStroke; SolidColorStroke;
	import org.apache.flex.svg.Text; Text;
	import org.apache.flex.svg.CompoundGraphic; CompoundGraphic;
	import org.apache.flex.svg.LinearGradient; LinearGradient;
	import org.apache.flex.graphics.CubicCurve; CubicCurve;
	import org.apache.flex.graphics.LineStyle; LineStyle;
	import org.apache.flex.graphics.LineTo; LineTo;
	import org.apache.flex.graphics.MoveTo; MoveTo;
	import org.apache.flex.graphics.PathBuilder; PathBuilder;
	import org.apache.flex.graphics.QuadraticCurve; QuadraticCurve;
	import org.apache.flex.svg.DOMWrapper; DOMWrapper;

}

}

////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package
{

/**
 *  @private
 *  This class is used to link additional classes into rpc.swc
 *  beyond those that are found by dependecy analysis starting
 *  from the classes specified in manifest.xml.
 */
internal class GraphicsClasses
{

	import org.apache.flex.svg.GraphicContainer; GraphicContainer;
	import org.apache.flex.svg.GraphicShape; GraphicShape;
	import org.apache.flex.svg.Rect; Rect;
	import org.apache.flex.svg.Ellipse; Ellipse;
	import org.apache.flex.svg.Circle; Circle;
	import org.apache.flex.svg.Path; Path;
	import org.apache.flex.graphics.SolidColor; SolidColor;
	import org.apache.flex.graphics.SolidColorStroke; SolidColorStroke;
	import org.apache.flex.svg.Text; Text;
	import org.apache.flex.svg.CompoundGraphic; CompoundGraphic;
	import org.apache.flex.svg.TransformBead; TransformBead;
	import org.apache.flex.svg.LinearGradient; LinearGradient;
	import org.apache.flex.graphics.CubicCurve; CubicCurve;
	import org.apache.flex.graphics.LineStyle; LineStyle;
	import org.apache.flex.graphics.LineTo; LineTo;
	import org.apache.flex.graphics.MoveTo; MoveTo;
	import org.apache.flex.graphics.PathBuilder; PathBuilder;
	import org.apache.flex.graphics.QuadraticCurve; QuadraticCurve;
	import org.apache.flex.svg.DOMWrapper; DOMWrapper;

}

}

Add transform bead to GraphicClasses

Add transform bead to GraphicClasses


////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package
{

/**
 *  @private
 *  This class is used to link additional classes into rpc.swc
 *  beyond those that are found by dependecy analysis starting
 *  from the classes specified in manifest.xml.
 */
internal class FlexJSUIClasses
{
	import org.apache.flex.html.staticControls.beads.IButtonBead; IButtonBead;
	import org.apache.flex.html.staticControls.beads.CSSTextButtonBead; CSSTextButtonBead;
	import org.apache.flex.html.staticControls.beads.TextButtonBead; TextButtonBead;
	import org.apache.flex.html.staticControls.beads.TextFieldBead; TextFieldBead;
	import org.apache.flex.html.staticControls.beads.TextInputBead; TextInputBead;
	import org.apache.flex.html.staticControls.beads.TextInputWithBorderBead; TextInputWithBorderBead;
	import org.apache.flex.html.staticControls.beads.TextAreaBead; TextAreaBead;
	import org.apache.flex.html.staticControls.beads.CheckBoxBead; CheckBoxBead;
	import org.apache.flex.html.staticControls.beads.RadioButtonBead; RadioButtonBead;
	import org.apache.flex.html.staticControls.beads.ComboBoxBead; ComboBoxBead;
	import org.apache.flex.html.staticControls.beads.models.TextModel; TextModel;
	import org.apache.flex.html.staticControls.beads.models.ComboBoxModel; ComboBoxModel;
	import org.apache.flex.html.staticControls.beads.models.ToggleButtonModel; ToggleButtonModel;
	import org.apache.flex.html.staticControls.beads.models.ValueToggleButtonModel; ValueToggleButtonModel;
    import org.apache.flex.html.staticControls.beads.models.ArraySelectionModel; ArraySelectionModel;
	import org.apache.flex.events.CustomEvent; CustomEvent;
	import org.apache.flex.events.Event; Event;
	import org.apache.flex.utils.Timer; Timer;
}

}

////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package
{

/**
 *  @private
 *  This class is used to link additional classes into rpc.swc
 *  beyond those that are found by dependecy analysis starting
 *  from the classes specified in manifest.xml.
 */
internal class FlexJSUIClasses
{
	import org.apache.flex.html.staticControls.beads.IButtonBead; IButtonBead;
	import org.apache.flex.html.staticControls.beads.CSSTextButtonBead; CSSTextButtonBead;
	import org.apache.flex.html.staticControls.beads.TextButtonBead; TextButtonBead;
	import org.apache.flex.html.staticControls.beads.TextFieldBead; TextFieldBead;
	import org.apache.flex.html.staticControls.beads.TextInputBead; TextInputBead;
	import org.apache.flex.html.staticControls.beads.TextInputWithBorderBead; TextInputWithBorderBead;
	import org.apache.flex.html.staticControls.beads.TextAreaBead; TextAreaBead;
	import org.apache.flex.html.staticControls.beads.CheckBoxBead; CheckBoxBead;
	import org.apache.flex.html.staticControls.beads.RadioButtonBead; RadioButtonBead;
	import org.apache.flex.html.staticControls.beads.ComboBoxBead; ComboBoxBead;
    import org.apache.flex.html.staticControls.beads.ContainerBead; ContainerBead;
	import org.apache.flex.html.staticControls.beads.models.TextModel; TextModel;
	import org.apache.flex.html.staticControls.beads.models.ComboBoxModel; ComboBoxModel;
	import org.apache.flex.html.staticControls.beads.models.ToggleButtonModel; ToggleButtonModel;
	import org.apache.flex.html.staticControls.beads.models.ValueToggleButtonModel; ValueToggleButtonModel;
    import org.apache.flex.html.staticControls.beads.models.ArraySelectionModel; ArraySelectionModel;
	import org.apache.flex.events.CustomEvent; CustomEvent;
	import org.apache.flex.events.Event; Event;
	import org.apache.flex.utils.Timer; Timer;
}

}

Add bead to SWC

Add bead to SWC


/*
* actionscript-cafe AbstractObserver 18 avr. 2011 adesmarais
*
* Created by Servebox
* Copyright 2010 Servebox (c) All rights reserved. You may not use, distribute
* or modify this code under its source or binary form
* without the express authorization of ServeBox. Contact : info@servebox.com
*/
package org.servebox.cafe.core.observer
{
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;
	import flash.utils.describeType;

	import org.servebox.cafe.core.observer.IObservable;
	import org.servebox.cafe.core.observer.IObserver;
	import org.servebox.cafe.core.observer.Notification;
	import org.servebox.cafe.core.signal.Signal;

	public class AbstractObserver extends EventDispatcher implements IObserver
	{
		public function AbstractObserver()
		{
		}

		private var notificationHandlers : Dictionary = null;
		private var signalHandlers : Dictionary = null;

		private function loadMetadata() : void
		{
			if( notificationHandlers != null )
			{
				return;
			}

			notificationHandlers = new Dictionary();
			signalHandlers = new Dictionary();
			var typeDesc : XML = describeType( this );
			for each( var method : XML in typeDesc.method )
			{
				try
				{
					for each ( var metadata : XML in method.metadata.(@name="NotificationHandler")  )
					{
						var notification : String = metadata.arg.(@key=="triggerFor").@value;
						if( notification.length < 1 )
						{
							continue;
						}
						if( notificationHandlers[ notification ] == null )
						{
							notificationHandlers[ notification ] = [];
						}
						notificationHandlers[ notification ].push( this[ method.@name ] );
					}
					for each ( var metadataSignal : XML in method.metadata.(@name="SignalHandler") )
					{
						var signal : String = metadataSignal.arg.(@key=="triggerFor").@value;
						if( signal.length < 1 )
						{
							continue;
						}
						if( signalHandlers[ signal ] == null )
						{
							signalHandlers[ signal ] = [];
						}
						signalHandlers[ signal ].push( this[ method.@name ] );
					}
				}catch( e : Error ){}
			}
		}

		public function update( source : IObservable, notification : Notification ) : void
		{
			loadMetadata();

			if ( !(notification is Signal) )
			{
				var notificationHandlers : Array = notificationHandlers[ notification.getType() ];
				if( notificationHandlers != null )
				{
					for each( var notificationHandler : Function in notificationHandlers )
					{
						notificationHandler.apply( this, [ source, notification ] );
					}
				}
			}
			else
			{
				var signalHandlers : Array = signalHandlers[ notification.getType() ];
				if ( signalHandlers != null )
				{
					for each ( var signalHandler : Function in signalHandlers )
					{
						signalHandler.apply( this, [notification.getCargo()] );
					}
				}
			}
		}
	}
}

/*
* actionscript-cafe AbstractObserver 18 avr. 2011 adesmarais
*
* Created by Servebox
* Copyright 2010 Servebox (c) All rights reserved. You may not use, distribute
* or modify this code under its source or binary form
* without the express authorization of ServeBox. Contact : info@servebox.com
*/
package org.servebox.cafe.core.observer
{
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;
	import flash.utils.describeType;

	import org.servebox.cafe.core.observer.IObservable;
	import org.servebox.cafe.core.observer.IObserver;
	import org.servebox.cafe.core.observer.Notification;
	import org.servebox.cafe.core.signal.Signal;

	public class AbstractObserver extends EventDispatcher implements IObserver
	{
		public function AbstractObserver()
		{
		}

		private var notificationHandlers : Dictionary = null;
		private var signalHandlers : Dictionary = null;

		private function loadMetadata() : void
		{
			if( notificationHandlers != null )
			{
				return;
			}

			notificationHandlers = new Dictionary();
			signalHandlers = new Dictionary();
			var typeDesc : XML = describeType( this );
			for each( var method : XML in typeDesc.method )
			{
				try
				{
					for each ( var metadata : XML in method.metadata.(@name="NotificationHandler")  )
					{
						var notification : String = metadata.arg.(@key=="triggerFor").@value;
						if( notification.length < 1 )
						{
							continue;
						}
						if( notificationHandlers[ notification ] == null )
						{
							notificationHandlers[ notification ] = [];
						}
						notificationHandlers[ notification ].push( this[ method.@name ] );
					}
					for each ( var metadataSignal : XML in method.metadata.(@name="SignalHandler") )
					{
						var signal : String = metadataSignal.arg.(@key=="triggerFor").@value;
						if( signal.length < 1 )
						{
							continue;
						}
						if( signalHandlers[ signal ] == null )
						{
							signalHandlers[ signal ] = [];
						}
						signalHandlers[ signal ].push( this[ method.@name ] );
					}
				}catch( e : Error ){}
			}
		}

		public function update( source : IObservable, notification : Notification ) : void
		{
			loadMetadata();

			if ( !(notification is Signal) )
			{
				var notificationHandlers : Array = notificationHandlers[ notification.getType() ];
				if( notificationHandlers != null )
				{
					for each( var notificationHandler : Function in notificationHandlers )
					{
						notificationHandler.apply( this, [ source, notification ] );
					}
				}
			}
			else
			{
				var signalHandlers : Array = signalHandlers[ notification.getType() ];
				if ( signalHandlers != null )
				{
					for each ( var signalHandler : Function in signalHandlers )
					{
						if ( notification.getCargo() != null )
						{
							signalHandler.apply( this, [notification.getCargo()] );
						}
						else
						{
							signalHandler.apply( this );
						}
					}
				}
			}
		}
	}
}

Change apply method if signal has no cargo.


package com.kaltura.kdpfl.plugin
{
	import com.akamai.osmf.utils.AkamaiStrings;
	import com.kaltura.kdpfl.model.ConfigProxy;
	import com.kaltura.kdpfl.model.MediaProxy;
	import com.kaltura.kdpfl.model.type.NotificationType;
	import com.kaltura.kdpfl.view.media.KMediaPlayerMediator;

	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.mediator.Mediator;

	public class akamaiHDMediator extends Mediator
	{

		public static const NAME:String = "akamaiHDMediator";
		/**
		 * default buffer length to be used when playing with HD Akamai plugin
		 */
		public static const DEFAULT_HD_BUFFER_LENGTH:int = 20;

		/**
		 * default bandwith check time in seconds
		 */
		public static const DEFAULT_HD_BANDWIDTH_CHECK_TIME:int = 2;

		private var _mediaProxy:MediaProxy;
		private var _flashvars:Object;

		public function akamaiHDMediator(viewComponent:Object=null)
		{
			super(NAME, viewComponent);
		}

		override public function onRegister():void
		{
			_mediaProxy = facade.retrieveProxy(MediaProxy.NAME) as MediaProxy;
			_flashvars = (facade.retrieveProxy(ConfigProxy.NAME) as ConfigProxy).vo.flashvars;
			super.onRegister();
		}

		override public function listNotificationInterests():Array
		{
			return [
				NotificationType.MEDIA_READY,
				NotificationType.PLAYER_PLAYED
			];
		}

		override public function handleNotification(notification:INotification):void
		{
			switch (notification.getName())
			{
				case NotificationType.PLAYER_PLAYED:
					//workaround to display the bitrate that was automatically detected by akamai
					if (_flashvars.hdnetworkEnableBRDetection && _flashvars.hdnetworkEnableBRDetection=="true")
					{
						_mediaProxy.notifyStartingIndexChanged((facade.retrieveMediator(KMediaPlayerMediator.NAME) as KMediaPlayerMediator).player.currentDynamicStreamIndex);
					}
					break;

				case NotificationType.MEDIA_READY:
					//add akamai metadata on the stream resource

					//find last index of resource metadata flashvars.
					var i:int = 0;
					while (_flashvars.hasOwnProperty("objMetadataNamespace" + i) && _flashvars.hasOwnProperty("objMetadataValues" + i))
					{
						i++;
					}

					var bufferLength:int = DEFAULT_HD_BUFFER_LENGTH;
					if (_flashvars.hdnetworkBufferLength && _flashvars.hdnetworkBufferLength!="")
					{
						bufferLength = _flashvars.hdnetworkBufferLength;
					}

					//Then add akamai resource metadata on the next index
					_flashvars["objMetadataNamespace"+i] = AkamaiStrings.AKAMAI_ADVANCED_STREAMING_PLUGIN_METADATA_NAMESPACE;
					//set buffer length
					var akamaiMetadataValues:String = AkamaiStrings.AKAMAI_METADATA_KEY_MAX_BUFFER_LENGTH + "=" + bufferLength;

					if (_flashvars.hdnetworkEnableBRDetection && _flashvars.hdnetworkEnableBRDetection=="true")
					{
						//var bwEstimationObject:Object = new Object();
						//bwEstimationObject.enabled = true;
						var bandwidthEstimationPeriodInSeconds:int;
						if (_flashvars.hdnetworkBRDetectionTime && _flashvars.hdnetworkBRDetectionTime!="")
						{
							bandwidthEstimationPeriodInSeconds = _flashvars.hdnetworkBRDetectionTime;
						}
						else
						{
							bandwidthEstimationPeriodInSeconds = DEFAULT_HD_BANDWIDTH_CHECK_TIME;
						}
						//enable akamai BW detection
						akamaiMetadataValues += "&"+ AkamaiStrings.AKAMAI_METADATA_KEY_SET_BANDWIDTH_ESTIMATION_ENABLED + "={enabled:true,bandwidthEstimationPeriodInSeconds:"+bandwidthEstimationPeriodInSeconds+"}";
					}
					else
					{
						var preferedIndex:int = _mediaProxy.getFlavorByBitrate(_mediaProxy.vo.preferedFlavorBR);
						if (preferedIndex!=-1)
						{
							akamaiMetadataValues += "&" + AkamaiStrings.AKAMAI_METDATA_KEY_MBR_STARTING_INDEX + "=" + preferedIndex;
							_mediaProxy.notifyStartingIndexChanged(preferedIndex);
						}
					}

					_flashvars["objMetadataValues"+i] = akamaiMetadataValues;
					break;
			}
		}
	}
}

package com.kaltura.kdpfl.plugin
{
	import com.akamai.osmf.utils.AkamaiStrings;
	import com.kaltura.kdpfl.model.ConfigProxy;
	import com.kaltura.kdpfl.model.MediaProxy;
	import com.kaltura.kdpfl.model.type.NotificationType;
	import com.kaltura.kdpfl.view.media.KMediaPlayerMediator;

	import org.osmf.events.MediaElementEvent;
	import org.osmf.traits.DVRTrait;
	import org.osmf.traits.MediaTraitType;
	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.mediator.Mediator;

	public class akamaiHDMediator extends Mediator
	{

		public static const NAME:String = "akamaiHDMediator";
		/**
		 * default buffer length to be used when playing with HD Akamai plugin
		 */
		public static const DEFAULT_HD_BUFFER_LENGTH:int = 20;

		/**
		 * default bandwith check time in seconds
		 */
		public static const DEFAULT_HD_BANDWIDTH_CHECK_TIME:int = 2;

		private var _mediaProxy:MediaProxy;
		private var _flashvars:Object;

		public function akamaiHDMediator(viewComponent:Object=null)
		{
			super(NAME, viewComponent);
		}

		override public function onRegister():void
		{
			_mediaProxy = facade.retrieveProxy(MediaProxy.NAME) as MediaProxy;
			_flashvars = (facade.retrieveProxy(ConfigProxy.NAME) as ConfigProxy).vo.flashvars;
			super.onRegister();
		}

		override public function listNotificationInterests():Array
		{
			return [
				NotificationType.MEDIA_READY,
				NotificationType.PLAYER_PLAYED,
				NotificationType.MEDIA_ELEMENT_READY
			];
		}

		override public function handleNotification(notification:INotification):void
		{
			switch (notification.getName())
			{
				case NotificationType.PLAYER_PLAYED:
					//workaround to display the bitrate that was automatically detected by akamai
					if (_flashvars.hdnetworkEnableBRDetection && _flashvars.hdnetworkEnableBRDetection=="true")
					{
						_mediaProxy.notifyStartingIndexChanged((facade.retrieveMediator(KMediaPlayerMediator.NAME) as KMediaPlayerMediator).player.currentDynamicStreamIndex);
					}
					break;

				case NotificationType.MEDIA_READY:
					//add akamai metadata on the stream resource

					//find last index of resource metadata flashvars.
					var i:int = 0;
					while (_flashvars.hasOwnProperty("objMetadataNamespace" + i) && _flashvars.hasOwnProperty("objMetadataValues" + i))
					{
						i++;
					}

					var bufferLength:int = DEFAULT_HD_BUFFER_LENGTH;
					if (_flashvars.hdnetworkBufferLength && _flashvars.hdnetworkBufferLength!="")
					{
						bufferLength = _flashvars.hdnetworkBufferLength;
					}

					//Then add akamai resource metadata on the next index
					_flashvars["objMetadataNamespace"+i] = AkamaiStrings.AKAMAI_ADVANCED_STREAMING_PLUGIN_METADATA_NAMESPACE;
					//set buffer length
					var akamaiMetadataValues:String = AkamaiStrings.AKAMAI_METADATA_KEY_MAX_BUFFER_LENGTH + "=" + bufferLength;

					if (_flashvars.hdnetworkEnableBRDetection && _flashvars.hdnetworkEnableBRDetection=="true")
					{
						//var bwEstimationObject:Object = new Object();
						//bwEstimationObject.enabled = true;
						var bandwidthEstimationPeriodInSeconds:int;
						if (_flashvars.hdnetworkBRDetectionTime && _flashvars.hdnetworkBRDetectionTime!="")
						{
							bandwidthEstimationPeriodInSeconds = _flashvars.hdnetworkBRDetectionTime;
						}
						else
						{
							bandwidthEstimationPeriodInSeconds = DEFAULT_HD_BANDWIDTH_CHECK_TIME;
						}
						//enable akamai BW detection
						akamaiMetadataValues += "&"+ AkamaiStrings.AKAMAI_METADATA_KEY_SET_BANDWIDTH_ESTIMATION_ENABLED + "={enabled:true,bandwidthEstimationPeriodInSeconds:"+bandwidthEstimationPeriodInSeconds+"}";
					}
					else
					{
						var preferedIndex:int = _mediaProxy.getFlavorByBitrate(_mediaProxy.vo.preferedFlavorBR);
						if (preferedIndex!=-1)
						{
							akamaiMetadataValues += "&" + AkamaiStrings.AKAMAI_METDATA_KEY_MBR_STARTING_INDEX + "=" + preferedIndex;
							_mediaProxy.notifyStartingIndexChanged(preferedIndex);
						}
					}

					_flashvars["objMetadataValues"+i] = akamaiMetadataValues;
					break;

				case NotificationType.MEDIA_ELEMENT_READY:
					if (_mediaProxy.vo.isLive && _mediaProxy.vo.canSeek && _mediaProxy.vo.media)
					{
						_mediaProxy.vo.media.addEventListener(MediaElementEvent.TRAIT_ADD, onMediaTraitAdd);

					}
					break;
			}
		}

		/**
		 * sets DVR window size according to actual window size (including Akamai's padding)
		 * @param e
		 *
		 */
		private function onMediaTraitAdd(e: MediaElementEvent) :  void
		{
			if (e.traitType==MediaTraitType.DVR)
			{
				var dvrTrait:DVRTrait = _mediaProxy.vo.media.getTrait(MediaTraitType.DVR) as DVRTrait;
				(facade.retrieveMediator(KMediaPlayerMediator.NAME) as KMediaPlayerMediator).dvrWinSize = dvrTrait.windowDuration;
				_mediaProxy.vo.media.removeEventListener(MediaElementEvent.TRAIT_ADD, onMediaTraitAdd);
			}

		}

	}
}

fix livestream with dvr window size

fix livestream with dvr window size


/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics
{
    import com.google.analytics.core.Buffer;
    import com.google.analytics.core.EventTracker;
    import com.google.analytics.core.GIFRequest;
    import com.google.analytics.core.ServerOperationMode;
    import com.google.analytics.core.TrackerCache;
    import com.google.analytics.core.TrackerMode;
    import com.google.analytics.core.ga_internal;
    import com.google.analytics.debug.DebugConfiguration;
    import com.google.analytics.debug.Layout;
    import com.google.analytics.events.AnalyticsEvent;
    import com.google.analytics.external.AdSenseGlobals;
    import com.google.analytics.external.HTMLDOM;
    import com.google.analytics.external.JavascriptProxy;
    import com.google.analytics.utils.Environment;
    import com.google.analytics.utils.Version;
    import com.google.analytics.v4.Bridge;
    import com.google.analytics.v4.Configuration;
    import com.google.analytics.v4.GoogleAnalyticsAPI;
    import com.google.analytics.v4.Tracker;

    import flash.display.DisplayObject;
    import flash.events.Event;
    import flash.events.EventDispatcher;

    /* force import for type in the includes */
    EventTracker;
    ServerOperationMode;

    /**
     * Dispatched after the factory has built the tracker object.
     * @eventType com.google.analytics.events.AnalyticsEvent.READY
     */
    [Event(name="ready", type="com.google.analytics.events.AnalyticsEvent")]

    /**
     * Google Analytic Tracker Code (GATC)'s code-only component.
     */
    public class GATracker implements AnalyticsTracker
    {
        private var _ready:Boolean = false;

        private var _display:DisplayObject;
        private var _eventDispatcher:EventDispatcher;
        private var _tracker:GoogleAnalyticsAPI;

        //factory
        private var _config:Configuration;
        private var _debug:DebugConfiguration;
        private var _env:Environment;
        private var _buffer:Buffer;
        private var _gifRequest:GIFRequest;
        private var _jsproxy:JavascriptProxy;
        private var _dom:HTMLDOM;
        private var _adSense:AdSenseGlobals;

        //object properties
        private var _account:String;
        private var _mode:String;
        private var _visualDebug:Boolean;

        /**
         * Indicates if the tracker is automatically build.
         */
        public static var autobuild:Boolean = true;

        /**
         * The version of the tracker.
         */
        public static var version:Version = API.version;

        /**
         * Creates a new GATracker instance.
         *
Note: the GATracker need to be instancied and added to the Stage or at least
         * being placed in a display list.

         */
        public function GATracker( display:DisplayObject, account:String,
                                   mode:String = "AS3", visualDebug:Boolean = false,
                                   config:Configuration = null, debug:DebugConfiguration = null )
        {
            _display = display;
            _eventDispatcher = new EventDispatcher( this ) ;
            _tracker = new TrackerCache();

            this.account     = account;
            this.mode        = mode;
            this.visualDebug = visualDebug;

            if( !debug )
            {
                this.debug = new DebugConfiguration();
            }

            if( !config )
            {
                this.config = new Configuration( debug );
            }

            if( autobuild )
            {
                _factory();
            }
        }

        /**
         * @private
         * Factory to build the different trackers
         */
        private function _factory():void
        {
            _jsproxy = new JavascriptProxy( debug );

            if( visualDebug )
            {
                debug.layout = new Layout( debug, _display );
                debug.active = visualDebug;
            }

            var activeTracker:GoogleAnalyticsAPI;
            var cache:TrackerCache = _tracker as TrackerCache;

            switch( mode )
            {
                case TrackerMode.BRIDGE :
                {
                    activeTracker = _bridgeFactory();
                    break;
                }

                case TrackerMode.AS3 :
                default:
                {
                    activeTracker = _trackerFactory();
                }
            }

            if( !cache.isEmpty() )
            {
                cache.tracker = activeTracker;
                cache.flush();
            }

            _tracker = activeTracker;

            _ready = true;
            dispatchEvent( new AnalyticsEvent( AnalyticsEvent.READY, this ) );
        }

        /**
        * @private
        * Factory method for returning a Tracker object.
        *
        * @return {GoogleAnalyticsAPI}
        */
        private function _trackerFactory():GoogleAnalyticsAPI
        {
            debug.info( "GATracker (AS3) v" + version +"\naccount: " + account );

            /* note:
               for unit testing and to avoid 2 different branches AIR/Flash
               here we will detect if we are in the Flash Player or AIR
               and pass the infos to the LocalInfo

               By default we will define "Flash" for our local tests
            */

            _adSense   = new AdSenseGlobals( debug );

            _dom        = new HTMLDOM( debug );
            _dom.cacheProperties();

            _env        = new Environment( "", "", "", debug, _dom );

            _buffer     = null;
            _gifRequest = null;

            /* note:
               To be able to obtain the URL of the main SWF containing the GA API
               we need to be able to access the stage property of a DisplayObject,
               here we open the internal namespace to be able to set that reference
               at instanciation-time.

               We keep the implementation internal to be able to change it if required later.
            */
            use namespace ga_internal;
            _env.url = _display.stage.loaderInfo.url;

            return new Tracker( account, config, debug, _env, _buffer, _gifRequest, _adSense, _display );
        }

        /**
        * @private
        * Factory method for returning a Bridge object.
        *
        * @return {GoogleAnalyticsAPI}
        */
        private function _bridgeFactory():GoogleAnalyticsAPI
        {
            debug.info( "GATracker (Bridge) v" + version +"\naccount: " + account );
            return new Bridge( account, _debug, _jsproxy );
        }

        /**
         * Indicates the account value of the tracking.
         */
        public function get account():String
        {
            return _account;
        }

        /**
         * @private
         */
        public function set account( value:String ):void
        {
            _account = value;
        }

        /**
         * Determinates the Configuration object of the tracker.
         */
        public function get config():Configuration
        {
            return _config;
        }

        /**
         * @private
         */
        public function set config( value:Configuration ):void
        {
            _config = value;
        }

        /**
         * Determinates the DebugConfiguration of the tracker.
         */
        public function get debug():DebugConfiguration
        {
            return _debug;
        }

        /**
         * @private
         */
        public function set debug( value:DebugConfiguration ):void
        {
            _debug = value;
        }

        /**
         * Indicates if the tracker is ready to use.
         */
        public function isReady():Boolean
        {
            return _ready;
        }

        /**
         * Indicates the mode of the tracking "AS3" or "Bridge".
         */
        public function get mode():String
        {
            return _mode;
        }

        /**
         * @private
         */
        public function set mode( value:String ):void
        {
            _mode = value ;
        }

        /**
         * Indicates if the tracker use a visual debug.
         */
        public function get visualDebug():Boolean
        {
            return _visualDebug;
        }

        /**
         * @private
         */
        public function set visualDebug( value:Boolean ):void
        {
            _visualDebug = value;
        }

        /**
         * Builds the tracker.
         */
        public function build():void
        {
            if( !isReady() )
            {
                _factory();
            }
        }

        // IEventDispatcher implementation

        /**
         * Allows the registration of event listeners on the event target.
         * @param type A string representing the event type to listen for. If eventName value is "ALL" addEventListener use addGlobalListener
         * @param listener The Function that receives a notification when an event of the specified type occurs.
         * @param useCapture Determinates if the event flow use capture or not.
         * @param priority Determines the priority level of the event listener.
         * @param useWeakReference Indicates if the listener is a weak reference.
         */
        public function addEventListener( type:String, listener:Function, useCapture:Boolean = false, priority:int = 0,
                                          useWeakReference:Boolean = false):void
        {
            _eventDispatcher.addEventListener( type, listener, useCapture, priority, useWeakReference );
        }

        /**
         * Dispatches an event into the event flow.
         * @param event The Event object that is dispatched into the event flow.
         * @return true if the Event is dispatched.
         */
        public function dispatchEvent( event:Event ):Boolean
        {
            return _eventDispatcher.dispatchEvent( event );
        }

        /**
         * Checks whether the EventDispatcher object has any listeners registered for a specific type of event.
         * This allows you to determine where altered handling of an event type has been introduced in the event flow heirarchy by an EventDispatcher object.
         */
        public function hasEventListener( type:String ):Boolean
        {
            return _eventDispatcher.hasEventListener( type );
        }

        /**
         * Removes a listener from the EventDispatcher object.
         * If there is no matching listener registered with the EventDispatcher object, then calling this method has no effect.
         * @param type Specifies the type of event.
         * @param listener The Function that receives a notification when an event of the specified type occurs.
         * @param useCapture Determinates if the event flow use capture or not.
         */
        public function removeEventListener( type:String, listener:Function, useCapture:Boolean = false ):void
        {
            _eventDispatcher.removeEventListener( type, listener, useCapture );
        }

        /**
         * Checks whether an event listener is registered with this EventDispatcher object or any of its ancestors for the specified event type.
         * This method returns true if an event listener is triggered during any phase of the event flow when an event of the specified type is dispatched to this EventDispatcher object or any of its descendants.
         * @return A value of true if a listener of the specified type will be triggered; false otherwise.
         */
        public function willTrigger( type:String ):Boolean
        {
            return _eventDispatcher.willTrigger( type );
        }

        include "common.txt"

    }
}

Fix - eat blank lines

Fix - eat blank lines


package dolly {

import dolly.core.dolly_internal;
import dolly.core.errors.CloningError;
import dolly.core.metadata.MetadataName;
import dolly.utils.PropertyUtil;

import org.as3commons.reflect.Accessor;
import org.as3commons.reflect.AccessorAccess;
import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;

use namespace dolly_internal;

public class Cloner {

	private static function isTypeCloneable(type:Type):Boolean {
		return type.hasMetadata(MetadataName.CLONEABLE);
	}

	private static function failIfTypeIsNotCloneable(type:Type):void {
		if (!isTypeCloneable(type)) {
			throw new CloningError(
					CloningError.CLASS_IS_NOT_CLONEABLE_MESSAGE,
					CloningError.CLASS_IS_NOT_CLONEABLE_CODE
			);
		}
	}

	dolly_internal static function findAllWritableFieldsForType(type:Type):Vector.<Field> {
		failIfTypeIsNotCloneable(type);

		const result:Vector.<Field> = new Vector.<Field>();

		for each(var field:Field in type.properties) {
			if (!(field is Accessor) || (field as Accessor).access == AccessorAccess.READ_WRITE) {
				result.push(field);
			}
		}

		return result;
	}

	dolly_internal static function doClone(source:*, deep:int, type:Type = null):* {
		const fieldsToClone:Vector.<Field> = findAllWritableFieldsForType(type);
		const clonedInstance:* = new (type.clazz)();

		for each(var field:Field in fieldsToClone) {
			PropertyUtil.cloneProperty(source, clonedInstance, field.name);
		}

		return clonedInstance;
	}

	public static function clone(source:*):* {
		const type:Type = Type.forInstance(source);

		failIfTypeIsNotCloneable(type);

		const deep:int = 2;

		return doClone(source, deep, type);
	}
}
}

package dolly {

import dolly.core.dolly_internal;
import dolly.core.errors.CloningError;
import dolly.core.metadata.MetadataName;
import dolly.utils.PropertyUtil;

import org.as3commons.reflect.Accessor;
import org.as3commons.reflect.AccessorAccess;
import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;

use namespace dolly_internal;

public class Cloner {

	private static function isTypeCloneable(type:Type):Boolean {
		return type.hasMetadata(MetadataName.CLONEABLE);
	}

	private static function failIfTypeIsNotCloneable(type:Type):void {
		if (!isTypeCloneable(type)) {
			throw new CloningError(
					CloningError.CLASS_IS_NOT_CLONEABLE_MESSAGE,
					CloningError.CLASS_IS_NOT_CLONEABLE_CODE
			);
		}
	}

	dolly_internal static function findAllWritableFieldsForType(type:Type):Vector.<Field> {
		failIfTypeIsNotCloneable(type);

		const result:Vector.<Field> = new Vector.<Field>();

		for each(var field:Field in type.properties) {
			if (!(field is Accessor) || (field as Accessor).access == AccessorAccess.READ_WRITE) {
				result.push(field);
			}
		}

		return result;
	}

	dolly_internal static function doClone(source:*, deep:int, type:Type = null):* {
		if(!type) {
			type = Type.forInstance(source);
		}

		const fieldsToClone:Vector.<Field> = findAllWritableFieldsForType(type);
		const clonedInstance:* = new (type.clazz)();

		for each(var field:Field in fieldsToClone) {
			PropertyUtil.cloneProperty(source, clonedInstance, field.name);
		}

		return clonedInstance;
	}

	public static function clone(source:*):* {
		const type:Type = Type.forInstance(source);

		failIfTypeIsNotCloneable(type);

		const deep:int = 2;

		return doClone(source, deep, type);
	}
}
}

Initialize "type" parameter in Cloner.doClone() method.


package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.scene.controller.mesh.VisibilityController;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.math.Ray;

	use namespace minko_scene;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractSceneNode
	{
		public static const DEFAULT_MATERIAL	: Material	= new BasicMaterial();

		private var _geometry			: Geometry;
		private var _properties			: DataProvider;
		private var _material			: Material;
		private var _bindings			: DataBindings;

		private var _visibility			: VisibilityController;

		private var _frame				: uint;

		private var _cloned				: Signal;
		private var _materialChanged	: Signal;
		private var _frameChanged		: Signal;
		private var _geometryChanged	: Signal;

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : Material
		{
			return _material;
		}
		public function set material(value : Material) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				_material = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			if (_geometry != value)
			{
				var oldGeometry	: Geometry = _geometry;

				if (oldGeometry)
					oldGeometry.changed.remove(geometryChangedHandler);

				_geometry = value;

				if (value)
					_geometry.changed.add(geometryChangedHandler);

				_geometryChanged.execute(this, oldGeometry, value);
			}
		}

		/**
		 * Whether the mesh is visible or not.
		 *
		 * @return
		 *
		 */
		public function get visible() : Boolean
		{
			return _visibility.visible;
		}
		public function set visible(value : Boolean) : void
		{
			_visibility.visible = value;
		}

		public function get frustumCulling() : uint
		{
			return _visibility.frustumCulling;
		}
		public function set frustumCulling(value : uint) : void
		{
			_visibility.frustumCulling = value;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get materialChanged() : Signal
		{
			return _materialChanged;
		}

		public function get frameChanged() : Signal
		{
			return _frameChanged;
		}

		public function get geometryChanged() : Signal
		{
			return _geometryChanged;
		}

		public function get frame() : uint
		{
			return _frame;
		}
		public function set frame(value : uint) : void
		{
			if (_frame != value)
			{
				var oldFrame : uint = _frame;

				_frame = value;
				_frameChanged.execute(this, oldFrame, value);
			}
		}

		public function Mesh(geometry	: Geometry	= null,
							 material	: Material	= null,
							 name		: String	= null)
		{
			super();

			initialize(geometry, material, name);
		}

		private function initialize(geometry	: Geometry,
									material	: Material,
									name		: String) : void
		{
			if (name)
				this.name = name;

			_cloned = new Signal('Mesh.clones');
			_materialChanged = new Signal('Mesh.materialChanged');
			_frameChanged = new Signal('Mesh.frameChanged');
			_geometryChanged = new Signal('Mesh.geometryChanged');

			_bindings = new DataBindings(this);
			this.properties = new DataProvider(properties, 'meshProperties', DataProviderUsage.EXCLUSIVE);

			this.geometry = geometry;
			this.material = material || DEFAULT_MATERIAL;

			_visibility = new VisibilityController();
//			_visibility.frustumCulling = FrustumCulling.BOX ^ FrustumCulling.TOP_BOX;
			addController(_visibility);
		}

		public function cast(ray : Ray, maxDistance : Number = Number.POSITIVE_INFINITY) : Number
		{
			return _geometry.boundingBox.testRay(
				ray,
				worldToLocal,
				maxDistance
			);
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var clone : Mesh = new Mesh();

			clone.name 		= name;
			clone.geometry 	= _geometry;

			clone.properties = DataProvider(_properties.clone());
			clone._bindings.copySharedProvidersFrom(_bindings);

			clone.transform.copyFrom(transform);
			clone.material = _material;

			this.cloned.execute(this, clone);

			return clone;
		}

		override protected function addedToSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.addedToSceneHandler(child, scene);

			if (child === this)
				_bindings.addProvider(transformData);
		}

		override protected function removedFromSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.removedFromSceneHandler(child, scene);

			if (child === this)
				_bindings.removeProvider(transformData);
		}

		private function geometryChangedHandler(geometry : Geometry) : void
		{
			_geometryChanged.execute(this, _geometry, _geometry);
		}
	}
}

package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.scene.controller.mesh.VisibilityController;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.math.Ray;

	use namespace minko_scene;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractSceneNode
	{
		public static const DEFAULT_MATERIAL	: Material	= new BasicMaterial();

		private var _geometry			: Geometry;
		private var _properties			: DataProvider;
		private var _material			: Material;
		private var _bindings			: DataBindings;

		private var _visibility			: VisibilityController;

		private var _frame				: uint;

		private var _cloned				: Signal;
		private var _materialChanged	: Signal;
		private var _frameChanged		: Signal;
		private var _geometryChanged	: Signal;

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : Material
		{
			return _material;
		}
		public function set material(value : Material) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				var oldMaterial : Material = _material;

				_material = value;

				if (value)
					_bindings.addProvider(value);

				_materialChanged.execute(this, oldMaterial, value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			if (_geometry != value)
			{
				var oldGeometry	: Geometry = _geometry;

				if (oldGeometry)
					oldGeometry.changed.remove(geometryChangedHandler);

				_geometry = value;

				if (value)
					_geometry.changed.add(geometryChangedHandler);

				_geometryChanged.execute(this, oldGeometry, value);
			}
		}

		/**
		 * Whether the mesh is visible or not.
		 *
		 * @return
		 *
		 */
		public function get visible() : Boolean
		{
			return _visibility.visible;
		}
		public function set visible(value : Boolean) : void
		{
			_visibility.visible = value;
		}

		public function get frustumCulling() : uint
		{
			return _visibility.frustumCulling;
		}
		public function set frustumCulling(value : uint) : void
		{
			_visibility.frustumCulling = value;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get materialChanged() : Signal
		{
			return _materialChanged;
		}

		public function get frameChanged() : Signal
		{
			return _frameChanged;
		}

		public function get geometryChanged() : Signal
		{
			return _geometryChanged;
		}

		public function get frame() : uint
		{
			return _frame;
		}
		public function set frame(value : uint) : void
		{
			if (_frame != value)
			{
				var oldFrame : uint = _frame;

				_frame = value;
				_frameChanged.execute(this, oldFrame, value);
			}
		}

		public function Mesh(geometry	: Geometry	= null,
							 material	: Material	= null,
							 name		: String	= null)
		{
			super();

			initialize(geometry, material, name);
		}

		private function initialize(geometry	: Geometry,
									material	: Material,
									name		: String) : void
		{
			if (name)
				this.name = name;

			_cloned = new Signal('Mesh.clones');
			_materialChanged = new Signal('Mesh.materialChanged');
			_frameChanged = new Signal('Mesh.frameChanged');
			_geometryChanged = new Signal('Mesh.geometryChanged');

			_bindings = new DataBindings(this);
			this.properties = new DataProvider(properties, 'meshProperties', DataProviderUsage.EXCLUSIVE);

			this.geometry = geometry;
			this.material = material || DEFAULT_MATERIAL;

			_visibility = new VisibilityController();
//			_visibility.frustumCulling = FrustumCulling.BOX ^ FrustumCulling.TOP_BOX;
			addController(_visibility);
		}

		public function cast(ray : Ray, maxDistance : Number = Number.POSITIVE_INFINITY) : Number
		{
			return _geometry.boundingBox.testRay(
				ray,
				worldToLocal,
				maxDistance
			);
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var clone : Mesh = new Mesh();

			clone.name 		= name;
			clone.geometry 	= _geometry;

			clone.properties = DataProvider(_properties.clone());
			clone._bindings.copySharedProvidersFrom(_bindings);

			clone.transform.copyFrom(transform);
			clone.material = _material;

			this.cloned.execute(this, clone);

			return clone;
		}

		override protected function addedToSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.addedToSceneHandler(child, scene);

			if (child === this)
				_bindings.addProvider(transformData);
		}

		override protected function removedFromSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.removedFromSceneHandler(child, scene);

			if (child === this)
				_bindings.removeProvider(transformData);
		}

		private function geometryChangedHandler(geometry : Geometry) : void
		{
			_geometryChanged.execute(this, _geometry, _geometry);
		}
	}
}

fix Mesh.materialChanged signal never executed