--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntplsql/src/cplcontactsfile.cpp Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,479 @@
+// Copyright (c) 2004-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:
+//
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+#include "persistencelayerimpl.h"
+#include "clplcontactproperties.h"
+#include "cntfilesearch.h"
+#include <bautils.h>
+#include "persistencelayer.h"
+
+const TInt KDriveNameWidth = 2; // e.g. "C:"
+
+_LIT(KSqLiteFilePrefix, "SQLite__");
+
+// Transaction constants (only used by CPplContactsFile)
+_LIT(KStartTransaction,"BEGIN TRANSACTION;");
+_LIT(KCommitTransaction,"COMMIT;");
+_LIT(KRollbackTransaction,"ROLLBACK;");
+
+/**
+@SYMPatchable
+@publishedPartner
+@released
+
+Patchable optional constant that overrides the cache size of the Contacts model databases set in the
+SqlServer.cfg file in the SQL data cage.
+If this value is left at 0, the cache size from the SqlServer.cfg file is used.
+The cache size affects the size of the cache in Kb that opens and creates Contacts model files.
+See SQLite documentation for more details.
+
+The constant can be changed at ROM build time using patchdata OBY keyword.
+*/
+IMPORT_C extern const TInt KContactsModelSqliteDbCacheSize;
+
+const TInt KCacheDataSize = 8; // The size in chars of patchable constant 'KContactsModelSqliteDbCacheSize' passed in
+
+//configure string used to create and open sqlite database
+_LIT8(KSqliteCacheSize, "cache_size=%d");
+
+/**
+CPplContactsFile NewL.
+*/
+CPplContactsFile* CPplContactsFile::NewL(CLplContactProperties& aProps, MContactDbObserver* aObserver)
+ {
+ CPplContactsFile* self = new (ELeave) CPplContactsFile(aProps, aObserver);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+CPplContactsFile ConstructL.
+*/
+void CPplContactsFile::ConstructL()
+ {
+ iItemManager = CPplContactItemManager::NewL(iDatabase, *this, iContactProperties, iIccContactStore);
+ iContactProperties.SetContactItemManagerL(*iItemManager);
+
+ iConfigureStr = NULL;
+ if(KContactsModelSqliteDbCacheSize > 0)
+ {
+ //Create configure string to be used when creating/opening database
+ iConfigureStr = HBufC8::NewL(KSqliteCacheSize().Length() + KCacheDataSize);
+ TPtr8 ptrConfigureStr = iConfigureStr->Des();
+ ptrConfigureStr.Format(KSqliteCacheSize(), KContactsModelSqliteDbCacheSize);
+ }
+ }
+
+
+/**
+CPplContactsFile constructor.
+*/
+CPplContactsFile::CPplContactsFile(CLplContactProperties& aProps, MContactDbObserver* aObserver)
+ :
+ iActive(EFalse),
+ iDbObserver(aObserver),
+ iContactProperties(aProps),
+ iIccContactStore(aProps)
+ {
+ }
+
+/**
+CPplContactsFile destructor.
+*/
+CPplContactsFile::~CPplContactsFile()
+ {
+ Close();
+ delete iItemManager;
+ delete iConfigureStr;
+ iSqlDatabaseObservers.Reset();
+ }
+
+
+/**
+Set the database observer for event propagation.
+*/
+void CPplContactsFile::RegisterDbObserver(MContactDbObserver& aDbObserver)
+ {
+ iDbObserver = &aDbObserver;
+ }
+
+/**
+Utility method used to construct physical path for a given file name
+
+@param aPhysicalFileName in/out paramter; file name to which physical path will be append
+@param aSecuredFileName secured file name
+*/
+void CPplContactsFile::GetPhysicalFileNameL(TDes& aPhysicalFileName, const TDesC& aSecuredFileName)
+ {
+ GetPhysicalPathL(aPhysicalFileName, aSecuredFileName);
+ aPhysicalFileName.Append(KSqLiteFilePrefix);
+ aPhysicalFileName.Append(aSecuredFileName.Right(aSecuredFileName.Length() - KDriveNameWidth));
+ }
+
+/**
+Utility method used to construct physical path for a given file name
+
+@param aPhysicalFileName in/out paramter; file name to which physical path will be append
+@param aSecuredFileName secured file name
+*/
+void CPplContactsFile::GetPhysicalPathL(TDes& aPhysicalFileName, const TDesC& aSecuredFileName)
+ {
+ const TUint16 KDriveDelimiter = ':';
+
+ // Check for the drive delimiter.
+ __ASSERT_ALWAYS(aSecuredFileName.Length() > 2 &&
+ aSecuredFileName[1] == KDriveDelimiter, User::Leave(KErrBadName));
+
+ // Check for malformed file name (path included explicitly).
+ __ASSERT_ALWAYS(aSecuredFileName.Locate('\\') == KErrNotFound, User::Leave(KErrBadName));
+
+ // Get the private path from the file session.
+ const TInt KMaxPrivatePathLength = 32;
+ TBuf<KMaxPrivatePathLength> privatePath;
+
+ LocalFsL();
+ iLocalFs.PrivatePath(privatePath);
+
+ aPhysicalFileName = aSecuredFileName.Left(KDriveNameWidth);
+
+ // Set current drive.
+ iDatabaseDrive = aPhysicalFileName;
+
+ aPhysicalFileName.Append(privatePath);
+
+ // Make sure private path exists.
+ TInt err = iLocalFs.MkDirAll(aPhysicalFileName);
+ if (err != KErrNone && err != KErrAlreadyExists)
+ {
+ User::Leave(err);
+ }
+ }
+
+/**
+Open the given database file.
+*/
+void CPplContactsFile::OpenL(const TDesC& aFileName, TBool aNotify)
+ {
+ // Contact databases are in the Contact model private directory.
+ TFileName fileName;
+ GetPhysicalFileNameL(fileName, aFileName);
+
+ iDatabase.Close();
+ iDatabase.OpenL(fileName, iConfigureStr);
+
+ iFileIsOpen = ETrue;
+ GenerateNotificationEventL(aNotify);
+ }
+
+/**
+Utility method used to generate EContactDbObserverEventTablesOpened event
+*/
+void CPplContactsFile::GenerateNotificationEventL(TBool aNotify)
+ {
+ #if defined(__PROFILE_DEBUG__)
+ RDebug::Print(_L("[CNTMODEL] MTD: CPplContactsFile::GenerateNotificationEventL"));
+ #endif
+
+ // Generate an event - this event is generated if this was an explicit call from the
+ // server to opentables or recover database - ie A call on the contactsDatabase API
+ if (iDbObserver && aNotify)
+ {
+ TContactDbObserverEvent event;
+ event.iType = EContactDbObserverEventTablesOpened;
+ event.iContactId = 0;
+ event.iConnectionId = 0;
+ TRAP_IGNORE(iDbObserver->HandleDatabaseEventL(event));
+ }
+ }
+
+
+/**
+ Open the database tables (a state change, no action on file necessary).
+*/
+void CPplContactsFile::OpenTablesL(TBool aNotify)
+ {
+ // Do nothing but notify
+
+ #if defined(__PROFILE_DEBUG__)
+ _LIT(KMessage, "[CNTMODEL] MTD: CPplContactsFile::OpenTablesL");
+ RDebug::Print(KMessage);
+ #endif
+
+ iFileIsOpen = ETrue;
+ GenerateNotificationEventL(aNotify);
+ }
+
+
+/**
+ Close the database tables leaving the iDatabase itself open.
+ Despite the trailing 'L', this method cannot leave.
+*/
+void CPplContactsFile::CloseTablesL(TBool aNotify)
+ {
+ // Do nothing but notify
+
+ if (iDbObserver && aNotify) // Observer is optional.
+ {
+ // Notify observers that table is closed.
+ TContactDbObserverEvent event;
+ event.iType = EContactDbObserverEventTablesClosed;
+ event.iContactId = 0;
+ event.iConnectionId = 0;
+ TRAP_IGNORE(iDbObserver->HandleDatabaseEventL(event));
+ }
+ }
+
+
+/**
+File cleanup class used if creating database and its tables leaves.
+*/
+class TFileCleanup
+ {
+public:
+ TFileCleanup(RSqlDatabase& aDb, RFs& aFs, const TDesC& aFileName) : iDb(aDb),iFs(aFs),iFileName(aFileName) {}
+ static void Cleanup(TAny* aSelf) { STATIC_CAST(TFileCleanup*,aSelf)->DoCleanup(); }
+
+private:
+ void DoCleanup()
+ {
+ iDb.Close();
+ (void)iFs.Delete(iFileName);
+ }
+
+public:
+ RSqlDatabase& iDb;
+ RFs& iFs;
+ const TDesC& iFileName;
+ };
+
+
+/**
+Create a new database.
+*/
+EXPORT_C void CPplContactsFile::CreateL(const TDesC& aFileName, TPlCreateMode aMode)
+ {
+ TFileName fileName;
+ GetPhysicalFileNameL(fileName, aFileName);
+
+ TUint attVal;
+ LocalFsL();
+ TInt err = iLocalFs.Att(fileName, attVal);
+ TBool fileExists = (err == KErrNone);
+
+ if (fileExists)
+ {
+ switch (aMode)
+ {
+ case EPlLeaveIfExist:
+ User::Leave(KErrAlreadyExists);
+ break;
+
+ case EPlOverwrite:
+ err = iLocalFs.Delete(fileName);
+ break;
+ }
+ }
+
+ // If the database is not created propertly delete the database file using
+ // the cleanup item.
+ TFileCleanup cleanupData(iDatabase, iLocalFs, fileName);
+ CleanupStack::PushL(TCleanupItem(TFileCleanup::Cleanup,&cleanupData));
+
+ if ((err != KErrNone) && (err != KErrNotFound))
+ {
+ User::LeaveIfError(err);
+ }
+
+ User::LeaveIfError(iDatabase.Create(fileName, iConfigureStr));
+ iItemManager->CreateTablesL();
+ iContactProperties.SystemTemplateManager().RecreateSystemTemplateL();
+
+ CleanupStack::Pop(); // The TCleanupItem.
+
+ iDatabase.Close();
+ }
+
+
+/**
+Delete the given database.
+*/
+void CPplContactsFile::DeleteL(const TDesC& aFileName)
+ {
+ TFileName fileName;
+ GetPhysicalFileNameL(fileName, aFileName);
+
+ User::LeaveIfError(iLocalFs.Delete(fileName));
+ iFileIsOpen = EFalse;
+ }
+
+
+/**
+Get a list of the contacts database on the given drive.
+*/
+CDesCArray* CPplContactsFile::ListL(TDriveUnit* aDriveUnit)
+ {
+ LocalFsL();
+ return CCntFileScanner::ListFilesL(iLocalFs, aDriveUnit);
+ }
+
+
+/**
+Close the database.
+*/
+void CPplContactsFile::Close(TBool aNotify)
+ {
+ // Close the resource which depends on iDatabase before it will be closed.
+ for (TInt i = 0; i < iSqlDatabaseObservers.Count(); i++ )
+ {
+ iSqlDatabaseObservers[i]->OnCloseL();
+ }
+
+ iDatabase.Close();
+ iFileIsOpen = EFalse;
+
+ REComSession::FinalClose(); // This line is necessary to make sure the plug-in is unloaded properly
+ iLocalFs.Close(); //we now use a local File Session
+
+ iIccContactStore.Close();
+
+ TRAP_IGNORE(CloseTablesL(aNotify) ); // CloseTablesL() cannot leave anyway but still
+ // trap in case implementation changes later
+ }
+
+
+/**
+Starts a new transaction if one is not currently active otherwise leave.
+*/
+void CPplContactsFile::StartTransactionL()
+ {
+ if (iActive)
+ {
+ User::Leave(KErrInUse);
+ }
+ User::LeaveIfError(iDatabase.Exec(KStartTransaction));
+ iIccContactStore.StartTransactionL();
+ iActive = ETrue;
+ }
+
+
+/**
+Commit all changes made since the transaction was started.
+*/
+void CPplContactsFile::CommitCurrentTransactionL(TUint aSessionId)
+ {
+
+ if (!iActive)
+ {
+ User::Leave(KErrNotReady);
+ }
+ iIccContactStore.CommitCurrentTransactionL(aSessionId);
+ User::LeaveIfError(iDatabase.Exec(KCommitTransaction));
+ iActive = EFalse;
+ }
+
+
+/**
+Rollback all changes made since the active the transaction was started.
+*/
+void CPplContactsFile::RollbackCurrentTransactionL(TUint aSessionId)
+ {
+ // Check that the database is open before rolling back.
+ if (iFileIsOpen && iActive)
+ {
+ iActive = EFalse;
+ iIccContactStore.RollbackCurrentTransaction(aSessionId);
+ User::LeaveIfError(iDatabase.Exec(KRollbackTransaction));
+ }
+ }
+
+/**
+Gets the size of the database file in bytes.
+
+@return The size of the contact database.
+*/
+TInt CPplContactsFile::FileSize() const
+ {
+ return iDatabase.Size();
+ }
+
+
+/**
+Gets the current database drive. The database drive is the drive on which
+the default contact database is located.
+
+@param aDriveUnit On return, contains the database drive.
+*/
+void CPplContactsFile::DatabaseDrive(TDriveUnit& aDriveUnit)
+ {
+ aDriveUnit = iDatabaseDrive;
+ }
+
+
+/**
+A static method to determine if a given Contacts database exists.
+
+@param aFileName The Contacts database to search for.
+
+@return ETrue if the Contacts database is found, EFalse otherwise.
+*/
+TBool CPplContactsFile::DatabaseExistsL(const TDesC& aFileName)
+ {
+ TFileName fileName;
+ GetPhysicalFileNameL(fileName, aFileName);
+ LocalFsL();
+ return BaflUtils::FileExists(iLocalFs, fileName);
+ }
+
+
+/**
+ * Add an observer for monitoring RSqlDatabase.
+ *
+ * @param aSqlDatabaseObserver The observer for monitoring RSqlDatabase.
+ *
+ * @return None
+ */
+void CPplContactsFile::AddSqlDBObserverL(
+ MLplSqlDatabaseObserver& aSqlDatabaseObserver )
+ {
+ iSqlDatabaseObservers.AppendL( &aSqlDatabaseObserver );
+ }
+
+
+/**
+ * Remove an RSqlDatabase observer.
+ *
+ * @param aSqlDatabaseObserver The observer is to be removed.
+ *
+ * @return None
+ */
+void CPplContactsFile::RemoveSqlDBObserverL(
+ MLplSqlDatabaseObserver& aSqlDatabaseObserver )
+ {
+ TInt id = iSqlDatabaseObservers.Find( &aSqlDatabaseObserver );
+ if ( id != KErrNotFound )
+ {
+ iSqlDatabaseObservers.Remove( id );
+ }
+ }
+
+