// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "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:
//
#include <bautils.h>
#include "logservpanic.h"
#include "LogServResourceInterpreter.h"
// Constants
const TInt KLogResourceFileGranularity = 2;
// Literal constants
_LIT(KResourceFileClient,"\\private\\101f401d\\logserv.rsc");
_LIT(KResourceFileWrapper,"\\resource\\logeng\\logwrap.rsc");
/////////////////////////////////////////////////////////////////////////////////////////
// -----> CLogServResourceInterpreter (source)
/////////////////////////////////////////////////////////////////////////////////////////
CLogServResourceInterpreter::CLogServResourceInterpreter(RFs& aFsSession) :
iFsSession(aFsSession), iResourceFiles(KLogResourceFileGranularity),
iResourceStringCache(CResourceStringCacheEntry::Offset()),
iResourceStringCacheIter(iResourceStringCache)
{
}
CLogServResourceInterpreter::~CLogServResourceInterpreter()
{
const TInt count = iResourceFiles.Count();
for(TInt i=0; i<count; i++)
{
TResourceFileEntry& entry = iResourceFiles[i];
entry.iFile.Close();
}
iResourceFiles.Close();
// Iterate through list of cache entries deleting them in turn.
CResourceStringCacheEntry* item ;
iResourceStringCacheIter.SetToFirst() ;
while ((item = iResourceStringCacheIter++) != NULL)
{
iResourceStringCache.Remove(*item);
delete item;
}
}
void CLogServResourceInterpreter::ConstructL()
{
// Load standard resource files
LoadResourceFileL(KResourceFileClient, ELogServer);
LoadResourceFileL(KResourceFileWrapper, ELogWrap);
}
CLogServResourceInterpreter* CLogServResourceInterpreter::NewL(RFs& aFsSession)
{
CLogServResourceInterpreter* self = new(ELeave) CLogServResourceInterpreter(aFsSession);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
void CLogServResourceInterpreter::CreateResourceReaderLC(TResourceReader& aReader, TInt aId, TResourceType aType)
{
HBufC8* buf = GetResourceBufferL(aId, aType) ;
// Resource reader needs to be created with a copy of the cache buffer as otherwise
// our cache buffer will be deleted when the resource reader is deleted!
aReader.SetBuffer(buf->AllocLC());
}
HBufC8* CLogServResourceInterpreter::GetResourceBufferL(TInt aId, TResourceType aType)
{
// Attempt to find the requested resource in the cache
CResourceStringCacheEntry* cacheEntry = FindCachedResourceString(aId, aType) ;
HBufC8* buf ;
if (!cacheEntry)
{
// Not found in cache, load from resource file and add to the
// linked list which forms the cache.
buf = ResourceFileForType(aType).AllocReadLC(aId);
cacheEntry = CResourceStringCacheEntry::NewL(aId, aType, buf) ;
iResourceStringCache.AddLast(*cacheEntry) ;
// buf is now the responsibility of iResourceStringCache and
// will be tidied up by the destructor...
CleanupStack::Pop(buf);
}
else
{
buf = cacheEntry->ResourceString();
}
return buf ;
}
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
void CLogServResourceInterpreter::LoadResourceFileL(const TDesC& aName, TResourceType aType)
{
LOGTEXT3("CLogServResourceInterpreter::LoadResourceFileL(%S, %d)", &aName, aType);
// Find the resource file
TFileName fileName;
fileName.Copy(RProcess().FileName());
TParse parse;
parse.Set(aName, &fileName, NULL);
fileName = parse.FullName();
// Get language of resource file
BaflUtils::NearestLanguageFile(iFsSession, fileName);
// Check the entry exists on this drive (e.g. if we are running the log server
// from RAM, then default to the ROM if no RSC on the current drive exists).
TEntry fsEntry;
if (iFsSession.Entry(fileName, fsEntry) == KErrNotFound)
{
// Switch to ROM (we might already have been launching from the ROM,
// in which case this will have no effect anyway).
fileName[0] = 'Z';
}
// Open resource file
TResourceFileEntry entry;
entry.iType = aType;
CleanupClosePushL(entry.iFile);
LOGTEXT2("CLogServResourceInterpreter::LoadResourceFileL() - localized name is: %S", &fileName);
entry.iFile.OpenL(iFsSession, fileName);
LOGTEXT("CLogServResourceInterpreter::LoadResourceFileL() - resource file open");
// I'm leaving this in just in case somebody decides to try and add this code
// without realising the consequences...
#ifdef __CAN_BREAK_BC__
//
// Can't use BAFL 'NAME' support in resource file, since this
// will break data compatibility with old software using the existing
// logwrap and logcli RSG header files :((
entry.iFile.ConfirmSignatureL();
__ASSERT_ALWAYS(entry.iFile.Offset() != 0, Panic(ELogNoResourceName));
#endif
User::LeaveIfError(iResourceFiles.Append(entry));
CleanupStack::Pop(&entry.iFile);
LOGTEXT("CLogServResourceInterpreter::LoadResourceFileL() - end");
}
const RResourceFile& CLogServResourceInterpreter::ResourceFileForType(TResourceType aType) const
{
const RResourceFile* ret = NULL;
//
const TInt count = iResourceFiles.Count();
for(TInt i=0; i<count; i++)
{
const TResourceFileEntry& entry = iResourceFiles[i];
if (entry.iType == aType)
{
ret = &entry.iFile;
break;
}
}
__ASSERT_ALWAYS(ret != NULL, Panic(ELogNoResourceForId));
return *ret;
}
CLogServResourceInterpreter::CResourceStringCacheEntry * CLogServResourceInterpreter::FindCachedResourceString(const TInt aId, TResourceType aType)
{
CLogServResourceInterpreter::CResourceStringCacheEntry* item ;
// Iterate through linked list of cache entries looking for a
// match - if no match found will drop out with a NULL pointer.
iResourceStringCacheIter.SetToFirst() ;
while ((item = iResourceStringCacheIter++) != NULL)
{
if ((item->ResourceType() == aType) && (item->ResourceId() == aId))
{
break ;
}
};
return item ;
}
/////////////////////////////////////////////////////////////////////////////////////////
// -----> CLogServResourceInterpreter::CResourceStringCacheEntry (source)
/////////////////////////////////////////////////////////////////////////////////////////
CLogServResourceInterpreter::CResourceStringCacheEntry::CResourceStringCacheEntry(TInt aResourceId, CLogServResourceInterpreter::TResourceType aType, HBufC8* aResourceString) : iResourceId (aResourceId), iResourceType (aType), iResourceString(aResourceString)
{
}
CLogServResourceInterpreter::CResourceStringCacheEntry::~CResourceStringCacheEntry()
{
delete iResourceString ;
}
CLogServResourceInterpreter::CResourceStringCacheEntry* CLogServResourceInterpreter::CResourceStringCacheEntry::NewL(TInt aResourceId, CLogServResourceInterpreter::TResourceType aType, HBufC8* aResourceString)
{
return new(ELeave) CResourceStringCacheEntry(aResourceId, aType, aResourceString);
}
TUint CLogServResourceInterpreter::CResourceStringCacheEntry::ResourceId(void)
{
return iResourceId ;
}
CLogServResourceInterpreter::TResourceType CLogServResourceInterpreter::CResourceStringCacheEntry::ResourceType(void)
{
return iResourceType ;
}
HBufC8* CLogServResourceInterpreter::CResourceStringCacheEntry::ResourceString (void)
{
return iResourceString ;
}
TInt CLogServResourceInterpreter::CResourceStringCacheEntry::Offset()
{
return (_FOFF(CLogServResourceInterpreter::CResourceStringCacheEntry, iLink));
}