phonebookengines/contactsmodel/cntplsql/src/cplcontactsfile.cpp
changeset 0 e686773b3f54
child 9 0d28c1c5b6dd
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19  @released
       
    20 */
       
    21 
       
    22 #include "persistencelayerimpl.h"
       
    23 #include "clplcontactproperties.h"
       
    24 #include "cntfilesearch.h"
       
    25 #include <bautils.h>
       
    26 #include "persistencelayer.h"
       
    27 
       
    28 const TInt KDriveNameWidth = 2; // e.g. "C:"
       
    29 
       
    30 _LIT(KSqLiteFilePrefix, "SQLite__");
       
    31 
       
    32 // Transaction constants (only used by CPplContactsFile)
       
    33 _LIT(KStartTransaction,"BEGIN TRANSACTION;");
       
    34 _LIT(KCommitTransaction,"COMMIT;");
       
    35 _LIT(KRollbackTransaction,"ROLLBACK;");
       
    36 
       
    37 /**
       
    38 @SYMPatchable
       
    39 @publishedPartner
       
    40 @released
       
    41 
       
    42 Patchable optional constant that overrides the cache size of the Contacts model databases set in the 
       
    43 SqlServer.cfg file in the SQL data cage.
       
    44 If this value is left at 0, the cache size from the SqlServer.cfg file is used.
       
    45 The cache size affects the size of the cache in Kb that opens and creates Contacts model files.
       
    46 See SQLite documentation for more details.
       
    47 
       
    48 The constant can be changed at ROM build time using patchdata OBY keyword.
       
    49 */
       
    50 IMPORT_C extern const TInt KContactsModelSqliteDbCacheSize;
       
    51 
       
    52 const TInt KCacheDataSize = 8; // The size in chars of patchable constant 'KContactsModelSqliteDbCacheSize' passed in 
       
    53 
       
    54 //configure string used to create and open sqlite database
       
    55 _LIT8(KSqliteCacheSize, "cache_size=%d");
       
    56 
       
    57 /**
       
    58 CPplContactsFile NewL.
       
    59 */
       
    60 CPplContactsFile* CPplContactsFile::NewL(CLplContactProperties& aProps, MContactDbObserver* aObserver)
       
    61 	{
       
    62 	CPplContactsFile* self = new (ELeave) CPplContactsFile(aProps, aObserver);
       
    63 	CleanupStack::PushL(self);
       
    64 	self->ConstructL();
       
    65 	CleanupStack::Pop(self);
       
    66 	return self;
       
    67 	}
       
    68 
       
    69 /**
       
    70 CPplContactsFile ConstructL.
       
    71 */	
       
    72 void CPplContactsFile::ConstructL()
       
    73 	{
       
    74 	iItemManager = CPplContactItemManager::NewL(iDatabase, *this, iContactProperties, iIccContactStore);
       
    75 	iContactProperties.SetContactItemManagerL(*iItemManager);
       
    76 	
       
    77 	iConfigureStr = NULL;
       
    78 	if(KContactsModelSqliteDbCacheSize > 0)
       
    79 		{
       
    80 		//Create configure string to be used when creating/opening database
       
    81 		iConfigureStr = HBufC8::NewL(KSqliteCacheSize().Length() + KCacheDataSize);
       
    82 		TPtr8 ptrConfigureStr = iConfigureStr->Des();
       
    83 		ptrConfigureStr.Format(KSqliteCacheSize(), KContactsModelSqliteDbCacheSize);
       
    84 		}
       
    85 	}
       
    86 	
       
    87 	
       
    88 /**
       
    89 CPplContactsFile constructor.
       
    90 */
       
    91 CPplContactsFile::CPplContactsFile(CLplContactProperties& aProps, MContactDbObserver* aObserver)
       
    92 	:
       
    93 	iActive(EFalse),
       
    94  	iDbObserver(aObserver),
       
    95  	iContactProperties(aProps),
       
    96  	iIccContactStore(aProps)
       
    97 	{
       
    98 	}
       
    99 
       
   100 /**
       
   101 CPplContactsFile destructor.
       
   102 */
       
   103 CPplContactsFile::~CPplContactsFile()
       
   104 	{
       
   105   	Close();
       
   106 	delete iItemManager;
       
   107 	delete iConfigureStr;
       
   108 	}
       
   109 
       
   110 
       
   111 /**
       
   112 Set the database observer for event propagation.
       
   113 */
       
   114 void CPplContactsFile::RegisterDbObserver(MContactDbObserver& aDbObserver)
       
   115 	{
       
   116 	iDbObserver = &aDbObserver;	  
       
   117 	}
       
   118 
       
   119 /**
       
   120 Utility method used to construct physical path for a given file name
       
   121 
       
   122 @param aPhysicalFileName in/out paramter; file name to which physical path will be append
       
   123 @param aSecuredFileName secured file name
       
   124 */
       
   125 void CPplContactsFile::GetPhysicalFileNameL(TDes& aPhysicalFileName, const TDesC& aSecuredFileName)
       
   126 	{
       
   127 	GetPhysicalPathL(aPhysicalFileName, aSecuredFileName);
       
   128 	aPhysicalFileName.Append(KSqLiteFilePrefix);
       
   129 	aPhysicalFileName.Append(aSecuredFileName.Right(aSecuredFileName.Length() - KDriveNameWidth));
       
   130 	}
       
   131 
       
   132 /**
       
   133 Utility method used to construct physical path for a given file name
       
   134 
       
   135 @param aPhysicalFileName in/out paramter; file name to which physical path will be append
       
   136 @param aSecuredFileName secured file name
       
   137 */
       
   138 void CPplContactsFile::GetPhysicalPathL(TDes& aPhysicalFileName, const TDesC& aSecuredFileName)
       
   139 	{
       
   140 	const TUint16 KDriveDelimiter = ':';
       
   141 
       
   142 	// Check for the drive delimiter.
       
   143 	__ASSERT_ALWAYS(aSecuredFileName.Length() > 2 &&
       
   144 		aSecuredFileName[1] == KDriveDelimiter, User::Leave(KErrBadName)); 
       
   145 
       
   146 	// Check for malformed file name (path included explicitly).
       
   147 	__ASSERT_ALWAYS(aSecuredFileName.Locate('\\') == KErrNotFound, User::Leave(KErrBadName)); 
       
   148 
       
   149 	// Get the private path from the file session.
       
   150 	const TInt KMaxPrivatePathLength = 32;
       
   151 	TBuf<KMaxPrivatePathLength> privatePath;
       
   152 	
       
   153   	LocalFsL();
       
   154   	iLocalFs.PrivatePath(privatePath);
       
   155 	
       
   156 	aPhysicalFileName = aSecuredFileName.Left(KDriveNameWidth);
       
   157 		
       
   158 	// Set current drive.
       
   159 	iDatabaseDrive = aPhysicalFileName;
       
   160 
       
   161 	aPhysicalFileName.Append(privatePath);
       
   162 
       
   163   	// Make sure private path exists.
       
   164   	TInt err = iLocalFs.MkDirAll(aPhysicalFileName);
       
   165 	if (err != KErrNone && err != KErrAlreadyExists)
       
   166 		{
       
   167 		User::Leave(err);
       
   168 		}
       
   169 	}
       
   170 
       
   171 /**
       
   172 Open the given database file.
       
   173 */
       
   174 void CPplContactsFile::OpenL(const TDesC& aFileName, TBool aNotify)
       
   175 	{
       
   176 	// Contact databases are in the Contact model private directory.  
       
   177 	TFileName fileName;
       
   178 	GetPhysicalFileNameL(fileName, aFileName);
       
   179 	
       
   180 	iDatabase.Close();
       
   181 	iDatabase.OpenL(fileName, iConfigureStr);
       
   182 	
       
   183 	iFileIsOpen = ETrue;
       
   184 	GenerateNotificationEventL(aNotify);	
       
   185 	}
       
   186 
       
   187 /**
       
   188 Utility method used to generate EContactDbObserverEventTablesOpened event
       
   189 */
       
   190 void CPplContactsFile::GenerateNotificationEventL(TBool aNotify)
       
   191 	{
       
   192 	#if defined(__PROFILE_DEBUG__)
       
   193 		RDebug::Print(_L("[CNTMODEL] MTD: CPplContactsFile::GenerateNotificationEventL"));
       
   194 	#endif 
       
   195 	
       
   196 	// Generate an event - this event is generated if this was an explicit call from the
       
   197  	// server to opentables or recover database - ie A call on the contactsDatabase API
       
   198  	if (iDbObserver && aNotify)
       
   199  		{
       
   200  		TContactDbObserverEvent event;
       
   201 		event.iType = EContactDbObserverEventTablesOpened;
       
   202 		event.iContactId = 0;
       
   203  		event.iConnectionId = 0;
       
   204  		TRAP_IGNORE(iDbObserver->HandleDatabaseEventL(event));
       
   205  		}
       
   206 	}
       
   207 
       
   208 
       
   209 /**
       
   210   Open the database tables (a state change, no action on file necessary).
       
   211 */
       
   212 void CPplContactsFile::OpenTablesL(TBool aNotify)
       
   213   	{
       
   214   	// Do nothing but notify
       
   215   	
       
   216   	#if defined(__PROFILE_DEBUG__)
       
   217   	    _LIT(KMessage, "[CNTMODEL] MTD: CPplContactsFile::OpenTablesL");
       
   218   		RDebug::Print(KMessage);
       
   219   	#endif 
       
   220   		
       
   221 	iFileIsOpen = ETrue;
       
   222  	GenerateNotificationEventL(aNotify);		  
       
   223    	}
       
   224 
       
   225 	
       
   226 /**	
       
   227   Close the database tables leaving the iDatabase itself open.
       
   228   Despite the trailing 'L', this method cannot leave.
       
   229 */
       
   230 void CPplContactsFile::CloseTablesL(TBool aNotify)
       
   231 	{
       
   232 	// Do nothing but notify
       
   233   
       
   234  	if (iDbObserver && aNotify) // Observer is optional.
       
   235   		{
       
   236   		// Notify observers that table is closed.
       
   237   		TContactDbObserverEvent event;
       
   238   		event.iType = EContactDbObserverEventTablesClosed;
       
   239   		event.iContactId = 0;
       
   240   		event.iConnectionId = 0;
       
   241   		TRAP_IGNORE(iDbObserver->HandleDatabaseEventL(event));	
       
   242   		}
       
   243   	}
       
   244 	
       
   245 
       
   246 /**
       
   247 File cleanup class used if creating database and its tables leaves.
       
   248 */
       
   249 class TFileCleanup
       
   250 	{
       
   251 public:
       
   252 	TFileCleanup(RSqlDatabase& aDb, RFs& aFs, const TDesC& aFileName) : iDb(aDb),iFs(aFs),iFileName(aFileName) {}
       
   253 	static void Cleanup(TAny* aSelf) { STATIC_CAST(TFileCleanup*,aSelf)->DoCleanup(); }
       
   254 
       
   255 private:
       
   256 	void DoCleanup()
       
   257 		{
       
   258 		iDb.Close();
       
   259 		(void)iFs.Delete(iFileName);
       
   260 		}
       
   261 
       
   262 public:
       
   263 	RSqlDatabase& iDb;
       
   264 	RFs& iFs;
       
   265 	const TDesC& iFileName;
       
   266 	};
       
   267 
       
   268 
       
   269 /**
       
   270 Create a new database.
       
   271 */
       
   272 EXPORT_C void CPplContactsFile::CreateL(const TDesC& aFileName, TPlCreateMode aMode)
       
   273 	{
       
   274 	TFileName fileName;
       
   275 	GetPhysicalFileNameL(fileName, aFileName); 
       
   276 
       
   277 	TUint attVal;
       
   278 	LocalFsL();
       
   279 	TInt err = iLocalFs.Att(fileName, attVal);
       
   280 	TBool fileExists = (err == KErrNone);
       
   281 	
       
   282 	if (fileExists)
       
   283 		{
       
   284 		switch (aMode)
       
   285 			{
       
   286 			case EPlLeaveIfExist:
       
   287 				User::Leave(KErrAlreadyExists);
       
   288 				break;
       
   289 				
       
   290 			case EPlOverwrite:
       
   291 				err = iLocalFs.Delete(fileName);
       
   292 				break;
       
   293 			}
       
   294 		}
       
   295 	
       
   296 	// If the database is not created propertly delete the database file using
       
   297 	// the cleanup item.
       
   298 	TFileCleanup cleanupData(iDatabase, iLocalFs, fileName);
       
   299 	CleanupStack::PushL(TCleanupItem(TFileCleanup::Cleanup,&cleanupData)); 
       
   300 
       
   301 	if ((err != KErrNone) && (err != KErrNotFound)) 
       
   302 		{
       
   303 		User::LeaveIfError(err);
       
   304 		}
       
   305 	
       
   306 	User::LeaveIfError(iDatabase.Create(fileName, iConfigureStr));
       
   307   	iItemManager->CreateTablesL();
       
   308   	iContactProperties.SystemTemplateManager().RecreateSystemTemplateL();
       
   309 
       
   310 	CleanupStack::Pop(); // The TCleanupItem.
       
   311 	
       
   312 	iDatabase.Close();  
       
   313 	}
       
   314 
       
   315 
       
   316 /**
       
   317 Delete the given database.
       
   318 */
       
   319 void CPplContactsFile::DeleteL(const TDesC& aFileName)
       
   320 	{
       
   321 	TFileName fileName;
       
   322 	GetPhysicalFileNameL(fileName, aFileName);	
       
   323 	
       
   324 	User::LeaveIfError(iLocalFs.Delete(fileName));  
       
   325 	iFileIsOpen = EFalse;
       
   326 	}
       
   327 
       
   328 
       
   329 /**
       
   330 Get a list of the contacts database on the given drive.
       
   331 */
       
   332 CDesCArray* CPplContactsFile::ListL(TDriveUnit* aDriveUnit)  
       
   333 	{
       
   334  	LocalFsL();
       
   335   	return CCntFileScanner::ListFilesL(iLocalFs, aDriveUnit);
       
   336 	}
       
   337 
       
   338 
       
   339 /**
       
   340 Close the database.
       
   341 */
       
   342 void CPplContactsFile::Close(TBool aNotify)
       
   343 	{	 		
       
   344   	iDatabase.Close(); 
       
   345   	iFileIsOpen = EFalse;
       
   346   
       
   347   	REComSession::FinalClose(); // This line is necessary to make sure the plug-in is unloaded properly
       
   348   	iLocalFs.Close(); //we now use a local File Session	
       
   349 	
       
   350 	iIccContactStore.Close();
       
   351 	
       
   352 	TRAP_IGNORE(CloseTablesL(aNotify) ); // CloseTablesL() cannot leave anyway but still 
       
   353 										 // trap in case implementation changes later
       
   354 	}
       
   355 
       
   356 
       
   357 /**
       
   358 Starts a new transaction if one is not currently active otherwise leave.
       
   359 */
       
   360 void CPplContactsFile::StartTransactionL()
       
   361 	{
       
   362 	if (iActive)  
       
   363 		{
       
   364 		User::Leave(KErrInUse);
       
   365 		}
       
   366 	User::LeaveIfError(iDatabase.Exec(KStartTransaction));
       
   367 	iIccContactStore.StartTransactionL();   
       
   368 	iActive = ETrue;
       
   369 	}
       
   370 
       
   371 
       
   372 /**
       
   373 Commit all changes made since the transaction was started.
       
   374 */
       
   375 void CPplContactsFile::CommitCurrentTransactionL(TUint aSessionId)
       
   376 	{
       
   377 
       
   378 	if (!iActive)  
       
   379 		{
       
   380 		User::Leave(KErrNotReady);
       
   381 		}
       
   382 	iIccContactStore.CommitCurrentTransactionL(aSessionId);  
       
   383 	User::LeaveIfError(iDatabase.Exec(KCommitTransaction));
       
   384 	iActive = EFalse;	
       
   385 	}
       
   386 
       
   387 
       
   388 /**
       
   389 Rollback all changes made since the active the transaction was started.
       
   390 */
       
   391 void CPplContactsFile::RollbackCurrentTransactionL(TUint aSessionId)
       
   392 	{
       
   393 	// Check that the database is open before rolling back.
       
   394 	if (iFileIsOpen && iActive)
       
   395 		{
       
   396 		iActive = EFalse;
       
   397 		iIccContactStore.RollbackCurrentTransaction(aSessionId); 
       
   398 		User::LeaveIfError(iDatabase.Exec(KRollbackTransaction)); 
       
   399 		}
       
   400 	}
       
   401 	
       
   402 /**
       
   403 Gets the size of the database file in bytes.
       
   404 
       
   405 @return The size of the contact database.
       
   406 */
       
   407 TInt CPplContactsFile::FileSize() const
       
   408  	{
       
   409   	return iDatabase.Size();
       
   410   	}	
       
   411 	
       
   412 
       
   413 /**
       
   414 Gets the current database drive.  The database drive is the drive on which 
       
   415 the default contact database is located.
       
   416 
       
   417 @param aDriveUnit On return, contains the database drive.
       
   418 */
       
   419 void CPplContactsFile::DatabaseDrive(TDriveUnit& aDriveUnit)
       
   420 	{
       
   421 	aDriveUnit = iDatabaseDrive;
       
   422 	}
       
   423 
       
   424 
       
   425 /**
       
   426 A static method to determine if a given Contacts database exists.
       
   427 
       
   428 @param	aFileName The Contacts database to search for.
       
   429 
       
   430 @return ETrue if the Contacts database is found, EFalse otherwise.
       
   431 */
       
   432 TBool CPplContactsFile::DatabaseExistsL(const TDesC& aFileName)
       
   433 	{
       
   434 	TFileName fileName;
       
   435 	GetPhysicalFileNameL(fileName, aFileName);
       
   436 	LocalFsL();
       
   437 	return BaflUtils::FileExists(iLocalFs, fileName);
       
   438 	}
       
   439