هل يمكنني الكتابة إلى وحدة تحكم Beanshell من Java؟

StackOverflow https://stackoverflow.com/questions/1760917

  •  21-09-2019
  •  | 
  •  

سؤال

أنا أستخدم Beanshell كأداة تصحيح أخطاء مضمنة في تطبيقي. هذا يعني أنه يمكنني telnet إلى تطبيقي والتجول مع الداخلية أثناء تشغيله (عادةً ما أقوم بلف جلسة Telnet باستخدام RLWRAP).

المشكلة هي أن الطريقة الوحيدة التي وجدتها للطباعة على وحدة تحكم Beanshell ، بدلاً من stdout للتطبيق نفسه ، هي طريقة print () داخل Beanshell.

لكني أرغب في كتابة رمز في جافا ، يمكنني الاتصال من 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 (بدلاً من النظام.

هل كانت مفيدة؟

المحلول

سأنسخها هناك كما يبدو أن التعليقات تم تجاهلها هذه الأيام.

يمكنك: بدلاً من وجود طريقة تقوم بطباعة معلومات التصحيح إلى إرجاع الإخراج القياسي الذي يعيد معلومات التصحيح:

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 () Scripted (إنه ضمن مصطلحات 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); }
    }
}

نصائح أخرى

أعتقد أنه من غير الممكن مع Out Hack ... ، آسف ، تكييف تطبيق خادم Telnet لـ BSH.

الفصل الذي نبحث عنه bsh.util.Sessiond. بمجرد بدء تشغيله ، يفتح ويحافظ على خادم Telnet. عندما يتلقى أي شيء أمرًا ، فإنه ينشئ مؤشر ترابط عامل جديد ، فإن ذلك ينشئ BSH.Interpreter جديد مع تدفقات الإدخال والإخراج الصحيحة (المشتقة من المقبس) ويقوم بتشغيل المترجم المترجم.

لذلك فمن المنطقي ، أن إخراج الأوامر المفسرة فقط هو إرسال إلى عميل Telnet ، لأن System.out و System.err لا يتم إعادة توجيهها.

ولكن هذا هو بالضبط ما يجب القيام به في حالتك: إعادة التوجيه System.out و System.err إلى دفق إخراج Sockets قبل تشغيل المترجم المترجم وإعادة ضبط التدفقات بعد الانتهاء.

أود أن أقترح ، تقوم بنسخ bsh.util.Sessiond الفصل لشيء مثل mybsh.util.DebuggerSessiond, ، قم بتطبيق رمز إعادة التوجيه على طريقة التشغيل في SessionDconnection الداخلية والتعديل bsh/commands/server.bsh لبدء خادم Telnet "الجديد" بالإضافة إلى ذلك (أو بدلاً من الخادم الأصلي). (أعتقد ، هذا البرنامج النصي يبدأ الخوادم ...)

يمكن العثور على رمز المصدر هنا: مستودع Beanshell

إذا تم كتابة جميع إخراج التطبيق الخاص بك باستخدام بعض إطار التسجيل على أي حال ، فيمكنك كتابة جهد/معالج مخصص ، إلى جانب تسجيل الدخول إلى قول ملف سيكتب إلى وحدة تحكم Beanshell بالإضافة إلى ذلك؟ ربما تمكين وتعطيل تغطير وحدة التحكم بعد تنفيذ بعض قيادة Beanshell.

(لم أكن على دراية بـ Beanshell من قبل ، لكنه يبدو مفيدًا!)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top