datacommsserver/esockserver/ssock/ss_rmetaextensioncontainer.cpp
changeset 0 dfb7c4ff071f
child 27 5ebd530e523b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/ssock/ss_rmetaextensioncontainer.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,332 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// ss_rmetaextensioncontainer.cpp 
+//
+
+
+#include "ss_rmetaextensioncontainer.h"
+#include "ss_cmetaextensioncontainer.h"
+
+using namespace ESock;
+
+_LIT(KMecPanic, "mecpanic");
+
+void PanicMec(TMecPanic aCode)
+    {
+    User::Panic(KMecPanic, aCode);
+    }
+
+// ===========================================================
+// RMetaExtensionContainerC
+// ===========================================================
+
+EXPORT_C RMetaExtensionContainerC::RMetaExtensionContainerC()
+    : iContainerImpl(NULL)
+    {
+    }
+
+EXPORT_C RMetaExtensionContainerC::~RMetaExtensionContainerC()
+    {
+    }
+
+EXPORT_C void RMetaExtensionContainerC::Open()
+    {
+    __ASSERT_ALWAYS(iContainerImpl, PanicMec(ENoImplementation));
+    iContainerImpl->Open();
+    }
+
+EXPORT_C void RMetaExtensionContainerC::Open(const RMetaExtensionContainerC& aSource)
+    {
+    __ASSERT_ALWAYS(&aSource != this, PanicMec(EInvalidSelfReference));
+    __ASSERT_ALWAYS(aSource.Container(), PanicMec(ENoImplementation));
+    __ASSERT_ALWAYS(!iContainerImpl, PanicMec(EAlreadyOpen));
+    
+    aSource.Container()->Open();
+    iContainerImpl = aSource.Container();
+    }
+
+EXPORT_C void RMetaExtensionContainerC::Close()
+    {
+    if (iContainerImpl)
+        {
+        iContainerImpl->Close();
+        iContainerImpl = NULL;
+        }
+    }
+
+EXPORT_C const Meta::SMetaData* RMetaExtensionContainerC::FindExtension(const Meta::STypeId& aTypeId) const
+    {
+    __ASSERT_ALWAYS(iContainerImpl, PanicMec(ENoImplementation));
+    return iContainerImpl->FindExtension(aTypeId);
+    }
+
+
+EXPORT_C const Meta::SMetaData& RMetaExtensionContainerC::FindExtensionL(const Meta::STypeId& aTypeId) const
+    {
+    __ASSERT_ALWAYS(iContainerImpl, PanicMec(ENoImplementation));
+    return iContainerImpl->FindExtensionL(aTypeId);
+    }
+
+
+// ===========================================================
+// RMetaExtensionContainer
+// ===========================================================
+
+EXPORT_C RMetaExtensionContainer::RMetaExtensionContainer()
+    : iIsLazyCreationDone(EFalse), iIsOpen(EFalse), iCurrentExtensionContainer(NULL)
+    {
+    }
+
+
+EXPORT_C void RMetaExtensionContainer::Open()
+    {
+    __ASSERT_ALWAYS(!iIsOpen, PanicMec(EAlreadyOpen));
+    
+    // Using lazy creation of the implementation so that Open() is infallible
+    // This boolean ensures that Open() is still called before use of the container
+    iIsOpen = ETrue;
+    }
+
+
+EXPORT_C void RMetaExtensionContainer::Open(const RMetaExtensionContainerC& aBaseContainer)
+    {
+    __ASSERT_ALWAYS(!iIsOpen, PanicMec(EAlreadyOpen));
+	RMetaExtensionContainerC::Open(aBaseContainer);
+    iIsOpen = ETrue;
+    }
+
+
+EXPORT_C void RMetaExtensionContainer::Close()
+    {
+    if (iIsOpen)
+        {
+        if (AppendableExtensionContainer())
+        	{
+        	AppendableExtensionContainer()->Compact();
+        	}
+        iIsOpen = EFalse;
+        }
+    
+    RMetaExtensionContainerC::Close();
+    }
+
+
+void RMetaExtensionContainer::CreateExtensionContainerL()
+    {
+    // Don't call it unless it should be created
+    __ASSERT_DEBUG(!AppendableExtensionContainer(), PanicMec(EIllegalState));
+    
+	CMetaExtensionContainerImplBase* pendingBaseContainerImpl = NULL;
+	if (!iIsLazyCreationDone)
+		{
+		// Retrieve the pending base container implementation if there is one
+		pendingBaseContainerImpl = Container();
+		}
+	
+    CMetaExtensionContainer* mecImpl = CMetaExtensionContainer::NewLC(pendingBaseContainerImpl);
+    if (!iIsLazyCreationDone)
+    	{
+    	// If there is no proper container implementation this normal extension container
+    	// will become it.
+    	// Base class takes ownership of the new container implementation reference
+    	SetContainer(mecImpl);
+
+        if (pendingBaseContainerImpl)
+            {
+            // Remove the holding reference - the new container implementation has its own
+            pendingBaseContainerImpl->Close();
+            }
+        
+        iIsLazyCreationDone = ETrue;
+        }
+    else
+    	{
+    	// There is an existing container implementation. Given the fact that the
+    	// CreateExtensionContainerL method has been called it must be of the
+    	// container array type. This will own (the reference on) our new extension
+    	// container.
+    	__ASSERT_DEBUG(Container()->Type() == CMetaExtensionContainerImplBase::EMetaExtensionContainerArray, PanicMec(EIllegalState));
+    	__ASSERT_DEBUG(!pendingBaseContainerImpl, PanicMec(EIllegalState));
+    	User::LeaveIfError(AppendableContainerArray()->AppendContainer(*mecImpl));
+    	}
+    
+	__ASSERT_DEBUG(!iCurrentExtensionContainer, PanicMec(EIllegalState));
+	iCurrentExtensionContainer = mecImpl;
+    CleanupStack::Pop(mecImpl);
+    }
+
+
+void RMetaExtensionContainer::CreateContainerArrayL()
+    {
+    ASSERT(!AppendableContainerArray()); // Don't call it unless it should be created
+    
+	CMetaExtensionContainerImplBase* pendingBaseContainerImpl = NULL;
+	if (!iIsLazyCreationDone)
+		{
+		// Retrieve the pending base container implementation if there is one
+		pendingBaseContainerImpl = Container();
+		}
+	
+	CMetaExtensionContainerArray* mecImpl = CMetaExtensionContainerArray::NewLC(pendingBaseContainerImpl);
+    if (!iIsLazyCreationDone)
+    	{
+    	// If there is no proper container implementation this container array implementation
+    	// will become it.
+    	// Base class takes ownership of the new container implementation reference
+    	SetContainer(mecImpl);
+        
+    	if (pendingBaseContainerImpl)
+            {
+            // Remove the holding reference - the new container implementation has its own
+            pendingBaseContainerImpl->Close();
+            }
+    	
+    	iIsLazyCreationDone = ETrue;
+    	}
+    else
+    	{
+    	// There is an existing container implementation. Given the fact that the
+    	// CreateContainerArrayL method has been called it must be of the
+    	// normal extension container type. This will be replaced with a container
+    	// array implementation which will own (the reference on) the existing
+    	// container.
+    	__ASSERT_DEBUG(Container()->Type() == CMetaExtensionContainerImplBase::EMetaExtensionContainer, PanicMec(EIllegalState));
+    	__ASSERT_DEBUG(!pendingBaseContainerImpl, PanicMec(EIllegalState));
+    	__ASSERT_DEBUG(iCurrentExtensionContainer, PanicMec(EIllegalState));
+    	User::LeaveIfError(mecImpl->AppendContainer(*iCurrentExtensionContainer));
+
+    	// Close our reference on the extension container, the container array will open its own
+    	iCurrentExtensionContainer->Close();
+    	iCurrentExtensionContainer = NULL;
+    	SetContainer(mecImpl);
+    	}
+
+    CleanupStack::Pop(mecImpl);
+    }
+
+
+EXPORT_C const Meta::SMetaData* RMetaExtensionContainer::FindExtension(const Meta::STypeId& aTypeId) const
+    {
+    __ASSERT_ALWAYS(iIsOpen, PanicMec(ENoImplementation));
+    if (Container())
+    	{
+    	return Container()->FindExtension(aTypeId);
+    	}
+    return NULL;
+    }
+
+
+EXPORT_C const Meta::SMetaData& RMetaExtensionContainer::FindExtensionL(const Meta::STypeId& aTypeId) const
+    {
+    __ASSERT_ALWAYS(iIsOpen, PanicMec(ENoImplementation));
+    if (!Container())
+    	{
+        User::Leave(KErrNotFound);
+    	}
+	return Container()->FindExtensionL(aTypeId);
+    }
+
+
+EXPORT_C TInt RMetaExtensionContainer::AppendExtension(const Meta::SMetaData* aExtension)
+    {
+    __ASSERT_ALWAYS(iIsOpen, PanicMec(ENoImplementation));
+
+    if (!aExtension)
+        {
+        return KErrArgument;
+        }
+    
+    CMetaExtensionContainer* mecImpl = AppendableExtensionContainer();
+    if (!mecImpl)
+        {
+        // Do lazy creation
+        TRAPD(err, CreateExtensionContainerL());
+        if (err != KErrNone)
+            {
+            return err;
+            }
+        mecImpl = AppendableExtensionContainer();
+        }
+
+    return mecImpl->AppendExtension(aExtension);
+    }
+
+
+EXPORT_C void RMetaExtensionContainer::AppendExtensionL(const Meta::SMetaData* aExtension)
+    {
+    __ASSERT_ALWAYS(iIsOpen, PanicMec(ENoImplementation));
+
+    if (!aExtension)
+        {
+        User::Leave(KErrArgument);
+        }
+    
+    CMetaExtensionContainer* mecImpl = AppendableExtensionContainer();
+    if (!mecImpl)
+        {
+        // Do lazy creation
+        CreateExtensionContainerL();
+        mecImpl = AppendableExtensionContainer();
+        }
+
+    mecImpl->AppendExtensionL(aExtension);
+    }
+
+
+EXPORT_C void RMetaExtensionContainer::AppendContainerL(const RMetaExtensionContainerC& aContainer)
+	{
+    __ASSERT_ALWAYS(&aContainer != this, PanicMec(EInvalidSelfReference));
+	__ASSERT_ALWAYS(iIsOpen, PanicMec(ENoImplementation));
+	
+	CMetaExtensionContainerImplBase* containerImpl = static_cast<const RMetaExtensionContainer&>(aContainer).Container();
+	__ASSERT_ALWAYS(containerImpl, PanicMec(ENoImplementation));
+	__ASSERT_ALWAYS(containerImpl != Container(), PanicMec(EInvalidSelfReference));
+		
+	CMetaExtensionContainerArray* mecImpl = AppendableContainerArray();
+	if (!mecImpl)
+		{
+		// Do lazy creation
+		CreateContainerArrayL();
+		mecImpl = AppendableContainerArray();
+		}
+
+    const RMetaExtensionContainer& containerIfc = static_cast<const RMetaExtensionContainer&>(aContainer);
+	User::LeaveIfError(mecImpl->AppendContainer(*containerIfc.Container()));
+	
+	// Null the current extension container pointer forcing a new extension container to be
+	// created and appended to the array after the one that has been added
+	iCurrentExtensionContainer = NULL;
+	}
+
+
+CMetaExtensionContainer* RMetaExtensionContainer::AppendableExtensionContainer() const
+    {
+	return iIsLazyCreationDone ? iCurrentExtensionContainer : NULL;
+    }
+
+
+CMetaExtensionContainerArray* RMetaExtensionContainer::AppendableContainerArray() const
+    {
+    if (iIsLazyCreationDone)
+    	{
+		const CMetaExtensionContainerImplBase* mecImpl = Container();
+		if (mecImpl && mecImpl->Type() == CMetaExtensionContainerImplBase::EMetaExtensionContainerArray)
+			{
+			return const_cast<CMetaExtensionContainerArray*>(static_cast<const CMetaExtensionContainerArray*>(mecImpl));
+			}
+    	}
+    return NULL;
+    }
+
+