You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2012/06/01 16:37:55 UTC
svn commit: r1345205 - in /felix/trunk/webconsole-plugins/gogo: ./
src/main/appended-resources/META-INF/
src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/
src/main/resources/res/ui/
Author: fmeschbe
Date: Fri Jun 1 14:37:54 2012
New Revision: 1345205
URL: http://svn.apache.org/viewvc?rev=1345205&view=rev
Log:
FELIX-3530 Replace JLine with adapted AjaxTerm
Added:
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/SessionTerminal.java
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/SessionTerminalManager.java
Removed:
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/AggregateCompleter.java
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/CloseShellException.java
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/CommandSessionHolder.java
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/CommandsCompleter.java
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/NameScoping.java
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Parser.java
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/StringsCompleter.java
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/WebTerminal.java
Modified:
felix/trunk/webconsole-plugins/gogo/pom.xml
felix/trunk/webconsole-plugins/gogo/src/main/appended-resources/META-INF/DEPENDENCIES
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Activator.java
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Console.java
felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/GogoPlugin.java
felix/trunk/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.js
Modified: felix/trunk/webconsole-plugins/gogo/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/gogo/pom.xml?rev=1345205&r1=1345204&r2=1345205&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/gogo/pom.xml (original)
+++ felix/trunk/webconsole-plugins/gogo/pom.xml Fri Jun 1 14:37:54 2012
@@ -78,19 +78,6 @@
<Bundle-Activator>
org.apache.felix.webconsole.plugins.gogo.impl.Activator
</Bundle-Activator>
- <Embed-Dependency>
- jline;inline=true
- </Embed-Dependency>
- <Bundle-NativeCode>
- META-INF/native/windows32/jansi.dll;osname=Win32;processor=x86,
- META-INF/native/windows64/jansi.dll;osname=Win32;processor=x86-64,
- <!--
- META-INF/native/linux32/libjansi.so;osname=Linux;processor=x86,
- META-INF/native/linux64/libjansi.so;osname=Linux;processor=x86-64,
- META-INF/native/osx/libjansi.jnilib;osname=MacOSX,
- -->
- *
- </Bundle-NativeCode>
</instructions>
</configuration>
</plugin>
@@ -128,11 +115,5 @@
<version>2.3</version>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.sonatype.jline</groupId>
- <artifactId>jline</artifactId>
- <version>2.5</version>
- <scope>provided</scope>
- </dependency>
</dependencies>
</project>
Modified: felix/trunk/webconsole-plugins/gogo/src/main/appended-resources/META-INF/DEPENDENCIES
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/gogo/src/main/appended-resources/META-INF/DEPENDENCIES?rev=1345205&r1=1345204&r2=1345205&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/gogo/src/main/appended-resources/META-INF/DEPENDENCIES (original)
+++ felix/trunk/webconsole-plugins/gogo/src/main/appended-resources/META-INF/DEPENDENCIES Fri Jun 1 14:37:54 2012
@@ -5,10 +5,9 @@ This product includes software developed
The Apache Software Foundation (http://www.apache.org/).
Licensed under the Apache License 2.0.
-This product includes software from https://github.com/jline/jline2
-Copyright (c) 2002-2006, Marc Prud'hommeaux <mw...@cornell.edu>
-All rights reserved.
-Licensed under the BSD License
+This product includes files derived from Ajaxterm
+http://antony.lesuisse.org/software/ajaxterm/
+Ajaxterm files are released in the Public Domain
This plugin draws from Apache Karaf Console and Web Console bundles.
Kudos!
Modified: felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Activator.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Activator.java?rev=1345205&r1=1345204&r2=1345205&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Activator.java (original)
+++ felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Activator.java Fri Jun 1 14:37:54 2012
@@ -18,18 +18,18 @@
*/
package org.apache.felix.webconsole.plugins.gogo.impl;
-import org.fusesource.jansi.AnsiConsole;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
+ private SessionTerminalManager terminalManager;
+
private GogoPlugin plugin;
public void start(BundleContext context) throws Exception {
- AnsiConsole.systemInstall();
-
- this.plugin = new GogoPlugin();
+ this.terminalManager = new SessionTerminalManager(context);
+ this.plugin = new GogoPlugin(this.terminalManager);
this.plugin.register(context);
}
@@ -38,8 +38,10 @@ public class Activator implements Bundle
this.plugin.unregister();
this.plugin = null;
}
-
- AnsiConsole.systemUninstall();
+ if (this.terminalManager != null) {
+ this.terminalManager.shutdown();
+ this.terminalManager = null;
+ }
}
}
Modified: felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Console.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Console.java?rev=1345205&r1=1345204&r2=1345205&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Console.java (original)
+++ felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/Console.java Fri Jun 1 14:37:54 2012
@@ -18,52 +18,24 @@
*/
package org.apache.felix.webconsole.plugins.gogo.impl;
-import java.io.CharArrayWriter;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.io.Reader;
import java.util.Map;
-import java.util.Properties;
+import java.util.Map.Entry;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import jline.Terminal;
-import jline.UnsupportedTerminal;
-import jline.console.ConsoleReader;
-import jline.console.completer.Completer;
-import jline.console.history.PersistentHistory;
import org.apache.felix.service.command.CommandProcessor;
import org.apache.felix.service.command.CommandSession;
-import org.apache.felix.service.command.Converter;
-import org.fusesource.jansi.Ansi;
public class Console implements Runnable {
- public static final String SHELL_INIT_SCRIPT = "karaf.shell.init.script";
-
- public static final String PROMPT = "PROMPT";
-
- public static final String DEFAULT_PROMPT = "\u001B[1m${USER}\u001B[0m@${APPLICATION}> ";
-
- public static final String PRINT_STACK_TRACES = "karaf.printStackTraces";
-
- public static final String LAST_EXCEPTION = "karaf.lastException";
-
public static final String IGNORE_INTERRUPTS = "karaf.ignoreInterrupts";
protected CommandSession session;
- private ConsoleReader reader;
-
private BlockingQueue<Integer> queue;
private boolean interrupt;
@@ -76,8 +48,6 @@ public class Console implements Runnable
private Runnable closeCallback;
- private Terminal terminal;
-
private InputStream consoleInput;
private InputStream in;
@@ -88,28 +58,20 @@ public class Console implements Runnable
private Thread thread;
- public Console(CommandProcessor processor, InputStream in, PrintStream out, PrintStream err, Terminal term,
- Runnable closeCallback) throws Exception {
+ public Console(CommandProcessor processor, InputStream in, PrintStream out, PrintStream err,
+ Runnable closeCallback, Map<String, String> sessionProps) throws Exception {
this.in = in;
this.out = out;
this.err = err;
this.queue = new ArrayBlockingQueue<Integer>(1024);
- this.terminal = term == null ? new UnsupportedTerminal() : term;
this.consoleInput = new ConsoleInputStream();
this.session = processor.createSession(this.consoleInput, this.out, this.err);
- this.session.put("SCOPE", "shell:osgi:*");
this.closeCallback = closeCallback;
- reader = new ConsoleReader(this.consoleInput, new PrintWriter(this.out), getClass().getResourceAsStream(
- "keybinding.properties"), this.terminal);
-
- session.put(".jline.history", reader.getHistory());
- Completer completer = createCompleter();
- if (completer != null) {
- reader.addCompleter(completer);
- }
- if (Boolean.getBoolean("jline.nobell")) {
- reader.setBellEnabled(false);
+ if (sessionProps != null) {
+ for (Entry<String, String> entry: sessionProps.entrySet()) {
+ this.session.put(entry.getKey(), entry.getValue());
+ }
}
pipe = new Thread(new Pipe());
pipe.setName("gogo shell pipe thread");
@@ -121,109 +83,30 @@ public class Console implements Runnable
}
public void close() {
- // System.err.println("Closing");
- if (reader.getHistory() instanceof PersistentHistory) {
- try {
- ((PersistentHistory) reader.getHistory()).flush();
- } catch (IOException e) {
- // ignore
- }
- }
running = false;
- CommandSessionHolder.unset();
pipe.interrupt();
}
public void run() {
- ThreadLocal<CommandSessionHolder> consoleState = new ThreadLocal<CommandSessionHolder>();
thread = Thread.currentThread();
- CommandSessionHolder.setSession(session);
running = true;
pipe.start();
- welcome();
- setSessionProperties();
- String scriptFileName = System.getProperty(SHELL_INIT_SCRIPT);
- if (scriptFileName != null) {
- Reader r = null;
- try {
- File scriptFile = new File(scriptFileName);
- r = new InputStreamReader(new FileInputStream(scriptFile));
- CharArrayWriter w = new CharArrayWriter();
- int n;
- char[] buf = new char[8192];
- while ((n = r.read(buf)) > 0) {
- w.write(buf, 0, n);
- }
- session.execute(new String(w.toCharArray()));
- } catch (Exception e) {
- System.err.println("Error in initialization script: " + e.getMessage());
- } finally {
- if (r != null) {
- try {
- r.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- }
- }
- while (running) {
- try {
- String command = null;
- boolean loop = true;
- boolean first = true;
- while (loop) {
- checkInterrupt();
- String line = reader.readLine(first ? getPrompt() : "> ");
- if (line == null) {
- break;
- }
- if (command == null) {
- command = line;
- } else {
- command += " " + line;
- }
- if (reader.getHistory().size() == 0) {
- reader.getHistory().add(command);
- } else {
- reader.getHistory().replace(command);
- }
- try {
- new Parser(command, 0).program();
- loop = false;
- } catch (Exception e) {
- loop = true;
- first = false;
- }
- }
- if (command == null) {
- break;
- }
- // session.getConsole().println("Executing: " + line);
- Object result = session.execute(command);
- if (result != null) {
- session.getConsole().println(session.format(result, Converter.INSPECT));
- }
- } catch (InterruptedIOException e) {
- // System.err.println("^C");
- // TODO: interrupt current thread
- } catch (CloseShellException e) {
- break;
- } catch (Exception t) {
- try {
- session.put(LAST_EXCEPTION, t);
- session.getConsole().print(Ansi.ansi().fg(Ansi.Color.RED).toString());
- session.getConsole().println(
- "Error executing command: "
- + (t.getMessage() != null ? t.getMessage() : t.getClass().getName()));
- session.getConsole().print(Ansi.ansi().fg(Ansi.Color.DEFAULT).toString());
- } catch (Exception ignore) {
- // ignore
- }
- }
+ try
+ {
+ session.execute("gosh --login --noshutdown");
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace(this.err);
+ }
+ finally
+ {
+ session.close();
+
+ this.out.println("Good Bye!");
}
close();
- // System.err.println("Exiting console...");
+
if (closeCallback != null) {
closeCallback.run();
}
@@ -243,90 +126,6 @@ public class Console implements Runnable
return Boolean.parseBoolean(s.toString());
}
- protected void welcome() {
- Properties props = loadBrandingProperties();
- String welcome = props.getProperty("welcome");
- if (welcome != null && welcome.length() > 0) {
- session.getConsole().println(welcome);
- }
- }
-
- protected void setSessionProperties() {
- Properties props = loadBrandingProperties();
- for (Map.Entry<Object, Object> entry : props.entrySet()) {
- String key = (String) entry.getKey();
- if (key.startsWith("session.")) {
- session.put(key.substring("session.".length()), entry.getValue());
- }
- }
- }
-
- protected Completer createCompleter() {
- return new CommandsCompleter(session);
- }
-
- protected Properties loadBrandingProperties() {
- Properties props = new Properties();
- loadProps(props, "org/apache/karaf/shell/console/branding.properties");
- loadProps(props, "org/apache/karaf/branding/branding.properties");
- return props;
- }
-
- protected void loadProps(Properties props, String resource) {
- InputStream is = null;
- try {
- is = getClass().getClassLoader().getResourceAsStream(resource);
- if (is != null) {
- props.load(is);
- }
- } catch (IOException e) {
- // ignore
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- }
- }
-
- protected String getPrompt() {
- try {
- String prompt;
- try {
- Object p = session.get(PROMPT);
- if (p != null) {
- prompt = p.toString();
- } else {
- Properties properties = loadBrandingProperties();
- if (properties.getProperty("prompt") != null) {
- prompt = properties.getProperty("prompt");
- // we put the PROMPT in ConsoleSession to avoid to read
- // the properties file each time.
- session.put(PROMPT, prompt);
- } else {
- prompt = DEFAULT_PROMPT;
- }
- }
- } catch (Throwable t) {
- prompt = DEFAULT_PROMPT;
- }
- Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(prompt);
- while (matcher.find()) {
- Object rep = session.get(matcher.group(1));
- if (rep != null) {
- prompt = prompt.replace(matcher.group(0), rep.toString());
- matcher.reset(prompt);
- }
- }
- return prompt;
- } catch (Throwable t) {
- return "$ ";
- }
- }
-
private void checkInterrupt() throws IOException {
if (Thread.interrupted() || interrupt) {
interrupt = false;
@@ -408,14 +207,13 @@ public class Console implements Runnable
try {
while (running) {
try {
- int c = terminal.readCharacter(in);
+ int c = in.read();
if (c == -1) {
return;
} else if (c == 4 && !getBoolean(IGNORE_INTERRUPTS)) {
err.println("^D");
} else if (c == 3 && !getBoolean(IGNORE_INTERRUPTS)) {
err.println("^C");
- reader.getCursorBuffer().clear();
interrupt();
}
queue.put(c);
Modified: felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/GogoPlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/GogoPlugin.java?rev=1345205&r1=1345204&r2=1345205&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/GogoPlugin.java (original)
+++ felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/GogoPlugin.java Fri Jun 1 14:37:54 2012
@@ -22,22 +22,12 @@
package org.apache.felix.webconsole.plugins.gogo.impl;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.InterruptedIOException;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.zip.GZIPOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
-import org.apache.felix.service.command.CommandProcessor;
-import org.apache.felix.service.command.CommandSession;
import org.apache.felix.webconsole.SimpleWebConsolePlugin;
import org.osgi.framework.BundleContext;
@@ -54,175 +44,71 @@ public class GogoPlugin extends SimpleWe
public static final String TITLE = "Gogo";
public static final int TERM_WIDTH = 120;
+
public static final int TERM_HEIGHT = 39;
- private CommandProcessor commandProcessor;
+ private final SessionTerminalManager terminalManager;
- public GogoPlugin() {
+ public GogoPlugin(final SessionTerminalManager terminalManager) {
super(LABEL, TITLE, null);
+ this.terminalManager = terminalManager;
}
@Override
public void activate(BundleContext bundleContext) {
super.activate(bundleContext);
- this.commandProcessor = new CommandProcessor() {
- public CommandSession createSession(InputStream in, PrintStream out, PrintStream err) {
- return ((CommandProcessor) getService(CommandProcessor.class.getName())).createSession(in, out, err);
- }
- };
}
@Override
public void deactivate() {
- this.commandProcessor = null;
super.deactivate();
}
- protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws IOException
- {
+ protected void renderContent(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter pw = response.getWriter();
String appRoot = request.getContextPath() + request.getServletPath();
- pw.println( "<link href=\"" + appRoot + "/gogo/res/ui/gogo.css\" rel=\"stylesheet\" type=\"text/css\" />" );
- pw.println( "<script src=\"" + appRoot + "/gogo/res/ui/gogo.js\" type=\"text/javascript\"></script>" );
- pw.println( "<div id='console'><div id='term'></div></div>" );
- pw.println( "<script type=\"text/javascript\"><!--" );
- pw.println( "window.onload = function() { gogo.Terminal(document.getElementById(\"term\"), " + TERM_WIDTH + ", " + TERM_HEIGHT + "); }" );
- pw.println( "--></script>" );
+ pw.println("<link href=\"" + appRoot + "/gogo/res/ui/gogo.css\" rel=\"stylesheet\" type=\"text/css\" />");
+ pw.println("<script src=\"" + appRoot + "/gogo/res/ui/gogo.js\" type=\"text/javascript\"></script>");
+ pw.println("<p id=\"statline\" class=\"statline\"> </p>");
+ pw.println("<div id='console'><div id='term'></div></div>");
+ pw.println("<script type=\"text/javascript\"><!--");
+ pw.println("window.onload = function() { gogo.Terminal(document.getElementById(\"term\"), " + TERM_WIDTH + ", "
+ + TERM_HEIGHT + "); }");
+ pw.println("--></script>");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
String encoding = request.getHeader("Accept-Encoding");
boolean supportsGzip = (encoding != null && encoding.toLowerCase().indexOf("gzip") > -1);
- SessionTerminal st = getSessionTerminal(request);
- String str = request.getParameter("k");
- String f = request.getParameter("f");
- String dump = st.handle(str, f != null && f.length() > 0);
- if (dump != null) {
- if (supportsGzip) {
- response.setHeader("Content-Encoding", "gzip");
- response.setHeader("Content-Type", "text/html");
- try {
- GZIPOutputStream gzos = new GZIPOutputStream(response.getOutputStream());
- gzos.write(dump.getBytes());
- gzos.close();
- } catch (IOException ie) {
- // handle the error here
- ie.printStackTrace();
- }
- } else {
- response.getOutputStream().write(dump.getBytes());
- }
- }
- }
-
- private SessionTerminal getSessionTerminal(final HttpServletRequest request) throws IOException{
- final Object terminal = request.getSession(true).getAttribute("terminal");
- if (terminal instanceof SessionTerminal) {
- final SessionTerminal st = (SessionTerminal) terminal;
- if (!st.isClosed()) {
- return st;
- }
- }
-
- final SessionTerminal st = new SessionTerminal(request.getRemoteUser());
- request.getSession().setAttribute("terminal", st);
- return st;
- }
-
- public class SessionTerminal implements Runnable {
-
- private Terminal terminal;
- private Console console;
- private PipedOutputStream in;
- private PipedInputStream out;
- private boolean closed;
-
- public SessionTerminal(final String user) throws IOException {
- try {
- this.terminal = new Terminal(TERM_WIDTH, TERM_HEIGHT);
- terminal.write("\u001b\u005B20\u0068"); // set newline mode on
-
- in = new PipedOutputStream();
- out = new PipedInputStream();
- PrintStream pipedOut = new PrintStream(new PipedOutputStream(out), true);
-
- console = new Console(commandProcessor,
- new PipedInputStream(in),
- pipedOut,
- pipedOut,
- new WebTerminal(TERM_WIDTH, TERM_HEIGHT),
- null);
- CommandSession session = console.getSession();
- session.put("APPLICATION", System.getProperty("karaf.name", "root"));
- session.put("USER", user);
- session.put("COLUMNS", Integer.toString(TERM_WIDTH));
- session.put("LINES", Integer.toString(TERM_HEIGHT));
- } catch (IOException e) {
- e.printStackTrace();
- throw e;
- } catch (Exception e) {
- e.printStackTrace();
- throw (IOException) new IOException().initCause(e);
- }
- new Thread(console).start();
- new Thread(this).start();
- }
-
- public boolean isClosed() {
- return closed;
- }
-
- public String handle(String str, boolean forceDump) throws IOException {
- try {
- if (str != null && str.length() > 0) {
- String d = terminal.pipe(str);
- for (byte b : d.getBytes()) {
- in.write(b);
- }
- in.flush();
- }
- } catch (IOException e) {
- closed = true;
- throw e;
- }
- try {
- return terminal.dump(10, forceDump);
- } catch (InterruptedException e) {
- throw new InterruptedIOException(e.toString());
- }
- }
-
- public void run() {
- try {
- for (;;) {
- byte[] buf = new byte[8192];
- int l = out.read(buf);
- InputStreamReader r = new InputStreamReader(new ByteArrayInputStream(buf, 0, l));
- StringBuilder sb = new StringBuilder();
- for (;;) {
- int c = r.read();
- if (c == -1) {
- break;
- }
- sb.append((char) c);
- }
- if (sb.length() > 0) {
- terminal.write(sb.toString());
- }
- String s = terminal.read();
- if (s != null && s.length() > 0) {
- for (byte b : s.getBytes()) {
- in.write(b);
- }
+ SessionTerminal st = terminalManager.getSessionTerminal(request);
+ if (st != null) {
+ String str = request.getParameter("k");
+ String f = request.getParameter("f");
+ String dump = st.handle(str, f != null && f.length() > 0);
+ if (dump != null) {
+ if (supportsGzip) {
+ response.setHeader("Content-Encoding", "gzip");
+ response.setHeader("Content-Type", "text/html; charset=UTF-8");
+ try {
+ GZIPOutputStream gzos = new GZIPOutputStream(response.getOutputStream());
+ gzos.write(dump.getBytes("UTF-8"));
+ gzos.close();
+ } catch (IOException ie) {
+ // handle the error here
+ ie.printStackTrace();
}
+ } else {
+ response.setContentType("text/html; charset=UTF-8");
+ response.getOutputStream().write(dump.getBytes("UTF-8"));
}
- } catch (IOException e) {
- closed = true;
- e.printStackTrace();
}
+ } else {
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
+ response.flushBuffer();
}
+
}
Added: felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/SessionTerminal.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/SessionTerminal.java?rev=1345205&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/SessionTerminal.java (added)
+++ felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/SessionTerminal.java Fri Jun 1 14:37:54 2012
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.felix.webconsole.plugins.gogo.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.InterruptedIOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+
+import org.apache.felix.service.command.CommandProcessor;
+
+public class SessionTerminal implements Runnable {
+
+ private Terminal terminal;
+ private Console console;
+ private PipedOutputStream in;
+ private PipedInputStream out;
+ private boolean closed;
+
+ @SuppressWarnings("serial")
+ public SessionTerminal(final CommandProcessor commandProcessor, final String user) throws IOException {
+ try {
+ this.terminal = new Terminal(GogoPlugin.TERM_WIDTH, GogoPlugin.TERM_HEIGHT);
+ terminal.write("\u001b\u005B20\u0068"); // set newline mode on
+
+ in = new PipedOutputStream();
+ out = new PipedInputStream();
+ PrintStream pipedOut = new PrintStream(new PipedOutputStream(out), true);
+
+ console = new Console(commandProcessor, new PipedInputStream(in), pipedOut, pipedOut, new Runnable() {
+ public void run() {
+ SessionTerminal.this.terminal.write("done...");
+ close();
+ }
+ }, new HashMap<String, String>() {
+ {
+ put("USER", user);
+ put("COLUMNS", Integer.toString(GogoPlugin.TERM_WIDTH));
+ put("LINES", Integer.toString(GogoPlugin.TERM_HEIGHT));
+ }
+ });
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ throw (IOException) new IOException().initCause(e);
+ }
+ new Thread(console).start();
+ new Thread(this).start();
+ }
+
+ public boolean isClosed() {
+ return closed;
+ }
+
+ public void close() {
+ if (!closed) {
+ this.closed = true;
+
+ this.console.close();
+
+ try {
+ this.in.close();
+ } catch (IOException e) {
+ }
+ try {
+ this.out.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ public String handle(String str, boolean forceDump) throws IOException {
+ try {
+ if (str != null && str.length() > 0) {
+ String d = terminal.pipe(str);
+ // echo unless backspace
+ if (d.charAt(0) != '\b') {
+ terminal.write(d);
+ }
+ in.write(d.getBytes());
+ in.flush();
+ }
+ } catch (IOException e) {
+ // ignore
+ }
+ try {
+ return terminal.dump(10, forceDump);
+ } catch (InterruptedException e) {
+ throw new InterruptedIOException(e.toString());
+ }
+ }
+
+ public void run() {
+ try {
+ for (;;) {
+ byte[] buf = new byte[8192];
+ int l = out.read(buf);
+ InputStreamReader r = new InputStreamReader(new ByteArrayInputStream(buf, 0, l));
+ StringBuilder sb = new StringBuilder();
+ for (;;) {
+ int c = r.read();
+ if (c == -1) {
+ break;
+ }
+ sb.append((char) c);
+ }
+ if (sb.length() > 0) {
+ terminal.write(sb.toString());
+ }
+ String s = terminal.read();
+ if (s != null && s.length() > 0) {
+ for (byte b : s.getBytes()) {
+ in.write(b);
+ }
+ }
+ }
+ } catch (IOException e) {
+ closed = true;
+ e.printStackTrace();
+ }
+ }
+
+}
\ No newline at end of file
Added: felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/SessionTerminalManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/SessionTerminalManager.java?rev=1345205&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/SessionTerminalManager.java (added)
+++ felix/trunk/webconsole-plugins/gogo/src/main/java/org/apache/felix/webconsole/plugins/gogo/impl/SessionTerminalManager.java Fri Jun 1 14:37:54 2012
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.felix.webconsole.plugins.gogo.impl;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+import org.apache.felix.service.command.CommandProcessor;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * The <code>SessionTerminalManager</code> manages {@link SessionTerminal}
+ * instances on behalf of the {@link GogoPlugin}. The instances are stored in
+ * HttpSessions and cleared when (a) the owning session is destroyed and (b)
+ * when this manager is {@link #shutdown() shut down}.
+ */
+public class SessionTerminalManager implements HttpSessionListener {
+
+ private final ServiceRegistration service;
+
+ private final ServiceTracker commandProcessor;
+
+ private final Set<SessionTerminal> sessions = new HashSet<SessionTerminal>();
+
+ @SuppressWarnings("serial")
+ public SessionTerminalManager(final BundleContext context) {
+ this.commandProcessor = new ServiceTracker(context, CommandProcessor.class.getName(), null) {
+ @Override
+ public void removedService(ServiceReference reference, Object service) {
+ cleanupSessions();
+ super.removedService(reference, service);
+ }
+ };
+ this.commandProcessor.open();
+
+ Hashtable<String, Object> props = new Hashtable<String, Object>();
+ props.put(Constants.SERVICE_DESCRIPTION, "Gogo Shell Terminal Session Reaper");
+ service = context.registerService(HttpSessionListener.class.getName(), this, props);
+ }
+
+ void shutdown() {
+ this.service.unregister();
+ this.commandProcessor.close();
+ this.cleanupSessions();
+ }
+
+ SessionTerminal getSessionTerminal(final HttpServletRequest request) throws IOException {
+ final HttpSession session = request.getSession(true);
+ final Object terminal = session.getAttribute("terminal");
+ if (terminal instanceof SessionTerminal) {
+ final SessionTerminal st = (SessionTerminal) terminal;
+ if (!st.isClosed()) {
+ return st;
+ }
+ }
+
+ final CommandProcessor cp = (CommandProcessor) this.commandProcessor.getService();
+ if (cp != null) {
+ final SessionTerminal st = new SessionTerminal(cp, request.getRemoteUser());
+ this.sessions.add(st);
+ session.setAttribute("terminal", st);
+ return st;
+ }
+
+ // no session because there is no command processor !
+ return null;
+ }
+
+ public void sessionCreated(HttpSessionEvent event) {
+ // don't care
+ }
+
+ public void sessionDestroyed(HttpSessionEvent event) {
+ final Object terminal = event.getSession().getAttribute("terminal");
+ if (terminal instanceof SessionTerminal) {
+ sessions.remove(terminal);
+ ((SessionTerminal) terminal).close();
+ }
+ }
+
+ void cleanupSessions() {
+ for (SessionTerminal session : sessions) {
+ session.close();
+ }
+ this.sessions.clear();
+ }
+}
Modified: felix/trunk/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.js?rev=1345205&r1=1345204&r2=1345205&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.js (original)
+++ felix/trunk/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.js Fri Jun 1 14:37:54 2012
@@ -36,7 +36,7 @@ gogo.Terminal_ctor = function(div, width
var dstat = document.createElement('pre');
var sled = document.createElement('span');
- var sdebug = document.createElement('span');
+ var sdebug = document.getElementById('statline');
var dterm = document.createElement('div');
function debug(s) {
@@ -45,11 +45,11 @@ gogo.Terminal_ctor = function(div, width
function error() {
sled.className = 'off';
- debug("Connection lost timeout ts:" + ((new Date).getTime()));
+ debug("Gogo Shell Processor not available");
}
function update() {
- if (sending == 0) {
+ if (sending == 0 /* && keybuf.length > 0 */ ) {
sending = 1;
sled.className = 'on';
var r = new XMLHttpRequest();
@@ -79,8 +79,10 @@ gogo.Terminal_ctor = function(div, width
sending=0;
sled.className = 'off';
timeout = window.setTimeout(update, rmax);
+ } else if (r.status == 500) {
+ debug("Gogo Shell Processor not available")
} else {
- debug("Connection error status:" + r.status);
+ debug("General failure with Gogo Shell: " + r.status);
}
}
}
@@ -183,11 +185,13 @@ gogo.Terminal_ctor = function(div, width
default: k = String.fromCharCode(kc); break;
}
+ var s = encodeURIComponent(k);
+
// debug("fromkeydown=" + fromkeydown + ", ev.keyCode=" + ev.keyCode + ", " +
// "ev.which=" + ev.which + ", ev.ctrlKey=" + ev.ctrlKey + ", " +
-// "kc=" + kc + ", k=" + k);
+// "kc=" + kc + ", k=" + k + ", s=" + s);
- queue(encodeURIComponent(k));
+ queue(s);
ev.cancelBubble = true;
if (ev.stopPropagation) ev.stopPropagation();
@@ -203,8 +207,22 @@ gogo.Terminal_ctor = function(div, width
113:1, 114:1, 115:1, 116:1, 117:1, 118:1, 119:1, 120:1, 121:1, 122:1, 123:1 };
if (o[ev.keyCode] || ev.ctrlKey || ev.altKey) {
keypress(ev, true);
+ } else {
+ ev.cancelBubble = true;
+ if (ev.stopPropagation) ev.stopPropagation();
+ if (ev.preventDefault) ev.preventDefault();
}
}
+
+ function ignoreKey(ev) {
+ if (!ev) {
+ ev = window.event;
+ }
+
+ ev.cancelBubble = true;
+ if (ev.stopPropagation) ev.stopPropagation();
+ if (ev.preventDefault) ev.preventDefault();
+ }
function init() {
if (typeof(XMLHttpRequest) == "undefined") {
@@ -220,18 +238,22 @@ gogo.Terminal_ctor = function(div, width
throw new Error("This browser does not support XMLHttpRequest.");
};
}
+
sled.appendChild(document.createTextNode('\xb7'));
sled.className = 'off';
dstat.appendChild(sled);
dstat.appendChild(document.createTextNode(' '));
- dstat.appendChild(sdebug);
+// dstat.appendChild(sdebug);
dstat.className = 'stat';
+
div.appendChild(dstat);
var d = document.createElement('div');
d.appendChild(dterm);
div.appendChild(d);
+
document.onkeypress = keypress;
- document.onkeydown = keydown;
+ document.onkeydown = ignoreKey;
+ document.onkeyup = ignoreKey;
timeout = window.setTimeout(update, 100);
}