libraries/iosrv/client/server_command.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // server_command.cpp
       
     2 // 
       
     3 // Copyright (c) 2009 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include <fshell/ioutils.h>
       
    14 #include <fshell/line_editor.h>
       
    15 #include "command_base.h"
       
    16 
       
    17 using namespace IoUtils;
       
    18 
       
    19 
       
    20 //
       
    21 // Constants.
       
    22 //
       
    23 
       
    24 _LIT(KTab, "\t");
       
    25 _LIT(KSpace, " ");
       
    26 _LIT(KNewLine, "\r\n");
       
    27 _LIT(KHelpCommandName, "help");
       
    28 
       
    29 
       
    30 // used for sorting RArray<TPtrC>'s
       
    31 TInt PtrOrder(const TPtrC& aDennis, const TPtrC& aGnasher)
       
    32 	{
       
    33 	return aDennis.Compare(aGnasher);
       
    34 	}
       
    35 
       
    36 
       
    37 //
       
    38 // TServerCommandId.
       
    39 //
       
    40 
       
    41 EXPORT_C TServerCommandId::TServerCommandId()
       
    42 	: iId(0)
       
    43 	{
       
    44 	}
       
    45 
       
    46 EXPORT_C TServerCommandId::TServerCommandId(TUint aValue)
       
    47 	: iId(aValue)
       
    48 	{
       
    49 	}
       
    50 
       
    51 EXPORT_C TUint TServerCommandId::Value() const
       
    52 	{
       
    53 	return iId;
       
    54 	}
       
    55 
       
    56 EXPORT_C void TServerCommandId::Set(const TServerCommandId& aId)
       
    57 	{
       
    58 	iId = aId.iId;
       
    59 	}
       
    60 
       
    61 EXPORT_C TBool TServerCommandId::operator==(const TServerCommandId& aId) const
       
    62 	{
       
    63 	return (iId == aId.iId);
       
    64 	}
       
    65 
       
    66 
       
    67 //
       
    68 // CServerCommandBase.
       
    69 //
       
    70 
       
    71 EXPORT_C CServerCommandBase::~CServerCommandBase()
       
    72 	{
       
    73 	}
       
    74 
       
    75 EXPORT_C const TServerCommandId& CServerCommandBase::Id() const
       
    76 	{
       
    77 	return iId;
       
    78 	}
       
    79 
       
    80 EXPORT_C void CServerCommandBase::SetId(const TServerCommandId& aId)
       
    81 	{
       
    82 	iId.Set(aId);
       
    83 	}
       
    84 
       
    85 EXPORT_C void CServerCommandBase::SetFactory(CServerCommandFactory& aFactory)
       
    86 	{
       
    87 	iFactory = &aFactory;
       
    88 	}
       
    89 
       
    90 EXPORT_C CServerCommandBase::CServerCommandBase()
       
    91 	{
       
    92 	}
       
    93 
       
    94 EXPORT_C CServerCommandBase::CServerCommandBase(TUint aFlags)
       
    95 	: CCommandBase(aFlags)
       
    96 	{
       
    97 	}
       
    98 
       
    99 EXPORT_C CServerCommandFactory& CServerCommandBase::Factory()
       
   100 	{
       
   101 	__ASSERT_ALWAYS(iFactory, Panic(ENoFactory));
       
   102 	return *iFactory;
       
   103 	}
       
   104 
       
   105 EXPORT_C void CServerCommandBase::PrintList(TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
   106 	{
       
   107 	if (iReporter)
       
   108 		{
       
   109 		iReporter->ReportList(iId, aFmt, aList);
       
   110 		}
       
   111 	else
       
   112 		{
       
   113 		CCommandBase::PrintList(aFmt, aList);
       
   114 		}
       
   115 	}
       
   116 
       
   117 EXPORT_C void CServerCommandBase::PrintList(TRefByValue<const TDesC8> aFmt, VA_LIST& aList)
       
   118 	{
       
   119 	if (iReporter)
       
   120 		{
       
   121 		iReporter->ReportList(iId, aFmt, aList);
       
   122 		}
       
   123 	else
       
   124 		{
       
   125 		CCommandBase::PrintList(aFmt, aList);
       
   126 		}
       
   127 	}
       
   128 
       
   129 EXPORT_C void CServerCommandBase::PrintErrorList(TInt aError, TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
   130 	{
       
   131 	if (iReporter)
       
   132 		{
       
   133 		iReporter->ReportErrorList(iId, aError, aFmt, aList);
       
   134 		}
       
   135 	else
       
   136 		{
       
   137 		CCommandBase::PrintErrorList(aError, aFmt, aList);
       
   138 		}
       
   139 	}
       
   140 
       
   141 EXPORT_C void CServerCommandBase::PrintWarningList(TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
   142 	{
       
   143 	if (iReporter)
       
   144 		{
       
   145 		iReporter->ReportWarningList(iId, aFmt, aList);
       
   146 		}
       
   147 	else
       
   148 		{
       
   149 		CCommandBase::PrintWarningList(aFmt, aList);
       
   150 		}
       
   151 	}
       
   152 
       
   153 void CServerCommandBase::SetReporter(MServerCommandReporter* aReporter)
       
   154 	{
       
   155 	iReporter = aReporter;
       
   156 	}
       
   157 
       
   158 
       
   159 //
       
   160 // CHelpCommand.
       
   161 //
       
   162 
       
   163 NONSHARABLE_CLASS(CHelpCommand) : public CServerCommandBase
       
   164 	{
       
   165 public:
       
   166 	static CServerCommandBase* NewLC();
       
   167 	~CHelpCommand();
       
   168 	static const TDesC& NameS();
       
   169 private:
       
   170 	CHelpCommand();
       
   171 	void ConstructL();
       
   172 	void GenerateTextL(const CServerCommandFactory& aFactory, TInt aIndent = 0);
       
   173 	HBufC* FullCommandNameLC() const;
       
   174 	void Write(TInt aIndent, const TDesC& aCommandName);
       
   175 private: // From CCommandBase.
       
   176 	virtual const TDesC& Name() const;
       
   177 	virtual const TDesC& Description() const;
       
   178 	virtual void DoRunL();
       
   179 private:
       
   180 	CTextBuffer* iBuffer;
       
   181 	CTextFormatter* iFormatter;
       
   182 	RArray<TPtrC> iCommandNameStack;
       
   183 	RFile iPodIndex;
       
   184 	};
       
   185 
       
   186 CServerCommandBase* CHelpCommand::NewLC()
       
   187 	{
       
   188 	CHelpCommand* self = new(ELeave) CHelpCommand();
       
   189 	CleanupStack::PushL(self);
       
   190 	self->ConstructL();
       
   191 	return self;
       
   192 	}
       
   193 
       
   194 CHelpCommand::~CHelpCommand()
       
   195 	{
       
   196 	delete iBuffer;
       
   197 	delete iFormatter;
       
   198 	iPodIndex.Close();
       
   199 	iCommandNameStack.Close();
       
   200 	}
       
   201 
       
   202 const TDesC& CHelpCommand::NameS()
       
   203 	{
       
   204 	return KHelpCommandName;
       
   205 	}
       
   206 
       
   207 CHelpCommand::CHelpCommand()
       
   208 	{
       
   209 	}
       
   210 
       
   211 void CHelpCommand::ConstructL()
       
   212 	{
       
   213 	BaseConstructL();
       
   214 	}
       
   215 
       
   216 const TDesC& CHelpCommand::Name() const
       
   217 	{
       
   218 	return KHelpCommandName;
       
   219 	}
       
   220 
       
   221 const TDesC& CHelpCommand::Description() const
       
   222 	{
       
   223 	_LIT(KDescription, "List the commands the amsrv supports.");
       
   224 	return KDescription;
       
   225 	}
       
   226 	
       
   227 void CHelpCommand::GenerateTextL(const CServerCommandFactory& aFactory, TInt aIndent)
       
   228 	{
       
   229 	RArray<TPtrC> commands;
       
   230 	CleanupClosePushL(commands);
       
   231 	aFactory.ListCommandsL(commands);
       
   232 	commands.Sort(TLinearOrder<TPtrC>(PtrOrder));
       
   233 	
       
   234 	const TInt numCommands = commands.Count();
       
   235 	for (TInt i = 0; i < numCommands; ++i)
       
   236 		{
       
   237 		const TDesC& commandName = commands[i];
       
   238 		Write(aIndent, commandName);
       
   239 
       
   240 		const CServerCommandConstructor& cmnd = aFactory.GetSubCommandL(commandName);
       
   241 		if (cmnd.IsFactory())
       
   242 			{
       
   243 			GenerateTextL((const CServerCommandFactory&)cmnd, aIndent+1);
       
   244 			}
       
   245 		}
       
   246 	CleanupStack::PopAndDestroy();
       
   247 	}
       
   248 
       
   249 HBufC* CHelpCommand::FullCommandNameLC() const
       
   250 	{
       
   251 	const TInt numCommands = iCommandNameStack.Count();
       
   252 	TInt length = 0;
       
   253 	for (TInt i = 0; i < numCommands; ++i)
       
   254 		{
       
   255 		length += iCommandNameStack[i].Length();
       
   256 		if (i > 0)
       
   257 			{
       
   258 			++length;
       
   259 			}
       
   260 		}
       
   261 	HBufC* name = HBufC::NewLC(length);
       
   262 	TPtr namePtr(name->Des());
       
   263 	for (TInt i = 0; i < numCommands; ++i)
       
   264 		{
       
   265 		if (i > 0)
       
   266 			{
       
   267 			namePtr.Append('_');
       
   268 			}
       
   269 		namePtr.Append(iCommandNameStack[i]);
       
   270 		}
       
   271 	return name;
       
   272 	}
       
   273 
       
   274 void CHelpCommand::Write(TInt aIndent, const TDesC& aCommandName)
       
   275 	{
       
   276 	_LIT(KIndent, "  ");
       
   277 
       
   278 	if (iBuffer)
       
   279 		{
       
   280 		for (TInt j=0; j<aIndent; ++j)
       
   281 			{
       
   282 			iBuffer->AppendL(KIndent);
       
   283 			}
       
   284 		iBuffer->AppendL(aCommandName);
       
   285 		iBuffer->AppendL(KTab);
       
   286 		}
       
   287 	else
       
   288 		{
       
   289 		for (TInt j=0; j<aIndent; ++j)
       
   290 			{
       
   291 			CCommandBase::Write(KIndent);
       
   292 			}
       
   293 		CCommandBase::Write(aCommandName);
       
   294 		CCommandBase::Write(KNewLine);
       
   295 		}
       
   296 	}
       
   297 
       
   298 void CHelpCommand::DoRunL()
       
   299 	{
       
   300 	if (Stdout().AttachedToConsole())
       
   301 		{
       
   302 		iBuffer = CTextBuffer::NewL(0x100);
       
   303 		iFormatter = CTextFormatter::NewL(Stdout());
       
   304 		}
       
   305 	GenerateTextL(Factory());
       
   306 	if (iBuffer)
       
   307 		{
       
   308 		iFormatter->ColumnizeL(0, 2, iBuffer->Descriptor());
       
   309 		CCommandBase::Write(iFormatter->Descriptor());
       
   310 		}
       
   311 	CCommandBase::Write(_L("\r\n"));
       
   312 	}
       
   313 
       
   314 
       
   315 //
       
   316 // CRootCommand.
       
   317 //
       
   318 
       
   319 NONSHARABLE_CLASS(CRootCommand) : public CBranchCommandBase
       
   320 	{
       
   321 public:
       
   322 	static CRootCommand* NewL(CServerCommandFactory& aFactory);
       
   323 	~CRootCommand();
       
   324 private:
       
   325 	CRootCommand();
       
   326 	void ConstructL(CServerCommandFactory& aFactory);
       
   327 private: // From CCommandBase.
       
   328 	virtual const TDesC& Name() const;
       
   329 	virtual const TDesC& Description() const;
       
   330 private: // From CAmCmndParent.
       
   331 	virtual const TDesC& TypeDescription();
       
   332 	};
       
   333 
       
   334 CRootCommand* CRootCommand::NewL(CServerCommandFactory& aFactory)
       
   335 	{
       
   336 	CRootCommand* root = new(ELeave)CRootCommand();
       
   337 	CleanupStack::PushL(root);
       
   338 	root->ConstructL(aFactory);
       
   339 	CleanupStack::Pop(root);
       
   340 	return root;
       
   341 	}
       
   342 
       
   343 CRootCommand::~CRootCommand()
       
   344 	{
       
   345 	}
       
   346 
       
   347 CRootCommand::CRootCommand()
       
   348 	{
       
   349 	}
       
   350 
       
   351 void CRootCommand::ConstructL(CServerCommandFactory& aFactory)
       
   352 	{
       
   353 	SetFactory(aFactory);
       
   354 	}
       
   355 
       
   356 const TDesC& CRootCommand::Name() const
       
   357 	{
       
   358 	_LIT(KCommandName, "root");
       
   359 	return KCommandName;
       
   360 	}
       
   361 
       
   362 const TDesC& CRootCommand::Description() const
       
   363 	{
       
   364 	_LIT(KDescription, "A pseudo-command that is the ancestor of all other commands available in this server. Not intended to be run directly.");
       
   365 	return KDescription;
       
   366 	}
       
   367 
       
   368 const TDesC& CRootCommand::TypeDescription()
       
   369 	{
       
   370 	return KNullDesC;
       
   371 	}
       
   372 
       
   373 
       
   374 //
       
   375 // CServerBase.
       
   376 //
       
   377 
       
   378 EXPORT_C CServerBase::~CServerBase()
       
   379 	{
       
   380 	delete iLineEditor;
       
   381 	delete iFactory;
       
   382 	}
       
   383 
       
   384 EXPORT_C CServerBase::CServerBase(TUint aFlags, const TDesC& aPrompt, const TDesC& aCommandHistoryFileName)
       
   385 	: CCommandBase(aFlags), iPrompt(aPrompt), iCommandHistoryFileName(aCommandHistoryFileName), iWriterAdaptor(Stdout())
       
   386 	{
       
   387 	}
       
   388 
       
   389 EXPORT_C CServerCommandFactory& CServerBase::Factory()
       
   390 	{
       
   391 	return *iFactory;
       
   392 	}
       
   393 
       
   394 EXPORT_C void CServerBase::Exit(TInt aError)
       
   395 	{
       
   396 	iExitReason = aError;
       
   397 	iExit = ETrue;
       
   398 	}
       
   399 
       
   400 EXPORT_C void CServerBase::BaseConstructL()
       
   401 	{
       
   402 	CCommandBase::BaseConstructL();
       
   403 	}
       
   404 
       
   405 EXPORT_C void CServerBase::DoRunL()
       
   406 	{
       
   407 	iFactory = CServerCommandFactory::NewL(this, Cif());
       
   408 	iLineEditor = CLineEditor::NewL(FsL(), iWriterAdaptor, *this, *iFactory, iCommandHistoryFileName);
       
   409 	InitializeL();
       
   410 	RProcess::Rendezvous(KErrNone);
       
   411 
       
   412 	do
       
   413 		{
       
   414 		CheckNewConsoleLine();
       
   415 		Write(iPrompt);
       
   416 		ParseLineL(NextLineL());
       
   417 		}
       
   418 		while (!iExit);
       
   419 
       
   420 	Complete(iExitReason);
       
   421 	}
       
   422 
       
   423 EXPORT_C void CServerBase::PrintList(TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
   424 	{
       
   425 	TOverflowTruncate overflow;
       
   426 	TBuf<0x100> buf;
       
   427 	buf.AppendFormatList(aFmt, aList, &overflow);
       
   428 	Report(TServerCommandId(), buf);
       
   429 	}
       
   430 
       
   431 EXPORT_C void CServerBase::PrintList(TRefByValue<const TDesC8> aFmt, VA_LIST& aList)
       
   432 	{
       
   433 	TOverflowTruncate8 overflow;
       
   434 	TBuf8<0x100> buf;
       
   435 	buf.AppendFormatList(aFmt, aList, &overflow);
       
   436 	Report(TServerCommandId(), buf);
       
   437 	}
       
   438 
       
   439 EXPORT_C void CServerBase::PrintErrorList(TInt aError, TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
   440 	{
       
   441 	if (!iErrorReported)
       
   442 		{
       
   443 		TOverflowTruncate overflow;
       
   444 		TBuf<0x100> buf;
       
   445 		buf.AppendFormatList(aFmt, aList, &overflow);
       
   446 		ReportError(TServerCommandId(), aError, buf);
       
   447 		iErrorReported = ETrue;
       
   448 		}
       
   449 	}
       
   450 
       
   451 EXPORT_C void CServerBase::PrintWarningList(TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
   452 	{
       
   453 	TOverflowTruncate overflow;
       
   454 	TBuf<0x100> buf;
       
   455 	buf.AppendFormatList(aFmt, aList, &overflow);
       
   456 	ReportWarning(TServerCommandId(), buf);
       
   457 	}
       
   458 
       
   459 EXPORT_C void CServerBase::Report(const TServerCommandId& aId, TRefByValue<const TDesC> aFmt, ...)
       
   460 	{
       
   461 	VA_LIST list;
       
   462 	VA_START(list, aFmt);
       
   463 	ReportList(aId, aFmt, list);
       
   464 	VA_END(list);
       
   465 	}
       
   466 
       
   467 EXPORT_C void CServerBase::ReportList(const TServerCommandId& aId, TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
   468 	{
       
   469 	TOverflowTruncate overflow;
       
   470 	TBuf<0x100> buf;
       
   471 	buf.AppendFormatList(aFmt, aList, &overflow);
       
   472 	Report(aId, buf);
       
   473 	}
       
   474 
       
   475 EXPORT_C void CServerBase::Report(const TServerCommandId& aId, TRefByValue<const TDesC8> aFmt, ...)
       
   476 	{
       
   477 	VA_LIST list;
       
   478 	VA_START(list, aFmt);
       
   479 	ReportList(aId, aFmt, list);
       
   480 	VA_END(list);
       
   481 	}
       
   482 
       
   483 EXPORT_C void CServerBase::ReportList(const TServerCommandId& aId, TRefByValue<const TDesC8> aFmt, VA_LIST& aList)
       
   484 	{
       
   485 	TOverflowTruncate8 overflow;
       
   486 	TBuf8<0x100> buf;
       
   487 	buf.AppendFormatList(aFmt, aList, &overflow);
       
   488 	Report(aId, buf);
       
   489 	}
       
   490 
       
   491 EXPORT_C void CServerBase::ReportWarning(const TServerCommandId& aId, TRefByValue<const TDesC> aFmt, ...)
       
   492 	{
       
   493 	VA_LIST list;
       
   494 	VA_START(list, aFmt);
       
   495 	ReportWarningList(aId, aFmt, list);
       
   496 	VA_END(list);
       
   497 	}
       
   498 
       
   499 EXPORT_C void CServerBase::ReportWarningList(const TServerCommandId& aId, TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
   500 	{
       
   501 	TOverflowTruncate overflow;
       
   502 	TBuf<0x100> buf;
       
   503 	buf.AppendFormatList(aFmt, aList, &overflow);
       
   504 	ReportWarning(aId, buf);
       
   505 	}
       
   506 
       
   507 EXPORT_C void CServerBase::ReportError(const TServerCommandId& aId, TInt aError, TRefByValue<const TDesC> aFmt, ...)
       
   508 	{
       
   509 	VA_LIST list;
       
   510 	VA_START(list, aFmt);
       
   511 	ReportErrorList(aId, aError, aFmt, list);
       
   512 	VA_END(list);
       
   513 	}
       
   514 
       
   515 EXPORT_C void CServerBase::ReportErrorList(const TServerCommandId& aId, TInt aError, TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
   516 	{
       
   517 	if (!iErrorReported)
       
   518 		{
       
   519 		TOverflowTruncate overflow;
       
   520 		TBuf<0x100> buf;
       
   521 		buf.AppendFormatList(aFmt, aList, &overflow);
       
   522 		ReportError(aId, aError, buf);
       
   523 		iErrorReported = ETrue;
       
   524 		}
       
   525 	}
       
   526 
       
   527 EXPORT_C void CServerBase::LeoHandleLine(const TDesC& aLine)
       
   528 	{
       
   529 	iLine = aLine;
       
   530 	iLineRead = ETrue;
       
   531 	}
       
   532 
       
   533 void CServerBase::ParseLineL(const TDesC& aLine)
       
   534 	{
       
   535 	if (aLine.Length() > 0)
       
   536 		{
       
   537 		iErrorReported = EFalse;
       
   538 		CRootCommand* root = CRootCommand::NewL(Factory());
       
   539 		root->SetReporter(this);
       
   540 		root->RunCommand(IoSession(), Stdin(), Stdout(), Stderr(), &aLine, &Env(), NULL);
       
   541 		__ASSERT_ALWAYS(root->IsComplete(), Panic(EUnexpectedAsyncCommand));
       
   542 		delete root;
       
   543 		}
       
   544 	}
       
   545 
       
   546 const TDesC& CServerBase::NextLineL()
       
   547 	{
       
   548 retry:
       
   549 	iLine.Zero();
       
   550 
       
   551 	if (Stdin().AttachedToConsole())
       
   552 		{
       
   553 		iLineEditor->Start(KNullDesC);
       
   554 		iLineEditor->ReinstatePromptAndUserInput();
       
   555 		iLineRead = EFalse;
       
   556 		do
       
   557 			{
       
   558 			TRequestStatus status;
       
   559 			Stdin().WaitForKey(status);
       
   560 			User::WaitForRequest(status);
       
   561 			if (status.Int() == KErrNotSupported)
       
   562 				{
       
   563 				// Likely that we're no longer attached to a console and are instead attached to a pipe.
       
   564 				// Note, using "pcons" directly gives us a console, but using "am.exe" gives us a pipe.
       
   565 				iLineEditor->Abort();
       
   566 				goto retry;
       
   567 				}
       
   568 			User::LeaveIfError(status.Int());
       
   569 			iLineEditor->HandleKey(Stdin().KeyCode(), Stdin().KeyModifiers());
       
   570 			}
       
   571 			while (!iLineRead);
       
   572 		}
       
   573 	else
       
   574 		{
       
   575 		LeaveIfErr(Stdin().SetReadMode(RIoReadHandle::ELine), _L("Couldn't set stdin to line mode"));
       
   576 		Stdin().SetLineSeparatorL(KNewLine());
       
   577 		User::LeaveIfError(Stdin().Read(iLine));
       
   578 		}
       
   579 
       
   580 	iLine.TrimRight();
       
   581 	return iLine;
       
   582 	}
       
   583 
       
   584 EXPORT_C void CServerBase::CheckNewConsoleLine()
       
   585 	{
       
   586 	if (Stdout().AttachedToConsole())
       
   587 		{
       
   588 		TPoint cursorPos(0, 0);
       
   589 		Stdout().GetCursorPos(cursorPos);
       
   590 		if (cursorPos.iX != 0)
       
   591 			{
       
   592 			Stdout().Write(KNewLine);
       
   593 			}
       
   594 		}
       
   595 	}
       
   596 
       
   597 
       
   598 //
       
   599 // CServerCommandConstructor.
       
   600 //
       
   601 
       
   602 EXPORT_C CServerCommandConstructor* CServerCommandConstructor::NewLC(const TDesC& aName, TServerCommandConstructor aConstructor, CServerCommandFactory& aFactory, MServerCommandReporter* aReporter, const CCommandInfoFile* aCif)
       
   603 	{
       
   604 	CServerCommandConstructor* self = new(ELeave)CServerCommandConstructor(aName, aConstructor, aFactory, aReporter, aCif);
       
   605 	CleanupStack::PushL(self);
       
   606 	return self;
       
   607 	}
       
   608 
       
   609 EXPORT_C CServerCommandConstructor::~CServerCommandConstructor()
       
   610 	{
       
   611 	}
       
   612 
       
   613 EXPORT_C const TPtrC& CServerCommandConstructor::Name() const
       
   614 	{
       
   615 	return iName;
       
   616 	}
       
   617 
       
   618 EXPORT_C CServerCommandBase* CServerCommandConstructor::CreateImplementationLC() const
       
   619 	{
       
   620 	CServerCommandBase* commandBase = (*iConstructorLC)();
       
   621 	commandBase->SetReporter(iReporter);
       
   622 	commandBase->SetFactory(iFactory);
       
   623 	if (iCif)
       
   624 		{
       
   625 		commandBase->SetCif(*iCif);
       
   626 		}
       
   627 	return commandBase;	
       
   628 	}
       
   629 
       
   630 EXPORT_C TBool CServerCommandConstructor::IsFactory() const
       
   631 	{
       
   632 	return EFalse;
       
   633 	}
       
   634 
       
   635 CServerCommandConstructor::CServerCommandConstructor(const TDesC& aName, TServerCommandConstructor aConstructor, CServerCommandFactory& aFactory, MServerCommandReporter* aReporter, const CCommandInfoFile* aCif)
       
   636 	: iName(aName), iConstructorLC(aConstructor), iFactory(aFactory), iReporter(aReporter), iCif(aCif)
       
   637 	{
       
   638 	}
       
   639 
       
   640 TUint32 DefaultTPtrCHash(const TPtrC& aPtr)
       
   641 	{
       
   642 	return DefaultHash::Des16(aPtr);
       
   643 	}
       
   644 	
       
   645 TBool DefaultIdTPtrCRelation(const TPtrC& aPtr1, const TPtrC& aPtr2)
       
   646 	{
       
   647 	return DefaultIdentity::Des16(aPtr1, aPtr2);
       
   648 	}
       
   649 
       
   650 	
       
   651 //
       
   652 // CServerCommandFactory.
       
   653 //
       
   654 
       
   655 EXPORT_C CServerCommandFactory* CServerCommandFactory::NewL(MServerCommandReporter* aReporter, const CCommandInfoFile* aCif)
       
   656 	{
       
   657 	CServerCommandFactory* self = new(ELeave)CServerCommandFactory(aReporter, aCif);
       
   658 	CleanupStack::PushL(self);
       
   659 	self->ConstructL(ERoot);
       
   660 	CleanupStack::Pop(self);
       
   661 	return self;
       
   662 	}
       
   663 
       
   664 EXPORT_C CServerCommandFactory* CServerCommandFactory::NewLC(const TDesC& aName, TServerCommandConstructor aConstructor, MServerCommandReporter* aReporter, const CCommandInfoFile* aCif)
       
   665 	{
       
   666 	CServerCommandFactory* self = new(ELeave)CServerCommandFactory(aName, aConstructor, aReporter, aCif);
       
   667 	CleanupStack::PushL(self);
       
   668 	self->ConstructL(EBranch);
       
   669 	return self;
       
   670 	}
       
   671 	
       
   672 EXPORT_C CServerCommandFactory::~CServerCommandFactory()
       
   673 	{
       
   674 	THashMapIter<const TPtrC, const CServerCommandConstructor*> iter(iSubCommands);
       
   675 	while (iter.NextKey())
       
   676 		{
       
   677 		delete *iter.CurrentValue();
       
   678 		}
       
   679 	iSubCommands.Close();
       
   680 	}
       
   681 
       
   682 EXPORT_C const CServerCommandConstructor& CServerCommandFactory::GetSubCommandL(const TDesC& aName) const
       
   683 	{
       
   684 	const CServerCommandConstructor* cmnd = GetSubCommand(aName);
       
   685 	if (!cmnd)
       
   686 		{
       
   687 		if (iReporter)
       
   688 			{
       
   689 			iReporter->ReportError(TServerCommandId(), KErrNotFound, _L("Couldn't create command \"%S\""), &aName);
       
   690 			}
       
   691 		User::Leave(KErrNotFound);
       
   692 		}
       
   693 	return *cmnd;
       
   694 	}
       
   695 
       
   696 const CServerCommandConstructor* CServerCommandFactory::GetSubCommand(const TDesC& aName) const
       
   697 	{
       
   698 	TPtrC name(aName);
       
   699 	const CServerCommandConstructor* const * cmnd = iSubCommands.Find(name);
       
   700 	if (!cmnd)
       
   701 		{
       
   702 		return NULL;
       
   703 		}
       
   704 	return *cmnd;
       
   705 	}
       
   706 
       
   707 EXPORT_C TBool CServerCommandFactory::IsFactory() const
       
   708 	{
       
   709 	return ETrue;
       
   710 	}
       
   711 
       
   712 EXPORT_C void CServerCommandFactory::AddSubCommandL(const CServerCommandConstructor* aCommand)
       
   713 	{
       
   714 	iSubCommands.InsertL(aCommand->Name(), aCommand);
       
   715 	}
       
   716 
       
   717 CServerCommandFactory::CServerCommandFactory(MServerCommandReporter* aReporter, const CCommandInfoFile* aCif)
       
   718 	: CServerCommandConstructor(KNullDesC, NULL, *this, aReporter, aCif), iSubCommands(THashFunction32<const TPtrC>(&DefaultTPtrCHash), TIdentityRelation<const TPtrC>(&DefaultIdTPtrCRelation))
       
   719 	{
       
   720 	}
       
   721 
       
   722 CServerCommandFactory::CServerCommandFactory(const TDesC& aName, TServerCommandConstructor aConstructor, MServerCommandReporter* aReporter, const CCommandInfoFile* aCif)
       
   723 	: CServerCommandConstructor(aName, aConstructor, *this, aReporter, aCif), iSubCommands(THashFunction32<const TPtrC>(&DefaultTPtrCHash), TIdentityRelation<const TPtrC>(&DefaultIdTPtrCRelation))
       
   724 	{
       
   725 	}
       
   726 
       
   727 void CServerCommandFactory::ConstructL(TFactoryType aType)
       
   728 	{
       
   729 	if (aType == ERoot)
       
   730 		{
       
   731 		AddLeafCommandL<CHelpCommand>();
       
   732 		}
       
   733 	}
       
   734 
       
   735 void CServerCommandFactory::LcCompleteLineL(TConsoleLine& aLine, const TChar&)
       
   736 	{
       
   737 	TLex lex(aLine.ContentsToCursor());
       
   738 	TInt pos = 0;
       
   739 	
       
   740 	const CServerCommandFactory* factory = this;
       
   741 	
       
   742 	do
       
   743 		{
       
   744 		lex.SkipSpaceAndMark();
       
   745 		pos = lex.Offset();
       
   746 		lex.SkipCharacters();
       
   747 		
       
   748 		if (!lex.Eos())
       
   749 			{
       
   750 			const CServerCommandConstructor* command = GetSubCommand(lex.MarkedToken());
       
   751 			if (!command || !command->IsFactory())
       
   752 				{
       
   753 				User::Leave(KErrNotFound);
       
   754 				}
       
   755 			factory = static_cast<const CServerCommandFactory*>(command);
       
   756 			}
       
   757 		
       
   758 		} while (!lex.Eos());
       
   759 	
       
   760 	
       
   761 	
       
   762 	RArray<TPtrC> commands;
       
   763 	CleanupClosePushL(commands);
       
   764 	TPtrC partialCommandName(lex.MarkedToken());
       
   765 
       
   766 	factory->ListCommandsL(commands);
       
   767 
       
   768 	// Remove commands that don't match.
       
   769 	TInt i;
       
   770 	for (i = (commands.Count() - 1); i >= 0; --i)
       
   771 		{
       
   772 		if (commands[i].Find(partialCommandName) != 0)
       
   773 			{
       
   774 			commands.Remove(i);
       
   775 			}
       
   776 		}
       
   777 
       
   778 	if (commands.Count() > 0)
       
   779 		{
       
   780 		CompleteLineL(aLine, pos, commands);
       
   781 		}
       
   782 
       
   783 	CleanupStack::PopAndDestroy(&commands);
       
   784 	}
       
   785 
       
   786 void CServerCommandFactory::CompleteLineL(TConsoleLine& aLine, TInt aPos, const RArray<TPtrC> aPossibilities) const
       
   787 	{
       
   788 	const TInt numPossibilities = aPossibilities.Count();
       
   789 
       
   790 	if (numPossibilities > 1)
       
   791 		{
       
   792 		// Fill out possibilities buffer.
       
   793 		IoUtils::CTextBuffer* possibilities = IoUtils::CTextBuffer::NewLC(0x100);
       
   794 		for (TInt i = 0; i < numPossibilities; ++i)
       
   795 			{
       
   796 			possibilities->AppendL(aPossibilities[i]);
       
   797 			if (i != (numPossibilities - 1))
       
   798 				{
       
   799 				possibilities->AppendL(KTab);
       
   800 				}
       
   801 			}
       
   802 
       
   803 		aLine.PrintCompletionPossibilitiesL(possibilities->Descriptor());
       
   804 		CleanupStack::PopAndDestroy(possibilities);
       
   805 		}
       
   806 
       
   807 	if (numPossibilities > 0)
       
   808 		{
       
   809 		IoUtils::CTextBuffer* completion = IoUtils::CTextBuffer::NewLC(0x100);
       
   810 		TPtrC commonChars(NULL, 0);
       
   811 		if (numPossibilities > 1)
       
   812 			{
       
   813 			// Find common leading characters of the possibilities.
       
   814 			TInt commonCharPos = -1;
       
   815 			TBool finished(EFalse);
       
   816 			do
       
   817 				{
       
   818 				++commonCharPos;
       
   819 				TChar character(0);
       
   820 				for (TInt i = 0; i < numPossibilities; ++i)
       
   821 					{
       
   822 					if (commonCharPos >= aPossibilities[i].Length())
       
   823 						{
       
   824 						finished = ETrue;
       
   825 						break;
       
   826 						}
       
   827 					else if (i == 0)
       
   828 						{
       
   829 						character = aPossibilities[0][commonCharPos];
       
   830 						character.Fold();
       
   831 						}
       
   832 					else
       
   833 						{
       
   834 						TChar c(aPossibilities[i][commonCharPos]);
       
   835 						c.Fold();
       
   836 						if (c != character)
       
   837 							{
       
   838 							finished = ETrue;
       
   839 							break;
       
   840 							}
       
   841 						}
       
   842 					}
       
   843 				}
       
   844 				while (!finished);
       
   845 
       
   846 			commonChars.Set(aPossibilities[0].Mid(0, commonCharPos));
       
   847 			}
       
   848 		else
       
   849 			{
       
   850 			commonChars.Set(aPossibilities[0]);
       
   851 			}
       
   852 
       
   853 		completion->AppendL(commonChars);
       
   854 		if (numPossibilities == 1)
       
   855 			{
       
   856 			completion->AppendL(KSpace);
       
   857 			}
       
   858 		if (completion->Descriptor().Length() > 0)
       
   859 			{
       
   860 			aLine.Replace(aPos, completion->Descriptor());
       
   861 			}
       
   862 		CleanupStack::PopAndDestroy(completion);
       
   863 		}
       
   864 	}
       
   865 
       
   866 EXPORT_C void CServerCommandFactory::ListCommandsL(RArray<TPtrC>& aList) const
       
   867 	{
       
   868 	THashMapIter<const TPtrC, const CServerCommandConstructor*> iter(iSubCommands);
       
   869 	while (iter.NextKey())
       
   870 		{
       
   871 		aList.AppendL(*iter.CurrentKey());
       
   872 		}
       
   873 	aList.Sort(TLinearOrder<TPtrC>(PtrOrder));
       
   874 	}
       
   875 
       
   876 
       
   877 
       
   878 //
       
   879 // CBranchCommandBase.
       
   880 //
       
   881 
       
   882 EXPORT_C CBranchCommandBase::~CBranchCommandBase()
       
   883 	{
       
   884 	delete iSubCommandEnum;
       
   885 	delete iSubCommandArgs;
       
   886 	}
       
   887 
       
   888 EXPORT_C CBranchCommandBase::CBranchCommandBase()
       
   889 	{
       
   890 	}
       
   891 
       
   892 EXPORT_C void CBranchCommandBase::DoRunL()
       
   893 	{
       
   894 	TPtrC subCommandName(iArguments.AsString(&iType));
       
   895 
       
   896 	CServerCommandBase* subCommand = Factory().GetSubCommandL(subCommandName).CreateImplementationLC();
       
   897 	ConfigureSubCommand(*subCommand);
       
   898 	subCommand->RunCommand(IoSession(), Stdin(), Stdout(), Stderr(), iSubCommandArgs ? iSubCommandArgs : &KNullDesC, &Env(), NULL);
       
   899 	if (subCommand->IsComplete())
       
   900 		{
       
   901 		HandleSubCommandComplete(*subCommand);
       
   902 		CleanupStack::PopAndDestroy(subCommand);
       
   903 		}
       
   904 	else
       
   905 		{
       
   906 		HandleBackgroundSubCommand(*subCommand);
       
   907 		CleanupStack::Pop(subCommand);
       
   908 		}
       
   909 	}
       
   910 
       
   911 void CBranchCommandBase::BuildEnumL()
       
   912 	{
       
   913 	_LIT(KComma, ",");
       
   914 	RArray<TPtrC> subCommands;
       
   915 	CleanupClosePushL(subCommands);
       
   916 	Factory().ListCommandsL(subCommands);
       
   917 	subCommands.Sort(TLinearOrder<TPtrC>(PtrOrder));
       
   918 	iSubCommandEnum = IoUtils::CTextBuffer::NewL(0x10);
       
   919 	for (TInt i=0; i<subCommands.Count(); ++i)
       
   920 		{
       
   921 		iSubCommandEnum->AppendL(subCommands[i]);
       
   922 		iSubCommandEnum->AppendL(KComma);
       
   923 		}
       
   924 	CleanupStack::PopAndDestroy(&subCommands);
       
   925 	}
       
   926 	
       
   927 EXPORT_C void CBranchCommandBase::ArgumentsL(RCommandArgumentList& aArguments)
       
   928 	{
       
   929 	_LIT(KArgType, "type");
       
   930 	_LIT(KArgArgs, "arguments");
       
   931 
       
   932 	if (!iSubCommandEnum)
       
   933 		{
       
   934 		BuildEnumL();
       
   935 		}
       
   936 
       
   937 	if (UsingCif())
       
   938 		{
       
   939 		aArguments.AppendEnumL((TInt&)iType, KArgType, iSubCommandEnum->Descriptor());
       
   940 		aArguments.AppendStringL(iSubCommandArgs, KArgArgs);
       
   941 		}
       
   942 	else
       
   943 		{
       
   944 		aArguments.AppendEnumL((TInt&)iType, KArgType, TypeDescription(), iSubCommandEnum->Descriptor());
       
   945 
       
   946 		_LIT(KArgArgsDescription, "A set of type-specific arguments and options.");
       
   947 		aArguments.AppendStringL(iSubCommandArgs, KArgArgs, KArgArgsDescription, KValueTypeFlagOptional | KValueTypeFlagLast);
       
   948 		}
       
   949 	}
       
   950 
       
   951 EXPORT_C const TDesC& CBranchCommandBase::TypeDescription()
       
   952 	{
       
   953 	return KNullDesC;
       
   954 	}
       
   955 
       
   956 EXPORT_C void CBranchCommandBase::ConfigureSubCommand(CServerCommandBase&)
       
   957 	{
       
   958 	}
       
   959 
       
   960 EXPORT_C void CBranchCommandBase::HandleSubCommandComplete(CServerCommandBase& aCommand)
       
   961 	{
       
   962 	if (aCommand.CompletionReason() < 0)
       
   963 		{
       
   964 		PrintError(aCommand.CompletionReason(), _L("Couldn't run sub-command \"%S\" of command \"%S\""), &aCommand.Name(), &Name());
       
   965 		}
       
   966 	}
       
   967 
       
   968 EXPORT_C void CBranchCommandBase::HandleBackgroundSubCommand(CServerCommandBase&)
       
   969 	{
       
   970 	}