messagingfw/biomsgfw/BIOCSRC/BIOOP.CPP
changeset 0 8e480a14352b
child 44 7c176670643f
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     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 // This class contains the parsing and processing of BIO messages.
       
    15 // This functionality was originally carried out in the BIO Server MTM but
       
    16 // has been moved to the Client MTM for reasons of capability. Potentially,
       
    17 // BIO parsers may need additional capabilities for their processing and it would
       
    18 // be difficult to ensure that the Message Server (and all other server MTMs) had
       
    19 // the same capabilities.  By moving the processing to the Client MTM it is only 
       
    20 // the client UI app that needs the additional capabilities.
       
    21 // Parsing and processing of a message is initiated by calling StartCommandL().
       
    22 // The command function can be one of the following:
       
    23 // KBiosMtmParse - just parse the message
       
    24 // KBiosMtmParseThenProcess - parse the message and then process it
       
    25 // KBiosMtmProcess - just process the mesage (must have been parsed previously)
       
    26 // Parsing a message involves finding the relevant BIO parser, loading it and then calling
       
    27 // ParseL() on the parser.
       
    28 // Processing a message involves finding the relevant BIO parser, loading it and then
       
    29 // calling ProcessL() on the parser.
       
    30 // To avoid unresponsiveness, a parse-then-process command is carried out in two steps.
       
    31 // The parsing is carried out first and then the AO is set up so the processing is
       
    32 // carried out in a separate RunL().
       
    33 // Both the parser ParseL() and parser ProcessL() are asynchronous methods.
       
    34 // 
       
    35 //
       
    36 
       
    37 #include <e32uid.h>   	
       
    38 #include <msvstd.h>
       
    39 #include <biodb.h>		// bio database
       
    40 #include <biouids.h>	// contains panic codes
       
    41 #include <txtrich.h>
       
    42 #include <txtfmlyr.h>
       
    43 
       
    44 #include "BIOSCMDS.H"
       
    45 #include "regpsdll.h"   // Parser Registry - used to load the parser
       
    46 #include "bsp.h"		// CBaseScriptParser, CBaseScriptParser2
       
    47 #include "BIOOP.H"
       
    48 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    49 #include <biomessageuids.h>
       
    50 #include "tmsvbioinfo.h"
       
    51 #endif
       
    52 
       
    53 // panic text
       
    54 _LIT(KBioOpPanic, "BIOO");
       
    55 	
       
    56 CBIOOperation* CBIOOperation::NewL(RFs aRFs, CMsvSession& aSession, CBIODatabase* aBDB, TRequestStatus& aCompletionStatus)
       
    57 	{
       
    58 	CBIOOperation* self=new(ELeave) CBIOOperation(aRFs, aSession, aBDB, aCompletionStatus);
       
    59 	CleanupStack::PushL(self);
       
    60 	self->ConstructL();
       
    61 	CleanupStack::Pop(self);
       
    62 	return self;
       
    63 	}
       
    64 
       
    65 
       
    66 CBIOOperation::CBIOOperation(RFs aRFs, CMsvSession& aSession, CBIODatabase* aBDB, TRequestStatus& aCompletionStatus)
       
    67 : CMsvOperation(aSession, EPriorityStandard, aCompletionStatus), 
       
    68 iFs(aRFs), iBioDatabase(aBDB), iInOperation(EFalse)
       
    69 	{
       
    70 	}
       
    71 
       
    72 	
       
    73 void CBIOOperation::ConstructL()
       
    74 //
       
    75 // 2nd phase construction
       
    76 //
       
    77 	{
       
    78 	// initiallise progress
       
    79 	iProgress.iBioState = TBioProgress::EBiosWaiting;
       
    80 
       
    81 	// create msv entry
       
    82 	iCurrentEntry = CMsvEntry::NewL(iMsvSession, KMsvRootIndexEntryIdValue, TMsvSelectionOrdering());
       
    83 	
       
    84 	// add active object
       
    85 	CActiveScheduler::Add(this);
       
    86 	}
       
    87 
       
    88 
       
    89 CBIOOperation::~CBIOOperation()
       
    90 	{
       
    91 	Cancel();
       
    92 	delete iParser;
       
    93 	delete iCurrentEntry;
       
    94 	delete iRegisteredParserDll;
       
    95 	delete iMessageBody;
       
    96 	}
       
    97 
       
    98 
       
    99 void CBIOOperation::StartCommand(const CMsvEntrySelection& aSelection, TInt aCommand, TRequestStatus& aStatus)
       
   100 //
       
   101 // BIOServer specific commands
       
   102 //
       
   103 	{
       
   104 	__ASSERT_DEBUG(iBioOperationState == EBiooWaiting, User::Panic(KBioOpPanic, KBIOMessageOperationNotInactive));
       
   105 	__ASSERT_ALWAYS(aSelection.Count() >= 1, User::Panic(KBioOpPanic, KBIOMessageNotFound));
       
   106 	
       
   107 	// to notify caller on completion
       
   108 	iReportStatus = &aStatus;
       
   109 	aStatus = KRequestPending;
       
   110 
       
   111 	TMsvId service;
       
   112 	TMsvEntry entry;
       
   113 
       
   114 	TInt error = iMsvSession.GetEntry(aSelection.At(0), service, entry);
       
   115 
       
   116 	iMtm = entry.iMtm;   
       
   117 	iService = entry.iServiceId; 
       
   118 
       
   119 	// perform the command, no need to go on if we already got an error
       
   120 	if (error == KErrNone)
       
   121 		{
       
   122 		switch (aCommand)
       
   123 			{
       
   124 		case KBiosMtmParse:
       
   125 			TRAP(error, ParseL(aSelection, EFalse));
       
   126 			break;
       
   127 		case KBiosMtmParseThenProcess:
       
   128 			TRAP(error, ParseL(aSelection, ETrue));
       
   129 			break;
       
   130 		case KBiosMtmProcess:
       
   131 			TRAP(error, ProcessL(aSelection));
       
   132 			break;
       
   133 		default:
       
   134 			error = KErrNotSupported;
       
   135 			break;
       
   136 			}
       
   137 		};
       
   138 	
       
   139 	// check for errors	
       
   140 	if (error != KErrNone)
       
   141 		{
       
   142 		// complete
       
   143 		iStatus = KRequestPending;
       
   144 		TRequestStatus* stat = &iStatus;
       
   145 		SetActive();
       
   146 		User::RequestComplete(stat, error);
       
   147 		}
       
   148 	}
       
   149 
       
   150 
       
   151 void CBIOOperation::DoCancel()
       
   152 //
       
   153 // Cancel
       
   154 //
       
   155 	{
       
   156 	if (iParser)
       
   157 		iParser->Cancel();
       
   158 	iInOperation = EFalse;
       
   159 	User::RequestComplete(iReportStatus, KErrCancel);
       
   160 	}
       
   161 
       
   162 
       
   163 void CBIOOperation::RunL()
       
   164 //
       
   165 // Active object RunL
       
   166 //
       
   167 	{
       
   168 	TInt error = iStatus.Int();
       
   169 	if (error == KErrNone)
       
   170 		{
       
   171 		switch (iBioOperationState)
       
   172 			{
       
   173 		case EBiooParsing:
       
   174 			{
       
   175 			iCurrentEntry->SetEntryL(iCurrentMsvId);
       
   176 
       
   177 			if (iBioOperationOperation == EBioParseAndProcess)
       
   178 				{
       
   179 				iBioOperationState = EBiooWaiting;
       
   180 				ProcessL();
       
   181 				}
       
   182 			else
       
   183 				{
       
   184 				iBioOperationState = EBiooComplete;
       
   185 				}
       
   186 			break;
       
   187 			}
       
   188 		case EBiooProcessing:
       
   189 			iBioOperationState = EBiooComplete;
       
   190 		case EBiooCreating:
       
   191 		case EBiooWaiting:
       
   192 		default:
       
   193 			break;
       
   194 			}
       
   195 		}
       
   196 
       
   197 	if (iBioOperationState == EBiooComplete || error != KErrNone)
       
   198 		{
       
   199 		RunError(error);
       
   200 		}
       
   201 	}
       
   202 
       
   203 
       
   204 TInt CBIOOperation::RunError(TInt aError)
       
   205 	{
       
   206 	// also called with aError == KErrNone
       
   207 	TMsvEntry entry = iCurrentEntry->Entry();
       
   208 	entry.SetReadOnly(ETrue);
       
   209 	TInt error = KErrNone;
       
   210 	TRAP(error,iCurrentEntry->ChangeL(entry));
       
   211 		
       
   212 	iBioOperationState = EBiooWaiting;
       
   213 	iInOperation = EFalse;
       
   214 	iProgress.iErrorCode = aError;
       
   215 		
       
   216 	User::RequestComplete(iReportStatus, aError);
       
   217 	
       
   218 	return error;
       
   219 	}
       
   220 
       
   221 
       
   222 void CBIOOperation::ParseL(const CMsvEntrySelection& aSelection, TBool aCommit)
       
   223 	{
       
   224 	// parse and process?
       
   225 	iBioOperationOperation = aCommit ? EBioParseAndProcess : EBioParseOnly;
       
   226 
       
   227 	// set context
       
   228     iCurrentMsvId = aSelection[0];
       
   229 	iCurrentEntry->SetEntryL(iCurrentMsvId);
       
   230 
       
   231 	// check if it's alreadly parsed
       
   232 	// iMtmData3 == 0 => not yet parsed
       
   233 	// iMtmData3 == 1 => parsed
       
   234 	// iMtmData3 == 2 => processed
       
   235 	if (iCurrentEntry->Entry().MtmData3()==EBioMsgNotParsed)
       
   236 		{
       
   237 		// put in check that it's a valid SMS/smart message	
       
   238 		StartParserL();
       
   239 		}
       
   240 	else if (iCurrentEntry->Entry().MtmData3()==EBioMsgParsed || 
       
   241 			 iCurrentEntry->Entry().MtmData3()==EBioMsgProcessed)
       
   242 		{
       
   243 		iStatus = KRequestPending;
       
   244 		TRequestStatus* ps = &iStatus;
       
   245 		SetActive();
       
   246 		User::RequestComplete(ps, KErrNone);
       
   247 		iProgress.iBioState = TBioProgress::EBiosCreating;
       
   248 
       
   249 		if (iBioOperationOperation == EBioParseAndProcess)
       
   250 			{
       
   251 			iBioOperationState = EBiooParsing;
       
   252 			CreateParserL();
       
   253 			}
       
   254 		else
       
   255 			{
       
   256 			iBioOperationState = EBiooComplete;
       
   257 			}
       
   258 		}
       
   259 	else
       
   260 		{
       
   261 		User::Leave(KErrCorrupt);
       
   262 		}
       
   263 	iInOperation = ETrue;
       
   264 	}
       
   265 
       
   266 
       
   267 void CBIOOperation::CreateParserL()
       
   268 	{
       
   269 
       
   270 	// get bio type uid from message	
       
   271 	TUid parserUid;
       
   272 	parserUid.iUid = iCurrentEntry->Entry().iBioType;
       
   273 
       
   274 	// check if we already have a parser and if it's the correct one
       
   275 	if ((iParser != NULL) && (parserUid != iParser->ParserUid()))
       
   276 		{
       
   277 		// first delete the old parser before creating the new one
       
   278 		delete iParser;
       
   279 		iParser = NULL;
       
   280 		}
       
   281 		
       
   282 	if (iParser == NULL)
       
   283 		{	
       
   284 	  	// create the local variables 
       
   285 		if (parserUid.iUid == 0)
       
   286 			User::Leave(KBspSmartMessageNoParserDefined);
       
   287 		
       
   288 		// get parser filename for loading
       
   289 		TFileName parserDllName(iBioDatabase->GetBioParserNameL(parserUid));
       
   290 		
       
   291 		// create dll registry
       
   292 		delete iRegisteredParserDll;
       
   293 		iRegisteredParserDll = NULL;
       
   294 		iRegisteredParserDll = CRegisteredParserDll::NewL(parserDllName);
       
   295 
       
   296 		// get handle to dll		
       
   297 		RLibrary parserlibrary;
       
   298 		User::LeaveIfError(iRegisteredParserDll->GetLibrary(iFs, parserlibrary));
       
   299 
       
   300 		// create a typedef so that we can make a call to the dll to create a parser.
       
   301 		typedef CBaseScriptParser2* (*NewParserL)(CRegisteredParserDll& registeredparserdll, CMsvEntry& aEntry, RFs& aFs);
       
   302 		
       
   303 		// entry point for NewL function found at ordinal 1
       
   304 		TLibraryFunction libFunc = parserlibrary.Lookup(1);
       
   305 		
       
   306 		// check that we found the entry point
       
   307 		if (libFunc == NULL) 
       
   308 			User::Leave(KErrBadLibraryEntryPoint) ;
       
   309 
       
   310 		// create a function pointer to NewL
       
   311 		NewParserL pFunc = (NewParserL)libFunc;  
       
   312 		CBaseScriptParser2* parser(NULL);
       
   313 	
       
   314 		TInt refcount = iRegisteredParserDll->DllRefCount();
       
   315 		TRAPD(ret, parser = ((*pFunc)(*iRegisteredParserDll, *iCurrentEntry, iFs)));
       
   316 
       
   317 	    // unload the library if allocation failed and refcount == 1
       
   318 		if ((ret != KErrNone) && (iRegisteredParserDll->DllRefCount() == refcount))
       
   319 			iRegisteredParserDll->ReleaseLibrary();
       
   320 		
       
   321 		// leave if error
       
   322 		User::LeaveIfError(ret);
       
   323 		iParser = parser;
       
   324 		}
       
   325 	}
       
   326 
       
   327 
       
   328 void CBIOOperation::StartParserL()
       
   329 //
       
   330 // We have a parser parse the message (fire up the parser)
       
   331 //
       
   332 	{
       
   333 	__ASSERT_DEBUG(iBioOperationState == EBiooWaiting, User::Panic(KBioOpPanic, KBIOMessageOperationNotInactive));
       
   334 	
       
   335 	// get the msg body
       
   336 	ExtractMessageBodyL();
       
   337 
       
   338 	// create parser
       
   339 	CreateParserL();
       
   340 
       
   341 	// set the entry and start the parser (parser takes ownership of entry)
       
   342     // make sure it points to the message
       
   343     iCurrentEntry->SetEntryL(iCurrentMsvId);
       
   344 
       
   345 	// make the entry editable
       
   346 	TMsvEntry entry(iCurrentEntry->Entry());
       
   347 	entry.SetReadOnly(EFalse);
       
   348 	iCurrentEntry->ChangeL(entry);
       
   349 	
       
   350 	// parse 
       
   351 	iParser->ParseL(iStatus, *iMessageBody);
       
   352 	SetActive();
       
   353 	
       
   354 	iBioOperationState = EBiooParsing;
       
   355 	iProgress.iBioState = TBioProgress::EBiosParsing;
       
   356 	}
       
   357 
       
   358 
       
   359 void CBIOOperation::ExtractMessageBodyL()
       
   360 //
       
   361 // Get the message body
       
   362 //
       
   363 	{
       
   364 	// build a CRichText object to read in message body
       
   365 	CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
       
   366     CleanupStack::PushL(paraFormatLayer);
       
   367     CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL();
       
   368     CleanupStack::PushL(charFormatLayer);
       
   369     CRichText* richText = CRichText::NewL(paraFormatLayer, charFormatLayer);
       
   370     CleanupStack::PushL(richText);
       
   371 
       
   372 	// get store holding message body
       
   373     CMsvStore* store = iCurrentEntry->ReadStoreL();
       
   374 	CleanupStack::PushL(store);
       
   375 
       
   376 	// check for message body
       
   377     if (!store->HasBodyTextL())
       
   378     	User::Leave(KErrNotFound);
       
   379 	
       
   380     // extract the body text
       
   381     store->RestoreBodyTextL(*richText);
       
   382     
       
   383     // create buffer to hold body text
       
   384 	TInt messageLength = richText->DocumentLength();
       
   385 	if (iMessageBody)
       
   386 		{
       
   387 		delete iMessageBody;
       
   388 		iMessageBody = NULL;
       
   389 		}
       
   390 	iMessageBody = HBufC::NewL(messageLength);
       
   391 
       
   392 	// read in message body
       
   393 	TPtr messDes = iMessageBody->Des();
       
   394 	TInt length = messDes.Length();
       
   395 	while (length < messageLength)
       
   396 		{
       
   397 		TPtrC desc = richText->Read(length, messageLength-length);
       
   398 		messDes.Append(desc);
       
   399 		length+=desc.Length();
       
   400 		}
       
   401 	CleanupStack::PopAndDestroy(4, paraFormatLayer); // store, text, charFormatLayer, paraFormatLayer
       
   402 	}
       
   403 
       
   404 
       
   405 void CBIOOperation::ProcessL(const CMsvEntrySelection& aSelection)
       
   406 //
       
   407 // successfully parsed the message - do the settings
       
   408 //
       
   409 	{
       
   410 	// set operation
       
   411 	iBioOperationOperation = EBioProcess;
       
   412 
       
   413 	// get the id of the bio message
       
   414     iCurrentMsvId = aSelection[0];
       
   415 	iCurrentEntry->SetEntryL(iCurrentMsvId);
       
   416 
       
   417 	CreateParserL();
       
   418 
       
   419 	iInOperation = ETrue;
       
   420 	ProcessL();
       
   421 	}
       
   422 	
       
   423 	
       
   424 void CBIOOperation::ProcessL()
       
   425 //
       
   426 // successfully parsed the message - do the settings
       
   427 //
       
   428 	{
       
   429 	__ASSERT_DEBUG(iBioOperationState == EBiooWaiting, User::Panic(KBioOpPanic, KBIOMessageOperationNotInactive));
       
   430 
       
   431 	if (iInOperation == EFalse)
       
   432 		User::Leave(KErrDisconnected);
       
   433 	
       
   434 	__ASSERT_ALWAYS(iParser != NULL, User::Panic(KBioOpPanic, KBIOMessageNoParserCreated));
       
   435 	iProgress.iBioState = TBioProgress::EBiosProcessing;
       
   436 	
       
   437 	// make entry readable so we can change things
       
   438 	TMsvEntry entry = iCurrentEntry->Entry();
       
   439 	if (entry.ReadOnly())
       
   440 		{
       
   441 		entry.SetReadOnly(EFalse);
       
   442 		iCurrentEntry->ChangeL(entry);
       
   443 		}
       
   444 
       
   445 	// start to process message
       
   446 	iParser->ProcessL(iStatus);
       
   447 	SetActive();
       
   448 	
       
   449 	iBioOperationState = EBiooProcessing;
       
   450 	}
       
   451 	
       
   452 	
       
   453 const TDesC8& CBIOOperation::ProgressL()
       
   454 //
       
   455 // get progress information
       
   456 //
       
   457 	{
       
   458 	iProgressBuf = TBioProgressBuf(iProgress);
       
   459 	return iProgressBuf;
       
   460 	}