commands/swi/swi.cpp
changeset 0 7f656887cf89
child 6 96d581d2147d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/swi/swi.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,1250 @@
+// swi.cpp
+// 
+// Copyright (c) 2008 - 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "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:
+// Accenture - Initial contribution
+//
+
+#include "swi.h"
+#include <fshell/common.mmh>
+#include <fshell/ltkutils.h>
+
+typedef TBuf<1> TUserInput;
+_LIT(KSwiYes,	"y");
+_LIT(KSwiNo,	"n");
+_LIT(KSwiJarExtension,	"*.jar");
+_LIT(KSwiJadExtension,	"*.jad");
+#ifndef SYMBIAN_JAVA_NOT_INCLUDED
+_LIT8(KDefaultJadMimeType, "text/vnd.sun.j2me.app-descriptor");
+_LIT8(KDefaultJarMimeType, "application/java-archive");
+#endif
+_LIT(KDefaultMatch, "*");
+
+//
+// CCmdSwi
+// class to handle the fshell console user interaction
+//
+CCommandBase* CCmdSwi::NewLC()
+	{
+	CCmdSwi* self = new(ELeave) CCmdSwi();
+	CleanupStack::PushL(self);
+	self->BaseConstructL();
+	return self;
+	}
+
+CCmdSwi::~CCmdSwi()
+	{
+#ifndef SYMBIAN_JAVA_NOT_INCLUDED
+	delete iMidletHandler;
+#endif
+	delete iSisHandler;
+	delete iMatch;
+	}
+
+CCmdSwi::CCmdSwi():
+CCommandBase(CCommandBase::EManualComplete)
+	{
+	}
+
+const TDesC& CCmdSwi::Name() const
+	{
+	_LIT(KName, "swi");
+	return KName;
+	}
+
+void CCmdSwi::ArgumentsL(RCommandArgumentList& aArguments)
+	{
+	aArguments.AppendEnumL((TInt&)iCommand, _L("operation"));
+
+	_LIT(KArgFilename, "sis-file");
+	aArguments.AppendFileNameL(iSisFile, KArgFilename);
+	}
+	
+void CCmdSwi::OptionsL(RCommandOptionList& aOptions)
+	{
+	_LIT(KOptUid, "uid");
+	aOptions.AppendUintL((TUint&)iUid.iUid, KOptUid);
+
+	_LIT(KOptVerbose, "verbose");
+	aOptions.AppendBoolL(iVerbose, KOptVerbose);
+
+	_LIT(KOptQuiet, "quiet");
+	aOptions.AppendBoolL(iQuiet, KOptQuiet);
+
+	_LIT(KOptMatch, "match");
+	aOptions.AppendStringL(iMatch, KOptMatch);
+	}
+
+void CCmdSwi::DoRunL()
+	{
+	if (iMatch == NULL)
+		{
+		iMatch = KDefaultMatch().AllocL();
+		}
+
+	iSisHandler = CSwiSisInstallerAO::NewL(*this, FsL(), iVerbose, iQuiet);
+#ifndef SYMBIAN_JAVA_NOT_INCLUDED
+	iMidletHandler = CSwiMidletInstallerAO::NewL(*this, FsL(), iVerbose, iQuiet);
+#endif
+
+	switch (iCommand)
+		{
+	case EList:
+		//TODO matching
+		TRAPL(iSisHandler->ListInstalledAppsL(iUid, *iMatch), _L("Couldn't list installed SIS files"));
+#ifndef SYMBIAN_JAVA_NOT_INCLUDED
+		TRAPL(iMidletHandler->ListInstalledAppsL(iUid, *iMatch), _L("Couldn't list installed midlets"));
+#endif
+		Complete(KErrNone);
+		break;
+		
+	case EUninstall:
+		if (!iOptions.IsPresent(&iUid))
+			{
+			LeaveIfErr(KErrArgument, _L("UID must be specified for \"uninstall\""));
+			}
+		TRAPD(error, iSisHandler->UninstallL(iUid));
+		if (error != KErrNone)
+			{
+#ifndef SYMBIAN_JAVA_NOT_INCLUDED
+			// possibly a midlet
+			TRAP(error, iMidletHandler->UninstallL(iUid));
+#endif
+			}
+		LeaveIfErr(error, _L("Failed to uninstall package 0x%08x"), iUid.iUid);
+		break;
+		
+	case EInstall:
+		if (!iArguments.IsPresent(1))
+			{
+			LeaveIfErr(KErrArgument, _L("SIS file must be specified for \"install\""));
+			}
+		User::LeaveIfError(Stdin().SetReadMode(RIoReadHandle::ELine));
+#ifndef SYMBIAN_JAVA_NOT_INCLUDED
+		if (IsMidlet())
+			{
+			TRAPL(iMidletHandler->InstallL(iSisFile), _L("Failed to install midlet '%S'"), &iSisFile);
+			}
+		else
+#endif
+			{
+			TRAPL(iSisHandler->InstallL(iSisFile), _L("Failed to install sis '%S'"), &iSisFile);
+			}
+		break;
+		}
+
+	}
+	
+TBool CCmdSwi::IsMidlet()
+	{
+	if ((iSisFile.MatchF(KSwiJarExtension) != KErrNotFound) || (iSisFile.MatchF(KSwiJadExtension) != KErrNotFound))
+		return ETrue;
+	return EFalse;
+	}
+
+//
+// CCmdSwi::GetAnswer
+// only for use when not in quiet mode
+// Reads input from stdin, determines whether it's a 'yes' or 'no', returning ETrue, EFalse respectively
+//
+TBool CCmdSwi::GetAnswer()
+	{
+	ASSERT(!iQuiet);
+	TUserInput in;
+	for (;;)
+		{
+		if (Stdin().Read(in) != KErrNone)
+			{
+			return EFalse;
+			}
+		Stdout().Write(in);
+		if (in.MatchF(KSwiYes) == 0)
+			{
+			return ETrue;
+			}
+		if (in.MatchF(KSwiNo) == 0)
+			{
+			return EFalse;
+			}
+		// else it's an unrecognised response
+		}
+	}
+
+//
+// MCmdSwiParent hooks
+//
+RIoConsoleReadHandle& CCmdSwi::Input()
+	{
+	return Stdin();
+	}
+
+RIoConsoleWriteHandle& CCmdSwi::Output(TInt aError)
+	{
+	if (aError == KErrNone)
+		{
+		return Stdout();
+		}
+	return Stderr();
+	}
+
+//
+// CCmdSwi::Finished
+// callback from the underlying AO's RunL
+//
+void CCmdSwi::Finished(const TInt aError)
+	{
+	Complete(aError);
+	}
+
+//
+// Sis installer AO
+//
+CSwiSisInstallerAO* CSwiSisInstallerAO::NewL(MCmdSwiParent& aParent, RFs& aFs, TBool aVerbose, TBool aQuiet)
+	{
+	CSwiSisInstallerAO* self = new (ELeave) CSwiSisInstallerAO(aParent, aFs, aVerbose, aQuiet);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CSwiSisInstallerAO::CSwiSisInstallerAO(MCmdSwiParent& aParent, RFs& aFs, TBool aVerbose, TBool aQuiet)
+	: CActive(CActive::EPriorityStandard), iParent(aParent), iVerbose(aVerbose), iQuiet(aQuiet), iCurrentDrive('c')
+	{
+	TFileName sessionPath;
+	TInt err = aFs.SessionPath(sessionPath);
+	if (err == KErrNone)
+		{
+		iCurrentDrive = sessionPath[0];
+		iCurrentDrive.LowerCase();
+		}
+	CActiveScheduler::Add(this);
+	}
+
+CSwiSisInstallerAO::~CSwiSisInstallerAO()
+	{
+	Cancel();
+	delete iLauncher;
+	delete iRegPackage;
+	iRegistrySession.Close();
+	delete iPrefs;
+	}
+
+void CSwiSisInstallerAO::ConstructL()
+	{
+	iLauncher = CAsyncLauncher::NewL();
+	User::LeaveIfError(iRegistrySession.Connect());
+	iPrefs = Swi::CInstallPrefs::NewL();
+	iPrefs->SetPerformRevocationCheck(EFalse); // TODO - not currently supported in CCmdSwi
+	}
+
+void CSwiSisInstallerAO::RunL()
+	{
+	iParent.Finished(iStatus.Int());
+	}
+
+void CSwiSisInstallerAO::DoCancel()
+	{
+	iLauncher->CancelOperation();
+	iParent.Finished(KErrCancel);
+	}
+
+void CSwiSisInstallerAO::PrintDetails(Swi::CSisRegistryPackage& aPackage)
+	{
+	if (iVerbose)
+		{
+		TName myBuf;
+		myBuf.Format(_L("\r\nName:\t%S\r\n"), &aPackage.Name());
+		Stdout().Write(myBuf);
+		myBuf.Format(_L("Vendor:\t%S\r\n"), &aPackage.Vendor());
+		Stdout().Write(myBuf);
+		myBuf.Format(_L("Uid:\t0x%x\r\n"), aPackage.Uid());
+		Stdout().Write(myBuf);
+		}
+	else
+		{
+		TBuf<256> buf; buf.Format(_L("0x%08x: "), aPackage.Uid());
+		Stdout().Write(buf);
+		Stdout().Write(aPackage.Name());
+		Stdout().Write(_L("\r\n"));
+		}
+	}
+
+void CSwiSisInstallerAO::InstallL(TFileName& aInstallFile)
+	{
+	// install regular sis file
+	ASSERT(iPrefs);
+	ASSERT(iLauncher);
+	iLauncher->InstallL(*this, aInstallFile, *iPrefs, iStatus);
+	SetActive();
+	}
+
+void CSwiSisInstallerAO::UninstallL(const TUid& aPackageUid)
+	{
+	// remove regular sis file
+	ASSERT(iLauncher);
+	ASSERT(!iRegPackage);
+	Swi::CSisRegistryPackage* iRegPackage = GetSisRegistryPackageL(aPackageUid);
+	iLauncher->UninstallL(*this, *iRegPackage, iStatus);
+	SetActive();
+	}
+
+//
+// CSwiSisInstallerAO::ListInstalledAppsL
+// lists apps currently installed on the device
+//
+void CSwiSisInstallerAO::ListInstalledAppsL(const TUid& aAppUid, const TDesC& aMatchString)
+	{
+	if (aAppUid.iUid != 0)
+		{
+		DisplayPackageL(aAppUid);
+		}
+	else
+		{
+		ASSERT(iRegistrySession.Handle() > 0);
+		RPointerArray<CSisRegistryPackage> packages;
+		LtkUtils::CleanupResetAndDestroyPushL(packages);
+		iRegistrySession.InstalledPackagesL(packages);
+		if (packages.Count() <= 0)
+			{
+			User::Leave(KErrNotFound);
+			}
+		TInt count = 0;
+		const TInt endCount = packages.Count();
+		do
+			{
+			CSisRegistryPackage* current = packages[count++];
+			if ((current->Name().MatchF(aMatchString) >= 0) || (current->Vendor().MatchF(aMatchString) >= 0))
+				{
+				PrintDetails(*current);
+				}
+			} while (count < endCount);
+		CleanupStack::PopAndDestroy(&packages);
+		}
+	}
+
+//
+// CSwiSisInstallerAO::DisplayPackageL
+// find information on the specified package uid and display it on the console
+//
+void CSwiSisInstallerAO::DisplayPackageL(const TUid& aPackageUid)
+	{
+	ASSERT(iRegistrySession.Handle() > 0);
+	Swi::RSisRegistryEntry entry;
+	User::LeaveIfError(entry.Open(iRegistrySession, aPackageUid));
+	CleanupClosePushL(entry);
+	Swi::CSisRegistryPackage* registryPackage = entry.PackageL();
+	CleanupStack::PushL(registryPackage);
+	PrintDetails(*registryPackage);
+	CleanupStack::PopAndDestroy(2, &entry);	
+	}
+
+//
+// CSwiSisInstallerAO::GetSisRegistryPackageL
+// locate the sis registry package corresponding to the specified package ui
+//
+Swi::CSisRegistryPackage* CSwiSisInstallerAO::GetSisRegistryPackageL(const TUid& aPackageUid)
+	{
+	ASSERT(iRegistrySession.Handle() > 0);
+	if (!iRegistrySession.IsInstalledL(aPackageUid))
+		{
+		User::Leave(KErrNotFound); // invalid uid
+		}
+	// else iterate through the installed packages to find ours
+	RPointerArray<Swi::CSisRegistryPackage> packages;
+	iRegistrySession.InstalledPackagesL(packages);
+	if (packages.Count() <= 0)
+		{
+		User::Leave(KErrNotFound);
+		}
+	TInt count = 0;
+	const TInt endCount = packages.Count();
+	Swi::CSisRegistryPackage* found = NULL;
+	do
+		{
+		Swi::CSisRegistryPackage* current = packages[count];
+		 if (current->Uid() == aPackageUid)
+			{
+			found = current;
+			break;
+			}
+		count++;
+		} while (count < endCount);
+	ASSERT(found); // IsInstalledL stated it's in there
+	return found; 
+	}
+
+//
+// SWI UI Hooks
+//
+TBool CSwiSisInstallerAO::DisplayTextL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TFileTextOption /*aOption*/, const TDesC& aText)
+	{
+	TBool response = ETrue; // default, the user will continue with the installation/uninstallation
+	if (!iQuiet)
+		{
+		Stdout().Write(aText);
+		Stdout().Write(_L("Continue [y/n]?\r\n"));
+		response = iParent.GetAnswer();
+		}
+	return response;
+	}
+
+void CSwiSisInstallerAO::DisplayErrorL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TErrorDialog aType, const TDesC& /*aParam*/)
+	{
+	if (iVerbose)
+		{
+		switch (aType)
+			{
+			case Swi::EUiAlreadyInRom:
+				Stderr().Write(_L("\r\nCannot overwrite a ROM component.\r\n"));
+			break;
+			
+			case Swi::EUiMissingDependency:
+				Stderr().Write(_L("\r\nMissing a dependency.\r\n"));
+			break;
+			
+			case Swi::EUiRequireVer:
+				Stderr().Write(_L("\r\nA dependency exists on a specific version of an application which is different from the one installed.\r\n"));
+			break;
+
+			case Swi::EUiFileCorrupt:
+				Stderr().Write(_L("\r\nSISX file corrupt. Checksums stored in file do not match actual.\r\n"));
+			break;
+
+			case Swi::EUiDiskNotPresent:
+				Stderr().Write(_L("\r\nAll your bases are belong to us. <disk not present>\r\n"));
+			break;
+
+			case Swi::EUiCannotRead:
+				Stderr().Write(_L("\r\nCannot read a file which is needed in order to proceed.\r\n"));
+			break;
+
+			case Swi::EUiCannotDelete:
+				Stderr().Write(_L("\r\nCannot delete a file.\r\n"));
+			break;
+
+			case Swi::EUiInvalidFileName:
+				Stderr().Write(_L("\r\nA filename specified in the SISX package is not valid.\r\n"));
+			break;
+
+			case Swi::EUiInsufficientSpaceOnDrive:
+				Stderr().Write(_L("\r\nInsufficient space on the drive.\r\n"));
+			break;
+
+			case Swi::EUiCapabilitiesCannotBeGranted:
+				Stderr().Write(_L("\r\nApplication requires system capability it is not signed for.\r\n"));
+			break;
+
+			case Swi::EUiUnknownFile:
+				Stderr().Write(_L("\r\nNot a recognised SISX file.\r\n"));
+			break;
+
+			case Swi::EUiMissingBasePackage:
+				Stderr().Write(_L("\r\nA base package required for installation is not present.\r\n"));
+			break;
+
+			case Swi::EUiConstraintsExceeded:
+				Stderr().Write(_L("\r\nConstraints imposed by a developer mode certificate have been exceeded.\r\n"));
+			break;
+
+			case Swi::EUiSIDViolation:
+				Stderr().Write(_L("\r\nThe package contains a file with a protected SID which is not signed for.\r\n"));
+			break;
+
+			case Swi::EUiVIDViolation:
+				Stderr().Write(_L("\r\nThe package contains a file with a protected VID which is not signed for.\r\n"));
+			break;
+
+			case Swi::EUiSIDMismatch:
+				Stderr().Write(_L("\r\nMismatched SID.\r\n"));
+			break;
+
+			case Swi::EUiBlockingEclipsingFile:
+				Stderr().Write(_L("\r\nThe package contains an invalid eclipsing file which is already in the device other than ROM.\r\n"));
+			break;
+
+			default:
+				{
+				TBuf<64> buf;
+				buf.Format(_L("\r\nAn error %d has occured. Aborting.\r\n"), aType);
+				Stderr().Write(buf);
+				}
+			break;
+			};
+		}
+	}
+	
+TBool CSwiSisInstallerAO::DisplayDependencyBreakL(const Swi::CAppInfo& /*aAppInfo*/, const RPointerArray<TDesC>& /*aComponents*/)
+	{
+	TBool response = ETrue; // default response is to continue with uninstallation
+	if (iVerbose)
+		{
+		Stdout().Write(_L("\r\nComponent being uninstalled has dependencies which may no longer work. Continue uninstalling [y/n]?\r\n"));
+		response = iParent.GetAnswer();
+		}
+	return response;
+	}
+
+TBool CSwiSisInstallerAO::DisplayApplicationsInUseL(const Swi::CAppInfo& /*aAppInfo*/, const RPointerArray<TDesC>& /*aAppNames*/)
+	{
+	TBool response = EFalse; // EFalse indicates we don't continue with uninstallation
+	if (!iQuiet)
+		{
+		Stdout().Write(_L("\r\nApplication is currently open. Continue uninstalling? [y/n]\r\n"));
+		response = iParent.GetAnswer();
+		}
+	if (!response)
+		{
+		Stderr().Write(_L("Uninstall aborted. Application will not be closed.\r\n"));
+		}
+	return response;
+	}
+
+TBool CSwiSisInstallerAO::DisplayQuestionL(const Swi::CAppInfo& /* aAppInfo */, Swi::TQuestionDialog aQuestion, const TDesC& aDes)
+	{
+	TBool response = ETrue; // default behaviour assumes the user presses 'Yes' to any question
+	if (!iQuiet)
+		{
+		if (aQuestion == Swi::EQuestionIncompatible)
+			{
+			Stdout().Write(_L("\r\nApplication is not compatible with this device. Install anyway [y/n]?"));
+			}
+		else if (aQuestion == Swi::EQuestionOverwriteFile)
+			{
+			Stdout().Write(_L("\r\nSome system files will be overwritten by this installation. Install anyway [y/n]?"));
+			}
+		else
+			{
+			TBuf<128> buf; buf.Format(_L("Unrecognised question from engine %d\r\n"), aQuestion);
+			Stderr().Write(buf);
+			User::Leave(KErrNotSupported);
+			}
+
+		if (aDes.Length() > 0)
+			{
+			Stdout().Write(aDes);
+			}
+		Stdout().Write(_L("\r\n"));
+		response = iParent.GetAnswer();
+		}
+	return response;
+	}
+	
+TBool CSwiSisInstallerAO::DisplayInstallL(const Swi::CAppInfo& aAppInfo, const CApaMaskedBitmap* /*aLogo*/, const RPointerArray<Swi::CCertificateInfo>& /*aCertificates*/)
+	{
+	if (iVerbose)
+		{
+		TBuf<256> myBuf;
+		myBuf.Format(_L("NAME:\t\t%S\r\n"), &aAppInfo.AppName());
+		Stdout().Write(myBuf);
+		myBuf.Format(_L("VENDOR:\t\t%S\r\n"), &aAppInfo.AppVendor());
+		Stdout().Write(myBuf);
+		myBuf.Format(_L("VERSION:\t%d.%d.%d\r\n"), aAppInfo.AppVersion().iMajor, aAppInfo.AppVersion().iMinor, aAppInfo.AppVersion().iBuild);
+		Stdout().Write(myBuf);
+		}
+	TBool response = ETrue; // default behaviour is to continue the install
+	return response;
+	}
+	
+TBool CSwiSisInstallerAO::DisplayGrantCapabilitiesL(const Swi::CAppInfo& /*aAppInfo*/, const TCapabilitySet& /*aCapabilitySet*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the install
+	if (iVerbose)
+		{
+		// todo verbose mode
+		Stdout().Write(_L("\r\nTODO - CCmdSwi::DisplayGrantCapabilitiesL\r\n"));
+		}
+	return response;
+	}
+	
+TInt CSwiSisInstallerAO::DisplayLanguageL(const Swi::CAppInfo& /*aAppInfo*/, const RArray<TLanguage>& /*aLanguages*/)
+	{
+	if (iVerbose)
+		{
+		// todo verbose mode
+		Stdout().Write(_L("\r\nTODO - CCmdSwi::DisplayLanguageL\r\n"));
+		}
+	return 0; // the first language
+	}
+	
+TInt CSwiSisInstallerAO::DisplayDriveL(const Swi::CAppInfo& /*aAppInfo*/, TInt64 aSize, const RArray<TChar>& aDriveLetters, const RArray<TInt64>& aDriveSpaces)
+	{
+	TInt response = 0; // default to the first known drive
+	for (TInt i = 0; i < aDriveLetters.Count(); i++)
+		{
+		TChar letter = aDriveLetters[i];
+		letter.LowerCase();
+		if (letter == iCurrentDrive)
+			{
+			response = i; // Default to using the CWD drive, if it is in the list of available drives
+			break;
+			}
+		}
+
+	if (!iQuiet)
+		{
+		TBuf<128> info;
+		info.Format(_L("Application requires %d bytes free space. Please select installation drive:\r\n"), aSize);
+		Stdout().Write(info);
+		for (TInt ii = 0 ; ii < aDriveLetters.Count() ; ii++)
+			{
+			info.Format(_L("%d. \'"), ii);		// pseudo-drive number
+			info.Append(aDriveLetters[ii]);		// drive letter
+			info.Append(_L("\' "));
+			info.AppendNum(aDriveSpaces[ii]); // free space
+			info.Append(_L(" bytes free\r\n"));
+			Stdout().Write(info);
+			}
+		TUserInput in;
+		User::LeaveIfError(Stdin().Read(in));
+		TLex lex(in);
+		User::LeaveIfError(lex.Val(response));
+		}
+	return response;
+	}
+	
+TBool CSwiSisInstallerAO::DisplayUpgradeL(const Swi::CAppInfo& /*aAppInfo*/, const Swi::CAppInfo& /*aExistingAppInfo*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the install
+	if (!iQuiet)
+		{
+		Stdout().Write(_L("Do you wish to replace the existing installed application [y/n]?\r\n"));
+		response = iParent.GetAnswer();
+		}
+	return response;
+	}
+	
+TBool CSwiSisInstallerAO::DisplayOptionsL(const Swi::CAppInfo& /*aAppInfo*/, const RPointerArray<TDesC>& /*aOptions*/, RArray<TBool>& /*aSelections*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the install
+	if (iVerbose)
+		{
+		// todo verbose mode
+		Stdout().Write(_L("TODO - CCmdSwi::DisplayOptionsL\r\n"));
+		}
+	return response;
+	}
+	
+TBool CSwiSisInstallerAO::HandleInstallEventL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TInstallEvent aEvent, TInt /*aValue*/, const TDesC& /*aDes*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the install
+	if (iVerbose)
+		{
+		switch (aEvent)
+			{
+			case Swi::EEventUpdateProgressBar:
+				Stdout().Write(_L("."));
+			break;
+			
+			case Swi::EEventCompletedInstall:
+			case Swi::EEventCompletedUnInstall:
+				{
+				Stdout().Write(_L("\r\nComplete\r\n"));
+				}
+			break;
+
+			default:
+				// do nothing to inform the user of other cases
+			break;
+			};
+		}
+	return response;
+	}
+	
+void CSwiSisInstallerAO::HandleCancellableInstallEventL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TInstallCancellableEvent aEvent, Swi::MCancelHandler& /*aCancelHandler*/, TInt /*aValue*/, const TDesC& /*aDes*/)
+	{
+	if (iVerbose)
+		{
+		switch (aEvent)
+			{
+			case Swi::EEventRemovingFiles:
+				{
+				Stdout().Write(_L("\r\nRemoving files\r\n"));
+				}
+			break;
+			
+			case Swi::EEventShuttingDownApps:
+				{
+				Stdout().Write(_L("Closing App\r\n"));
+				}
+			break;
+
+			case Swi::EEventCopyingFiles:
+				{
+				Stdout().Write(_L("Copying files\r\n"));
+				}
+			break;
+
+			default:
+			break;
+			};
+		}
+	}
+
+TBool CSwiSisInstallerAO::DisplaySecurityWarningL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TSignatureValidationResult /*aSigValidationResult*/, RPointerArray<CPKIXValidationResultBase>& /*aPkixResults*/, RPointerArray<Swi::CCertificateInfo>& /*aCertificates*/, TBool /*aInstallAnyway*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the install
+	if (!iQuiet)
+		{
+		Stdout().Write(_L("\r\nApplication signature cannot be validated. Continue installing [y/n]?\r\n"));
+		response = iParent.GetAnswer();
+		}
+	return response;
+	}
+	
+TBool CSwiSisInstallerAO::DisplayOcspResultL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TRevocationDialogMessage /*aMessage*/, RPointerArray<TOCSPOutcome>& /*aOutcomes*/, RPointerArray<Swi::CCertificateInfo>& /*aCertificates*/, TBool /*aWarningOnly*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the install
+	if (iVerbose)
+		{
+		// todo verbose mode
+		Stdout().Write(_L("TODO - CCmdSwi::DisplayOcspResultL\r\n"));
+		}
+	return response;	
+	}
+	
+void CSwiSisInstallerAO::DisplayCannotOverwriteFileL(const Swi::CAppInfo& /*aAppInfo*/, const Swi::CAppInfo& /*aInstalledAppInfo*/, const TDesC& aFileName)
+	{
+	if (iVerbose)
+		{
+		Stdout().Write(_L("\r\nCannot overwrite a file required for installation. Aborting -"));
+		Stdout().Write(aFileName);
+		Stdout().Write(_L(" - \r\n"));
+		}
+	}
+	
+TBool CSwiSisInstallerAO::DisplayMissingDependencyL(const Swi::CAppInfo& /*aAppInfo*/, const TDesC& aDependencyName, TVersion /*aWantedVersionFrom*/, TVersion /*aWantedVersionTo*/, TVersion /*aInstalledVersion*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the install
+	if (!iQuiet)
+		{
+		Stdout().Write(_L("Warning: Depedency is missing or has incorrect version - "));
+		Stdout().Write(aDependencyName);
+		Stdout().Write(_L(" - \r\n"));
+		}
+	return response;	
+	}
+	
+TBool CSwiSisInstallerAO::DisplayUninstallL(const Swi::CAppInfo& aAppInfo)
+	{
+	if (iVerbose)
+		{
+		TName myBuf;
+		myBuf.Format(_L("NAME:\t\t%S\r\n"), &aAppInfo.AppName());
+		Stdout().Write(myBuf);
+		myBuf.Format(_L("VENDOR:\t\t%S\r\n"), &aAppInfo.AppVendor());
+		Stdout().Write(myBuf);
+		myBuf.Format(_L("VERSION:\t%d.%d.%d\r\n"), aAppInfo.AppVersion().iMajor, aAppInfo.AppVersion().iMinor, aAppInfo.AppVersion().iBuild);
+		Stdout().Write(myBuf);
+		}
+	TBool response = ETrue; // default behaviour is to continue the uninstall
+	return response;	
+	}
+
+#ifndef SYMBIAN_JAVA_NOT_INCLUDED
+//
+// java ui installer
+//
+CSwiMidletInstallerAO* CSwiMidletInstallerAO::NewL(MCmdSwiParent& aParent, RFs& aFs, TBool aVerbose, TBool aQuiet)
+	{
+	CSwiMidletInstallerAO* self = new (ELeave) CSwiMidletInstallerAO(aParent, aFs, aVerbose, aQuiet);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CSwiMidletInstallerAO::CSwiMidletInstallerAO(MCmdSwiParent& aParent, RFs& aFs, TBool aVerbose, TBool aQuiet)
+	: CActive(CActive::EPriorityStandard), iParent(aParent), iFs(aFs), iVerbose(aVerbose), iQuiet(aQuiet)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CSwiMidletInstallerAO::~CSwiMidletInstallerAO()
+	{
+	Cancel();
+	if (iInstaller)
+		delete iInstaller;
+	if (iJadHandle)
+		iJadHandle->CloseFileHandle();
+	if (iJarHandle)
+		iJarHandle->CloseFileHandle();
+	if (iInfo)
+		delete iInfo;
+	if (iRemover)
+		delete iRemover;
+	}
+
+void CSwiMidletInstallerAO::ConstructL()
+	{
+	iInstaller = CJavaInstaller::NewL(*this, *this, KNullDesC8, EFalse, 0);
+	}
+
+TBool CSwiMidletInstallerAO::IsJad(TDes& aMidlet)
+	{
+	if (aMidlet.MatchF(KSwiJadExtension) > 0)
+		return ETrue;
+	return EFalse;
+	}
+
+TBool CSwiMidletInstallerAO::IsJar(TDes& aMidlet)
+	{
+	if (aMidlet.MatchF(KSwiJarExtension) > 0)
+		return ETrue;
+	return EFalse;
+	}
+
+void CSwiMidletInstallerAO::ListInstalledAppsL(TUid aAppUid, const TDesC& aMatchString)
+	{
+	MJavaRegistry* reg = MJavaRegistry::CreateL();
+	RArray<TUid> list;
+	TInt count = 0;
+	CleanupStack::PushL(reg);
+	if ((aAppUid.iUid != 0) && (reg->SuiteEntryExistsL(aAppUid)))
+		{
+		MJavaRegistrySuiteEntry* suite = reg->SuiteEntryL(aAppUid);
+		CleanupStack::PushL(suite);
+		suite->MIDletUidsL(list);
+		while (count < list.Count())
+			{
+			MJavaRegistryMIDletEntry* entry = reg->MIDletEntryL(list[count++]);
+			CleanupStack::PushL(entry);
+			DisplayPackageL(*entry);
+			CleanupStack::Pop(entry);
+			entry->Release();
+			}
+		CleanupStack::Pop(suite);
+		suite->Release();
+		}
+	else
+		{
+		reg->InstalledMIDletUidsL(list);
+		while (count < list.Count())
+			{
+			MJavaRegistryMIDletEntry* entry = reg->MIDletEntryL(list[count++]);
+			CleanupStack::PushL(entry);
+			if ((entry->MIDletNameL().MatchF(aMatchString)>=0) || (entry->SuiteEntryL().VendorL().MatchF(aMatchString)>=0))
+				{
+				DisplayPackageL(*entry);
+				}
+			CleanupStack::Pop(entry);
+			entry->Release();
+			}
+		}
+	CleanupStack::Pop(reg);
+	}
+
+//
+// CSwiMidleInstallerAO::DisplayPackageL
+// find information on the specified package uid and display it on the console
+//
+void CSwiMidletInstallerAO::DisplayPackageL(MJavaRegistryMIDletEntry& aPackage)
+	{
+	TName myBuf;
+	myBuf.Format(_L("\r\nNAME:\t%S\r\n"), &aPackage.MIDletNameL());
+	Stdout().Write(myBuf);
+	myBuf.Format(_L("VENDOR:\t%S\r\n"), &aPackage.SuiteEntryL().VendorL());
+	Stdout().Write(myBuf);
+	myBuf.Format(_L("UID:\t0x%x\r\n"), aPackage.SuiteEntryL().UidL());
+	Stdout().Write(myBuf);
+	}
+
+//
+// CSwiMidletInstallerAO::InstallL
+// installs a jar/jad midp 1.0/2.0-compatible midlet
+//
+void CSwiMidletInstallerAO::InstallL(TFileName& aInstallFile)
+	{
+	ASSERT(iInstaller);
+	ASSERT(!iInfo);
+	ASSERT(!iJarHandle);
+	ASSERT(!iJadHandle);
+	if (aInstallFile.Length() <= 0)
+		{
+		User::Leave(KErrNotFound);
+		}
+	if (iVerbose)
+		{
+		Stdout().Write(_L("Installing Midlet...\r\n"));
+		}
+	const TInt length = aInstallFile.Length() - 3; // the java midlet filename minus the jad/jar extension name
+	TFileName sisterFile(aInstallFile.Left(length));
+	if (IsJad(aInstallFile))
+		{
+		iJadHandle = CJavaFileHandle::NewL(iFs, aInstallFile, KNullDesC, KDefaultJadMimeType());
+		// name the associated jar file
+		sisterFile.Append(_L("jar"));
+		iJarHandle = CJavaFileHandle::NewL(iFs, sisterFile, KNullDesC, KDefaultJarMimeType());
+		}
+	else
+		{
+		ASSERT(IsJar(aInstallFile));
+		iJarHandle = CJavaFileHandle::NewL(iFs, aInstallFile, KNullDesC, KDefaultJarMimeType());
+		// name the associated jad file
+		sisterFile.Append(_L("jad"));
+		iJadHandle = CJavaFileHandle::NewL(iFs, sisterFile, KNullDesC, KDefaultJadMimeType());
+		}
+	iInfo = CMIDPInstallationLaunchInfo::NewL(iFs, *iJadHandle, *iJarHandle);
+	iInstaller->Install(*iInfo, iStatus);
+	SetActive();
+	}
+
+//
+// CSwiMidletInstallerAO::Uninstall
+// uninstalls a jar/jad midp 1.0/2.0-compatible midlet
+//
+void CSwiMidletInstallerAO::UninstallL(const TUid& aPackageUid)
+	{
+	ASSERT(!iRemover);
+	if (iVerbose)
+		{
+		Stdout().Write(_L("Removing Midlet...\r\n"));
+		}
+	iRemover = CJavaRemover::NewL(aPackageUid, *this);
+	iRemover->Remove(iStatus);
+	SetActive();
+	}
+
+void CSwiMidletInstallerAO::RunL()
+	{
+	iParent.Finished(iStatus.Int());
+	}
+
+void CSwiMidletInstallerAO::DoCancel()
+	{
+	ASSERT(iInstaller);
+	ASSERT(iRemover);
+	iInstaller->Cancel();
+	iRemover->Cancel();
+	iParent.Finished(KErrCancel);
+	}
+
+//
+// java installer UI hooks
+//
+TBool CSwiMidletInstallerAO::StartInstallL(const CMIDletSuiteAttributes& aMIDlet)
+	{
+	if (iVerbose)
+		{
+		TName myBuf;
+		myBuf.Format(_L("\r\nNAME:\t\t%S\r\n"), &aMIDlet.MIDletName());
+		Stdout().Write(myBuf);
+		myBuf.Format(_L("VENDOR:\t\t%S\r\n"), &aMIDlet.MIDletVendor());
+		Stdout().Write(myBuf);
+		myBuf.Format(_L("VERSION:\t%d.%d.%d\r\n"), aMIDlet.MIDletVersion().iMajor, aMIDlet.MIDletVersion().iMinor, aMIDlet.MIDletVersion().iBuild);
+		Stdout().Write(myBuf);
+		}
+	TBool response = ETrue; // default behaviour is to continue the install
+	return response;
+	}
+
+TBool CSwiMidletInstallerAO::SelectDriveL(const CMIDletSuiteAttributes& /*aMIDlet*/, TInt aSpaceRequired, TChar& aDrive, TBool& aSufficientSpace)
+	{
+	aSufficientSpace = ETrue;
+	aDrive = 'c';
+	if (iQuiet)
+		{
+		// Default to CWD drive if writeable
+		TFileName sessionPath;
+		TInt err = iFs.SessionPath(sessionPath);
+		if (err == KErrNone)
+			{
+			TChar drive = sessionPath[0];
+			drive.LowerCase();
+			TVolumeInfo volInfo;
+			if (iFs.Volume(volInfo, ((TUint)drive)-'a') == KErrNone && volInfo.iFree >= aSpaceRequired && !(volInfo.iDrive.iDriveAtt & KDriveAttRom) && !(volInfo.iDrive.iMediaAtt & KMediaAttWriteProtected))
+				{
+				aDrive = drive;
+				}
+			}
+		}
+	else
+		{
+		// ask the question
+		TBuf<128> info;
+		info.Format(_L("Midlet requires %d bytes free space. Please select installation drive:\r\n"), aSpaceRequired);
+		Stdout().Write(info);
+
+		// cycle through drive list checking for existing drive
+		TDriveList drives;
+		TVolumeInfo volume;
+		TChar driveChar;
+		TBool displayed = EFalse;
+		User::LeaveIfError(iFs.DriveList(drives));
+		for (TInt ii = 0 ; ii < KMaxDrives ; ii++)
+			{
+			if (drives[ii])
+				{
+				// drive exists
+				if (KErrNone == iFs.Volume(volume, ii))
+					{
+					// drive is present
+					if (volume.iFree >= aSpaceRequired)
+						{
+						// drive has sufficient space
+						aSufficientSpace = ETrue;
+						if (!(volume.iDrive.iDriveAtt & KDriveAttRom) && 
+							!(volume.iDrive.iMediaAtt & KMediaAttWriteProtected))
+							{
+							// drive is not a rom drive and is not write protected
+							User::LeaveIfError(iFs.DriveToChar(ii, driveChar));
+							info.Format(_L("%d. \'"), ii);		// drive number
+							info.Append(driveChar);		// drive letter
+							info.Append(_L("\' "));
+							info.AppendNum(volume.iFree); // free space
+							info.Append(_L(" bytes free\r\n"));
+							Stdout().Write(info);
+							displayed = ETrue;
+							}
+						}
+					}
+				}
+			}
+		// get the answer
+		if (displayed)
+			{
+			TUserInput in;
+			User::LeaveIfError(Stdin().Read(in));
+			TLex lex(in);
+			TInt response;
+			User::LeaveIfError(lex.Val(response));
+			User::LeaveIfError(iFs.DriveToChar(response, aDrive));
+			}
+		else
+			{
+			Stdout().Write(_L("Error. No drives capable of supporting midlet install. Aborting\r\n"));
+			return EFalse;
+			}
+		}
+	return ETrue;
+	}
+
+TBool CSwiMidletInstallerAO::ReplaceExistingMIDletL(const CMIDletSuiteAttributes& /*aMIDlet*/, const TAppVersion& /*aOldVersion*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the install
+	if (!iQuiet)
+		{
+		Stdout().Write(_L("Do you wish to replace the existing midlet [y/n]?\r\n"));
+		response = iParent.GetAnswer();
+		}
+	return response;
+	}
+	
+TBool CSwiMidletInstallerAO::UpgradeRMSL(const CMIDletSuiteAttributes& /*aMIDlet*/, const TAppVersion& /*aOldVersion*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the install
+	if (!iQuiet)
+		{
+		Stdout().Write(_L("Do you wish to upgrade the existing midlet [y/n]?\r\n"));
+		response = iParent.GetAnswer();
+		}
+	return response;
+	}
+
+TBool CSwiMidletInstallerAO::MIDletUntrustedL(const CMIDletSuiteAttributes& /*aMIDlet*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the install
+	if (!iQuiet)
+		{
+		Stdout().Write(_L("\r\nMidlet is untrusted. Continue installing [y/n]?\r\n"));
+		response = iParent.GetAnswer();
+		}
+	return response;
+	}
+
+void CSwiMidletInstallerAO::CertificateHasNoRootL(const CMIDletSuiteAttributes& /*aMIDlet*/, const CPKIXCertChain& /*aCertChain*/, const CPKIXValidationResult& /*aValidationResult*/)
+	{
+	Stderr().Write(_L("\r\nCertificate attached to midlet has no identifiable root. Aborting installation.\r\n"));
+	}
+
+void CSwiMidletInstallerAO::BadSignatureL(const CMIDletSuiteAttributes& /*aMIDlet*/, const CPKIXCertChain& /*aCertChain*/, const CPKIXValidationResult& /*aValidationResult*/)
+	{
+	if (iVerbose)
+		{
+		Stdout().Write(_L("\r\nWarning: Midlet certificate chain is incomplete. Continuing installation\r\n"));
+		}
+	}
+
+TBool CSwiMidletInstallerAO::PerformRevocationCheckL(TBool& aDoCheck)
+	{
+	aDoCheck = EFalse;
+	return ETrue;
+	}
+
+void CSwiMidletInstallerAO::StartRevocationCheckL()
+	{
+	if (iVerbose)
+		{
+		Stdout().Write(_L("\r\nStarted: Revocation check\r\n"));
+		}
+	}
+
+void CSwiMidletInstallerAO::FinishedRevocationCheckL()
+	{
+	if (iVerbose)
+		{
+		Stdout().Write(_L("\r\nFinished: Revocation check\r\n"));
+		}
+	}
+
+void CSwiMidletInstallerAO::StartIconConversionL()
+	{
+	}
+
+void CSwiMidletInstallerAO::FinishedIconConversionL()
+	{
+	}
+
+TBool CSwiMidletInstallerAO::OCSPWarningL(const CMIDletSuiteAttributes& /*aMIDlet*/, TRevocationMsg /*aRevocationMsg*/, const TOCSPOutcome* /*aOCSPOutcome*/)
+	{
+	if (iVerbose)
+		{
+		Stdout().Write(_L("\r\nWarning: OCSP failure. Continuing installation.\r\n"));
+		}
+	return ETrue;
+	}
+
+void CSwiMidletInstallerAO::OCSPErrorL(const CMIDletSuiteAttributes& /*aMIDlet*/, TRevocationMsg /*aRevocationMsg*/, const TOCSPOutcome* /*aOCSPOutcome*/)
+	{
+	Stderr().Write(_L("\r\nOCSP Error. Aborting installation.\r\n"));
+	}
+
+TBool CSwiMidletInstallerAO::MIDletInUseL(const CMIDletSuiteAttributes& /*aMIDlet*/)
+	{
+	TBool response = EFalse; // EFalse indicates we don't continue with uninstallation
+	if (!iQuiet)
+		{
+		// print the question
+		Stdout().Write(_L("\r\nMidlet is currently open. Continue installing? [y/n]\r\n"));
+		
+		// get the answer
+		TUserInput in;
+		const TInt error = Stdin().Read(in);
+		if ((error == KErrNone) && (in.MatchF(KSwiYes) == 0))
+			{
+			response = ETrue;
+			}
+		}
+	if (!response)
+		{
+		Stderr().Write(_L("Uninstall aborted. Midlet has not been closed.\r\n"));
+		}
+	return response;
+	}
+
+void CSwiMidletInstallerAO::OTAReportResponseL(TInt aOTAResponseCode, const TDesC& /*aReportBody*/)
+	{
+	if (iVerbose)
+		{
+		switch (aOTAResponseCode)
+			{
+			case CJavaMIDletInstallationResult::EOkay:
+				Stdout().Write(_L("\r\nComplete\r\n"));
+			break;
+			
+			default:
+				Stdout().Write(_L("Abort\r\n"));
+			break;
+			};
+		}
+	}
+
+TInt CSwiMidletInstallerAO::CopyStarted(TInt /*aSize*/)
+	{
+	return KErrNone;
+	}
+
+TInt CSwiMidletInstallerAO::DownloadStarted(TInt /*aSize*/)
+	{
+	if (iVerbose)
+		{
+		Stdout().Write(_L("Downloading midlet\r\n"));
+		}
+	return KErrNone;
+	}
+
+TInt CSwiMidletInstallerAO::UpdateProgress(TInt /*aSize*/)
+	{
+	if (iVerbose)
+		{
+		Stdout().Write(_L("."));
+		}
+	return KErrNone;
+	}
+
+TBool CSwiMidletInstallerAO::GetUsernamePasswordL(HBufC8*& /*aUsername*/, HBufC8*& /*aPassword*/)
+	{
+	if (iVerbose)
+		{
+		Stdout().Write(_L("\r\nTODO: CCmdSwi::GetUsernamePasswordL\r\n"));
+		}
+	return EFalse;
+	}
+
+TBool CSwiMidletInstallerAO::ConfirmRemovalL(const TDesC& /*aRemovalMessage*/)
+	{
+	TBool response = ETrue; // default behaviour is to continue the uninstall
+	return response;	
+	}
+
+void CSwiMidletInstallerAO::InitialiseProgressBarL(TInt /*aMaximumLength*/)
+	{
+	}
+
+void CSwiMidletInstallerAO::UpdateProgressBarL(TInt /*aUnits*/)
+	{
+	if (iVerbose)
+		{
+		Stdout().Write(_L("."));
+		}
+	}
+
+TBool CSwiMidletInstallerAO::MIDletInUseL()
+	{
+	TBool response = EFalse; // EFalse indicates we don't continue with uninstallation
+	if (!iQuiet)
+		{
+		// print the question
+		Stdout().Write(_L("\r\nApplication is currently open. Continue uninstalling? [y/n]\r\n"));
+		
+		// get the answer
+		TUserInput in;
+		const TInt error = Stdin().Read(in);
+		if ((error == KErrNone) && (in.MatchF(KSwiYes) == 0))
+			{
+			response = ETrue;
+			}
+		}
+	return response;
+	}
+
+TBool CSwiMidletInstallerAO::FileInUseL(const TDesC& /*aFileName*/)
+	{
+	TBool response = EFalse; // EFalse indicates we don't continue with uninstallation
+	if (!iQuiet)
+		{
+		// print the question
+		Stdout().Write(_L("\r\nApplication has a file handle open. Continue uninstalling? [y/n]\r\n"));
+		
+		// get the answer
+		TUserInput in;
+		const TInt error = Stdin().Read(in);
+		if ((error == KErrNone) && (in.MatchF(KSwiYes) == 0))
+			{
+			response = ETrue;
+			}
+		}
+	return response;
+	}
+
+#endif //  SYMBIAN_JAVA_NOT_INCLUDED
+
+#ifdef EXE_BUILD
+EXE_BOILER_PLATE(CCmdSwi)
+#endif
+