// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.components.runtime.util;
import android.util.Log;
import gnu.expr.Language;
import gnu.mapping.Environment;
import gnu.mapping.OutPort;
import gnu.mapping.Procedure0;
import gnu.mapping.TtyInPort;
import gnu.mapping.Values;
import gnu.text.FilePath;
import kawa.Shell;
import kawa.Telnet;
/**
* This is code for running Telnet-based Read-Eval-Print loops. It's based on the code for
* {@link kawa.TelnetRepl}
*/
public class TelnetRepl extends Procedure0 {
// close when finished.
java.net.Socket socket;
Language language;
private static final int REPL_STACK_SIZE = 256*1024;
public TelnetRepl(Language language, java.net.Socket socket) {
this.language = language;
this.socket = socket;
}
public Object apply0 () {
Thread thread = Thread.currentThread();
ClassLoader contextClassLoader = thread.getContextClassLoader();
if (contextClassLoader == null) {
// TODO(markf): this is a hack to deal with calls to getContextClassLoader() within the
// Shell.run() call below which return null on some older Android phones.
thread.setContextClassLoader(Telnet.class.getClassLoader());
}
try {
Shell.run(language, Environment.getCurrent());
return Values.empty;
} catch (RuntimeException e) {
Log.d("TelnetRepl", "Repl is exiting with error " + e.getMessage());
e.printStackTrace();
throw e;
} finally {
try {
socket.close();
} catch (java.io.IOException ex) {
// This ignoring of the exception was in the original version of the code - markf
}
}
}
/** Run a Kawa repl as a telnet server.
* @param client A client that has connected to us,
* and that wants to use the telnet protocol to talk to a
* Scheme read-eval-print-loop.
*/
public static Thread serve (Language language, java.net.Socket client)
throws java.io.IOException {
Telnet conn = new Telnet(client, true);
java.io.OutputStream sout = conn.getOutputStream();
java.io.InputStream sin = conn.getInputStream();
OutPort out = new OutPort(sout, FilePath.valueOf("/dev/stdout"));
TtyInPort in = new TtyInPort(sin, FilePath.valueOf("/dev/stdin"), out);
// The following was commented out in the original code - markf
/*
conn.request(Telnet.DO, Telnet.EOF);
conn.request(Telnet.DO, Telnet.NAWS);
conn.request(Telnet.DO, Telnet.TTYPE);
conn.request(Telnet.DO, Telnet.LINEMODE);
*/
Thread thread =
new BiggerFuture(new TelnetRepl(language, client),
in, out, out, "Telnet Repl Thread", REPL_STACK_SIZE);
thread.start();
return thread;
}
}