Example for terminal with GUI (swing)

613 views
Skip to first unread message

Abu Abdullah

unread,
Dec 8, 2016, 9:59:36 AM12/8/16
to sshj-users
Hi,

I'm trying to have basic terminal emulator with swing GUI based on one of the examples in the respository. the following code is first attemp with some limitations and issues.

i hope others to improve it so that we can a basic terminal that can help to integrate it directly in any java app and also identifying issues quickly in the library.

import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.StreamCopier;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Shell;
import net.schmizz.sshj.transport.verification.HostKeyVerifier;
import net.schmizz.sshj.connection.channel.direct.PTYMode;

import java.io.*;
import java.security.PublicKey;
import java.util.*;
import net.schmizz.sshj.common.LoggerFactory;

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

class Console extends JTextPane
{
   
DocOutputStream out;
   
PrintStream pout;
   
DocInputStream in;
   
JFrame frame;
   
StyledDocument doc;

   
Console() throws Exception, Throwable
   
{
        setPreferredSize
(new Dimension(600, 500));
        doc
= this.getStyledDocument();
       
out = new DocOutputStream(doc, this);
        pout
= new PrintStream(out);
       
in = new DocInputStream();
       
this.addKeyListener(in);
        setFont
(new Font("Courier New", Font.PLAIN, 12));
       
//setEditorKit(new HTMLEditorKit());
        frame
= new JFrame("Console");
        frame
.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame
.add(new JScrollPane(this));
        frame
.pack();
        frame
.setVisible(true);

       
final SSHClient ssh = new SSHClient();
        ssh
.addHostKeyVerifier(
               
new HostKeyVerifier()
               
{
                   
@Override
                   
public boolean verify(String s, int i, PublicKey publicKey)
                   
{
                       
return true;
                   
}
               
});

        ssh
.connect("sdf.org");
       
try
       
{
            ssh
.authPassword("naseh", "naseh");

           
final Session session = ssh.startSession();

           
try
           
{
                java
.util.Map<PTYMode, Integer> ptyModeMap = new HashMap<>();

               
// disables echoing of input to output
                ptyModeMap
.put(PTYMode.ECHO, 0);

                session
.allocatePTY("vt100", 120, 120, 0, 0, ptyModeMap);

               
final Shell shell = session.startShell();

               
new StreamCopier(shell.getInputStream(), getOut(), LoggerFactory.DEFAULT)
                       
.bufSize(shell.getLocalMaxPacketSize())
                       
.spawn("stdout");

               
new StreamCopier(shell.getErrorStream(), getOut(), LoggerFactory.DEFAULT)
                       
.bufSize(shell.getLocalMaxPacketSize())
                       
.spawn("stderr");

               
new StreamCopier(getIn(), shell.getOutputStream(), LoggerFactory.DEFAULT)
                       
.bufSize(shell.getRemoteMaxPacketSize())
                       
.copy();

           
} finally
           
{
                session
.close();
           
}

       
} finally
       
{
            ssh
.disconnect();
       
}
   
}

   
public InputStream getIn()
   
{
       
return in;
   
}

   
public PrintStream getOut()
   
{
       
return pout;
   
}

   
private static class DocOutputStream extends OutputStream
   
{
       
StyledDocument doc;
       
MutableAttributeSet cur;
       
JTextPane pane;

       
public DocOutputStream(StyledDocument doc, JTextPane pane)
       
{
           
this.doc = doc;
           
this.pane = pane;
            cur
= new SimpleAttributeSet();
       
}

       
@Override
       
public void write(int b) throws IOException
       
{
           
try
           
{
                doc
.insertString(doc.getLength(), (char) b + "", cur);
                pane
.setCaretPosition(doc.getLength());
           
}
           
catch (BadLocationException ex)
           
{
                ex
.printStackTrace();
           
}
       
}
   
}

   
private static class DocInputStream extends InputStream implements KeyListener
   
{
       
ArrayBlockingQueue<Integer> queue;

       
public DocInputStream()
       
{
            queue
= new ArrayBlockingQueue<Integer>(1024);
       
}

       
@Override
       
public int read() throws IOException
       
{
           
Integer i = null;
           
try
           
{
                i
= queue.take();
           
}
           
catch (InterruptedException ex)
           
{
                ex
.printStackTrace();
           
}
           
if (i != null)
               
return i;
           
return -1;
       
}

       
@Override
       
public int read(byte[] b, int off, int len) throws IOException
       
{
           
if (b == null)
           
{
               
throw new NullPointerException();
           
}
           
else
               
if (off < 0 || len < 0 || len > b.length - off)
               
{
                   
throw new IndexOutOfBoundsException();
               
}
               
else
                   
if (len == 0)
                   
{
                       
return 0;
                   
}
           
int c = read();
           
if (c == -1)
           
{
               
return -1;
           
}
            b
[off] = (byte) c;

           
int i = 1;
           
try
           
{
               
for (; i < len && available() > 0; i++)
               
{
                    c
= read();
                   
if (c == -1)
                   
{
                       
break;
                   
}
                    b
[off + i] = (byte) c;
               
}
           
}
           
catch (IOException ee)
           
{
           
}
           
return i;
       
}

       
@Override
       
public int available()
       
{
           
return queue.size();
       
}

       
@Override
       
public void keyTyped(KeyEvent e)
       
{
           
int c = e.getKeyChar();
           
try
           
{
                queue
.put(c);
           
}
           
catch (InterruptedException ex)
           
{
                ex
.printStackTrace();
           
}
       
}

       
@Override
       
public void keyPressed(KeyEvent e)
       
{
       
}

       
@Override
       
public void keyReleased(KeyEvent e)
       
{
       
}
   
}

   
public static void main(String... args) throws Exception, Throwable
   
{
       
new Console();
   
}
}


some limitations to work with:
- interpret ANSI Escape code since you will see many codes in the output command (e.g. color)
- disable editing the previous output and the command prompt
- enable history (arrow up/down)
- interactive shell
- Disable echo (working in some shells and others are not working. in the example it is not working with sdf.org shells
- hide password ..... and many more

lb.bu...@gmail.com

unread,
Aug 14, 2018, 2:44:39 AM8/14/18
to sshj-users
Hi,Is there any idea to interpret ANSI Escape code?
I searched some answers,but failed.

在 2016年12月8日星期四 UTC+8下午10:59:36,Abu Abdullah写道:

Annan Marnah

unread,
Apr 13, 2019, 8:41:26 PM4/13/19
to sshj-users
please i need your help to work on my semester project am Aminu Umar from Ghana
Reply all
Reply to author
Forward
0 new messages