/*
* ProActive Parallel Suite(TM):
* The Open Source library for parallel and distributed
* Workflows & Scheduling, Orchestration, Cloud Automation
* and Big Data Analysis on Enterprise Grids & Clouds.
*
* Copyright (c) 2007 - 2017 ActiveEon
* Contact: contact@activeeon.com
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation: version 3 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* If needed, contact us to obtain a release under GPL Version 2 or 3
* or a different license than the AGPL.
*/
package org.ow2.proactive_grid_cloud_portal.cli.console;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import org.ow2.proactive_grid_cloud_portal.cli.CommandSet;
import jline.console.ConsoleReader;
import jline.console.completer.AggregateCompleter;
import jline.console.completer.ArgumentCompleter;
import jline.console.completer.FileNameCompleter;
import jline.console.history.FileHistory;
public class JLineDevice extends AbstractDevice {
private static final String HFILE = System.getProperty("user.home") + File.separator + ".proactive" +
File.separator + "restcli.hist";
private final FileHistory history;
private ConsoleReader reader;
private PrintWriter writer;
public JLineDevice(InputStream in, PrintStream out) throws IOException {
File hfile = new File(HFILE);
if (!hfile.exists()) {
File parentFile = hfile.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
hfile.createNewFile();
}
writer = new PrintWriter(out, true);
reader = new ConsoleReader(in, out);
history = new FileHistory(hfile);
reader.setHistory(history);
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
writeHistory();
}
}));
}
@Override
public Writer getWriter() {
return writer;
}
private void writeHistory() {
try {
history.flush();
} catch (IOException ignored) {
}
}
private String[] getCommandsAsArray(CommandSet.Entry[] entries) {
List<String> cmds = new ArrayList<>();
for (CommandSet.Entry entry : entries) {
if (entry.jsCommand() != null) {
String jsCommand = entry.jsCommand();
int index = jsCommand.indexOf('(');
if ((jsCommand.indexOf(')') - index) == 1) {
cmds.add(jsCommand.substring(0, index + 2));
} else {
cmds.add(jsCommand.substring(0, index + 1));
}
}
}
return cmds.toArray(new String[cmds.size()]);
}
public void setCommands(CommandSet.Entry[] entries) throws IOException {
AggregateCompleter aggregateCompleter = new AggregateCompleter(new SimpleCompletor(getCommandsAsArray(entries)),
new ClassNameCompletor(),
new FileNameCompleter());
ArgumentCompleter argumentCompleter = new ArgumentCompleter(createArgumentDelimiter(), aggregateCompleter);
argumentCompleter.setStrict(false);
reader.addCompleter(argumentCompleter);
}
private ArgumentCompleter.WhitespaceArgumentDelimiter createArgumentDelimiter() {
return new ArgumentCompleter.WhitespaceArgumentDelimiter() {
@Override
public boolean isDelimiterChar(CharSequence buffer, int pos) {
return super.isDelimiterChar(buffer, pos) || buffer.charAt(pos) == '\'' || buffer.charAt(pos) == '"' ||
buffer.charAt(pos) == '{' || buffer.charAt(pos) == '}' || buffer.charAt(pos) == ',' ||
buffer.charAt(pos) == ';';
}
};
}
@Override
public String readLine(String fmt, Object... args) throws IOException {
return reader.readLine(String.format(fmt, args));
}
@Override
public char[] readPassword(String fmt, Object... args) throws IOException {
// String.format(fmt, args),
return reader.readLine(String.format(fmt, args), new Character('*')).toCharArray();
}
@Override
public void writeLine(String format, Object... args) throws IOException {
writer.println(String.format(format, args));
}
@Override
public int read() throws IOException {
return reader.getInput().read();
}
@Override
public boolean canRead() throws IOException {
return reader.getInput().available() > 0;
}
@Override
public int getHeight() {
return reader.getTerminal().getHeight();
}
@Override
public int getWidth() {
return reader.getTerminal().getWidth();
}
}