diff -r 000000000000 -r 7f85d04be362 upnpmediaserver/contentdirectoryservice/src/upnpcontentdirectorydb.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnpmediaserver/contentdirectoryservice/src/upnpcontentdirectorydb.cpp Thu Dec 17 08:52:00 2009 +0200 @@ -0,0 +1,1418 @@ +/** @file +* Copyright (c) 2005-2006 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: Database for MediaServer + * +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +#include "upnpprotocolinfo.h" + +#include "upnpfileutils.h" +#include "upnpcontentdirectorydb.h" +#include "upnpcontentdirectoryglobals.h" +#include "upnpelementfactory.h" +#include "upnpelementbean.h" +#include "upnpobjectbean.h" +#include "upnpattributebean.h" +#include "upnpfilterelement.h" +#include "upnpresourcesbean.h" +#include "upnpcdutils.h" +#include "upnpcddbfactory.h" +#include "upnpmetadatastorage.h" + +#define KLogFile _L("ContentDirectoryDb.log") +#include "upnpcustomlog.h" + +// ============================= LOCAL FUNCTIONS =============================== +// ----------------------------------------------------------------------------- +// CleanupFilterElementPointerArray +// Used by TCleanupItem to clean a RPointerArray +// ----------------------------------------------------------------------------- +// +void CleanupFilterElementPointerArray( TAny* aArray ) + { + (reinterpret_cast*> (aArray))->ResetAndDestroy( ); + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::CUpnpContentDirectoryDb +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CUpnpContentDirectoryDb::CUpnpContentDirectoryDb( + CUpnpMetadataStorage* aMetadataStorage ) + { + iMetadataStorage =aMetadataStorage; + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::ConstructL() + { + iDOMImpl.OpenL( ); + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CUpnpContentDirectoryDb* CUpnpContentDirectoryDb::NewLC( + CUpnpMetadataStorage* aMetadataStorage ) + { + CUpnpContentDirectoryDb* self = new ( ELeave ) CUpnpContentDirectoryDb(aMetadataStorage); + CleanupStack::PushL( self ); + self->ConstructL( ); + return self; + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CUpnpContentDirectoryDb* CUpnpContentDirectoryDb::NewL( + CUpnpMetadataStorage* aMetadataStorage ) + { + CUpnpContentDirectoryDb* self = NewLC( aMetadataStorage ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::~~CUpnpContentDirectoryDb +// Destructor +// ----------------------------------------------------------------------------- +// +CUpnpContentDirectoryDb::~CUpnpContentDirectoryDb() + { + iDOMImpl.Close( ); + LOGCD( "CUpnpContentDirectoryDb::~CUpnpContentDirectoryDb", "", 0, + "DataBase closed" ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::InsertObjectL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::InsertObjectL( + RXmlEngDocument& aFragment, TInt aContainerId, TInt* aId ) + { + TUpnpErrorCode ret( EUpnpUndefined ); + // get object element + TXmlEngElement element = UpnpCdUtils::GetObjectElementL( aFragment ); + + // start transaction + iMetadataStorage->BeginTransactionL( ); + + TRAPD( err, ret = DoInsertObjectL( element, aContainerId, aId ) ); + if ( err ) + { // rollback if error + iMetadataStorage->RollbackTransactionL( ); + User::Leave( err ); + } + iMetadataStorage->CommitTransactionL( ); + + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjectListL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::GetObjectListL( TInt aParentId, + RArray& aList ) + { + return iMetadataStorage->GetObjectListL( aParentId, aList ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjectListL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::GetObjectListL( const RArray& aIds, + const TDesC8& aFilter, RArray& aObjs ) + { + for ( TInt i = 0; i < aIds.Count( ); i++ ) + { + RXmlEngDocument obj; + CleanupClosePushL( obj ); + GetObjectL( aIds[i], obj, aFilter ); + aObjs.AppendL( obj ); + CleanupStack::Pop( &obj ); + } + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::DeleteObjectL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::DeleteObjectL( TInt aObjId, + RArray& aRefList, TBool aDeleteResource ) + { + return iMetadataStorage->DeleteObjectL( aObjId, aRefList, aDeleteResource ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::UpdateObjectL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::UpdateObjectL( TInt aObjId, + RXmlEngDocument& aFragment ) + { + TUpnpErrorCode ret = EUpnpUndefined; + + // // get object element + TXmlEngElement element = UpnpCdUtils::GetObjectElementL( aFragment ); + + // start transaction + iMetadataStorage->BeginTransactionL( ); + + TRAPD( err, ret = DoUpdateObjectL( aObjId, element ) ); + if ( err ) + { // rollback - error + iMetadataStorage->RollbackTransactionL( ); + User::Leave( err ); + } + // commit if success + iMetadataStorage->CommitTransactionL( ); + + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::DoUpdateObjectL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::DoUpdateObjectL( TInt aObjId, + TXmlEngElement aFragment ) + { + TUpnpErrorCode ret = EUpnpUndefined; + + // delete object + ret = iMetadataStorage->DoDeleteObjectL( aObjId, EFalse, EFalse ); + TXmlEngElement el = aFragment; + ret = InsertUpdatedL( aObjId, el ); + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::InsertUpdatedL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::InsertUpdatedL( TInt aObjId, + TXmlEngElement& aElement ) + { + TUpnpErrorCode ret = EUpnpUndefined; + iMetadataStorage->InsertObjectIntoObjectTableL( aElement ); + ret = EUpnpOk; + RXmlEngNodeList elements; + CleanupClosePushL( elements ); + aElement.GetChildElements( elements ); + + while ( elements.HasNext( ) ) + { + TXmlEngElement el = elements.Next( ); + if ( el.Name().CompareF( KClassTagName ) && el.Name().CompareF( KTitleTagName ) ) + { + ret = InsertElementL( el, aObjId ); + } + else + { + UpnpCdUtils::IsElementRequiredL( el ); // just remove the marker attr + } + } + CleanupStack::PopAndDestroy( &elements ); + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::InsertElementL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::InsertElementL( + const TXmlEngElement& aElement, TInt aObjId ) + { + return InsertAttributesL( aElement, iMetadataStorage->InsertElementL( + aElement, aObjId ), aObjId ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::PrepareDidlDocumentL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +RXmlEngDocument CUpnpContentDirectoryDb::PrepareDidlDocumentL() + { + RXmlEngDocument doc; + doc.OpenL( iDOMImpl ); + TXmlEngElement el = doc.CreateDocumentElementL( KDidlLite( ) ); + el.AddNamespaceDeclarationL( KXmlnsNsUri( ), KCmlnsNsPref( ) ); + el.AddNamespaceDeclarationL( KDcNsUri( ), KDcNsPref( ) ); + el.AddNamespaceDeclarationL( KUpnpNsUri( ), KUpnpNsPref( ) ); + return doc; + + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::CheckObjectRestrictionL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::CheckObjectRestrictionL( TInt aObjId ) + { + return iMetadataStorage->CheckObjectRestrictionL( aObjId ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjectL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +TUpnpErrorCode CUpnpContentDirectoryDb::GetObjectL( TInt aObjectID, + RXmlEngDocument& aDoc, const TDesC8& aFilterString ) + { + TUpnpErrorCode ret = EUpnpUndefined; + + if ( aFilterString == KAsterisk8 ) + { // get the whole object + ret = DoGetObjectL( aObjectID, aDoc, ETrue ); + } + else if ( !aFilterString.Length( ) ) + { // get only required properties + ret = DoGetObjectL( aObjectID, aDoc, EFalse ); + } + else + { + RXmlEngDocument doc; // before the whole obj is created do not change the given reference, + CleanupClosePushL( doc ); // it prevents from returning not completed object if something goes wrong + // during construction of response object + // get required properties + ret = DoGetObjectL( aObjectID, doc, EFalse ); + if ( ret == EUpnpOk ) // do not not continue if something went wrong + { + // prepare a list of filter elements + RPointerArray filterElements; + TCleanupItem cleanupItem( CleanupFilterElementPointerArray, + &filterElements ); + CleanupStack::PushL( cleanupItem ); + // parse filter string + ParseFilterStringL( aFilterString, filterElements ); + // add requested elements + AddRequestedPropertiesL( aObjectID, + UpnpCdUtils::GetObjectElementL( doc ), filterElements ); // ignore if error + //clean up + CleanupStack::PopAndDestroy( &filterElements ); + } + if ( ret == EUpnpOk ) + { // object is completed + aDoc = doc; + CleanupStack::Pop( &doc ); + } + else + { // something went wrong + CleanupStack::PopAndDestroy( &doc ); + } + + } + + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjectL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +TUpnpErrorCode CUpnpContentDirectoryDb::AddRequestedPropertiesL( + TInt aObjectID, TXmlEngElement aElement, + const RPointerArray& aFilterElements ) + { + TUpnpErrorCode ret = EUpnpUndefined; + // aFilterElements must be sorted + for ( TInt i = 0; i < aFilterElements.Count( ); i++ ) + { + const CUpnpFilterElement* filter = aFilterElements[i]; + if ( filter->ElementName().Length( ) ) + { // element part defined + AddElementL( aElement, aObjectID, filter ); + } + else + { // element part not defined - it is attribute of main element tag + for ( TInt j = 0; j < filter->Count( ); j++ ) + { + if ( (*filter)[j] == KChildCount ) + { + SetChildCountL( aElement, aObjectID ); + ret = EUpnpOk; + } + else + { + ret = iMetadataStorage->AddMainTagAttrL( aElement, + aObjectID, (*filter)[j] ); + } + } + } + } + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::SetChildCountL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +void CUpnpContentDirectoryDb::SetChildCountL( TXmlEngElement aElement, + TInt aId ) + { + if ( aElement.Name( ) == KContainer ) + { + // value + TInt childCount = iMetadataStorage->GetChildCountL( aId ); + TBuf8 num; + num.Num( childCount ); + + // is it already exist? + TXmlEngAttr childAttr = aElement.AttributeNodeL( KChildCount( ) ); + if ( childAttr.IsNull( ) ) + { // not exist - add + aElement.AddNewAttributeL( KChildCount( ), num ); + } + else + { // already exists - update + childAttr.SetValueL( num ); + } + } + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::AddElementL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +void CUpnpContentDirectoryDb::AddElementL( TXmlEngElement aElement, + TInt aObjectID, const CUpnpFilterElement* aReqElement ) + { + // get elements from database + RDbView view = iMetadataStorage->GetElementViewL( aObjectID, + aReqElement->ElementName( ) ); + CleanupClosePushL( view ); + + // for each element found + while ( view.NextL( ) ) + { + view.GetL( ); + CUpnpElementBean* elBean = CUpnpElementBean::NewLC( view ); + + // add element + TXmlEngElement newElement = elBean->AttachElmL( aElement ); + + // add required attributes + AddAttributesL( elBean->ElmId( ), aObjectID, newElement, EFalse ); + + // for each requested attribute + for ( TInt i = 0; i < aReqElement->Count( ); i++ ) + { + TPtrC8 attrNamePtr((*aReqElement)[i]); + + TXmlEngAttr attr = newElement.AttributeNodeL( attrNamePtr ); + // add if not present + // ignore if element has not any attribute + if ( attr.IsNull( ) && elBean->ElmHasAttribute( ) ) + { + AddAttributeL( newElement, attrNamePtr, elBean->ElmId( ), + aObjectID ); + } + } + // clean up + CleanupStack::PopAndDestroy( elBean ); + } + // clean up + CleanupStack::PopAndDestroy( &view ); + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::ParseFilterStringL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::ParseFilterStringL( const TDesC8& aFilter, + RPointerArray& aList ) + { + // separate filter's parts + CDesC8ArrayFlat* list = new(ELeave) CDesC8ArrayFlat(KDefaultGranularity); + CleanupStack::PushL( list ); + TInt commaPos; + TPtrC8 filter(aFilter); + while ( (commaPos = filter.Find( KCommaStr8( ) ) ) != KErrNotFound ) + { + HBufC8* buf = filter.Left(commaPos).AllocLC( ); + buf->Des().TrimAll( ); + list->AppendL( *buf ); + filter.Set( filter.Mid( commaPos+1 ) ); + CleanupStack::PopAndDestroy( buf ); + } + // add last + HBufC8* buf = filter.AllocLC( ); + buf->Des().TrimAll( ); + list->AppendL( *buf ); + filter.Set( filter.Mid( commaPos+1 ) ); + CleanupStack::PopAndDestroy( buf ); + + // sort to simplify + list->Sort( ); + + TPtrC8 curr( KMinusOne8 ); + for ( TInt i = 0; i< list->Count( ); i++ ) // for each filter property + { + // split filter string - element@attribute + TInt atPos = (*list)[i].Find( KAtStr8 ); + TPtrC8 attr; + if ( atPos == KErrNotFound ) // is it element name + { // it is element + attr.Set( KNullDesC8 ); + atPos = (*list)[i].Length( ); + } + else + { + attr.Set( (*list)[i].Mid( atPos+1 ) ); + } + TPtrC8 element((*list)[i].Left( atPos ) ); + + // do not add "class" and "title" elements - required by default + if ( element.CompareF( KClassTagNameWithNs8 ) + && element.CompareF( KTitleTagNameWithNs8 ) ) + { // it is neither a class nor title element + if ( element == curr ) + { // already exists, add next attribute + if ( attr.Length( ) ) // ignore empty attr + aList[aList.Count()-1]->AppendAttributeL( attr ); + } + else + { // create new filter element + CUpnpFilterElement* tmp = CUpnpFilterElement::NewLC( ); + tmp->SetElementNameL( element ); + if ( attr.Length( ) ) // ignore epmty attr + tmp->AppendAttributeL( attr ); + aList.AppendL( tmp ); + CleanupStack::Pop( tmp ); + curr.Set( element ); + } + } + } + // clean up + CleanupStack::PopAndDestroy( list ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::DoGetObjectL +// Function returns DIDL-Lite XML fragment with metadata for requested object. +// IMPORTANT: 1. Caller takes responsibility for returned document and is +// obliged to close it. +// 2. The root element of the document is element and +// the object's element is its direct, onluy child. +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::DoGetObjectL( TInt aObjectID, + RXmlEngDocument& aDoc, TBool aAll ) + { + TUpnpErrorCode ret = EUpnpUndefined; + RDbView view = iMetadataStorage->GetObjViewL( aObjectID ); + CleanupClosePushL( view ); + + // Get result + if ( view.FirstL( ) ) + { + // get row + view.GetL( ); + + // prepare DIDL-Lite + RXmlEngDocument doc; + CleanupClosePushL( doc ); + doc = PrepareDidlDocumentL( ); + + // object bean + CUpnpObjectBean* objBean = CUpnpObjectBean::NewLC( view ); + TXmlEngElement objElement; + + if ( aAll ) + { // all object's properties + objElement + = objBean->AttachWholeObjectElL( doc.DocumentElement( ) ); + // childCount + SetChildCountL( UpnpCdUtils::GetObjectElementL( doc ), + objBean->ObjId( ) ); + } + else + { // only required + objElement = objBean->AttachObjectElL( doc.DocumentElement( ) ); + } + + // clean up + CleanupStack::PopAndDestroy( objBean ); + + // aObjectID might be a reference object, so trying to get real object id + TInt realObjectId = ReferedObjectIdL( aObjectID ); + + // add elements to the tree + AddElementsL( realObjectId, objElement, aAll ); + + // assign to the given reference + aDoc = doc; + // everything went right + ret = EUpnpOk; + // do not remove doc + CleanupStack::Pop( &doc ); + } + else + { // the is no such object + ret = ENoSuchObject; + } + // clean up + CleanupStack::PopAndDestroy( &view ); + + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::AddElementsL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::AddElementsL( TInt aObjectID, + TXmlEngElement aObjectElement, TBool aAll ) + { + RDbView view = iMetadataStorage->GetElementsViewL( aObjectID, aAll ); + CleanupClosePushL( view ); + // Iterate through elements + while ( view.NextL( ) ) + { + view.GetL( ); + CUpnpElementBean* elBean = CUpnpElementBean::NewLC( view ); + + // add new element + TXmlEngElement newElement = elBean->AttachElmL( aObjectElement ); + + // add attributes + AddAttributesL( elBean->ElmId( ), aObjectID, newElement, aAll ); + + // clean up + CleanupStack::PopAndDestroy( elBean ); + } + // clean up + CleanupStack::PopAndDestroy( &view ); + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::AddAttributesL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::AddAttributesL( TInt aElementId, + TInt aObjectID, TXmlEngElement& aElement, TBool aAll ) + { + RDbView view = iMetadataStorage->GetAttributesViewByObjectIdL( aObjectID, + aAll ); + CleanupClosePushL( view ); + + CDbColSet* colSet = view.ColSetL( ); + const TInt elmIdColNo = colSet->ColNo( KAtrElmIdColName ); + delete colSet; + + // Iterate through attributes + while ( view.NextL( ) ) + { + view.GetL( ); + + if ( view.ColInt( elmIdColNo ) == aElementId ) + { + CUpnpAttributeBean* atr = CUpnpAttributeBean::NewLC( view ); + atr->AttachAttrL( aElement ); + CleanupStack::PopAndDestroy( atr ); + } + } + // clean up + CleanupStack::PopAndDestroy( &view ); + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::DoInsertObjectL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::DoInsertObjectL( + TXmlEngElement& aElement, TInt aContainerId, TInt* aId ) + { + TUpnpErrorCode ret = EUpnpUndefined; + + *aId = SetObjectIdL( aElement ); + UpnpCdUtils::SetContainerIdL( aElement, aContainerId ); + iMetadataStorage->InsertObjectIntoObjectTableL( aElement ); + ret = EUpnpOk; + RXmlEngNodeList elements; + CleanupClosePushL( elements ); + aElement.GetChildElements( elements ); + + while ( elements.HasNext( ) ) + { + TXmlEngElement el = elements.Next( ); + if ( el.Name().CompareF( KClassTagName ) && el.Name().CompareF( KTitleTagName ) ) + { + ret = InsertElementL( el, *aId ); + } + else + { + UpnpCdUtils::IsElementRequiredL( el ); // just remove the marker attr + } + } + // set object childCount + SetChildCountL( aElement, *aId ); + + CleanupStack::PopAndDestroy( &elements ); + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::InsertAttributesL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::InsertAttributesL( + const TXmlEngElement aElement, TInt aElmId, TInt aObjId ) + { + TUpnpErrorCode ret = EUpnpUndefined; + RXmlEngNodeList list; + CleanupClosePushL( list ); + aElement.GetAttributes( list ); + if ( list.Count( ) ) + { + RArray attributes; // to store real attr + CleanupClosePushL( attributes ); + RArray markers; // to store marker attr + CleanupClosePushL( markers ); + // separate markers from attr + while ( list.HasNext( ) ) + { + TXmlEngAttr attr = list.Next( ); + if ( attr.Name().Match( KRequiredAtrSufPattern ) == KErrNotFound ) + { + attributes.AppendL( attr ); + } + else + { + markers.AppendL( attr ); + } + } + + // insert attributes + for ( TInt i = 0; i < attributes.Count( ); i++ ) + { + iMetadataStorage->InsertAttributeL( attributes[i], aElmId, + IsAttrRequiredL( attributes[i], markers ), aObjId ); + ret = EUpnpOk; + } + // remove markers from DOM tree + for ( TInt i = 0; i < markers.Count( ); i++ ) + { + markers[i].Remove( ); + } + // clean up + CleanupStack::PopAndDestroy( &markers ); + CleanupStack::PopAndDestroy( &attributes ); + } + else + { + ret = EUpnpOk; + } + + CleanupStack::PopAndDestroy( &list ); + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::IsAttrRequiredL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CUpnpContentDirectoryDb::IsAttrRequiredL( const TXmlEngAttr& aAttr, + RArray& aMarkers ) + { + TBool ret = EFalse; + + for ( TInt i = 0; i< aMarkers.Count( ); i++ ) + { + if ( aMarkers[i].Name().Find( aAttr.Name( ) ) == 0 ) + { // attr required + ret = ETrue; + break; + } + } + + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::SetObjectIdL +// Sets the id val in the objected to be created +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::SetObjectIdL( TXmlEngElement& aElement ) + { + TInt ret = iMetadataStorage->GetNextKeyL( KObjectTableName8 ); + UpnpCdUtils::SetObjectIdL( aElement, ret ); + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjectIdL +// Gets the id val in the objected to be created +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::GetObjectIdL() + { + TInt ret = iMetadataStorage->NextKeyL( KObjectTableName8 ); + + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjectIdL +// Gets the id val in the objected to be created +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +HBufC8* CUpnpContentDirectoryDb::GetObjectTitleL( TInt aId ) + { + return iMetadataStorage->GetObjectTitleL( aId ); + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::ReferedObjectIdL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::ReferedObjectIdL( TInt aObjectId ) + { + TInt ret = KErrNotFound; + + TInt refId = iMetadataStorage->ReferedObjectIdL( aObjectId ); + + if ( refId != KErrNotFound ) + { + ret = ReferedObjectIdL( refId ); + } + else + { + ret = aObjectId; + } + + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetElIdByAttrL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::GetObjIdByAttrL( const TDesC8& aAttrName, + const TDesC8& aAttrVal ) + { + TInt objId = KErrNotFound; + + TInt elmId = iMetadataStorage->GetElmIdForAttrL( aAttrName, aAttrVal ); + if ( elmId != KErrNotFound ) + { + objId = iMetadataStorage->GetObjIdForElmIdL( elmId ); + } + + return objId; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjIdByAttrLikeL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::GetObjIdByAttrLikeL( const TDesC8& aAttrName, + const TDesC8& aAttrVal ) + { + TInt objId = KErrNotFound; + + TInt elmId = iMetadataStorage->GetElmIdForAttrLikeL( aAttrName, aAttrVal ); + if ( elmId != KErrNotFound ) + { + objId = iMetadataStorage->GetObjIdForElmIdL( elmId ); + } + + return objId; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjectByAttrL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::GetObjectByAttrL( + RXmlEngDocument& aDoc, TInt* aObjId, const TDesC8& aAttrName, + const TDesC8& aAttrVal ) + { + TUpnpErrorCode ret = EUndefined; + + *aObjId = GetObjIdByAttrL( aAttrName, aAttrVal ); + if ( *aObjId >= 0 ) + { + ret = GetObjectL( *aObjId, aDoc, KAsterisk8 ); + } + else + { // something went wrong + ret = ENoSuchObject; + } + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::CheckParentRestrictionL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUpnpErrorCode CUpnpContentDirectoryDb::CheckParentRestrictionL( TInt aObjId ) + { + return iMetadataStorage->CheckParentRestrictionL( aObjId ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::DeleteResourceL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::DeleteResourceL( const TDesC8& aResVal, + RArray& aContIds ) + { + // start transaction + iMetadataStorage->BeginTransactionL( ); + + TRAPD( err, DoDeleteResourceL( aResVal, aContIds ) ); + if ( err != KErrNone ) + { // rollback - error + iMetadataStorage->RollbackTransactionL( ); + User::Leave( err ); + } + // commit if success + iMetadataStorage->CommitTransactionL( ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::DoDeleteResourceL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::DoDeleteResourceL( const TDesC8& aResVal, + RArray& aContIds ) + { + HBufC* resVal = HBufC::NewLC( aResVal.Length( ) ); + resVal->Des().Copy( aResVal ); + + HBufC* resValReplaced16 = UpnpCdUtils::EscapeAposL( *resVal ); + CleanupStack::PushL( resValReplaced16 ); + HBufC8* resValReplaced8 = UpnpCdUtils::DesToDes8LC( *resValReplaced16 ); + RArray objs; + CleanupClosePushL( objs ); + GetObjectsByResourceL( objs, *resValReplaced16 ); + + // not any obj? + if ( !objs.Count( ) ) + { + User::Leave( ENoSourceResource ); + } + + TUpnpErrorCode err = EUpnpOk; + + // for each object + for ( TInt i = 0; i < objs.Count( ); i++ ) + { + CUpnpObjectBean* objBn = GetObjBeanLC( objs[i] ); + if ( !objBn->ObjRestricted( ) ) + { + if ( CheckObjectRestrictionL( objBn->ObjParentId( ) ) == EUpnpOk ) + { + iMetadataStorage->DeleteResElL( *resValReplaced16, + objBn->ObjId( ) ); + aContIds.AppendL( objBn->ObjParentId( ) ); + } + else + { + err = ERestrictedParentObject; + } + } + else + { + err = ERestrictedObject; + } + CleanupStack::PopAndDestroy( objBn ); + } + + // was any deleted + if ( !aContIds.Count( ) ) + { + User::Leave( err ); + } + + // if each deleted? + if ( aContIds.Count( ) == objs.Count( ) ) + { + // try to fetch resource id + TRAPD( err, UpnpCdUtils::ResIdFromUriL( *resValReplaced8 ) ); + // ignore if error - resource id could not be fetched + if ( !err ) + { // OK + // delete resource + DeleteResourceByResIdL( UpnpCdUtils::ResIdFromUriL( *resValReplaced8 ) ); + } + } + + CleanupStack::PopAndDestroy( &objs ); + CleanupStack::PopAndDestroy( resValReplaced8 ); + CleanupStack::PopAndDestroy( resValReplaced16 ); + CleanupStack::PopAndDestroy( resVal ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjBeanLC +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CUpnpObjectBean* CUpnpContentDirectoryDb::GetObjBeanLC( TInt aObjId ) + { + CUpnpObjectBean* objBn = 0; + + RDbView view = iMetadataStorage->GetObjViewL( aObjId ); + CleanupClosePushL( view ); + + if ( view.FirstL( ) ) + { + // get values + view.GetL( ); + objBn = CUpnpObjectBean::NewL( view ); + } + + // clean up + CleanupStack::PopAndDestroy( &view ); + + CleanupStack::PushL( objBn ); + return objBn; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjectIdsL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::GetObjectsByResourceL( RArray& aIds, + const TDesC& aResVal ) + { + + RDbView view = iMetadataStorage->GetViewOfObjectListForResL( aResVal ); + CleanupClosePushL( view ); + + CDbColSet* colSet = view.ColSetL( ); + const TInt colNo = colSet->ColNo( KElmObjIdColName ); + delete colSet; + + // for each row + while ( view.NextL( ) ) + { + view.GetL( ); + TInt no = view.ColInt( colNo ); + aIds.AppendL( no ); + } + + // clean up + CleanupStack::PopAndDestroy( &view ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetProtocolInfoL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::GetProtocolInfoL( const TDesC8& aContentUri, + CUpnpDlnaProtocolInfo*& aProtocolInfo ) + { + HBufC* uri = HBufC::NewLC( aContentUri.Length( ) ); + TPtr uriPtr(uri->Des( )); + uriPtr.Copy( aContentUri ); + TInt ret = GetElmIdByNameAndValL( KRes16, uriPtr ); + if ( ret >= 0 ) + { + HBufC8* attrVal; + GetAttrValueByNameL( ret, KprotocolInfo, attrVal ); + CleanupStack::PushL( attrVal ); + aProtocolInfo = CUpnpDlnaProtocolInfo::NewL( *attrVal ); + CleanupStack::PopAndDestroy( attrVal ); + } + CleanupStack::PopAndDestroy( uri ); + + if ( ret >= 0 ) //item ID number is't meaningfull for function caller + { + ret = KErrNone; + } + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetElmIdByNameAndValL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::GetElmIdByNameAndValL( const TDesC& aElmName, + const TDesC& aElmValue ) + { + TInt ret = KErrNotFound; + + RDbView view = iMetadataStorage->GetViewOfElmIdByNameAndValL( aElmName, + aElmValue ); + CleanupClosePushL( view ); + + // col id + CDbColSet* colSet = view.ColSetL( ); + const TInt colNo = colSet->ColNo( KElmIdColName ); + delete colSet; + + while ( view.NextL( ) ) + { + view.GetL( ); + ret = view.ColInt( colNo ); + } + + // clean up + CleanupStack::PopAndDestroy( &view ); + + return ret; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetAttrValueByNameL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// + +HBufC8* CUpnpContentDirectoryDb::GetProtocolInfoByImportUriL( + const TDesC8& aImportUri ) + { + CUpnpAttributeBean* attBean = + GetAttrByValueL( KImportUri8( ), aImportUri ); + CleanupStack::PushL( attBean ); + + HBufC8* attValBuf = NULL; + if ( attBean ) + { + //KprotocolInfo + CUpnpAttributeBean* att = GetAttrByNameL( attBean->AtrElmId( ), + KprotocolInfo( ), attValBuf ); + delete att; + } + CleanupStack::PopAndDestroy( attBean ); + return attValBuf; + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetAttrValueByNameL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::GetAttrValueByNameL( TInt aElmId, + const TDesC8& aAttrName, HBufC8*& aAttrVal ) + { + CUpnpAttributeBean* atrBean = + GetAttrByNameL( aElmId, aAttrName, aAttrVal ); + delete atrBean; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetAttrByValueL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CUpnpAttributeBean* CUpnpContentDirectoryDb::GetAttrByValueL( + const TDesC8& aAttrName, const TDesC8& aAttrVal ) + { + RDbView view = iMetadataStorage->GetAttrViewL( aAttrName, aAttrVal ); + CleanupClosePushL( view ); + + TInt number = view.CountL( ); + + CDbColSet* colSet = view.ColSetL( ); + const TInt colNo = colSet->ColNo( KAtrValueColName ); + delete colSet; + + CUpnpAttributeBean* atrBean = NULL; + if ( view.FirstL( ) ) + { + view.GetL( ); + atrBean = CUpnpAttributeBean::NewLC( view ); + CleanupStack::Pop( atrBean ); + } + else + { + User::Leave( KErrNotFound ); + } + + // clean up + CleanupStack::PopAndDestroy( &view ); + return atrBean; + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetAttrByNameL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CUpnpAttributeBean* CUpnpContentDirectoryDb::GetAttrByNameL( TInt aElmId, + const TDesC8& aAttrName, HBufC8*& aAttrVal ) + { + RDbView view = iMetadataStorage->GetAttrViewL( aElmId, aAttrName ); + CleanupClosePushL( view ); + + CDbColSet* colSet = view.ColSetL( ); + const TInt colNo = colSet->ColNo( KAtrValueColName ); + delete colSet; + + CUpnpAttributeBean* atrBean = NULL; + if ( view.FirstL( ) ) + { + view.GetL( ); + atrBean = CUpnpAttributeBean::NewLC( view ); + aAttrVal = atrBean->AtrValue().AllocL( ); + CleanupStack::Pop( atrBean ); + } + else + { + User::Leave( KErrNotFound ); + } + + // clean up + CleanupStack::PopAndDestroy( &view ); + return atrBean; + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetObjectIdByElementValueLikeL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::GetObjectIdByElementValueLikeL( + const TDesC8& aElmName, const TDesC8& aElmValue ) + { + // convert to unicode + HBufC* elmName = UpnpCdUtils::Des8ToDesLC( aElmName ); + HBufC* elmValue = UpnpCdUtils::Des8ToDesLC( aElmValue ); + + // prepare query buf + HBufC* query = HBufC::NewLC( KSelectFromSqlCmd().Length( ) + KElmObjIdColName().Length( ) + KElementTableName().Length( ) + KElmNameColName().Length( ) + elmName->Length( ) + KAndLikeConditionSqlCmd().Length( ) + KElmValueColName().Length( ) + elmValue->Length( ) ); + + TPtr queryPtr(query->Des( )); + + // format query + queryPtr.Format( KSelectFromSqlCmd, &KElmObjIdColName, + &KElementTableName, &KElmNameColName, elmName ); + queryPtr.AppendFormat( KAndLikeConditionSqlCmd, &KElmValueColName, + elmValue ); + + // prepare + RDbView view = iMetadataStorage->GetEvaluatedViewL( queryPtr ); + CleanupClosePushL( view ); + + // col no + CDbColSet* colSet = view.ColSetL( ); + const TInt colNo = colSet->ColNo( KElmObjIdColName ); + delete colSet; + + TInt ret = KErrNotFound; + + // for one row + if ( view.NextL( ) ) + { + view.GetL( ); + if ( !view.IsColNull( colNo ) ) + { + ret = view.ColInt( colNo ); + } + } + + CleanupStack::PopAndDestroy( &view ); + CleanupStack::PopAndDestroy( query ); + + CleanupStack::PopAndDestroy( elmValue ); + CleanupStack::PopAndDestroy( elmName ); + + return ret; + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetParentIdL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::GetParentIdL( TInt aObjectId ) + { + return iMetadataStorage->GetParentIdL( aObjectId ); + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::AddAttributeL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// + +void CUpnpContentDirectoryDb::AddAttributeL( TXmlEngElement aElement, + const TDesC8& aAttrName, TInt aElementId, TInt aObjectId ) + { + RDbView view = iMetadataStorage->GetAttrViewByObjectIdL( aObjectId, + aAttrName ); + CleanupClosePushL( view ); + + CDbColSet* colSet = view.ColSetL( ); + const TInt elmIdColNo = colSet->ColNo( KAtrElmIdColName ); + delete colSet; + + // Iterate through attributes - usually there is only one + while ( view.NextL( ) ) + { + view.GetL( ); + + if ( view.ColInt( elmIdColNo ) == aElementId ) + { + CUpnpAttributeBean* atr = CUpnpAttributeBean::NewLC( view ); + atr->AttachAttrL( aElement ); + CleanupStack::PopAndDestroy( atr ); + } + } + + // clean up + CleanupStack::PopAndDestroy( &view ); + } +// ----------------------------------------------------------------------------- +// CContentDirectoryDb::CanBeNestedL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CUpnpContentDirectoryDb::CanBeNestedL( TInt aObjId ) + { + // get path + HBufC8* path = iMetadataStorage->GetObjectPathL( aObjId ); + CleanupStack::PushL( path ); + + // count levels + TPtrC8 rest(path->Des( )); + TInt levelNo(1); // root level + TInt pos( KErrNotFound ); + while ( (pos = rest.Find( KPathSeparator8 )) != KErrNotFound ) + { + rest.Set( rest.Mid( pos + KPathSeparator8().Length( ) ) ); + levelNo++; + } + // clean up + CleanupStack::PopAndDestroy( path ); + return (levelNo < KAvailableNestedLevels); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::AddResourceL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::AddResourceL( CUpnpResourcesBean* aResBean, + TInt aObjId ) + { + iMetadataStorage->AddResourceL( aResBean, aObjId ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::DeleteResourceL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::DeleteResourceByResIdL( TInt64 aResId, + TBool aDeleteFile ) + { + iMetadataStorage->DeleteResourceByResIdL( aResId, aDeleteFile ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::DeleteResourceL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::DeleteResourceByObjIdL( TInt aObjId, + TBool aDeleteFile ) + { + iMetadataStorage->DeleteResourceByObjIdL( aObjId, aDeleteFile ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetResourceL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CUpnpResourcesBean* CUpnpContentDirectoryDb::GetResourceL( TInt64 aResId ) + { + return iMetadataStorage->GetResourceL( aResId ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::ResNewDownloadDirectoryL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::NewMediaDirectoryL( const TDesC& aOldDir ) + { + //UPDATE resources SET rsc_readonly=1 WHERE KRscPathColName LIKE $aOldDir* AND KRscReadonlyColName=0 + // prepare command + HBufC* query = HBufC::NewLC( KNewMediaDirSqlCmd().Length( ) + aOldDir.Length( ) ); + TPtr SqlCmd(query->Des( )); + SqlCmd.Format( KNewMediaDirSqlCmd, &aOldDir ); + + // execute + iMetadataStorage->ExecuteL( SqlCmd ); + + CleanupStack::PopAndDestroy( query ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::GetKeyForUriL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::GetKeyForUriL() + { + return iMetadataStorage->GetNextKeyL( KImportUriId8 ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::CheckDatabaseL +// ----------------------------------------------------------------------------- +// +void CUpnpContentDirectoryDb::CheckDatabaseL() + { + iMetadataStorage->CheckDatabaseL( ); + } +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::RecreateDatabaseFile +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::RecreateDatabaseFile() + { + TRAPD( err, iMetadataStorage->RecreateDatabaseFileL( ) ); + return err; + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::HandleDbError +// ----------------------------------------------------------------------------- +// +TInt CUpnpContentDirectoryDb::HandleDbError( TInt aError ) + { + return iMetadataStorage->HandleDbError( aError ); + } + +// ----------------------------------------------------------------------------- +// CUpnpContentDirectoryDb::IsDbCreated +// ----------------------------------------------------------------------------- +// +TBool CUpnpContentDirectoryDb::IsDbCreated() + { + return iMetadataStorage->IsDbCreated( ); + } + +// End of File