com.fluxtion.server.plugin.adminconsole.TelnetAdminCommandProcessor Maven / Gradle / Ivy
/*
* SPDX-FileCopyrightText: © 2024 Gregory Higgins
* SPDX-License-Identifier: AGPL-3.0-only
*/
package com.fluxtion.server.plugin.adminconsole;
import com.fluxtion.runtime.annotations.runtime.ServiceRegistered;
import com.fluxtion.runtime.lifecycle.Lifecycle;
import com.fluxtion.server.service.admin.AdminCommandRegistry;
import com.fluxtion.server.service.admin.AdminCommandRequest;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
import org.jline.builtins.telnet.Telnet;
import org.jline.reader.Candidate;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.jline.utils.AttributedString;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Log4j2
public class TelnetAdminCommandProcessor implements Lifecycle {
private AdminCommandRegistry adminCommandRegistry;
@Getter
@Setter
private int listenPort = 2019;
private Telnet telnet;
public TelnetAdminCommandProcessor(int listenPort) {
this.listenPort = listenPort;
}
public TelnetAdminCommandProcessor() {
}
@ServiceRegistered
public void adminRegistry(AdminCommandRegistry adminCommandRegistry, String name) {
log.info("Admin registry: '{}' name: '{}'", adminCommandRegistry, name);
this.adminCommandRegistry = adminCommandRegistry;
}
@Override
public void init() {
}
@Override
public void start() {
try {
log.info("Starting Jline admin command service port: {}", listenPort);
Terminal terminal = TerminalBuilder.terminal();
telnet = new Telnet(terminal, this::shell);
telnet.telnetd(new String[]{"telnetd", "-i127.0.0.1", "-p" + listenPort, "start"});
} catch (Exception e) {
log.error("problem starting Jline admin command service", e);
}
}
@Override
public void tearDown() {
try {
log.info("Stopping Jline admin command service port: {}", listenPort);
telnet.telnetd(new String[]{"stop"});
} catch (Exception e) {
log.error("problem stopping Jline admin command service", e);
}
}
private void shell(Terminal terminal, Map environment) {
try {
LineReader reader = LineReaderBuilder.builder()
.terminal(terminal)
.completer((reader1, line, candidates) -> {
for (String string : adminCommandRegistry.commandList()) {
candidates.add(new Candidate(AttributedString.stripAnsi(string), string, null, null, null, null, true));
}
candidates.add(new Candidate(AttributedString.stripAnsi("quit"), "quit", null, null, null, null, true));
})
.build();
processCommand(terminal, new String[]{"?"});
processCommand(terminal, new String[]{"commands"});
while (true) {
String line = reader.readLine("command > ").trim();
if (line == null || line.equalsIgnoreCase("quit")) {
break;
}
String[] commandArgs = line.trim().split("\\s+");
if (commandArgs.length > 0) {
reader.getHistory().add(line);
processCommand(terminal, commandArgs);
}
}
} catch (Exception e) {
log.error("problem executing shell", e);
}
}
private void processCommand(Terminal terminal, String[] commandArgs) {
AdminCommandRequest adminCommandRequest = new AdminCommandRequest();
List commandArgsList = new ArrayList<>(Arrays.asList(commandArgs));
commandArgsList.remove(0);
adminCommandRequest.setCommand(commandArgs[0]);
adminCommandRequest.setArguments(commandArgsList);
adminCommandRequest.setOutput(terminal.writer()::println);
adminCommandRequest.setErrOutput(terminal.writer()::println);
log.info("adminCommandRequest: " + adminCommandRequest);
if (adminCommandRegistry != null) {
adminCommandRegistry.processAdminCommandRequest(adminCommandRequest);
}
}
}