// Copyright (c) 2003-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:
//
/**
@file
@internalComponent
@released
*/
#include <e32test.h>
#include <s32mem.h>
#include <badesca.h> //For CDesCArray
#include <cntstd.h>
#include "dbdbmsdumper.h"
#include "dbhtmltags.h"
#include <CoreAppstest\TestServer.h>
_LIT(KErrorMessage, "DBDbmsDumper Failed");
const TInt KMaxPathLength = 100;
const TInt KBufferLength = 80;
/**
Class destructor
*/
CDbDbmsDumper::~CDbDbmsDumper()
{
delete iBuffer;
delete iTableNames;
iFile.Close();
iDatabase.Close();
iDbsSession.Close();
iFsSession.Close();
}
/**
Second phase constructor for CDbDbmsDumper
@param aDbName name of the database to be dumped.
@param aOutputDir directory where html file will be generated
*/
void CDbDbmsDumper::ConstructL(const TDesC& aDbName, const TDesC& aOutputDir)
{
// Output File Name
_LIT(KOutputFile,"DbDump.html");
TBuf<KMaxPathLength> path(aOutputDir);
path.Append(KOutputFile);
User::LeaveIfError(iFsSession.Connect());
User::LeaveIfError(iDbsSession.Connect());
// Copy the Contacts database from the contacts server private directory to
// the DBMS private directory
RPIMTestServer serv;
User::LeaveIfError(serv.Connect());
_LIT(KDBContactsPrivFile, "?:\\private\\10003a73\\Contacts.cdb");
_LIT(KDBDBMsPrivFile, "?:\\private\\100012a5\\DBS_100065FF_Contacts.cdb");
TBuf<sizeof(KDBContactsPrivFile)> contactsDBPrivFilePath(KDBContactsPrivFile);
TBuf<sizeof(KDBDBMsPrivFile)> dBMsPrivFilePath(KDBDBMsPrivFile);
contactsDBPrivFilePath[0] = (TUint8) RFs::GetSystemDriveChar();
dBMsPrivFilePath[0] = (TUint8) RFs::GetSystemDriveChar();
serv.CopyFileL(contactsDBPrivFilePath, dBMsPrivFilePath);
serv.Close();
_LIT(KCntDbSecureFormat,"secure[100065FF]");
// Contact databases are in DBMS private directory
User::LeaveIfError(iDatabase.Open(iDbsSession, aDbName, KCntDbSecureFormat));
User::LeaveIfError(iFile.Replace(iFsSession, path, EFileWrite) );
iBuffer = HBufC8::NewL(KBufferLength);
iTableNames = iDatabase.TableNamesL();
}
/**
Return a concrete CDbDbmsDumper object
@param aDbName name of the database to be dumped.
@param aOutputDir directory where html file will be generated
*/
CDbDbmsDumper* CDbDbmsDumper::NewLC(const TDesC& aDbName, const TDesC& aOutputDir)
{
CDbDbmsDumper* self = new (ELeave) CDbDbmsDumper();
CleanupStack::PushL(self);
self->ConstructL(aDbName, aOutputDir);
return self;
}
/**
Returns number of tables that exist in the curent dbms database
*/
TInt CDbDbmsDumper::NumberOfTables() const
{
return iTableNames->Count();
}
/**
Output one table to the html file. Traverse a table and output each row
in the html file
@param aTableIndex table index in the table array
*/
void CDbDbmsDumper::OutputTableToFileL(TInt aTableIndex)
{
iFile.Write(KTable);
OutputTableNameToFile(aTableIndex);
CDesCArray* colNames = OutputTableColHeadingsToFileLC(aTableIndex);
User::LeaveIfError(iDbTable.Open(iDatabase, (*iTableNames)[aTableIndex], RDbRowSet::EReadOnly) );
User::LeaveIfError(iDbTable.SetNoIndex() ); // set rowset order as underlying row order
iDbTable.BeginningL(); // set cursor to start of table
iDbTable.NextL();
// output the table's rows
while (!iDbTable.AtEnd() )
{
iFile.Write(KRow);
OutputTableColDataToFileL(*colNames);
iDbTable.NextL();
iFile.Write(KRowEnd);
}
iDbTable.Close();
iFile.Write(KTableEnd);
CleanupStack::PopAndDestroy(colNames);
}
/**
Output table name to the html file
@param aTableIndex table index in the table array
*/
void CDbDbmsDumper::OutputTableNameToFile(TInt aTableIndex)
{
iFile.Write(KBold);
iBuffer->Des().Copy( (*iTableNames)[aTableIndex]); // write (*iTableNames)[aTableIndex] to the file.
iFile.Write(*iBuffer);
iFile.Write(KBoldEnd);
}
/**
Outputs table header for the tables created in the html file
The header contains the column names
@param aTableIndex table index in the table array
*/
CDesCArray* CDbDbmsDumper::OutputTableColHeadingsToFileLC(TInt aTableIndex)
{
CDesCArraySeg* colNames = new (ELeave) CDesCArraySeg(8);
CleanupStack::PushL(colNames);
CDbColSet* colSet = iDatabase.ColSetL( (*iTableNames)[aTableIndex] );
CleanupStack::PushL(colSet);
const TInt KMaxCols( (colSet->Count() ) );
TInt counter = 0;
iFile.Write(KHdRow);
// cols are from 1, to maxCols. not from 0 to maxCols-1.
for (counter = 1; counter <= KMaxCols; ++counter)
{
iFile.Write(KCell);
iBuffer->Des().Copy( (*colSet)[counter].iName );
colNames->AppendL((*colSet)[counter].iName);
iFile.Write(*iBuffer);
iFile.Write(KCellEnd);
}
iFile.Write(KRowEnd);
CleanupStack::PopAndDestroy(colSet);
return colNames;
}
/**
Output a table row to the html file
@param colNames descriptor array containing rows to be written in the resulting html file
*/
void CDbDbmsDumper::OutputTableColDataToFileL(const CDesCArray& colNames)
{
TInt counter = 0;
const TInt KNumberOfCols( (iDbTable.ColCount() ));
iDbTable.GetL(); // get the row to be output
// cols are from 1, to maxCols. not from 0 to KNumberOfCols-1.
for (counter = 1; counter <= KNumberOfCols; ++counter) // for each column value in this row
{
iFile.Write(KCell);
if (iDbTable.IsColNull(counter) )
{
iBuffer->Des().Format(KNullCol); // write out 'NULL' to the file
}
else
{
switch ( iDbTable.ColType(counter) )
{
case EDbColInt8:
case EDbColInt16:
case EDbColInt32:
{
TInt32 val = iDbTable.ColInt32(counter);
iBuffer->Des().Format(KInt32String, val);
}
break;
case EDbColBit:
case EDbColUint8:
case EDbColUint16:
case EDbColUint32:
{
TUint32 val = iDbTable.ColUint32(counter);
iBuffer->Des().Format(KUInt32String, val);
}
break;
case EDbColInt64:
{
TInt64 val = iDbTable.ColInt64(counter);
iBuffer->Des().Format(KUInt64String, I64HIGH(val), I64LOW(val) );
}
break;
case EDbColReal32:
{
TReal32 val = iDbTable.ColReal32(counter);
iBuffer->Des().Format(KRealString, val);
}
break;
case EDbColReal64:
{
TReal64 val = iDbTable.ColReal64(counter);
iBuffer->Des().Format(KRealString, val);
}
break;
case EDbColDateTime:
{
TTime val = iDbTable.ColTime(counter);
TBuf<80> tmpBuffer;
val.FormatL(tmpBuffer, KFormatDate);
iBuffer->Des().Copy(tmpBuffer);
}
break;
case EDbColBinary:
case EDbColText8:
{
TPtrC8 val = iDbTable.ColDes8(counter);
iBuffer->Des().Copy(val);
}
break;
case EDbColText16:
{
TPtrC16 val = iDbTable.ColDes16(counter);
iBuffer->Des().Copy(val);
}
break;
case EDbColLongText8:
iBuffer->Des().Format(KLongText8);
break;
case EDbColLongText16:
LongBinaryL(counter);
break;
case EDbColLongBinary:
if (colNames[counter-1] == KFieldHeaderColName)
{
FieldHeaderColL(counter);
}
else
{
LongBinaryL(counter);
}
break;
default:
iBuffer->Des().Format(KUnknownMessage);
break;
} // switch
} // if
iFile.Write(*iBuffer);
iFile.Write(KCellEnd);
} // for
}
/**
Output the header blob to resulting html file
@param aFieldIndex column index containing the header values in dbms database
*/
void CDbDbmsDumper::FieldHeaderColL(TInt aFieldIndex)
{
TAutoClose<RDbColReadStream> headerBlob;
TAutoClose<RStoreReadStream> stream;
headerBlob.iObj.OpenL(iDbTable, aFieldIndex);
CEmbeddedStore* headerStore=CEmbeddedStore::FromLC(headerBlob.iObj);
stream.iObj.OpenLC(*headerStore, headerStore->Root());
DumpStreamL(stream.iObj);
CleanupStack::PopAndDestroy(&stream.iObj); //OpenLC
CleanupStack::PopAndDestroy(headerStore);
}
/**
Output the values stored in binary blob fields in dbms database
@param aFieldIndex column index containing the binary values in dbms database
*/
void CDbDbmsDumper::LongBinaryL(TInt aFieldIndex)
{
TAutoClose<RDbColReadStream> rdStream;
rdStream.iObj.OpenL(iDbTable,aFieldIndex);
DumpStreamL(rdStream.iObj);
}
/**
Utility method. Used to read from read stream and output to html file
*/
void CDbDbmsDumper::DumpStreamL(RReadStream& stream)
{
const TInt KStreamSize = stream.Source()->SizeL();
iFile.Write(KDumpFont);
_LIT8(KSizeMessage, "size is %d <BR>");
_LIT8(KEightSpaces, " ");
_LIT8(KByteFormat, "%02x ");
_LIT8(KFormatString, "%S <BR>\r\n");
iBuffer->Des().Format(KSizeMessage, KStreamSize);
iFile.Write(*iBuffer);
TBuf8<8> str(KEightSpaces); //Reserve 8 symbols
TInt counter(0);
while (counter < KStreamSize)
{
for(TInt i=0; i < 8; ++i)
{
if (counter >= KStreamSize)
{
break;
}
//format byte in a printable character
TInt8 byte( stream.ReadInt8L() );
iBuffer->Des().Format(KByteFormat, byte);
iFile.Write(*iBuffer);
str[i] = (byte>32 ? byte : '.');
++counter;
}
iBuffer->Des().Format(KFormatString, &str);
iFile.Write(*iBuffer);
}
iFile.Write(KDumpFontEnd);
}
/**
Dump the content of a dbms database in a html file
*/
void CDbDbmsDumper::OutputDBContentsL()
{
// Output Title
_LIT8(KHdr,"<H2>Contacts Model DB Dump:</H2>");
iFile.Write(KHdr);
// Preferences Table Name that will appear first in the output file
_LIT(KPrefTableName,"PREFERENCES");
TInt counter = 0;
const TInt KNumTables( (iTableNames->Count() ));
TBool outputPrefTable( (EFalse) );
// if a Table named Preferences Exists in the DB output it first
while (!outputPrefTable && counter < KNumTables)
{
if ((*iTableNames)[counter++].Compare(KPrefTableName) == 0)
{
OutputTableToFileL(--counter);
outputPrefTable = ETrue;
}
}
// for each table - output all tables except the Preferences Table
for (counter = 0; counter < KNumTables; ++counter)
{
if ((*iTableNames)[counter].Compare(KPrefTableName) != 0)
{
OutputTableToFileL(counter);
}
}
}
void RunDumpL()
{
// Location of Output Directory. (File will be called DbDump.html). Final "\" required on path.
_LIT(KOutputDir, "?:\\");
TBuf<sizeof(KOutputDir)> outputDir(KOutputDir);
outputDir[0] = (TUint8) RFs::GetSystemDriveChar();
// Location of Contacts DB
_LIT(KDBName, "?:Contacts.cdb");
TBuf<sizeof(KDBName)> fileDBName(KDBName);
fileDBName[0] = (TUint8) RFs::GetSystemDriveChar();
// dump dbms database
CDbDbmsDumper* dbmsDumper = CDbDbmsDumper::NewLC(fileDBName, outputDir);
dbmsDumper->OutputDBContentsL();
CleanupStack::PopAndDestroy(dbmsDumper);
}
GLDEF_C TInt E32Main()
{
__UHEAP_MARK;
CActiveScheduler* scheduler = new CActiveScheduler;
if (scheduler)
{
CActiveScheduler::Install(scheduler);
CTrapCleanup* cleanup = CTrapCleanup::New();
if (cleanup)
{
TRAPD(err,RunDumpL() );
__ASSERT_ALWAYS(err == KErrNone, User::Panic(KErrorMessage,err) );
delete cleanup;
}
delete scheduler;
}
__UHEAP_MARKEND;
return KErrNone;
}