org.aesh.command.impl.AeshCommandRuntime Maven / Gradle / Ivy
The newest version!
/*
* JBoss, Home of Professional Open Source
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aesh.command.impl;
import org.aesh.command.Command;
import org.aesh.command.CommandException;
import org.aesh.command.CommandNotFoundException;
import org.aesh.command.CommandNotFoundHandler;
import org.aesh.command.CommandResolver;
import org.aesh.command.CommandResult;
import org.aesh.command.CommandRuntime;
import org.aesh.command.Execution;
import org.aesh.command.Executor;
import org.aesh.command.activator.CommandActivatorProvider;
import org.aesh.command.activator.OptionActivatorProvider;
import org.aesh.command.completer.CompleterInvocation;
import org.aesh.command.completer.CompleterInvocationProvider;
import org.aesh.command.container.CommandContainer;
import org.aesh.command.converter.ConverterInvocationProvider;
import org.aesh.command.impl.activator.AeshOptionActivatorProvider;
import org.aesh.command.impl.completer.CompleterData;
import org.aesh.command.impl.completer.FileOptionCompleter;
import org.aesh.command.impl.internal.ProcessedCommand;
import org.aesh.command.impl.internal.ProcessedOption;
import org.aesh.command.impl.invocation.AeshInvocationProviders;
import org.aesh.command.impl.parser.AeshCommandLineCompletionParser;
import org.aesh.command.impl.parser.CommandLineParser;
import org.aesh.command.invocation.CommandInvocation;
import org.aesh.command.invocation.CommandInvocationBuilder;
import org.aesh.command.invocation.CommandInvocationConfiguration;
import org.aesh.command.invocation.CommandInvocationProvider;
import org.aesh.command.invocation.InvocationProviders;
import org.aesh.command.operator.OperatorType;
import org.aesh.command.parser.CommandLineParserException;
import org.aesh.command.registry.CommandRegistry;
import org.aesh.command.validator.CommandValidatorException;
import org.aesh.command.validator.OptionValidatorException;
import org.aesh.command.validator.ValidatorInvocationProvider;
import org.aesh.complete.AeshCompleteOperation;
import org.aesh.parser.LineParser;
import org.aesh.parser.ParsedLine;
import org.aesh.parser.ParserStatus;
import org.aesh.readline.AeshContext;
import java.io.IOException;
import java.util.EnumSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Implementation of the Command processor.
*
* @author [email protected]
*/
public class AeshCommandRuntime
implements CommandRuntime, CommandRegistry.CommandRegistrationListener {
private final CommandRegistry registry;
private final CommandInvocationProvider commandInvocationProvider;
private final InvocationProviders invocationProviders;
private static final Logger LOGGER = Logger.getLogger(AeshCommandRuntime.class.getName());
private final CommandNotFoundHandler commandNotFoundHandler;
private final CommandResolver commandResolver;
private final AeshContext ctx;
private final CommandInvocationBuilder commandInvocationBuilder;
private final boolean parseBrackets;
private final EnumSet operators;
public AeshCommandRuntime(AeshContext ctx,
CommandRegistry registry,
CommandInvocationProvider commandInvocationProvider,
CommandNotFoundHandler commandNotFoundHandler,
CompleterInvocationProvider completerInvocationProvider,
ConverterInvocationProvider converterInvocationProvider,
ValidatorInvocationProvider validatorInvocationProvider,
OptionActivatorProvider optionActivatorProvider,
CommandActivatorProvider commandActivatorProvider,
CommandInvocationBuilder commandInvocationBuilder,
boolean parseBrackets,
EnumSet operators) {
this.ctx = ctx;
this.registry = registry;
commandResolver = new AeshCommandResolver<>(registry);
this.commandInvocationProvider = commandInvocationProvider;
this.commandNotFoundHandler = commandNotFoundHandler;
this.commandInvocationBuilder = commandInvocationBuilder;
this.invocationProviders
= new AeshInvocationProviders(converterInvocationProvider, completerInvocationProvider,
validatorInvocationProvider, optionActivatorProvider, commandActivatorProvider);
processAfterInit();
registry.addRegistrationListener(this);
this.parseBrackets = parseBrackets;
this.operators = operators;
}
@Override
public CommandRegistry getCommandRegistry() {
return registry;
}
@Override
public AeshContext getAeshContext() {
return ctx;
}
@Override
public CommandInvocationBuilder commandInvocationBuilder() {
return commandInvocationBuilder;
}
@Override
public InvocationProviders invocationProviders() {
return invocationProviders;
}
@Override
public CommandResult executeCommand(String line) throws CommandNotFoundException,
CommandLineParserException,
CommandValidatorException,
CommandException,
InterruptedException,
IOException {
Executor executor;
try {
executor = buildExecutor(line);
}
catch (CommandLineParserException e) {
throw e;
} catch (CommandNotFoundException cmd) {
if (commandNotFoundHandler != null) {
commandNotFoundHandler.handleCommandNotFound(line,
commandInvocationBuilder.build(this, null, null).getShell());
}
throw cmd;
}
Execution exec;
CommandResult result = null;
while ((exec = executor.getNextExecution()) != null) {
try {
result = exec.execute();
} catch (CommandException cmd) {
if (exec.getResultHandler() != null) {
exec.getResultHandler().onExecutionFailure(CommandResult.FAILURE, cmd);
}
throw cmd;
} catch (CommandValidatorException | CommandLineParserException e) {
if (exec.getResultHandler() != null) {
exec.getResultHandler().onValidationFailure(CommandResult.FAILURE, e);
}
throw e;
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
if (exec.getResultHandler() != null) {
exec.getResultHandler().onValidationFailure(CommandResult.FAILURE, ex);
}
throw ex;
} catch (Exception e) {
if (exec.getResultHandler() != null) {
exec.getResultHandler().onValidationFailure(CommandResult.FAILURE, e);
}
throw new RuntimeException(e);
}
}
if(result != null)
return result;
else
return CommandResult.FAILURE;
}
@Override
public CommandResult executeCommand(String... lines) throws CommandNotFoundException, CommandLineParserException, OptionValidatorException, CommandValidatorException, CommandException, InterruptedException, IOException {
if(lines == null || lines.length == 0)
throw new CommandException("No input lines");
CommandResult result = null;
for(String line : lines) {
result = executeCommand(line);
if(result == CommandResult.FAILURE)
return result;
}
return result;
}
private void processAfterInit() {
try {
for (String commandName : registry.getAllCommandNames()) {
updateCommand(commandName);
}
} catch (Exception e) {
LOGGER.log(Level.FINER, "Exception while iterating commands.", e);
}
}
private void updateCommand(String commandName) throws CommandNotFoundException {
ProcessedCommand, CI> cmd = registry.getCommand(commandName, "").getParser().getProcessedCommand();
List> childParsers = registry.getChildCommandParsers(commandName);
if (!(invocationProviders.getOptionActivatorProvider() instanceof AeshOptionActivatorProvider)) {
//we have a custom OptionActivatorProvider, and need to process all options
cmd.updateInvocationProviders(invocationProviders);
for (CommandLineParser> child : childParsers) {
child.getProcessedCommand().updateInvocationProviders(invocationProviders);
}
}
}
@Override
public Executor buildExecutor(String line) throws CommandNotFoundException,
CommandLineParserException, IOException {
LOGGER.fine("Command: " + line);
List lines = new LineParser().parseLine(line, -1, parseBrackets, operators);
List> executions = Executions.buildExecution(lines, this);
return new Executor<>(executions);
}
CI buildCommandInvocation(CommandInvocationConfiguration config, CommandContainer commandContainer) {
return commandInvocationProvider.
enhanceCommandInvocation(commandInvocationBuilder.build(this, config, commandContainer));
}
CommandContainer findCommandContainer(ParsedLine aeshLine) throws CommandNotFoundException {
if (aeshLine.words().isEmpty()) {
return null;
}
final String name = aeshLine.firstWord().word();
CommandContainer container =
commandResolver.resolveCommand(name, aeshLine.line());
if (container == null) {
throw new CommandNotFoundException("No command handler for '"+name+ "'.",name);
}
container.addLine(aeshLine);
return container;
}
void populateAskedOption(ProcessedOption option) {
try {
option.injectValueIntoField(option.parent().getCommand(), invocationProviders, getAeshContext(), false);
}
catch(OptionValidatorException e) {
LOGGER.log(Level.WARNING, "Trying to inject value: "+option.getValue()+", into option: "+option.name()+" failed", e);
}
}
@Override
public void registrationAction(String commandName, CommandRegistry.REGISTRATION_ACTION action) {
if (action == CommandRegistry.REGISTRATION_ACTION.ADDED) {
try {
updateCommand(commandName);
} catch (Exception e) {
LOGGER.log(Level.FINER, "Exception while iterating commands.", e);
}
}
}
@Override
public void complete(AeshCompleteOperation completeOperation) {
if(operators.isEmpty())
simpleComplete(completeOperation);
else {
completeWithOperators(completeOperation);
}
}
private void completeWithOperators(AeshCompleteOperation completeOperation) {
List lines = new LineParser()
.input(completeOperation.getBuffer())
.cursor(completeOperation.getCursor())
.parseBrackets(true)
.operators(operators)
.parseWithOperators();
if(!lines.isEmpty()) {
for(int i=0; i < lines.size(); i++) {
if (lines.get(i).cursor() > -1) {
if(i == 0) {
doSimpleComplete(completeOperation, lines.get(i));
return;
}
//we need to check the previous line
//if it is redirect/append out we should use a file completer
else {
if(OperatorType.isAppendOrRedirectInOrOut(lines.get(i-1).operator())) {
//do file completion
FileOptionCompleter completer = new FileOptionCompleter();
CompleterInvocation invocation
= new CompleterData(completeOperation.getContext(),
lines.get(i).selectedWord().word(), null);
completer.complete(invocation);
completeOperation.addCompletionCandidatesTerminalString(invocation.getCompleterValues());
AeshCommandLineCompletionParser.verifyCompleteValue(completeOperation,
invocation,
lines.get(i).selectedWord().word(),
lines.get(i).selectedWord().status(), null);
return;
}
else {
doSimpleComplete(completeOperation, lines.get(i));
return;
}
}
}
}
//we should not end up here, but if we do, use the last line
doSimpleComplete(completeOperation, lines.get(lines.size() - 1));
}
simpleComplete(completeOperation);
}
private void simpleComplete(AeshCompleteOperation completeOperation) {
ParsedLine parsedLine = new LineParser()
.input(completeOperation.getBuffer())
.cursor(completeOperation.getCursor())
.parseBrackets(true)
.parse();
doSimpleComplete(completeOperation, parsedLine);
}
private void doSimpleComplete(AeshCompleteOperation completeOperation, ParsedLine parsedLine) {
if((parsedLine.selectedIndex() == 0 || //possible command name
parsedLine.words().size() == 0) && ParserStatus.okForCompletion(parsedLine.status())) {
commandResolver.getRegistry().completeCommandName(completeOperation, parsedLine);
}
if (completeOperation.getCompletionCandidates().size() < 1) {
try (CommandContainer commandContainer = commandResolver.resolveCommand(parsedLine)) {
commandContainer.getParser()
.complete(completeOperation, parsedLine, invocationProviders);
}
catch (CommandNotFoundException ignored) {
}
catch (Exception ex) {
LOGGER.log(Level.SEVERE, "Runtime exception when completing: "
+ completeOperation, ex);
}
}
}
@Override
protected void finalize() throws Throwable {
registry.removeRegistrationListener(this);
super.finalize();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy