commands/swi/swi.cpp
author Tom Sutcliffe <thomas.sutcliffe@accenture.com>
Thu, 09 Sep 2010 15:47:34 +0100
changeset 57 683f4b1f08ce
parent 6 96d581d2147d
permissions -rw-r--r--
merge

// 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)
	{
	SetExtension(this);
	}

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(TInt aError)
	{
	Complete(aError);
	}

#define CASE_RETURN_LIT(XXX, YYY) case XXX: { _LIT(_KLit, #YYY); return &_KLit; }
const TDesC* CCmdSwi::StringifyError(TInt aError) const
	{
	switch (aError)
		{
		CASE_RETURN_LIT(-10100, KErrSISFieldIdMissing);
		CASE_RETURN_LIT(-10101, KErrSISFieldLengthMissing);
		CASE_RETURN_LIT(-10102, KErrSISFieldLengthInvalid);
		CASE_RETURN_LIT(-10103, KErrSISStringInvalidLength);
		CASE_RETURN_LIT(-10104, KErrSISSignedControllerSISControllerMissing);
		CASE_RETURN_LIT(-10105, KErrSISControllerSISInfoMissing);
		CASE_RETURN_LIT(-10106, KErrSISInfoSISUidMissing);
		CASE_RETURN_LIT(-10107, KErrSISInfoSISNamesMissing);
		CASE_RETURN_LIT(-10108, KErrSISFieldBufferTooShort);
		CASE_RETURN_LIT(-10109, KErrSISStringArrayInvalidElement);
		CASE_RETURN_LIT(-10110, KErrSISInfoSISVendorNamesMissing);
		CASE_RETURN_LIT(-10111, KErrSISInfoSISVersionMissing);
		CASE_RETURN_LIT(-10112, KErrSISControllerSISSupportedLanguagesMissing);
		CASE_RETURN_LIT(-10113, KErrSISSupportedLanguagesInvalidElement);
		CASE_RETURN_LIT(-10114, KErrSISLanguageInvalidLength);
		CASE_RETURN_LIT(-10115, KErrSISContentsSISSignedControllerMissing);
		CASE_RETURN_LIT(-10116, KErrSISContentsSISDataMissing);
		CASE_RETURN_LIT(-10117, KErrSISDataSISFileDataUnitMissing);
		CASE_RETURN_LIT(-10118, KErrSISFileDataUnitTargetMissing);
		CASE_RETURN_LIT(-10119, KErrSISFileOptionsMissing);
		CASE_RETURN_LIT(-10120, KErrSISFileDataUnitDescriptorMissing);
		CASE_RETURN_LIT(-10121, KErrSISFileDataDescriptionMissing);
		CASE_RETURN_LIT(-10122, KErrSISContentsMissing);
		CASE_RETURN_LIT(-10123, KErrSISEmbeddedControllersMissing);
		CASE_RETURN_LIT(-10124, KErrSISEmbeddedDataUnitsMissing);
		CASE_RETURN_LIT(-10125, KErrSISControllerOptionsMissing);
		CASE_RETURN_LIT(-10126, KErrSISExpressionMissing);
		CASE_RETURN_LIT(-10127, KErrSISExpressionStringValueMissing);
		CASE_RETURN_LIT(-10128, KErrSISOptionsStringMissing);
		CASE_RETURN_LIT(-10129, KErrSISFileOptionsExpressionMissing);
		CASE_RETURN_LIT(-10130, KErrSISExpressionHeadValueMissing);
		CASE_RETURN_LIT(-10131, KErrSISEmbeddedSISOptionsMissing);
		CASE_RETURN_LIT(-10132, KErrSISInfoSISUpgradeRangeMissing);
		CASE_RETURN_LIT(-10133, KErrSISDependencyMissingUid);
		CASE_RETURN_LIT(-10134, KErrSISDependencyMissingVersion);
		CASE_RETURN_LIT(-10135, KErrSISDependencyMissingNames);
		CASE_RETURN_LIT(-10136, KErrSISPrerequisitesMissingDependency);
		CASE_RETURN_LIT(-10137, KErrSISControllerMissingPrerequisites);
		CASE_RETURN_LIT(-10138, KErrSISUpgradeRangeMissingVersion);
		CASE_RETURN_LIT(-10139, KErrSISUnexpectedFieldType);
		CASE_RETURN_LIT(-10140, KErrSISExpressionUnknownOperator);
		CASE_RETURN_LIT(-10141, KErrSISArrayReadError);
		CASE_RETURN_LIT(-10142, KErrSISArrayTypeMismatch);
		CASE_RETURN_LIT(-10143, KErrSISInvalidStringLength);
		CASE_RETURN_LIT(-10144, KErrSISCompressionNotSupported);
		CASE_RETURN_LIT(-10145, KErrSISTooDeeplyEmbedded);
		CASE_RETURN_LIT(-10146, KErrSISInvalidTargetFile);
		CASE_RETURN_LIT(-10147, KErrSISWouldOverWrite);
		CASE_RETURN_LIT(-10148, KErrSISInfoMissingRemoveDirectories);
		CASE_RETURN_LIT(-10149, KErrSISNotEnoughSpaceToInstall);
		CASE_RETURN_LIT(-10200, KErrInstallerLeave);
		CASE_RETURN_LIT(-10250, KErrPolicyFileCorrupt);
		CASE_RETURN_LIT(-10251, KErrSignatureSchemeNotSupported);
		CASE_RETURN_LIT(-10252, KErrDigestNotSupported);
		CASE_RETURN_LIT(-10253, KErrBadHash);
		CASE_RETURN_LIT(-10254, KErrSecurityError);
		CASE_RETURN_LIT(-10263, KErrBadUsage);
		CASE_RETURN_LIT(-10260, KErrInvalidType); 
		CASE_RETURN_LIT(-10261, KErrInvalidExpression); 
		CASE_RETURN_LIT(-10262, KErrExpressionToComplex); 
		CASE_RETURN_LIT(-10255, KErrMissingBasePackage); 
		CASE_RETURN_LIT(-10256, KErrInvalidUpgrade); 
		CASE_RETURN_LIT(-10257, KErrInvalidEclipsing);
		CASE_RETURN_LIT(-10258, KErrWrongHeaderFormat);
		CASE_RETURN_LIT(-10259, KErrCapabilitiesMismatch); 
		CASE_RETURN_LIT(-10270, KErrLegacySisFile);
		CASE_RETURN_LIT(-10271, KErrInvalidSoftwareTypeRegistrationFile); 
		default:
			return NULL;
		}
	}

//
// 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