diff -r 000000000000 -r 7f656887cf89 libraries/iosrv/client/server_command.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libraries/iosrv/client/server_command.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,970 @@ +// server_command.cpp +// +// Copyright (c) 2009 - 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 +#include +#include "command_base.h" + +using namespace IoUtils; + + +// +// Constants. +// + +_LIT(KTab, "\t"); +_LIT(KSpace, " "); +_LIT(KNewLine, "\r\n"); +_LIT(KHelpCommandName, "help"); + + +// used for sorting RArray's +TInt PtrOrder(const TPtrC& aDennis, const TPtrC& aGnasher) + { + return aDennis.Compare(aGnasher); + } + + +// +// TServerCommandId. +// + +EXPORT_C TServerCommandId::TServerCommandId() + : iId(0) + { + } + +EXPORT_C TServerCommandId::TServerCommandId(TUint aValue) + : iId(aValue) + { + } + +EXPORT_C TUint TServerCommandId::Value() const + { + return iId; + } + +EXPORT_C void TServerCommandId::Set(const TServerCommandId& aId) + { + iId = aId.iId; + } + +EXPORT_C TBool TServerCommandId::operator==(const TServerCommandId& aId) const + { + return (iId == aId.iId); + } + + +// +// CServerCommandBase. +// + +EXPORT_C CServerCommandBase::~CServerCommandBase() + { + } + +EXPORT_C const TServerCommandId& CServerCommandBase::Id() const + { + return iId; + } + +EXPORT_C void CServerCommandBase::SetId(const TServerCommandId& aId) + { + iId.Set(aId); + } + +EXPORT_C void CServerCommandBase::SetFactory(CServerCommandFactory& aFactory) + { + iFactory = &aFactory; + } + +EXPORT_C CServerCommandBase::CServerCommandBase() + { + } + +EXPORT_C CServerCommandBase::CServerCommandBase(TUint aFlags) + : CCommandBase(aFlags) + { + } + +EXPORT_C CServerCommandFactory& CServerCommandBase::Factory() + { + __ASSERT_ALWAYS(iFactory, Panic(ENoFactory)); + return *iFactory; + } + +EXPORT_C void CServerCommandBase::PrintList(TRefByValue aFmt, VA_LIST& aList) + { + if (iReporter) + { + iReporter->ReportList(iId, aFmt, aList); + } + else + { + CCommandBase::PrintList(aFmt, aList); + } + } + +EXPORT_C void CServerCommandBase::PrintList(TRefByValue aFmt, VA_LIST& aList) + { + if (iReporter) + { + iReporter->ReportList(iId, aFmt, aList); + } + else + { + CCommandBase::PrintList(aFmt, aList); + } + } + +EXPORT_C void CServerCommandBase::PrintErrorList(TInt aError, TRefByValue aFmt, VA_LIST& aList) + { + if (iReporter) + { + iReporter->ReportErrorList(iId, aError, aFmt, aList); + } + else + { + CCommandBase::PrintErrorList(aError, aFmt, aList); + } + } + +EXPORT_C void CServerCommandBase::PrintWarningList(TRefByValue aFmt, VA_LIST& aList) + { + if (iReporter) + { + iReporter->ReportWarningList(iId, aFmt, aList); + } + else + { + CCommandBase::PrintWarningList(aFmt, aList); + } + } + +void CServerCommandBase::SetReporter(MServerCommandReporter* aReporter) + { + iReporter = aReporter; + } + + +// +// CHelpCommand. +// + +NONSHARABLE_CLASS(CHelpCommand) : public CServerCommandBase + { +public: + static CServerCommandBase* NewLC(); + ~CHelpCommand(); + static const TDesC& NameS(); +private: + CHelpCommand(); + void ConstructL(); + void GenerateTextL(const CServerCommandFactory& aFactory, TInt aIndent = 0); + HBufC* FullCommandNameLC() const; + void Write(TInt aIndent, const TDesC& aCommandName); +private: // From CCommandBase. + virtual const TDesC& Name() const; + virtual const TDesC& Description() const; + virtual void DoRunL(); +private: + CTextBuffer* iBuffer; + CTextFormatter* iFormatter; + RArray iCommandNameStack; + RFile iPodIndex; + }; + +CServerCommandBase* CHelpCommand::NewLC() + { + CHelpCommand* self = new(ELeave) CHelpCommand(); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +CHelpCommand::~CHelpCommand() + { + delete iBuffer; + delete iFormatter; + iPodIndex.Close(); + iCommandNameStack.Close(); + } + +const TDesC& CHelpCommand::NameS() + { + return KHelpCommandName; + } + +CHelpCommand::CHelpCommand() + { + } + +void CHelpCommand::ConstructL() + { + BaseConstructL(); + } + +const TDesC& CHelpCommand::Name() const + { + return KHelpCommandName; + } + +const TDesC& CHelpCommand::Description() const + { + _LIT(KDescription, "List the commands the amsrv supports."); + return KDescription; + } + +void CHelpCommand::GenerateTextL(const CServerCommandFactory& aFactory, TInt aIndent) + { + RArray commands; + CleanupClosePushL(commands); + aFactory.ListCommandsL(commands); + commands.Sort(TLinearOrder(PtrOrder)); + + const TInt numCommands = commands.Count(); + for (TInt i = 0; i < numCommands; ++i) + { + const TDesC& commandName = commands[i]; + Write(aIndent, commandName); + + const CServerCommandConstructor& cmnd = aFactory.GetSubCommandL(commandName); + if (cmnd.IsFactory()) + { + GenerateTextL((const CServerCommandFactory&)cmnd, aIndent+1); + } + } + CleanupStack::PopAndDestroy(); + } + +HBufC* CHelpCommand::FullCommandNameLC() const + { + const TInt numCommands = iCommandNameStack.Count(); + TInt length = 0; + for (TInt i = 0; i < numCommands; ++i) + { + length += iCommandNameStack[i].Length(); + if (i > 0) + { + ++length; + } + } + HBufC* name = HBufC::NewLC(length); + TPtr namePtr(name->Des()); + for (TInt i = 0; i < numCommands; ++i) + { + if (i > 0) + { + namePtr.Append('_'); + } + namePtr.Append(iCommandNameStack[i]); + } + return name; + } + +void CHelpCommand::Write(TInt aIndent, const TDesC& aCommandName) + { + _LIT(KIndent, " "); + + if (iBuffer) + { + for (TInt j=0; jAppendL(KIndent); + } + iBuffer->AppendL(aCommandName); + iBuffer->AppendL(KTab); + } + else + { + for (TInt j=0; jColumnizeL(0, 2, iBuffer->Descriptor()); + CCommandBase::Write(iFormatter->Descriptor()); + } + CCommandBase::Write(_L("\r\n")); + } + + +// +// CRootCommand. +// + +NONSHARABLE_CLASS(CRootCommand) : public CBranchCommandBase + { +public: + static CRootCommand* NewL(CServerCommandFactory& aFactory); + ~CRootCommand(); +private: + CRootCommand(); + void ConstructL(CServerCommandFactory& aFactory); +private: // From CCommandBase. + virtual const TDesC& Name() const; + virtual const TDesC& Description() const; +private: // From CAmCmndParent. + virtual const TDesC& TypeDescription(); + }; + +CRootCommand* CRootCommand::NewL(CServerCommandFactory& aFactory) + { + CRootCommand* root = new(ELeave)CRootCommand(); + CleanupStack::PushL(root); + root->ConstructL(aFactory); + CleanupStack::Pop(root); + return root; + } + +CRootCommand::~CRootCommand() + { + } + +CRootCommand::CRootCommand() + { + } + +void CRootCommand::ConstructL(CServerCommandFactory& aFactory) + { + SetFactory(aFactory); + } + +const TDesC& CRootCommand::Name() const + { + _LIT(KCommandName, "root"); + return KCommandName; + } + +const TDesC& CRootCommand::Description() const + { + _LIT(KDescription, "A pseudo-command that is the ancestor of all other commands available in this server. Not intended to be run directly."); + return KDescription; + } + +const TDesC& CRootCommand::TypeDescription() + { + return KNullDesC; + } + + +// +// CServerBase. +// + +EXPORT_C CServerBase::~CServerBase() + { + delete iLineEditor; + delete iFactory; + } + +EXPORT_C CServerBase::CServerBase(TUint aFlags, const TDesC& aPrompt, const TDesC& aCommandHistoryFileName) + : CCommandBase(aFlags), iPrompt(aPrompt), iCommandHistoryFileName(aCommandHistoryFileName), iWriterAdaptor(Stdout()) + { + } + +EXPORT_C CServerCommandFactory& CServerBase::Factory() + { + return *iFactory; + } + +EXPORT_C void CServerBase::Exit(TInt aError) + { + iExitReason = aError; + iExit = ETrue; + } + +EXPORT_C void CServerBase::BaseConstructL() + { + CCommandBase::BaseConstructL(); + } + +EXPORT_C void CServerBase::DoRunL() + { + iFactory = CServerCommandFactory::NewL(this, Cif()); + iLineEditor = CLineEditor::NewL(FsL(), iWriterAdaptor, *this, *iFactory, iCommandHistoryFileName); + InitializeL(); + RProcess::Rendezvous(KErrNone); + + do + { + CheckNewConsoleLine(); + Write(iPrompt); + ParseLineL(NextLineL()); + } + while (!iExit); + + Complete(iExitReason); + } + +EXPORT_C void CServerBase::PrintList(TRefByValue aFmt, VA_LIST& aList) + { + TOverflowTruncate overflow; + TBuf<0x100> buf; + buf.AppendFormatList(aFmt, aList, &overflow); + Report(TServerCommandId(), buf); + } + +EXPORT_C void CServerBase::PrintList(TRefByValue aFmt, VA_LIST& aList) + { + TOverflowTruncate8 overflow; + TBuf8<0x100> buf; + buf.AppendFormatList(aFmt, aList, &overflow); + Report(TServerCommandId(), buf); + } + +EXPORT_C void CServerBase::PrintErrorList(TInt aError, TRefByValue aFmt, VA_LIST& aList) + { + if (!iErrorReported) + { + TOverflowTruncate overflow; + TBuf<0x100> buf; + buf.AppendFormatList(aFmt, aList, &overflow); + ReportError(TServerCommandId(), aError, buf); + iErrorReported = ETrue; + } + } + +EXPORT_C void CServerBase::PrintWarningList(TRefByValue aFmt, VA_LIST& aList) + { + TOverflowTruncate overflow; + TBuf<0x100> buf; + buf.AppendFormatList(aFmt, aList, &overflow); + ReportWarning(TServerCommandId(), buf); + } + +EXPORT_C void CServerBase::Report(const TServerCommandId& aId, TRefByValue aFmt, ...) + { + VA_LIST list; + VA_START(list, aFmt); + ReportList(aId, aFmt, list); + VA_END(list); + } + +EXPORT_C void CServerBase::ReportList(const TServerCommandId& aId, TRefByValue aFmt, VA_LIST& aList) + { + TOverflowTruncate overflow; + TBuf<0x100> buf; + buf.AppendFormatList(aFmt, aList, &overflow); + Report(aId, buf); + } + +EXPORT_C void CServerBase::Report(const TServerCommandId& aId, TRefByValue aFmt, ...) + { + VA_LIST list; + VA_START(list, aFmt); + ReportList(aId, aFmt, list); + VA_END(list); + } + +EXPORT_C void CServerBase::ReportList(const TServerCommandId& aId, TRefByValue aFmt, VA_LIST& aList) + { + TOverflowTruncate8 overflow; + TBuf8<0x100> buf; + buf.AppendFormatList(aFmt, aList, &overflow); + Report(aId, buf); + } + +EXPORT_C void CServerBase::ReportWarning(const TServerCommandId& aId, TRefByValue aFmt, ...) + { + VA_LIST list; + VA_START(list, aFmt); + ReportWarningList(aId, aFmt, list); + VA_END(list); + } + +EXPORT_C void CServerBase::ReportWarningList(const TServerCommandId& aId, TRefByValue aFmt, VA_LIST& aList) + { + TOverflowTruncate overflow; + TBuf<0x100> buf; + buf.AppendFormatList(aFmt, aList, &overflow); + ReportWarning(aId, buf); + } + +EXPORT_C void CServerBase::ReportError(const TServerCommandId& aId, TInt aError, TRefByValue aFmt, ...) + { + VA_LIST list; + VA_START(list, aFmt); + ReportErrorList(aId, aError, aFmt, list); + VA_END(list); + } + +EXPORT_C void CServerBase::ReportErrorList(const TServerCommandId& aId, TInt aError, TRefByValue aFmt, VA_LIST& aList) + { + if (!iErrorReported) + { + TOverflowTruncate overflow; + TBuf<0x100> buf; + buf.AppendFormatList(aFmt, aList, &overflow); + ReportError(aId, aError, buf); + iErrorReported = ETrue; + } + } + +EXPORT_C void CServerBase::LeoHandleLine(const TDesC& aLine) + { + iLine = aLine; + iLineRead = ETrue; + } + +void CServerBase::ParseLineL(const TDesC& aLine) + { + if (aLine.Length() > 0) + { + iErrorReported = EFalse; + CRootCommand* root = CRootCommand::NewL(Factory()); + root->SetReporter(this); + root->RunCommand(IoSession(), Stdin(), Stdout(), Stderr(), &aLine, &Env(), NULL); + __ASSERT_ALWAYS(root->IsComplete(), Panic(EUnexpectedAsyncCommand)); + delete root; + } + } + +const TDesC& CServerBase::NextLineL() + { +retry: + iLine.Zero(); + + if (Stdin().AttachedToConsole()) + { + iLineEditor->Start(KNullDesC); + iLineEditor->ReinstatePromptAndUserInput(); + iLineRead = EFalse; + do + { + TRequestStatus status; + Stdin().WaitForKey(status); + User::WaitForRequest(status); + if (status.Int() == KErrNotSupported) + { + // Likely that we're no longer attached to a console and are instead attached to a pipe. + // Note, using "pcons" directly gives us a console, but using "am.exe" gives us a pipe. + iLineEditor->Abort(); + goto retry; + } + User::LeaveIfError(status.Int()); + iLineEditor->HandleKey(Stdin().KeyCode(), Stdin().KeyModifiers()); + } + while (!iLineRead); + } + else + { + LeaveIfErr(Stdin().SetReadMode(RIoReadHandle::ELine), _L("Couldn't set stdin to line mode")); + Stdin().SetLineSeparatorL(KNewLine()); + User::LeaveIfError(Stdin().Read(iLine)); + } + + iLine.TrimRight(); + return iLine; + } + +EXPORT_C void CServerBase::CheckNewConsoleLine() + { + if (Stdout().AttachedToConsole()) + { + TPoint cursorPos(0, 0); + Stdout().GetCursorPos(cursorPos); + if (cursorPos.iX != 0) + { + Stdout().Write(KNewLine); + } + } + } + + +// +// CServerCommandConstructor. +// + +EXPORT_C CServerCommandConstructor* CServerCommandConstructor::NewLC(const TDesC& aName, TServerCommandConstructor aConstructor, CServerCommandFactory& aFactory, MServerCommandReporter* aReporter, const CCommandInfoFile* aCif) + { + CServerCommandConstructor* self = new(ELeave)CServerCommandConstructor(aName, aConstructor, aFactory, aReporter, aCif); + CleanupStack::PushL(self); + return self; + } + +EXPORT_C CServerCommandConstructor::~CServerCommandConstructor() + { + } + +EXPORT_C const TPtrC& CServerCommandConstructor::Name() const + { + return iName; + } + +EXPORT_C CServerCommandBase* CServerCommandConstructor::CreateImplementationLC() const + { + CServerCommandBase* commandBase = (*iConstructorLC)(); + commandBase->SetReporter(iReporter); + commandBase->SetFactory(iFactory); + if (iCif) + { + commandBase->SetCif(*iCif); + } + return commandBase; + } + +EXPORT_C TBool CServerCommandConstructor::IsFactory() const + { + return EFalse; + } + +CServerCommandConstructor::CServerCommandConstructor(const TDesC& aName, TServerCommandConstructor aConstructor, CServerCommandFactory& aFactory, MServerCommandReporter* aReporter, const CCommandInfoFile* aCif) + : iName(aName), iConstructorLC(aConstructor), iFactory(aFactory), iReporter(aReporter), iCif(aCif) + { + } + +TUint32 DefaultTPtrCHash(const TPtrC& aPtr) + { + return DefaultHash::Des16(aPtr); + } + +TBool DefaultIdTPtrCRelation(const TPtrC& aPtr1, const TPtrC& aPtr2) + { + return DefaultIdentity::Des16(aPtr1, aPtr2); + } + + +// +// CServerCommandFactory. +// + +EXPORT_C CServerCommandFactory* CServerCommandFactory::NewL(MServerCommandReporter* aReporter, const CCommandInfoFile* aCif) + { + CServerCommandFactory* self = new(ELeave)CServerCommandFactory(aReporter, aCif); + CleanupStack::PushL(self); + self->ConstructL(ERoot); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C CServerCommandFactory* CServerCommandFactory::NewLC(const TDesC& aName, TServerCommandConstructor aConstructor, MServerCommandReporter* aReporter, const CCommandInfoFile* aCif) + { + CServerCommandFactory* self = new(ELeave)CServerCommandFactory(aName, aConstructor, aReporter, aCif); + CleanupStack::PushL(self); + self->ConstructL(EBranch); + return self; + } + +EXPORT_C CServerCommandFactory::~CServerCommandFactory() + { + THashMapIter iter(iSubCommands); + while (iter.NextKey()) + { + delete *iter.CurrentValue(); + } + iSubCommands.Close(); + } + +EXPORT_C const CServerCommandConstructor& CServerCommandFactory::GetSubCommandL(const TDesC& aName) const + { + const CServerCommandConstructor* cmnd = GetSubCommand(aName); + if (!cmnd) + { + if (iReporter) + { + iReporter->ReportError(TServerCommandId(), KErrNotFound, _L("Couldn't create command \"%S\""), &aName); + } + User::Leave(KErrNotFound); + } + return *cmnd; + } + +const CServerCommandConstructor* CServerCommandFactory::GetSubCommand(const TDesC& aName) const + { + TPtrC name(aName); + const CServerCommandConstructor* const * cmnd = iSubCommands.Find(name); + if (!cmnd) + { + return NULL; + } + return *cmnd; + } + +EXPORT_C TBool CServerCommandFactory::IsFactory() const + { + return ETrue; + } + +EXPORT_C void CServerCommandFactory::AddSubCommandL(const CServerCommandConstructor* aCommand) + { + iSubCommands.InsertL(aCommand->Name(), aCommand); + } + +CServerCommandFactory::CServerCommandFactory(MServerCommandReporter* aReporter, const CCommandInfoFile* aCif) + : CServerCommandConstructor(KNullDesC, NULL, *this, aReporter, aCif), iSubCommands(THashFunction32(&DefaultTPtrCHash), TIdentityRelation(&DefaultIdTPtrCRelation)) + { + } + +CServerCommandFactory::CServerCommandFactory(const TDesC& aName, TServerCommandConstructor aConstructor, MServerCommandReporter* aReporter, const CCommandInfoFile* aCif) + : CServerCommandConstructor(aName, aConstructor, *this, aReporter, aCif), iSubCommands(THashFunction32(&DefaultTPtrCHash), TIdentityRelation(&DefaultIdTPtrCRelation)) + { + } + +void CServerCommandFactory::ConstructL(TFactoryType aType) + { + if (aType == ERoot) + { + AddLeafCommandL(); + } + } + +void CServerCommandFactory::LcCompleteLineL(TConsoleLine& aLine, const TChar&) + { + TLex lex(aLine.ContentsToCursor()); + TInt pos = 0; + + const CServerCommandFactory* factory = this; + + do + { + lex.SkipSpaceAndMark(); + pos = lex.Offset(); + lex.SkipCharacters(); + + if (!lex.Eos()) + { + const CServerCommandConstructor* command = GetSubCommand(lex.MarkedToken()); + if (!command || !command->IsFactory()) + { + User::Leave(KErrNotFound); + } + factory = static_cast(command); + } + + } while (!lex.Eos()); + + + + RArray commands; + CleanupClosePushL(commands); + TPtrC partialCommandName(lex.MarkedToken()); + + factory->ListCommandsL(commands); + + // Remove commands that don't match. + TInt i; + for (i = (commands.Count() - 1); i >= 0; --i) + { + if (commands[i].Find(partialCommandName) != 0) + { + commands.Remove(i); + } + } + + if (commands.Count() > 0) + { + CompleteLineL(aLine, pos, commands); + } + + CleanupStack::PopAndDestroy(&commands); + } + +void CServerCommandFactory::CompleteLineL(TConsoleLine& aLine, TInt aPos, const RArray aPossibilities) const + { + const TInt numPossibilities = aPossibilities.Count(); + + if (numPossibilities > 1) + { + // Fill out possibilities buffer. + IoUtils::CTextBuffer* possibilities = IoUtils::CTextBuffer::NewLC(0x100); + for (TInt i = 0; i < numPossibilities; ++i) + { + possibilities->AppendL(aPossibilities[i]); + if (i != (numPossibilities - 1)) + { + possibilities->AppendL(KTab); + } + } + + aLine.PrintCompletionPossibilitiesL(possibilities->Descriptor()); + CleanupStack::PopAndDestroy(possibilities); + } + + if (numPossibilities > 0) + { + IoUtils::CTextBuffer* completion = IoUtils::CTextBuffer::NewLC(0x100); + TPtrC commonChars(NULL, 0); + if (numPossibilities > 1) + { + // Find common leading characters of the possibilities. + TInt commonCharPos = -1; + TBool finished(EFalse); + do + { + ++commonCharPos; + TChar character(0); + for (TInt i = 0; i < numPossibilities; ++i) + { + if (commonCharPos >= aPossibilities[i].Length()) + { + finished = ETrue; + break; + } + else if (i == 0) + { + character = aPossibilities[0][commonCharPos]; + character.Fold(); + } + else + { + TChar c(aPossibilities[i][commonCharPos]); + c.Fold(); + if (c != character) + { + finished = ETrue; + break; + } + } + } + } + while (!finished); + + commonChars.Set(aPossibilities[0].Mid(0, commonCharPos)); + } + else + { + commonChars.Set(aPossibilities[0]); + } + + completion->AppendL(commonChars); + if (numPossibilities == 1) + { + completion->AppendL(KSpace); + } + if (completion->Descriptor().Length() > 0) + { + aLine.Replace(aPos, completion->Descriptor()); + } + CleanupStack::PopAndDestroy(completion); + } + } + +EXPORT_C void CServerCommandFactory::ListCommandsL(RArray& aList) const + { + THashMapIter iter(iSubCommands); + while (iter.NextKey()) + { + aList.AppendL(*iter.CurrentKey()); + } + aList.Sort(TLinearOrder(PtrOrder)); + } + + + +// +// CBranchCommandBase. +// + +EXPORT_C CBranchCommandBase::~CBranchCommandBase() + { + delete iSubCommandEnum; + delete iSubCommandArgs; + } + +EXPORT_C CBranchCommandBase::CBranchCommandBase() + { + } + +EXPORT_C void CBranchCommandBase::DoRunL() + { + TPtrC subCommandName(iArguments.AsString(&iType)); + + CServerCommandBase* subCommand = Factory().GetSubCommandL(subCommandName).CreateImplementationLC(); + ConfigureSubCommand(*subCommand); + subCommand->RunCommand(IoSession(), Stdin(), Stdout(), Stderr(), iSubCommandArgs ? iSubCommandArgs : &KNullDesC, &Env(), NULL); + if (subCommand->IsComplete()) + { + HandleSubCommandComplete(*subCommand); + CleanupStack::PopAndDestroy(subCommand); + } + else + { + HandleBackgroundSubCommand(*subCommand); + CleanupStack::Pop(subCommand); + } + } + +void CBranchCommandBase::BuildEnumL() + { + _LIT(KComma, ","); + RArray subCommands; + CleanupClosePushL(subCommands); + Factory().ListCommandsL(subCommands); + subCommands.Sort(TLinearOrder(PtrOrder)); + iSubCommandEnum = IoUtils::CTextBuffer::NewL(0x10); + for (TInt i=0; iAppendL(subCommands[i]); + iSubCommandEnum->AppendL(KComma); + } + CleanupStack::PopAndDestroy(&subCommands); + } + +EXPORT_C void CBranchCommandBase::ArgumentsL(RCommandArgumentList& aArguments) + { + _LIT(KArgType, "type"); + _LIT(KArgArgs, "arguments"); + + if (!iSubCommandEnum) + { + BuildEnumL(); + } + + if (UsingCif()) + { + aArguments.AppendEnumL((TInt&)iType, KArgType, iSubCommandEnum->Descriptor()); + aArguments.AppendStringL(iSubCommandArgs, KArgArgs); + } + else + { + aArguments.AppendEnumL((TInt&)iType, KArgType, TypeDescription(), iSubCommandEnum->Descriptor()); + + _LIT(KArgArgsDescription, "A set of type-specific arguments and options."); + aArguments.AppendStringL(iSubCommandArgs, KArgArgs, KArgArgsDescription, KValueTypeFlagOptional | KValueTypeFlagLast); + } + } + +EXPORT_C const TDesC& CBranchCommandBase::TypeDescription() + { + return KNullDesC; + } + +EXPORT_C void CBranchCommandBase::ConfigureSubCommand(CServerCommandBase&) + { + } + +EXPORT_C void CBranchCommandBase::HandleSubCommandComplete(CServerCommandBase& aCommand) + { + if (aCommand.CompletionReason() < 0) + { + PrintError(aCommand.CompletionReason(), _L("Couldn't run sub-command \"%S\" of command \"%S\""), &aCommand.Name(), &Name()); + } + } + +EXPORT_C void CBranchCommandBase::HandleBackgroundSubCommand(CServerCommandBase&) + { + }