From d98c1b88ed01ab9c9ffe8f6cfb164ee03e3a1ce7 Mon Sep 17 00:00:00 2001 From: mertcaliskan Date: Sun, 17 Feb 2019 23:12:12 +0300 Subject: [PATCH] PAYARA-3492-Upgrade-JLine-version-to-v3.x --- nucleus/admin/cli/pom.xml | 2 +- .../sun/enterprise/admin/cli/CLICommand.java | 59 +- .../admin/cli/MultimodeCommand.java | 725 +++++++++--------- .../osgi-cli-interactive/pom.xml | 3 +- .../interactive/LocalOSGiShellCommand.java | 39 +- nucleus/packager/nucleus/pom.xml | 2 +- nucleus/pom.xml | 5 +- 7 files changed, 421 insertions(+), 414 deletions(-) diff --git a/nucleus/admin/cli/pom.xml b/nucleus/admin/cli/pom.xml index 6cc43b33032..66eb49217a7 100755 --- a/nucleus/admin/cli/pom.xml +++ b/nucleus/admin/cli/pom.xml @@ -166,7 +166,7 @@ ${project.version} - jline + org.jline jline diff --git a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/CLICommand.java b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/CLICommand.java index 274dfe04552..1853c6df131 100644 --- a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/CLICommand.java +++ b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/CLICommand.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ -// Portions Copyright [2018] Payara Foundation and/or affiliates +// Portions Copyright [2018-2019] Payara Foundation and/or affiliates package com.sun.enterprise.admin.cli; @@ -46,7 +46,9 @@ import java.lang.annotation.Annotation; import java.util.logging.*; -import jline.console.ConsoleReader; +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; +import org.jline.terminal.TerminalBuilder; import org.jvnet.hk2.annotations.Contract; import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.config.InjectionManager; @@ -912,10 +914,12 @@ protected void prevalidate() throws CommandException { /* * Check for missing options and operands. */ - ConsoleReader cons = null; + LineReader reader = null; if (programOpts.isInteractive()) { try { - cons = new ConsoleReader(System.in, System.out, null); + reader = LineReaderBuilder.builder() + .terminal(TerminalBuilder.builder().streams(System.in, System.out).build()) + .build(); } catch (IOException ioe) { logger.log(Level.WARNING, "Error instantiating console", ioe); } @@ -935,15 +939,10 @@ protected void prevalidate() throws CommandException { continue; } // if option isn't set, prompt for it (if interactive) - if (getOption(opt.getName()) == null && cons != null && !missingOption) { - cons.setPrompt(strings.get("optionPrompt", lc(opt.getName()))); - try { - String val = cons.readLine(); - if (ok(val)) { - options.set(opt.getName(), val); - } - } catch (IOException ioe) { - logger.log(Level.WARNING, "Error reading input", ioe); + if (getOption(opt.getName()) == null && reader != null && !missingOption) { + String val = reader.readLine(strings.get("optionPrompt", lc(opt.getName()))); + if (ok(val)) { + options.set(opt.getName(), val); } } // if it's still not set, that's an error @@ -967,16 +966,11 @@ protected void prevalidate() throws CommandException { operandMax = operandParam.getParam().multiple() ? Integer.MAX_VALUE : 1; } - if (operands.size() < operandMin && cons != null) { - cons.setPrompt(strings.get("operandPrompt", operandParam.getName())); - try { - String val = cons.readLine(); - if (ok(val)) { - operands = new ArrayList(); - operands.add(val); - } - } catch (IOException ioe) { - throw new CommandValidationException("Error reading input", ioe); + if (operands.size() < operandMin && reader != null) { + String val = reader.readLine(strings.get("operandPrompt", operandParam.getName())); + if (ok(val)) { + operands = new ArrayList<>(); + operands.add(val); } } if (operands.size() < operandMin) { @@ -1209,15 +1203,26 @@ private String passwordName(ParamModel opt) { protected char[] readPassword(String prompt) { char[] pc = null; - try (ConsoleReader consoleReader = new ConsoleReader(System.in, System.out, null)) { + LineReader lineReader = null; + try { + lineReader = LineReaderBuilder.builder() + .terminal(TerminalBuilder.builder() + .streams(System.in, System.out).build()).build(); // Don't echo anything when reading - char echoCharacter = 0; - consoleReader.setEchoCharacter(echoCharacter); + lineReader.getTerminal().echo(false); - String line = consoleReader.readLine(prompt); + String line = lineReader.readLine(prompt); pc = line.toCharArray(); } catch (IOException ioe) { logger.log(Level.WARNING, "IOException reading password.", ioe); + } finally { + if (lineReader != null && lineReader.getTerminal() != null) { + try { + lineReader.getTerminal().close(); + } catch (IOException ioe) { + logger.log(Level.WARNING, "IOException reading password.", ioe); + } + } } return pc; diff --git a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/MultimodeCommand.java b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/MultimodeCommand.java index a94e75a9911..1d8f667902a 100644 --- a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/MultimodeCommand.java +++ b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/MultimodeCommand.java @@ -1,365 +1,360 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common Development - * and Distribution License("CDDL") (collectively, the "License"). You - * may not use this file except in compliance with the License. You can - * obtain a copy of the License at - * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html - * or packager/legal/LICENSE.txt. See the License for the specific - * language governing permissions and limitations under the License. - * - * When distributing the software, include this License Header Notice in each - * file and include the License file at packager/legal/LICENSE.txt. - * - * GPL Classpath Exception: - * Oracle designates this particular file as subject to the "Classpath" - * exception as provided by Oracle in the GPL Version 2 section of the License - * file that accompanied this code. - * - * Modifications: - * If applicable, add the following below the License Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * "Portions Copyright [year] [name of copyright owner]" - * - * Contributor(s): - * If you wish your version of this file to be governed by only the CDDL or - * only the GPL Version 2, indicate your decision by adding "[Contributor] - * elects to include this software in this distribution under the [CDDL or GPL - * Version 2] license." If you don't indicate a single choice of license, a - * recipient has the option to distribute your version of this file under - * either the CDDL, the GPL Version 2 or to extend the choice of license to - * its licensees as provided above. However, if you add GPL Version 2 code - * and therefore, elected the GPL Version 2 license, then the option applies - * only if the new code is made subject to such option by the copyright - * holder. - */ -// Portions Copyright [2018] Payara Foundation and/or affiliates - -package com.sun.enterprise.admin.cli; - -import static com.sun.enterprise.admin.cli.CLICommand.ERROR; -import java.io.*; -import java.util.*; - -import org.jvnet.hk2.annotations.Service; -import org.glassfish.api.Param; -import org.glassfish.api.admin.*; -import org.glassfish.api.admin.CommandModel.ParamModel; -import org.glassfish.hk2.api.ActiveDescriptor; -import org.glassfish.hk2.api.DynamicConfiguration; -import org.glassfish.hk2.api.DynamicConfigurationService; -import org.glassfish.hk2.api.PerLookup; -import org.glassfish.hk2.api.ServiceLocator; -import org.glassfish.hk2.utilities.BuilderHelper; - -import com.sun.enterprise.admin.util.*; -import com.sun.enterprise.universal.i18n.LocalStringsImpl; -import java.util.logging.Level; - -import javax.inject.Inject; -import jline.console.ConsoleReader; -import jline.console.completer.Completer; -import jline.console.completer.StringsCompleter; - -/** - * A scaled-down implementation of multi-mode command. - * - * @author केदार(km@dev.java.net) - * @author Bill Shannon - */ -@Service(name = "multimode") -@PerLookup -public class MultimodeCommand extends CLICommand { - - @Inject - private ServiceLocator habitat; - @Inject - private CLIContainer container; - @Param(optional = true, shortName = "f") - private File file; - @Param(name = "printprompt", optional = true) - private Boolean printPromptOpt; - private boolean printPrompt; - @Param(optional = true) - private String encoding; - private boolean echo; // saved echo flag - private static final LocalStringsImpl strings = new LocalStringsImpl(MultimodeCommand.class); - - private static final String ASADMIN = "asadmin"; - - /** - * The validate method validates that the type and quantity of parameters - * and operands matches the requirements for this command. The validate - * method supplies missing options from the environment. - * @throws CommandException - * @throws CommandValidationException - */ - @Override - protected void validate() throws CommandException, CommandValidationException { - if (printPromptOpt != null) { - printPrompt = printPromptOpt; - } else { - printPrompt = programOpts.isInteractive(); - } - /* - * Save value of --echo because CLICommand will reset it - * before calling our executeCommand method but we want it - * to also apply to all commands in multimode. - */ - echo = programOpts.isEcho(); - } - - /** - * In the usage message modify the --printprompt option to have a default - * based on the --interactive option. - * @return - */ - @Override - protected Collection usageOptions() { - Collection opts = commandModel.getParameters(); - Set uopts = new LinkedHashSet(); - ParamModel p = new CommandModelData.ParamModelData("printprompt", boolean.class, true, Boolean.toString(programOpts.isInteractive())); - for (ParamModel pm : opts) { - if (pm.getName().equals("printprompt")) { - uopts.add(p); - } else { - uopts.add(pm); - } - } - return uopts; - } - - @Override - protected int executeCommand() throws CommandException, CommandValidationException { - ConsoleReader reader = null; - programOpts.setEcho(echo); // restore echo flag, saved in validate - try { - checkToDisableJLineLogging(); - if (file == null) { - System.out.println(strings.get("multimodeIntro")); - reader = new ConsoleReader(ASADMIN, System.in, System.out, null, encoding); - } else { - printPrompt = false; - if (!file.canRead()) { - throw new CommandException("File: " + file + " can not be read"); - } - OutputStream out = new OutputStream() { - - @Override - public void write(int b) throws IOException { - return; - } - - @Override - public void write(byte[] b) throws IOException { - return; - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - return; - } - }; - reader = new ConsoleReader(ASADMIN, new FileInputStream(file), out, null, encoding); - } - - reader.setBellEnabled(false); - reader.addCompleter(getAllCommandsCompleter()); - - return executeCommands(reader); - } - catch (IOException e) { - throw new CommandException(e); - } - finally { - try { - if (file != null && reader != null) - reader.close(); - } - catch (Exception e) { - // ignore it - } - } - } - - private static void checkToDisableJLineLogging(){ - if (Boolean.getBoolean("fish.payara.admin.command.jline.log.disable")) { - System.setProperty("jline.log.jul", "false"); - final OutputStream noOpOutputStream = new OutputStream() { - @Override - public void write(int b) throws IOException { - //NO-OP - } - }; - jline.internal.Log.setOutput(new PrintStream(noOpOutputStream)); - } - } - - private static void atomicReplace(ServiceLocator locator, ProgramOptions options) { - DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class); - DynamicConfiguration config = dcs.createDynamicConfiguration(); - - config.addUnbindFilter(BuilderHelper.createContractFilter(ProgramOptions.class.getName())); - ActiveDescriptor desc = BuilderHelper.createConstantDescriptor(options, null, ProgramOptions.class); - config.addActiveDescriptor(desc); - - config.commit(); - } - - /** - * Read commands from the specified BufferedReader and execute them. If - * printPrompt is set, prompt first. - * - * @return the exit code of the last command executed - */ - private int executeCommands(ConsoleReader reader) throws CommandException, CommandValidationException, IOException { - String line = null; - int rc = 0; - - /* - * Any program options we start with are copied to the environment - * to serve as defaults for commands we run, and then we give each - * command an empty program options. - */ - programOpts.toEnvironment(env); - String prompt = programOpts.getCommandName() + "> "; - for (;;) { - if (printPrompt) { - line = reader.readLine(prompt); - } else { - line = reader.readLine(); - } - if (line == null) { - if (printPrompt) - System.out.println(); - break; - } - - if (line.trim().startsWith("#")){ // ignore comment lines - continue; - } - - String[] args; - try { - args = getArgs(line); - } catch (ArgumentTokenizer.ArgumentException ex) { - logger.info(ex.getMessage()); - continue; - } - - if (args.length == 0) { - continue; - } - - String command = args[0]; - if (command.length() == 0) { - continue; - } - - // handle built-in exit and quit commands - // XXX - care about their arguments? - if (command.equals("exit") || command.equals("quit")){ - break; - } - - CLICommand cmd = null; - ProgramOptions po = null; - try { - /* - * Every command gets its own copy of program options - * so that any program options specified in its - * command line options don't effect other commands. - * But all commands share the same environment. - */ - po = new ProgramOptions(env); - // copy over AsadminMain info - po.setClassPath(programOpts.getClassPath()); - po.setClassName(programOpts.getClassName()); - po.setCommandName(programOpts.getCommandName()); - // remove the old one and replace it - atomicReplace(habitat, po); - - cmd = CLICommand.getCommand(habitat, command); - rc = cmd.execute(args); - } - catch (CommandValidationException cve) { - logger.severe(cve.getMessage()); - if (cmd != null) { - logger.severe(cmd.getUsage()); - } - rc = ERROR; - } - catch (InvalidCommandException ice) { - // find closest match with local or remote commands - logger.severe(ice.getMessage()); - try { - if(po != null) // many layers below, null WILL be de-referenced. - CLIUtil.displayClosestMatch(command, - CLIUtil.getAllCommands(container, po, env), - strings.get("ClosestMatchedLocalAndRemoteCommands"), logger); - } - catch (InvalidCommandException e) { - // not a big deal if we cannot help - } - rc = ERROR; - } - catch (CommandException ce) { - if (ce.getCause() instanceof java.net.ConnectException) { - // find closest match with local commands - logger.severe(ce.getMessage()); - try { - CLIUtil.displayClosestMatch(command, - CLIUtil.getLocalCommands(container), - strings.get("ClosestMatchedLocalCommands"), logger); - } - catch (InvalidCommandException e) { - logger.info(strings.get("InvalidRemoteCommand", command)); - } - } else { - logger.severe(ce.getMessage()); - } - rc = ERROR; - } finally { - // restore the original program options - // XXX - is this necessary? - atomicReplace(habitat, programOpts); - } - - // XXX - this duplicates code in AsadminMain, refactor it - switch (rc) { - case SUCCESS: - if (!programOpts.isTerse()) - logger.log(Level.FINE, strings.get("CommandSuccessful", command)); - break; - - case ERROR: - case INVALID_COMMAND_ERROR: - case CONNECTION_ERROR: - default: - logger.log(Level.FINE, strings.get("CommandUnSuccessful", command)); - break; - } - CLIUtil.writeCommandToDebugLog(programOpts.getCommandName() + "[multimode]", env, args, rc); - } - return rc; - } - - private String[] getArgs(String line) throws ArgumentTokenizer.ArgumentException { - - List args = new ArrayList(); - ArgumentTokenizer t = new ArgumentTokenizer(line); - while (t.hasMoreTokens()) { - args.add(t.nextToken()); - } - return args.toArray(new String[args.size()]); - } - - private Completer getAllCommandsCompleter(){ - return new StringsCompleter(CLIUtil.getAllCommands(container, programOpts, env)); - - } -} +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +// Portions Copyright [2018-2019] Payara Foundation and/or affiliates + +package com.sun.enterprise.admin.cli; + +import java.io.*; +import java.util.*; + +import org.jline.reader.Completer; +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; +import org.jline.reader.impl.completer.StringsCompleter; +import org.jline.terminal.TerminalBuilder; +import org.jvnet.hk2.annotations.Service; +import org.glassfish.api.Param; +import org.glassfish.api.admin.*; +import org.glassfish.api.admin.CommandModel.ParamModel; +import org.glassfish.hk2.api.ActiveDescriptor; +import org.glassfish.hk2.api.DynamicConfiguration; +import org.glassfish.hk2.api.DynamicConfigurationService; +import org.glassfish.hk2.api.PerLookup; +import org.glassfish.hk2.api.ServiceLocator; +import org.glassfish.hk2.utilities.BuilderHelper; + +import com.sun.enterprise.admin.util.*; +import com.sun.enterprise.universal.i18n.LocalStringsImpl; +import java.util.logging.Level; + +import javax.inject.Inject; + +/** + * A scaled-down implementation of multi-mode command. + * + * @author केदार(km@dev.java.net) + * @author Bill Shannon + */ +@Service(name = "multimode") +@PerLookup +public class MultimodeCommand extends CLICommand { + + @Inject + private ServiceLocator habitat; + @Inject + private CLIContainer container; + @Param(optional = true, shortName = "f") + private File file; + @Param(name = "printprompt", optional = true) + private Boolean printPromptOpt; + private boolean printPrompt; + @Param(optional = true) + private String encoding; + private boolean echo; // saved echo flag + private static final LocalStringsImpl strings = new LocalStringsImpl(MultimodeCommand.class); + + private static final String ASADMIN = "asadmin"; + + /** + * The validate method validates that the type and quantity of parameters + * and operands matches the requirements for this command. The validate + * method supplies missing options from the environment. + * @throws CommandException + * @throws CommandValidationException + */ + @Override + protected void validate() throws CommandException, CommandValidationException { + if (printPromptOpt != null) { + printPrompt = printPromptOpt; + } else { + printPrompt = programOpts.isInteractive(); + } + /* + * Save value of --echo because CLICommand will reset it + * before calling our executeCommand method but we want it + * to also apply to all commands in multimode. + */ + echo = programOpts.isEcho(); + } + + /** + * In the usage message modify the --printprompt option to have a default + * based on the --interactive option. + * @return + */ + @Override + protected Collection usageOptions() { + Collection opts = commandModel.getParameters(); + Set uopts = new LinkedHashSet(); + ParamModel p = new CommandModelData.ParamModelData("printprompt", boolean.class, true, Boolean.toString(programOpts.isInteractive())); + for (ParamModel pm : opts) { + if (pm.getName().equals("printprompt")) { + uopts.add(p); + } else { + uopts.add(pm); + } + } + return uopts; + } + + @Override + protected int executeCommand() throws CommandException, CommandValidationException { + LineReader reader = null; + programOpts.setEcho(echo); // restore echo flag, saved in validate + try { + if (file == null) { + System.out.println(strings.get("multimodeIntro")); + + reader = LineReaderBuilder.builder() + .terminal(TerminalBuilder.builder() + .streams(System.in, System.out).encoding(encoding).build()) + .appName(ASADMIN) + .build(); + } else { + printPrompt = false; + if (!file.canRead()) { + throw new CommandException("File: " + file + " can not be read"); + } + OutputStream out = new OutputStream() { + + @Override + public void write(int b) throws IOException { + return; + } + + @Override + public void write(byte[] b) throws IOException { + return; + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + return; + } + }; + + reader = LineReaderBuilder.builder() + .completer(getAllCommandsCompleter()) + .terminal(TerminalBuilder.builder().encoding(encoding) + .streams(new FileInputStream(file), out).build()) + .appName(ASADMIN) + .build(); + } + + return executeCommands(reader); + } + catch (IOException e) { + throw new CommandException(e); + } + finally { + try { + if (file != null && reader != null && reader.getTerminal() != null) + reader.getTerminal().close(); + } + catch (Exception e) { + // ignore it + } + } + } + + private static void atomicReplace(ServiceLocator locator, ProgramOptions options) { + DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class); + DynamicConfiguration config = dcs.createDynamicConfiguration(); + + config.addUnbindFilter(BuilderHelper.createContractFilter(ProgramOptions.class.getName())); + ActiveDescriptor desc = BuilderHelper.createConstantDescriptor(options, null, ProgramOptions.class); + config.addActiveDescriptor(desc); + + config.commit(); + } + + /** + * Read commands from the specified BufferedReader and execute them. If + * printPrompt is set, prompt first. + * + * @return the exit code of the last command executed + */ + private int executeCommands(LineReader reader) throws IOException { + String line; + int rc = 0; + + /* + * Any program options we start with are copied to the environment + * to serve as defaults for commands we run, and then we give each + * command an empty program options. + */ + programOpts.toEnvironment(env); + String prompt = programOpts.getCommandName() + "> "; + for (;;) { + if (printPrompt) { + line = reader.readLine(prompt); + } else { + line = reader.readLine(); + } + if (line == null) { + if (printPrompt) + System.out.println(); + break; + } + + if (line.trim().startsWith("#")){ // ignore comment lines + continue; + } + + String[] args; + try { + args = getArgs(line); + } catch (ArgumentTokenizer.ArgumentException ex) { + logger.info(ex.getMessage()); + continue; + } + + if (args.length == 0) { + continue; + } + + String command = args[0]; + if (command.length() == 0) { + continue; + } + + // handle built-in exit and quit commands + // XXX - care about their arguments? + if (command.equals("exit") || command.equals("quit")){ + break; + } + + CLICommand cmd = null; + ProgramOptions po = null; + try { + /* + * Every command gets its own copy of program options + * so that any program options specified in its + * command line options don't effect other commands. + * But all commands share the same environment. + */ + po = new ProgramOptions(env); + // copy over AsadminMain info + po.setClassPath(programOpts.getClassPath()); + po.setClassName(programOpts.getClassName()); + po.setCommandName(programOpts.getCommandName()); + // remove the old one and replace it + atomicReplace(habitat, po); + + cmd = CLICommand.getCommand(habitat, command); + rc = cmd.execute(args); + } + catch (CommandValidationException cve) { + logger.severe(cve.getMessage()); + if (cmd != null) { + logger.severe(cmd.getUsage()); + } + rc = ERROR; + } + catch (InvalidCommandException ice) { + // find closest match with local or remote commands + logger.severe(ice.getMessage()); + try { + if(po != null) // many layers below, null WILL be de-referenced. + CLIUtil.displayClosestMatch(command, + CLIUtil.getAllCommands(container, po, env), + strings.get("ClosestMatchedLocalAndRemoteCommands"), logger); + } + catch (InvalidCommandException e) { + // not a big deal if we cannot help + } + rc = ERROR; + } + catch (CommandException ce) { + if (ce.getCause() instanceof java.net.ConnectException) { + // find closest match with local commands + logger.severe(ce.getMessage()); + try { + CLIUtil.displayClosestMatch(command, + CLIUtil.getLocalCommands(container), + strings.get("ClosestMatchedLocalCommands"), logger); + } + catch (InvalidCommandException e) { + logger.info(strings.get("InvalidRemoteCommand", command)); + } + } else { + logger.severe(ce.getMessage()); + } + rc = ERROR; + } finally { + // restore the original program options + // XXX - is this necessary? + atomicReplace(habitat, programOpts); + } + + // XXX - this duplicates code in AsadminMain, refactor it + switch (rc) { + case SUCCESS: + if (!programOpts.isTerse()) + logger.log(Level.FINE, strings.get("CommandSuccessful", command)); + break; + + case ERROR: + case INVALID_COMMAND_ERROR: + case CONNECTION_ERROR: + default: + logger.log(Level.FINE, strings.get("CommandUnSuccessful", command)); + break; + } + CLIUtil.writeCommandToDebugLog(programOpts.getCommandName() + "[multimode]", env, args, rc); + } + return rc; + } + + private String[] getArgs(String line) throws ArgumentTokenizer.ArgumentException { + + List args = new ArrayList(); + ArgumentTokenizer t = new ArgumentTokenizer(line); + while (t.hasMoreTokens()) { + args.add(t.nextToken()); + } + return args.toArray(new String[args.size()]); + } + + private Completer getAllCommandsCompleter(){ + return new StringsCompleter(CLIUtil.getAllCommands(container, programOpts, env)); + + } +} diff --git a/nucleus/osgi-platforms/osgi-cli-interactive/pom.xml b/nucleus/osgi-platforms/osgi-cli-interactive/pom.xml index 1633c4746dd..c2da771c69e 100644 --- a/nucleus/osgi-platforms/osgi-cli-interactive/pom.xml +++ b/nucleus/osgi-platforms/osgi-cli-interactive/pom.xml @@ -41,6 +41,7 @@ Portions Copyright [2019] [Payara Foundation and/or its affiliates] --> + 4.0.0 @@ -77,7 +78,7 @@ ${project.version} - jline + org.jline jline diff --git a/nucleus/osgi-platforms/osgi-cli-interactive/src/main/java/org/glassfish/osgi/cli/interactive/LocalOSGiShellCommand.java b/nucleus/osgi-platforms/osgi-cli-interactive/src/main/java/org/glassfish/osgi/cli/interactive/LocalOSGiShellCommand.java index bc19efeaa89..50026450066 100644 --- a/nucleus/osgi-platforms/osgi-cli-interactive/src/main/java/org/glassfish/osgi/cli/interactive/LocalOSGiShellCommand.java +++ b/nucleus/osgi-platforms/osgi-cli-interactive/src/main/java/org/glassfish/osgi/cli/interactive/LocalOSGiShellCommand.java @@ -37,6 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ +// Portions Copyright [2019] Payara Foundation and/or affiliates package org.glassfish.osgi.cli.interactive; @@ -60,10 +61,6 @@ import java.util.List; import java.util.Set; import javax.inject.Inject; -import jline.console.ConsoleReader; -import jline.console.completer.Completer; -import jline.console.completer.NullCompleter; -import jline.console.completer.StringsCompleter; import org.glassfish.api.I18n; import org.glassfish.api.Param; import org.glassfish.api.admin.CommandException; @@ -76,6 +73,13 @@ import org.glassfish.hk2.api.PerLookup; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.hk2.utilities.BuilderHelper; +import org.jline.reader.Completer; +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; +import org.jline.reader.impl.completer.NullCompleter; +import org.jline.reader.impl.completer.StringsCompleter; +import org.jline.terminal.Terminal; +import org.jline.terminal.TerminalBuilder; import org.jvnet.hk2.annotations.Service; /** @@ -225,9 +229,8 @@ protected Collection usageOptions() { } @Override - protected int executeCommand() - throws CommandException, CommandValidationException { - ConsoleReader reader = null; + protected int executeCommand() throws CommandException { + LineReader reader; if(cmd == null) { throw new CommandException("Remote command 'osgi' is not available."); @@ -247,9 +250,11 @@ protected int executeCommand() if (file == null) { System.out.println(strings.get("multimodeIntro")); - reader = new ConsoleReader(REMOTE_COMMAND, - new FileInputStream(FileDescriptor.in), System.out, - null); + reader = LineReaderBuilder.builder() + .terminal(TerminalBuilder.builder() + .streams(new FileInputStream(FileDescriptor.in), System.out).build()) + .appName(REMOTE_COMMAND) + .build(); } else { printPrompt = false; if (!file.canRead()) { @@ -275,14 +280,14 @@ public void write(byte[] b, int off, int len) throws IOException { } }; - reader = new ConsoleReader(REMOTE_COMMAND, - new FileInputStream(file), out, - null); + Terminal terminal = TerminalBuilder.builder().streams(new FileInputStream(file), out).build(); + reader = LineReaderBuilder.builder() + .completer(getCommandCompleter()) + .terminal(terminal) + .appName(REMOTE_COMMAND) + .build(); } - reader.setBellEnabled(false); - reader.addCompleter(getCommandCompleter()); - return executeCommands(reader); } catch (IOException e) { throw new CommandException(e); @@ -376,7 +381,7 @@ private Completer getCommandCompleter() { * * @return the exit code of the last command executed */ - private int executeCommands(ConsoleReader reader) + private int executeCommands(LineReader reader) throws CommandException, CommandValidationException, IOException { String line = null; int rc = 0; diff --git a/nucleus/packager/nucleus/pom.xml b/nucleus/packager/nucleus/pom.xml index 2113c9a9084..7b631bd1c7c 100644 --- a/nucleus/packager/nucleus/pom.xml +++ b/nucleus/packager/nucleus/pom.xml @@ -247,7 +247,7 @@ true - jline + org.jline jline true diff --git a/nucleus/pom.xml b/nucleus/pom.xml index b18bfb51010..2b391f31b43 100644 --- a/nucleus/pom.xml +++ b/nucleus/pom.xml @@ -326,6 +326,7 @@ 0.31.0 + 3.10.0 6.0.1 @@ -1348,9 +1349,9 @@ Parent is ${project.parent} - jline + org.jline jline - 2.14.6 + ${jline.version} org.fusesource.hawtjni