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