package org.yi.worthing.scott.ant;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.taskdefs.MatchingTask;
import com.oroinc.net.telnet.*;
import org.apache.tools.ant.BuildException;
import java.io.*;
import java.lang.*;
import java.util.*;

/**
 * Class to provide automated telnet protocol support for the Ant build tool
 *
 * TelnetTask.java 
 * @author Scott Carlson<a href="mailto:ScottCarlson@email.com">ScottCarlson@email.com</a>
 * @version $Revision: 1.3 $
 */

public class TelnetTask extends Task {
    /**
     *  The userid to login with, if automated login is used
     */
    private String userid  = null;

    /**
     *  The password to login with, if automated login is used
     */
    private String password= null;

    /**
     *  The server to connect to. 
     */
    private String server  = null;

    /**
     *  The tcp port to connect to. 
     */
    private int port = 23;

    /**
     *  The Object which handles the telnet session.
     */
    private AntTelnetClient telnet = null;

    /**
     *  The list of read/write commands for this session
     */
    private ArrayList telnetTasks = new ArrayList();

    /** 
     *  Verify that all parameters are included. 
     *  Connect and possibly login
     *  Iterate through the list of Reads and writes 
     */
    public void execute() throws BuildException 
    {
       /**  A server name is required to continue */
       if (server== null)
           throw new BuildException("No Server Specified");
       /**  A userid and password must appear together 
        *   if they appear.  They are not required.
        */
       if (userid == null && password != null)
           throw new BuildException("No Userid Specified");
       if (password == null && userid != null)
           throw new BuildException("No Password Specified");

       /**  Create the telnet client object */
       telnet = new AntTelnetClient();
       try {
           telnet.connect(server, port);
       } catch(IOException e) {
           throw new BuildException("Can't connect to "+server);
       }
       /**  Login if userid and password were specified */
       if (userid != null && password != null)
          login();
       /**  Process each sub command */
       Iterator tasksToRun = telnetTasks.iterator();
       while (tasksToRun!=null && tasksToRun.hasNext())
       {
           TelnetSubTask task = (TelnetSubTask) tasksToRun.next();
           task.execute(telnet);
       }
    }

    /**  
     *  Process a 'typical' login.  If it differs, use the read 
     *  and write tasks explicitely
     */
    private void login()
    {
       telnet.waitForString("ogin:");
       telnet.sendString(userid);
       telnet.waitForString("assword:");
       telnet.sendString(password);
    }

    /**
     *  Set the userid attribute 
     */
    public void setUserid(String u) { this.userid = u; }
    /**
     *  Set the password attribute 
     */
    public void setPassword(String p) { this.password = p; }
    /**
     *  Set the server address attribute 
     */
    public void setServer(String m) { this.server = m; }
    /**
     *  Set the tcp port to connect to attribute 
     */
    public void setPort(String p) { this.port = Integer.parseInt(p); }

    /**
     *  A subTask <read> tag was found.  Create the object, 
     *  Save it in our list, and return it.
     */
   
    public TelnetSubTask createRead()
    {
        TelnetSubTask task = (TelnetSubTask)new TelnetRead();
        telnetTasks.add(task);
        return task;
    }

    /**
     *  A subTask <write> tag was found.  Create the object, 
     *  Save it in our list, and return it.
     */
    public TelnetSubTask createWrite()
    {
        TelnetSubTask task = (TelnetSubTask)new TelnetWrite();
        telnetTasks.add(task);
        return task;
    }

    /**  
     *  This class is the parent of the Read and Write tasks.
     *  It handles the common attributes for both.
     */
    public class TelnetSubTask extends MatchingTask
    {
        protected String taskString= null;
        public void execute(AntTelnetClient telnet) 
                throws BuildException
        {
            throw new BuildException("Shouldn't be able instantiate a SubTask directly");
        }
        public void addText(String s) { setString(s);}
        public void setString(String s)
        {
           taskString= s; 
        }
    }
    /**
     *  This class sends text to the connected server 
     */
    public class TelnetWrite extends TelnetSubTask
    {
        public void execute(AntTelnetClient telnet) 
               throws BuildException
        {
            telnet.sendString(taskString);
        }
    }
    /**
     *  This class reads the output from the connected server
     *  until the required string is found. 
     */
    public class TelnetRead extends TelnetSubTask
    {
        public void execute(AntTelnetClient telnet) 
               throws BuildException
        {
            telnet.waitForString(taskString);
        }
    }
    /**
     *  This class handles the abstraction of the telnet protocol.
     *  Currently it is a wrapper around <a href="www.oroinc.com">ORO</a>'s 
     *  NetComponents
     */
    public class AntTelnetClient extends TelnetClient
    {
      public void waitForString(String s)
      {
        InputStream is =this.getInputStream();
        try {
          StringBuffer sb = new StringBuffer();
          while (sb.toString().indexOf(s) == -1)
          {
              while (is.available() == 0);
              int iC = is.read();
              Character c = new Character((char)iC);
              sb.append(c);
              System.out.print(c);
          }
        } catch (Exception e)
        { 
          e.printStackTrace();
          System.exit(1);
        }
      }
    
      public void sendString(String s)
      {
        OutputStream os =this.getOutputStream();
        try {
          os.write((s + "\n").getBytes());
          System.out.println(s );
          os.flush();
        } catch (Exception e)
        { 
          e.printStackTrace();
          System.exit(1);
        }
      }
    }
}
