[asterisk-scf-commits] asterisk-scf/integration/ice-util-cpp.git branch "basecomponent" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Tue Jun 21 10:39:09 CDT 2011


branch "basecomponent" has been updated
       via  48ec22a79bae9c6613c8983be7c079b74fb45106 (commit)
      from  f1ba89aa404fe8e47887d8d9af2692187b9b9c44 (commit)

Summary of changes:
 include/AsteriskSCF/Component/Component.h          |  186 +++++
 include/AsteriskSCF/Component/TestContext.h        |   95 +++
 .../Discovery/LocatorRegistrationWrapper.h         |   44 +-
 .../AsteriskSCF/Replication/ReplicationContext.h   |   70 ++
 src/CMakeLists.txt                                 |    6 +
 src/Component/Component.cpp                        |  833 ++++++++++++++++++++
 src/Component/TestContext.cpp                      |  113 +++
 src/Replication/ReplicationContext.cpp             |   67 ++
 test/CMakeLists.txt                                |    1 +
 test/Component/.component-base-test.conf.swp       |  Bin 0 -> 12288 bytes
 test/Component/CMakeLists.txt                      |   25 +
 test/Component/ComponentTest.cpp                   |  287 +++++++
 test/Component/ComponentTestIf.ice                 |   55 ++
 test/Component/MockComponent.cpp                   |  173 ++++
 test/Component/component-base-test.conf            |   86 ++
 .../LocatorRegistrationTest.cpp                    |    4 +-
 16 files changed, 2034 insertions(+), 11 deletions(-)
 create mode 100644 include/AsteriskSCF/Component/Component.h
 create mode 100644 include/AsteriskSCF/Component/TestContext.h
 create mode 100644 include/AsteriskSCF/Replication/ReplicationContext.h
 create mode 100644 src/Component/Component.cpp
 create mode 100644 src/Component/TestContext.cpp
 create mode 100644 src/Replication/ReplicationContext.cpp
 create mode 100644 test/Component/.component-base-test.conf.swp
 create mode 100644 test/Component/CMakeLists.txt
 create mode 100644 test/Component/ComponentTest.cpp
 create mode 100644 test/Component/ComponentTestIf.ice
 create mode 100644 test/Component/MockComponent.cpp
 create mode 100644 test/Component/component-base-test.conf


- Log -----------------------------------------------------------------
commit 48ec22a79bae9c6613c8983be7c079b74fb45106
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Tue Jun 21 10:37:56 2011 -0500

    Component base class and test driver.

diff --git a/include/AsteriskSCF/Component/Component.h b/include/AsteriskSCF/Component/Component.h
new file mode 100644
index 0000000..2a6009f
--- /dev/null
+++ b/include/AsteriskSCF/Component/Component.h
@@ -0,0 +1,186 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#pragma once
+
+#include <Ice/Ice.h>
+#include <IceBox/IceBox.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/Replication/ReplicationContext.h>
+#include <AsteriskSCF/Component/TestContext.h>
+#include <AsteriskSCF/Discovery/LocatorRegistrationWrapper.h>
+#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
+#include <AsteriskSCF/System/Component/ReplicaIf.h>
+
+namespace AsteriskSCF
+{
+namespace Component
+{
+class ASTERISK_SCF_ICEBOX_EXPORT Component : public IceBox::Service
+{
+public:
+    Component(const AsteriskSCF::System::Logging::Logger& logger,
+              const std::string& componentDiscoveryCategory);
+
+    /////////////////////////////////////////////////////////////////////
+    // Support for ComponentService interface.
+    void suspended();
+    void resumed();
+    void shutdown();
+
+    /////////////////////////////////////////////////////////////////////
+    // Support for ComponentTest interface.
+    void setTestMode(const std::string& mode);
+    void setTestModeWithArgs(const std::string& mode,
+                                     const AsteriskSCF::System::Component::V1::ComponentTestParamSeq& args);
+    void clearTestModes();
+    void clearTestMode(const std::string& mode);
+
+    ////////////////////////////////
+    // Support for Replica control interface.
+    bool isActive();
+    void activated();
+    void standby();
+
+protected:
+   
+    void registerPrimaryService(const AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr& service);
+    void registerBackplaneService(const AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr& service);
+
+    /////////////////////////////////////////////////////////////////////
+    // Notification for some of 
+    // the component events.
+    virtual void onInitialize() {}
+    virtual void onSuspend() {}
+    virtual void onResume() {}
+    virtual void onStop() {}
+    virtual void onStart() {}
+    virtual void onActivated() {}
+    virtual void onStandby() {}
+
+    /////////////////////////////////////////////////////////////////////
+    // Every component must provded
+    // custom implementations. 
+    virtual void createReplicationStateListeners() = 0;
+
+    /** 
+     * Unregister as a listener to our state replicator. 
+     * A component in active mode doesn't neeed to listen to
+     * state replication data. 
+     */
+    virtual void stopListeningToStateReplicators() = 0;
+
+    /** 
+     * Register as a listener to our state replicator. 
+     * A component in standby mode will do this to monitor state changes
+     * being sent from an active component. 
+     */
+    virtual void listenToStateReplicators() = 0;
+
+    /////////////////////////////////////////////////////////////////////
+    // Operations called by the initialize method, which implements the
+    // Template Method pattern. 
+    virtual void createAdapters();
+    virtual void initReplicationContext();
+    virtual void initTestContext();
+    virtual void configureLogger();
+    virtual void createPrimaryServices() = 0;
+    virtual void createBackplaneServices();
+    virtual void activateAdapters();
+    virtual void initServiceLocatorProxies();
+    virtual void findRemoteServices() = 0;
+
+    /////////////////////////////////////////////////////////////////////
+    // Service locator interfaces
+    virtual void registerPrimaryServices() = 0;
+    void unregisterPrimaryServices();
+    void suspendPrimaryServices();
+    void unsuspendPrimaryServices();
+
+    virtual void registerBackplaneServices();
+    void unregisterBackplaneServices();
+    void suspendBackplaneServices();
+    void unsuspendBackplaneServices();
+
+    /////////////////////////////////////////////////////////////////////
+    // Accessors to state variables
+    AsteriskSCF::Replication::ReplicationContextPtr getReplicationContext() {return mReplicationContext;}
+    AsteriskSCF::Component::TestContextPtr getTestContext() {return mTestContext;}
+    std::string getComponentName() {return mComponentName;}
+    Ice::CommunicatorPtr getCommunicator() {return mCommunicator;}
+    Ice::StringSeq getArgs() {return mArgs;}
+    AsteriskSCF::Core::Discovery::V1::ServiceLocatorManagementPrx getServiceLocatorManagement() {return mServiceLocatorManagement;}
+    AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx  getServiceLocator() {return mServiceLocator;}
+    Ice::ObjectAdapterPtr getServiceAdapter() {return mServiceAdapter;}
+    Ice::ObjectAdapterPtr getBackplaneAdapter() {return mBackplaneAdapter;}
+    std::string getServiceLocatorManagementProperty();
+
+    // State data
+    AsteriskSCF::System::Logging::Logger mLogger;
+
+private:
+    void initialize();
+    void suspendService(bool shuttingDown);
+
+    /////////////////////////////////////////////////////////////////////
+    // Overrides for IceBox::Service
+    void start(const std::string& name, 
+               const Ice::CommunicatorPtr& communicator, 
+               const Ice::StringSeq& args);
+    void stop();
+
+    /////////////////////////////////////////////////////////////////////
+    // State data
+
+    bool mInitialized;
+    bool mRunning;
+    bool mPublishTestInterface;
+
+    std::string mComponentDiscoveryCategory;
+
+    std::string mComponentName;
+    Ice::CommunicatorPtr mCommunicator;
+    Ice::StringSeq mArgs;
+
+    AsteriskSCF::System::Component::V1::ComponentServicePtr mComponentService;
+    AsteriskSCF::System::Component::V1::ComponentServicePrx mComponentServicePrx;
+    AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr mComponentRegistration;
+
+    AsteriskSCF::System::Component::V1::ReplicaPtr mReplica;
+    AsteriskSCF::System::Component::V1::ReplicaPrx mReplicaPrx;
+    AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr mReplicaRegistration;
+
+    AsteriskSCF::System::Component::V1::ComponentTestPtr mComponentTest;
+    AsteriskSCF::System::Component::V1::ComponentTestPrx mComponentTestPrx;
+
+    AsteriskSCF::Replication::ReplicationContextPtr mReplicationContext;
+    AsteriskSCF::Component::TestContextPtr mTestContext;
+
+    Ice::ObjectAdapterPtr mServiceAdapter;
+    Ice::ObjectAdapterPtr mBackplaneAdapter;
+
+    AsteriskSCF::Core::Discovery::V1::ServiceLocatorManagementPrx mServiceLocatorManagement;
+    AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx mServiceLocator;
+
+    std::vector<AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr> mPrimaryServices;
+    std::vector<AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr> mBackplaneServices;
+};
+
+
+} // end Component
+} // end AsteriskSCF
diff --git a/include/AsteriskSCF/Component/TestContext.h b/include/AsteriskSCF/Component/TestContext.h
new file mode 100644
index 0000000..15564fd
--- /dev/null
+++ b/include/AsteriskSCF/Component/TestContext.h
@@ -0,0 +1,95 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
+
+namespace AsteriskSCF
+{
+namespace Component
+{
+class TestContextPriv;
+
+class InvalidTestMode : public std::exception
+{
+public:
+    InvalidTestMode(const std::string& mode)
+    {
+        mMsg = "Invalid Test Mode. Mode " + mode + " is not set.";
+    }
+
+    virtual const char* what() const throw()
+    {
+        return mMsg.c_str();
+    }
+
+private:
+    std::string mMsg;
+};
+
+/** 
+ * This class provides the component's classes with the context 
+ * needed for testing.
+ */
+class TestContext 
+{
+public:
+    TestContext() ;
+
+    /**
+     * Indicates whether a test mode with given name
+     * has been set. 
+     * @param mode The name of the mode to query.
+     */
+    bool hasTestMode(const std::string& mode);
+   
+    /** 
+     * Gets the paramters to for the test mode. 
+     * If the mode hasn't been set, will throw InvalidTestMode. 
+     */
+    AsteriskSCF::System::Component::V1::ComponentTestParamSeq 
+         getTestModeParams(const std::string& mode);
+
+    /**
+     * Sets a test mode. 
+     */
+    void setTestMode(const std::string& mode);
+    
+    /**
+     * Sets a current test mode with parameters. 
+     */
+    void setTestMode(const std::string& mode, 
+         const AsteriskSCF::System::Component::V1::ComponentTestParamSeq& params);
+
+    /**
+     * Clears a testing mode.
+     */
+    void clearTestMode(const std::string& mode);
+
+    /**
+     * Clears testing mode.
+     */
+    void clearAllTestModes();
+
+private:
+    boost::shared_ptr<TestContextPriv> mImpl;
+};
+typedef boost::shared_ptr<TestContext> TestContextPtr;
+
+} // end Component
+} // end AsteriskSCF
diff --git a/include/AsteriskSCF/Discovery/LocatorRegistrationWrapper.h b/include/AsteriskSCF/Discovery/LocatorRegistrationWrapper.h
index ca8e81a..ff4a061 100644
--- a/include/AsteriskSCF/Discovery/LocatorRegistrationWrapper.h
+++ b/include/AsteriskSCF/Discovery/LocatorRegistrationWrapper.h
@@ -33,7 +33,6 @@ namespace Discovery
  * TODO: It might be handy to add some "termination conditions" so it doesn't simply wait forever.
  *
  **/
-template <class T>   
 class LocatorRegistrationWrapper : public IceUtil::Shared
 {
 public:
@@ -42,10 +41,12 @@ public:
      * Normally, I avoid default args, but you can't really implement one constructor in terms of another
      * so it's less maintenance overhead to have the single constructor with the defaults.
      **/
-    LocatorRegistrationWrapper(const Ice::CommunicatorPtr& communicator, const std::string& proxyString,
-            const T& service, const std::string& name,
-            const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr& params, 
-            const std::string& comparatorGUID = "") :
+    LocatorRegistrationWrapper(const Ice::CommunicatorPtr& communicator, 
+                               const std::string& proxyString,
+                               const Ice::ObjectPrx& service, 
+                               const std::string& name,
+                               const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr& params, 
+                               const std::string& comparatorGUID = "") :
         mCommunicator(communicator),
         mProxyString(proxyString),
         mService(service),
@@ -97,6 +98,30 @@ public:
         mServiceManagement->unregister();
     }
 
+    void suspend()
+    {
+        {
+            IceUtil::Mutex::Lock lock(mLock);
+            if(!mServiceManagement)
+            {
+                return;
+            }
+        }
+        mServiceManagement->suspend();
+    }
+
+    void unsuspend()
+    {
+        {
+            IceUtil::Mutex::Lock lock(mLock);
+            if(!mServiceManagement)
+            {
+                return;
+            }
+        }
+        mServiceManagement->unsuspend();
+    }
+
 private:
 
     //
@@ -106,12 +131,13 @@ private:
     IceUtil::Mutex mLock;
     Ice::CommunicatorPtr mCommunicator;
     std::string mProxyString;
-    T mService;
+    Ice::ObjectPrx mService;
     std::string mName;
     AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr mParameters;
     AsteriskSCF::Core::Discovery::V1::ServiceManagementPrx mServiceManagement;
     std::string mComparatorGUID;
 };
+typedef IceUtil::Handle<LocatorRegistrationWrapper> LocatorRegistrationWrapperPtr;
 
 /**
 * This thread takes care of registering the registration wrapper instance if the service discovery components are
@@ -121,7 +147,7 @@ template <class T>
 class RegisterThread : public IceUtil::Thread
 {
 public:
-    RegisterThread(const IceUtil::Handle<LocatorRegistrationWrapper<T> >& registration,
+    RegisterThread(const IceUtil::Handle<LocatorRegistrationWrapper>& registration,
             const IceUtil::Time& retryInterval) :
         mRegistration(registration),
         mRetryInterval(retryInterval),
@@ -129,7 +155,7 @@ public:
     {
     }
 
-    RegisterThread(const IceUtil::Handle<LocatorRegistrationWrapper<T> >& registration) :
+    RegisterThread(const IceUtil::Handle<LocatorRegistrationWrapper>& registration) :
         mRegistration(registration),
         mRetryInterval(IceUtil::Time::seconds(15)),
         mStopped(false)
@@ -167,7 +193,7 @@ public:
 
 private:
     IceUtil::Monitor<IceUtil::Mutex> mMonitor;
-    IceUtil::Handle<LocatorRegistrationWrapper<T> > mRegistration;
+    IceUtil::Handle<LocatorRegistrationWrapper> mRegistration;
     IceUtil::Time mRetryInterval;
     bool mStopped;
 };
diff --git a/include/AsteriskSCF/Replication/ReplicationContext.h b/include/AsteriskSCF/Replication/ReplicationContext.h
new file mode 100644
index 0000000..eebe1ba
--- /dev/null
+++ b/include/AsteriskSCF/Replication/ReplicationContext.h
@@ -0,0 +1,70 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+namespace AsteriskSCF
+{
+namespace Replication
+{
+class ReplicationContextPriv;
+
+/** 
+ * This class provides the component with context
+ * related to state replication. 
+ */
+class ReplicationContext 
+{
+public:
+    ReplicationContext(bool componentIsActive, bool standalone);
+
+    /**
+     * Returns true if this component is active, non-standalone.
+     */
+    virtual bool isReplicating();
+
+    /**
+     * Indicates whether this component is in active (as opposed to standby) mode. 
+     */
+    bool isComponentActive();
+
+    /**
+     * If true, the component is in standalone mode. 
+     * @see isReplicating
+     */
+    bool isStandalone();
+
+    /**
+     * Changes this context to reflect active mode.
+     */
+    void setComponentActive();
+
+    /**
+     * Changes this context to reflect standby mode.
+     */
+    void setComponentStandby();
+
+private:
+    bool mActive;
+    bool mStandalone;
+    boost::shared_mutex mLock;
+};
+typedef boost::shared_ptr<ReplicationContext> ReplicationContextPtr;
+
+} // namespace Replication
+} // namespace AsteriskSCF
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c6cc0d8..a85e19a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,6 +1,8 @@
 # Ice Utilities for C++
 
 asterisk_scf_component_init(ice-util-cpp)
+asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/Component/Component.h)
+asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/Component/TestContext.h)
 asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/Discovery/SmartProxy.h)
 asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/Discovery/LocatorRegistrationWrapper.h)
 asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/Async/AmiCollector.h)
@@ -10,9 +12,13 @@ asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/Helpers/Prox
 asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/Helpers/Retry.h)
 asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/Listener/ListenerManager.h)
 asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/Replication/StateReplicator.h)
+asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/Replication/ReplicationContext.h)
+asterisk_scf_component_add_file(ice-util-cpp Replication/ReplicationContext.cpp)
 asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/WorkQueue/WorkQueue.h)
 asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/WorkQueue/SuspendableWorkQueue.h)
 asterisk_scf_component_add_file(ice-util-cpp ../include/AsteriskSCF/WorkQueue/DefaultQueueListener.h)
+asterisk_scf_component_add_file(ice-util-cpp Component/Component.cpp)
+asterisk_scf_component_add_file(ice-util-cpp Component/TestContext.cpp)
 asterisk_scf_component_add_file(ice-util-cpp WorkQueue/WorkQueue.cpp)
 asterisk_scf_component_add_file(ice-util-cpp WorkQueue/SuspendableWorkQueue.cpp)
 asterisk_scf_component_add_file(ice-util-cpp WorkQueue/DefaultQueueListener.cpp)
diff --git a/src/Component/Component.cpp b/src/Component/Component.cpp
new file mode 100644
index 0000000..7585eba
--- /dev/null
+++ b/src/Component/Component.cpp
@@ -0,0 +1,833 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include <boost/algorithm/string/predicate.hpp>
+
+#include <Ice/Ice.h>
+#include <IceBox/IceBox.h>
+
+#include <AsteriskSCF/Listener/ListenerManager.h>
+#include <AsteriskSCF/Component/Component.h>
+#include <AsteriskSCF/Logger/IceLogger.h>
+#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
+#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
+#include <AsteriskSCF/System/Component/ReplicaIf.h>
+#include <AsteriskSCF/Discovery/LocatorRegistrationWrapper.h>
+
+using namespace std;
+using namespace AsteriskSCF::System::Component::V1;
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::Discovery;
+using namespace AsteriskSCF::Replication;
+
+namespace AsteriskSCF
+{
+namespace Component
+{
+
+static const string ServiceLocatorManagementPropertyName("LocatorServiceManagement.Proxy");
+static const string ServiceLocatorPropertyName("LocatorService.Proxy");
+
+static const string ComponentServiceProxyId("ComponentService");
+static const string ReplicaProxyId("Replica");
+
+/**
+ * This class provides implementation for the ComponentService interface.
+ * Every Asterisk SCF component is expected to expose the ComponentService interface.
+ */
+class ComponentServiceImpl : public ComponentService
+{
+public:
+    ComponentServiceImpl(Component& component) :
+        mComponent(component)
+    {
+    }
+
+public: // Overrides of the ComponentService interface.
+    void suspend(const ::Ice::Current&)
+    {
+        mComponent.suspended();
+    }
+
+    void resume(const ::Ice::Current&)
+    {
+        mComponent.resumed();
+    }
+
+    void shutdown(const ::Ice::Current&)
+    {
+        // This should probably get the icebox admin interface and call 
+        // that shutdown() operartion. 
+        mComponent.shutdown();
+    }
+
+private:
+    AsteriskSCF::Component::Component& mComponent;
+
+}; // class ComponentServiceImpl
+
+/** 
+ * This interface is published as a facet of the Component Service interface.
+ * It exists to allow additional control of a component during testing.
+ */
+class ComponentTestImpl : public ComponentTest
+{
+public:
+    ComponentTestImpl(Component& component) :
+        mComponent(component)
+    {
+    }
+
+    void setTestMode(const std::string& mode, const ::Ice::Current&)
+    {
+        mComponent.setTestMode(mode);
+    }
+
+    void setTestModeWithArgs(const std::string& mode, 
+                             const ComponentTestParamSeq& args, 
+                             const ::Ice::Current&)
+    {
+        mComponent.setTestModeWithArgs(mode, args);
+    }
+
+    void clearTestMode(const string& mode, const ::Ice::Current&)
+    {
+        mComponent.clearTestMode(mode);
+    }
+
+    void clearTestModes(const ::Ice::Current&)
+    {
+        mComponent.clearTestModes();
+    }
+
+private:
+   AsteriskSCF::Component::Component& mComponent;
+
+}; // class ComponentTestImpl
+
+/**
+ * This class provides implementation for this component's Replica management interface.
+ * TBD... Use ListenerManager template to notify listeners.
+ */
+class ReplicaImpl : public Replica 
+{
+public:
+    /**
+     * Constructor. 
+     *  @param app 
+     *  @param adapter The adapter is assumed to have been activated. 
+     */
+    ReplicaImpl(Component& component, 
+                const ::Ice::ObjectAdapterPtr& adapter) : 
+      mComponent(component), 
+      mAdapter(adapter), 
+      mProxyInitialized(false)
+    { 
+    }
+
+    bool isActive(const ::Ice::Current&)
+    {
+        return mComponent.isActive();
+    }
+
+    void initProxy()
+    {
+        mReplicaPrx = ReplicaPrx::uncheckedCast(mAdapter->createDirectProxy(
+                          mAdapter->getCommunicator()->stringToIdentity(ReplicaProxyId)));
+        mProxyInitialized = true;
+    }
+
+    bool activate(const ::Ice::Current&)
+    {
+        mComponent.activated();
+
+        if (!mProxyInitialized)
+        {
+            initProxy();
+        }
+
+        for (vector<ReplicaListenerPrx>::const_iterator listener = mListeners.begin(); 
+             listener != mListeners.end(); ++listener)
+        {
+            (*listener)->activated(mReplicaPrx);
+        }
+
+        return true;
+    }
+
+    void standby(const ::Ice::Current&)
+    {
+        mComponent.standby();
+
+        if (!mProxyInitialized)
+        {
+            initProxy();
+        }
+
+        for (vector<ReplicaListenerPrx>::const_iterator listener = mListeners.begin(); 
+                listener != mListeners.end(); ++listener)
+        {
+            (*listener)->onStandby(mReplicaPrx);
+        }
+    }
+
+    void addListener(const AsteriskSCF::System::Component::V1::ReplicaListenerPrx& listener, 
+                     const ::Ice::Current&)
+    {
+        mListeners.push_back(listener);
+    }
+
+    void removeListener(const AsteriskSCF::System::Component::V1::ReplicaListenerPrx& listener, 
+                        const ::Ice::Current&)
+    {
+        mListeners.erase(std::remove(mListeners.begin(), mListeners.end(), listener), 
+                         mListeners.end());
+    }
+
+private:
+    Component &mComponent;
+
+    /**
+     * Pointer to the object adapter we exist on.
+     */
+    ::Ice::ObjectAdapterPtr mAdapter;
+
+    ReplicaPrx mReplicaPrx;
+    bool mProxyInitialized;
+
+    /**
+     * Listeners that we need to push state change notifications out to.
+     */
+    vector<AsteriskSCF::System::Component::V1::ReplicaListenerPrx> mListeners;
+
+}; // class ReplicaImpl
+
+/**
+ * Constructor. 
+ */
+Component::Component(const AsteriskSCF::System::Logging::Logger& logger,
+                     const std::string& componentDiscoveryCategory) :
+      mInitialized(false),
+      mRunning(false),
+      mPublishTestInterface(false),
+      mLogger(logger),
+      mComponentDiscoveryCategory(componentDiscoveryCategory)
+{
+}
+
+std::string Component::getServiceLocatorManagementProperty()
+{
+    return mCommunicator->getProperties()->getProperty(ServiceLocatorManagementPropertyName);
+}
+
+void Component::setTestMode(const std::string& mode)
+{
+    mTestContext->setTestMode(mode);
+}
+    
+void Component::setTestModeWithArgs(const std::string& mode, 
+                                    const ComponentTestParamSeq& params)
+{ 
+    mTestContext->setTestMode(mode, params);
+}
+
+void Component::clearTestMode(const string& mode)
+{
+    mTestContext->clearTestMode(mode);
+}
+
+void Component::clearTestModes()
+{
+    mTestContext->clearAllTestModes();
+}
+
+bool Component::isActive()
+{
+    // The Replication Context is tracking our current status. 
+    return mReplicationContext->isComponentActive();
+}
+
+void Component::activated()
+{
+    mReplicationContext->setComponentActive();
+    stopListeningToStateReplicators();
+
+    // Notify subclasses
+    onActivated();
+}
+
+void Component::standby()
+{
+    mReplicationContext->setComponentStandby();
+    listenToStateReplicators();
+
+    // Notify subclasses
+    onStandby();
+}
+
+/**
+ * In the override of registerServices(), this operation should
+ * be called for each primary interface registered with the service locator.
+ */
+void Component::registerPrimaryService(const AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr& service)
+{
+    mPrimaryServices.push_back(service);
+    service->registerService();
+}
+
+/**
+ * This operation should be called for each backplane interface registered with the service locator.
+ */
+void Component::registerBackplaneService(const AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr& service)
+{
+    mBackplaneServices.push_back(service);
+    service->registerService();
+}
+
+/**
+ * Register this component's backplane interfaces with the Service Locator.
+ */
+void Component::registerBackplaneServices()
+{
+    try
+    {
+        // Register the ComponentService interface with the Service Locator.
+        {
+        ServiceLocatorParamsPtr parameters(new ServiceLocatorParams);
+        parameters->category = mComponentDiscoveryCategory;
+        parameters->id = mComponentName + ".ComponentService";
+        mComponentRegistration = 
+            new LocatorRegistrationWrapper(mCommunicator, 
+                                           getServiceLocatorManagementProperty(), 
+                                           mComponentServicePrx, 
+                                           mComponentName + ".ComponentService", 
+                                           parameters);
+        registerBackplaneService(mComponentRegistration);
+        }
+
+        if (mPublishTestInterface)
+        {
+            // Register our test servant as a facet of the ComponentService interface.
+            mComponentTestPrx = ComponentTestPrx::uncheckedCast(
+                mBackplaneAdapter->addFacet(mComponentTest, 
+                                            mComponentServicePrx->ice_getIdentity(), 
+                                            AsteriskSCF::System::Component::V1::ComponentTestFacet));
+        }
+
+
+        // Register the Replica interface with the Service Locator.
+        {
+        ServiceLocatorParamsPtr parameters(new ServiceLocatorParams);
+        parameters->category = mComponentDiscoveryCategory + ".Replica";
+        parameters->id = mComponentName + ".Replica";
+        mReplicaRegistration = 
+            new LocatorRegistrationWrapper(mCommunicator, 
+                                           getServiceLocatorManagementProperty(), 
+                                           mReplicaPrx, 
+                                           parameters->id, 
+                                           parameters);
+        registerBackplaneService(mReplicaRegistration);
+        }
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << "Exception in component " << mComponentName << 
+            " in " << BOOST_CURRENT_FUNCTION << ". Details: " << e.what();
+        throw;
+    }
+}
+
+/**
+ * Unregister this component's primary service interfaces from the Service Locator.
+ */
+void Component::unregisterPrimaryServices()
+{
+    try
+    {
+        vector<LocatorRegistrationWrapperPtr>::iterator i;
+        for(i=mPrimaryServices.begin(); i != mPrimaryServices.end(); ++i)
+        {
+            (*i)->unregister();
+        }
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+    }
+}
+
+/**
+ * Unregister this component's backplane interfaces from the Service Locator.
+ */
+void Component::unregisterBackplaneServices()
+{
+    try
+    {
+        vector<LocatorRegistrationWrapperPtr>::iterator i;
+        for(i=mBackplaneServices.begin(); i != mBackplaneServices.end(); ++i)
+        {
+            (*i)->unregister();
+        }
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+    }
+}
+
+/**
+ * Suspends this component's primary public interfaces 
+ * within the Service Locator. When suspended in this manner, 
+ * the ServiceLocator will not consider the component during 
+ * lookup requests. 
+ */
+void Component::suspendPrimaryServices()
+{
+    try
+    {
+        vector<LocatorRegistrationWrapperPtr>::iterator i;
+        for(i=mPrimaryServices.begin(); i != mPrimaryServices.end(); ++i)
+        {
+            (*i)->suspend();
+        }
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+    }
+}
+
+/**
+ * Unsuspends this component's primary public interfaces 
+ * within the Service Locator. This allows them to be 
+ * located again via the Service Locator. 
+ */
+void Component::unsuspendPrimaryServices()
+{
+    try
+    {
+        vector<LocatorRegistrationWrapperPtr>::iterator i;
+        for(i=mPrimaryServices.begin(); i != mPrimaryServices.end(); ++i)
+        {
+            (*i)->unsuspend();
+        }
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+    }
+}
+
+/**
+ * Suspends this component's backplane interfaces 
+ * within the Service Locator. When suspended in this manner, 
+ * the ServiceLocator will not consider the component during lookup requests. 
+ */
+void Component::suspendBackplaneServices()
+{
+    try
+    {
+        vector<LocatorRegistrationWrapperPtr>::iterator i;
+        for(i=mBackplaneServices.begin(); i != mBackplaneServices.end(); ++i)
+        {
+            (*i)->suspend();
+        }
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+    }
+}
+
+/**
+ * Unsuspends this component's backplane interfaces 
+ * within the Service Locator. This allows them to be 
+ * located again via the Service Locator. 
+ */
+void Component::unsuspendBackplaneServices()
+{
+    try
+    {
+        vector<LocatorRegistrationWrapperPtr>::iterator i;
+        for(i=mBackplaneServices.begin(); i != mBackplaneServices.end(); ++i)
+        {
+            (*i)->unsuspend();
+        }
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+    }
+}
+
+/**
+ * Create the adapters for this component.
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::createAdapters()
+{
+    try
+    {
+        // Create the adapter that our functional services are published on.
+        mServiceAdapter = mCommunicator->createObjectAdapter(mComponentName);
+
+        // Create an adapter for our backplane services. 
+        mBackplaneAdapter = mCommunicator->createObjectAdapter(mComponentName + ".Backplane");
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+
+/**
+ * Activate the adapters for this component.
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::activateAdapters()
+{
+    try
+    {
+        mServiceAdapter->activate();
+        mBackplaneAdapter->activate();
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+
+/**
+ * Create a ReplicationContext for this component. 
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::initReplicationContext()
+{
+    try
+    {
+        string standaloneProp = mCommunicator->getProperties()->getPropertyWithDefault(
+              mComponentName + ".Standalone", "no");
+        bool standalone = boost::iequals(standaloneProp,"yes") || 
+                          boost::iequals(standaloneProp,"true");
+
+        bool active(false);
+
+        if (standalone)
+        {
+            active = true;
+        }
+        else
+        {
+            // NOTE: In the near future, Standalone instances are the only 
+            // instances that will default to being active. When that is in 
+            // place, non-standalone instances will need to be made active via 
+            // the Replica interface. But for now, we default to active unless 
+            // the Standby property is set. 
+            string standbyProp = 
+                mCommunicator->getProperties()->getPropertyWithDefault(mComponentName + ".Standby", "no");
+            active = boost::iequals(standbyProp,"no") || boost::iequals(standbyProp,"false");
+        }
+
+        // Create the replication context.
+        mReplicationContext = ReplicationContextPtr(
+            new ReplicationContext(active, standalone));
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+
+
+/**
+ * Create a TestContext for this component. 
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::initTestContext()
+{
+    try
+    {
+        // Create the test context.
+        mTestContext = TestContextPtr(new TestContext());
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+/**
+ * Configure the logger. 
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::configureLogger()
+{
+    try
+    {
+        ConfiguredIceLoggerPtr mIceLogger = createIceLogger(mBackplaneAdapter);
+        getLoggerFactory().setLogOutput(mIceLogger->getLogger());
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+
+/**
+ * Create the backplane servant implementations.
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::createBackplaneServices()
+{
+    try
+    {
+        // Check to see if we're configured to publish a test interface.
+        string testProp = mCommunicator->getProperties()->getPropertyWithDefault(
+                                 mComponentName + ".ComponentTest", "no");
+        mPublishTestInterface = boost::iequals(testProp,"yes") || boost::iequals(testProp,"true");
+
+        if (mPublishTestInterface)
+        {
+            // Create and publish the ComponentTest servant. This will be exposed
+            // as a facet of ComponentService.
+            mComponentTest = new ComponentTestImpl(*this);
+        }
+
+        // Create and publish the ComponentService interface on the backplane adapter. 
+        mComponentService = new ComponentServiceImpl(*this);
+        mComponentServicePrx = ComponentServicePrx::uncheckedCast(
+            mBackplaneAdapter->add(mComponentService, 
+                                   mCommunicator->stringToIdentity(ComponentServiceProxyId)));
+
+        // Create and publish our Replica interface on the management adapter. 
+        // This interface allows this component to be activated or placed in standby mode. 
+        mReplica = new ReplicaImpl(*this, mBackplaneAdapter);
+        mReplicaPrx = ReplicaPrx::uncheckedCast(mBackplaneAdapter->add(mReplica, 
+                  mCommunicator->stringToIdentity(ReplicaProxyId)));
+
+        createReplicationStateListeners();
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+
+/**
+ * Initialize the service locator proxies. 
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::initServiceLocatorProxies()
+{
+    // Get a proxy to the management interface for the Service Locator manager.
+    mServiceLocatorManagement = 
+        ServiceLocatorManagementPrx::checkedCast(mCommunicator->propertyToProxy(ServiceLocatorManagementPropertyName));
+
+    // Get a proxy to the interface for the Service Locator.
+    mServiceLocator = 
+        ServiceLocatorPrx::checkedCast(mCommunicator->propertyToProxy(ServiceLocatorPropertyName));
+}
+
+/**
+ * This method is an instance of the Template method pattern. Each of the
+ * operations called are virtual methods. Some are optionally overridden within a
+ * component, and others are required to be overridden. 
+ */
+void Component::initialize()
+{
+    try
+    {
+        createAdapters();
+
+        initReplicationContext();
+
+        initTestContext();
+
+        configureLogger();
+
+        createPrimaryServices();
+
+        createBackplaneServices();
+
+        activateAdapters();
+
+        initServiceLocatorProxies();
+
+        mInitialized = true;
+    }
+    catch(const ::Ice::Exception &e)
+    {
+        mLogger(Error) << "Problems in " << mComponentName << BOOST_CURRENT_FUNCTION << e.what();
+        throw e;
+    }
+
+    findRemoteServices();
+
+    // Notify subclasses.
+    onInitialize();
+}
+
+/**
+ * Override of the IceBox::Service start method.
+ */
+void Component::start(const string& name, 
+                                   const ::Ice::CommunicatorPtr& communicator, 
+                                   const ::Ice::StringSeq& args)
+{
+    mLogger(Info) << "Starting...";
+
+    mCommunicator = communicator;
+    mComponentName = name;
+    mArgs = args;   // Arguments that weren't stripped off by IceBox.
+
+    if (!mInitialized)
+    {
+        initialize();
+    }
+    else
+    {
+        mServiceAdapter->activate();
+        mBackplaneAdapter->activate();
+    }
+
+    // Plug into the Asterisk SCF discovery system so that the interfaces we provide
+    // can be located.
+    registerBackplaneServices();
+    registerPrimaryServices();
+    
+    // Standby mode?
+    if (!mReplicationContext->isComponentActive())
+    {
+        listenToStateReplicators();
+    } 
+
+    // Notify subclasses
+    onStart();
+
+    mRunning = true;
+    mLogger(Info) << "Started";
+}
+
+/**
+ * Things we do to resume operation after a pause().
+ */
+void Component::resumed()
+{
+    if (!mRunning)
+    {
+        // Standby mode?
+        if (!mReplicationContext->isComponentActive())
+        {
+            listenToStateReplicators();
+        } 
+
+        // Allow servants on this adapter to process requests.
+        mServiceAdapter->activate();
+
+        // Re-enable lookups of our interfaces in the ServiceLocator. 
+        unsuspendPrimaryServices();
+    }
+
+    // Notify subclasses
+    onResume();
+
+    mRunning = true;
+}
+
+/** 
+ * Utility function to suspend the service for a suspend() or stop().
+ */
+void Component::suspendService(bool shuttingDown)
+{
+    if (mRunning)
+    {
+        // Suspend lookups of our interfaces in the ServiceLocator. If shutting down,
+        // we'll be deregestering our interfaces with the ServiceLocator,
+        // so we won't waste the bandwidth doing a suspend in that case. 
+        if (!shuttingDown)
+        {
+            suspendPrimaryServices();
+        }
+
+        // Standby mode?
+        if (!mReplicationContext->isComponentActive())
+        {
+           stopListeningToStateReplicators();
+        }
+
+        // Place the service adapter in holding state.
+        // The adapter that services the ComponentService stays active. 
+        mServiceAdapter->hold();
+    }
+
+    mRunning = false;
+}
+
+/** 
+ * Handle a notice from the ComponentService. 
+ */
+void Component::suspended()
+{
+    mLogger(Info) << "Suspending...";
+
+    suspendService(false);
+
+    // Notify subclasses
+    onSuspend();
+
+    mLogger(Info) << "Suspended.";
+}
+
+/**
+ * Shutdown the Icebox component. 
+ * This is a command via ComponentService, not
+ * a notification.
+ */
+void Component::shutdown()
+{
+    // TBD. 
+}
+
+/**
+ * Override of the IceBox::Service stop method. 
+ */
+void Component::stop()
+{
+    mLogger(Info) << "Stopping...";
+
+    suspendService(true);
+
+    unregisterPrimaryServices();
+    unregisterBackplaneServices();
+
+    // Turn off our management interface. 
+    // Only a start() directly from IceBox can restart us now. 
+    mBackplaneAdapter->hold();
+
+    // Notify subclasses
+    onStop();
+
+    mLogger(Info) << "Stopped.";
+}
+
+} // end Component
+} // end AsteriskSCF
diff --git a/src/Component/TestContext.cpp b/src/Component/TestContext.cpp
new file mode 100644
index 0000000..c4213f1
--- /dev/null
+++ b/src/Component/TestContext.cpp
@@ -0,0 +1,113 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
+
+#include <AsteriskSCF/Component/TestContext.h>
+
+using namespace std;
+using namespace AsteriskSCF::System::Component::V1;
+
+namespace AsteriskSCF
+{
+namespace Component
+{
+
+class TestContextPriv
+{
+public:
+    TestContextPriv() 
+    {
+    }
+
+    map<string, ComponentTestParamSeq> mTestModeMap;
+    boost::shared_mutex mLock;
+};
+
+TestContext::TestContext() : mImpl(new TestContextPriv()) 
+{
+}
+
+/**
+ * Indicates whether a test mode with given name
+ * has been set. 
+ * @param mode The name of the mode to query.
+ */
+bool TestContext::hasTestMode(const std::string& mode)
+{
+    boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
+    return (mImpl->mTestModeMap.find(mode) != mImpl->mTestModeMap.end());
+}
+
+/**
+ * Gets the current test mode's parameters.
+ */
+ComponentTestParamSeq TestContext::getTestModeParams(const std::string& mode)
+{
+    boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
+    
+    map<string, ComponentTestParamSeq>::iterator i = mImpl->mTestModeMap.find(mode);
+    if (i == mImpl->mTestModeMap.end())
+    {
+        throw InvalidTestMode(mode);
+    }
+
+    return (*i).second;
+}
+
+/**
+ * Sets a test mode. 
+ */
+void TestContext::setTestMode(const std::string& mode) 
+{
+    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
+    ComponentTestParamSeq emptyParams;
+
+    mImpl->mTestModeMap[mode] = emptyParams;
+}
+
+/**
+ * Sets a current test mode with parameters. 
+ */
+void TestContext::setTestMode(const std::string& mode, 
+         const ComponentTestParamSeq& params)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
+    mImpl->mTestModeMap[mode] = params;
+}
+
+/**
+ * Clears testing mode.
+ */
+void TestContext::clearTestMode(const std::string& mode)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+    mImpl->mTestModeMap.erase(mode);
+}
+
+/**
+ * Clears all testing modes.
+ */
+void TestContext::clearAllTestModes()
+{
+    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+    mImpl->mTestModeMap.clear();
+}
+
+} // end Component
+} // end AsteriskSCF
diff --git a/src/Replication/ReplicationContext.cpp b/src/Replication/ReplicationContext.cpp
new file mode 100644
index 0000000..0fa71dd
--- /dev/null
+++ b/src/Replication/ReplicationContext.cpp
@@ -0,0 +1,67 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#include <boost/thread/locks.hpp>
+
+#include <AsteriskSCF/Replication/ReplicationContext.h>
+
+namespace AsteriskSCF
+{
+namespace Replication
+{
+
+ReplicationContext::ReplicationContext(bool componentIsActive, bool standalone)
+    :  mActive(componentIsActive), mStandalone(standalone)
+{
+}
+
+bool ReplicationContext::isReplicating()
+{
+    boost::shared_lock<boost::shared_mutex> lock(mLock);
+
+    return mActive && !mStandalone;
+}
+
+bool ReplicationContext::isComponentActive()
+{
+    boost::shared_lock<boost::shared_mutex> lock(mLock);
+
+    return mActive;
+}
+
+bool ReplicationContext::isStandalone()
+{
+    boost::shared_lock<boost::shared_mutex> lock(mLock);
+
+    return mStandalone;
+}
+
+void ReplicationContext::setComponentActive() 
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+    mActive = true;
+
+}
+
+void ReplicationContext::setComponentStandby() 
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+    mActive = false;
+}
+
+} // end BasicRoutingService
+} // end AsteriskSCF
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index b26ab49..f67c37d 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -13,6 +13,7 @@ asterisk_scf_component_build_icebox(ice-util-cpp-test)
 target_link_libraries(ice-util-cpp-test asterisk-scf-api)
 
 add_subdirectory(Async)
+add_subdirectory(Component)
 add_subdirectory(Replication)
 add_subdirectory(ThreadPool)
 add_subdirectory(WorkQueue)
diff --git a/test/Component/.component-base-test.conf.swp b/test/Component/.component-base-test.conf.swp
new file mode 100644
index 0000000..58afc30
Binary files /dev/null and b/test/Component/.component-base-test.conf.swp differ
diff --git a/test/Component/CMakeLists.txt b/test/Component/CMakeLists.txt
new file mode 100644
index 0000000..e6f3127
--- /dev/null
+++ b/test/Component/CMakeLists.txt
@@ -0,0 +1,25 @@
+include_directories(${API_INCLUDE_DIR})
+include_directories(${logger_dir}/include)
+include_directories(${ice-util-cpp_dir}/include)
+
+# A mock component that derives from our base Component.
+asterisk_scf_component_init(component-base-test-mockcomponent)
+asterisk_scf_component_add_slice(component-base-test-mockcomponent ComponentTestIf.ice)
+asterisk_scf_component_add_file(component-base-test-mockcomponent MockComponent.cpp)
+asterisk_scf_component_add_ice_libraries(component-base-test-mockcomponent IceBox)
+asterisk_scf_component_add_boost_libraries(component-base-test-mockcomponent date_time thread)
+asterisk_scf_component_build_icebox(component-base-test-mockcomponent)
+target_link_libraries(component-base-test-mockcomponent asterisk-scf-api ice-util-cpp logging-client)
+
+# A test driver.
+asterisk_scf_component_init(component-base-test)
+asterisk_scf_component_add_slice(component-base-test ComponentTestIf.ice)
+asterisk_scf_component_add_file(component-base-test ComponentTest.cpp)
+asterisk_scf_component_add_boost_libraries(component-base-test unit_test_framework thread)
+asterisk_scf_component_build_icebox(component-base-test)
+target_link_libraries(component-base-test asterisk-scf-api ice-util-cpp logging-client)
+asterisk_scf_test_icebox(component-base-test component-base-test.conf)
+
+
+
+
diff --git a/test/Component/ComponentTest.cpp b/test/Component/ComponentTest.cpp
new file mode 100644
index 0000000..ce9d7fe
--- /dev/null
+++ b/test/Component/ComponentTest.cpp
@@ -0,0 +1,287 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#define BOOST_TEST_MODULE BasicRoutingServiceTestSuite
+
+#define BOOST_TEST_NO_MAIN
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/debug.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+
+#include <Ice/Ice.h>
+#include <IceBox/IceBox.h>
+#include <IceUtil/UUID.h>
+
+#include <AsteriskSCF/Testing/IceBoxBoostTest.h>
+#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
+#include <AsteriskSCF/System/Component/ReplicaIf.h>
+#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
+
+#include "ComponentTestIf.h"
+
+using namespace std;
+using namespace AsteriskSCF::ComponentTest;
+using namespace AsteriskSCF::System::Component::V1;
+using namespace AsteriskSCF::Core::Discovery::V1;
+
+/**
+ * The MockComponent forwards the on<Event> messages 
+ * to a listener for testing purposes.
+ */
+class MockServiceListenerImpl : public MockServiceListener
+{
+public:
+    MockServiceListenerImpl() {}
+
+    void onInitialize(const ::Ice::Current&) { initCount++; }
+    void onSuspend(const ::Ice::Current&)    { suspendCount++; }
+    void onResume(const ::Ice::Current&)     { resumeCount++; }
+    void onStop(const ::Ice::Current&)       { stopCount++;  }
+    void onStart(const ::Ice::Current&)      { startCount++;  }
+    void onActivated(const ::Ice::Current&)  { activateCount++; }
+    void onStandby(const ::Ice::Current&)    { standbyCount++; }
+
+    void resetCounters()
+    {
+        initCount = 0;
+        suspendCount = 0;
+        resumeCount = 0;
+        startCount = 0;
+        stopCount = 0;
+        activateCount = 0;
+        standbyCount = 0;
+    }
+
+    int initCount;
+    int suspendCount;
+    int resumeCount;
+    int startCount;
+    int stopCount;
+    int activateCount;
+    int standbyCount;
+};
+typedef IceUtil::Handle<MockServiceListenerImpl> MockServiceListenerImplPtr;
+
+struct SharedTestData
+{
+    MockServiceListenerImplPtr mListener;
+    MockServiceListenerPrx mListenerPrx;
+    ServiceLocatorPrx mServiceLocator;
+    ComponentServicePrx mComponentServicePrx;
+};
+SharedTestData sharedTestData;
+
+/**
+ * A global fixture for Ice initialization.
+ * Provides setup/teardown for the entire set of tests.
+ */
+struct GlobalIceFixture
+{
+    GlobalIceFixture()
+    {
+        BOOST_TEST_MESSAGE("Setting up Component Base test fixture");
+
+        ::boost::debug::detect_memory_leaks(false);
+        ::boost::unit_test::unit_test_log.set_stream( std::cout );
+        int status = 0;
+        try
+        {
+            IceBoxTestEnv.adapter  = IceBoxTestEnv.communicator->createObjectAdapterWithEndpoints("ComponentTest", "default -p 10300");
+            sharedTestData.mListener = new MockServiceListenerImpl();
+            sharedTestData.mListenerPrx = MockServiceListenerPrx::uncheckedCast(
+                IceBoxTestEnv.adapter->addWithUUID(sharedTestData.mListener));
+
+            IceBoxTestEnv.adapter->activate();
+
+            sharedTestData.mServiceLocator = 
+               ServiceLocatorPrx::checkedCast(IceBoxTestEnv.communicator->propertyToProxy("LocatorService.Proxy"));
+
+            sharedTestData.mComponentServicePrx = 
+               ComponentServicePrx::checkedCast(IceBoxTestEnv.communicator->propertyToProxy("ComponentService.Proxy"));
+        }
+        catch (const Ice::Exception& ex)
+        {
+            cerr << ex << endl;
+            status = 1;
+        }
+    } // end Fixture() constructor
+
+    ~GlobalIceFixture()
+    {
+        BOOST_TEST_MESSAGE("Tearing down Component Base global test fixture");
+    }
+
+
+};
+
+BOOST_GLOBAL_FIXTURE(GlobalIceFixture);
+
+/**
+ * Make sure the base Component class properly registered the
+ * ComponentService interface with the ServiceLocator. 
+ */
+BOOST_AUTO_TEST_CASE(LocateComponentService)
+{
+    try
+    {
+        ServiceLocatorParamsPtr params = new ServiceLocatorParams("MockCategory", "MockComponent.ComponentService");
+        Ice::ObjectPrx prx = sharedTestData.mServiceLocator->locate(params);
+        BOOST_CHECK(prx != 0);
+    }
+    catch (...)
+    {
+        BOOST_FAIL("Exception locating ComponentService.");
+    }
+}
+
+/**
+ * Make sure the base Component class properly registered the
+ * Replica interface with the ServiceLocator. 
+ */
+BOOST_AUTO_TEST_CASE(LocateReplica)
+{
+    try
+    {
+        ServiceLocatorParamsPtr params = new ServiceLocatorParams("MockCategory.Replica", "MockComponent.Replica");
+        Ice::ObjectPrx prx = sharedTestData.mServiceLocator->locate(params);
+        BOOST_CHECK(prx != 0);
+    }
+    catch (...)
+    {
+        BOOST_FAIL("Exception locating Replica.");
+    }
+}
+
+/**
+ * Utility function that attempts to access the MockService
+ * interface published by the MockComponent under test. 
+ *
+ * @return True if the service can be reached.
+ */
+bool accessMockService(const MockServicePrx& mockService)
+{
+    try
+    {
+        mockService->testState();
+    }
+    catch (const Ice::Exception&)
+    {
+        return false;
+    }
+    return true;
+}
+
+/**
+ * Verify that the ComponentService inteface is functional. 
+ */
+BOOST_AUTO_TEST_CASE(ManipulateComponentService)
+{
+    sharedTestData.mListener->resetCounters();
+
+    MockServicePrx mockService;
+    ComponentServicePrx componentService;
+
+    try
+    {
+        ServiceLocatorParamsPtr serviceparams = new ServiceLocatorParams("MockCategory", "MockComponent.ComponentService");
+        componentService = ComponentServicePrx::uncheckedCast(sharedTestData.mServiceLocator->locate(serviceparams));
+        BOOST_CHECK(componentService != 0);
+
+        ServiceLocatorParamsPtr mockservparams = new ServiceLocatorParams("MockService", "");
+        mockService = MockServicePrx::uncheckedCast(sharedTestData.mServiceLocator->locate(mockservparams));
+        BOOST_CHECK(mockService != 0);
+
+        mockService->setListener(sharedTestData.mListenerPrx);
+    }
+    catch (...)
+    {
+        BOOST_FAIL("Exception locating ComponentService.");
+    }
+
+    BOOST_CHECK(accessMockService(mockService));
+
+    componentService->suspend();
+    BOOST_CHECK(sharedTestData.mListener->suspendCount == 1);
+
+    // Should be inaccessible while in suspended mode. 
+    BOOST_CHECK(!accessMockService(mockService));
+
+    componentService->resume();
+    BOOST_CHECK(sharedTestData.mListener->resumeCount == 1);
+
+    // Should be accessible once more. 
+    BOOST_CHECK(accessMockService(mockService));
+
+    sharedTestData.mListener->resetCounters();
+}
+
+/** 
+ * If the ComponentTest interface is enabled in the config file,
+ * verify that the facet is available.
+ */
+BOOST_AUTO_TEST_CASE(AccessTestFacet)
+{
+    try
+    {
+        string testProp = IceBoxTestEnv.communicator->getProperties()->getPropertyWithDefault(
+                                  "MockComponent.ComponentTest", "no");
+        bool hasTestFacet = boost::iequals(testProp,"yes") || boost::iequals(testProp,"true");
+
+        if (!hasTestFacet)
+        {
+            return;  // The facet is disabled by configuration. Nothing to test. 
+        }
+
+        ComponentTestPrx prx = ComponentTestPrx::checkedCast(sharedTestData.mComponentServicePrx, 
+                   AsteriskSCF::System::Component::V1::ComponentTestFacet);
+        BOOST_CHECK(prx != 0);
+    }
+    catch(...)
+    {
+        BOOST_FAIL("Exception locating ComponentTest facet.");
+    }
+}
+
+/**
+ * Verify the Replica inteface is functional. 
+ */
+BOOST_AUTO_TEST_CASE(CheckReplica)
+{
+    sharedTestData.mListener->resetCounters();
+
+    // The Replica is registered under the same category as the ComponentService + ".Replica". 
+    // The unique id is the component's name + ".Replica"
+    ServiceLocatorParamsPtr params = new ServiceLocatorParams("MockCategory.Replica", "MockComponent.Replica");
+    ReplicaPrx prx = ReplicaPrx::uncheckedCast(sharedTestData.mServiceLocator->locate(params));
+    BOOST_CHECK(prx != 0);
+
+    BOOST_CHECK(prx->isActive());
+
+    prx->standby();
+
+    BOOST_CHECK(!prx->isActive());
+
+    prx->activate();
+
+    BOOST_CHECK(prx->isActive());
+
+    // Verify that the on<Event> messages were called to notify
+    // the derived component. 
+    BOOST_CHECK(sharedTestData.mListener->activateCount == 1);
+    BOOST_CHECK(sharedTestData.mListener->standbyCount == 1);
+
+    sharedTestData.mListener->resetCounters();
+}
diff --git a/test/Component/ComponentTestIf.ice b/test/Component/ComponentTestIf.ice
new file mode 100644
index 0000000..d39f493
--- /dev/null
+++ b/test/Component/ComponentTestIf.ice
@@ -0,0 +1,55 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+ 
+#pragma once
+
+module AsteriskSCF
+{
+/**
+ * These interfaces are used to test the
+ * base Component class functionality.
+ * A MockComponent subclasses the base Component
+ * and a test driver interacts then interacts with
+ * it.
+ */
+module ComponentTest
+{
+    /**
+     * The test driver implements this to monitor
+     * the MockComponent's internal events.
+     */
+    interface MockServiceListener
+    {
+        void onInitialize();
+        void onSuspend();
+        void onResume();
+        void onStop();
+        void onStart();
+        void onActivated();
+        void onStandby();
+    };
+
+    /**
+     * Mock service for the MockComponent to implement. 
+     */
+    interface MockService
+    {
+        bool testState();
+        void setListener(MockServiceListener *listener);
+    };
+
+}; //module V1
+}; //module V1
diff --git a/test/Component/MockComponent.cpp b/test/Component/MockComponent.cpp
new file mode 100644
index 0000000..c7d845b
--- /dev/null
+++ b/test/Component/MockComponent.cpp
@@ -0,0 +1,173 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include <AsteriskSCF/Component/Component.h>
+
+#include <AsteriskSCF/logger.h>
+#include "ComponentTestIf.h"
+
+using namespace AsteriskSCF::System::Logging;
... 260 lines suppressed ...


-- 
asterisk-scf/integration/ice-util-cpp.git



More information about the asterisk-scf-commits mailing list