Results 1 to 11 of 11
  1. #1
    c26354 is offline Member
    Join Date
    Jun 2008
    Posts
    11
    Rep Power
    0

    Default Creating an InputStream

    Hi,

    What i'm doing is trying to send ssh commands using java to a server. I'm using the Jsch package to do this. The ssh part works, what i'm having trouble with is sending the commands to the server. There is an example which creates a shell in the console, it looks like this:

    Java Code:
    public class Shell
    {
    	public static void main(String[] arg)
    	{
    		try
    		{
    			JSch jsch=new JSch();
    
    			String host = "host";
    			String user= "user";
    			Session session=jsch.getSession(user, host, 22);
    			session.setPassword("pass");
    
    			session.setConfig("StrictHostKeyChecking", "no");
    
    			session.connect(30000);   // making a connection with timeout.
    
    			Channel channel=session.openChannel("shell");
    
    			channel.setInputStream(System.in);
    			channel.setOutputStream(System.out);
    
    			channel.connect(30000);
    		}
    		catch(Exception e)
    		{
    			System.out.println(e);
    		}
    	}
    }
    This works and connects to the server correctly (since you can see the logon being printed in the console), but it requires that the user enter commands from the console:

    channel.setInputStream(System.in);

    What I want to do is make my own input stream and then send commands. I have been looking into the BufferedInputStream class, but I can't get it to work, and all the examples are for reading from files.

    What I want to do is something like this:

    String command = "ls -l";

    and then somehow send command to an InputStream. That way I can replace System.in with my own InputStream.

    Thanks.

  2. #2
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    send command to an InputStream
    Not sure what this means. I read "send" as to write and InputStream as a way to read.
    There is a System class method that allows you to replace System.in with your class. Read the API doc.

    Perhaps the Process and Runtime classes would help.

  3. #3
    c26354 is offline Member
    Join Date
    Jun 2008
    Posts
    11
    Rep Power
    0

    Default

    Let me clarify:

    Basically what I think I need to do is something like create an InputStream:
    Java Code:
    InputStream toServer;
    Then instead of having the line:
    Java Code:
    channel.setInputStream(System.in);
    I would have:
    Java Code:
    channel.setInputStream(toServer);
    The problem is how can I write to the input stream 'toServer'?

  4. #4
    Nicholas Jordan's Avatar
    Nicholas Jordan is offline Senior Member
    Join Date
    Jun 2008
    Location
    Southwest
    Posts
    1,018
    Rep Power
    8

    Default ByteChannel

    Probably, you are not looking for Process (Java 2 Platform SE v1.4.2)

    What is seems you want to do is represented by a somewhat misnamed ByteArrayOutputStream (Java 2 Platform SE v1.4.2) in which the read / write operations occur to memory.

    To do this with Channels would either be ReadableByteChannel (Java 2 Platform SE v1.4.2) or WritableByteChannel (Java 2 Platform SE v1.4.2)
    Introduction to Programming Using Java.
    Cybercartography: A new theoretical construct proposed by D.R. Fraser Taylor

  5. #5
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    I think what you want to do is control what your InputStream reads. A way to do that is to create your own class that extends InputStream and pass that in the method setInputStream().

    You'll "write to the input stream" by returning data as the input stream is read.

    Or using Nicholas's idea, if you know exactly what you want to be read, create a ByteArrayInputStream with preloaded data and pass an instance of it to the set...() method.

  6. #6
    c26354 is offline Member
    Join Date
    Jun 2008
    Posts
    11
    Rep Power
    0

    Default

    Ok, first of all thanks Nicholas and Norm, the ByteArrayInputStream works well. So what I have is:
    Java Code:
    ByteArrayInputStream bi = new ByteArrayInputStream("ls -l\n".getBytes());
    channel.setInputStream(bi);
    And that will send the command "ls -l" to the server and the result prints to the console.

    What I want to do now is send a second command to the server. In the original code (my first post), with System.in, you can type in as many commands as you want into the console one after another. So what I need is a way to change ByteArrayInputStream to be something else. I tried:

    Java Code:
    bi = new ByteArrayInputStream("ls -l\n".getBytes());
    but it doesn't do anything. Any ideas?


    My current code is:

    Java Code:
    import com.jcraft.jsch.*;
    import java.io.*;
    
    public class Shell
    {
    	public static void main(String[] arg)
    	{
    		try
    		{
    			JSch jsch=new JSch();
    
    			String host = "host";
    			String user= "user";
    			Session session=jsch.getSession(user, host, 22);
    			session.setPassword("pass");
    
    			session.setConfig("StrictHostKeyChecking", "no");
    
    			//session.connect();
    			session.connect(30000);   // making a connection with timeout.
    
    			Channel channel = session.openChannel("shell");
    
    			ByteArrayInputStream bi = new ByteArrayInputStream("ls -l\r".getBytes());
    			channel.setInputStream(bi);
    			
    			channel.setOutputStream(System.out);
    
    			//channel.connect();
    			channel.connect(30000);
    		}
    		catch(Exception e)
    		{
    			System.out.println(e);
    		}
    	}
    }
    Thanks.

  7. #7
    Nicholas Jordan's Avatar
    Nicholas Jordan is offline Senior Member
    Join Date
    Jun 2008
    Location
    Southwest
    Posts
    1,018
    Rep Power
    8

    Default

    short of reading the entire code, what I was working on yesterday is close to this.

    Still wrestling with some fundamental concepts but in general we have to get a byte array reference of some kind and do length and so on off of that.

    IOW:

    byte[] butylene = "someString or other string".getBytes();
    then construct byte array output stream using default constructor.

    Then and only then do what you are trying to do using the methods as documented in class java.io.ByteArrayOutputStream;//

    As Norm observes, you are trying to get control on Stream such and such so as to control the feed to some sink...

    That is done with a while byte array still has bytes do so and so. If I may suggest: Study the methods of DataOutputStream.

    Observe the limitations of strong typing. Weep and read.
    Introduction to Programming Using Java.
    Cybercartography: A new theoretical construct proposed by D.R. Fraser Taylor

  8. #8
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    ByteArrayInputStream works well.
    and
    it doesn't do anything
    The code looks the same for when it works and when it doesn't do anything. Could you explain some more?
    I want to do now is send a second command
    Can all the commands be together or do you need to a separate connect for each one?

  9. #9
    Nicholas Jordan's Avatar
    Nicholas Jordan is offline Senior Member
    Join Date
    Jun 2008
    Location
    Southwest
    Posts
    1,018
    Rep Power
    8

    Default no constructor taking byte[]

    Quote Originally Posted by Norm View Post
    The code looks the same for when it works and when it doesn't do anything. Could you explain some more?
    Java Code:
    //Creates a new byte array output stream.
    ByteArrayOutputStream() 
    
    // Creates a new byte array output stream, with a buffer capacity of the specified size, in bytes. 
    ByteArrayOutputStream(int size)
    Neither of these constructors are as poster has.

    ByteArrayOutputStream (Java 2 Platform SE 5.0)
    Introduction to Programming Using Java.
    Cybercartography: A new theoretical construct proposed by D.R. Fraser Taylor

  10. #10
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    I guess you need new glasses. The OP posted constructors for ...In... not ...Out...

  11. #11
    DeanC is offline Member
    Join Date
    Jul 2011
    Posts
    1
    Rep Power
    0

    Default You need to think Terminal Emulation instead

    Norm,

    I also had your problem. Its an old post but I couldn't find an answer anywhere else so I uploaded my solution.

    Firstly, the main problem is that JSch takes (rapid) asynchronious reads from what it expects to be a console or silimar until there is no text left to send and it breaks the conection. As suggested above you can override InputStream (or BufferedInputStream) and the Session Class will call getBytes() from the IO class with the set InputStream in a loop until no bytes are left and it breaks so even if you create your own inputStream it is still a one shot deal. Once the buffer is empty the connection is over. In my example I wanted to send a polling command every 10 seconds and monitor a result and this couldn't be achieved.

    By the very fact that JSch 'WRITES' to an InputStream and "READS" from a OutputStream it is clear that our perspective is backwards to the initial intent of the application. Instead of a Shell you need to look at jcterm which is a Terminal emulator that allows Synch 'Triggered' writes to a server and polled reads.

    The package com.jcraft.jcterm has a Class called JSchSession which is a wrapper for the Session Class (Not extended but exposes the Session through an accessor).This Class allows you to open a channel and get InputStreams and OutputStreams to the server in a way that you are expecting. From there you can run a Thread to accept the inputs and write (and Flush) to the outputStream.

    E.G:

    package SSHTests;

    import com.jcraft.jcterm.JSchSession;
    import com.jcraft.jsch.Channel;
    import com.jcraft.jsch.JSch;
    import com.jcraft.jsch.Session;
    import com.jcraft.jsch.UIKeyboardInteractive;
    import com.jcraft.jsch.UserInfo;
    import java.awt.Container;
    import java.awt.Dimension;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import javax.swing.JButton;
    import javax.swing.JDialog;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JPasswordField;
    import javax.swing.JTextField;

    /**
    *
    * @author dcolcott
    */

    public class TestSHH_WithConnection{

    public static void main(String args[]){
    TestSHH_WithConnection app = new TestSHH_WithConnection();
    app.initSession();
    app.startreadThread();
    app.shInputDialog();
    }

    private void initSession(){

    try{
    UserInfo ui=new MyUserInfo();
    jschsession=JSchSession.getSession("user", "pass", "host", 22, ui, null);

    java.util.Properties config=new java.util.Properties();
    config.put("compression.s2c", "none");
    config.put("compression.c2s", "none");

    config.put("compression.s2c", "zlib,none");
    config.put("compression.c2s", "zlib,none");

    jschsession.getSession().setConfig(config);
    jschsession.getSession().rekey();

    Channel channel=null;

    channel=jschsession.getSession().openChannel("shel l");
    fout=channel.getOutputStream();
    fin=channel.getInputStream();
    channel.connect();

    }catch(Exception e){e.printStackTrace();}
    }
    private void startreadThread(){new readInput().start();}
    private void shInputDialog(){

    JDialog d = new JDialog();
    JPanel p = new JPanel();
    final JTextField t = new JTextField();
    t.setPreferredSize(new Dimension(250, 20));
    JButton b = new JButton("Write");
    b.addActionListener(new java.awt.event.ActionListener() {

    public void actionPerformed(ActionEvent e) {
    try{
    fout.write(t.getText().getBytes());
    fout.write(KeyEvent.VK_ENTER);
    fout.flush();
    t.setText("");

    }catch(Exception ex){ex.printStackTrace();}
    }
    });
    p.add(t); p.add(b);
    d.add(p); d.pack();
    d.setVisible(true);

    }

    class readInput extends Thread{

    @Override
    public void run(){
    int b;
    try{
    while(true){
    b=fin.read();

    if(b!=-1){
    System.out.print((char)(b));

    }else{
    try{Thread.sleep(1000);}catch(InterruptedException intEx){}
    }
    }
    }catch(IOException ex){
    System.out.println("Reading from session caused an IOException. Out of read loop");
    }
    }
    }

    public static class MyUserInfo implements UserInfo, UIKeyboardInteractive{

    public String getPassword(){ return passwd; }
    public boolean promptYesNo(String str){
    Object[] options={ "yes", "no" };
    int foo=JOptionPane.showOptionDialog(null,
    str,
    "Warning",
    JOptionPane.DEFAULT_OPTION,
    JOptionPane.WARNING_MESSAGE,
    null, options, options[0]);
    return foo==0;
    }

    String passwd;
    JTextField passwordField=(JTextField)new JPasswordField(20);

    public String getPassphrase(){ return null; }
    public boolean promptPassphrase(String message){ return true; }
    public boolean promptPassword(String message){
    Object[] ob={passwordField};
    int result=JOptionPane.showConfirmDialog(null, ob, message,
    JOptionPane.OK_CANCEL_OPTION);
    if(result==JOptionPane.OK_OPTION){
    passwd=passwordField.getText();
    return true;
    }
    else{
    return false;
    }
    }
    public void showMessage(String message){
    JOptionPane.showMessageDialog(null, message);
    }
    public String[] promptKeyboardInteractive(String destination,
    String name, String instruction,
    String[] prompt, boolean[] echo){
    panel = new JPanel();
    panel.setLayout(new GridBagLayout());

    gbc.weightx = 1.0;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.gridx = 0;
    panel.add(new JLabel(instruction), gbc);
    gbc.gridy++;

    gbc.gridwidth = GridBagConstraints.RELATIVE;

    JTextField[] texts=new JTextField[prompt.length];
    for(int i=0; i<prompt.length; i++){
    gbc.fill = GridBagConstraints.NONE;
    gbc.gridx = 0;
    gbc.weightx = 1;
    panel.add(new JLabel(prompt[i]),gbc);

    gbc.gridx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weighty = 1;
    if(echo[i]){
    texts[i]=new JTextField(20);
    }
    else{
    texts[i]=new JPasswordField(20);
    }
    panel.add(texts[i], gbc);
    gbc.gridy++;
    }

    if(JOptionPane.showConfirmDialog(null, panel,
    destination+": "+name,
    JOptionPane.OK_CANCEL_OPTION,
    JOptionPane.QUESTION_MESSAGE)
    ==JOptionPane.OK_OPTION){
    String[] response=new String[prompt.length];
    for(int i=0; i<prompt.length; i++){
    response[i]=texts[i].getText();
    }
    return response;
    }
    else{
    return null; // cancel
    }
    }

    final GridBagConstraints gbc = new GridBagConstraints(0,0,1,1,1,1,
    GridBagConstraints.NORTHWEST,
    GridBagConstraints.NONE,
    new Insets(0,0,0,0),0,0);
    private Container panel;
    }

    private JSchSession jschsession=null;
    private OutputStream fout;
    private InputStream fin;
    }

Similar Threads

  1. Converting InputStream to OutputStream
    By Java Tip in forum Java Tip
    Replies: 1
    Last Post: 01-11-2008, 10:13 PM
  2. Replies: 0
    Last Post: 11-27-2007, 10:23 AM
  3. Reading bytes from InputStream
    By Java Tip in forum Java Tip
    Replies: 0
    Last Post: 11-25-2007, 07:51 PM
  4. Un expected behaviour when reading from inputstream
    By adoorsarath in forum Advanced Java
    Replies: 3
    Last Post: 08-10-2007, 05:02 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •