layouts/cdl/CdlServer/src/CdlSFiles.cpp
changeset 0 05e9090e2422
equal deleted inserted replaced
-1:000000000000 0:05e9090e2422
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 #include "CdlSFiles.h"
       
    18 #include "CdlServer.h"
       
    19 #include <e32uid.h>
       
    20 
       
    21 const TUid KCdlLibraryUid = { 0x101F8BD1 };
       
    22 
       
    23 _LIT(KCdlLibsPath,"*:\\sys\\bin");
       
    24 
       
    25 CCdlRefCollection* CCdlDllsWatcherBase::FileContentsLC(const TDesC& aFileName)
       
    26 	{
       
    27 	return CdlServerEngine::FileContentsLC(aFileName);
       
    28 	}
       
    29 
       
    30 //
       
    31 // CCdlDirs
       
    32 //
       
    33 
       
    34 const TInt KCCdlDirsGranularity = 4;
       
    35 
       
    36 CCdlDirs::CCdlDirs()
       
    37 : CArrayPtrFlat<CDir>(KCCdlDirsGranularity)
       
    38 	{
       
    39 	}
       
    40 
       
    41 CCdlDirs::~CCdlDirs()
       
    42 	{
       
    43 	ResetAndDestroy();
       
    44 	}
       
    45 
       
    46 
       
    47 //
       
    48 // CFsWatcher
       
    49 //
       
    50 
       
    51 CFsWatcher::CFsWatcher(RFs& aFs, MFsWatcherObserver& aObserver)
       
    52 : CActive(EPriorityStandard), iFs(aFs), iObserver(aObserver)
       
    53 	{
       
    54 	CActiveScheduler::Add(this);
       
    55 	Queue();
       
    56 	}
       
    57 
       
    58 CFsWatcher::~CFsWatcher()
       
    59 	{
       
    60 	Cancel();
       
    61 	}
       
    62 
       
    63 void CFsWatcher::ConstructL()
       
    64 	{
       
    65 	}
       
    66 
       
    67 CCdlDirs* CFsWatcher::CreateDirsListL() const
       
    68 	{
       
    69 	CCdlDirs* dirs = new(ELeave) CCdlDirs();
       
    70 	CleanupStack::PushL(dirs);
       
    71 
       
    72 	TDriveList drives;
       
    73 	User::LeaveIfError(iFs.DriveList(drives));
       
    74 	TFileName path(KCdlLibsPath);
       
    75 	path.Append('\\');
       
    76 	for (TInt drive = EDriveZ; drive >= EDriveA; drive--)
       
    77 		{
       
    78 		if (drives[drive])
       
    79 			{
       
    80 			path[0] = TText('A' + drive);
       
    81 			CDir* fileList=NULL;
       
    82 			const TUidType dllType(KDynamicLibraryUid, KCdlLibraryUid);
       
    83 			if (iFs.GetDir(path, dllType, ESortByName, fileList) == KErrNone)
       
    84 				{
       
    85 				CleanupStack::PushL(fileList);
       
    86 				dirs->AppendL(fileList);
       
    87 				CleanupStack::Pop(fileList);
       
    88 				}
       
    89 			}
       
    90 		}
       
    91 
       
    92 	CleanupStack::Pop(dirs);
       
    93 	return dirs;
       
    94 	}
       
    95 
       
    96 void CFsWatcher::DoCancel()
       
    97 	{
       
    98 	iFs.NotifyChangeCancel();
       
    99 	}
       
   100 
       
   101 void CFsWatcher::RunL()
       
   102 	{
       
   103 	// errors in the FS watcher can't be reported sensibly, so they are ignored.
       
   104 	TRAPD(ignore, DoRunL());
       
   105 	}
       
   106 
       
   107 void CFsWatcher::DoRunL()
       
   108 	{
       
   109 	// error from RFs::NotifyChange will stop the watcher
       
   110 	User::LeaveIfError(iStatus.Int());
       
   111 	Queue();
       
   112 	// error from CreateDirsListL, most likely OOM, will stop the change from being processed
       
   113 	// immediately, but further changes will make it catch up.
       
   114 	iObserver.NewDirsList(CreateDirsListL());
       
   115 	}
       
   116 
       
   117 void CFsWatcher::Queue()
       
   118 	{
       
   119 	iFs.NotifyChange(ENotifyAll, iStatus, KCdlLibsPath);
       
   120 	SetActive();
       
   121 	}
       
   122 
       
   123 
       
   124 //
       
   125 // CCdlDllsWatcher
       
   126 //
       
   127 
       
   128 void CCdlDllsWatcherBase::NewL(CCdlDllsWatcherBase*& iWatcher, RFs& aFs, MCdlDllsObserver* aObserver)
       
   129 	{
       
   130 	CCdlDllsWatcher* self = new(ELeave) CCdlDllsWatcher(aFs, aObserver);
       
   131 	iWatcher = self;
       
   132 	self->ConstructL();
       
   133 	}
       
   134 
       
   135 CCdlDllsWatcher::CCdlDllsWatcher(RFs& aFs, MCdlDllsObserver* aObserver)
       
   136 : CCdlDllsWatcherBase(aFs), iObserver(aObserver)
       
   137 	{
       
   138 	}
       
   139 
       
   140 CCdlDllsWatcher::~CCdlDllsWatcher()
       
   141 	{
       
   142 	delete iFsWatcher;
       
   143 	delete iCurrent.iDirs;
       
   144 	delete iNew.iDirs;
       
   145 	delete iNext;
       
   146 	Cancel();
       
   147 	}
       
   148 
       
   149 void CCdlDllsWatcher::ConstructL()
       
   150 	{
       
   151 	iFsWatcher = new(ELeave) CFsWatcher(iFs, *this);
       
   152 	iFsWatcher->ConstructL();
       
   153 	iNew.iDirs = iFsWatcher->CreateDirsListL();
       
   154 	iNew.Reset();
       
   155 	Queue();
       
   156 	}
       
   157 
       
   158 void CCdlDllsWatcher::DoCancel()
       
   159 	{
       
   160 	}
       
   161 
       
   162 void CCdlDllsWatcher::RunL()
       
   163 	{
       
   164 	// errors here will be caused by leaves in the observer. These should not stop
       
   165 	// processing of further DLLs. So, errors are ignored.
       
   166 	TRAPD(ignore, DoRunL());
       
   167 	}
       
   168 
       
   169 void CCdlDllsWatcher::DoRunL()
       
   170 	{
       
   171 	if (iCurrent.AtEnd() && iNew.AtEnd())	// At end of both queues, restart if there is a pending dirs list
       
   172 
       
   173 		{
       
   174 		delete iCurrent.iDirs;
       
   175 		iCurrent.iDirs = iNew.iDirs;
       
   176 		iCurrent.Reset();
       
   177 
       
   178 		iNew.iDirs = iNext;
       
   179 		iNext = NULL;
       
   180 		iNew.Reset();
       
   181 
       
   182 		if (iNew.iDirs)
       
   183 			Queue();
       
   184 
       
   185 		if (iTellingObserver)
       
   186 			{
       
   187 			iTellingObserver = EFalse;
       
   188 			iObserver->McdoChangesCompleteL();
       
   189 			}
       
   190 		}
       
   191 	else if (iCurrent.AtEnd())				// at end of current list, any DLLs left in new list should be added
       
   192 		{
       
   193 		AddNewToObserverL();
       
   194 		}
       
   195 	else if (iNew.AtEnd())					// at end of new list, any DLLs left in current list should be removed
       
   196 		{
       
   197 		RemoveCurrentFromObserverL();
       
   198 		}
       
   199 	else if (iCurrent == iNew)				// DLLs are the same, skip to the next one
       
   200 		{
       
   201 		iCurrent.Next();
       
   202 		iNew.Next();
       
   203 		Queue();
       
   204 		}
       
   205 	else if (iCurrent < iNew)				// current DLL does not appear in new list, remove it
       
   206 		{	
       
   207 		// note: it is important to check for deletes before adds, because the
       
   208 		// two files may have the same name but different times.
       
   209 		RemoveCurrentFromObserverL();
       
   210 		}
       
   211 	else									// new DLL does not appear in current list, add it
       
   212 		{
       
   213 		AddNewToObserverL();
       
   214 		}
       
   215 	}
       
   216 
       
   217 void CCdlDllsWatcher::AddNewToObserverL()
       
   218 	{
       
   219 	const TEntry& file = iNew.Current();
       
   220 	iNew.Next();
       
   221 	Queue();
       
   222 	StartTellingObserverIfNecessaryL();
       
   223 	iObserver->McdoFileAddedL(file.iName);
       
   224 	}
       
   225 
       
   226 void CCdlDllsWatcher::RemoveCurrentFromObserverL()
       
   227 	{
       
   228 	const TEntry& file = iCurrent.Current();
       
   229 	iCurrent.Next();
       
   230 	Queue();
       
   231 	StartTellingObserverIfNecessaryL();
       
   232 	iObserver->McdoFileRemovedL(file.iName);
       
   233 	}
       
   234 
       
   235 void CCdlDllsWatcher::StartTellingObserverIfNecessaryL()
       
   236 	{
       
   237 	if (!iTellingObserver)
       
   238 		iObserver->McdoPrepareForChangesL();
       
   239 	iTellingObserver = ETrue;
       
   240 	}
       
   241 
       
   242 void CCdlDllsWatcher::Queue()
       
   243 	{
       
   244 	iStatus = KRequestPending;
       
   245 	TRequestStatus* s = &iStatus;
       
   246 	User::RequestComplete(s, KErrNone);
       
   247 	SetActive();
       
   248 	}
       
   249 
       
   250 void CCdlDllsWatcher::NewDirsList(CCdlDirs* aNewDirs)
       
   251 	{
       
   252 	if (IsActive())
       
   253 		{
       
   254 		delete iNext;
       
   255 		iNext = aNewDirs;
       
   256 		}
       
   257 	else
       
   258 		{
       
   259 		iNew.iDirs = aNewDirs;
       
   260 		iNew.Reset();
       
   261 		Queue();
       
   262 		}
       
   263 	}
       
   264 
       
   265 
       
   266 //
       
   267 // CCdlDllsWatcher::TDllList
       
   268 //
       
   269 
       
   270 void CCdlDllsWatcher::TDllList::Reset()
       
   271 	{
       
   272 	Mem::FillZ(iIndices, sizeof(TInt)*KMaxDrives);
       
   273 	SetCurrent();
       
   274 	}
       
   275 
       
   276 TBool CCdlDllsWatcher::TDllList::operator==(const TDllList& aRhs) const
       
   277 	{
       
   278 	__ASSERT_ALWAYS(iCurrent, Panic(EPanicTDllListOpEqNullCurrent));
       
   279 
       
   280 	const TEntry& rhsEntry = aRhs.Current();
       
   281 	return	iCurrent->iName.CompareF(rhsEntry.iName) == 0 &&
       
   282 			iCurrent->iModified == rhsEntry.iModified;
       
   283 	}
       
   284 
       
   285 TBool CCdlDllsWatcher::TDllList::operator<(const TDllList& aRhs) const
       
   286 	{
       
   287 	__ASSERT_ALWAYS(iCurrent, Panic(EPanicTDllListOpLtNullCurrent));
       
   288 
       
   289 	const TEntry& rhsEntry = aRhs.Current();
       
   290 	TInt cmp = iCurrent->iName.CompareF(rhsEntry.iName);
       
   291 	return	cmp < 0 || (cmp == 0 && iCurrent->iModified < rhsEntry.iModified);
       
   292 	}
       
   293 
       
   294 const TEntry& CCdlDllsWatcher::TDllList::Current() const
       
   295 	{
       
   296 	__ASSERT_ALWAYS(iCurrent, Panic(EPanicTDllListCurrentNullCurrent));
       
   297 
       
   298 	return *iCurrent;
       
   299 	}
       
   300 
       
   301 TBool CCdlDllsWatcher::TDllList::AtEnd() const
       
   302 	{
       
   303 	if (!iDirs)
       
   304 		return ETrue;
       
   305 
       
   306 	return !iCurrent;
       
   307 	}
       
   308 
       
   309 void CCdlDllsWatcher::TDllList::Next()
       
   310 	{
       
   311 	__ASSERT_ALWAYS(iCurrent, Panic(EPanicTDllListNextNullCurrent));
       
   312 	__ASSERT_ALWAYS(iDirs, Panic(EPanicTDllListNextNullDirs));
       
   313 
       
   314 	TInt count = iDirs->Count();
       
   315 	for (TInt ii = 0; ii < count; ii++)
       
   316 		{
       
   317 		CDir& dir = *iDirs->At(ii);
       
   318 		if (iIndices[ii] < dir.Count())
       
   319 			{
       
   320 			const TEntry& entry = dir[iIndices[ii]];
       
   321 			if (entry.iName.CompareF(iCurrent->iName) == 0)
       
   322 				iIndices[ii]++;
       
   323 			}
       
   324 		}
       
   325 
       
   326 	SetCurrent();
       
   327 	}
       
   328 
       
   329 void CCdlDllsWatcher::TDllList::SetCurrent()
       
   330 	{
       
   331 	// This function implements the CDL drive priority rule, 
       
   332 	// where DLLs on Z are higher priority than Y...
       
   333 	// nb. Z: is the first in iDirs, A: is last.
       
   334 
       
   335 	iCurrent = NULL;
       
   336 	if (!iDirs)
       
   337 		return;
       
   338 
       
   339 	TInt count = iDirs->Count();
       
   340 	for (TInt ii = 0; ii < count; ii++)
       
   341 		{
       
   342 		CDir& dir = *iDirs->At(ii);
       
   343 		if (iIndices[ii] < dir.Count())
       
   344 			{
       
   345 			const TEntry& entry = dir[iIndices[ii]];
       
   346 			if (!iCurrent || entry.iName.CompareF(iCurrent->iName) < 0)
       
   347 				iCurrent = &entry;
       
   348 			}
       
   349 		}
       
   350 	}
       
   351 
       
   352 TInt CCdlDllsWatcher::IsPluginInRom(const TDesC& /*aFileName*/, TBool& /*aIsInRom*/) const
       
   353 	{
       
   354 	return KErrNotSupported;
       
   355 	}
       
   356 
       
   357