browserutilities/feedsengine/FeedsServer/Server/src/FeedsServer.cpp
changeset 0 dd21522fd290
child 25 0ed94ceaa377
--- /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<CFeedsServer*>(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<KMaxFileName>  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<iUpdateManagerList.Count(); i++ )
+        {
+        delete iUpdateManagerList[ i ];
+        }
+    iUpdateManagerList.Reset();
+
+    delete iFeedHandler;
+    iFeedHandler = NULL;
+    
+    delete iFolderHandler;
+    iFolderHandler = NULL;
+    
+    delete iFeedsDatabase;
+    iFeedsDatabase = NULL;
+    
+    delete iXmlUtils;
+    iXmlUtils = NULL;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsServer::NotifyFolderListChanged
+//
+// Notify the open sessions that the given folder-list changed.
+// -----------------------------------------------------------------------------
+//
+void CFeedsServer::NotifyFolderListChanged(TInt aFolderListId)
+    {
+    CSession2*  session = NULL;
+
+    // Notify all of the open sessions.    
+    iSessionIter.SetToFirst();
+    while ((session = iSessionIter++) != NULL)
+        {
+        static_cast<CFeedsServerSession*>(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<CFeedsServerSession*>(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<CFeedsServer*>(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<TInt> &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<KMaxFileName>  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<TInt>     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);
+            }
+        }	
+    }
+