You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by hn...@apache.org on 2010/10/04 18:21:18 UTC

svn commit: r1004309 [1/2] - in /shindig/trunk/extras/src/main/javascript/features-extras: ./ org.openajax.hub-2.0.3/ org.openajax.hub-2.0.4/ org.openajax.hub-2.0.5/ pubsub-2/

Author: hnguy
Date: Mon Oct  4 16:21:18 2010
New Revision: 1004309

URL: http://svn.apache.org/viewvc?rev=1004309&view=rev
Log:
SHINDIG-1438 - Patch from Han Nguyen - upgrade OpenAjaxHub from v2.0.4 to v2.0.5 for pubsub-2 gadgets refresh error.

Added:
    shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/
    shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/OpenAjax-mashup.js
    shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/crypto.js
    shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/feature.xml
    shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/iframe.js
Removed:
    shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.3/
    shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.4/
Modified:
    shindig/trunk/extras/src/main/javascript/features-extras/features.txt
    shindig/trunk/extras/src/main/javascript/features-extras/pubsub-2/feature.xml

Modified: shindig/trunk/extras/src/main/javascript/features-extras/features.txt
URL: http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/features.txt?rev=1004309&r1=1004308&r2=1004309&view=diff
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/features.txt (original)
+++ shindig/trunk/extras/src/main/javascript/features-extras/features.txt Mon Oct  4 16:21:18 2010
@@ -20,4 +20,4 @@ features-extras/org.jquery.core-1.4.2/fe
 features-extras/wave/feature.xml
 features-extras/opensocial-payment/feature.xml
 features-extras/pubsub-2/feature.xml
-features-extras/org.openajax.hub-2.0.4/feature.xml
+features-extras/org.openajax.hub-2.0.5/feature.xml

Added: shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/OpenAjax-mashup.js
URL: http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/OpenAjax-mashup.js?rev=1004309&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/OpenAjax-mashup.js (added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/OpenAjax-mashup.js Mon Oct  4 16:21:18 2010
@@ -0,0 +1,1357 @@
+/*******************************************************************************
+ * OpenAjax-mashup.js
+ *
+ * Reference implementation of the OpenAjax Hub, as specified by OpenAjax Alliance.
+ * Specification is under development at: 
+ *
+ *   http://www.openajax.org/member/wiki/OpenAjax_Hub_Specification
+ *
+ * Copyright 2006-2009 OpenAjax Alliance
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+var OpenAjax = OpenAjax || {};
+
+if ( !OpenAjax.hub ) {  // prevent re-definition of the OpenAjax.hub object
+
+OpenAjax.hub = function() {
+    var libs = {};
+    var ooh = "org.openajax.hub.";
+
+    return /** @scope OpenAjax.hub */ {
+        implementer: "http://openajax.org",
+        implVersion: "2.0.5",
+        specVersion: "2.0",
+        implExtraData: {},
+        libraries: libs,
+    
+        registerLibrary: function(prefix, nsURL, version, extra) {
+            libs[prefix] = {
+                prefix: prefix,
+                namespaceURI: nsURL,
+                version: version,
+                extraData: extra 
+            };
+            this.publish(ooh+"registerLibrary", libs[prefix]);
+        },
+        
+        unregisterLibrary: function(prefix) {
+            this.publish(ooh+"unregisterLibrary", libs[prefix]);
+            delete libs[prefix];
+        }
+    };
+}();
+
+/**
+ * Error
+ * 
+ * Standard Error names used when the standard functions need to throw Errors.
+ */
+OpenAjax.hub.Error = {
+    // Either a required argument is missing or an invalid argument was provided
+    BadParameters: "OpenAjax.hub.Error.BadParameters",
+    // The specified hub has been disconnected and cannot perform the requested
+    // operation:
+    Disconnected: "OpenAjax.hub.Error.Disconnected",
+    // Container with specified ID already exists:
+    Duplicate: "OpenAjax.hub.Error.Duplicate",
+    // The specified ManagedHub has no such Container (or it has been removed)
+    NoContainer: "OpenAjax.hub.Error.NoContainer",
+    // The specified ManagedHub or Container has no such subscription
+    NoSubscription: "OpenAjax.hub.Error.NoSubscription",
+    // Permission denied by manager's security policy
+    NotAllowed: "OpenAjax.hub.Error.NotAllowed",
+    // Wrong communications protocol identifier provided by Container or HubClient
+    WrongProtocol: "OpenAjax.hub.Error.WrongProtocol",
+    // A 'tunnelURI' param was specified, but current browser does not support security features
+    IncompatBrowser: "OpenAjax.hub.Error.IncompatBrowser"
+};
+
+/**
+ * SecurityAlert
+ * 
+ * Standard codes used when attempted security violations are detected. Unlike
+ * Errors, these codes are not thrown as exceptions but rather passed into the 
+ * SecurityAlertHandler function registered with the Hub instance.
+ */
+OpenAjax.hub.SecurityAlert = {
+    // Container did not load (possible frame phishing attack)
+    LoadTimeout: "OpenAjax.hub.SecurityAlert.LoadTimeout",
+    // Hub suspects a frame phishing attack against the specified container
+    FramePhish: "OpenAjax.hub.SecurityAlert.FramePhish",
+    // Hub detected a message forgery that purports to come to a specified
+    // container
+    ForgedMsg: "OpenAjax.hub.SecurityAlert.ForgedMsg"
+};
+
+/**
+ * Debugging Help
+ *
+ * OpenAjax.hub.enableDebug
+ *
+ *      If OpenAjax.hub.enableDebug is set to true, then the "debugger" keyword
+ *      will get hit whenever a user callback throws an exception, thereby
+ *      bringing up the JavaScript debugger.
+ */
+OpenAjax.hub._debugger = function() {
+//    if ( OpenAjax.hub.enableDebug ) debugger; // REMOVE ON BUILD
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Hub interface
+ * 
+ * Hub is implemented on the manager side by ManagedHub and on the client side
+ * by ClientHub.
+ */
+//OpenAjax.hub.Hub = function() {}
+
+/**
+ * Subscribe to a topic.
+ *
+ * @param {String} topic
+ *     A valid topic string. MAY include wildcards.
+ * @param {Function} onData   
+ *     Callback function that is invoked whenever an event is 
+ *     published on the topic
+ * @param {Object} [scope]
+ *     When onData callback or onComplete callback is invoked,
+ *     the JavaScript "this" keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ * @param {Function} [onComplete]
+ *     Invoked to tell the client application whether the 
+ *     subscribe operation succeeded or failed. 
+ * @param {*} [subscriberData]
+ *     Client application provides this data, which is handed
+ *     back to the client application in the subscriberData
+ *     parameter of the onData callback function.
+ * 
+ * @returns subscriptionID
+ *     Identifier representing the subscription. This identifier is an 
+ *     arbitrary ID string that is unique within this Hub instance
+ * @type {String}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic is invalid (e.g. contains an empty token)
+ */
+//OpenAjax.hub.Hub.prototype.subscribe = function( topic, onData, scope, onComplete, subscriberData ) {}
+
+/**
+ * Publish an event on a topic
+ *
+ * @param {String} topic
+ *     A valid topic string. MUST NOT include wildcards.
+ * @param {*} data
+ *     Valid publishable data. To be portable across different
+ *     Container implementations, this value SHOULD be serializable
+ *     as JSON.
+ *     
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic cannot be published (e.g. contains 
+ *     wildcards or empty tokens) or if the data cannot be published (e.g. cannot be serialized as JSON)
+ */
+//OpenAjax.hub.Hub.prototype.publish = function( topic, data ) {}
+
+/**
+ * Unsubscribe from a subscription
+ *
+ * @param {String} subscriptionID
+ *     A subscriptionID returned by Hub.subscribe()
+ * @param {Function} [onComplete]
+ *     Callback function invoked when unsubscribe completes
+ * @param {Object} [scope]
+ *     When onComplete callback function is invoked, the JavaScript "this"
+ *     keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ *     
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if no such subscription is found
+ */
+//OpenAjax.hub.Hub.prototype.unsubscribe = function( subscriptionID, onComplete, scope ) {}
+
+/**
+ * Return true if this Hub instance is in the Connected state.
+ * Else returns false.
+ * 
+ * This function can be called even if the Hub is not in a CONNECTED state.
+ * 
+ * @returns Boolean
+ * @type {Boolean}
+ */
+//OpenAjax.hub.Hub.prototype.isConnected = function() {}
+
+/**
+ * Returns the scope associated with this Hub instance and which will be used
+ * with callback functions.
+ * 
+ * This function can be called even if the Hub is not in a CONNECTED state.
+ * 
+ * @returns scope object
+ * @type {Object}
+ */
+//OpenAjax.hub.Hub.prototype.getScope = function() {}
+
+/**
+ * Returns the subscriberData parameter that was provided when 
+ * Hub.subscribe was called.
+ *
+ * @param {String} subscriptionID
+ *     The subscriberID of a subscription
+ * 
+ * @returns subscriberData
+ * @type {*}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if there is no such subscription
+ */
+//OpenAjax.hub.Hub.prototype.getSubscriberData = function(subscriptionID) {}
+
+/**
+ * Returns the scope associated with a specified subscription.  This scope will
+ * be used when invoking the 'onData' callback supplied to Hub.subscribe().
+ *
+ * @param {String} subscriberID
+ *     The subscriberID of a subscription
+ * 
+ * @returns scope
+ * @type {*}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if there is no such subscription
+ */
+//OpenAjax.hub.Hub.prototype.getSubscriberScope = function(subscriberID) {}
+
+/**
+ * Returns the params object associated with this Hub instance.
+ *
+ * @returns params
+ *     The params object associated with this Hub instance
+ * @type {Object}
+ */
+//OpenAjax.hub.Hub.prototype.getParameters = function() {}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * HubClient interface 
+ * 
+ * Extends Hub interface.
+ * 
+ * A HubClient implementation is typically specific to a particular 
+ * implementation of Container.
+ */
+
+/**
+ * Create a new HubClient. All HubClient constructors MUST have this 
+ * signature.
+ * @constructor
+ * 
+ * @param {Object} params 
+ *    Parameters used to instantiate the HubClient.
+ *    Once the constructor is called, the params object belongs to the
+ *    HubClient. The caller MUST not modify it.
+ *    Implementations of HubClient may specify additional properties
+ *    for the params object, besides those identified below. 
+ * 
+ * @param {Function} params.HubClient.onSecurityAlert
+ *     Called when an attempted security breach is thwarted
+ * @param {Object} [params.HubClient.scope]
+ *     Whenever one of the HubClient's callback functions is called,
+ *     references to "this" in the callback will refer to the scope object.
+ *     If not provided, the default is window.
+ * @param {Function} [params.HubClient.log]
+ *     Optional logger function. Would be used to log to console.log or
+ *     equivalent. 
+ *     
+ * @throws {OpenAjax.hub.Error.BadParameters} if any of the required
+ *     parameters is missing, or if a parameter value is invalid in 
+ *     some way.
+ */
+//OpenAjax.hub.HubClient = function( params ) {}
+
+/**
+ * Requests a connection to the ManagedHub, via the Container
+ * associated with this HubClient.
+ * 
+ * If the Container accepts the connection request, the HubClient's 
+ * state is set to CONNECTED and the HubClient invokes the 
+ * onComplete callback function.
+ * 
+ * If the Container refuses the connection request, the HubClient
+ * invokes the onComplete callback function with an error code. 
+ * The error code might, for example, indicate that the Container 
+ * is being destroyed.
+ * 
+ * In most implementations, this function operates asynchronously, 
+ * so the onComplete callback function is the only reliable way to
+ * determine when this function completes and whether it has succeeded
+ * or failed.
+ * 
+ * A client application may call HubClient.disconnect and then call
+ * HubClient.connect.
+ * 
+ * @param {Function} [onComplete]
+ *     Callback function to call when this operation completes.
+ * @param {Object} [scope]  
+ *     When the onComplete function is invoked, the JavaScript "this"
+ *     keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ *
+ * @throws {OpenAjax.hub.Error.Duplicate} if the HubClient is already connected
+ */
+//OpenAjax.hub.HubClient.prototype.connect = function( onComplete, scope ) {}
+
+/**
+ * Disconnect from the ManagedHub
+ * 
+ * Disconnect immediately:
+ * 
+ * 1. Sets the HubClient's state to DISCONNECTED.
+ * 2. Causes the HubClient to send a Disconnect request to the 
+ * 		associated Container. 
+ * 3. Ensures that the client application will receive no more
+ * 		onData or onComplete callbacks associated with this 
+ * 		connection, except for the disconnect function's own
+ * 		onComplete callback.
+ * 4. Automatically destroys all of the HubClient's subscriptions.
+ *
+ * In most implementations, this function operates asynchronously, 
+ * so the onComplete callback function is the only reliable way to
+ * determine when this function completes and whether it has succeeded
+ * or failed.
+ * 
+ * A client application is allowed to call HubClient.disconnect and 
+ * then call HubClient.connect.
+ * 	
+ * @param {Function} [onComplete]
+ *     Callback function to call when this operation completes.
+ * @param {Object} [scope]  
+ *     When the onComplete function is invoked, the JavaScript "this"
+ *     keyword refers to the scope object.
+ *     If no scope is provided, default is window.
+ *
+ * @throws {OpenAjax.hub.Error.Disconnected} if the HubClient is already
+ *     disconnected
+ */
+//OpenAjax.hub.HubClient.prototype.disconnect = function( onComplete, scope ) {}
+
+/**
+ * If DISCONNECTED: Returns null
+ * If CONNECTED: Returns the origin associated with the window containing the
+ * Container associated with this HubClient instance. The origin has the format
+ *  
+ * [protocol]://[host]
+ * 
+ * where:
+ * 
+ * [protocol] is "http" or "https"
+ * [host] is the hostname of the partner page.
+ * 
+ * @returns Partner's origin
+ * @type {String}
+ */
+//OpenAjax.hub.HubClient.prototype.getPartnerOrigin = function() {}
+
+/**
+ * Returns the client ID of this HubClient
+ *
+ * @returns clientID
+ * @type {String}
+ */
+//OpenAjax.hub.HubClient.prototype.getClientID = function() {}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * OpenAjax.hub.ManagedHub
+ *
+ * Managed hub API for the manager application and for Containers. 
+ * 
+ * Implements OpenAjax.hub.Hub.
+ */
+
+/**
+ * Create a new ManagedHub instance
+ * @constructor
+ *     
+ * This constructor automatically sets the ManagedHub's state to
+ * CONNECTED.
+ * 
+ * @param {Object} params
+ *     Parameters used to instantiate the ManagedHub.
+ *     Once the constructor is called, the params object belongs exclusively to
+ *     the ManagedHub. The caller MUST not modify it.
+ *     
+ * The params object may contain the following properties:
+ * 
+ * @param {Function} params.onPublish
+ *     Callback function that is invoked whenever a 
+ *     data value published by a Container is about
+ *     to be delivered to some (possibly the same) Container.
+ *     This callback function implements a security policy;
+ *     it returns true if the delivery of the data is
+ *     permitted and false if permission is denied.
+ * @param {Function} params.onSubscribe
+ *     Called whenever a Container tries to subscribe
+ *     on behalf of its client.
+ *     This callback function implements a security policy;
+ *     it returns true if the subscription is permitted 
+ *     and false if permission is denied.
+ * @param {Function} [params.onUnsubscribe]
+ *     Called whenever a Container unsubscribes on behalf of its client. 
+ *     Unlike the other callbacks, onUnsubscribe is intended only for 
+ *     informative purposes, and is not used to implement a security
+ *     policy.
+ * @param {Object} [params.scope]
+ *     Whenever one of the ManagedHub's callback functions is called,
+ *     references to the JavaScript "this" keyword in the callback 
+ *     function refer to this scope object
+ *     If no scope is provided, default is window.
+ * @param {Function} [params.log]  Optional logger function. Would
+ *     be used to log to console.log or equivalent.
+ * 
+ * @throws {OpenAjax.hub.Error.BadParameters} if any of the required
+ *     parameters are missing
+ */
+OpenAjax.hub.ManagedHub = function( params )
+{
+    if ( ! params || ! params.onPublish || ! params.onSubscribe )
+        throw new Error( OpenAjax.hub.Error.BadParameters );
+    
+    this._p = params;
+    this._onUnsubscribe = params.onUnsubscribe ? params.onUnsubscribe : null;
+    this._scope = params.scope || window;
+
+    if ( params.log ) {
+        var that = this;
+        this._log = function( msg ) {
+            try {
+                params.log.call( that._scope, "ManagedHub: " + msg );
+            } catch( e ) {
+                OpenAjax.hub._debugger();
+            }
+        };
+    } else {
+        this._log = function() {};
+    }
+
+    this._subscriptions = { c:{}, s:null };
+    this._containers = {};
+
+    // Sequence # used to create IDs that are unique within this hub
+    this._seq = 0;
+
+    this._active = true;
+    
+    this._isPublishing = false;
+    this._pubQ = [];
+}
+
+/**
+ * Subscribe to a topic on behalf of a Container. Called only by 
+ * Container implementations, NOT by manager applications.
+ * 
+ * This function:
+ * 1. Checks with the ManagedHub's onSubscribe security policy
+ *    to determine whether this Container is allowed to subscribe 
+ *    to this topic.
+ * 2. If the subscribe operation is permitted, subscribes to the
+ *    topic and returns the ManagedHub's subscription ID for this
+ *    subscription. 
+ * 3. If the subscribe operation is not permitted, throws
+ *    OpenAjax.hub.Error.NotAllowed.
+ * 
+ * When data is published on the topic, the ManagedHub's 
+ * onPublish security policy will be invoked to ensure that
+ * this Container is permitted to receive the published data.
+ * If the Container is allowed to receive the data, then the
+ * Container's sendToClient function will be invoked.
+ * 
+ * When a Container needs to create a subscription on behalf of
+ * its client, the Container MUST use this function to create
+ * the subscription.
+ * 
+ * @param {OpenAjax.hub.Container} container  
+ *     A Container
+ * @param {String} topic 
+ *     A valid topic
+ * @param {String} containerSubID  
+ *     Arbitrary string ID that the Container uses to 
+ *     represent the subscription. Must be unique within the 
+ *     context of the Container
+ *
+ * @returns managerSubID  
+ *     Arbitrary string ID that this ManagedHub uses to 
+ *     represent the subscription. Will be unique within the 
+ *     context of this ManagedHub
+ * @type {String}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this.isConnected() returns false
+ * @throws {OpenAjax.hub.Error.NotAllowed} if subscription request is denied by the onSubscribe security policy
+ * @throws {OpenAjax.hub.Error.BadParameters} if one of the parameters, e.g. the topic, is invalid
+ */
+OpenAjax.hub.ManagedHub.prototype.subscribeForClient = function( container, topic, containerSubID )
+{
+    this._assertConn();
+    // check subscribe permission
+    if ( this._invokeOnSubscribe( topic, container ) ) {
+        // return ManagedHub's subscriptionID for this subscription
+        return this._subscribe( topic, this._sendToClient, this, { c: container, sid: containerSubID } );
+    }
+    throw new Error(OpenAjax.hub.Error.NotAllowed);
+}
+
+/**
+ * Unsubscribe from a subscription on behalf of a Container. Called only by 
+ * Container implementations, NOT by manager application code.
+ * 
+ * This function:
+ * 1. Destroys the specified subscription
+ * 2. Calls the ManagedHub's onUnsubscribe callback function
+ * 
+ * This function can be called even if the ManagedHub is not in a CONNECTED state.
+ * 
+ * @param {OpenAjax.hub.Container} container  
+ *    container instance that is unsubscribing
+ * @param {String} managerSubID  
+ *    opaque ID of a subscription, returned by previous call to subscribeForClient()
+ * 
+ * @throws {OpenAjax.hub.Error.NoSubscription} if subscriptionID does not refer to a valid subscription
+ */
+OpenAjax.hub.ManagedHub.prototype.unsubscribeForClient = function( container, managerSubID )
+{
+    this._unsubscribe( managerSubID );
+    this._invokeOnUnsubscribe( container, managerSubID );
+}
+  
+/**
+ * Publish data on a topic on behalf of a Container. Called only by 
+ * Container implementations, NOT by manager application code.
+ *
+ * @param {OpenAjax.hub.Container} container
+ *      Container on whose behalf data should be published
+ * @param {String} topic
+ *      Valid topic string. Must NOT contain wildcards.
+ * @param {*} data
+ *      Valid publishable data. To be portable across different
+ *      Container implementations, this value SHOULD be serializable
+ *      as JSON.
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this.isConnected() returns false
+ * @throws {OpenAjax.hub.Error.BadParameters} if one of the parameters, e.g. the topic, is invalid
+ */
+OpenAjax.hub.ManagedHub.prototype.publishForClient = function( container, topic, data )
+{
+    this._assertConn();
+    this._publish( topic, data, container );
+}
+
+/**
+ * Destroy this ManagedHub
+ * 
+ * 1. Sets state to DISCONNECTED. All subsequent attempts to add containers,
+ *  publish or subscribe will throw the Disconnected error. We will
+ *  continue to allow "cleanup" operations such as removeContainer
+ *  and unsubscribe, as well as read-only operations such as 
+ *  isConnected
+ * 2. Remove all Containers associated with this ManagedHub
+ */
+OpenAjax.hub.ManagedHub.prototype.disconnect = function()
+{
+    this._active = false;
+    for (var c in this._containers) {
+        this.removeContainer( this._containers[c] );
+    }
+}
+
+/**
+ * Get a container belonging to this ManagedHub by its clientID, or null
+ * if this ManagedHub has no such container
+ * 
+ * This function can be called even if the ManagedHub is not in a CONNECTED state.
+ * 
+ * @param {String} containerId
+ *      Arbitrary string ID associated with the container
+ *
+ * @returns container associated with given ID
+ * @type {OpenAjax.hub.Container}
+ */
+OpenAjax.hub.ManagedHub.prototype.getContainer = function( containerId ) 
+{
+    var container = this._containers[containerId];
+    return container ? container : null;
+}
+
+/**
+ * Returns an array listing all containers belonging to this ManagedHub.
+ * The order of the Containers in this array is arbitrary.
+ * 
+ * This function can be called even if the ManagedHub is not in a CONNECTED state.
+ * 
+ * @returns container array
+ * @type {OpenAjax.hub.Container[]}
+ */
+OpenAjax.hub.ManagedHub.prototype.listContainers = function() 
+{
+    var res = [];
+    for (var c in this._containers) { 
+        res.push(this._containers[c]);
+    }
+    return res;
+}
+
+/**
+ * Add a container to this ManagedHub.
+ *
+ * This function should only be called by a Container constructor.
+ * 
+ * @param {OpenAjax.hub.Container} container
+ *      A Container to be added to this ManagedHub
+ * 
+ * @throws {OpenAjax.hub.Error.Duplicate} if there is already a Container
+ *      in this ManagedHub whose clientId is the same as that of container
+ * @throws {OpenAjax.hub.Error.Disconnected} if this.isConnected() returns false
+ */
+OpenAjax.hub.ManagedHub.prototype.addContainer = function( container ) 
+{ 
+    this._assertConn();
+    var containerId = container.getClientID();
+    if ( this._containers[containerId] ) {
+        throw new Error(OpenAjax.hub.Error.Duplicate);
+    }
+    this._containers[containerId] = container;
+}
+
+/**
+ * Remove a container from this ManagedHub immediately
+ * 
+ * This function can be called even if the ManagedHub is not in a CONNECTED state.
+ * 
+ * @param {OpenAjax.hub.Container} container  
+ *      A Container to be removed from this ManagedHub
+ *  
+ * @throws {OpenAjax.hub.Error.NoContainer}  if no such container is found
+ */
+OpenAjax.hub.ManagedHub.prototype.removeContainer = function( container )
+{
+    var containerId = container.getClientID();
+    if ( ! this._containers[ containerId ] ) {
+        throw new Error(OpenAjax.hub.Error.NoContainer);
+    }
+    container.remove();
+    delete this._containers[ containerId ];
+}
+
+    /*** OpenAjax.hub.Hub interface implementation ***/
+
+/**
+ * Subscribe to a topic.
+ * 
+ * This implementation of Hub.subscribe is synchronous. When subscribe 
+ * is called:
+ * 
+ * 1. The ManagedHub's onSubscribe callback is invoked. The 
+ * 		container parameter is null, because the manager application, 
+ * 		rather than a container, is subscribing.
+ * 2. If onSubscribe returns true, then the subscription is created.
+ * 3. The onComplete callback is invoked.
+ * 4. Then this function returns.
+ * 
+ * @param {String} topic
+ *     A valid topic string. MAY include wildcards.
+ * @param {Function} onData   
+ *     Callback function that is invoked whenever an event is 
+ *     published on the topic
+ * @param {Object} [scope]
+ *     When onData callback or onComplete callback is invoked,
+ *     the JavaScript "this" keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ * @param {Function} [onComplete]
+ *     Invoked to tell the client application whether the 
+ *     subscribe operation succeeded or failed. 
+ * @param {*} [subscriberData]
+ *     Client application provides this data, which is handed
+ *     back to the client application in the subscriberData
+ *     parameter of the onData and onComplete callback functions.
+ * 
+ * @returns subscriptionID
+ *     Identifier representing the subscription. This identifier is an 
+ *     arbitrary ID string that is unique within this Hub instance
+ * @type {String}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic is invalid (e.g. contains an empty token)
+ */
+OpenAjax.hub.ManagedHub.prototype.subscribe = function( topic, onData, scope, onComplete, subscriberData ) 
+{
+    this._assertConn();
+    this._assertSubTopic(topic);
+    if ( ! onData ) {
+        throw new Error( OpenAjax.hub.Error.BadParameters );
+    }
+    
+    scope = scope || window;
+    
+    // check subscribe permission
+    if ( ! this._invokeOnSubscribe( topic, null ) ) {
+        this._invokeOnComplete( onComplete, scope, null, false, OpenAjax.hub.Error.NotAllowed );
+        return;
+    }
+    
+    // on publish event, check publish permissions
+    var that = this;
+    function publishCB( topic, data, sd, pcont ) {
+        if ( that._invokeOnPublish( topic, data, pcont, null ) ) {
+            try {
+                onData.call( scope, topic, data, subscriberData );
+            } catch( e ) {
+                OpenAjax.hub._debugger();
+                that._log( "caught error from onData callback to Hub.subscribe(): " + e.message );
+            }
+        }
+    }
+    var subID = this._subscribe( topic, publishCB, scope, subscriberData );
+    this._invokeOnComplete( onComplete, scope, subID, true );
+    return subID;
+}
+
+/**
+ * Publish an event on a topic
+ *
+ * This implementation of Hub.publish is synchronous. When publish 
+ * is called:
+ * 
+ * 1. The target subscriptions are identified.
+ * 2. For each target subscription, the ManagedHub's onPublish
+ * 		callback is invoked. Data is only delivered to a target
+ * 		subscription if the onPublish callback returns true.
+ * 		The pcont parameter of the onPublish callback is null.
+ *      This is because the ManagedHub, rather than a container,
+ *      is publishing the data.
+ * 
+ * @param {String} topic
+ *     A valid topic string. MUST NOT include wildcards.
+ * @param {*} data
+ *     Valid publishable data. To be portable across different
+ *     Container implementations, this value SHOULD be serializable
+ *     as JSON.
+ *     
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic cannot be published (e.g. contains 
+ *     wildcards or empty tokens) or if the data cannot be published (e.g. cannot be serialized as JSON)
+ */
+OpenAjax.hub.ManagedHub.prototype.publish = function( topic, data ) 
+{
+    this._assertConn();
+    this._assertPubTopic(topic);
+    this._publish( topic, data, null );
+}
+
+/**
+ * Unsubscribe from a subscription
+ * 
+ * This implementation of Hub.unsubscribe is synchronous. When unsubscribe 
+ * is called:
+ * 
+ * 1. The subscription is destroyed.
+ * 2. The ManagedHub's onUnsubscribe callback is invoked, if there is one.
+ * 3. The onComplete callback is invoked.
+ * 4. Then this function returns.
+ * 
+ * @param {String} subscriptionID
+ *     A subscriptionID returned by Hub.subscribe()
+ * @param {Function} [onComplete]
+ *     Callback function invoked when unsubscribe completes
+ * @param {Object} [scope]
+ *     When onComplete callback function is invoked, the JavaScript "this"
+ *     keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ *     
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if no such subscription is found
+ */
+OpenAjax.hub.ManagedHub.prototype.unsubscribe = function( subscriptionID, onComplete, scope )
+{
+    this._assertConn();
+    if ( ! subscriptionID ) {
+        throw new Error( OpenAjax.hub.Error.BadParameters );
+    }
+    this._unsubscribe( subscriptionID );
+    this._invokeOnUnsubscribe( null, subscriptionID );
+    this._invokeOnComplete( onComplete, scope, subscriptionID, true );
+}
+
+/**
+ * Returns true if disconnect() has NOT been called on this ManagedHub, 
+ * else returns false
+ * 
+ * @returns Boolean
+ * @type {Boolean}
+ */
+OpenAjax.hub.ManagedHub.prototype.isConnected = function()
+{
+    return this._active;
+}
+
+/**
+* Returns the scope associated with this Hub instance and which will be used
+* with callback functions.
+* 
+* This function can be called even if the Hub is not in a CONNECTED state.
+* 
+* @returns scope object
+* @type {Object}
+ */
+OpenAjax.hub.ManagedHub.prototype.getScope = function()
+{
+    return this._scope;
+}
+
+/**
+ * Returns the subscriberData parameter that was provided when 
+ * Hub.subscribe was called.
+ *
+ * @param subscriberID
+ *     The subscriberID of a subscription
+ * 
+ * @returns subscriberData
+ * @type {*}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if there is no such subscription
+ */
+OpenAjax.hub.ManagedHub.prototype.getSubscriberData = function( subscriberID )
+{
+    this._assertConn();
+    var path = subscriberID.split(".");
+    var sid = path.pop();
+    var sub = this._getSubscriptionObject( this._subscriptions, path, 0, sid );
+    if ( sub ) 
+        return sub.data;
+    throw new Error( OpenAjax.hub.Error.NoSubscription );
+}
+
+/**
+ * Returns the scope associated with a specified subscription.  This scope will
+ * be used when invoking the 'onData' callback supplied to Hub.subscribe().
+ *
+ * @param subscriberID
+ *     The subscriberID of a subscription
+ * 
+ * @returns scope
+ * @type {*}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if there is no such subscription
+ */
+OpenAjax.hub.ManagedHub.prototype.getSubscriberScope = function( subscriberID )
+{
+    this._assertConn();
+    var path = subscriberID.split(".");
+    var sid = path.pop();
+    var sub = this._getSubscriptionObject( this._subscriptions, path, 0, sid );
+    if ( sub ) 
+        return sub.scope;
+    throw new Error( OpenAjax.hub.Error.NoSubscription );
+}
+
+/**
+ * Returns the params object associated with this Hub instance.
+ * Allows mix-in code to access parameters passed into constructor that created
+ * this Hub instance.
+ *
+ * @returns params  the params object associated with this Hub instance
+ * @type {Object}
+ */
+OpenAjax.hub.ManagedHub.prototype.getParameters = function()
+{
+    return this._p;
+}
+
+
+/* PRIVATE FUNCTIONS */
+
+/**
+ * Send a message to a container's client. 
+ * This is an OAH subscriber's data callback. It is private to ManagedHub
+ * and serves as an adapter between the OAH 1.0 API and Container.sendToClient.
+ * 
+ * @param {String} topic Topic on which data was published
+ * @param {Object} data  Data to be delivered to the client
+ * @param {Object} sd    Object containing properties 
+ *     c: container to which data must be sent
+ *     sid: subscription ID within that container
+ * @param {Object} pcont  Publishing container, or null if this data was
+ *      published by the manager
+ */
+OpenAjax.hub.ManagedHub.prototype._sendToClient = function(topic, data, sd, pcont) 
+{
+    if (!this.isConnected()) {
+        return;
+    }
+    if ( this._invokeOnPublish( topic, data, pcont, sd.c ) ) {
+        sd.c.sendToClient( topic, data, sd.sid );
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._assertConn = function() 
+{
+    if (!this.isConnected()) {
+        throw new Error(OpenAjax.hub.Error.Disconnected);
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._assertPubTopic = function(topic) 
+{
+    if ( !topic || topic === "" || (topic.indexOf("*") != -1) ||
+        (topic.indexOf("..") != -1) ||  (topic.charAt(0) == ".") ||
+        (topic.charAt(topic.length-1) == "."))
+    {
+        throw new Error(OpenAjax.hub.Error.BadParameters);
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._assertSubTopic = function(topic) 
+{
+    if ( ! topic ) {
+        throw new Error(OpenAjax.hub.Error.BadParameters);
+    }
+    var path = topic.split(".");
+    var len = path.length;
+    for (var i = 0; i < len; i++) {
+        var p = path[i];
+        if ((p === "") ||
+           ((p.indexOf("*") != -1) && (p != "*") && (p != "**"))) {
+            throw new Error(OpenAjax.hub.Error.BadParameters);
+        }
+        if ((p == "**") && (i < len - 1)) {
+            throw new Error(OpenAjax.hub.Error.BadParameters);
+        }
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._invokeOnComplete = function( func, scope, item, success, errorCode )
+{
+    if ( func ) { // onComplete is optional
+        try {
+            scope = scope || window;
+            func.call( scope, item, success, errorCode );
+        } catch( e ) {
+            OpenAjax.hub._debugger();
+            this._log( "caught error from onComplete callback: " + e.message );
+        }
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._invokeOnPublish = function( topic, data, pcont, scont )
+{
+    try {
+        return this._p.onPublish.call( this._scope, topic, data, pcont, scont );
+    } catch( e ) {
+        OpenAjax.hub._debugger();
+        this._log( "caught error from onPublish callback to constructor: " + e.message );
+    }
+    return false;
+}
+
+OpenAjax.hub.ManagedHub.prototype._invokeOnSubscribe = function( topic, container )
+{
+    try {
+        return this._p.onSubscribe.call( this._scope, topic, container );
+    } catch( e ) {
+        OpenAjax.hub._debugger();
+        this._log( "caught error from onSubscribe callback to constructor: " + e.message );
+    }
+    return false;
+}
+
+OpenAjax.hub.ManagedHub.prototype._invokeOnUnsubscribe = function( container, managerSubID )
+{
+    if ( this._onUnsubscribe ) {
+        var topic = managerSubID.slice( 0, managerSubID.lastIndexOf(".") );
+        try {
+            this._onUnsubscribe.call( this._scope, topic, container );
+        } catch( e ) {
+            OpenAjax.hub._debugger();
+            this._log( "caught error from onUnsubscribe callback to constructor: " + e.message );
+        }
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._subscribe = function( topic, onData, scope, subscriberData ) 
+{
+    var handle = topic + "." + this._seq;
+    var sub = { scope: scope, cb: onData, data: subscriberData, sid: this._seq++ };
+    var path = topic.split(".");
+    this._recursiveSubscribe( this._subscriptions, path, 0, sub );
+    return handle;
+}
+
+OpenAjax.hub.ManagedHub.prototype._recursiveSubscribe = function(tree, path, index, sub) 
+{
+    var token = path[index];
+    if (index == path.length) {
+        sub.next = tree.s;
+        tree.s = sub;
+    } else { 
+        if (typeof tree.c == "undefined") {
+             tree.c = {};
+         }
+        if (typeof tree.c[token] == "undefined") {
+            tree.c[token] = { c: {}, s: null }; 
+            this._recursiveSubscribe(tree.c[token], path, index + 1, sub);
+        } else {
+            this._recursiveSubscribe( tree.c[token], path, index + 1, sub);
+        }
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._publish = function( topic, data, pcont )
+{
+    // if we are currently handling a publish event, then queue this request
+    // and handle later, one by one
+    if ( this._isPublishing ) {
+        this._pubQ.push( { t: topic, d: data, p: pcont } );
+        return;
+    }
+    
+    this._safePublish( topic, data, pcont );
+    
+    while ( this._pubQ.length > 0 ) {
+        var pub = this._pubQ.shift();
+        this._safePublish( pub.t, pub.d, pub.p );
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._safePublish = function( topic, data, pcont )
+{
+    this._isPublishing = true;
+    var path = topic.split(".");
+    this._recursivePublish( this._subscriptions, path, 0, topic, data, pcont );
+    this._isPublishing = false;
+}
+
+OpenAjax.hub.ManagedHub.prototype._recursivePublish = function(tree, path, index, name, msg, pcont) 
+{
+    if (typeof tree != "undefined") {
+        var node;
+        if (index == path.length) {
+            node = tree;
+        } else {
+            this._recursivePublish(tree.c[path[index]], path, index + 1, name, msg, pcont);
+            this._recursivePublish(tree.c["*"], path, index + 1, name, msg, pcont);
+            node = tree.c["**"];
+        }
+        if (typeof node != "undefined") {
+            var sub = node.s;
+            while ( sub ) {
+                var sc = sub.scope;
+                var cb = sub.cb;
+                var d = sub.data;
+                if (typeof cb == "string") {
+                    // get a function object
+                    cb = sc[cb];
+                }
+                cb.call(sc, name, msg, d, pcont);
+                sub = sub.next;
+            }
+        }
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._unsubscribe = function( subscriptionID )
+{
+    var path = subscriptionID.split(".");
+    var sid = path.pop();
+    if ( ! this._recursiveUnsubscribe( this._subscriptions, path, 0, sid ) ) {
+        throw new Error( OpenAjax.hub.Error.NoSubscription );
+    }
+}
+
+/**
+ * @returns 'true' if properly unsubscribed; 'false' otherwise
+ */
+OpenAjax.hub.ManagedHub.prototype._recursiveUnsubscribe = function(tree, path, index, sid) 
+{
+    if ( typeof tree == "undefined" ) {
+        return false;
+    }
+    
+    if (index < path.length) {
+        var childNode = tree.c[path[index]];
+        if ( ! childNode ) {
+            return false;
+        }
+        this._recursiveUnsubscribe(childNode, path, index + 1, sid);
+        if ( ! childNode.s ) {
+            for (var x in childNode.c) {
+                return true;
+            }
+            delete tree.c[path[index]];    
+        }
+    } else {
+        var sub = tree.s;
+        var sub_prev = null;
+        var found = false;
+        while ( sub ) {
+            if ( sid == sub.sid ) {
+                found = true;
+                if ( sub == tree.s ) {
+                    tree.s = sub.next;
+                } else {
+                    sub_prev.next = sub.next;
+                }
+                break;
+            }
+            sub_prev = sub;
+            sub = sub.next;
+        }
+        if ( ! found ) {
+            return false;
+        }
+    }
+    
+    return true;
+}
+
+OpenAjax.hub.ManagedHub.prototype._getSubscriptionObject = function( tree, path, index, sid )
+{
+    if (typeof tree != "undefined") {
+        if (index < path.length) {
+            var childNode = tree.c[path[index]];
+            return this._getSubscriptionObject(childNode, path, index + 1, sid);
+        }
+
+        var sub = tree.s;
+        while ( sub ) {
+            if ( sid == sub.sid ) {
+                return sub;
+            }
+            sub = sub.next;
+        }
+    }
+    return null;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Container
+ * @constructor
+ * 
+ * Container represents an instance of a manager-side object that contains and
+ * communicates with a single client of the hub. The container might be an inline
+ * container, an iframe FIM container, or an iframe PostMessage container, or
+ * it might be an instance of some other implementation.
+ *
+ * @param {OpenAjax.hub.ManagedHub} hub
+ *    Managed Hub instance
+ * @param {String} clientID
+ *    A string ID that identifies a particular client of a Managed Hub. Unique
+ *    within the context of the ManagedHub.
+ * @param {Object} params  
+ *    Parameters used to instantiate the Container.
+ *    Once the constructor is called, the params object belongs exclusively to
+ *    the Container. The caller MUST not modify it.
+ *    Implementations of Container may specify additional properties
+ *    for the params object, besides those identified below.
+ *    The following params properties MUST be supported by all Container 
+ *    implementations:
+ * @param {Function} params.Container.onSecurityAlert
+ *    Called when an attempted security breach is thwarted.  Function is defined
+ *    as follows:  function(container, securityAlert)
+ * @param {Function} [params.Container.onConnect]
+ *    Called when the client connects to the Managed Hub.  Function is defined
+ *    as follows:  function(container)
+ * @param {Function} [params.Container.onDisconnect]
+ *    Called when the client disconnects from the Managed Hub.  Function is
+ *    defined as follows:  function(container)
+ * @param {Object} [params.Container.scope]
+ *    Whenever one of the Container's callback functions is called, references
+ *    to "this" in the callback will refer to the scope object. If no scope is
+ *    provided, default is window.
+ * @param {Function} [params.Container.log]
+ *    Optional logger function. Would be used to log to console.log or
+ *    equivalent. 
+ *
+ * @throws {OpenAjax.hub.Error.BadParameters}   if required params are not
+ *   present or null
+ * @throws {OpenAjax.hub.Error.Duplicate}   if a Container with this clientID
+ *   already exists in the given Managed Hub
+ * @throws {OpenAjax.hub.Error.Disconnected}   if ManagedHub is not connected
+ */
+//OpenAjax.hub.Container = function( hub, clientID, params ) {}
+
+/**
+ * Send a message to the client inside this container. This function MUST only
+ * be called by ManagedHub. 
+ * 
+ * @param {String} topic
+ *    The topic name for the published message
+ * @param {*} data
+ *    The payload. Can be any JSON-serializable value.
+ * @param {String} containerSubscriptionId
+ *    Container's ID for a subscription, from previous call to
+ *    subscribeForClient()
+ */
+//OpenAjax.hub.Container.prototype.sendToClient = function( topic, data, containerSubscriptionId ) {}
+
+/**
+ * Shut down a container. remove does all of the following:
+ * - disconnects container from HubClient
+ * - unsubscribes from all of its existing subscriptions in the ManagedHub
+ * 
+ * This function is only called by ManagedHub.removeContainer
+ * Calling this function does NOT cause the container's onDisconnect callback to
+ * be invoked.
+ */
+//OpenAjax.hub.Container.prototype.remove = function() {}
+
+/**
+ * Returns true if the given client is connected to the managed hub.
+ * Else returns false.
+ *
+ * @returns true if the client is connected to the managed hub
+ * @type boolean
+ */
+//OpenAjax.hub.Container.prototype.isConnected = function() {}
+
+/**
+ * Returns the clientID passed in when this Container was instantiated.
+ *
+ * @returns The clientID
+ * @type {String}  
+ */
+//OpenAjax.hub.Container.prototype.getClientID = function() {}
+
+/**
+ * If DISCONNECTED:
+ * Returns null
+ * If CONNECTED:
+ * Returns the origin associated with the window containing the HubClient
+ * associated with this Container instance. The origin has the format
+ *  
+ * [protocol]://[host]
+ * 
+ * where:
+ * 
+ * [protocol] is "http" or "https"
+ * [host] is the hostname of the partner page.
+ * 
+ * @returns Partner's origin
+ * @type {String}
+ */
+//OpenAjax.hub.Container.prototype.getPartnerOrigin = function() {}
+
+/**
+ * Returns the params object associated with this Container instance.
+ *
+ * @returns params
+ *    The params object associated with this Container instance
+ * @type {Object}
+ */
+//OpenAjax.hub.Container.prototype.getParameters = function() {}
+
+/**
+ * Returns the ManagedHub to which this Container belongs.
+ *
+ * @returns ManagedHub
+ *         The ManagedHub object associated with this Container instance
+ * @type {OpenAjax.hub.ManagedHub}
+ */
+//OpenAjax.hub.Container.prototype.getHub = function() {}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Unmanaged Hub
+ */
+
+/**
+ * OpenAjax.hub._hub is the default ManagedHub instance that we use to 
+ * provide OAH 1.0 behavior. 
+ */
+OpenAjax.hub._hub = new OpenAjax.hub.ManagedHub({ 
+    onSubscribe: function(topic, ctnr) { return true; },
+    onPublish: function(topic, data, pcont, scont) { return true; }
+});
+
+/**
+ * Subscribe to a topic.
+ *
+ * @param {String} topic
+ *     A valid topic string. MAY include wildcards.
+ * @param {Function|String} onData
+ *     Callback function that is invoked whenever an event is published on the
+ *     topic.  If 'onData' is a string, then it represents the name of a
+ *     function on the 'scope' object.
+ * @param {Object} [scope]
+ *     When onData callback is invoked,
+ *     the JavaScript "this" keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ * @param {*} [subscriberData]
+ *     Client application provides this data, which is handed
+ *     back to the client application in the subscriberData
+ *     parameter of the onData callback function.
+ * 
+ * @returns {String} Identifier representing the subscription.
+ * 
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic is invalid
+ *     (e.g.contains an empty token)
+ */
+OpenAjax.hub.subscribe = function(topic, onData, scope, subscriberData) 
+{
+    // resolve the 'onData' function if it is a string
+    if ( typeof onData === "string" ) {
+        scope = scope || window;
+        onData = scope[ onData ] || null;
+    }
+    
+    return OpenAjax.hub._hub.subscribe( topic, onData, scope, null, subscriberData );
+}
+
+/**
+ * Unsubscribe from a subscription.
+ *
+ * @param {String} subscriptionID
+ *     Subscription identifier returned by subscribe()
+ *     
+ * @throws {OpenAjax.hub.Error.NoSubscription} if no such subscription is found
+ */
+OpenAjax.hub.unsubscribe = function(subscriptionID) 
+{
+    return OpenAjax.hub._hub.unsubscribe( subscriptionID );
+}
+
+/**
+ * Publish an event on a topic.
+ *
+ * @param {String} topic
+ *     A valid topic string. MUST NOT include wildcards.
+ * @param {*} data
+ *     Valid publishable data.
+ *     
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic cannot be published
+ *     (e.g. contains wildcards or empty tokens)
+ */
+OpenAjax.hub.publish = function(topic, data) 
+{
+    OpenAjax.hub._hub.publish(topic, data);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Register the OpenAjax Hub itself as a library.
+OpenAjax.hub.registerLibrary("OpenAjax", "http://openajax.org/hub", "2.0", {});
+
+} // !OpenAjax.hub

Added: shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/crypto.js
URL: http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/crypto.js?rev=1004309&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/crypto.js (added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/crypto.js Mon Oct  4 16:21:18 2010
@@ -0,0 +1,244 @@
+/*
+
+        Copyright 2006-2009 OpenAjax Alliance
+
+        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.
+*/
+// SMASH.CRYPTO
+//
+// Small library containing some minimal crypto functionality for a
+// - a hash-function: SHA-1 (see FIPS PUB 180-2 for definition)
+//     BigEndianWord[5] <- smash.crypto.sha1( BigEndianWord[*] dataWA, int lenInBits)
+//
+// - a message authentication code (MAC): HMAC-SHA-1 (RFC2104/2202)
+//     BigEndianWord[5] <- smash.crypto.hmac_sha1(
+//                            BigEndianWord[3-16] keyWA, 
+//                            Ascii or Unicode string dataS,
+//		 		 		       int chrsz (8 for Asci/16 for Unicode)
+//
+// - pseudo-random number generator (PRNG): HMAC-SHA-1 in counter mode, following
+//   Barak & Halevi, An architecture for robust pseudo-random generation and applications to /dev/random, CCS 2005
+//     rngObj <- smash.crypto.newPRNG( String[>=12] seedS)
+//   where rngObj has methods
+//     addSeed(String seed)
+//     BigEndianWord[len] <- nextRandomOctets(int len)
+//     Base64-String[len] <- nextRandomB64Str(int len)
+//   Note: HMAC-SHA1 in counter-mode does not provide forward-security on corruption. 
+//         However, the PRNG state is kept inside a closure. So if somebody can break the closure, he probably could
+//         break a whole lot more and forward-security of the prng is not the highest of concerns anymore :-)
+
+if ( typeof OpenAjax._smash == 'undefined' ) { OpenAjax._smash = {}; }
+
+OpenAjax._smash.crypto = {
+
+  // Some utilities
+  // convert a string to an array of big-endian words
+  'strToWA': function (/* Ascii or Unicode string */ str, /* int 8 for Asci/16 for Unicode */ chrsz){
+    var bin = Array();
+    var mask = (1 << chrsz) - 1;
+    for(var i = 0; i < str.length * chrsz; i += chrsz)
+      bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
+    return bin;
+  },
+
+
+  // MAC
+  'hmac_sha1' : function(
+        /* BigEndianWord[3-16]*/             keyWA,
+       /* Ascii or Unicode string */       dataS,
+       /* int 8 for Asci/16 for Unicode */ chrsz)
+  {
+    // write our own hmac derived from paj's so we do not have to do constant key conversions and length checking ...
+    var ipad = Array(16), opad = Array(16);
+    for(var i = 0; i < 16; i++) {
+      ipad[i] = keyWA[i] ^ 0x36363636;
+      opad[i] = keyWA[i] ^ 0x5C5C5C5C;
+    }
+
+    var hash = this.sha1( ipad.concat(this.strToWA(dataS, chrsz)), 512 + dataS.length * chrsz);
+    return     this.sha1( opad.concat(hash), 512 + 160);
+  },
+
+
+  // PRNG factory method
+  // see below 'addSeed', 'nextRandomOctets' & 'nextRandomB64Octets' for public methods of returnd prng object
+  'newPRNG' : function (/* String[>=12] */ seedS) {
+    var that = this;
+
+    // parameter checking
+    // We cannot really verify entropy but obviously the string must have at least a minimal length to have enough entropy
+    // However, a 2^80 security seems ok, so we check only that at least 12 chars assuming somewhat random ASCII
+    if ( (typeof seedS != 'string') || (seedS.length < 12) ) {
+      alert("WARNING: Seed length too short ...");
+    }
+
+    // constants
+    var __refresh_keyWA = [ 0xA999, 0x3E36, 0x4706, 0x816A,
+    		 		 		     0x2571, 0x7850, 0xC26C, 0x9CD0,
+    		 		 		     0xBA3E, 0xD89D, 0x1233, 0x9525,
+    		 		 		     0xff3C, 0x1A83, 0xD491, 0xFF15 ]; // some random key for refresh ...
+
+    // internal state
+    var _keyWA = []; // BigEndianWord[5]
+    var _cnt = 0;  // int
+
+    function extract(seedS) {
+      return that.hmac_sha1(__refresh_keyWA, seedS, 8);
+    }
+
+    function refresh(seedS) {
+      // HMAC-SHA1 is not ideal, Rijndal 256bit block/key in CBC mode with fixed key might be better
+      // but to limit the primitives and given that we anyway have only limited entropy in practise
+      // this seems good enough
+      var uniformSeedWA = extract(seedS);
+      for(var i = 0; i < 5; i++) {
+        _keyWA[i] ^= uniformSeedWA[i];
+      }
+    }
+
+    // inital state seeding
+    refresh(seedS);
+
+    // public methods
+    return {
+      // Mix some additional seed into the PRNG state
+      'addSeed'         : function (/* String */ seed) {
+        // no parameter checking. Any added entropy should be fine ...
+        refresh(seed);
+      },
+
+
+      // Get an array of len random octets
+      'nextRandomOctets' : /* BigEndianWord[len] <- */ function (/* int */ len) {
+		 var randOctets = [];
+		 while (len > 0) {
+		   _cnt+=1;
+		   var nextBlock = that.hmac_sha1(_keyWA, (_cnt).toString(16), 8);
+		   for (i=0; (i < 20) & (len > 0); i++, len--) {
+		     randOctets.push( (nextBlock[i>>2] >> (i % 4) ) % 256);
+		   }
+		   // Note: if len was not a multiple 20, some random octets are ignored here but who cares ..
+		 }
+		 return randOctets;
+      },
+
+
+      // Get a random string of Base64-like (see below) chars of length len
+      // Note: there is a slightly non-standard Base64 with no padding and '-' and '_' for '+' and '/', respectively
+      'nextRandomB64Str' : /* Base64-String <- */ function (/* int */ len) {
+		 var b64StrMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+		 var randOctets = this.nextRandomOctets(len);
+		 var randB64Str = '';
+		 for (var i=0; i < len; i++) {
+		   randB64Str += b64StrMap.charAt(randOctets[i] & 0x3F);
+		 }
+        return randB64Str;
+      }
+
+    }
+  },
+
+
+  // Digest function:
+  // BigEndianWord[5] <- sha1( BigEndianWord[*] dataWA, int lenInBits)
+  'sha1' : function(){
+    // Note: all Section references below refer to FIPS 180-2.
+
+    // private utility functions
+
+    // - 32bit addition with wrap-around
+    var add_wa = function (x, y){
+      var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+      var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+      return (msw << 16) | (lsw & 0xFFFF);
+    }
+
+    // - 32bit rotatate left
+    var rol = function(num, cnt) {
+      return (num << cnt) | (num >>> (32 - cnt));
+    }
+
+    // - round-dependent function f_t from Section 4.1.1
+    function sha1_ft(t, b, c, d) {
+      if(t < 20) return (b & c) | ((~b) & d);
+      if(t < 40) return b ^ c ^ d;
+      if(t < 60) return (b & c) | (b & d) | (c & d);
+      return b ^ c ^ d;
+    }
+
+    // - round-dependent SHA-1 constants from Section 4.2.1
+    function sha1_kt(t) {
+      return (t < 20) ?  1518500249 :
+             (t < 40) ?  1859775393 :
+             (t < 60) ? -1894007588 :
+          /* (t < 80) */ -899497514 ;
+    }
+
+    // main algorithm. 
+    return function( /* BigEndianWord[*] */ dataWA, /* int */ lenInBits) {
+
+      // Section 6.1.1: Preprocessing
+      //-----------------------------
+      // 1. padding:  (see also Section 5.1.1)
+      //  - append one 1 followed by 0 bits filling up 448 bits of last (512bit) block
+      dataWA[lenInBits >> 5] |= 0x80 << (24 - lenInBits % 32);
+      //  - encode length in bits in last 64 bits
+      //    Note: we rely on javascript to zero file elements which are beyond last (partial) data-block
+      //    but before this length encoding!
+      dataWA[((lenInBits + 64 >> 9) << 4) + 15] = lenInBits;
+
+      // 2. 512bit blocks (actual split done ondemand later)
+      var W = Array(80);
+
+      // 3. initial hash using SHA-1 constants on page 13
+      var H0 =  1732584193;
+      var H1 = -271733879;
+      var H2 = -1732584194;
+      var H3 =  271733878;
+      var H4 = -1009589776;
+
+      // 6.1.2 SHA-1 Hash Computation
+      for(var i = 0; i < dataWA.length; i += 16) {
+        // 1. Message schedule, done below
+        // 2. init working variables
+        var a = H0; var b = H1; var c = H2; var d = H3; var e = H4;
+
+        // 3. round-functions
+        for(var j = 0; j < 80; j++)
+        {
+      		 // postponed step 2
+          W[j] = ( (j < 16) ? dataWA[i+j] : rol(W[j-3] ^ W[j-8] ^ W[j-14] ^ W[j-16], 1));
+
+          var T = add_wa( add_wa( rol(a, 5), sha1_ft(j, b, c, d)),
+                          add_wa( add_wa(e, W[j]), sha1_kt(j)) );
+          e = d;
+          d = c;
+          c = rol(b, 30);
+          b = a;
+          a = T;
+        }
+
+		 // 4. intermediate hash
+        H0 = add_wa(a, H0);
+        H1 = add_wa(b, H1);
+        H2 = add_wa(c, H2);
+        H3 = add_wa(d, H3);
+        H4 = add_wa(e, H4);
+      }
+
+      return Array(H0, H1, H2, H3, H4);
+    }
+  }()
+
+};

Added: shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/feature.xml
URL: http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/feature.xml?rev=1004309&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/feature.xml (added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/org.openajax.hub-2.0.5/feature.xml Mon Oct  4 16:21:18 2010
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations under the License.
+-->
+<feature>
+  <name>org.openajax.hub-2.0.5</name>
+  <dependency>rpc</dependency>
+  <gadget>
+    <script src="OpenAjax-mashup.js"/>
+    <script src="iframe.js"/>
+    <script src="crypto.js"/>
+  </gadget>
+  <container>
+    <script src="OpenAjax-mashup.js"/>
+    <script src="iframe.js"/>
+    <script src="crypto.js"/>
+  </container>
+</feature>