org.tdod.ether.ta.telnet.TelnetService.java Source code

Java tutorial

Introduction

Here is the source code for org.tdod.ether.ta.telnet.TelnetService.java

Source

/****************************************************************************
 * Ether Code base, version 1.0                                             *
 *==========================================================================*
 * Copyright (C) 2011 by Ron Kinney                                         *
 * All rights reserved.                                                     *
 *                                                                          *
 * This program 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 2 of the License, or     *
 * (at your option) any later version.                                      *
 *                                                                          *
 * This program 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.                             *
 *                                                                          *
 * Redistribution and use in source and binary forms, with or without       *
 * modification, are permitted provided that the following conditions are   *
 * met:                                                                     *
 *                                                                          *
 * * Redistributions of source code must retain this copyright notice,      *
 *   this list of conditions and the following disclaimer.                  *
 * * Redistributions in binary form must reproduce this copyright notice    *
 *   this list of conditions and the following disclaimer in the            *
 *   documentation and/or other materials provided with the distribution.   *
 *                                                                          *
 *==========================================================================*
 * Ron Kinney (ronkinney@gmail.com)                                         *
 * Ether Homepage:   http://tdod.org/ether                                  *
 ****************************************************************************/

package org.tdod.ether.ta.telnet;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import net.wimpi.telnetd.BootException;
import net.wimpi.telnetd.io.terminal.TerminalManager;
import net.wimpi.telnetd.net.PortListener;
import net.wimpi.telnetd.shell.ShellManager;
import net.wimpi.telnetd.util.PropertiesLoader;
import net.wimpi.telnetd.util.StringUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.meyling.telnet.startup.Loader;

/**
 * The telnet service.
 * @author rkinney
 */
public final class TelnetService {

    private static Log _log = LogFactory.getLog(TelnetService.class);

    /** The one and only instance of this telnet server. */
    private static TelnetService _instance = null;

    private ShellManager _shellManager;

    /** All port listeners. */
    private List<PortListener> _listeners;

    /**
     * A private constructor to enforce the singleton pattern.
     */
    private TelnetService() {
        _instance = this;
        _listeners = new ArrayList<PortListener>(5);
    }

    /**
     * Factory method to create a TelnetD singleton instance, loading the
     * standard properties files from the location
     *   <code>config/telnetd.properties</code>.
     *
     * @return     TenetD instance that has been properly set up according to the
     *             passed in properties, and is ready to start serving.
     * @throws     BootException    Setup process failed.
     */
    public static TelnetService createTelnetD() throws BootException {
        try {
            // try to load properties from classpath
            URL url = Loader.getResource("telnetd.properties");
            _log.info("url=" + url);
            if (url == null) {
                throw new BootException("Failed to load configuration file.");
            }
            Properties properties = PropertiesLoader.loadProperties(url);
            return createTelnetD(properties);
        } catch (IOException e) {
            _log.fatal(e, e);
            throw new BootException("Failed to load configuration file.");
        }
    }

    /**
     * Factory method to create a TelnetD Instance.
     *
     * @param     main    Properties object with settings for the TelnetD.
     * @return     TenetD instance that has been properly set up according to
     *             the passed in properties, and is ready to start serving.
     * @throws    BootException    Setup process failed.
     */
    public static TelnetService createTelnetD(final Properties main) throws BootException {

        if (_instance == null) {
            final TelnetService td = new TelnetService();
            td.prepareShellManager(main);
            td.prepareTerminals(main);
            final String[] listnames = StringUtil.split(main.getProperty("listeners"), ",");
            for (int i = 0; i < listnames.length; i++) {
                td.prepareListener(listnames[i], main);
            }
            return td;
        } else {
            throw new BootException("Singleton already instantiated.");
        }

    }

    /**
     * Start this telnet daemon, respectively all configured listeners.
     */
    public void start() {
        _log.debug("start()");
        for (int i = 0; i < _listeners.size(); i++) {
            final PortListener plis = (PortListener) _listeners.get(i);
            plis.start();
        }
    }

    /**
     * Stops the telnet service.
     */
    public void stop() {
        _log.debug("stop()");
        for (int i = 0; i < _listeners.size(); i++) {
            final PortListener plis = (PortListener) _listeners.get(i);
            plis.stop();
        }
    }

    /**
     * Prepares the terminal services.
     * @param terminals the terminal properties.
     * @throws BootException is thrown if initialization fails.
     */
    private void prepareTerminals(final Properties terminals) throws BootException {
        TerminalManager.createTerminalManager(terminals);
    }

    /**
     * Method to prepare the ShellManager.<br>
     *
     * Creates and prepares a Singleton instance of the ShellManager, with
     * settings from the passed in Properties.
     *
     * @param settings
     *            Properties object that holds main settings.
     * @throws BootException
     *             if preparation fails.
     */
    private void prepareShellManager(Properties settings) throws BootException {
        // use factory method for creating mgr singleton
        _shellManager = ShellManager.createShellManager(settings);
        if (_shellManager == null) {
            _log.fatal("creation of shell manager failed");
            System.exit(1);
        }
    }

    /**
     * Method to prepare the PortListener.<br>
     *
     * Creates and prepares and runs a PortListener, with settings from the
     * passed in Properties. Yet the Listener will not accept any incoming
     * connections before startServing() has been called. this has the advantage
     * that whenever a TelnetD Singleton has been factorized, it WILL 99% not
     * fail any longer (e.g. serve its purpose).
     *
     * @param   name            Name of listner.
     * @param     settings        Properties object that holds main settings.
     * @throws     BootException    Preparation failed.
     */
    private void prepareListener(final String name, final Properties settings) throws BootException {

        int port = 0;
        try {
            port = Integer.parseInt(settings.getProperty(name + ".port"));
            ServerSocket socket = new ServerSocket(port);
            socket.close();
        } catch (NumberFormatException e) {
            _log.fatal(e, e);
            throw new BootException(
                    "Failure while parsing port number for \"" + name + ".port\": " + e.getMessage());
        } catch (IOException e) {
            _log.fatal(e, e);
            throw new BootException(
                    "Failure while starting listener for port number " + port + ": " + e.getMessage());
        }
        // factorize PortListener
        final PortListener listener = PortListener.createPortListener(name, settings);
        // start the Thread derived PortListener
        try {
            _listeners.add(listener);
        } catch (Exception e) {
            _log.fatal(e, e);
            throw new BootException("Failure while starting PortListener thread: " + e.getMessage());
        }

    }

}