Search code examples
javaswtbufferedreaderjschsystem.in

java SWT to connect to remote server using Jcraft JSch


I am working on on a tool to connect to a remote server using jcraft.JSch (ssh to Unix server) and return the output and display its output (something like putty, but iam not keen on Plink or any third party thing). The code works fine when channel input outputs are System.in and System.out and the program is just a console java application. But when I try with SWT controls, it was having problem as explained in How to Map System.out and System.in to SWT controls

so, I believe its something anout the INFO and ERR tagging (which i will deal with later), anyways i changed the approach. now iam feeding commands through a SWT Text input. its working fine for single line outputs. but not for multi line.

enter image description here

The code which triggers the connection to shell and sends commands is as follows.

        public void widgetSelected(SelectionEvent e) {
        String command=CmdText.getText();
        System.out.println("runButton.widgetSelected:Command Obtained by buton is:"+command);
        if ( command.equals("") )
        {
           MessageDialog.openInformation(dialogShell,"Information","Please Eneter a Command!");
           return;
        }
        else if (command.contains("@"))
        {
            channel=CommandHandler.openshell();
            LogText.append("Connected to - :"+command+"\n>");
        }
        else
        {
            LogText.append(command+"\n");
            String outputstring="";
            try
            {
                 BufferedReader dataIn = new BufferedReader(new InputStreamReader(channel.getInputStream()));
                 DataOutputStream dataOut = new DataOutputStream(channel.getOutputStream());  

                 dataOut.writeBytes(command+"\n");
                 dataOut.flush();

                 String line="";
                 outputstring=""+line;
                 while ( line != null) {
                     try
                     {
                        line = dataIn.readLine();
                        line = dataIn.readLine();
                        LogText.append("<CommandResult>:"+line+"\n");
                        return;
                     }
                     catch (IOException e1) { B24IDEConsole.WriteLog("RemoteCall.connect_execute", e1.getMessage()); }
                     outputstring=outputstring+line;
                 }
            }
            catch(Exception e1){ B24IDEConsole.WriteLog("RemoteCall.connect_execute", e1.getMessage()); }
            LogText.append("<EndOfCommand>:"+outputstring+"\n");
        }
    }

When i remove return in the while loop the dialog and the eclipse (triggering the dialog) becomes un-responsive and i have to kill them both.

Any Help is appreciated, thank you for your time.


Solution

  • There are two things i was missing in the above code.

    1. getOutputStream and getInputStream were getting called after channel.connect while Jsch documentation says it shouldnt be ref: http://epaul.github.io/jsch-documentation/simple.javadoc/com/jcraft/jsch/Channel.html
    2. dataIn.available is a better test if any more data is available from the server or not. thanks to Sending commands to server via JSch shell channel.

    updated code is

                     InputStream dataIn = CommandHandler.getdatain();
                     OutputStream dataOut = CommandHandler.getdataout();
                     //dataOut.write(command.getBytes()+"\n");
                     byte[] inputbytes = command.getBytes();
                     dataOut.write(inputbytes,0,inputbytes.length);
                     dataOut.flush();
                     while (true) {
                            boolean readoutput=false;
                            while (dataIn.available() > 0) {
                                readoutput=true;
                                byte[] buffer=new byte[1024];
                                int i = dataIn.read(buffer, 0, 1024);
                                if (i < 0) {
                                    System.out.print("No more data available!");//It is printing the response to console
                                    break;
                                }
                                LogText.append(new String(buffer, 0, i));
                                //LogText.append(":"+new String(buffer, 0, i)+"\n>");
                                System.out.print(new String(buffer, 0, i));//It is printing the response to console
                            }
                            System.out.println(dataIn.available()+"done");
                            if ( readoutput )
                            {
                                if ( dataIn.available() == 0 )
                                {
                                    System.out.print("Read all the data and no nore is available, hence exiting!\n");//It is printing the response to console
                                    break;
                                }
                            }
                            if ( channel.isClosed() ) {
                                System.out.println("exit-status: " + channel.getExitStatus());
                                break;
                            }
                            try{Thread.sleep(1000);}catch(Exception ee){}
                     }
    

    break is still a problem but looks like can be fixed for now.