我使用beanshell作为我的应用程序中的嵌入式调试工具。这意味着我可以远程登录到我的应用程序,并在它运行时查看它的内部(我通常用rlwrap包装telnet会话)。
问题是,我找到的打印到beanshell控制台而不是应用程序本身的stdout的唯一方法是beanshell中的print()方法。
但我想用Java编写代码,我可以从Beanshell调用它,它将输出到Beanshell控制台-即。它将显示在我的telnet会话中,而不是发送到应用程序的stdout,就像您尝试使用system.out或system.err时一样。
这可能吗?
编辑:为了进一步澄清,我正在设置Beanshell服务器,如下所示:

public static void setUpBeanshell() {
    try {
        i.setShowResults(true);
        i.eval(new InputStreamReader(Bsh.class.getResourceAsStream("init.bsh")));
        i.eval("server(" + Main.globalConfig.beanShellPort + ");");
    } catch (final EvalError e) {
        Main.log.error("Error generated while starting BeanShell server", e);
    }
}

如何修改它,以便编写一个Java函数,输出到telnet会话(而不是应用程序的system.out)

最佳答案

我会把它复制到那里,因为这几天评论似乎被忽略了。
你可以:
不使用将调试信息打印到标准输出的方法,而是返回该调试信息:

class ClientList {
 Integer clients = 0;
 public String debugClientList() {
   return clients.toString();
 }

然后从Beanshell打来
print(clients.debugCientList());

会在你的telnet上给你一个输出
或者如果您需要更像日志的方式,则需要直接与解释器对象交互
InterpreterSingleton {
    public static final void Console console = new Interpreter();
}
....

class ClientList {
 Integer clients = 0;
 public void addClient(Client c) {
    ....
    InterpreterSingleton.console.print("Client added, clients now are " + clients);
 }

我在这里回复评论,因为它将需要更多的编码;telnet实现对每个连接使用不同的解释器,因此您必须将该解释器公开给打印到telnet客户端的对象。最快的方法是更改默认telnet服务器中的某些位,并使用修改后的位来启动服务器,而不是使用server()脚本命令(它是在lgpl或sun许可条款下)
注意,这种方式为每个连接都启动了一个解释器;简单而快速的解决方法是维护所有正在运行的解释器的列表,并将调试信息打印给每个解释器,因此:
class InterpreterSingletonList {
    public static final void Set<Interpreter> is = new HashSet();
    void printToAll(String s) {
         for (Interpreter i: is) {
             i.print(s);
         }
    }
}



package bsh.util;

import java.io.*;

import java.net.Socket;
import java.net.ServerSocket;
import bsh.*;

/**
    BeanShell remote session server.
    Starts instances of bsh for client connections.
    Note: the sessiond effectively maps all connections to the same interpreter
    (shared namespace).
*/
public class Sessiond extends Thread
{
    private ServerSocket ss;
    NameSpace globalNameSpace;

    public Sessiond(NameSpace globalNameSpace, int port) throws IOException
    {
        ss = new ServerSocket(port);
        this.globalNameSpace = globalNameSpace;
    }

    public void run()
    {
        try
        {
            while(true)
                new SessiondConnection(globalNameSpace, ss.accept()).start();
        }
        catch(IOException e) { System.out.println(e); }
    }
}

class SessiondConnection extends Thread
{
    NameSpace globalNameSpace;
    Socket client;

    SessiondConnection(NameSpace globalNameSpace, Socket client)
    {
        this.client = client;
        this.globalNameSpace = globalNameSpace;
    }

    public void run()
    {
        try
        {
            InputStream in = client.getInputStream();
            PrintStream out = new PrintStream(client.getOutputStream());
            /* this is the one you're looking for */
                        Interpreter i = new Interpreter(
                new InputStreamReader(in), out, out, true, globalNameSpace);
            i.setExitOnEOF( false ); // don't exit interp
                    /*store the interpreter on the list*/
                    InterpreterSingletonList.is.add(i);
            i.run();
                    /*remove it (i.run() blocks)*/
                    InterpreterSingletonList.is.remove(i);
        }
        catch(IOException e) { System.out.println(e); }
    }
}

10-06 02:01