/*
* Copyright (C) 2012 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.crsh.web.servlet;
import org.crsh.keyboard.KeyHandler;
import org.crsh.keyboard.KeyType;
import org.crsh.shell.ShellProcess;
import org.crsh.shell.ShellProcessContext;
import org.crsh.shell.ShellResponse;
import org.crsh.text.Color;
import org.crsh.text.Screenable;
import org.crsh.text.Style;
import org.crsh.util.Utils;
import java.io.IOException;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.logging.Level;
/** @author Julien Viet */
public class WSProcessContext implements ShellProcessContext, KeyHandler {
/** . */
final ShellProcess process;
/** . */
final CRaSHSession session;
/** . */
private StringBuilder buffer = new StringBuilder();
/** . */
final int width;
/** . */
final int height;
/** . */
final String command;
public WSProcessContext(CRaSHSession session, ShellProcess process, String command, int width, int height) {
this.session = session;
this.process = process;
this.width = width;
this.height = height;
this.command = command;
}
@Override
public void handle(KeyType type, int[] sequence) {
KeyHandler keyHandler = process.getKeyHandler();
if (keyHandler != null) {
CRaSHConnector.log.fine("Processing key event " + type + " " + Arrays.toString(sequence));
try {
keyHandler.handle(type, sequence);
}
catch (Exception e) {
CRaSHConnector.log.log(Level.SEVERE, "Processing key handler " + keyHandler + " threw an exception", e);
}
}
}
public void end(ShellResponse response) {
CRaSHConnector.log.fine("Ended \"" + command + "\"");
session.current.compareAndSet(this, null);
flush();
String msg = response.getMessage();
if (msg.length() > 0) {
session.send("print", msg);
}
String prompt = session.shell.getPrompt();
session.send("prompt", prompt);
session.send("end");
}
public boolean takeAlternateBuffer() throws IOException {
return false;
}
public boolean releaseAlternateBuffer() throws IOException {
return false;
}
public String getProperty(String propertyName) {
return null;
}
public String readLine(String msg, boolean echo) {
return null;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
private static final EnumMap<Color, String> COLOR_MAP = new EnumMap<Color, String>(Color.class);
static {
COLOR_MAP.put(Color.black, "#000");
COLOR_MAP.put(Color.blue, "#0000AA");
COLOR_MAP.put(Color.cyan, "#00AAAA");
COLOR_MAP.put(Color.green, "#00AA00");
COLOR_MAP.put(Color.magenta, "#AA00AA");
COLOR_MAP.put(Color.white, "#AAAAAA");
COLOR_MAP.put(Color.yellow, "#AAAA00");
COLOR_MAP.put(Color.red, "#AA0000");
}
/** . */
private Style style = Style.reset;
@Override
public Appendable append(char c) throws IOException {
return append(Character.toString(c));
}
@Override
public Appendable append(CharSequence s) throws IOException {
return append(s, 0, s.length());
}
@Override
public Appendable append(CharSequence csq, int start, int end) throws IOException {
if (start < end) {
if (style.equals(Style.reset)) {
buffer.append(csq, start, end);
} else {
Style.Composite composite = (Style.Composite)style;
buffer.append("[[");
if (composite.getUnderline() == Boolean.TRUE) {
buffer.append('u');
}
if (composite.getBold() == Boolean.TRUE) {
buffer.append('b');
}
buffer.append(';');
if (composite.getForeground() != null) {
buffer.append(COLOR_MAP.get(composite.getForeground()));
}
buffer.append(';');
if (composite.getBackground() != null) {
buffer.append(COLOR_MAP.get(composite.getBackground()));
}
buffer.append(']');
while (start < end) {
char c = csq.charAt(start++);
if (c == ']') {
buffer.append("\\]");
} else {
buffer.append(c);
}
}
buffer.append(']');
}
}
return this;
}
@Override
public Screenable append(Style style) throws IOException {
this.style = style.merge(style);
return this;
}
@Override
public Screenable cls() throws IOException {
buffer.append("\033[");
buffer.append("2J");
buffer.append("\033[");
buffer.append("1;1H");
return this;
}
public void flush() {
if (buffer.length() > 0) {
session.send("print", buffer.toString());
buffer.setLength(0);
}
}
}