// APSSERV.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//


#include <e32svr.h>
#include "apfrec.h"
#include "apsses.h"
#include "apsstd.h"
#include "apffndr.h"
#include "apgaplst.h"
#include "apsscan.h"
#include "apsstd.h"
#include "apasvst.h"
#include "datastor.h"

//////////////////////////////
// CApaAppListServer
//////////////////////////////

const TInt KAppListServerPriority=CActive::EPriorityStandard;

EXPORT_C TPtrC NameApaServStartSemaphore()
	{
	return _L("AppArcServerSemaphore");
	}

EXPORT_C TPtrC NameApaServServerThread()
	{
	return _L("AppArcServerThread");
	}

EXPORT_C CApaAppListServer* CApaAppListServer::NewL(CApaAppList* aAppList,CApaFileRecognizer* aRecognizer)
// Create and start a new CApaAppListServer
	{
	__ASSERT_ALWAYS(aAppList && aRecognizer,PanicServer(ESvrCreateServer));
	CApaAppListServer* server=new(ELeave) CApaAppListServer(KAppListServerPriority,aAppList,aRecognizer);
	CleanupStack::PushL(server);
	server->ConstructL(NULL);
	CleanupStack::Pop();
	return(server);
	}

EXPORT_C CApaAppListServer* CApaAppListServer::NewL(MApaAppStarter& aAppStarter)
// Create a new CApaAppListServer which owns it's own resources
	{
	CApaAppListServer* self=new(ELeave) CApaAppListServer(KAppListServerPriority,NULL,NULL);
	CleanupStack::PushL(self);
	self->ConstructL(&aAppStarter);
	CleanupStack::Pop();
	return self;
	}

CApaAppListServer::CApaAppListServer(TInt aPriority,CApaAppList* aAppList,CApaFileRecognizer* aRecognizer)
	: CServer(aPriority),
	iFileRecognizer(aRecognizer),
	iAppList(aAppList)
	{
	__DECLARE_NAME(_S("CApaAppListServer"));
	if (!iFileRecognizer)
		iOwnsList|=EOwnsFileRecognizer;
	if (!iAppList)
		iOwnsList|=EOwnsAppList;
	}

void CApaAppListServer::ConstructL(MApaAppStarter* aAppStarter)
	{
	iName=KAppListServerName.AllocL();
	User::LeaveIfError(Start());
	User::LeaveIfError(iFs.Connect());
	if (iOwnsList&EOwnsFileRecognizer)
		{
		iScanningFileRecognizer=CApaScanningFileRecognizer::NewL(iFs,aAppStarter);
		iFileRecognizer=iScanningFileRecognizer;
		}
	if (iOwnsList&EOwnsAppList)
		{
		iScanningAppFinder=CApaScanningAppFinder::NewL(iFs);
		iAppList=CApaAppList::NewL(iFs,iScanningAppFinder); // takes ownership of scanner
		}
	iDataRecognizer=CApaScanningDataRecognizer::NewL(iFs);
	iAppFsMonitor=CApaFsMonitor::NewL(iFs,KAppDllSearchString,TCallBack(&AppFsNotifyCallBack,this));
	iAppFsMonitor->Start(ENotifyFile);
	AppFsNotifyCallBack(this);
	iRecogFsMonitor=CApaFsMonitor::NewL(iFs,KAppRecognizerSearchString,TCallBack(&RecogFsNotifyCallBack,this));
	iRecogFsMonitor->Start(ENotifyFile);
	RecogFsNotifyCallBack(this);
	iTypeStoreManager=CTypeStoreManager::NewL(iFs);
	TRAPD(err,iTypeStoreManager->RestoreL());
	}


EXPORT_C CApaAppListServer::~CApaAppListServer()
	{
	if (iOwnsList&EOwnsFileRecognizer)
		delete iScanningFileRecognizer;
	if (iOwnsList&EOwnsAppList)
		delete iAppList; // deletes scanner
	delete iDataRecognizer;
	delete iTypeStoreManager;
	iFs.Close();
	}


CSession* CApaAppListServer::NewSessionL(RThread aClient, const TVersion& aVersion) const
// Create a new server session.
	{
	// check we're the right version
	TVersion v(KAppListServMajorVersionNumber,KAppListServMinorVersionNumber,KAppListServBuildVersionNumber);
	if (!User::QueryVersionSupported(v,aVersion))
		User::Leave(KErrNotSupported);
	// make new session
	return CApaAppListServSession::NewL(aClient,(CApaAppListServer*)this);
	}

//
// scanning code here
//

TInt CApaAppListServer::AppFsNotifyCallBack(TAny* aObject)
	{
	REINTERPRET_CAST(CApaAppListServer*,aObject)->UpdateApps();
	return KErrNone;
	}

TInt CApaAppListServer::RecogFsNotifyCallBack(TAny* aObject)
	{
	REINTERPRET_CAST(CApaAppListServer*,aObject)->UpdateRecogs();
	return KErrNone;
	}

void CApaAppListServer::UpdateApps()
// update the list
	{
	if (iOwnsList&EOwnsAppList)
		{
		TRAPD(err,iAppList->StartIdleUpdateL());
		}
	}

void CApaAppListServer::UpdateRecogs()
// update the recognizers
	{
	TInt err;
	if (iOwnsList&EOwnsFileRecognizer)
		TRAP(err,iScanningFileRecognizer->ScanForRecognizersL());
	TRAP(err,iDataRecognizer->ScanForRecognizersL());
	}

void CApaAppListServer::UpdateTypeStore()
// Update the internal type store if things have changed
	{
	// check the time stamp to see if we are interested in an update
	TRAPD(r,
		CTypeStoreManager* manager=CTypeStoreManager::NewL(iFs);
		CleanupStack::PushL(manager);
		TTime modified;
		TInt err=iFs.Modified(manager->IniFileName(),modified);
		if (modified>iTypeStoreModified && err==KErrNone)
			{
			TRAPD(err,manager->RestoreL());
			if (err!=KErrNone)
				CleanupStack::PopAndDestroy(); // manager
			else
				{
				delete iTypeStoreManager;
				iTypeStoreManager=manager;
				CleanupStack::Pop(); // manager
				}
			}
		);
	}