--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/widgetengine/src/Preferences.cpp Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,484 @@
+/*
+* Copyright (c) 2006 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: This class represents the Widget Preferences object
+*
+*/
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <S32FILE.H>
+#include <f32file.h>
+#include <uri16.h>
+#include <e32hashtab.h>
+#include "Preferences.h"
+
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+const TInt KMaxIntLength = 10;
+const TInt KMaxKeyValueSize = 4096; //4 k
+
+_LIT( KKeyFormat, "%d.%S" );
+_LIT( KPrefsFile,"prefs.dat" );
+
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::WidgetPreferences
+// C++ Constructor
+//
+//
+// ----------------------------------------------------------------------------
+WidgetPreferences::WidgetPreferences() :m_widgetid(0),
+ m_widgetbundleid(0),
+ m_basepath(0),
+ m_filepath(0)
+{
+ m_preferences = new RPtrHashMap<TDesC,PrefElement>();
+}
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::~WidgetPreferences
+// Destructor
+//
+//
+// ----------------------------------------------------------------------------
+WidgetPreferences::~WidgetPreferences()
+{
+ TRAP_IGNORE( saveL() );
+ if (m_preferences) {
+ m_preferences->ResetAndDestroy();
+ m_preferences->Close();
+ delete m_preferences;
+ }
+ delete m_basepath;
+ delete m_widgetbundleid;
+ delete m_filepath;
+}
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::setBasePathL
+//
+//
+// ----------------------------------------------------------------------------
+void WidgetPreferences::setBasePathL(const TDesC& aValue)
+{
+ m_basepath = aValue.AllocL();
+}
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::setWidgetId
+//
+//
+// ----------------------------------------------------------------------------
+void WidgetPreferences::setWidgetId(TInt aValue)
+{
+ m_widgetid = aValue;
+}
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::setBundleIdL
+//
+//
+// ----------------------------------------------------------------------------
+void WidgetPreferences::setWidgetBundleId(const TDesC& aValue)
+{
+ m_widgetbundleid = aValue.AllocL();
+}
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::setBundleIdL
+//
+//
+// ----------------------------------------------------------------------------
+TDesC& WidgetPreferences::getWidgetBundleId()
+{
+ return *m_widgetbundleid;
+}
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::PreferenceL
+// Get preference for a key
+//
+//
+// ----------------------------------------------------------------------------
+TInt WidgetPreferences::preferenceL( const TDesC& akey, TPtrC& avalue)
+{
+
+ TInt rSuccess = KErrNotFound;
+ TInt size = 0;
+
+ if ( !m_basepath || (m_basepath->Length() <= 0) )
+ return rSuccess;
+
+
+ if ( akey.Length() <= KMaxKeyValueSize ) {
+
+ HBufC* k = HBufC::NewLC( akey.Length() + KMaxIntLength + 1 );
+ k->Des().Format( KKeyFormat, m_widgetid, &akey );
+
+ PrefElement* pref = m_preferences->Find( *k );
+
+ if ( !pref ) {
+ CleanupStack::PopAndDestroy( k );
+ return rSuccess;
+ }
+
+ size = pref->valueSize();
+
+ if ( size > KMaxKeyValueSize ) {
+ // return contents from temp file whose name is stored
+ // in the m_value member of m_preferences
+ RFs fs;
+
+ if ( fs.Connect() == KErrNone ) {
+ CleanupClosePushL( fs );
+ HBufC* filePath = HBufC::NewLC( pref->value().Length() );
+ TPtr fName( filePath->Des() );
+ fName.Append( pref->value() );
+
+ RFileReadStream readStream;
+
+ if ( readStream.Open( fs, *filePath, EFileRead ) == KErrNone ) {
+ CleanupClosePushL( readStream );
+ TInt len( readStream.ReadInt32L() );
+ if ( len > 0 ) {
+ HBufC* v = HBufC::NewLC( len );
+ TPtr ptrvalue = v->Des();
+ readStream.ReadL( ptrvalue, len );
+ avalue.Set( *v );
+ CleanupStack::Pop( v );
+ rSuccess = KErrNone;
+ }
+ CleanupStack::PopAndDestroy();//readStream
+ }
+
+ CleanupStack::PopAndDestroy( 2 ); //filePath,fs
+ }
+ }
+ else if ( size >= 0 ) {
+ avalue.Set( pref->value() );
+ rSuccess = KErrNone;
+ }
+
+ CleanupStack::PopAndDestroy( k );
+ }
+
+ return rSuccess;
+
+}
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::SetPreferenceL
+// set Preference for a key
+//
+//
+// ----------------------------------------------------------------------------
+void WidgetPreferences::setPreferenceL( const TDesC& akey, const TDesC& avalue)
+{
+ if ( !m_basepath || (m_basepath->Length() <= 0) )
+ return;
+
+ if ( akey.Length() <= KMaxKeyValueSize ) {
+
+ HBufC* k = HBufC::NewLC( akey.Length() + KMaxIntLength + 1 );
+ k->Des().Format( KKeyFormat, m_widgetid, &akey );
+
+ // if hash has the key and its value
+ // delete the old value later when the new value was successfully updated
+ PrefElement* prefExisting = NULL;
+ prefExisting = m_preferences->Find( *k );
+
+ if ( avalue.Length() <= KMaxKeyValueSize ) {
+ PrefElement* pref = new (ELeave) PrefElement;
+ CleanupStack::PushL( pref );
+ pref->setValueL( avalue );
+ pref->setValueSize( avalue.Length() );
+ m_preferences->InsertL( k, pref );
+ CleanupStack::Pop(); //pref
+ }
+ else {
+ // create a temp file and save the value in temp file.
+ // m_value member of PrefElement contains the temp file name.
+ RFs fs;
+ RFile file;
+ if ( fs.Connect() == KErrNone ) {
+ CleanupClosePushL( fs );
+
+ // create and write to file
+ TFileName tempFileName;
+ file.Temp( fs, *m_basepath, tempFileName, EFileWrite|EFileShareExclusive );
+ CleanupClosePushL( file );
+ HBufC* filePath = HBufC::NewLC( tempFileName.Length() );
+ TPtr fName( filePath->Des() );
+ fName.Append( tempFileName );
+ RFileWriteStream writeStream( file );
+ CleanupClosePushL( writeStream );
+ TRAPD( err,
+ writeStream.WriteInt32L( avalue.Length() );
+ writeStream.WriteL( avalue );
+ writeStream.CommitL(); );
+ // If an error occured while writing to the file, delete the temp file
+ // This should be the case when disk is full
+ if ( err != KErrNone )
+ {
+ CleanupStack::PopAndDestroy( ); //writeStream
+ file.Close();
+ fs.Delete( *filePath );
+ User::Leave( err );
+ }
+
+ // create new preference element
+ PrefElement* pref = new ( ELeave ) PrefElement;
+ CleanupStack::PushL( pref );
+ pref->setValueSize( avalue.Length() );
+ pref->setValueL( *filePath );
+ // update new preference element
+ m_preferences->InsertL( k, pref );
+
+ CleanupStack::Pop( pref );
+ CleanupStack::PopAndDestroy( ); //writeStream
+ CleanupStack::PopAndDestroy( 3 ); //filePath,file,fs
+ }
+ }
+
+ // now the new value is updated, it's safe to delete the old value
+ if ( prefExisting ) {
+ prefExisting->setCleanFileFlag( ETrue );
+ delete prefExisting;
+ }
+
+ CleanupStack::Pop(); // k
+ }
+
+}
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::removePreferenceL
+// remove Preference for a key
+//
+//
+// ----------------------------------------------------------------------------
+void WidgetPreferences::removePreferenceL( const TDesC& akey, const TDesC& avalue)
+{
+ if ( !m_basepath || (m_basepath->Length() <= 0) )
+ return;
+
+ // double check value is NULL
+ if ( avalue != KNullDesC ) {
+ return;
+ }
+
+ if ( akey.Length() <= KMaxKeyValueSize ) {
+
+ HBufC* k = HBufC::NewLC( akey.Length() + KMaxIntLength + 1 );
+ k->Des().Format( KKeyFormat, m_widgetid, &akey );
+
+ // if hash has the key and its value
+ // delete the old value later when the new value was successfully updated
+ PrefElement* prefExisting = NULL;
+ prefExisting = m_preferences->Find( *k );
+
+ m_preferences->Remove(k);
+
+ // now the new value is updated, it's safe to delete the old value
+ if ( prefExisting ) {
+ prefExisting->setCleanFileFlag( ETrue );
+ delete prefExisting;
+ }
+
+ CleanupStack::PopAndDestroy(); // k
+ }
+}
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::SaveL
+// SAve preferences to persistent storage
+//
+//
+// ----------------------------------------------------------------------------
+void WidgetPreferences::saveL()
+{
+ if ( !m_basepath || (m_basepath->Length() <= 0) )
+ return;
+
+ RFs fs;
+
+ if ( fs.Connect() == KErrNone ) {
+
+ CleanupClosePushL( fs );
+ HBufC* filePath = HBufC::NewLC( m_basepath->Length() + KPrefsFile().Length() );
+
+ TPtr fName( filePath->Des() );
+ fName.Append( *m_basepath );
+ fName.Append( KPrefsFile );
+
+ RFileWriteStream writeStream;
+ TInt fileerror = writeStream.Replace( fs, *filePath, EFileWrite );
+
+ if ( fileerror != KErrNone ) {
+ fs.CreatePrivatePath( EDriveC );
+ fileerror = writeStream.Create( fs, *filePath, EFileWrite|EFileShareExclusive );
+ }
+
+ if ( fileerror == KErrNone ) {
+ CleanupClosePushL( writeStream );
+ writeStream.WriteInt32L( m_preferences->Count() );
+
+ TPtrHashMapIter<TDesC,PrefElement> it( *m_preferences );
+ const TDesC* key;
+ const PrefElement* pref;
+
+ while ( ( key = it.NextKey() ) != 0 ) {
+ pref = it.CurrentValue();
+ writeStream.WriteInt32L( key->Length() );
+ writeStream.WriteL( *key );
+ writeStream.WriteInt32L( pref->value().Length() );
+ writeStream.WriteL( pref->value() );
+ writeStream.WriteInt32L( pref->valueSize() );
+ }
+
+ writeStream.CommitL();
+ CleanupStack::PopAndDestroy(); //writeStream
+ }
+
+ CleanupStack::PopAndDestroy( 2 ); //fs,filePath
+ }
+
+}
+
+// ----------------------------------------------------------------------------
+// WidgetPreferences::LoadL
+// Load preferences from persistent storage
+//
+//
+// ----------------------------------------------------------------------------
+void WidgetPreferences::loadL()
+{
+ RFs fs;
+ if ( !m_basepath || (m_basepath->Length() <= 0) )
+ return;
+
+ if ( fs.Connect() == KErrNone ) {
+ CleanupClosePushL( fs );
+ HBufC* filePath = HBufC::NewLC( m_basepath->Length() + KPrefsFile().Length() );
+
+ TPtr fName( filePath->Des() );
+ fName.Append( *m_basepath );
+ fName.Append( KPrefsFile );
+
+ RFileReadStream readStream;
+
+ if ( readStream.Open( fs, *filePath, EFileRead ) == KErrNone ) {
+ CleanupClosePushL( readStream );
+ TInt count( readStream.ReadInt32L() );
+
+ for( TInt i = 0; i < count; i++ ) {
+ TInt len = readStream.ReadInt32L();
+
+ if ( len > 0 ) {
+ HBufC* key = HBufC::NewLC( len );
+ TPtr ptrkey = key->Des();
+ readStream.ReadL( ptrkey, len );
+ len = readStream.ReadInt32L();
+
+ if ( len <= KMaxKeyValueSize ) {
+ HBufC* value = HBufC::NewLC( len );
+ TPtr ptrvalue = value->Des();
+ readStream.ReadL( ptrvalue, len );
+ PrefElement* pref = new ( ELeave ) PrefElement;
+ CleanupStack::PushL( pref );
+ pref->setValueL( ptrvalue );
+ TInt size = readStream.ReadInt32L();
+ pref->setValueSize( size );
+ m_preferences->InsertL( key, pref );
+ CleanupStack::Pop(); //pref
+ CleanupStack::PopAndDestroy(); //value
+ CleanupStack::Pop(); //key
+ }
+ else {
+ CleanupStack::PopAndDestroy( key );
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(); //readStream
+ }
+
+ CleanupStack::PopAndDestroy( 2 ); //fs,filePath
+ }
+}
+
+// ----------------------------------------------------------------------------
+// PrefElement::PrefElement
+// C++ constructor
+//
+//
+// ----------------------------------------------------------------------------
+PrefElement::PrefElement() : m_value (0), m_valuesize (0), m_cleanFileFlag (EFalse)
+{
+}
+
+
+// ----------------------------------------------------------------------------
+// PrefElement::~PrefElement
+// Destructor
+//
+//
+// ----------------------------------------------------------------------------
+PrefElement::~PrefElement()
+{
+ // When we update the existing key with newer value:
+ // if the value > 4k, which means a file was created to store the value;
+ // we need to delete the old file.
+ // If called from ~Preferences(), we shouldn't do this -- cleanFileFlag is false
+ if ( m_cleanFileFlag && m_valuesize > KMaxKeyValueSize ) {
+ HBufC* filePathExisting = HBufC::NewLC( value().Length() );
+ TPtr fName( filePathExisting->Des() );
+ fName.Append( value() );
+
+ RFs fs;
+ if ( fs.Connect() == KErrNone ) {
+ fs.Delete(*filePathExisting);
+ fs.Close();
+ }
+
+ CleanupStack::PopAndDestroy(); //filePathExisting
+ }
+
+ delete m_value;
+}
+
+
+// ----------------------------------------------------------------------------
+// PrefElement::setValueL
+// set value for a preference
+//
+//
+// ----------------------------------------------------------------------------
+void PrefElement::setValueL( const TDesC& value )
+{
+ if ( m_value ) {
+ delete m_value;
+ }
+
+ m_value = value.AllocL();
+}
+
+