--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javatools/javarestoreconverter/src.s60/restoreconvertmidlet.cpp Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,1310 @@
+/*
+* Copyright (c) 2009 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: Java platform 2.0 javarestoreconverter process
+*
+*/
+
+
+#include <apacmdln.h>
+#include <apgcli.h>
+#include <driveinfo.h>
+#include <e32base.h>
+#include <pathinfo.h>
+#include <utf.h>
+#include <zipfile.h>
+
+#include "restoreconvertmidlet.h"
+
+#include "javacommonutils.h"
+#include "javaprocessconstants.h"
+#include "javastorage.h"
+#include "javastorageentry.h"
+#include "javastoragenames.h"
+#include "javasymbianoslayer.h"
+#include "javauids.h"
+#include "logger.h"
+
+
+using namespace java::storage;
+using namespace java::util;
+
+// MIDlet name and vendor max size is 255,
+// +1 added for terminating zero needed for logging
+const TInt KMaxBufferSize = 256;
+
+// character constants needed when parsing java attributes
+const TUint32 HT = 9; // horizontal tab
+const TUint32 LF = 10; // line feed
+const TUint32 CR = 13; // carriage return
+const TUint32 SP = 32; // space
+const TUint32 COLON = 58; // ':'
+
+
+_LIT(KJarFileNameSuffix, ".jar");
+_LIT(KJadFileNameSuffix, ".jad");
+_LIT(KFLJarFileNameSuffix, ".dm");
+_LIT(KSDJarFileNameSuffix, ".dcf");
+_LIT(KSMCBackSplash, "\\");
+_LIT(KDriveText, "drive");
+_LIT(KMidletName, "MIDlet-Name");
+_LIT(KMidletVendor, "MIDlet-Vendor");
+_LIT(KManifestEntryName, "META-INF/MANIFEST.MF");
+
+// The directory where the java applications to be converted are searched from
+_LIT(KMidletSuiteInstallBasePath, ":\\Private\\102033E6\\MIDlets\\");
+
+
+/**
+ * To create new instance of this class.
+ *
+ * @param aFs - A reference to the file server.
+ * @return Reference to the object of this class.
+ * @exception If construction fails.
+ *
+ */
+CRestoreConvertMIDlet* CRestoreConvertMIDlet::NewLC(RFs& aFs)
+{
+ CRestoreConvertMIDlet* self = new(ELeave) CRestoreConvertMIDlet(aFs);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+}
+
+/**
+ * To do 1st phase construction for this object.
+ *
+ * Adds this active object to the scheduler.
+ *
+ * @param aFs - A reference to the file server.
+ */
+CRestoreConvertMIDlet::CRestoreConvertMIDlet(RFs& aFs) :
+ CActive(EPriorityStandard), iFs(aFs), iNumberOfAppsToInstall(0)
+{
+ CActiveScheduler::Add(this);
+}
+
+/**
+ * To do 2nd phase construction for this object.
+ *
+ * @exception If the method is not able to allocate necessary buffers.
+ */
+void CRestoreConvertMIDlet::ConstructL()
+{
+ iConvertServer = new(ELeave) RestoreServer();
+ iMIDletName = HBufC::NewL(KMaxBufferSize);
+ iMIDletVendor = HBufC::NewL(KMaxBufferSize);
+}
+
+/**
+ * Deletes this object.
+ * All allocated resources are released.
+ */
+CRestoreConvertMIDlet::~CRestoreConvertMIDlet()
+{
+ Cancel();
+ iInstallFiles.ResetAndDestroy();
+ iInstallFiles.Close();
+
+ iUninstallUids.clear();
+
+ iDirs.ResetAndDestroy();
+ iDirs.Close();
+
+ iIsJad.Reset();
+
+ delete iMIDletName;
+ iMIDletName = NULL;
+
+ delete iMIDletVendor;
+ iMIDletVendor = NULL;
+
+ delete iConvertServer;
+ iConvertServer = NULL;
+}
+
+/**
+ * To start silent installation.
+ */
+void CRestoreConvertMIDlet::Start()
+{
+ iState = EFindOutDeviceDrives;
+ CompleteRequest();
+}
+
+/**
+ * To stop whole preinstaller.
+ * Stops the active scheduler.
+ */
+void CRestoreConvertMIDlet::Exit()
+{
+ Deque();
+ CActiveScheduler::Stop();
+}
+
+/**
+ * To complete the request for this object.
+ *
+ * @Postconditions The following conditions are true immediately after
+ * returning from this method.
+ * - iStatus == KErrNone
+ * - IsActive() == ETrue
+ */
+void CRestoreConvertMIDlet::CompleteRequest()
+{
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ if (!IsActive())
+ {
+ SetActive();
+ }
+}
+
+/**
+ * To run this active object.
+ *
+ * The state logic is:
+ *
+ * EFindOutDeviceDrives:
+ * - find out all non-remote drives in the device
+ * - mark externally mountable drives (removable drives)
+ * - mark read only drives (ROM)
+ *
+ * EGetDriveToBeScanned:
+ * - the drive to be scanned has been given as command line argument,
+ * store it to iDrive
+ *
+ * EAppsInInstalledDirectories:
+ * - go through all directories in iDirs one by one
+ * and find all java applications in the subdirectories of the directory
+ * - if only .jar/.dcf/.dm file is found it is added to iInstallFiles
+ * - if .jad file is found, it is added to iInstallFiles
+ *
+ * EUninstallFromOMJ:
+ * - uninstall all OMJ java applications in drive iDrive using Java Installer
+ * command line options 'uninstallall -drive=<iDrive>'
+ * - then for each java application in iInstallFiles try to find it from
+ * Java Storage based on MIDlet suite name and vendor name. If the MIDlet
+ * is still installed to OMJ (to some other drive than iDrive), it must
+ * be uninstalled from OMJ to reset the state of MIDlet (RMS data etc)
+ * to original state. The actual uninstallation is not done in this
+ * state, the uids of the applications to be uninstalled are just added to
+ * iUninstallUids in string format
+ *
+ * EExecuteRestoreServer:
+ * - give list of uninstall uids and list of install files to restore server
+ * - start restore server in another thread (it will listen to Comms messages)
+ * - start Java Installer in poll mode
+ * - when Java Installer polls for operations to be executed, the restore server
+ * will first ask it to uninstall each Java application in the list of uninstall uids,
+ * then restore server will ask Java Installer to install each .jad or .jar/.dcf/.dm file
+ * in the list of install files.
+ * Restore server will log whether each uninstallation / installation succeeds.
+ * - after all uninstallations and installations have been done, restore server will ask
+ * Java Installer to exit.
+ * - after that this active object moves to next state.
+ *
+ * EExit: free resources and exit
+ *
+ */
+void CRestoreConvertMIDlet::RunL()
+{
+ switch (iState)
+ {
+ case EFindOutDeviceDrives:
+ {
+ LOG(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::RunL EFindOutDeviceDrives");
+ GetAllDeviceDrivesL();
+ iState = EGetDriveToBeScanned;
+ CompleteRequest();
+ }
+ break;
+
+ case EGetDriveToBeScanned:
+ {
+ LOG(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::RunL EGetDriveToBeScanned");
+
+ HBufC *pBufCmdLine = HBufC::NewLC(User::CommandLineLength() + 10);
+ TPtr args = pBufCmdLine->Des();
+ User::CommandLine(args);
+ LOG1WSTR(EJavaConverters, EInfo,
+ "Command line arguments of javarestoreconverter.exe are : %s",
+ (wchar_t *)(args.PtrZ()));
+
+ // Check which drive is to be restored now from command line.
+ TDriveNumber drive = EDriveC;
+ TInt idx = args.Find(KDriveText());
+ if (KErrNotFound == idx)
+ {
+ LOG1WSTR(EJavaConverters, EError,
+ "no -drive<X> argument in javarestoreconveter.exe command line (%s)",
+ (wchar_t *)(args.PtrZ()));
+ User::Leave(KErrNotFound);
+ }
+
+ TChar driveChar = args[idx + KDriveText().Length()];
+ char argLetter = args[idx + KDriveText().Length()];
+ if (argLetter >= 'A' && argLetter <= 'J')
+ {
+ drive = (TDriveNumber)(argLetter - 'A');
+ }
+ else if (argLetter >= 'a' && argLetter <= 'j')
+ {
+ drive = (TDriveNumber)(argLetter - 'a');
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ CleanupStack::PopAndDestroy(pBufCmdLine);
+ iDrive = drive;
+
+ LOG1(EJavaConverters, EInfo, "Drive is %d", drive);
+
+ // forget old search directories
+ iDirs.ResetAndDestroy();
+
+ // The specified drive will be scanned for
+ // java applications to be converted
+ if (iDriveStatuses[drive] & DriveInfo::EDrivePresent)
+ {
+ (void)iFs.DriveToChar(drive, driveChar);
+
+ // The base Java application install directory in this
+ // drive must be scanned.
+ // Reserve memory also for drive letter and terminating zero
+ // for logging.
+ HBufC *baseInstallDir = HBufC::NewLC(KMidletSuiteInstallBasePath().Length() + 2);
+
+ TPtr dirPtr(baseInstallDir->Des());
+ dirPtr.Append(driveChar);
+ dirPtr.Append(KMidletSuiteInstallBasePath());
+
+ // Add new search directory
+ iDirs.AppendL(baseInstallDir);
+ CleanupStack::Pop(baseInstallDir);
+ }
+ else
+ {
+ // Restoring MIDlets to drive X but drive X is not present
+ ELOG1(EJavaConverters,
+ "javarestoreconverter.exe: Drive number %d is not present", drive);
+ User::Leave(KErrDisMounted);
+ }
+
+ iState = EAppsInInstalledDirectories;
+ CompleteRequest();
+ }
+ break;
+
+ case EAppsInInstalledDirectories:
+ {
+ LOG(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::RunL EAppsInInstalledDirectories");
+
+ GetInstallFilesL(iDirs);
+
+
+ iState = EUninstallFromOMJ;
+ CompleteRequest();
+ }
+ break;
+
+ case EUninstallFromOMJ:
+ {
+ LOG(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::RunL EUninstallFromOMJ");
+
+ // Uninstall all Java applications in current drive
+ UninstallAllFromDriveL(iDrive);
+
+ // Check all Jad / Jar files in iInstallFiles and
+ // add the Uids of those MIDlets still installed into OMJ
+ // to iUninstallUids
+ FindRemainingMIDletsToBeUninstalledL();
+
+ iState = EExecuteRestoreServer;
+ CompleteRequest();
+ }
+ break;
+
+ case EExecuteRestoreServer:
+ {
+ LOG(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::RunL EExecuteRestoreServer");
+
+ if (iNumberOfAppsToInstall > 0)
+ {
+ // Uninstall all MIDlet suites in iUninstallUids and then
+ // install all MIDlet suites in iInstallFiles.
+
+ // Tell RestoreServer what should be uninstalled and what
+ // should be converted
+ iConvertServer->setOperations(iInstallFiles, iUninstallUids);
+
+ // Start the server
+ int err = iConvertServer->start();
+ if (0 != err)
+ {
+ // server cannot be started
+ ELOG1(EJavaConverters,
+ "Cannot start convert server, err %d", err);
+ }
+
+ // Starts Java Installer, waits until Java Installer exits
+ RunJavaInstallerL();
+
+ iState = EExit;
+ }
+ else
+ {
+ iState = EExit;
+ CompleteRequest();
+ }
+ }
+ break;
+
+ case EExit:
+ {
+ LOG(EJavaConverters, EInfo, "CRestoreConvertMIDlet::RunL EExit");
+
+ // Stops the server if it is running
+ iConvertServer->stop();
+
+ FullCleanup();
+
+ // The whole javaappconverter process is stopped.
+ Exit();
+ }
+ break;
+ }
+}
+
+/**
+ * To handle leave from RunL.
+ * This method exits this active object using normal state machine
+ * After calling this method this active object will exit.
+ *
+ * @param aError - A reason of error.
+ * @return KErrNone.
+ */
+TInt CRestoreConvertMIDlet::RunError(TInt aError)
+{
+ ELOG2(EJavaConverters,
+ "CRestoreConvertMIDlet::RunError(%d) from state %d", aError, iState);
+
+ Cancel();
+
+ iState = EExit;
+ CompleteRequest();
+
+ return KErrNone;
+}
+
+/**
+ * To do cancelling for this object.
+ *
+ */
+void CRestoreConvertMIDlet::DoCancel()
+{
+ ELOG1(EJavaConverters,
+ "CRestoreConvertMIDlet::DoCancel from state %d", iState);
+
+ // Check whether restore server must be stopped
+ if (iState == EExecuteRestoreServer)
+ {
+ // Stops the server if it is running
+ iConvertServer->stop();
+ }
+}
+
+/**
+ * Add .jad files in the directories specified in aDirs to iInstallFiles.
+ * If a directory does not contain a .jad file but it contains a .jar/.dcf/.dm file,
+ * add that file to iInstallFiles
+ *
+ * @param aDirs - An array of directories to be scanned.
+ * @exception Unable to alloc memory for the internal buffers.
+ * @exception Unable to get directory's contents.
+ */
+void CRestoreConvertMIDlet::GetInstallFilesL(RPointerArray<HBufC>& aDirs)
+{
+ // Number of MIDlet installation base directories to scan,
+ // one directory per local drive
+ const TInt nBaseDirs = aDirs.Count();
+
+ for (TInt i = 0; i < nBaseDirs; i++)
+ {
+ TFileName suitePath;
+
+ // Form base directory path, MIDlets have been installed
+ // to subdirectories of this directory
+ const TPtrC& dir = ((HBufC *)(aDirs[i]))->Des();
+ TFileName baseSuitePath = dir;
+
+ CDir *entryList;
+ CDir *dirList;
+ TInt err = iFs.GetDir(baseSuitePath, KEntryAttMatchMask, ESortNone, entryList, dirList);
+ if (KErrNone != err)
+ {
+ WLOG1WSTR(EJavaConverters,
+ "CRestoreConvertMIDlet::GetInstallFilesL Cannot list directory %s",
+ (wchar_t *)(baseSuitePath.PtrZ()));
+
+ // If no S60 Java application has been installed to the drive,
+ // the directory does not exist but it is OK
+ if (KErrPathNotFound != err)
+ {
+ User::Leave(err);
+ }
+ continue;
+ }
+
+ // Only midlet installation directory entries are meaningfull,
+ // discard other possible entries
+ delete entryList;
+
+ TInt nCount = dirList->Count();
+ TEntry dirEntry;
+
+ for (TInt nInd = 0; nInd < nCount; nInd++)
+ {
+ dirEntry = (*dirList)[nInd];
+ // Just to make sure this really is subdirectory
+ if (dirEntry.IsDir())
+ {
+ // Is this midlet suite subdir?
+ // Midlet suite subdirs look like this "[102b567B]"
+ // Must parse the value of the Uid as unsigned int to avoid
+ // overflow
+ TUint32 nUid;
+ TLex lexer(dirEntry.iName);
+ lexer.Inc();
+ err = lexer.Val(nUid, EHex);
+ if (KErrNone != err)
+ {
+ // Not midlet suite subdir, skip it
+ continue;
+ }
+
+ // Does the subdirectory contain any Jar files?
+ suitePath = baseSuitePath;
+ suitePath.Append(dirEntry.iName);
+ suitePath.Append(KSMCBackSplash);
+
+ CDir *suiteDirEntryList;
+ err = iFs.GetDir(suitePath, KEntryAttMatchMask, ESortNone, suiteDirEntryList);
+ if (KErrNone != err)
+ {
+ LOG1WSTR(EJavaConverters, EError,
+ "CRestoreConvertMIDlet::GetInstallFilesL Cannot list content of suite dir %s",
+ (wchar_t *)(suitePath.PtrZ()));
+ User::Leave(err);
+ return;
+ }
+ // If there is .jad or Jar file in suiteDirEntryList, adds
+ // it to iInstallFiles.
+ // Recognizes also DRM protected Jar files (.dm, .dcf)
+ AddJadJarToInstallFilesL(suitePath, suiteDirEntryList);
+ delete suiteDirEntryList;
+ }
+ } // for - loop all directory entries in a base installation directories
+ delete dirList;
+
+ } // for - loop all base installation directories
+
+ if (iInstallFiles.Count() == 0)
+ {
+ WLOG(EJavaConverters,
+ "CRestoreConvertMIDlet::GetInstallFilesL No MIDlets to convert");
+ }
+
+ // how many applications to restore
+ iNumberOfAppsToInstall = iInstallFiles.Count();
+}
+
+/**
+ * For each java application in iInstallFiles try to find it from
+ * Java Storage based on MIDlet suite name and vendor name. If the MIDlet
+ * is still installed to OMJ (to some other drive than iDrive), it must
+ * be uninstalled from OMJ to reset the state of MIDlet (RMS data etc)
+ * to original state. Add the uids of the applications to be uninstalled
+ * to iUninstallUids in string format
+ */
+void CRestoreConvertMIDlet::FindRemainingMIDletsToBeUninstalledL()
+{
+ TBool namesParsed;
+ for (TInt nInd = 0; nInd < iNumberOfAppsToInstall; nInd++)
+ {
+ // Get the MIDlet-Name and MIDlet-Vendor from iInstallFiles[nInd]
+ if (iIsJad[nInd] == 1)
+ {
+ namesParsed = ParseJadL(*iInstallFiles[nInd]);
+ }
+ else
+ {
+ // If file is .jar file, get the names from Manifest
+ namesParsed = ParseJarL(*iInstallFiles[nInd]);
+ }
+
+ // Search for the MIDlet suite from Java Storage table APPLICATION_PACKAGE_TABLE
+ // If it is found, add the suite Uid in string format to iUninstallUids
+ if (namesParsed)
+ {
+ TPtr suite = iMIDletName->Des();
+ TPtr vendor = iMIDletVendor->Des();
+ std::wstring suiteUid = IsSuiteInstalled(suite, vendor);
+ if (!suiteUid.empty())
+ {
+ iUninstallUids.push_back(suiteUid);
+ }
+ }
+ }
+}
+
+/**
+ * Parse MIDlet-Name and MIDlet-Vendor parameters from JAD file.
+ * Parameters are stored to iMIDletName and iMIDletVendor
+ *
+ * @param ETrue if parsing succeeds otherwise EFalse.
+ */
+TBool CRestoreConvertMIDlet::ParseJadL(const TDesC& aJadFileName)
+{
+ HBufC *jadContent = NULL;
+ // Trap leave thrown if reading jad content fails
+ TRAPD(err, jadContent = GetJadContentL(aJadFileName));
+ if (KErrNone != err)
+ {
+ ELOG1(EJavaConverters,
+ "CRestoreConvertMIDlet::ParseJadL Reading Jad content failed, error %d",
+ err);
+ return EFalse;
+ }
+ CleanupStack::PushL(jadContent);
+
+ HBufC *midletName = ParseAttribute(jadContent, KMidletName);
+ if (NULL == midletName)
+ {
+ ELOG(EJavaConverters,
+ "CRestoreConvertMIDlet::ParseJadL Parsing midlet name failed.");
+ CleanupStack::PopAndDestroy(jadContent);
+ return EFalse;
+ }
+ // store midlet name to member variable and log it
+ TPtr namePtr(iMIDletName->Des());
+ namePtr.Copy(*midletName);
+ LOG1WSTR(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::ParseJadL MIDlet-Name %s",
+ (wchar_t *)(namePtr.PtrZ()));
+ delete midletName;
+
+ HBufC *midletVendor = ParseAttribute(jadContent, KMidletVendor);
+ if (NULL == midletVendor)
+ {
+ ELOG(EJavaConverters,
+ "CRestoreConvertMIDlet::ParseJadL Parsing midlet vendor failed.");
+ CleanupStack::PopAndDestroy(jadContent);
+ return EFalse;
+ }
+ // store midlet vendor to member variable and log it
+ TPtr vendorPtr(iMIDletVendor->Des());
+ vendorPtr.Copy(*midletVendor);
+ LOG1WSTR(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::ParseJadL MIDlet-Vendor %s",
+ (wchar_t *)(vendorPtr.PtrZ()));
+ delete midletVendor;
+
+ CleanupStack::PopAndDestroy(jadContent);
+ return ETrue;
+}
+
+
+/**
+ * Reads the whole content of the Jad file and returns it in
+ * buffer in Symbian Unicode character set.
+ * @param[in] aJadFile
+ * @return pointer to HBufC that contains the Jad file,
+ * ownership is transferred to caller
+ * @exception If jad file content cannot be read
+ */
+HBufC *CRestoreConvertMIDlet::GetJadContentL(const TDesC& aJadFileName)
+{
+ RFile jadFile;
+ TInt err = jadFile.Open(iFs, aJadFileName, EFileRead);
+ User::LeaveIfError(err);
+ CleanupClosePushL(jadFile);
+
+ // Reserve buffer for Jad in UTF-8 char set
+ TInt jadSize = 0;
+ err = jadFile.Size(jadSize);
+ User::LeaveIfError(err);
+ HBufC8 *bufUtf8Jad = HBufC8::NewL(jadSize);
+ CleanupStack::PushL(bufUtf8Jad);
+
+ // Read the content in Utf8 char set
+ TPtr8 tmpPtr(bufUtf8Jad->Des());
+ err = jadFile.Read(tmpPtr, jadSize);
+ User::LeaveIfError(err);
+
+ // Convert to Unicode
+ HBufC *bufUnicodeJad =
+ CnvUtfConverter::ConvertToUnicodeFromUtf8L(*bufUtf8Jad);
+
+ CleanupStack::PopAndDestroy(bufUtf8Jad);
+ CleanupStack::PopAndDestroy(&jadFile);
+
+ // Return to caller
+ return bufUnicodeJad;
+}
+
+
+/**
+ * Parse MIDlet-Name and MIDlet-Vendor parameters from Manifest inside
+ * a .jar file.
+ * Parameters are stored to iMIDletName and iMIDletVendor
+ *
+ * @param ETrue if parsing succeeds otherwise EFalse.
+ */
+TBool CRestoreConvertMIDlet::ParseJarL(const TDesC& aJarFileName)
+{
+ HBufC *manifestContent = NULL;
+ // Trap leave thrown if reading Manifest content fails
+ TRAPD(err, manifestContent = GetManifestContentL(aJarFileName));
+ if (KErrNone != err)
+ {
+ ELOG1(EJavaConverters,
+ "CRestoreConvertMIDlet::ParseJarL Reading Manifest failed, error %d",
+ err);
+ return EFalse;
+ }
+ CleanupStack::PushL(manifestContent);
+
+ HBufC *midletName = ParseAttribute(manifestContent, KMidletName);
+ if (NULL == midletName)
+ {
+ ELOG(EJavaConverters,
+ "CRestoreConvertMIDlet::ParseJarL Parsing midlet name failed.");
+ CleanupStack::PopAndDestroy(manifestContent);
+ return EFalse;
+ }
+ // store midlet name to member variable and log it
+ TPtr namePtr(iMIDletName->Des());
+ namePtr.Copy(*midletName);
+ LOG1WSTR(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::ParseJarL MIDlet-Name %s",
+ (wchar_t *)(namePtr.PtrZ()));
+ delete midletName;
+
+ HBufC *midletVendor = ParseAttribute(manifestContent, KMidletVendor);
+ if (NULL == midletVendor)
+ {
+ ELOG(EJavaConverters,
+ "CRestoreConvertMIDlet::ParseJarL Parsing midlet vendor failed.");
+ CleanupStack::PopAndDestroy(manifestContent);
+ return EFalse;
+ }
+ // store midlet vendor to member variable and log it
+ TPtr vendorPtr(iMIDletVendor->Des());
+ vendorPtr.Copy(*midletVendor);
+ LOG1WSTR(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::ParseJarL MIDlet-Vendor %s",
+ (wchar_t *)(vendorPtr.PtrZ()));
+ delete midletVendor;
+
+ CleanupStack::PopAndDestroy(manifestContent);
+ return ETrue;
+}
+
+
+/**
+ * Reads the whole content of the Manifest inside Jar file
+ * and returns it in buffer in Symbian Unicode character set.
+ * @param[in] aJarFile
+ * @return pointer to HBufC that contains the Manifest,
+ * ownership is transferred to caller
+ * @exception If Manifest content cannot be read
+ */
+HBufC *CRestoreConvertMIDlet::GetManifestContentL(const TDesC& aJarFileName)
+{
+ CZipFile* zipFile = CZipFile::NewL(iFs, aJarFileName);
+ CleanupStack::PushL(zipFile);
+
+ // Seek manifest file
+ CZipFileMember* zippedFile =
+ zipFile->CaseSensitiveOrCaseInsensitiveMemberL(KManifestEntryName());
+ if (!zippedFile)
+ {
+ ELOG(EJavaConverters,
+ "CRestoreConvertMIDlet::GetManifestContentL Package is missing manifest");
+ User::Leave(KErrNotFound);
+ }
+ CleanupStack::PushL(zippedFile);
+
+ TUint uncompressedSize = zippedFile->UncompressedSize();
+ if ((TUint)uncompressedSize >= (KMaxTInt/2))
+ {
+ ELOG(EJavaConverters, "CRestoreConvertMIDlet::GetManifestContentL Invalid manifest");
+ User::Leave(KErrCorrupt);
+ }
+
+ // Buffer to read Manifest into
+ HBufC8* resultData = HBufC8::NewLC(uncompressedSize);
+
+ RZipFileMemberReaderStream* zippedStream = 0;
+ TInt err = zipFile->GetInputStreamL(zippedFile, zippedStream);
+ User::LeaveIfError(err);
+ CleanupStack::PushL(zippedStream);
+
+ TPtr8 ptr(resultData->Des());
+ User::LeaveIfError(zippedStream->Read(ptr, uncompressedSize));
+
+ CleanupStack::PopAndDestroy(zippedStream);
+
+ // Manifest buffer when converted to UCS-2
+ HBufC *manifestContent = HBufC16::NewL(uncompressedSize);
+ TPtr16 ucsPtr(manifestContent->Des());
+ err = CnvUtfConverter::ConvertToUnicodeFromUtf8(ucsPtr, ptr);
+ if (KErrNone != err)
+ {
+ ELOG1(EJavaConverters,
+ "CRestoreConvertMIDlet::GetManifestContentL UTF-8 to unicode"
+ " conversion failed: %d", err);
+ User::Leave(err);
+ }
+ CleanupStack::PopAndDestroy(resultData);
+ CleanupStack::PopAndDestroy(zippedFile);
+ CleanupStack::PopAndDestroy(zipFile);
+
+ // Return to caller
+ return manifestContent;
+}
+
+
+std::wstring CRestoreConvertMIDlet::IsSuiteInstalled(TPtr& aSuiteName, TPtr& aVendorName)
+{
+ std::wstring suiteName(desToWstring(aSuiteName));
+ std::wstring vendorName(desToWstring(aVendorName));
+ std::wstring suiteUid;
+
+ // Find application uid based on names from Java Storage
+ JavaStorage *js = JavaStorage::createInstance();
+
+ try
+ {
+ js->open(JAVA_DATABASE_NAME);
+
+ JavaStorageEntry attribute;
+ JavaStorageApplicationEntry_t findPattern;
+ JavaStorageApplicationList_t foundEntries;
+
+ // Get ID from APPLICATION_PACKAGE_TABLE based on PACKAGE_NAME and VENDOR
+ attribute.setEntry(PACKAGE_NAME, suiteName);
+ findPattern.insert(attribute);
+ attribute.setEntry(VENDOR, vendorName);
+ findPattern.insert(attribute);
+ attribute.setEntry(ID, L"");
+ findPattern.insert(attribute);
+
+ js->search(APPLICATION_PACKAGE_TABLE , findPattern, foundEntries);
+
+ // Anything found?
+ if (foundEntries.size() > 0)
+ {
+ // The application package has been found, get the ID of the package
+ suiteUid = foundEntries.front().begin()->entryValue();
+ LOG1WSTR(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::IsSuiteInstalled: Found suite by name. Uid is %s",
+ suiteUid.c_str());
+ }
+ }
+ catch (JavaStorageException& e)
+ {
+ ELOG1(EJavaConverters,
+ "CRestoreConvertMIDlet::IsSuiteInstalled: Java Storage exception %s", e.what());
+ }
+
+ try
+ {
+ js->close();
+ }
+ catch (JavaStorageException& e2)
+ {
+ WLOG1(EJavaConverters,
+ "CRestoreConvertMIDlet::IsSuiteInstalled: Java Storage exception "
+ "when closing storage %s", e2.what());
+ }
+
+ delete js;
+
+ // suiteUid is empty if suite was not found
+ return suiteUid;
+}
+
+
+/**
+ * Finds the java attribute specified by aAttributeName
+ * from aBuf and returns the value of that attribute
+ * in HBufC.
+ * @param[in] aBuf contents of .jad / Manifest file
+ * @param[in] aAttributeName the name of a java attribute
+ * @return the value of the attribute. Caller gets the ownership of the
+ * returned HBufC.
+ * If the attribute is not found, returns NULL
+ */
+HBufC *CRestoreConvertMIDlet::ParseAttribute(const HBufC *aBuf, const TDesC& aAttributeName)
+{
+ TInt nInd(0);
+ TBool fullNameFound(EFalse);
+ TUint32 ch;
+
+ // Start parsing from the beginning
+ TPtrC parsePtr = aBuf->Mid(nInd);
+
+ do
+ {
+ // Find attribute name
+ nInd = parsePtr.Find(aAttributeName);
+ if (nInd < 0)
+ {
+ // Returns NULL if the attribute cannot be found
+ return NULL;
+ }
+
+ // Check that the attribute name was preceded by line break or
+ // it was at the beginning
+ if (nInd == 0)
+ {
+ fullNameFound = ETrue;
+ }
+ else
+ {
+ ch = parsePtr[nInd-1];
+ if ((ch == CR) || (ch == LF))
+ {
+ fullNameFound = ETrue;
+ }
+ else
+ {
+ // Name was just a part of longer string (not 'word match')
+ fullNameFound = EFalse;
+ // Skip to the last character of the found match.
+ // We can skip because we are insterested only in 'word' matches
+ // so the next cannot start inside the area we are skipping now.
+ parsePtr.Set(parsePtr.Mid(nInd + aAttributeName.Length() - 1));
+ continue;
+ }
+ }
+
+ // Check whether buffer ends after attribute name
+ if (nInd + aAttributeName.Length() >= parsePtr.Length())
+ {
+ // Buffer ends immediately after the found
+ // attribute name instance. No attribute value
+ return NULL;
+ }
+
+ // Check that there is a white space character or colon after
+ // attribute name
+ ch = parsePtr[nInd + aAttributeName.Length()];
+ if ((ch == COLON) || (ch == SP) || (ch == HT))
+ {
+ fullNameFound = ETrue;
+ }
+ else
+ {
+ // Name was just a part of longer string (not 'word match')
+ fullNameFound = EFalse;
+ // Skip to the next character after the found match
+ parsePtr.Set(parsePtr.Mid(nInd + aAttributeName.Length()));
+ continue;
+ }
+ }
+ while (!fullNameFound);
+
+ // Skip to the end of the attribute name and find ':' after the name.
+ // The skipped characters must be white space chacraters, otherwise
+ // the attribute name is illegal and Java Installer will not accept
+ // the Jad file / Manifest.
+ parsePtr.Set(parsePtr.Mid(nInd + aAttributeName.Length() - 1));
+ nInd = parsePtr.Locate(COLON);
+ if (nInd < 0)
+ {
+ return NULL;
+ }
+ nInd++;
+
+ // Parse attribute value (CR or LF ends)
+ TInt nEndInd = parsePtr.Locate(CR);
+ TInt nTmpInd = parsePtr.Locate(LF);
+
+ if (KErrNotFound == nEndInd)
+ {
+ nEndInd = parsePtr.Length() - 1;
+ }
+ if (KErrNotFound == nTmpInd)
+ {
+ nTmpInd = parsePtr.Length() - 1;
+ }
+
+ if (nTmpInd < nEndInd)
+ {
+ nEndInd = nTmpInd;
+ }
+
+ if (nEndInd < nInd)
+ {
+ return NULL;
+ }
+
+ TPtrC attributeValue = parsePtr.Mid(nInd, (nEndInd - nInd));
+
+ // Remove possible white space from the beginning and end of the value
+ HBufC *bufValue = attributeValue.Alloc();
+ if (NULL == bufValue)
+ {
+ return NULL;
+ }
+ TPtr value = bufValue->Des();
+ value.Trim();
+
+ return bufValue;
+} // parseAttribute
+
+
+/**
+ * Uninstall all Java 2.x MIDlets from drive given in aDrive
+ *
+ * @param aDrive uninstallation drive
+ */
+void CRestoreConvertMIDlet::UninstallAllFromDriveL(TDriveNumber &aDrive)
+{
+ // Execute Java Installer with uninstallall -drive=X command line options
+
+ LOG1(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::UninstallAllFromDriveL Going to uninstall "
+ "MIDlets from drive number %d", aDrive);
+
+ RProcess rJavaInstaller;
+ TBuf<256> commandLine;
+
+ // Build command line used to pass all necessary info to Java Installer
+ commandLine = _L("javainstallerstarter");
+ commandLine.Append(_L(" uninstallall -forceuninstall -captainmsgs=no"));
+
+ // Run installer silently, do not send uninstall notification messages
+ commandLine.Append(_L(" -silent -skipotastatus -drive="));
+
+ // Add drive letter
+ commandLine.Append((TChar)('A' + aDrive));
+
+ // start JavaInstaller
+#ifdef RD_JAVA_S60_RELEASE_5_0_IAD
+ TBuf<128> processName = _L("j9midps60");
+#else // RD_JAVA_S60_RELEASE_5_0_IAD
+ TBuf<128> processName = _L("javamidp");
+#endif // RD_JAVA_S60_RELEASE_5_0_IAD
+
+ TInt err = rJavaInstaller.Create(processName, commandLine);
+ if (KErrNone == err)
+ {
+ LOG(EJavaConverters, EInfo, "CRestoreConvertMIDlet::UninstallAllFromDriveL calling Rendezvous");
+ // This call will wait until Java Installer exits (or panics)
+ TRequestStatus status;
+ rJavaInstaller.Logon(status);
+
+ LOG(EJavaConverters, EInfo, "CRestoreConvertMIDlet::UninstallAllFromDriveL calling Resume");
+ rJavaInstaller.Resume();
+
+ // now wait until Java Installer exits
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone)
+ {
+ ELOG1(EJavaConverters,
+ "CRestoreConvertMIDlet::UninstallAllFromDriveL Installer exited with error %d",
+ status.Int());
+ }
+ }
+ else
+ {
+ ELOG1(EJavaConverters,
+ "CRestoreConvertMIDlet::UninstallAllFromDriveL Cannot start Installer, error %d", err);
+ }
+
+ LOG(EJavaConverters, EInfo, "CRestoreConvertMIDlet::UninstallAllFromDriveL calling RProcess::Close");
+ // free resources before returning
+ rJavaInstaller.Close();
+}
+
+
+/**
+ * Scan the content of one directory entry and add the name of
+ * .jad / .jar /.dcf/.dm file to iInstallFiles if
+ * the directory contains a valid, installed Java application.
+ * Recognizes also DRM protected jar files (.dm, .dcf)
+ *
+ * @param aSuitePathName - directory to be scanned.
+ * @param aSuiteDirEntryList - contents of the directory
+ * @exception Unable to alloc memory for the internal buffers.
+ */
+void CRestoreConvertMIDlet::AddJadJarToInstallFilesL(
+ const TFileName &aSuitePathName,
+ const CDir *aSuiteDirEntryList)
+{
+ if (NULL == aSuiteDirEntryList)
+ {
+ return;
+ }
+
+ TInt nCount = aSuiteDirEntryList->Count();
+ if (0 == nCount)
+ {
+ return;
+ }
+
+ TInt suffixPos;
+ TEntry dirEntry;
+ TBool jarFileInSuiteDir = EFalse;
+ TBool jadFileInSuiteDir = EFalse;
+ TFileName jadFullPathName;
+ TFileName jarFullPathName;
+
+ for (TInt nInd = 0; nInd < nCount; nInd++)
+ {
+ dirEntry = (*aSuiteDirEntryList)[nInd];
+ // Directory cannot be Jar file.
+ // Empty file cannot valid Jar file
+ if (dirEntry.IsDir() || (dirEntry.iSize == 0))
+ {
+ continue;
+ }
+ // get the suffix of the name
+ suffixPos = dirEntry.iName.LocateReverse('.');
+ if (suffixPos == KErrNotFound)
+ {
+ // File name does not contain '.' char
+ continue;
+ }
+ TPtrC suffix(dirEntry.iName.Mid(suffixPos));
+
+ // if the name ends with ".jar" the name is current candidate
+ // for the name to be added to iInstallFiles list
+ if (suffix.CompareF(KJarFileNameSuffix) == 0)
+ {
+ jarFullPathName = aSuitePathName;
+ jarFullPathName.Append(dirEntry.iName);
+ jarFileInSuiteDir = ETrue;
+ }
+ else if (suffix.CompareF(KJadFileNameSuffix) == 0)
+ {
+ // If .jad file is found, then it will be added
+ // to iInstallFiles list
+ jadFullPathName = aSuitePathName;
+ jadFullPathName.Append(dirEntry.iName);
+ jadFileInSuiteDir = ETrue;
+ }
+ else if (suffix.CompareF(KFLJarFileNameSuffix) == 0)
+ {
+ // forward locked and combined delivery DRM protected
+ // .jar files have suffix ".dm"
+ jarFullPathName = aSuitePathName;
+ jarFullPathName.Append(dirEntry.iName);
+ jarFileInSuiteDir = ETrue;
+ }
+ else if (suffix.CompareF(KSDJarFileNameSuffix) == 0)
+ {
+ // separate delivery DRM protected .jar files have suffix ".dcf"
+ jarFullPathName = aSuitePathName;
+ jarFullPathName.Append(dirEntry.iName);
+ jarFileInSuiteDir = ETrue;
+ }
+ }
+
+ // If directory contains a Jar file, then add something to iInstallFiles
+ if (jarFileInSuiteDir)
+ {
+ // If directory contains also .jad file, add .jad file name to iInstallFiles
+ if (jadFileInSuiteDir)
+ {
+ // Reserve one char for null terminator
+ HBufC* path = HBufC::NewLC(jadFullPathName.Length() + 1);
+ TPtr pathPtr(path->Des());
+ pathPtr.Append(jadFullPathName);
+
+ LOG1WSTR(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::AddJadJarToInstallFilesL Adding jad file %s",
+ (wchar_t *)(pathPtr.PtrZ()));
+ iInstallFiles.Append(path);
+ CleanupStack::Pop(path);
+ iIsJad.AppendL(1);
+ }
+ else
+ {
+ // Reserve one char for null terminator
+ HBufC* path = HBufC::NewLC(jarFullPathName.Length() + 1);
+ TPtr pathPtr(path->Des());
+ pathPtr.Append(jarFullPathName);
+
+ LOG1WSTR(EJavaConverters, EInfo,
+ "CRestoreConvertMIDlet::AddJadJarToInstallFilesL Adding jar file %s",
+ (wchar_t *)(pathPtr.PtrZ()));
+ iInstallFiles.Append(path);
+ CleanupStack::Pop(path);
+ iIsJad.AppendL(0);
+ }
+ }
+}
+
+/**
+ * Start Java Installer in poll mode and then wait until it exits.
+ */
+void CRestoreConvertMIDlet::RunJavaInstallerL()
+{
+ LOG(EJavaConverters, EInfo, "CRestoreConvertMIDlet::RunJavaInstaller");
+
+ RProcess rJavaInstaller;
+ TFileName fileName;
+ TInt err;
+ // Max one path name, user name and password and some options ->
+ // 1536 is enough
+ TBuf<1536> commandLine;
+
+ // Build command line used to pass all necessary info to Java Installer
+ std::auto_ptr<HBufC> installerStarterDll(
+ stringToDes(java::runtime::JAVA_INSTALLER_STARTER_DLL));
+ commandLine = installerStarterDll->Des();
+ commandLine.Append(_L(" poll -address=convert"));
+
+ // Run installer silently
+ commandLine.Append(_L(" -silent -skipotastatus -silentconversion"));
+
+ // Convert old S60 applications so that applications uids,
+ // private data and RMS data are all preserved
+ commandLine.Append(_L(" -convert=yes"));
+
+ // Upgrading MIDlets is allowed
+ commandLine.Append(_L(" -upgrade=yes"));
+
+ // No OCSP checks for converted MIDlets
+ commandLine.Append(_L(" -ocsp=no"));
+
+ // Allow upgrade even if version number has not increased
+ commandLine.Append(_L(" -overwrite=yes"));
+
+ // Downloading .jar is not allowed.
+ commandLine.Append(_L(" -download=no"));
+
+ // If upgrade install, automatically upgrade also the data
+ commandLine.Append(_L(" -upgrade_data=yes"));
+
+ // MIDlets must be restored to the original drive
+ if (iDrive > -1)
+ {
+ TChar targetDrive;
+ err = RFs::DriveToChar(iDrive, targetDrive);
+ if (KErrNone == err)
+ {
+ commandLine.Append(_L(" -drive="));
+ commandLine.Append(targetDrive);
+ }
+ }
+
+ // start JavaInstaller
+ std::auto_ptr<HBufC> installerProcess(
+ stringToDes(java::runtime::JAVA_PROCESS));
+ err = rJavaInstaller.Create(installerProcess->Des(), commandLine);
+ if (KErrNone == err)
+ {
+ LOG(EJavaConverters, EInfo, "CRestoreConvertMIDlet::RunJavaInstaller calling Rendezvous");
+ // This call will wait until Java Installer exits (or panics)
+ rJavaInstaller.Logon(iStatus);
+
+ LOG(EJavaConverters, EInfo, "CRestoreConvertMIDlet::RunJavaInstaller calling Resume");
+ rJavaInstaller.Resume();
+ }
+ else
+ {
+ ELOG1(EJavaConverters,
+ "CRestoreConvertMIDlet::RunJavaInstaller Cannot start Installer, error %d", err);
+ // CActive will trap the following leave, execution will go to RunError
+ User::Leave(err);
+ }
+
+ LOG(EJavaConverters, EInfo, "CRestoreConvertMIDlet::RunJavaInstaller calling RProcess::Close");
+ // free resources before returning
+ rJavaInstaller.Close();
+
+ // now wait until Java Installer exits
+ SetActive();
+}
+
+/**
+ * To cleanup member variables.
+ */
+void CRestoreConvertMIDlet::FullCleanup()
+{
+ iDirs.ResetAndDestroy();
+ iInstallFiles.ResetAndDestroy();
+ iUninstallUids.clear();
+ iIsJad.Reset();
+}
+
+
+/**
+ * Checks all local drives in the device and stores the DriveInfo API drive
+ * status information for each drive to iDriveStatuses
+ * @exception Cannot get drive list.
+ */
+void CRestoreConvertMIDlet::GetAllDeviceDrivesL()
+{
+ TDriveList driveList;
+ // get all drives
+ TInt err = iFs.DriveList(driveList);
+ if (KErrNone != err)
+ {
+ ELOG1(EJavaConverters,
+ "CRestoreConvertMIDlet::GetAllDeviceDrives cannot get drive list, err %d", err);
+ User::Leave(err);
+ }
+
+ // store status of the non-remote, non-substed drives
+ TUint status = 0;
+ for (TInt drive = 0; drive < KMaxDrives; drive++)
+ {
+ iDriveStatuses[drive] = 0;
+
+ if (driveList[drive] == 0)
+ {
+ // no such drive in this device
+ continue;
+ }
+
+ err = DriveInfo::GetDriveStatus(iFs, drive, status);
+ if (KErrNone != err)
+ {
+ ELOG2(EJavaConverters,
+ "CRestoreConvertMIDlet::GetAllDeviceDrivesL cannot get drive %d status, err %d",
+ drive, err);
+ User::Leave(err);
+ }
+ // D drive is temporary RAM drive, skip it
+ // Drives J to Y are substed or remote drives, skip them
+ if ((drive == EDriveD) || ((drive >= EDriveJ) && (drive <= EDriveY)))
+ {
+ continue;
+ }
+
+ iDriveStatuses[drive] = status;
+ }
+}