phonebookengines/contactsmodel/cntsrv/src/CCntBackupRestoreAgent.cpp
changeset 0 e686773b3f54
child 24 0ba2181d7c28
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 // Copyright (c) 2005-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 #include "connect/sbdefs.h" // For conn::EBURNormal etc.
       
    17 #include <utf.h> // For CnvUtfConverter::ConvertFromUnicodeToUtf8().
       
    18 
       
    19 #include "CCntBackupRestoreAgent.h"
       
    20 #include "CIniFileManager.h"
       
    21 #include "CCntDbManagerController.h"
       
    22 #include "CCntServer.h" // For KCntNullConnectionId.
       
    23 #include "CCntLogger.h"
       
    24 
       
    25 
       
    26 const TInt CCntBackupRestoreAgent::KMaxFileNameLength = 256;
       
    27 
       
    28 _LIT(KSqLiteFilePrefix, "SQLite__");
       
    29 
       
    30 /** Object factory method for CCntBackupRestoreAgent.
       
    31 */
       
    32 CCntBackupRestoreAgent* CCntBackupRestoreAgent::NewL(RFs& aFs, CCntDbManagerController& aDbMgrCtrlr)
       
    33 	{
       
    34 	CCntBackupRestoreAgent* self = new(ELeave) CCntBackupRestoreAgent(aFs, aDbMgrCtrlr);
       
    35 	return self;
       
    36 	}
       
    37 
       
    38 
       
    39 /** Destructor. 
       
    40 */
       
    41 CCntBackupRestoreAgent::~CCntBackupRestoreAgent()
       
    42 	{
       
    43 	Cancel();
       
    44 	iBackupRestoreNotification.Close();
       
    45 	}
       
    46 
       
    47 
       
    48 /** Process any initial notification and start monitoring for changes in the
       
    49 	Backup/Restore property used by the SBEngine component.
       
    50 */
       
    51 void CCntBackupRestoreAgent::StartL()
       
    52 	{
       
    53 	TInt newState = 0;
       
    54 	
       
    55 	// Check to see if a Backup/Restore is currently in progress.
       
    56 	if (iBackupRestoreNotification.Get(newState) != KErrNotFound)
       
    57 		{
       
    58 		ProcessInitialStateL(newState);
       
    59 		}
       
    60 
       
    61 	SetActive();
       
    62 	}
       
    63 
       
    64 
       
    65 /** First phase default constructor.
       
    66 */
       
    67 CCntBackupRestoreAgent::CCntBackupRestoreAgent(RFs& aFs, CCntDbManagerController& aDbMgrCtrlr)
       
    68 	: CActive(CActive::EPriorityStandard), iFs(aFs), iDbMgrCtrlr(aDbMgrCtrlr)
       
    69 	{
       
    70 	CActiveScheduler::Add(this);
       
    71 
       
    72 	iEvent.iType = EContactDbObserverEventNull;		// Changed as required.
       
    73 	iEvent.iContactId =	KNullContactId;				// Always this value.
       
    74 	iEvent.iConnectionId = KCntNullConnectionId;	// Always this value.
       
    75 
       
    76 	// Attach and subscribe to the Backup/Restore property used by the SBEngine
       
    77 	// component.
       
    78 	iBackupRestoreNotification.Attach(KUidSystemCategory, conn::KUidBackupRestoreKey);
       
    79 	iBackupRestoreNotification.Subscribe(iStatus);
       
    80 	}
       
    81 
       
    82 
       
    83 /** Indicates if a Backup operation is currently in progress.
       
    84 	@return ETrue if operation in progress else EFalse.
       
    85 */
       
    86 TBool CCntBackupRestoreAgent::BackupInProgress() const
       
    87 	{
       
    88 	return (iCurrentState & (conn::EBURBackupPartial | conn::EBURBackupFull));
       
    89 	}
       
    90 
       
    91 
       
    92 /** Indicates if a Restore operation is currently in progress.
       
    93 	@return	ETrue if operation in progress else EFalse.
       
    94 */
       
    95 TBool CCntBackupRestoreAgent::RestoreInProgress() const
       
    96 	{
       
    97 	return (iCurrentState & (conn::EBURRestorePartial | conn::EBURRestoreFull));
       
    98 	}
       
    99 
       
   100 
       
   101 /** Create a new XML backup registration file for the file aFileName.  The file
       
   102 	will be created on the same drive as aFileName in the Contacts Model private
       
   103 	data directory.
       
   104 
       
   105 	@param aFileName File name including drive letter i.e. <drive>:<file>.
       
   106 */
       
   107 void CCntBackupRestoreAgent::CreateBackupRegistrationFileL(const TDesC& aFileName)
       
   108 	{
       
   109 	_LIT8(KXmlFilePart1, "<?xml version=\"1.0\" standalone=\"yes\"?>\r\n"
       
   110 		"<backup_registration>\r\n"
       
   111 		"    <passive_backup base_backup_only=\"yes\">\r\n"
       
   112 		"        <include_file name=\"");
       
   113 	_LIT8(KXmlFilePart2, "\"/>\r\n"
       
   114 		"    </passive_backup>\r\n"
       
   115 		"</backup_registration>\r\n");
       
   116 		
       
   117 	// Find out the drive held in aFileName.  If a drive letter is not present
       
   118 	// then the method leaves.
       
   119 	TParsePtrC parseFileName(aFileName);
       
   120 	User::LeaveIfError(parseFileName.DrivePresent());
       
   121 	
       
   122 	TPath privatePath;
       
   123 	User::LeaveIfError(iFs.PrivatePath(privatePath));
       
   124 	User::LeaveIfError(iFs.SetSessionPath(parseFileName.Drive()));
       
   125 	User::LeaveIfError(iFs.SetSessionPath(privatePath));
       
   126 
       
   127 	// If the path does not exist create it.
       
   128 	TInt err = iFs.MkDirAll(privatePath);
       
   129 
       
   130 	if (err != KErrAlreadyExists && err != KErrNone)
       
   131 		{
       
   132 		User::Leave(err);
       
   133 		}
       
   134 
       
   135 	HBufC* newFileName = CreateBackupRegistrationFileNameLC(parseFileName.NameAndExt());
       
   136 	TPtr newFileNamePtr(newFileName->Des());
       
   137 
       
   138 	// Create registration file.
       
   139 	RFile file;
       
   140 	CleanupClosePushL(file);
       
   141 
       
   142 	err = file.Create(iFs, *newFileName, EFileWrite);
       
   143 
       
   144 	// Registration file already exists so we're done.
       
   145 	if (err == KErrAlreadyExists)
       
   146 		{
       
   147 		CleanupStack::PopAndDestroy(2, newFileName); // file, newFileName
       
   148 		return;
       
   149 		}
       
   150 
       
   151 	if (err)
       
   152 		{
       
   153 		User::Leave(err);
       
   154 		}
       
   155 		
       
   156 	HBufC* nameAndExt = NULL;
       
   157 	nameAndExt = HBufC::NewLC(KSqLiteFilePrefix().Length() + parseFileName.NameAndExt().Length());
       
   158 	if (parseFileName.NameAndExt().Compare(KContactsIniFileName) != 0)
       
   159 		{
       
   160 		nameAndExt->Des().Append(KSqLiteFilePrefix);
       
   161 		}	
       
   162 	nameAndExt->Des().Append(parseFileName.NameAndExt());
       
   163 
       
   164 	// Convert filename and extension to UTF8 before writing to file.
       
   165 	HBufC8* fileNameAndExt8 = HBufC8::NewLC(nameAndExt->Length());
       
   166 	TPtr8 pFileNameAndExt8(fileNameAndExt8->Des());
       
   167 	
       
   168 	User::LeaveIfError(CnvUtfConverter::ConvertFromUnicodeToUtf8(pFileNameAndExt8,
       
   169 		*nameAndExt));
       
   170 
       
   171 	// Write data into file.
       
   172 	User::LeaveIfError(file.Write(KXmlFilePart1()));
       
   173 	User::LeaveIfError(file.Write(pFileNameAndExt8));
       
   174 	User::LeaveIfError(file.Write(KXmlFilePart2()));
       
   175 	User::LeaveIfError(file.Flush());
       
   176 
       
   177 	CleanupStack::PopAndDestroy(4, newFileName); // fileNameAndExt8, file, nameAndExt, newFileName
       
   178 	}
       
   179 
       
   180 
       
   181 /** Delete the XML backup registration file associated with the filename.  The
       
   182 	registration file will be found on the same drive as aFileName.
       
   183 
       
   184 	@param aFileName File name including drive letter i.e. <drive>:<file>.
       
   185 */
       
   186 void CCntBackupRestoreAgent::DeleteBackupRegistrationFileL(const TDesC& aFileName)
       
   187 	{
       
   188 	TParsePtrC parseFileName(aFileName);
       
   189 	
       
   190 	// Find out the drive held in aFileName.  If a drive letter is not present
       
   191 	// then the method leaves.
       
   192 	User::LeaveIfError(parseFileName.DrivePresent());
       
   193 	
       
   194 	TPath privatePath;
       
   195 	User::LeaveIfError(iFs.PrivatePath(privatePath));
       
   196 	User::LeaveIfError(iFs.SetSessionPath(parseFileName.Drive()));
       
   197 	User::LeaveIfError(iFs.SetSessionPath(privatePath));
       
   198 
       
   199 	HBufC* regFileName = CreateBackupRegistrationFileNameLC(parseFileName.NameAndExt());
       
   200 	TPtrC regFileNamePtr(regFileName->Des());
       
   201 
       
   202 	// Check if registration file exists and if so delete it.
       
   203 	TEntry entry;
       
   204 	TInt err = iFs.Entry(regFileNamePtr, entry);
       
   205 
       
   206 	if((err == KErrNone) && !entry.IsDir())
       
   207 		{
       
   208 		User::LeaveIfError(iFs.Delete(regFileNamePtr));
       
   209 		}
       
   210 
       
   211 	CleanupStack::PopAndDestroy(regFileName);
       
   212 	}
       
   213 
       
   214 
       
   215 /** Handle change in value of the property KUidBackupRestoreKey (used to notify
       
   216 	subscribers of Backup/Restore events).
       
   217 	@see CActive
       
   218 */
       
   219 void CCntBackupRestoreAgent::RunL()
       
   220 	{
       
   221 	// Resubscribe before dealing with the current notification.
       
   222 	iBackupRestoreNotification.Subscribe(iStatus);
       
   223 	SetActive();
       
   224 
       
   225 	TInt newState = 0;
       
   226 	
       
   227 	// Flag updated.  Decide what to do in ReceivedNotificationL().
       
   228 	if (iBackupRestoreNotification.Get(newState) != KErrNotFound)
       
   229 		{
       
   230 		ReceivedNotificationL(newState);
       
   231 		}
       
   232 	}
       
   233 
       
   234 
       
   235 /** Recover if RunL() leaves.
       
   236 	@see CActive
       
   237 */
       
   238 TInt CCntBackupRestoreAgent::RunError(TInt /*aError*/)
       
   239 	{
       
   240 	
       
   241 	DEBUG_PRINT1(__VERBOSE_DEBUG__,_L("[CNTMODEL] CCntBackupRestoreAgent::RunError(): RunL() has left!\n")); 
       
   242 
       
   243 	return (KErrNone);
       
   244 	}
       
   245 
       
   246 
       
   247 /**
       
   248 	@see CActive
       
   249 */
       
   250 void CCntBackupRestoreAgent::DoCancel()
       
   251 	{
       
   252 	iBackupRestoreNotification.Cancel();
       
   253 	}
       
   254 
       
   255 
       
   256 /** Determines what operation is starting or has completed and calls the
       
   257 	relevant observer function.
       
   258 
       
   259 	@param aNewState Flags indicating what the new Backup/Restore state is:
       
   260 
       
   261 	1. No Backup/Restore is taking place = EBURNormal | ENoBackup		
       
   262 	2. Backup operation starting = (EBURBackupFull || EBURBackupPartial) &&
       
   263 	   EBackupBase
       
   264 	3. Restore operation starting = (EBURRestoreFull || EBURRestorePartial) &&
       
   265 	   EBackupBase
       
   266 */
       
   267 void CCntBackupRestoreAgent::ReceivedNotificationL(TInt aNewState)
       
   268 	{
       
   269 	// We are starting a a new operation...
       
   270 	// Was there a previous Restore which failed to complete?
       
   271 	if (!(aNewState & (conn::EBURNormal | conn::EBURUnset)) && RestoreInProgress())
       
   272 		{
       
   273 		iCurrentState = aNewState;
       
   274 		RestoreCompletedL(KErrAbort);
       
   275 		}
       
   276 	
       
   277 	// A Base Backup or Restore taking place.
       
   278 	if (aNewState & (conn::EBURBackupPartial | conn::EBURBackupFull) )
       
   279 		{			
       
   280 		// Backup is taking place (either partial or full) 
       
   281 		iCurrentState = aNewState;
       
   282 		BackupBeginningL();
       
   283 		}
       
   284 	else if (aNewState & (conn::EBURRestorePartial | conn::EBURRestoreFull)) 
       
   285 		{
       
   286 		// Restore is taking place (either partial or full)
       
   287 		iCurrentState = aNewState;
       
   288 		RestoreBeginningL();
       
   289 		}
       
   290 	else if (aNewState & (conn::EBURNormal | conn::EBURUnset))
       
   291 		{
       
   292 		// The state has changed to no Backup/Restore.  Decide which operation
       
   293 		// has just completed.
       
   294 		if (BackupInProgress())
       
   295 			{
       
   296 			iCurrentState = aNewState;
       
   297 			BackupCompletedL();
       
   298 			}
       
   299 		else if (RestoreInProgress())
       
   300 			{
       
   301 			iCurrentState = aNewState;
       
   302 			RestoreCompletedL(KErrNone);
       
   303 			}		
       
   304 		}
       
   305 	}
       
   306 
       
   307 
       
   308 void CCntBackupRestoreAgent::ProcessInitialStateL(TInt aNewState)
       
   309 	{
       
   310 	// A Base Backup or Restore is taking place.
       
   311 	if (aNewState & (conn::EBURBackupPartial | conn::EBURBackupFull) )
       
   312 		{
       
   313 		// Backup is taking place (either partial or full).
       
   314 		BackupBeginningL();
       
   315 		}
       
   316 	else if (aNewState & (conn::EBURRestorePartial | conn::EBURRestoreFull)) 
       
   317 		{
       
   318 		// Restore is taking place (either partial or full).
       
   319 		RestoreBeginningL();
       
   320 		}
       
   321 	iCurrentState = aNewState;
       
   322 	}
       
   323 
       
   324 
       
   325 void CCntBackupRestoreAgent::BackupBeginningL()
       
   326 	{
       
   327 	iEvent.iType = EContactDbObserverEventBackupBeginning;
       
   328 	iDbMgrCtrlr.HandleBackupRestoreEventL(iEvent);
       
   329 	iDbMgrCtrlr.IniFileManager().SaveIniFileSettingsIfRequestedL();
       
   330 	}
       
   331 
       
   332 
       
   333 void CCntBackupRestoreAgent::BackupCompletedL()
       
   334 	{
       
   335 	iEvent.iType = EContactDbObserverEventBackupRestoreCompleted;
       
   336 	iDbMgrCtrlr.HandleBackupRestoreEventL(iEvent);
       
   337 	// In case Store has been waiting for backup to finish.  Now attempt to
       
   338 	// perform deferred operation.
       
   339 	iDbMgrCtrlr.IniFileManager().RetryStoreOperation();
       
   340 	}
       
   341 
       
   342 
       
   343 void CCntBackupRestoreAgent::RestoreBeginningL()
       
   344 	{
       
   345 	iEvent.iType = EContactDbObserverEventRestoreBeginning;
       
   346 	iDbMgrCtrlr.HandleBackupRestoreEventL(iEvent);
       
   347 	iDbMgrCtrlr.IniFileManager().SaveIniFileSettingsIfRequestedL();
       
   348 	}
       
   349 
       
   350 
       
   351 void CCntBackupRestoreAgent::RestoreCompletedL(TInt aRestoreResult)
       
   352 	{
       
   353 	if (aRestoreResult == KErrNone)
       
   354 		{
       
   355 		iDbMgrCtrlr.IniFileManager().StartRestoreIniFileSettings();
       
   356 		iEvent.iType = EContactDbObserverEventBackupRestoreCompleted;
       
   357 		iDbMgrCtrlr.HandleBackupRestoreEventL(iEvent);
       
   358 		}
       
   359 	else
       
   360 		{
       
   361 		iEvent.iType = EContactDbObserverEventRestoreBadDatabase;
       
   362 		iDbMgrCtrlr.HandleBackupRestoreEventL(iEvent);
       
   363 		// A restore of the Contacts Model initialisation file failed so save
       
   364 		// initialisation file.
       
   365 		iDbMgrCtrlr.IniFileManager().ScheduleSaveIniFileSettings(CIniFileManager::ESaveAll);
       
   366 		}
       
   367 	}
       
   368 	
       
   369 
       
   370 /** Create an XML backup registration file name using aFileName.
       
   371 
       
   372 	@param aFileName File name without drive letter.
       
   373 */
       
   374 HBufC* CCntBackupRestoreAgent::CreateBackupRegistrationFileNameLC(const TDesC& aFileName)
       
   375 	{	
       
   376 	_LIT(KContactsBackupFileName, "backup_registration");
       
   377 	_LIT(KContactsBackupFileExtension, ".xml");
       
   378 
       
   379 	const TInt newFileNameLength = KContactsBackupFileName().Length() +	
       
   380 	KSqLiteFilePrefix().Length() +
       
   381 	aFileName.Length() + KContactsBackupFileExtension().Length();
       
   382 	
       
   383 	if (newFileNameLength > KMaxFileNameLength)
       
   384 		{
       
   385 		User::Leave(KErrArgument);
       
   386 		}
       
   387 		
       
   388 	HBufC* newFileName = HBufC::NewL(newFileNameLength);
       
   389 	CleanupStack::PushL(newFileName);
       
   390 
       
   391 	TPtr newFileNamePtr(newFileName->Des());
       
   392 
       
   393 	// New filename will be of the form backup_registration<aFileName>.xml.
       
   394 	// If aFileName has an extension then the '.' will be replaced with '_'.
       
   395 	newFileNamePtr.Append(KContactsBackupFileName);
       
   396 	
       
   397 	// if the it is the cntModel.ini file
       
   398 	// then do not append it in the file name
       
   399 	// this ensures that there is one file
       
   400 	// with the name backup_registration.xml file
       
   401 	// which is required for the Backup & Restore engine.
       
   402 	if (aFileName.Compare(KContactsIniFileName) != 0) 
       
   403 	    {
       
   404 	    newFileNamePtr.Append(KSqLiteFilePrefix);
       
   405 		newFileNamePtr.Append(aFileName);             
       
   406 	    }                                             
       
   407 	                                                  
       
   408 	                                                  
       
   409 	TInt dotPos = newFileNamePtr.LocateReverse('.');
       
   410 	if (dotPos != KErrNotFound )
       
   411 		{
       
   412 		newFileNamePtr[dotPos] = '_';
       
   413 		}
       
   414 	newFileNamePtr.Append(KContactsBackupFileExtension);
       
   415 
       
   416 	return newFileName;
       
   417 	}