com.comcast.cats.telnet.TelnetConnection.java Source code

Java tutorial

Introduction

Here is the source code for com.comcast.cats.telnet.TelnetConnection.java

Source

/**
 * Copyright 2014 Comcast Cable Communications Management, LLC
 *
 * This file is part of CATS.
 *
 * CATS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * CATS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with CATS.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.comcast.cats.telnet;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.SocketException;
import java.util.Date;

import org.apache.commons.net.telnet.TelnetClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Represents a generic telnet connection.
 *
 * @author skurup00c
 *
 */
public class TelnetConnection {
    private InputStream is;
    private PrintStream os;
    private String host;
    private Integer port;
    private String defaultPromptString;
    private TelnetClient telnetClient;
    private Integer defaultReadTimeout;
    protected Date lastActiveTime;
    protected Boolean isConnected = false;
    private boolean isBusy = false;

    public static final int DEFAULT_READ_TIMEOUT = 60000;//1 * 60 * 1000;   one minute

    public static final int DEFAULT_TIMEOUT = 300000;//5 * 60 * 1000;

    private static Logger logger = LoggerFactory.getLogger(TelnetConnection.class);

    /**
     * Creates a TelnetConnection insatnce.
     *
     * @param ip
     *            : of the telnet device
     * @param port
     *            : telnet port
     * @param defaultPromptString
     *            : default prompt string to be used. Usually ">".
     *
     */
    public TelnetConnection(String host, Integer port, String defaultPromptString) {
        this.host = host;
        this.port = port;
        this.defaultPromptString = defaultPromptString;
        this.telnetClient = new TelnetClient();
        setDefaultReadTimeout(DEFAULT_READ_TIMEOUT);
        lastActiveTime = new Date();
    }

    /**
     * Connect to the telnet client.
     *
     * @param isEnterRequired
     *            : sometime an ENTER key maybe required to reach the prompt.
     *
     * @return true: if connected.
     *
     * @throws SocketException
     * @throws IOException
     */
    public synchronized Boolean connect(Boolean isEnterRequired) throws SocketException, IOException {
        if (!isConnected) {
            try {
                telnetClient.connect(getHost(), getPort());
                logger.info("connected to telnet host " + host + " port " + port + " defaultPromptString "
                        + defaultPromptString);
            } catch (SocketException e) {
                logger.warn("Could not connect to telnetSession " + e.getMessage());
                throw new SocketException(e.getMessage());
            }
            is = telnetClient.getInputStream();
            os = new PrintStream(telnetClient.getOutputStream());
            if (isEnterRequired) {
                os.println();
            }

            isConnected = true;
            lastActiveTime = new Date();
        }

        return isConnected;
    }

    /**
     * Connect to the telnet client with a password.
     *
     * @param isEnterRequired
     *            : sometime an ENTER key maybe required to reach the prompt.
     *
     * @param password
     * @param passwordPromptString
     *            : the prompt that asks for a password : usually something like
     *            "Enter Password :"
     * @return true if connected successfully
     * @throws SocketException
     * @throws IOException
     */
    public synchronized Boolean connectWithPassword(String password, String passwordPromptString,
            Boolean isEnterRequired) throws SocketException, IOException {
        if (!isConnected && password != null && passwordPromptString != null) {
            try {
                telnetClient.connect(getHost(), getPort());
                logger.info("connected to telnet host " + host + " port " + port);
            } catch (SocketException e) {
                logger.warn("Could not connect to telnetSession " + e.getMessage());
                throw new SocketException(e.getMessage());
            }

            is = telnetClient.getInputStream();
            os = new PrintStream(telnetClient.getOutputStream());

            if (isEnterRequired) {
                os.println();
            }

            String passwordPrompt = readUntil(passwordPromptString);
            logger.debug("passwordPrompt " + passwordPrompt);
            if (passwordPrompt != null) {
                write(password);
                isConnected = true;
                lastActiveTime = new Date();
            } else {
                logger.info("Prompt string could not be reached");
                disconnect();
            }

        }
        return isConnected;
    }

    /**
     * Disconnects a telnet session.
     *
     * @throws IOException
     */
    public synchronized void disconnect() throws IOException {
        if (is != null) {
            is.close();
        }
        if (os != null) {
            os.close();
        }
        logger.trace("dicsonnecting telnetClient");
        if (telnetClient.isConnected()) {
            telnetClient.disconnect();
        }
        is = null;
        os = null;
        isConnected = false;

        logger.info("disconnected telnetConnection " + host + " port " + port);
    }

    /**
     * Status of telnet connection
     *
     * @return true if connected.
     */
    public synchronized Boolean isConnected() {
        return isConnected;
    }

    /**
     * Send a command to the telnet session. Requires
     * TelnetConnection.isConnected() to be true.
     *
     * @param command
     *            to send
     * @return returned value in telnet client after execution of command.
     * @throws IOException
     */
    public synchronized String sendCommand(String command) throws IOException {
        return sendCommand(command, defaultPromptString);
    }

    /**
     * Send a command to the telnet session, and read till the following prompt
     * instead of the default prompt.
     *
     * Requires TelnetConnection.isConnected() to be true.
     *
     * @param command
     * @param prompt
     * @return
     * @throws IOException
     */
    public synchronized String sendCommand(String command, String prompt) throws IOException {
        isBusy = true;
        logger.trace("sendCommand " + command + " prompt " + prompt);
        String result = null;
        if (isConnected && command != null) {
            write(command);
            result = readUntil(prompt);
        }
        lastActiveTime = new Date();
        isBusy = false;
        return result;
    }

    /**
     * if prompt string is not recieved within the default timeout value, the
     * read will be interrupted. This is important to avoid the connection to
     * hang on a read when the prompt string does not arrive. Default value is 1
     * minute.
     *
     * @return defaultTimeout value
     */
    public Integer getDefaultReadTimeout() {
        return defaultReadTimeout;
    }

    /**
     * Timeout to that closes the socket during a period of inactivity.
     *
     */
    public void setDefaultReadTimeout(Integer defaultReadTimeout) {
        this.defaultReadTimeout = defaultReadTimeout;
    }

    /**
     * This just provides the Output stream to write to the telnet connection.
     * Should be called only after a connect is called. This is to provide users
     * with an option to write stuff to the telnet connection other than what is
     * provided through this class. Its the responsibility of the user to
     * understand the working of TelnetConnection and the proper use of the
     * PrintStream
     *
     */
    public PrintStream getPrintStream() {
        return os;
    }

    /**
     * This just provides the input stream to write to the telnet connection.
     * Should be called only after a connect is called. This is to provide users
     * with an option to read stuff from the telnet connection other than what
     * is provided through this class. Its the responsibility of the user to
     * understand the working of TelnetConnection and the proper use of the
     * input
     *
     */
    public InputStream getInputStream() {
        return is;
    }

    /**
     * Get the last time a connect, or sendCommand was sent. can be used to
     * determine timeout to disconnect based on inactivity etc.
     *
     * @return
     */
    public Date getLastActiveTime() {
        return lastActiveTime;
    }

    public String getHost() {
        return host;
    }

    public Integer getPort() {
        return port;
    }

    public boolean isBusy() {
        return isBusy;
    }

    /**
     *
     * Reads Telnet response.
     *
     * @param pattern
     * @return
     * @throws IOException
     */
    private synchronized String readUntil(String pattern) throws IOException {
        logger.trace("readUntil " + pattern);
        String retVal = null;
        if (is != null) {
            StringBuffer sb = new StringBuffer();
            char lastChar = pattern.charAt(pattern.length() - 1);
            char ch;
            telnetClient.setSoTimeout(defaultReadTimeout);
            logger.trace("getDefaultReadTimeout() " + defaultReadTimeout);
            while (true) {
                try {
                    int readByte = is.read();
                    if (readByte != -1) {
                        ch = (char) readByte;
                    } else {
                        logger.warn("TelnetConnection: End of stream reached. Maybe remote end crashed ");
                        disconnect();
                        throw new IOException("TelnetConnection: End of stream reached. Maybe remote end crashed ");
                    }
                } catch (IOException e) {
                    logger.warn("Error occured in TelnetConnect readUntil " + e.getMessage());
                    disconnect();
                    throw new IOException(e);
                }
                sb.append(ch);
                if (ch == lastChar) {
                    if (sb.toString().endsWith(pattern)) {
                        String string = sb.toString();
                        retVal = string.substring(0, string.length() - pattern.length());
                        logger.trace("readUntil string " + retVal);
                        break;
                    }
                }

            }
        }
        return retVal;
    }

    /**
     * Sends actual Telnet command.
     *
     * @param value
     */
    private synchronized void write(String value) {
        if (null != os) {
            logger.trace("write value " + value);
            os.println(value);
            os.flush();
        }
    }
}