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

	import org.apache.flex.core.IBead;
	import org.apache.flex.core.ISelectionModel;
	import org.apache.flex.core.IStrand;
	import org.apache.flex.html.staticControls.beads.IDropDownListBead;
	import org.apache.flex.events.Event;
	import org.apache.flex.events.IEventDispatcher;

	public class DropDownListController implements IBead
	{
		public function DropDownListController()
		{
		}

		private var _strand:IStrand;

		public function set strand(value:IStrand):void
		{
			_strand = value;
            IEventDispatcher(value).addEventListener(MouseEvent.CLICK, clickHandler);
		}

        private function clickHandler(event:Event):void
        {
            var viewBead:IDropDownListBead = _strand.getBeadByType(IDropDownListBead) as IDropDownListBead;
            viewBead.popUpVisible = true;
            var selectionModel:ISelectionModel = _strand.getBeadByType(ISelectionModel) as ISelectionModel;
            var popUpModel:ISelectionModel = viewBead.popUp.getBeadByType(ISelectionModel) as ISelectionModel;
            popUpModel.dataProvider = selectionModel.dataProvider;
            popUpModel.selectedIndex = selectionModel.selectedIndex;
			DisplayObject(viewBead.popUp).width = DisplayObject(_strand).width;
			DisplayObject(viewBead.popUp).height = 200;
			DisplayObject(viewBead.popUp).x = DisplayObject(_strand).x;
			DisplayObject(viewBead.popUp).y = DisplayObject(_strand).y;
            IEventDispatcher(viewBead.popUp).addEventListener("change", changeHandler);
        }

        private function changeHandler(event:Event):void
        {
            var viewBead:IDropDownListBead = _strand.getBeadByType(IDropDownListBead) as IDropDownListBead;
            viewBead.popUpVisible = false;
            var selectionModel:ISelectionModel = _strand.getBeadByType(ISelectionModel) as ISelectionModel;
            var popUpModel:ISelectionModel = viewBead.popUp.getBeadByType(ISelectionModel) as ISelectionModel;
            selectionModel.selectedIndex = popUpModel.selectedIndex;
			IEventDispatcher(_strand).dispatchEvent(new Event("change"));
        }

	}
}

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

	import org.apache.flex.core.IBead;
	import org.apache.flex.core.ISelectionModel;
	import org.apache.flex.core.IStrand;
	import org.apache.flex.html.staticControls.beads.IDropDownListBead;
	import org.apache.flex.events.Event;
	import org.apache.flex.events.IEventDispatcher;

	public class DropDownListController implements IBead
	{
		public function DropDownListController()
		{
		}

		private var _strand:IStrand;

		public function set strand(value:IStrand):void
		{
			_strand = value;
            IEventDispatcher(value).addEventListener(MouseEvent.CLICK, clickHandler);
		}

        private function clickHandler(event:MouseEvent):void
        {
            var viewBead:IDropDownListBead = _strand.getBeadByType(IDropDownListBead) as IDropDownListBead;
            viewBead.popUpVisible = true;
            var selectionModel:ISelectionModel = _strand.getBeadByType(ISelectionModel) as ISelectionModel;
            var popUpModel:ISelectionModel = viewBead.popUp.getBeadByType(ISelectionModel) as ISelectionModel;
            popUpModel.dataProvider = selectionModel.dataProvider;
            popUpModel.selectedIndex = selectionModel.selectedIndex;
			DisplayObject(viewBead.popUp).width = DisplayObject(_strand).width;
			DisplayObject(viewBead.popUp).height = 200;
			DisplayObject(viewBead.popUp).x = DisplayObject(_strand).x;
			DisplayObject(viewBead.popUp).y = DisplayObject(_strand).y;
            IEventDispatcher(viewBead.popUp).addEventListener("change", changeHandler);
        }

        private function changeHandler(event:Event):void
        {
            var viewBead:IDropDownListBead = _strand.getBeadByType(IDropDownListBead) as IDropDownListBead;
            viewBead.popUpVisible = false;
            var selectionModel:ISelectionModel = _strand.getBeadByType(ISelectionModel) as ISelectionModel;
            var popUpModel:ISelectionModel = viewBead.popUp.getBeadByType(ISelectionModel) as ISelectionModel;
            selectionModel.selectedIndex = popUpModel.selectedIndex;
			IEventDispatcher(_strand).dispatchEvent(new Event("change"));
        }

	}
}

fix type error

fix type error


package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.text.TextField;
    import flash.net.Socket;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.utils.ByteArray;
    import flash.utils.setTimeout;

    public class swfcat extends Sprite
    {
        /* David's bridge (nickname eRYaZuvY02FpExln) that also serves a
           crossdomain policy. */
        private const DEFAULT_TOR_ADDR:Object = {
            // host: "173.255.221.44", 3VXRyxz67OeRoqHn
            host: "69.164.193.231",
            port: 9001
        };
        private const DEFAULT_FACILITATOR_ADDR:Object = {
            host: "173.255.221.44",
            port: 9002
        };

        // Milliseconds.
        private const FACILITATOR_POLL_INTERVAL:int = 10000;

        // Socket to facilitator.
        private var s_f:Socket;

        private var output_text:TextField;

        private var fac_addr:Object;

        [Embed(source="badge.png")]
        private var BadgeImage:Class;

        public function puts(s:String):void
        {
            output_text.appendText(s + "\n");
            output_text.scrollV = output_text.maxScrollV;
        }

        public function swfcat()
        {
            // Absolute positioning.
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            output_text = new TextField();
            output_text.width = stage.stageWidth;
            output_text.height = stage.stageHeight;
            output_text.background = true;
            output_text.backgroundColor = 0x001f0f;
            output_text.textColor = 0x44cc44;

            puts("Starting.");
            // Wait until the query string parameters are loaded.
            this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
        }

        private function loaderinfo_complete(e:Event):void
        {
            var fac_spec:String;

            puts("Parameters loaded.");

            if (this.loaderInfo.parameters["debug"])
                addChild(output_text);
            else
                addChild(new BadgeImage());

            fac_spec = this.loaderInfo.parameters["facilitator"];
            if (fac_spec) {
                puts("Facilitator spec: \"" + fac_spec + "\"");
                fac_addr = parse_addr_spec(fac_spec);
                if (!fac_addr) {
                    puts("Error: Facilitator spec must be in the form \"host:port\".");
                    return;
                }
            } else {
                fac_addr = DEFAULT_FACILITATOR_ADDR;
            }

            main();
        }

        /* The main logic begins here, after start-up issues are taken care of. */
        private function main():void
        {
            s_f = new Socket();

            s_f.addEventListener(Event.CONNECT, fac_connected);
            s_f.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("Facilitator: closed connection.");
                setTimeout(main, FACILITATOR_POLL_INTERVAL);
            });
            s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
            });
            s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
            });

            puts("Facilitator: connecting to " + fac_addr.host + ":" + fac_addr.port + ".");
            s_f.connect(fac_addr.host, fac_addr.port);
        }

        private function fac_connected(e:Event):void
        {
            puts("Facilitator: connected.");

            s_f.addEventListener(ProgressEvent.SOCKET_DATA, fac_data);

            s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
        }

        private function fac_data(e:ProgressEvent):void
        {
            var client_spec:String;
            var client_addr:Object;
            var proxy_pair:Object;

            client_spec = s_f.readMultiByte(e.bytesLoaded, "utf-8");
            puts("Facilitator: got \"" + client_spec + "\".");

            client_addr = parse_addr_spec(client_spec);
            if (!client_addr) {
                puts("Error: Client spec must be in the form \"host:port\".");
                return;
            }
            if (client_addr.host == "0.0.0.0" && client_addr.port == 0) {
                puts("Error: Facilitator has no clients.");
                return;
            }

            proxy_pair = new ProxyPair(this, client_addr, DEFAULT_TOR_ADDR);
            proxy_pair.connect();
        }

        /* Parse an address in the form "host:port". Returns an Object with
           keys "host" (String) and "port" (int). Returns null on error. */
        private static function parse_addr_spec(spec:String):Object
        {
            var parts:Array;
            var addr:Object;

            parts = spec.split(":", 2);
            if (parts.length != 2 || !parseInt(parts[1]))
                return null;
            addr = {}
            addr.host = parts[0];
            addr.port = parseInt(parts[1]);

            return addr;
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.Socket;
import flash.utils.ByteArray;

/* An instance of a client-relay connection. */
class ProxyPair
{
    // Address ({host, port}) of client.
    private var addr_c:Object;
    // Address ({host, port}) of relay.
    private var addr_r:Object;

    // Socket to client.
    private var s_c:Socket;
    // Socket to relay.
    private var s_r:Socket;

    // Parent swfcat, for UI updates.
    private var ui:swfcat;

    private function log(msg:String):void
    {
        ui.puts(id() + ": " + msg)
    }

    // String describing this pair for output.
    private function id():String
    {
        return "<" + this.addr_c.host + ":" + this.addr_c.port +
            "," + this.addr_r.host + ":" + this.addr_r.port + ">";
    }

    public function ProxyPair(ui:swfcat, addr_c:Object, addr_r:Object)
    {
        this.ui = ui;
        this.addr_c = addr_c;
        this.addr_r = addr_r;
    }

    public function connect():void
    {
        s_r = new Socket();

        s_r.addEventListener(Event.CONNECT, tor_connected);
        s_r.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Tor: closed.");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Tor: I/O error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Tor: security error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });

        log("Tor: connecting to " + addr_r.host + ":" + addr_r.port + ".");
        s_r.connect(addr_r.host, addr_r.port);
    }

    private function tor_connected(e:Event):void
    {
        log("Tor: connected.");

        s_c = new Socket();

        s_c.addEventListener(Event.CONNECT, client_connected);
        s_c.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Client: closed.");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Client: I/O error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Client: security error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });

        log("Client: connecting to " + addr_c.host + ":" + addr_c.port + ".");
        s_c.connect(addr_c.host, addr_c.port);
    }

    private function client_connected(e:Event):void
    {
        log("Client: connected.");

        s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_r.readBytes(bytes, 0, e.bytesLoaded);
            log("Tor: read " + bytes.length + ".");
            s_c.writeBytes(bytes);
        });
        s_c.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_c.readBytes(bytes, 0, e.bytesLoaded);
            log("Client: read " + bytes.length + ".");
            s_r.writeBytes(bytes);
        });
    }
}

package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.text.TextField;
    import flash.net.Socket;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.utils.ByteArray;
    import flash.utils.setTimeout;

    public class swfcat extends Sprite
    {
        /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
           crossdomain policy. */
        private const DEFAULT_TOR_ADDR:Object = {
            host: "173.255.221.44",
            port: 9001
        };
        private const DEFAULT_FACILITATOR_ADDR:Object = {
            host: "173.255.221.44",
            port: 9002
        };

        // Milliseconds.
        private const FACILITATOR_POLL_INTERVAL:int = 10000;

        // Socket to facilitator.
        private var s_f:Socket;

        private var output_text:TextField;

        private var fac_addr:Object;

        [Embed(source="badge.png")]
        private var BadgeImage:Class;

        public function puts(s:String):void
        {
            output_text.appendText(s + "\n");
            output_text.scrollV = output_text.maxScrollV;
        }

        public function swfcat()
        {
            // Absolute positioning.
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            output_text = new TextField();
            output_text.width = stage.stageWidth;
            output_text.height = stage.stageHeight;
            output_text.background = true;
            output_text.backgroundColor = 0x001f0f;
            output_text.textColor = 0x44cc44;

            puts("Starting.");
            // Wait until the query string parameters are loaded.
            this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
        }

        private function loaderinfo_complete(e:Event):void
        {
            var fac_spec:String;

            puts("Parameters loaded.");

            if (this.loaderInfo.parameters["debug"])
                addChild(output_text);
            else
                addChild(new BadgeImage());

            fac_spec = this.loaderInfo.parameters["facilitator"];
            if (fac_spec) {
                puts("Facilitator spec: \"" + fac_spec + "\"");
                fac_addr = parse_addr_spec(fac_spec);
                if (!fac_addr) {
                    puts("Error: Facilitator spec must be in the form \"host:port\".");
                    return;
                }
            } else {
                fac_addr = DEFAULT_FACILITATOR_ADDR;
            }

            main();
        }

        /* The main logic begins here, after start-up issues are taken care of. */
        private function main():void
        {
            s_f = new Socket();

            s_f.addEventListener(Event.CONNECT, fac_connected);
            s_f.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("Facilitator: closed connection.");
                setTimeout(main, FACILITATOR_POLL_INTERVAL);
            });
            s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
            });
            s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
            });

            puts("Facilitator: connecting to " + fac_addr.host + ":" + fac_addr.port + ".");
            s_f.connect(fac_addr.host, fac_addr.port);
        }

        private function fac_connected(e:Event):void
        {
            puts("Facilitator: connected.");

            s_f.addEventListener(ProgressEvent.SOCKET_DATA, fac_data);

            s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
        }

        private function fac_data(e:ProgressEvent):void
        {
            var client_spec:String;
            var client_addr:Object;
            var proxy_pair:Object;

            client_spec = s_f.readMultiByte(e.bytesLoaded, "utf-8");
            puts("Facilitator: got \"" + client_spec + "\".");

            client_addr = parse_addr_spec(client_spec);
            if (!client_addr) {
                puts("Error: Client spec must be in the form \"host:port\".");
                return;
            }
            if (client_addr.host == "0.0.0.0" && client_addr.port == 0) {
                puts("Error: Facilitator has no clients.");
                return;
            }

            proxy_pair = new ProxyPair(this, client_addr, DEFAULT_TOR_ADDR);
            proxy_pair.connect();
        }

        /* Parse an address in the form "host:port". Returns an Object with
           keys "host" (String) and "port" (int). Returns null on error. */
        private static function parse_addr_spec(spec:String):Object
        {
            var parts:Array;
            var addr:Object;

            parts = spec.split(":", 2);
            if (parts.length != 2 || !parseInt(parts[1]))
                return null;
            addr = {}
            addr.host = parts[0];
            addr.port = parseInt(parts[1]);

            return addr;
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.Socket;
import flash.utils.ByteArray;

/* An instance of a client-relay connection. */
class ProxyPair
{
    // Address ({host, port}) of client.
    private var addr_c:Object;
    // Address ({host, port}) of relay.
    private var addr_r:Object;

    // Socket to client.
    private var s_c:Socket;
    // Socket to relay.
    private var s_r:Socket;

    // Parent swfcat, for UI updates.
    private var ui:swfcat;

    private function log(msg:String):void
    {
        ui.puts(id() + ": " + msg)
    }

    // String describing this pair for output.
    private function id():String
    {
        return "<" + this.addr_c.host + ":" + this.addr_c.port +
            "," + this.addr_r.host + ":" + this.addr_r.port + ">";
    }

    public function ProxyPair(ui:swfcat, addr_c:Object, addr_r:Object)
    {
        this.ui = ui;
        this.addr_c = addr_c;
        this.addr_r = addr_r;
    }

    public function connect():void
    {
        s_r = new Socket();

        s_r.addEventListener(Event.CONNECT, tor_connected);
        s_r.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Tor: closed.");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Tor: I/O error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Tor: security error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });

        log("Tor: connecting to " + addr_r.host + ":" + addr_r.port + ".");
        s_r.connect(addr_r.host, addr_r.port);
    }

    private function tor_connected(e:Event):void
    {
        log("Tor: connected.");

        s_c = new Socket();

        s_c.addEventListener(Event.CONNECT, client_connected);
        s_c.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Client: closed.");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Client: I/O error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Client: security error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });

        log("Client: connecting to " + addr_c.host + ":" + addr_c.port + ".");
        s_c.connect(addr_c.host, addr_c.port);
    }

    private function client_connected(e:Event):void
    {
        log("Client: connected.");

        s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_r.readBytes(bytes, 0, e.bytesLoaded);
            log("Tor: read " + bytes.length + ".");
            s_c.writeBytes(bytes);
        });
        s_c.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_c.readBytes(bytes, 0, e.bytesLoaded);
            log("Client: read " + bytes.length + ".");
            s_r.writeBytes(bytes);
        });
    }
}

Change back to my relay, not an alternative bridge, now that hibernation is turned off on the relay.


/*
 * 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.utils
{
    import com.google.analytics.core.ga_internal;
    import com.google.analytics.debug.DebugConfiguration;
    import com.google.analytics.external.HTMLDOM;

    import core.strings.userAgent;
    import core.uri;

    import flash.system.Capabilities;
    import flash.system.Security;
    import flash.system.System;

    /**
     * Environment provides informations for the local environment.
     */
    public class Environment
    {
        private var _debug:DebugConfiguration;
        private var _dom:HTMLDOM;

        private var _protocol:String;
        private var _appName:String;
        private var _appVersion:Version;
        private var _userAgent:String;
        private var _url:String;

        /**
         * Creates a new Environment instance.
         * @param url The URL of the SWF.
         * @param app The application name
         * @param version The application version
         * @param dom the HTMLDOM reference.
         */
        public function Environment( url:String = "", app:String = "", version:String = "",
                                     debug:DebugConfiguration = null, dom:HTMLDOM = null )
        {
            var v:Version;

            if( app == "" )
            {
                if( isAIR() )
                {
                    app = "AIR";
                }
                else
                {
                    app = "Flash";
                }
            }

            if( version == "" )
            {
                v = flashVersion;
            }
            else
            {
                v = Version.fromString( version );
            }

            _url        = url;
            _appName    = app;
            _appVersion = v;

            _debug      = debug;
            _dom        = dom;
        }

        /**
         * @private
         */
        private function _findProtocol():void
        {
            _protocol = "";

            if( _url != "" )
            {
                var url:uri = new uri( _url );
                _protocol = url.scheme;
            }
        }

        /**
         * Indicates the name of the application.
         */
        public function get appName():String
        {
            return _appName;
        }

        /**
         * @private
         */
        public function set appName( value:String ):void
        {
            _appName = value;
            _defineUserAgent();
        }

        /**
         * Indicates the version of the application.
         */
        public function get appVersion():Version
        {
            return _appVersion;
        }

        /**
         * @private
         */
        public function set appVersion( value:Version ):void
        {
            _appVersion = value;
            _defineUserAgent();

        }

        /**
         * Sets the stage reference value of the application.
         */
        ga_internal function set url( value:String ):void
        {
            _url = value;
        }

        /**
         * Indicates the location of swf.
         */
        public function get locationSWFPath():String
        {
            return _url;
        }

        /**
         * Indicates the referrer value.
         */
        public function get referrer():String
        {
            var _referrer:String = _dom.referrer;

            if( _referrer )
            {
                return _referrer;
            }

            if( protocol == "file" )
            {
                return "localhost";
            }

            return "";
        }

        /**
         * Indicates the title of the document.
         */
        public function get documentTitle():String
        {
            var _title:String = _dom.title;

            if( _title )
            {
                return _title;
            }

            return "";
        }

        /**
         * Indicates the local domain name value.
         */
        public function get domainName():String
        {
            if( (protocol == "http") ||
                (protocol == "https") )
            {
                var url:uri = new uri( _url.toLowerCase() );
                return url.host;
            }

            if( protocol == "file" )
            {
                return "localhost";
            }

            return "";
        }

        /**
         * Indicates if the application is running in AIR.
         */
        public function isAIR():Boolean
        {
            return Security.sandboxType == "application";
        }

        /**
         * Indicates if the SWF is embeded in an HTML page.
         * @return true if the SWF is embeded in an HTML page.
         */
        public function isInHTML():Boolean
        {
            return Capabilities.playerType == "PlugIn" ;
        }

        /**
         * Indicates the locationPath value.
         */
        public function get locationPath():String
        {
            var _pathname:String = _dom.pathname;

            if( _pathname )
            {
                return _pathname;
            }

            return "";
        }

        /**
         * Indicates the locationSearch value.
         */
        public function get locationSearch():String
        {
            var _search:String = _dom.search;

            if( _search )
            {
                return _search;
            }

            return "";
        }

        /**
         * Returns the flash version object representation of the application.
         *
This object contains the attributes major, minor, build and revision :

         *
Example :

         *

         * import com.google.analytics.utils.Environment ;
         *
         * var info:Environment = new Environment( "http://www.domain.com" ) ;
         * var version:Object = info.flashVersion ;
         *
         * trace( version.major    ) ; // 9
         * trace( version.minor    ) ; // 0
         * trace( version.build    ) ; // 124
         * trace( version.revision ) ; // 0
         *

         * @return the flash version object representation of the application.
         */
        public function get flashVersion():Version
        {
            var v:Version = Version.fromString( Capabilities.version.split( " " )[1], "," ) ;
            return v ;
        }

        /**
         * Returns the language string as a lowercase two-letter language code from ISO 639-1.
         * @see Capabilities.language
         */
        public function get language():String
        {
            var _lang:String = _dom.language;
            var lang:String  = Capabilities.language;

            if( _lang )
            {
                if( (_lang.length > lang.length) &&
                    (_lang.substr(0,lang.length) == lang) )
                {
                    lang = _lang;
                }
            }

            return lang;
        }

        /**
         * Returns the internal character set used by the flash player
         *
Logic : by default flash player use unicode internally so we return UTF-8.

         *
If the player use the system code page then we try to return the char set of the browser.

         * @return the internal character set used by the flash player
         */
        public function get languageEncoding():String
        {
            if( System.useCodePage )
            {
                var _charset:String = _dom.characterSet;
                if( _charset )
                {
                    return _charset;
                }
                return "-"; //not found
            }
            //default
            return "UTF-8" ;
        }

        /**
         * Returns the operating system string.
         *
Note: The flash documentation indicate those strings

         *
"Windows XP"

         *
"Windows 2000"

         *
"Windows NT"

         *
"Windows 98/ME"

         *
"Windows 95"

         *
"Windows CE" (available only in Flash Player SDK, not in the desktop version)

         *
"Linux"

         *
"MacOS"

         *
Other strings we can obtain ( not documented : "Mac OS 10.5.4" , "Windows Vista")

         * @return the operating system string.
         * @see Capabilities.os
         */
        public function get operatingSystem():String
        {
            return Capabilities.os ;
        }

        /**
         * Returns the player type.
         *
Note : The flash documentation indicate those strings.

         *
"ActiveX"    : for the Flash Player ActiveX control used by Microsoft Internet Explorer.

         *
"Desktop"    : for the Adobe AIR runtime (except for SWF content loaded by an HTML page, which has Capabilities.playerType set to "PlugIn").

         *
"External"   : for the external Flash Player "PlugIn" for the Flash Player browser plug-in (and for SWF content loaded by an HTML page in an AIR application).

         *
"StandAlone" : for the stand-alone Flash Player.

         * @return the player type.
         * @see Capabilities.playerType
         */
        public function get playerType():String
        {
            return Capabilities.playerType;
        }

        /**
         * Returns the platform, can be "Windows", "Macintosh" or "Linux"
         * @see Capabilities.manufacturer
         */
        public function get platform():String
        {
            var p:String = Capabilities.manufacturer;
            return p.split( "Adobe " )[1];
        }

        /**
         * Indicates the Protocols object of this local info.
         */
        public function get protocol():String
        {
            if(!_protocol)
            {
                _findProtocol();
            }

            return _protocol;
        }

        /**
         * Indicates the height of the screen.
         * @see Capabilities.screenResolutionY
         */
        public function get screenHeight():Number
        {
            return Capabilities.screenResolutionY;
        }

        /**
         * Indicates the width of the screen.
         * @see Capabilities.screenResolutionX
         */
        public function get screenWidth():Number
        {
            return Capabilities.screenResolutionX;
        }

        /**
         * In AIR we can use flash.display.Screen to directly get the colorDepth property
         * in flash player we can only access screenColor in flash.system.Capabilities.
         *
Some ref : http://en.wikipedia.org/wiki/Color_depth

         *
"color" -> 16-bit or 24-bit or 32-bit

         *
"gray"  -> 2-bit

         *
"bw"    -> 1-bit

         */
        public function get screenColorDepth():String
        {
            var color:String;
            switch( Capabilities.screenColor )
            {
                case "bw":
                {
                    color = "1";
                    break;
                }
                case "gray":
                {
                    color = "2";
                    break;
                }
                /* note:
                   as we have no way to know if
                   we are in 16-bit, 24-bit or 32-bit
                   we gives 24-bit by default
                */
                case "color" :
                default      :
                {
                    color = "24" ;
                }
            }

            var _colorDepth:String = _dom.colorDepth;

            if( _colorDepth )
            {
                color = _colorDepth;
            }

            return color;
        }

        private function _defineUserAgent():void
        {
            _userAgent = core.strings.userAgent( appName + "/" + appVersion.toString(4) );
        }

        /**
         * Defines a custom user agent.
         *
For case where the user would want to define its own application name and version
         * it is possible to change appName and appVersion which are in sync with
         * applicationProduct and applicationVersion properties.

         */
        public function get userAgent():String
        {
            if( !_userAgent )
            {
                 _defineUserAgent();
            }

            return _userAgent;
        }

        /**
         * @private
         */
        public function set userAgent( custom:String ):void
        {
            _userAgent = custom;
        }

    }
}

/*
 * 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.utils
{
    import com.google.analytics.core.ga_internal;
    import com.google.analytics.debug.DebugConfiguration;
    import com.google.analytics.external.HTMLDOM;

    import core.strings.userAgent;
    import core.uri;
    import core.version;

    import flash.system.Capabilities;
    import flash.system.Security;
    import flash.system.System;

    /**
     * Environment provides informations for the local environment.
     */
    public class Environment
    {
        private var _debug:DebugConfiguration;
        private var _dom:HTMLDOM;

        private var _protocol:String;
        private var _appName:String;
        private var _appVersion:version;
        private var _userAgent:String;
        private var _url:String;

        /**
         * Creates a new Environment instance.
         * @param url The URL of the SWF.
         * @param app The application name
         * @param version The application version
         * @param dom the HTMLDOM reference.
         */
        public function Environment( url:String = "", app:String = "", version:String = "",
                                     debug:DebugConfiguration = null, dom:HTMLDOM = null )
        {
            var v:core.version;

            if( app == "" )
            {
                if( isAIR() )
                {
                    app = "AIR";
                }
                else
                {
                    app = "Flash";
                }
            }

            if( version == "" )
            {
                v = flashVersion;
            }
            else
            {
                v = getVersionFromString( version );
            }

            _url        = url;
            _appName    = app;
            _appVersion = v;

            _debug      = debug;
            _dom        = dom;
        }

        /**
         * @private
         */
        private function _findProtocol():void
        {
            _protocol = "";

            if( _url != "" )
            {
                var url:uri = new uri( _url );
                _protocol = url.scheme;
            }
        }

        /**
         * Indicates the name of the application.
         */
        public function get appName():String
        {
            return _appName;
        }

        /**
         * @private
         */
        public function set appName( value:String ):void
        {
            _appName = value;
            _defineUserAgent();
        }

        /**
         * Indicates the version of the application.
         */
        public function get appVersion():version
        {
            return _appVersion;
        }

        /**
         * @private
         */
        public function set appVersion( value:version ):void
        {
            _appVersion = value;
            _defineUserAgent();

        }

        /**
         * Sets the stage reference value of the application.
         */
        ga_internal function set url( value:String ):void
        {
            _url = value;
        }

        /**
         * Indicates the location of swf.
         */
        public function get locationSWFPath():String
        {
            return _url;
        }

        /**
         * Indicates the referrer value.
         */
        public function get referrer():String
        {
            var _referrer:String = _dom.referrer;

            if( _referrer )
            {
                return _referrer;
            }

            if( protocol == "file" )
            {
                return "localhost";
            }

            return "";
        }

        /**
         * Indicates the title of the document.
         */
        public function get documentTitle():String
        {
            var _title:String = _dom.title;

            if( _title )
            {
                return _title;
            }

            return "";
        }

        /**
         * Indicates the local domain name value.
         */
        public function get domainName():String
        {
            if( (protocol == "http") ||
                (protocol == "https") )
            {
                var url:uri = new uri( _url.toLowerCase() );
                return url.host;
            }

            if( protocol == "file" )
            {
                return "localhost";
            }

            return "";
        }

        /**
         * Indicates if the application is running in AIR.
         */
        public function isAIR():Boolean
        {
            return Security.sandboxType == "application";
        }

        /**
         * Indicates if the SWF is embeded in an HTML page.
         * @return true if the SWF is embeded in an HTML page.
         */
        public function isInHTML():Boolean
        {
            return Capabilities.playerType == "PlugIn" ;
        }

        /**
         * Indicates the locationPath value.
         */
        public function get locationPath():String
        {
            var _pathname:String = _dom.pathname;

            if( _pathname )
            {
                return _pathname;
            }

            return "";
        }

        /**
         * Indicates the locationSearch value.
         */
        public function get locationSearch():String
        {
            var _search:String = _dom.search;

            if( _search )
            {
                return _search;
            }

            return "";
        }

        /**
         * Returns the flash version object representation of the application.
         *
This object contains the attributes major, minor, build and revision :

         *
Example :

         *

         * import com.google.analytics.utils.Environment ;
         *
         * var info:Environment = new Environment( "http://www.domain.com" ) ;
         * var version:Object = info.flashVersion ;
         *
         * trace( version.major    ) ; // 9
         * trace( version.minor    ) ; // 0
         * trace( version.build    ) ; // 124
         * trace( version.revision ) ; // 0
         *

         * @return the flash version object representation of the application.
         */
        public function get flashVersion():version
        {
            var v:version = getVersionFromString( Capabilities.version.split( " " )[1], "," ) ;
            return v ;
        }

        /**
         * Returns the language string as a lowercase two-letter language code from ISO 639-1.
         * @see Capabilities.language
         */
        public function get language():String
        {
            var _lang:String = _dom.language;
            var lang:String  = Capabilities.language;

            if( _lang )
            {
                if( (_lang.length > lang.length) &&
                    (_lang.substr(0,lang.length) == lang) )
                {
                    lang = _lang;
                }
            }

            return lang;
        }

        /**
         * Returns the internal character set used by the flash player
         *
Logic : by default flash player use unicode internally so we return UTF-8.

         *
If the player use the system code page then we try to return the char set of the browser.

         * @return the internal character set used by the flash player
         */
        public function get languageEncoding():String
        {
            if( System.useCodePage )
            {
                var _charset:String = _dom.characterSet;
                if( _charset )
                {
                    return _charset;
                }
                return "-"; //not found
            }
            //default
            return "UTF-8" ;
        }

        /**
         * Returns the operating system string.
         *
Note: The flash documentation indicate those strings

         *
"Windows XP"

         *
"Windows 2000"

         *
"Windows NT"

         *
"Windows 98/ME"

         *
"Windows 95"

         *
"Windows CE" (available only in Flash Player SDK, not in the desktop version)

         *
"Linux"

         *
"MacOS"

         *
Other strings we can obtain ( not documented : "Mac OS 10.5.4" , "Windows Vista")

         * @return the operating system string.
         * @see Capabilities.os
         */
        public function get operatingSystem():String
        {
            return Capabilities.os ;
        }

        /**
         * Returns the player type.
         *
Note : The flash documentation indicate those strings.

         *
"ActiveX"    : for the Flash Player ActiveX control used by Microsoft Internet Explorer.

         *
"Desktop"    : for the Adobe AIR runtime (except for SWF content loaded by an HTML page, which has Capabilities.playerType set to "PlugIn").

         *
"External"   : for the external Flash Player "PlugIn" for the Flash Player browser plug-in (and for SWF content loaded by an HTML page in an AIR application).

         *
"StandAlone" : for the stand-alone Flash Player.

         * @return the player type.
         * @see Capabilities.playerType
         */
        public function get playerType():String
        {
            return Capabilities.playerType;
        }

        /**
         * Returns the platform, can be "Windows", "Macintosh" or "Linux"
         * @see Capabilities.manufacturer
         */
        public function get platform():String
        {
            var p:String = Capabilities.manufacturer;
            return p.split( "Adobe " )[1];
        }

        /**
         * Indicates the Protocols object of this local info.
         */
        public function get protocol():String
        {
            if(!_protocol)
            {
                _findProtocol();
            }

            return _protocol;
        }

        /**
         * Indicates the height of the screen.
         * @see Capabilities.screenResolutionY
         */
        public function get screenHeight():Number
        {
            return Capabilities.screenResolutionY;
        }

        /**
         * Indicates the width of the screen.
         * @see Capabilities.screenResolutionX
         */
        public function get screenWidth():Number
        {
            return Capabilities.screenResolutionX;
        }

        /**
         * In AIR we can use flash.display.Screen to directly get the colorDepth property
         * in flash player we can only access screenColor in flash.system.Capabilities.
         *
Some ref : http://en.wikipedia.org/wiki/Color_depth

         *
"color" -> 16-bit or 24-bit or 32-bit

         *
"gray"  -> 2-bit

         *
"bw"    -> 1-bit

         */
        public function get screenColorDepth():String
        {
            var color:String;
            switch( Capabilities.screenColor )
            {
                case "bw":
                {
                    color = "1";
                    break;
                }
                case "gray":
                {
                    color = "2";
                    break;
                }
                /* note:
                   as we have no way to know if
                   we are in 16-bit, 24-bit or 32-bit
                   we gives 24-bit by default
                */
                case "color" :
                default      :
                {
                    color = "24" ;
                }
            }

            var _colorDepth:String = _dom.colorDepth;

            if( _colorDepth )
            {
                color = _colorDepth;
            }

            return color;
        }

        private function _defineUserAgent():void
        {
            _userAgent = core.strings.userAgent( appName + "/" + appVersion.toString(4) );
        }

        /**
         * Defines a custom user agent.
         *
For case where the user would want to define its own application name and version
         * it is possible to change appName and appVersion which are in sync with
         * applicationProduct and applicationVersion properties.

         */
        public function get userAgent():String
        {
            if( !_userAgent )
            {
                 _defineUserAgent();
            }

            return _userAgent;
        }

        /**
         * @private
         */
        public function set userAgent( custom:String ):void
        {
            _userAgent = custom;
        }

    }
}

replace class Version by core.version

replace class Version by core.version


/* Compile using: mxmlc --target-player=10.0.0 -library-path+=lib ZeroClipboard.as */
package {
	import flash.display.Stage;
	import flash.display.Sprite;
	import flash.display.LoaderInfo;
	import flash.display.StageScaleMode;
	import flash.events.*;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.external.ExternalInterface;
	import flash.system.Security;
	import flash.utils.*;
	import flash.system.System;
	import flash.net.FileReference;
	import flash.net.FileFilter;

	/* PDF imports */
	import org.alivepdf.pdf.PDF;
	import org.alivepdf.data.Grid;
	import org.alivepdf.data.GridColumn;
	import org.alivepdf.layout.Orientation;
	import org.alivepdf.layout.Size;
	import org.alivepdf.layout.Unit;
	import org.alivepdf.display.Display;
	import org.alivepdf.saving.Method;
	import org.alivepdf.fonts.FontFamily;
	import org.alivepdf.fonts.Style;
	import org.alivepdf.fonts.CoreFont;
	import org.alivepdf.colors.RGBColor;

	public class ZeroClipboard extends Sprite {

		private var domId:String = '';
		private var button:Sprite;
		private var clipText:String = 'blank';
		private var fileName:String = '';
		private var action:String = 'copy';
		private var incBom:Boolean = true;
		private var charSet:String = 'utf8';

		public function ZeroClipboard() {
			// constructor, setup event listeners and external interfaces
			stage.scaleMode = StageScaleMode.EXACT_FIT;
			flash.system.Security.allowDomain("*");

			// import flashvars
			var flashvars:Object = LoaderInfo( this.root.loaderInfo ).parameters;
			domId = flashvars.id;

			// invisible button covers entire stage
			button = new Sprite();
			button.buttonMode = true;
			button.useHandCursor = true;
			button.graphics.beginFill(0x00FF00);
			button.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
			button.alpha = 0.0;
			addChild(button);

			button.addEventListener(MouseEvent.CLICK, clickHandler);
			button.addEventListener(MouseEvent.MOUSE_OVER, function(event:Event):void {
				ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'mouseOver', null );
			} );
			button.addEventListener(MouseEvent.MOUSE_OUT, function(event:Event):void {
				ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'mouseOut', null );
			} );
			button.addEventListener(MouseEvent.MOUSE_DOWN, function(event:Event):void {
				ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'mouseDown', null );
			} );
			button.addEventListener(MouseEvent.MOUSE_UP, function(event:Event):void {
				ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'mouseUp', null );
			} );

			// external functions
			ExternalInterface.addCallback("setHandCursor", setHandCursor);
			ExternalInterface.addCallback("clearText", clearText);
			ExternalInterface.addCallback("setText", setText);
			ExternalInterface.addCallback("appendText", appendText);
			ExternalInterface.addCallback("setFileName", setFileName);
			ExternalInterface.addCallback("setAction", setAction);
			ExternalInterface.addCallback("setCharSet", setCharSet);
			ExternalInterface.addCallback("setBomInc", setBomInc);

			// signal to the browser that we are ready
			ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'load', null );
		}

		public function setCharSet(newCharSet:String):void {
			if ( newCharSet == 'UTF16LE' ) {
				charSet = newCharSet;
			} else {
				charSet = 'UTF8';
			}
		}

		public function setBomInc(newBomInc:Boolean):void {
			incBom = newBomInc;
		}

		public function clearText():void {
			clipText = '';
		}

		public function appendText(newText:String):void {
			clipText += newText;
		}

		public function setText(newText:String):void {
			clipText = newText;
		}

		public function setFileName(newFileName:String):void {
			fileName = newFileName;
		}

		public function setAction(newAction:String):void {
			action = newAction;
		}

		public function setHandCursor(enabled:Boolean):void {
			// control whether the hand cursor is shown on rollover (true)
			// or the default arrow cursor (false)
			button.useHandCursor = enabled;
		}

		private function clickHandler(event:Event):void {
			var fileRef:FileReference = new FileReference();

			if ( action == "save" ) {
				/* Save as a file */
				if ( charSet == 'UTF16LE' ) {
					fileRef.save( strToUTF16LE(clipText), fileName );
				} else {
					fileRef.save( strToUTF8(clipText), fileName );
				}
			} else if ( action == "pdf" ) {
				/* Save as a PDF */
				var pdf:PDF = configPdf();
				fileRef.save( pdf.save( Method.LOCAL ), fileName );
			} else {
				/* Copy the text to the clipboard. Note charset and BOM have no effect here */
				System.setClipboard( clipText );
			}

			ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'complete', clipText );
		}

		private function getProp( prop:String, opts:Array ):String
		{
			var i:int, iLen:int;
			for ( i=0, iLen=opts.length ; i<iLen ; i++ )
			{
				if ( opts[i].indexOf( prop+":" ) != -1 )
				{
					return opts[i].replace( prop+":", "" );
				}
			}
			return "";
		}

		private function configPdf():PDF
		{
			var
				pdf:PDF,
				i:int, iLen:int,
				splitText:Array = clipText.split("--/TableToolsOpts--\n"),
				opts:Array = splitText[0].split("\n"),
				dataIn:Array = splitText[1].split("\n"),
				aColRatio:Array = getProp( 'colWidth', opts ).split('\t'),
				title:String = getProp( 'title', opts ),
				message:String = getProp( 'message', opts ),
				iPageWidth:int = 0,
				dataOut:Array = [],
				columns:Array = [],
				headers:Array,
				y:int = 0;

			/* Create the PDF */
			pdf = new PDF( Orientation.PORTRAIT, Unit.MM, Size.A4 );
			pdf.setDisplayMode( Display.FULL_WIDTH );
			pdf.addPage();
			iPageWidth = pdf.getCurrentPage().w-20

			/* Data setup. Split up the headers, and then construct the columns */
			for ( i=0, iLen=dataIn.length ; i<iLen ; i++ )
			{
				dataOut.push( dataIn[i].split("\t") );
			}
			headers = dataOut.shift();

			for ( i=0, iLen=headers.length ; i<iLen ; i++ )
			{
				columns.push( new GridColumn( headers[i], i.toString(), aColRatio[i]*iPageWidth ) );
			}

			pdf.textStyle( new RGBColor(0), 1 );
			pdf.setFont( new CoreFont(FontFamily.HELVETICA), 11 );
			var grid:Grid = new Grid(
				dataOut,                  /* 1. data */
				iPageWidth,               /* 2. width */
				100,                      /* 3. height */
				new RGBColor (0x00CCFF),  /* 4. headerColor */
				new RGBColor (0xFFFFFF),  /* 5. backgroundColor */
				true,                     /* 6. alternateRowColor */
				new RGBColor ( 0x0 ),     /* 7. borderColor */
				.1,                       /* 8. border alpha */
				null,                     /* 9. joins */
				columns                   /* 10. columns */
			);

			pdf.addGrid( grid, 0, y );
			return pdf;
		}

		/*
		 * Function: strToUTF8
		 * Purpose:  Convert a string to the output utf-8
		 * Returns:  ByteArray
		 * Inputs:   String
		 */
		private function strToUTF8( str:String ):ByteArray {
			var utf8:ByteArray = new ByteArray();

			/* BOM first */
			if ( incBom ) {
				utf8.writeByte( 0xEF );
				utf8.writeByte( 0xBB );
				utf8.writeByte( 0xBF );
			}
			utf8.writeUTFBytes( str );

			return utf8;
		}

		/*
		 * Function: strToUTF16LE
		 * Purpose:  Convert a string to the output utf-16
		 * Returns:  ByteArray
		 * Inputs:   String
		 * Notes:    The fact that this function is needed is a little annoying. Basically, strings in
		 *   AS3 are UTF-16 (with surrogate pairs and everything), but characters which take up less
		 *   than 8 bytes appear to be stored as only 8 bytes. This function effective adds the
		 *   padding required, and the BOM
		 */
		private function strToUTF16LE( str:String ):ByteArray {
			var utf16:ByteArray = new ByteArray();
			var iChar:uint;
			var i:uint=0, iLen:uint = str.length;

			/* BOM first */
			if ( incBom ) {
				utf16.writeByte( 0xFF );
				utf16.writeByte( 0xFE );
			}

			while ( i < iLen ) {
				iChar = str.charCodeAt(i);

				if ( iChar < 0xFF ) {
					/* one byte char */
					utf16.writeByte( iChar );
					utf16.writeByte( 0 );
				} else {
					/* two byte char */
					utf16.writeByte( iChar & 0x00FF );
					utf16.writeByte( iChar >> 8 );
				}

				i++;
			}

			return utf16;
		}
	}
}

/* Compile using: mxmlc --target-player=10.0.0 -library-path+=lib ZeroClipboardPdf.as */
package {
	import flash.display.Stage;
	import flash.display.Sprite;
	import flash.display.LoaderInfo;
	import flash.display.StageScaleMode;
	import flash.events.*;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.external.ExternalInterface;
	import flash.system.Security;
	import flash.utils.*;
	import flash.system.System;
	import flash.net.FileReference;
	import flash.net.FileFilter;

	/* PDF imports */
	import org.alivepdf.pdf.PDF;
	import org.alivepdf.data.Grid;
	import org.alivepdf.data.GridColumn;
	import org.alivepdf.layout.Orientation;
	import org.alivepdf.layout.Size;
	import org.alivepdf.layout.Unit;
	import org.alivepdf.display.Display;
	import org.alivepdf.saving.Method;
	import org.alivepdf.fonts.FontFamily;
	import org.alivepdf.fonts.Style;
	import org.alivepdf.fonts.CoreFont;
	import org.alivepdf.colors.RGBColor;

	public class ZeroClipboard extends Sprite {

		private var domId:String = '';
		private var button:Sprite;
		private var clipText:String = 'blank';
		private var fileName:String = '';
		private var action:String = 'copy';
		private var incBom:Boolean = true;
		private var charSet:String = 'utf8';

		public function ZeroClipboard() {
			// constructor, setup event listeners and external interfaces
			stage.scaleMode = StageScaleMode.EXACT_FIT;
			flash.system.Security.allowDomain("*");

			// import flashvars
			var flashvars:Object = LoaderInfo( this.root.loaderInfo ).parameters;
			domId = flashvars.id;

			// invisible button covers entire stage
			button = new Sprite();
			button.buttonMode = true;
			button.useHandCursor = true;
			button.graphics.beginFill(0x00FF00);
			button.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
			button.alpha = 0.0;
			addChild(button);

			button.addEventListener(MouseEvent.CLICK, clickHandler);
			button.addEventListener(MouseEvent.MOUSE_OVER, function(event:Event):void {
				ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'mouseOver', null );
			} );
			button.addEventListener(MouseEvent.MOUSE_OUT, function(event:Event):void {
				ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'mouseOut', null );
			} );
			button.addEventListener(MouseEvent.MOUSE_DOWN, function(event:Event):void {
				ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'mouseDown', null );
			} );
			button.addEventListener(MouseEvent.MOUSE_UP, function(event:Event):void {
				ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'mouseUp', null );
			} );

			// external functions
			ExternalInterface.addCallback("setHandCursor", setHandCursor);
			ExternalInterface.addCallback("clearText", clearText);
			ExternalInterface.addCallback("setText", setText);
			ExternalInterface.addCallback("appendText", appendText);
			ExternalInterface.addCallback("setFileName", setFileName);
			ExternalInterface.addCallback("setAction", setAction);
			ExternalInterface.addCallback("setCharSet", setCharSet);
			ExternalInterface.addCallback("setBomInc", setBomInc);

			// signal to the browser that we are ready
			ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'load', null );
		}

		public function setCharSet(newCharSet:String):void {
			if ( newCharSet == 'UTF16LE' ) {
				charSet = newCharSet;
			} else {
				charSet = 'UTF8';
			}
		}

		public function setBomInc(newBomInc:Boolean):void {
			incBom = newBomInc;
		}

		public function clearText():void {
			clipText = '';
		}

		public function appendText(newText:String):void {
			clipText += newText;
		}

		public function setText(newText:String):void {
			clipText = newText;
		}

		public function setFileName(newFileName:String):void {
			fileName = newFileName;
		}

		public function setAction(newAction:String):void {
			action = newAction;
		}

		public function setHandCursor(enabled:Boolean):void {
			// control whether the hand cursor is shown on rollover (true)
			// or the default arrow cursor (false)
			button.useHandCursor = enabled;
		}

		private function clickHandler(event:Event):void {
			var fileRef:FileReference = new FileReference();

			if ( action == "save" ) {
				/* Save as a file */
				if ( charSet == 'UTF16LE' ) {
					fileRef.save( strToUTF16LE(clipText), fileName );
				} else {
					fileRef.save( strToUTF8(clipText), fileName );
				}
			} else if ( action == "pdf" ) {
				/* Save as a PDF */
				var pdf:PDF = configPdf();
				fileRef.save( pdf.save( Method.LOCAL ), fileName );
			} else {
				/* Copy the text to the clipboard. Note charset and BOM have no effect here */
				System.setClipboard( clipText );
			}

			ExternalInterface.call( 'ZeroClipboard.dispatch', domId, 'complete', clipText );
		}

		private function getProp( prop:String, opts:Array ):String
		{
			var i:int, iLen:int;
			for ( i=0, iLen=opts.length ; i<iLen ; i++ )
			{
				if ( opts[i].indexOf( prop+":" ) != -1 )
				{
					return opts[i].replace( prop+":", "" );
				}
			}
			return "";
		}

		private function configPdf():PDF
		{
			var
				pdf:PDF,
				i:int, iLen:int,
				splitText:Array = clipText.split("--/TableToolsOpts--\n"),
				opts:Array = splitText[0].split("\n"),
				dataIn:Array = splitText[1].split("\n"),
				aColRatio:Array = getProp( 'colWidth', opts ).split('\t'),
				title:String = getProp( 'title', opts ),
				message:String = getProp( 'message', opts ),
				iPageWidth:int = 0,
				dataOut:Array = [],
				columns:Array = [],
				headers:Array,
				y:int = 0;

			/* Create the PDF */
			pdf = new PDF( Orientation.PORTRAIT, Unit.MM, Size.A4 );
			pdf.setDisplayMode( Display.FULL_WIDTH );
			pdf.addPage();
			iPageWidth = pdf.getCurrentPage().w-20

			/* Data setup. Split up the headers, and then construct the columns */
			for ( i=0, iLen=dataIn.length ; i<iLen ; i++ )
			{
				dataOut.push( dataIn[i].split("\t") );
			}
			headers = dataOut.shift();

			for ( i=0, iLen=headers.length ; i<iLen ; i++ )
			{
				columns.push( new GridColumn( headers[i], i.toString(), aColRatio[i]*iPageWidth ) );
			}

			pdf.textStyle( new RGBColor(0), 1 );
			pdf.setFont( new CoreFont(FontFamily.HELVETICA), 11 );
			var grid:Grid = new Grid(
				dataOut,                  /* 1. data */
				iPageWidth,               /* 2. width */
				100,                      /* 3. height */
				new RGBColor (0x00CCFF),  /* 4. headerColor */
				new RGBColor (0xFFFFFF),  /* 5. backgroundColor */
				true,                     /* 6. alternateRowColor */
				new RGBColor ( 0x0 ),     /* 7. borderColor */
				.1,                       /* 8. border alpha */
				null,                     /* 9. joins */
				columns                   /* 10. columns */
			);

			pdf.addGrid( grid, 0, y );
			return pdf;
		}

		/*
		 * Function: strToUTF8
		 * Purpose:  Convert a string to the output utf-8
		 * Returns:  ByteArray
		 * Inputs:   String
		 */
		private function strToUTF8( str:String ):ByteArray {
			var utf8:ByteArray = new ByteArray();

			/* BOM first */
			if ( incBom ) {
				utf8.writeByte( 0xEF );
				utf8.writeByte( 0xBB );
				utf8.writeByte( 0xBF );
			}
			utf8.writeUTFBytes( str );

			return utf8;
		}

		/*
		 * Function: strToUTF16LE
		 * Purpose:  Convert a string to the output utf-16
		 * Returns:  ByteArray
		 * Inputs:   String
		 * Notes:    The fact that this function is needed is a little annoying. Basically, strings in
		 *   AS3 are UTF-16 (with surrogate pairs and everything), but characters which take up less
		 *   than 8 bytes appear to be stored as only 8 bytes. This function effective adds the
		 *   padding required, and the BOM
		 */
		private function strToUTF16LE( str:String ):ByteArray {
			var utf16:ByteArray = new ByteArray();
			var iChar:uint;
			var i:uint=0, iLen:uint = str.length;

			/* BOM first */
			if ( incBom ) {
				utf16.writeByte( 0xFF );
				utf16.writeByte( 0xFE );
			}

			while ( i < iLen ) {
				iChar = str.charCodeAt(i);

				if ( iChar < 0xFF ) {
					/* one byte char */
					utf16.writeByte( iChar );
					utf16.writeByte( 0 );
				} else {
					/* two byte char */
					utf16.writeByte( iChar & 0x00FF );
					utf16.writeByte( iChar >> 8 );
				}

				i++;
			}

			return utf16;
		}
	}
}

Fix: Comment updated for the correct file name with the compile command


package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.Effect;
	import aerys.minko.render.Viewport;
	import aerys.minko.scene.controller.scene.RenderingController;
	import aerys.minko.scene.node.camera.AbstractCamera;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;

	import flash.display.BitmapData;
	import flash.utils.getTimer;

	/**
	 * Scene objects are the root of any 3D scene.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public final class Scene extends Group
	{
		use namespace minko_scene;

		minko_scene var _camera		: AbstractCamera;

		private var _renderingCtrl	: RenderingController;

		private var _properties		: DataProvider;
		private var _bindings		: DataBindings;

		private var _numTriangles	: uint;

		private var _enterFrame		: Signal;
		private var _renderingBegin	: Signal;
		private var _renderingEnd	: Signal;
		private var _exitFrame		: Signal;

		public function get activeCamera() : AbstractCamera
		{
			return _camera;
		}

		public function get numPasses() : uint
		{
			return _renderingCtrl.numPasses;
		}

		public function get numTriangles() : uint
		{
			return _numTriangles;
		}

		public function get postProcessingEffect() : Effect
		{
			return _renderingCtrl.postProcessingEffect;
		}
		public function set postProcessingEffect(value : Effect) : void
		{
			_renderingCtrl.postProcessingEffect = value;
		}

		public function get postProcessingProperties() : DataProvider
		{
			return _renderingCtrl.postProcessingProperties;
		}

		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 bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The signal executed when the viewport is about to start rendering a frame.
		 * Callback functions for this signal should accept the following arguments:
		 *

		 *
viewport : Viewport, the viewport who starts rendering the frame

		 *

		 * @return
		 *
		 */
		public function get enterFrame() : Signal
		{
			return _enterFrame;
		}

		/**
		 * The signal executed when the viewport is done rendering a frame.
		 * Callback functions for this signal should accept the following arguments:
		 *

		 *
viewport : Viewport, the viewport who just finished rendering the frame

		 *

		 * @return
		 *
		 */
		public function get exitFrame() : Signal
		{
			return _exitFrame;
		}

		public function get renderingBegin() : Signal
		{
			return _renderingBegin;
		}

		public function get renderingEnd() : Signal
		{
			return _renderingEnd;
		}

		public function Scene(...children)
		{
			super();
		}

		override protected function initialize() : void
		{
			_bindings = new DataBindings(this);
			this.properties = new DataProvider(DataProviderUsage.EXCLUSIVE);

			super.initialize();
		}

		override protected function initializeSignals() : void
		{
			super.initializeSignals();

			_enterFrame = new Signal('Scene.enterFrame');
			_renderingBegin = new Signal('Scene.renderingBegin');
			_renderingEnd = new Signal('Scene.renderingEnd');
			_exitFrame = new Signal('Scene.exitFrame');
		}

		override protected function initializeSignalHandlers() : void
		{
			super.initializeSignalHandlers();

			added.add(addedHandler);
		}

		override protected function initializeContollers() : void
		{
			_renderingCtrl = new RenderingController();
			addController(_renderingCtrl);

			super.initializeContollers();
		}

		public function render(viewport : Viewport, destination : BitmapData = null) : void
		{
			_enterFrame.execute(this, viewport, destination, getTimer());
			if (viewport.ready && viewport.visible)
			{
				_renderingBegin.execute(this, viewport, destination, getTimer());
				_numTriangles = _renderingCtrl.render(viewport, destination);
				_renderingEnd.execute(this, viewport, destination, getTimer());
			}
			_exitFrame.execute(this, viewport, destination, getTimer());
		}

		private function addedHandler(child : ISceneNode, parent : Group) : void
		{
			throw new Error();
		}
	}
}

package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.Effect;
	import aerys.minko.render.Viewport;
	import aerys.minko.scene.controller.scene.RenderingController;
	import aerys.minko.scene.node.camera.AbstractCamera;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;

	import flash.display.BitmapData;
	import flash.utils.getTimer;

	/**
	 * Scene objects are the root of any 3D scene.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public final class Scene extends Group
	{
		use namespace minko_scene;

		minko_scene var _camera		: AbstractCamera;

		private var _renderingCtrl	: RenderingController;

		private var _properties		: DataProvider;
		private var _bindings		: DataBindings;

		private var _numTriangles	: uint;

		private var _enterFrame		: Signal;
		private var _renderingBegin	: Signal;
		private var _renderingEnd	: Signal;
		private var _exitFrame		: Signal;

		public function get activeCamera() : AbstractCamera
		{
			return _camera;
		}

		public function get numPasses() : uint
		{
			return _renderingCtrl.numPasses;
		}

		public function get numTriangles() : uint
		{
			return _numTriangles;
		}

		public function get postProcessingEffect() : Effect
		{
			return _renderingCtrl.postProcessingEffect;
		}
		public function set postProcessingEffect(value : Effect) : void
		{
			_renderingCtrl.postProcessingEffect = value;
		}

		public function get postProcessingProperties() : DataProvider
		{
			return _renderingCtrl.postProcessingProperties;
		}

		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 bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The signal executed when the viewport is about to start rendering a frame.
		 * Callback functions for this signal should accept the following arguments:
		 *

		 *
viewport : Viewport, the viewport who starts rendering the frame

		 *

		 * @return
		 *
		 */
		public function get enterFrame() : Signal
		{
			return _enterFrame;
		}

		/**
		 * The signal executed when the viewport is done rendering a frame.
		 * Callback functions for this signal should accept the following arguments:
		 *

		 *
viewport : Viewport, the viewport who just finished rendering the frame

		 *

		 * @return
		 *
		 */
		public function get exitFrame() : Signal
		{
			return _exitFrame;
		}

		public function get renderingBegin() : Signal
		{
			return _renderingBegin;
		}

		public function get renderingEnd() : Signal
		{
			return _renderingEnd;
		}

		public function Scene(...children)
		{
			super(children);
		}

		override protected function initialize() : void
		{
			_bindings = new DataBindings(this);
			this.properties = new DataProvider(DataProviderUsage.EXCLUSIVE);

			super.initialize();
		}

		override protected function initializeSignals() : void
		{
			super.initializeSignals();

			_enterFrame = new Signal('Scene.enterFrame');
			_renderingBegin = new Signal('Scene.renderingBegin');
			_renderingEnd = new Signal('Scene.renderingEnd');
			_exitFrame = new Signal('Scene.exitFrame');
		}

		override protected function initializeSignalHandlers() : void
		{
			super.initializeSignalHandlers();

			added.add(addedHandler);
		}

		override protected function initializeContollers() : void
		{
			_renderingCtrl = new RenderingController();
			addController(_renderingCtrl);

			super.initializeContollers();
		}

		public function render(viewport : Viewport, destination : BitmapData = null) : void
		{
			_enterFrame.execute(this, viewport, destination, getTimer());
			if (viewport.ready && viewport.visible)
			{
				_renderingBegin.execute(this, viewport, destination, getTimer());
				_numTriangles = _renderingCtrl.render(viewport, destination);
				_renderingEnd.execute(this, viewport, destination, getTimer());
			}
			_exitFrame.execute(this, viewport, destination, getTimer());
		}

		private function addedHandler(child : ISceneNode, parent : Group) : void
		{
			throw new Error();
		}
	}
}

fix Scene constructor to pass the children argument to the parent constructor and init. children properly (issue #1105)


package dolly {
import dolly.core.dolly_internal;
import dolly.data.CloneableClass;
import dolly.data.CompositeCloneableClass;

import mx.collections.ArrayCollection;
import mx.collections.ArrayList;

import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;
import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertFalse;
import org.flexunit.asserts.assertNotNull;
import org.hamcrest.assertThat;
import org.hamcrest.collection.array;
import org.hamcrest.collection.arrayWithSize;
import org.hamcrest.collection.everyItem;
import org.hamcrest.core.isA;
import org.hamcrest.object.equalTo;

use namespace dolly_internal;

public class CloningOfCompositeCloneableClassTest {

	private var compositeCloneableClass:CompositeCloneableClass;
	private var compositeCloneableClassType:Type;

	[Before]
	public function before():void {
		compositeCloneableClass = new CompositeCloneableClass();

		const nestedCloneable:CloneableClass = new CloneableClass();
		nestedCloneable.property1 = "property1 value";
		nestedCloneable.writableField1 = "writableField1 value";

		const nestedCompositeCloneable:CompositeCloneableClass = new CompositeCloneableClass();
		nestedCompositeCloneable.compositeCloneable = compositeCloneableClass;
		nestedCompositeCloneable.array = [1, 2, 3];
		nestedCompositeCloneable.arrayList = new ArrayList([1, 2, 3]);
		nestedCompositeCloneable.arrayCollection = new ArrayCollection([1, 2, 3]);

		compositeCloneableClass.cloneable = nestedCloneable;
		compositeCloneableClass.compositeCloneable = nestedCompositeCloneable;
		compositeCloneableClass.array = [1, 2, 3, 4, 5];
		compositeCloneableClass.arrayList = new ArrayList([1, 2, 3, 4, 5]);
		compositeCloneableClass.arrayCollection = new ArrayCollection([1, 2, 3, 4, 5]);

		compositeCloneableClassType = Type.forInstance(compositeCloneableClass);
	}

	[After]
	public function after():void {
		compositeCloneableClass.compositeCloneable =
				compositeCloneableClass.compositeCloneable.compositeCloneable = null;
		compositeCloneableClass.cloneable = null;
		compositeCloneableClass = null;
		compositeCloneableClassType = null;
	}

	[Test]
	public function findingAllWritableFieldsForType():void {
		const writableFields:Vector.<Field> = Cloner.findAllWritableFieldsForType(compositeCloneableClassType);
		assertNotNull(writableFields);
		assertEquals(5, writableFields.length);
	}

	[Test]
	public function cloningOfArray():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		assertNotNull(clone.array);
		assertThat(clone.array, arrayWithSize(5));
		assertThat(clone.array, compositeCloneableClass.array);
		assertFalse(clone.array == compositeCloneableClass.array);
		assertThat(clone.array, everyItem(isA(Number)));
		assertThat(clone.array, array(equalTo(1), equalTo(2), equalTo(3), equalTo(4), equalTo(5)));
	}

	[Test]
	public function cloningOfArrayList():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		const arrayList:ArrayList = clone.arrayList;

		assertNotNull(arrayList);
		assertFalse(clone.arrayList == compositeCloneableClass.arrayList);
		assertEquals(arrayList.length, 5);
		assertEquals(arrayList.getItemAt(0), 1);
		assertEquals(arrayList.getItemAt(1), 2);
		assertEquals(arrayList.getItemAt(2), 3);
		assertEquals(arrayList.getItemAt(3), 4);
		assertEquals(arrayList.getItemAt(4), 5);
	}

	[Test]
	public function cloningOfArrayCollection():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		const arrayCollection:ArrayCollection = clone.arrayCollection;

		assertNotNull(arrayCollection);
		assertFalse(clone.arrayCollection == compositeCloneableClass.arrayCollection);
		assertEquals(arrayCollection.length, 5);
		assertEquals(arrayCollection.getItemAt(0), 1);
		assertEquals(arrayCollection.getItemAt(1), 2);
		assertEquals(arrayCollection.getItemAt(2), 3);
		assertEquals(arrayCollection.getItemAt(3), 4);
		assertEquals(arrayCollection.getItemAt(4), 5);
	}
}
}

package dolly {
import dolly.core.dolly_internal;
import dolly.data.CloneableClass;
import dolly.data.CompositeCloneableClass;

import mx.collections.ArrayCollection;
import mx.collections.ArrayList;

import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;
import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertFalse;
import org.flexunit.asserts.assertNotNull;
import org.hamcrest.assertThat;
import org.hamcrest.collection.array;
import org.hamcrest.collection.arrayWithSize;
import org.hamcrest.collection.everyItem;
import org.hamcrest.core.isA;
import org.hamcrest.core.not;
import org.hamcrest.object.equalTo;

use namespace dolly_internal;

public class CloningOfCompositeCloneableClassTest {

	private var compositeCloneableClass:CompositeCloneableClass;
	private var compositeCloneableClassType:Type;

	[Before]
	public function before():void {
		compositeCloneableClass = new CompositeCloneableClass();

		const nestedCloneable:CloneableClass = new CloneableClass();
		nestedCloneable.property1 = "property1 value";
		nestedCloneable.writableField1 = "writableField1 value";

		const nestedCompositeCloneable:CompositeCloneableClass = new CompositeCloneableClass();
		nestedCompositeCloneable.compositeCloneable = compositeCloneableClass;
		nestedCompositeCloneable.array = [1, 2, 3];
		nestedCompositeCloneable.arrayList = new ArrayList([1, 2, 3]);
		nestedCompositeCloneable.arrayCollection = new ArrayCollection([1, 2, 3]);

		compositeCloneableClass.cloneable = nestedCloneable;
		compositeCloneableClass.compositeCloneable = nestedCompositeCloneable;
		compositeCloneableClass.array = [1, 2, 3, 4, 5];
		compositeCloneableClass.arrayList = new ArrayList([1, 2, 3, 4, 5]);
		compositeCloneableClass.arrayCollection = new ArrayCollection([1, 2, 3, 4, 5]);

		compositeCloneableClassType = Type.forInstance(compositeCloneableClass);
	}

	[After]
	public function after():void {
		compositeCloneableClass.compositeCloneable =
				compositeCloneableClass.compositeCloneable.compositeCloneable = null;
		compositeCloneableClass.cloneable = null;
		compositeCloneableClass = null;
		compositeCloneableClassType = null;
	}

	[Test]
	public function findingAllWritableFieldsForType():void {
		const writableFields:Vector.<Field> = Cloner.findAllWritableFieldsForType(compositeCloneableClassType);
		assertNotNull(writableFields);
		assertEquals(5, writableFields.length);
	}

	[Test]
	public function cloningOfArray():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		assertNotNull(clone.array);
		assertThat(clone.array, arrayWithSize(5));
		assertThat(clone.array, compositeCloneableClass.array);
		assertFalse(clone.array == compositeCloneableClass.array);
		assertThat(clone.array, everyItem(isA(Number)));
		assertThat(clone.array, array(equalTo(1), equalTo(2), equalTo(3), equalTo(4), equalTo(5)));
	}

	[Test]
	public function cloningOfArrayList():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		const arrayList:ArrayList = clone.arrayList;

		assertNotNull(arrayList);
		assertFalse(clone.arrayList == compositeCloneableClass.arrayList);
		assertEquals(arrayList.length, 5);
		assertEquals(arrayList.getItemAt(0), 1);
		assertEquals(arrayList.getItemAt(1), 2);
		assertEquals(arrayList.getItemAt(2), 3);
		assertEquals(arrayList.getItemAt(3), 4);
		assertEquals(arrayList.getItemAt(4), 5);
	}

	[Test]
	public function cloningOfArrayCollection():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		const arrayCollection:ArrayCollection = clone.arrayCollection;

		assertNotNull(arrayCollection);
		assertFalse(clone.arrayCollection == compositeCloneableClass.arrayCollection);
		assertEquals(arrayCollection.length, 5);
		assertEquals(arrayCollection.getItemAt(0), 1);
		assertEquals(arrayCollection.getItemAt(1), 2);
		assertEquals(arrayCollection.getItemAt(2), 3);
		assertEquals(arrayCollection.getItemAt(3), 4);
		assertEquals(arrayCollection.getItemAt(4), 5);
	}

	[Test]
	public function cloningOfCloneableProperty():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		const cloneable:CloneableClass = clone.cloneable;

		assertNotNull(cloneable);
		assertThat(cloneable, isA(CloneableClass));
		assertEquals(cloneable.property1, "property1 value");
		assertEquals(cloneable.writableField1, "writableField1 value");
		assertThat(cloneable, not(compositeCloneableClass.cloneable));
	}
}
}

Test for cloning of property with type CloneableClass in CompositeCloneableClass.


package dolly {
import dolly.core.dolly_internal;

import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;
import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertNotNull;
import org.flexunit.asserts.assertNull;

use namespace dolly_internal;

public class ClonerTest {

	private var classMarkedAsCloneable:ClassLevelCloneable;
	private var classWithSomeCloneableFields:PropertyLevelCloneable;
	private var classMarkedAsCloneableType:Type;
	private var classWithSomeCloneableFieldsType:Type;

	[Before]
	public function before():void {
		classMarkedAsCloneable = new ClassLevelCloneable();
		classMarkedAsCloneable.property1 = "value 1";
		classMarkedAsCloneable.property2 = "value 2";
		classMarkedAsCloneable.property3 = "value 3";
		classMarkedAsCloneable.writableField = "value 4";

		classWithSomeCloneableFields = new PropertyLevelCloneable();
		classWithSomeCloneableFields.property1 = "value 1";
		classWithSomeCloneableFields.property2 = "value 2";
		classWithSomeCloneableFields.property3 = "value 3";
		classWithSomeCloneableFields.writableField = "value 4";

		classMarkedAsCloneableType = Type.forInstance(classMarkedAsCloneable);
		classWithSomeCloneableFieldsType = Type.forInstance(classWithSomeCloneableFields);
	}

	[After]
	public function after():void {
		classMarkedAsCloneable = null;
		classWithSomeCloneableFields = null;
		classMarkedAsCloneableType = null;
		classWithSomeCloneableFieldsType = null;
	}

	[Test]
	public function testGetCloneableFieldsForType():void {
		var cloneableFields:Vector.<Field> = Cloner.getCloneableFieldsForType(classMarkedAsCloneableType);

		assertNotNull(cloneableFields);
		assertEquals(4, cloneableFields.length);

		cloneableFields = Cloner.getCloneableFieldsForType(classWithSomeCloneableFieldsType);

		assertNotNull(cloneableFields);
		assertEquals(3, cloneableFields.length);
	}

	[Test]
	public function testCloneWithClassLevelMetadata():void {
		const clone:ClassLevelCloneable = Cloner.clone(classMarkedAsCloneable) as ClassLevelCloneable;

		assertNotNull(clone);
		assertNotNull(clone.property1);
		assertEquals(clone.property1, classMarkedAsCloneable.property1);
		assertNotNull(clone.property2);
		assertEquals(clone.property2, classMarkedAsCloneable.property2);
		assertNotNull(clone.property3);
		assertEquals(clone.property3, classMarkedAsCloneable.property3);
		assertNotNull(clone.writableField);
		assertEquals(clone.writableField, classMarkedAsCloneable.writableField);
	}

	[Test]
	public function testCloneWithPropertyLevelMetadata():void {
		const clone:PropertyLevelCloneable = Cloner.clone(
				classWithSomeCloneableFields
		) as PropertyLevelCloneable;

		assertNotNull(clone);
		assertNull(clone.property1);
		assertNotNull(clone.property2);
		assertEquals(clone.property2, classWithSomeCloneableFields.property2);
		assertNotNull(clone.property3);
		assertEquals(clone.property3, classWithSomeCloneableFields.property3);
		assertNotNull(clone.writableField);
		assertEquals(clone.writableField, classWithSomeCloneableFields.writableField);
	}
}
}

package dolly {
import dolly.core.dolly_internal;

import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;
import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertNotNull;
import org.flexunit.asserts.assertNull;

use namespace dolly_internal;

public class ClonerTest {

	private var classLevelCloneable:ClassLevelCloneable;
	private var classLevelCloneableType:Type;

	private var propertyLevelCloneable:PropertyLevelCloneable;
	private var propertyLevelCloneableType:Type;

	[Before]
	public function before():void {
		classLevelCloneable = new ClassLevelCloneable();
		classLevelCloneable.property1 = "value 1";
		classLevelCloneable.property2 = "value 2";
		classLevelCloneable.property3 = "value 3";
		classLevelCloneable.writableField = "value 4";

		propertyLevelCloneable = new PropertyLevelCloneable();
		propertyLevelCloneable.property1 = "value 1";
		propertyLevelCloneable.property2 = "value 2";
		propertyLevelCloneable.property3 = "value 3";
		propertyLevelCloneable.writableField = "value 4";

		classLevelCloneableType = Type.forInstance(classLevelCloneable);
		propertyLevelCloneableType = Type.forInstance(propertyLevelCloneable);
	}

	[After]
	public function after():void {
		classLevelCloneable = null;
		propertyLevelCloneable = null;
		classLevelCloneableType = null;
		propertyLevelCloneableType = null;
	}

	[Test]
	public function testGetCloneableFieldsForType():void {
		var cloneableFields:Vector.<Field> = Cloner.getCloneableFieldsForType(classLevelCloneableType);

		assertNotNull(cloneableFields);
		assertEquals(4, cloneableFields.length);

		cloneableFields = Cloner.getCloneableFieldsForType(propertyLevelCloneableType);

		assertNotNull(cloneableFields);
		assertEquals(3, cloneableFields.length);
	}

	[Test]
	public function testCloneWithClassLevelMetadata():void {
		const clone:ClassLevelCloneable = Cloner.clone(classLevelCloneable) as ClassLevelCloneable;

		assertNotNull(clone);
		assertNotNull(clone.property1);
		assertEquals(clone.property1, classLevelCloneable.property1);
		assertNotNull(clone.property2);
		assertEquals(clone.property2, classLevelCloneable.property2);
		assertNotNull(clone.property3);
		assertEquals(clone.property3, classLevelCloneable.property3);
		assertNotNull(clone.writableField);
		assertEquals(clone.writableField, classLevelCloneable.writableField);
	}

	[Test]
	public function testCloneWithPropertyLevelMetadata():void {
		const clone:PropertyLevelCloneable = Cloner.clone(
				propertyLevelCloneable
		) as PropertyLevelCloneable;

		assertNotNull(clone);
		assertNull(clone.property1);
		assertNotNull(clone.property2);
		assertEquals(clone.property2, propertyLevelCloneable.property2);
		assertNotNull(clone.property3);
		assertEquals(clone.property3, propertyLevelCloneable.property3);
		assertNotNull(clone.writableField);
		assertEquals(clone.writableField, propertyLevelCloneable.writableField);
	}
}
}

Rename properties in test class.

Rename properties in test class.