diff -r 000000000000 -r 62f9d29f7211 webservices/wsframework/src/senservicesession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webservices/wsframework/src/senservicesession.cpp Thu Jan 07 16:19:19 2010 +0200 @@ -0,0 +1,815 @@ +/* +* Copyright (c) 2002-2005 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: +* +*/ + + + + + + + + + + + +#include // for RPointerArray + +#include "SenServiceConnection.h" // session status constants +#include "senservicesession.h" +#include "SenXmlUtils.h" +#include "senpolicy.h" +#include "senserviceinvocationframework.h" +#include "senprovider.h" +#include "senidentifier.h" +#include "sentransportbase.h" + +#include "msenlayeredproperties.h" + +#include "msenremotehostlet.h" // internal + +#include "sendebug.h" +#include "senlogger.h" + +EXPORT_C CSenServiceSession::CSenServiceSession(TDescriptionClassType aType, + MSIF& aFramework) : + CSenWSDescription(aType), + iStatus(KSenConnectionStatusNew), + iFramework(aFramework), + ipTransport(NULL) + { + } + +EXPORT_C CSenServiceSession::~CSenServiceSession() + { + // The REMOTE consumers are also sessions which are + // owned by XMLDAO or ClientSession + iConsumerList.Reset(); + iFacets.ResetAndDestroy(); + if (iTransportOwned) + { + delete ipTransport; + } + ipTransport = NULL; + } + +// Constructor offered to subclasses: +EXPORT_C void CSenServiceSession::BaseConstructL() + { + TLSLOG_L(KSenCoreServiceManagerLogChannelBase , KMinLogLevel ,"CSenServiceSession::BaseConstructL - Version 2 [2006-05-09]"); + + // Sets the local name to "ServiceDescription" + // and initiates the inner ipElement + CSenWSDescription::ConstructL(); + } + +EXPORT_C TInt CSenServiceSession::InitializeFromL(MSenServiceDescription& aServiceDescription) + { + _LIT8(KTouch, "touch"); + CSenWSDescription& sd = (CSenWSDescription&)aServiceDescription; + const TDesC8* attrValue = sd.AsElement().AttrValue(KTouch); + if(attrValue != NULL) + { + AsElement().AddAttrL(KTouch, *attrValue); + } + _LIT8(KEndpointLocalname, "Endpoint"); + CSenElement* pEndpointElement = sd.AsElement().Element(KEndpointLocalname); + TPtrC8 transportCue; + if(pEndpointElement) + { + _LIT8(KCue, "cue"); + const TDesC8* cue = pEndpointElement->AttrValue(KCue); + if(cue && cue->Length()>0) + { + transportCue.Set(*cue); + SetTransportCueL(transportCue); + } + } + + if(IsLocalL()) + { + // Initialize local service sessions by trying to lookup the hostlet plug-in + // behind a local endpoint, and if such exists, by asking it to add (facet) + // data into this session. + + // Check transport cue; if such XML attribute + // has been set to 0 ) + { + hostletCue.Set( transportCue ); + } + + + + CSenProvider* pHostlet = NULL; + TInt leaveCode(KErrNone); + TRAP(leaveCode, pHostlet = CSenProvider::NewL(hostletCue)); + if(leaveCode == KErrNone && pHostlet) + { + CleanupStack::PushL(pHostlet); + + // Inside InitServiceSessionL, the hostlet can add it's facets into this + // session and possibly initialize some other data required. + CSenWSDescription* pSD = CSenWSDescription::NewLC(); + pHostlet->DescribeServiceL(*pSD); // pHostlet->InitServiceSessionL(*this); + this->InitializeFromL(*pSD); + CleanupStack::PopAndDestroy(pSD); + + + /* + CSenWSDescription* pSD = pHostlet->SessionDescriptionLC(); + // this->InitializeFacetsFromL(*pSD); + + // Copy the facets from local service provider session description + RFacetArray facets; + pSD->FacetsL(facets); + CleanupClosePushL(facets); + + TInt count(facets.Count()); + for (TInt i=0; iDes().Append(aInput); + return KErrNone; + } + +/** + * Ask the ServiceManager to save a description + * of this ServiceSession (in its DAO storage). + * + * This (convenience) method can be called from within other methods of + * ServiceSession (and/or subclasses) and by ServiceInvocationFramework + * implementations. + * + */ +EXPORT_C void CSenServiceSession::SaveL() + { + iFramework.Manager().SaveL(*this); + } + +/** + * Return the status of this ServiceSession. + * + * @return TInt the status + */ +EXPORT_C TInt CSenServiceSession::StatusL() + { + return(iStatus); + } + + + +/** + * SetStatus + * + * Compute the status of the ServiceSession. If the status + * changes to, or from, "KSenConnectionStatusReady" + * inform service consumers about the new status. + * + * @return TInt indicating the CHANGED status that was set + * + */ +EXPORT_C TInt CSenServiceSession::SetStatusL() + { + + TInt currentStatus = iStatus; + iStatus = ComputeStatusL(); + if ( (currentStatus == KSenConnectionStatusReady + && iStatus != KSenConnectionStatusReady) + || + (currentStatus != KSenConnectionStatusReady + && iStatus == KSenConnectionStatusReady) ) + { + + // notify clients + RServiceConsumerArray consumers; + CleanupClosePushL(consumers); + TInt err = Consumers(consumers); + + if(err==KErrNone) + { + TInt count = consumers.Count(); + for (TInt i=0; iSetStatusL(iStatus)); + if(error!=KErrNone) + { + TLSLOG_FORMAT((KSenCoreServiceManagerLogChannelBase , KMinLogLevel, _L8("CSenServiceSession::SetStatusL() \ + failed to set status of %d consumer, error code (%d)"), + (i+1), error)); + } + } + } + CleanupStack::PopAndDestroy(); // close() consumers + } + return(iStatus); + } + +/** + * Compute the current status of the ServiceSession. + * Subclasses __will__ override this. + * This method does not actually set the status of the ServiceSession + * and does not notify consumers about changes. + * + * @return TInt indicating the CURRENT computed status + */ +EXPORT_C TInt CSenServiceSession::ComputeStatusL() + { + TInt result = KSenConnectionStatusNew; + TPtrC8 endpoint = Endpoint(); + + if(endpoint.Length()>1) + result = KSenConnectionStatusReady; + + return result; + } + +EXPORT_C MSenRemoteServiceConsumer* CSenServiceSession::RemoteConsumerL( + const TDesC8& aSenderID) + { + TInt consumersCount(iConsumerList.Count()); + + for(TInt i=0; iId() == aSenderID) + { + return iConsumerList[i]; + } + } + return NULL; // not found + + } + + +EXPORT_C TInt CSenServiceSession::SubmitL(const TDesC8& aMessage, + const TDesC8& aTransportProperties, + MSenRemoteServiceConsumer& aConsumer, + HBufC8*& aResponse) + { +// CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenServiceSession::SubmitL"); + TPtrC8 endpoint = Endpoint(); + ////////////////////////////////////////////////////////////////////////// + //CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"***********************************************************"); + //CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Endpoint: %S"), &endpoint)); + //CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Request (%d bytes):"), aMessage.Length())); + //CSLOG_ALL(aConsumer.ConnectionId() , KMaxLogLevel,( aMessage )); + //CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"***********************************************************"); + ////////////////////////////////////////////////////////////////////////// + + delete aResponse; + aResponse = NULL; + + //MSenRemoteServiceConsumer* pConsumer = RemoteConsumerL(aSenderId); + + MSenTransport& transport = aConsumer.TransportL(); + TInt retVal( transport.SubmitL(endpoint, aMessage, aTransportProperties, aResponse,aConsumer) ); + if(retVal==KErrNone) + { + // attempt to parse the response. + + HBufC8* parsedResponse = NULL; + TInt leaveCode(KErrNone); + TRAP(leaveCode, ParseResponseL(*aResponse, parsedResponse)); + if(leaveCode!=KErrNone) + { + // response is returned as it is: unparsed (for debugging reasons) + retVal = leaveCode; + } + else + { + // parsing went OK. Release unparsed buffer + delete aResponse; + // assign the parsed buffer to aResponse + aResponse = parsedResponse; + } + } + // else directly return the error received from transport + return retVal; + } + + +/* + * @see CServiceConnection.Send(...) + */ +// add txnid, transport properties +EXPORT_C TInt CSenServiceSession::SendL( const TDesC8& aMessage, + const TDesC8& aTransportProperties, + MSenRemoteServiceConsumer& aConsumer, + TInt& aTxnId, + HBufC8*& /*aRevalidationError*/ ) + { + //CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"CSenServiceSession::SendL:"); + TPtrC8 endpoint = Endpoint(); + ////////////////////////////////////////////////////////////////////////// + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"***********************************************************"); + //CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Endpoint: %S"), &endpoint)); + //CSLOG_FORMAT((aConsumer.ConnectionId() , KMaxLogLevel, _L8("- Request (%d bytes):"), aMessage.Length())); + //CSLOG_ALL(aConsumer.ConnectionId() , KMaxLogLevel,( aMessage )); + CSLOG_L(aConsumer.ConnectionId() , KMaxLogLevel,"***********************************************************"); + ////////////////////////////////////////////////////////////////////////// + MSenTransport& t = aConsumer.TransportL(); + TInt retVal(t.SendL(endpoint, aMessage, aTransportProperties, *this, aConsumer, aTxnId)); + return retVal; + } + + +/* + * @see CServiceConnection.IsReadyL() + * *** Note: in Java reference implementation method's was named "isValid()"! + */ +EXPORT_C TBool CSenServiceSession::IsReadyL() + { + return (iStatus==KSenConnectionStatusReady); + } + +EXPORT_C TInt CSenServiceSession::CompleteServerMessagesOnOffL( + const TBool& aCompleteOnOff) + { + + if (aCompleteOnOff) + { + CSenFacet* pFacet = CSenFacet::NewL(); + CleanupStack::PushL(pFacet); + pFacet->SetNameL(KCompleteMessagesFacet); + pFacet->SetValueL(KSenFacetValTrue); + SetFacetL(*pFacet); + CleanupStack::PopAndDestroy(); // pFacet + } + else + { + RemoveFacet(KCompleteMessagesFacet); + } + + return KErrNone; + } + + +EXPORT_C TInt CSenServiceSession::HasFacetL(const TDesC8& aURI, TBool& aHasFacet) + { + aHasFacet = EFalse; + TInt count(iFacets.Count()); + + for (TInt i=0;iName() == aURI) + { + aHasFacet = ETrue; + } + } + + return KErrNone; + } + +EXPORT_C TInt CSenServiceSession::FacetValue(TDesC8& aURI, HBufC8*& aValueTo) + { + delete aValueTo; + aValueTo = NULL; + + TInt retVal = KErrNotFound; + TInt count(iFacets.Count()); + + for (TInt i=0; iName() == aURI) + { + aValueTo = iFacets[i]->Value().Alloc(); + if (aValueTo == NULL) + { + retVal = KErrNoMemory; + } + else + { + retVal = KErrNone; + } + } + } + return retVal; + } + +EXPORT_C TInt CSenServiceSession::AddFacetL(const CSenFacet& aFacet) + { + // In XML SD, this does not equal with SetFacetL(), but checks + // for duplicate, already reserved facet name and returns an + // error if such exists. + return SetFacetL(aFacet); + } + +EXPORT_C TInt CSenServiceSession::SetFacetL(const CSenFacet& aFacet) + { + TBool hasFacet; + HasFacetL(((CSenFacet&)aFacet).Name(),hasFacet); + if (hasFacet) + { + RemoveFacet(((CSenFacet&)aFacet).Name()); + } + CSenFacet* pNewFacet = CSenFacet::NewL(((CSenFacet&)aFacet)); + return iFacets.Append(pNewFacet); + } + +EXPORT_C TInt CSenServiceSession::RemoveFacet(const TDesC8& aURI) + { + TInt count(iFacets.Count()); + + for (TInt i=0;iName() == aURI) + { + delete iFacets[i]; + iFacets.Remove(i); + return KErrNone; + } + } + + return KErrNotFound; + } + +EXPORT_C TInt CSenServiceSession::FacetsL(RFacetArray& aFacetArray) + { + CSenFacet* pFacet = NULL; + TInt count(iFacets.Count()); + for (TInt i=0; i 0) && (aPattern.FrameworkId() == FrameworkId()) ) ) + { + if ((aPattern.Endpoint().Length() > 0) && (aPattern.Endpoint() == Endpoint())) + { + score = score + KSenServiceDescriptionBaseScore; + } + if ((aPattern.Contract().Length() > 0) && (aPattern.Contract() == Contract())) + { + score = score + KSenServiceDescriptionBaseScore; + } + } + + + if ( score > 0 ) + { + RFacetArray otherFacets; + CleanupClosePushL(otherFacets); + aPattern.FacetsL(otherFacets); + + HBufC8* pFacetValue = NULL; + TPtrC8 facetName; + + TInt count(otherFacets.Count()); + for (TInt i=0; iName()); + FacetValue(facetName,pFacetValue); + if (pFacetValue && *pFacetValue == otherFacets[i]->Value()) score++; + delete pFacetValue; + pFacetValue = NULL; + } + + otherFacets.ResetAndDestroy(); + CleanupStack::Pop(); + + if ( ipHostlet ) + { + score++; + } + } + + return score; + } + +EXPORT_C TBool CSenServiceSession::Matches(MSenServiceDescription& aOtherServiceDescription) + { + TPtrC8 patternEndpoint = aOtherServiceDescription.Endpoint(); + TPtrC8 thisEndpoint = Endpoint(); + + if(patternEndpoint.Length()>0) + { + if(!(thisEndpoint.Length()>0 && patternEndpoint == thisEndpoint)) + { + return EFalse; + } + } + + TPtrC8 patternContract = aOtherServiceDescription.Contract(); + TPtrC8 thisContract = Contract(); + + if(patternContract.Length()>0) + { + if(!(thisContract.Length()>0 && patternContract == thisContract)) + { + return EFalse; + } + } + + TPtrC8 patternFrameworkId = aOtherServiceDescription.FrameworkId(); + TPtrC8 thisFrameworkId = FrameworkId(); + if(patternFrameworkId.Length()>0) + { + if(!(thisFrameworkId.Length()>0 && patternFrameworkId == thisFrameworkId)) + { + return EFalse; + } + } + + + TBool match(ETrue); + TRAPD(retVal, + RFacetArray otherFacets; + CleanupClosePushL(otherFacets); + aOtherServiceDescription.FacetsL(otherFacets); + + TPtrC8 facetName; + TInt count(otherFacets.Count()); + for (TInt i=0; iName()); + HasFacetL(facetName, match); + } + otherFacets.ResetAndDestroy(); + CleanupStack::Pop(); // otherFacets + ); + return match; + } + +// implement the MSenRemoteServiceSession: +EXPORT_C TPtrC8 CSenServiceSession::Endpoint() + { + return CSenWSDescription::Endpoint(); + } + +EXPORT_C TPtrC8 CSenServiceSession::Contract() + { + return CSenWSDescription::Contract(); + } + +// implement the MSenRemoteServiceSession: +EXPORT_C TPtrC8 CSenServiceSession::FrameworkId() + { + return CSenWSDescription::FrameworkId(); + } + + +EXPORT_C RFileLogger* CSenServiceSession::Log() const + { + return iFramework.Manager().Log(); + } + +EXPORT_C void CSenServiceSession::WriteExtensionsAsXMLToL(RWriteStream& aWriteStream) + { + HBufC8* pFacetAsXML = NULL; + + TInt count(iFacets.Count()); + for (TInt i=0; iName() != KCompleteMessagesFacet) + { + pFacetAsXML = iFacets[i]->AsXmlL(); + CleanupStack::PushL(pFacetAsXML); + aWriteStream.WriteL(*pFacetAsXML); + CleanupStack::PopAndDestroy(1); // pFacetAsXML + } + } + } + +// This base class implementation passes the properties directly to consumer's transport +EXPORT_C TInt CSenServiceSession::SetTransportPropertiesL( const TDesC8& aProperties, + MSenRemoteServiceConsumer& aConsumer ) + { + + return aConsumer.TransportL().SetPropertiesL(aProperties, MSenLayeredProperties::ESenConsumerSessionLayer, &aConsumer); + } + +EXPORT_C TInt CSenServiceSession::TransportPropertiesL(HBufC8*& aProperties, + MSenRemoteServiceConsumer& aConsumer ) + { + return aConsumer.TransportL().PropertiesL(aProperties); + } + +EXPORT_C MSenServiceDescription::TDescriptionClassType CSenServiceSession::DescriptionClassType() + { + return CSenWSDescription::DescriptionClassType(); + } + + + +EXPORT_C MSenServiceDescription& CSenServiceSession::AsServiceDescription() + { + return *this; + } + +EXPORT_C TInt CSenServiceSession::RemoveConsumerL(MSenRemoteServiceConsumer& aConsumer) + { + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel ,"CSenServiceSession::RemoveConsumerL"); + TInt count(iConsumerList.Count()); + TInt index(KErrNotFound); + for ( TInt i = 0; i < count; i++ ) + { + MSenRemoteServiceConsumer* consumer = iConsumerList[i]; + if ( consumer ) + { + if ( consumer == &aConsumer ) + { + // match + index = i; + break; + } + + if ( consumer->Id() == aConsumer.Id() ) + { + // match + index = i; + break; + } + } + } + if( index != KErrNotFound ) + { + //CSLOG_FORMAT((aConsumer.ConnectionId() , KNormalLogLevel, _L8("- Removing consumer: %d/%d"), (index+1), iConsumerList.Count())); + iConsumerList.Remove(index); + index = KErrNone; // success + //CSLOG_FORMAT((aConsumer.ConnectionId() , KNormalLogLevel, _L8("- Consumer count now: %d"), iConsumerList.Count())); + //CSLOG_FORMAT((aConsumer.ConnectionId() , KNormalLogLevel, _L8("- Hostlet: %d"), ipHostlet?1:0)); + //CSLOG_FORMAT((aConsumer.ConnectionId() , KNormalLogLevel, _L8("- Transport: %d"), ipTransport?1:0)); + + if(ipTransport && iConsumerList.Count() == 0 && !ipHostlet) + { + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"- this session has no consumer(s) and no hostlet; deleting the transport -- START:"); + delete ipTransport; + CSLOG_L(aConsumer.ConnectionId() , KMinLogLevel,"- deleting transport --- END"); + ipTransport = NULL; + } + } + if (iTransportOwned) + { + delete ipTransport; + ipTransport = NULL; + } + + return index; + } + +EXPORT_C void CSenServiceSession::SetTransportL(CSenTransportBase* aTransport) + { + if (aTransport) + { + if(ipTransport && ipTransport != aTransport) + { + // delete the current transport, if it does not match with new one + delete ipTransport; // this will naturally cancel all pending txns + ipTransport = NULL; + } + ipTransport = aTransport; + iTransportOwned = aTransport->SessionOwned(); + } + } +EXPORT_C MSenTransport* CSenServiceSession::Transport() const + { + return ipTransport; + } + +EXPORT_C MSenTransport& CSenServiceSession::TransportL(MSenRemoteServiceConsumer& aRequestor) + { + if(!ipTransport) + { + MSenTransport& transport = aRequestor.TransportL(); + ipTransport = (CSenTransportBase*) &transport; + } + return *ipTransport; + } + +EXPORT_C TInt CSenServiceSession::SetHostletL(MSenRemoteHostlet* aHostlet) + { + ipHostlet = aHostlet; + if(!ipHostlet && iConsumerList.Count() == 0) + { + delete ipTransport; + ipTransport = NULL; + } + return KErrNone; // return value not used atm + } + +EXPORT_C MSenRemoteHostlet* CSenServiceSession::Hostlet() const + { + return ipHostlet; + } + +EXPORT_C TBool CSenServiceSession::HasSuperClass( TDescriptionClassType aType ) + { + if( aType == MSenServiceDescription::EWSDescription ) // direct superclass! + { + // If asked type is the know *direct* father/mother, return true: + return ETrue; + } + else + { + // Otherwise, ask from superclass (chain, recursively) + return CSenWSDescription::HasSuperClass( aType ); + } + } + +EXPORT_C TInt CSenServiceSession::SendToHostletL(MSenRemoteHostlet& aReceiver, + const TDesC8& aMessage, + const TInt aTxnId, + MSenRemoteServiceConsumer& aFrom, + MSenProperties* /* aProperties */) + { + // default impelementation routes the request directly to the hostlet + // Handler aware framework could load the required handlers in here + // to enable addressing / message correlation etc. + return aReceiver.ProcessRequestFromConsumerL(aMessage, aTxnId, aFrom /*, aProperties */); + } + +EXPORT_C TInt CSenServiceSession::ProvideHostletResponseL( MSenRemoteHostlet& /* aProvider */, + const TInt aTxnId, + const TInt aServiceCode, + const TDesC8& /* aRecipientsConsumerId */, + CSenChunk& /* aMessageChunk */ ) + { + TLSLOG_L(KSenCoreServiceManagerLogChannelBase , KMinLogLevel ,"CSenServiceSession::ProvideHostletResponseL"); + TInt retVal(KErrNone); + MSenTransport* pTransport = Transport(); + if ( pTransport ) + { + TLSLOG_FORMAT((KSenCoreServiceManagerLogChannelBase , KMinLogLevel, _L8("- Completing the transaction %d"), aTxnId)); + retVal = pTransport->CompleteTransaction( aTxnId, aServiceCode ); + } + else + { + TLSLOG_L(KSenCoreServiceManagerLogChannelBase , KMinLogLevel ,"- Fatal - Transport is NULL."); + retVal = KErrSenInternal; + } + return retVal; + } + +EXPORT_C TInt CSenServiceSession::SetTransportCueL(const TDesC8& aCue) + { + return CSenWSDescription::SetTransportCueL(aCue); + } + +EXPORT_C TPtrC8 CSenServiceSession::TransportCue() + { + return CSenWSDescription::TransportCue(); + } + +EXPORT_C TInt CSenServiceSession::RefreshMTL(HBufC8*& /*aRevalidationError*/) + { + return KErrNotSupported; + } + +// End of File +