diff -r 000000000000 -r dd21522fd290 browserutilities/feedsengine/FeedsServer/Server/src/FeedsServer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/browserutilities/feedsengine/FeedsServer/Server/src/FeedsServer.cpp Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,697 @@ +/* +* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: The FeedsServer main server class. +* +*/ + + +#include "FeedsDatabase.h" +#include "FeedHandler.h" +#include "FeedsServer.h" +#include "FeedsServerMsg.h" +#include "FeedsServerSession.h" +#include "OpmlParser.h" +#include "OpmlWriter.h" +#include "PackedFolder.h" +#include "ServerHttpConnection.h" +#include "Logger.h" +#include "XmlUtils.h" +#include "BackRestoreHandler.h" +#include "UpdateManager.h" + +// CONSTANTS +_LIT(KFeedsServerPanic, "FeedsServer"); + +//_LIT(KFileSchema, "file://c:"); +_LIT(KDefaultFeed, "default_feeds.xml"); + +_LIT(KDefaultOPMLFileParam, ""); + + +// ----------------------------------------------------------------------------- +// CFeedsServer::NewL +// +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CFeedsServer* CFeedsServer::NewL() + { + CFeedsServer* self = new (ELeave) CFeedsServer(EPriorityNormal); + + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + + return self; + } + + +// ----------------------------------------------------------------------------- +// CFeedsServer::NewL +// +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::ConstructL() + { + StartL(KFeedsServerName); + iBackRestoreHandler = CBackRestoreHandler::NewL(this); + iBackRestoreHandler->StartListening(); + } + + +// ----------------------------------------------------------------------------- +// CFeedsServer::CFeedsServer +// +// C++ default constructor can NOT contain any code that +// might leave. +// ----------------------------------------------------------------------------- +// +CFeedsServer::CFeedsServer(TInt aPriority): + CServer2(aPriority), iLeakTracker(CLeakTracker::EFeedsServer), iIsSleeping(ETrue) + { + } + + +// ----------------------------------------------------------------------------- +// CFeedsServer::~CFeedsServer +// +// Destructor +// ----------------------------------------------------------------------------- +// +CFeedsServer::~CFeedsServer() + { + SleepServer(); + delete iBackRestoreHandler; + iBackRestoreHandler = NULL; + } + + +// ----------------------------------------------------------------------------- +// CFeedsServer::NewSessionL +// +// Create session(s) to client(s) +// ----------------------------------------------------------------------------- +// +CSession2* CFeedsServer::NewSessionL(const TVersion& aVersion, + const RMessage2& /*aMessage*/) const + { + // check we're the right version + TVersion srvVersion(KFeedsServerMajorVersionNumber, + KFeedsServerMinorVersionNumber, + KFeedsServerBuildVersionNumber); + + if (!User::QueryVersionSupported(srvVersion, aVersion)) + { + User::Leave(KErrNotSupported); + } + + // make new session + return (CFeedsServerSession::NewL(*(const_cast(this)))); + } + + +// ----------------------------------------------------------------------------- +// CFeedsServer::RunServerL +// +// Runs the server. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::RunServerL() + { + CActiveScheduler* scheduler = NULL; + CFeedsServer* server = NULL; + + // Naming the server thread after the server helps to debug panics. + User::LeaveIfError(User::RenameThread(KFeedsServerName)); + + // Create and install the active scheduler. + scheduler = new (ELeave) CActiveScheduler; + CleanupStack::PushL(scheduler); + CActiveScheduler::Install(scheduler); + + // Create the server (leave it on the cleanup stack) + server = CFeedsServer::NewL(); + CleanupStack::PushL(server); + + // Initialisation complete, now signal the client + RProcess::Rendezvous(KErrNone); + + // Ready to run. This method doesn't return until the server is shutdown. + CActiveScheduler::Start(); + + // Cleanup. + CleanupStack::PopAndDestroy(server); + CleanupStack::PopAndDestroy(scheduler); + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::PanicClient +// +// Utility to panic the client. +// ----------------------------------------------------------------------------- +void CFeedsServer::PanicClient(const RMessage2& aMessage, TInt aPanic) + { + aMessage.Panic(KFeedsServerPanic, aPanic); + } + + +// ----------------------------------------------------------------------------- +// CFeedsServer::PanicServer +// +// Utility to panic the server. +// ----------------------------------------------------------------------------- +void CFeedsServer::PanicServer(TInt aPanic) + { + User::Panic(KFeedsServerPanic, aPanic); + } + + +// ----------------------------------------------------------------------------- +// CFeedsServer::WakeupServerL +// +// Ensures the server is ready for processing requests. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::WakeupServerL() + { + if (iIsSleeping) + { + // Wake up the server. + TRAPD(err, WakeupServerHelperL()); + + // If the server didn't fully wake up then sleep it and re-leave the error. + if (err != KErrNone) + { + SleepServer(); + User::Leave(err); + } + } + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::WakeupServerHelperL +// +// A helper method to ensure the server is fully started. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::WakeupServerHelperL() + { + TBool created; + + if (iIsSleeping) + { + // Create the shared xml utils instance. + iXmlUtils = CXmlUtils::NewL(); + + // Create the handlers. + iFeedHandler = CFeedHandler::NewL(*iXmlUtils); + iFolderHandler = COpmlParser::NewL(*iXmlUtils); + + // Create the database instance. + iFeedsDatabase = CFeedsDatabase::NewL(this,created); + + // If the database was newly created then load the default feeds into the + // the database. + if (created) + { + RFs rfs; + TBuf path; + RFile file; + CPackedFolder* packedFolder = NULL; + + // Ensure that the default folder file is copied from ROM. + EnsureDefaultFolderFileL(); + + // Get the path to the default folder. + User::LeaveIfError(rfs.Connect()); + CleanupClosePushL(rfs); + + rfs.PrivatePath(path); + path.Append(KDefaultFeed); + User::LeaveIfError(file.Open(rfs, path, EFileRead | EFileShareReadersOnly)); + CleanupClosePushL(file); + + // Import the default folder file synchronously. + packedFolder = ImportFolderL(file, KDefaultOPMLFileParam); + + CleanupStack::PopAndDestroy(/*file*/); + CleanupStack::PopAndDestroy(/*rfs*/); + + CleanupStack::PushL(packedFolder); + + // Load it into the database. + iFeedsDatabase->ImportFolderL(KDefaultFolderListId, *packedFolder); + CleanupStack::PopAndDestroy(packedFolder); + + // Compact the database. + iFeedsDatabase->Compact(); + + } + + ScheduleUpdateManagerL(); + + iIsSleeping = EFalse; + } + } + + +// ----------------------------------------------------------------------------- +// CFeedsServer::SleepServer +// +// Put the server in a resource reduced mode. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::SleepServer() + { + iIsSleeping = ETrue; + + for( int i=0; i(session)->NotifyFolderListChanged(aFolderListId); + } + } + + +// ----------------------------------------------------------------------------- +// CFeedsServer::NotifySettingsChanged +// +// Notify the open sessions that the given folder-list changed. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::NotifySettingsChanged(TInt aFolderListId) + { + CSession2* session = NULL; + + // Notify all of the open sessions. + iSessionIter.SetToFirst(); + while ((session = iSessionIter++) != NULL) + { + static_cast(session)->NotifySettingsChanged(aFolderListId); + } + } + + +#if 0 +// ----------------------------------------------------------------------------- +// CFeedsServer::PurgeOldItems +// +// A method used to purge old feed-items in the background every so often. +// ----------------------------------------------------------------------------- +// +TInt CFeedsServer::PurgeOldItems(TAny *aPtr) + { + CFeedsServer* self = static_cast(aPtr); + + TRAPD(err, self->PurgeOldItemsL()); + return err; + } + + +// ----------------------------------------------------------------------------- +// CFeedsServer::PurgeOldItemsL +// +// A method used to purge old feed-items in the background every so often. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::PurgeOldItemsL() + { + WakeupServerL(); + + // Purge any old items. + TTime yesterday; + + yesterday.UniversalTime(); + yesterday -= TTimeIntervalDays(1); + + iFeedsDatabase->PurgeOldItemsL(yesterday); + } +#endif + + +// ----------------------------------------------------------------------------- +// CFeedsServer::ImportFolderL +// +// Loads and parsers the folder of feeds at the given path. +// ----------------------------------------------------------------------------- +// +CPackedFolder* CFeedsServer::ImportFolderL(const RFile aFile, const TDesC& aOPMLFileName) + { + TInt size; + HBufC8* buffer = NULL; + TPtr8 bufferPtr(NULL, 0); + CPackedFolder* packedFolder = NULL; + + // Read file + User::LeaveIfError(aFile.Size(size)); + + buffer = HBufC8::NewLC(size); + bufferPtr.Set(buffer->Des()); + + User::LeaveIfError(aFile.Read(bufferPtr, size)); + + // Parse the buffer + packedFolder = iFolderHandler->ParseL(*buffer, KNullDesC, KNullDesC, aOPMLFileName); + + // Clean up. + CleanupStack::PopAndDestroy(buffer); + + return packedFolder; + } + +void CFeedsServer::ExportFolderL(RArray &aEntries, const TDesC& aExportFileName) + { + // Export folders to an OPML buffer + OpmlWriter::ExportL(aEntries, aExportFileName); + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::EnsureDefaultFolderFileL +// +// If need be copy default folder file from ROM. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::EnsureDefaultFolderFileL() + { + TInt err; + RFs defaultRfs; + TUint attValue = 0; + TBuf path; + + // Open a connection to the working drive. + User::LeaveIfError(defaultRfs.Connect()); + CleanupClosePushL(defaultRfs); + User::LeaveIfError(defaultRfs.SetSessionPath(_L("c:\\"))); + + // Build the path to the file. + defaultRfs.PrivatePath(path); + path.Append(KDefaultFeed); + + // Test whether or not the folder file is present. + err = defaultRfs.Att(path, attValue); + + // The file is there, just return. + if (err == KErrNone) + { + CleanupStack::PopAndDestroy(/*defaultRfs*/); + return; + } + + // If the file is missing copy it from ROM. + if ((err == KErrNotFound) || (err == KErrPathNotFound)) + { + RFs romRfs; + RFile file; + RFile romFile; + TInt size; + HBufC8* buffer = NULL; + + // Ensure the private path is defined on the c drive. + (void) defaultRfs.CreatePrivatePath(EDriveC); + + // Open an rfs for the z drive. + User::LeaveIfError(romRfs.Connect()); + CleanupClosePushL(romRfs); + User::LeaveIfError(romRfs.SetSessionPath(_L("z:\\"))); + + // Create the destination file. + User::LeaveIfError(file.Create(defaultRfs, path, EFileWrite)); + CleanupClosePushL(file); + + // Open the source file. + User::LeaveIfError(romFile.Open(romRfs, path, EFileRead)); + CleanupClosePushL(romFile); + + // Copy the file. + User::LeaveIfError(romFile.Size(size)); + buffer = HBufC8::NewLC(size); + TPtr8 bufferPtr(buffer->Des()); + + User::LeaveIfError(romFile.Read(bufferPtr, size)); + User::LeaveIfError(file.Write(bufferPtr, size)); + + // Clean up + CleanupStack::PopAndDestroy(buffer); + CleanupStack::PopAndDestroy(/*romFile*/); + CleanupStack::PopAndDestroy(/*file*/); + CleanupStack::PopAndDestroy(/*romRfs*/); + CleanupStack::PopAndDestroy(/*defaultRfs*/); + } + + // Otherwise leave. + else + { + User::LeaveIfError(err); + } + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::SessionOpened +// +// Called from CFeedsServerSession when a session is opened. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::SessionOpened() + { + iSessionCount++; + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::SessionClosed +// +// Called from CFeedsServerSession when a session is closed. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::SessionClosed() + { + iSessionCount--; + + // If all of the sessions are closed then terminate the server. + // + // TODO: Create a timer to delay the shutdown for 20 mins or so, in case + // the client crashes. + // Don't want to shut down feedsserver to ensure autoupdate can occur + if ( iSessionCount <= 0 && !CheckForUpdate() ) + { + CActiveScheduler::Stop(); + } + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::SetAutoUpdateSettingsL +// +// Called from CFeedsServerSession when setting changed. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::SetAutoUpdateSettingsL( TInt aFolderListId, TBool aAutoUpdate, TInt aAutoUpdateFreq, TUint32 aAutoUpdateAP, TBool aAutoUpdateWhileRoaming ) + { + TBool autoUpdate = EFalse; + TInt autoUpdateFreq = 0; + TUint32 autoUpdateAP = 0; + TBool autoUpdateWhileRoaming = EFalse; + + TRAPD( err, iFeedsDatabase->ExtractAutoUpdateSettingsL( aFolderListId, autoUpdate, autoUpdateFreq, autoUpdateAP, autoUpdateWhileRoaming ) ); + if( err != KErrNotFound && err != KErrNone ) + { + User::Leave( err ); + } + + // if any setting changed regarding auto update, restart the scheduler + if( autoUpdate != aAutoUpdate || autoUpdateFreq != aAutoUpdateFreq || autoUpdateAP != aAutoUpdateAP || autoUpdateWhileRoaming != aAutoUpdateWhileRoaming) + { + iFeedsDatabase->CommitAutoUpdateSettingsL( aFolderListId, aAutoUpdate, aAutoUpdateFreq, aAutoUpdateAP, aAutoUpdateWhileRoaming ); + + // notify all clients with the same folderListId about setting changes + NotifySettingsChanged( aFolderListId ); + + ScheduleUpdateManagerL( aFolderListId, aAutoUpdate, aAutoUpdateFreq, aAutoUpdateAP, aAutoUpdateWhileRoaming ); + } + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::ScheduleUpdateManagerL +// +// Schedule the update manager for all folder list ID +// ----------------------------------------------------------------------------- +// +void CFeedsServer::ScheduleUpdateManagerL() + { + RArray folderListIds; + TBool autoUpdate = EFalse; + TInt autoUpdateFreq = 0; + TUint32 autoUpdateAP = 0; + TBool autoUpdateWhileRoaming = EFalse; + + TRAPD( err, iFeedsDatabase->ExtractFolderListIdInSettingsL( folderListIds ) ); + if (err == KErrNone) + { + for( int i=0; i < folderListIds.Count(); i++) + { + // When err is KErrNotFound, autoUpdate will remain false + TRAPD( err, iFeedsDatabase->ExtractAutoUpdateSettingsL( folderListIds[i], autoUpdate, autoUpdateFreq, autoUpdateAP, autoUpdateWhileRoaming ) ); + if (err == KErrNone) + { + ScheduleUpdateManagerL( folderListIds[i], autoUpdate, autoUpdateFreq, autoUpdateAP, autoUpdateWhileRoaming ); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::ScheduleUpdateManagerL +// +// Schedule the update manager for all folder list ID +// ----------------------------------------------------------------------------- +// +void CFeedsServer::ScheduleUpdateManagerL( TInt aFolderListId) + { + TBool autoUpdate = EFalse; + TInt autoUpdateFreq = 0; + TUint32 autoUpdateAP = 0; + TBool autoUpdateWhileRoaming = EFalse; + + // When err is KErrNotFound, autoUpdate will remain false + TRAPD( err, iFeedsDatabase->ExtractAutoUpdateSettingsL( aFolderListId, autoUpdate, autoUpdateFreq, autoUpdateAP, autoUpdateWhileRoaming ) ); + if (err == KErrNone) + { + ScheduleUpdateManagerL( aFolderListId, autoUpdate, autoUpdateFreq, autoUpdateAP, autoUpdateWhileRoaming ); + } + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::ScheduleUpdateManagerL +// +// Schedule the background update all task for one folder list ID. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::ScheduleUpdateManagerL( TInt aFolderListId, TBool /*aAutoUpdate*/, TInt aAutoUpdateFreq, TUint32 aAutoUpdateAP, TBool aAutoUpdateWhileRoaming ) + { + // Clear the old timer. + + for( int i=0; i < iUpdateManagerList.Count(); i++) + { + if( iUpdateManagerList[ i ]->FolderListId() == aFolderListId ) + { + delete iUpdateManagerList[ i ]; + iUpdateManagerList.Remove(i); + break; + } + } + CUpdateManager* updateManager = CUpdateManager::NewL( aFolderListId, aAutoUpdateAP, aAutoUpdateFreq, aAutoUpdateWhileRoaming, *this ); + updateManager->StartL(); + iUpdateManagerList.AppendL( updateManager ); + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::ResetXmlUtilsL +// +// Called from CUpdateFeedTask::LoadCompleted when an error occurs while parsing +// the feed. +// ----------------------------------------------------------------------------- +// +void CFeedsServer::ResetXmlUtilsL() + { + if (iFolderHandler != NULL) + { + delete iFolderHandler; + iFolderHandler = NULL; + } + + if (iFeedHandler != NULL) + { + delete iFeedHandler; + iFeedHandler = NULL; + } + + if (iXmlUtils != NULL) + { + delete iXmlUtils; + iXmlUtils = NULL; + } + + iXmlUtils = CXmlUtils::NewL(); + iFeedHandler = CFeedHandler::NewL(*iXmlUtils); + iFolderHandler = COpmlParser::NewL(*iXmlUtils); + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::CheckForUpdate +// +// Checks whether update is happening +// ----------------------------------------------------------------------------- +// +TBool CFeedsServer::CheckForUpdate() + { + for(int i = 0;i < iUpdateManagerList.Count();i++) + { + if(iUpdateManagerList[i]->iQueueArray.Count() > 0) + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CFeedsServer::UpdateFeedL() +// +// Update the feed ID in Update manager +// ----------------------------------------------------------------------------- +// +void CFeedsServer::UpdateFeedL(TInt aFolderListId, TInt aFeedId, TBool aDeleteFeed) + { + for( int i=0; i < iUpdateManagerList.Count(); i++) + { + if( iUpdateManagerList[ i ]->FolderListId() == aFolderListId ) + { + iUpdateManagerList[ i ]->UpdateFeedL(aFeedId,aDeleteFeed); + return; + } + else if(aFolderListId == KNoFolderListId) + { + iUpdateManagerList[ i ]->UpdateFeedL(aFeedId,aDeleteFeed); + } + } + } +