For my simple MUD client I'm using Apache Telnet (no, not ssh).  A mud client is a strange beast:Generally, a MUD client is a very basic telnet client that lacks VT100 terminal emulation and the capability to perform telnet negotiations.      ...      Standard features seen in most MUD clients include ANSI color support, aliases, triggers and scripting.      - WikipediaI would like for a not-yet-written Controller to have a reference to TelnetConnection and just use it for a higher level of abstraction for I/O, but all attempts to prise this class apart fail for me.  TelnetConnection seems to take on responsibility for everything, and then some, and just keep growing.package telnet;import java.io.IOException;import java.io.OutputStream;import java.net.InetAddress;import java.net.SocketException;import java.util.Deque;import java.util.Observable;import java.util.Observer;import java.util.logging.Logger;import org.apache.commons.net.telnet.TelnetClient;import player.GameAction;import player.DataFromRegex;import player.Regex;public class TelnetConnection implements Observer {    private static Logger log = Logger.getLogger(TelnetConnection.class.getName());    private TelnetClient telnetClient = new TelnetClient();    private InputOutput inputOutput = new InputOutput();    private Regex regexParser = new Regex();    private DataFromRegex data = null;    private Logic logic = new Logic();    public TelnetConnection() {        init();    }    private void init() {        try {            int port = 3000;            InetAddress host = InetAddress.getByName(rainmaker.wunderground.com);            telnetClient.connect(host, port);            inputOutput.readWriteParse(telnetClient.getInputStream(), telnetClient.getOutputStream());        } catch (SocketException ex) {        } catch (IOException ex) {        }        inputOutput.addObserver(this);    }    private void sendAction(GameAction action) throws IOException {        log.info(action.toString());        byte[] actionBytes = action.getAction().getBytes();        OutputStream outputStream = telnetClient.getOutputStream();        outputStream.write(actionBytes);        outputStream.write(13);        outputStream.write(10);        outputStream.flush();    }    private void sendActions(Deque<GameAction> gameActions) {        while (!gameActions.isEmpty()) {            GameAction action = gameActions.remove();            try {                sendAction(action);            } catch (IOException ex) {            }        }    }    @Override    public void update(Observable o, Object arg) {        String line = null;        if (o instanceof InputOutput) {            line = inputOutput.getLine();            log.fine(line);            data = regexParser.parse(line);            Deque<GameAction> gameActions = logic.getActions(data);            sendActions(gameActions);        }    }    public static void main(String[] args) {        new TelnetConnection();    }}Part of the difficulty lies within the InputOutput class, which is adapted from IOUtil from Apache.  (For some reason, I cannot include the link to to the Apache source code.)Once I send the InputStream to InputOutput there needs to be callback using Observable to then send the String data for matching and searching?  And then get back what after matching and searching the text?The trick being, in terms of I/O:capture console inputprint remote output from the MUD server to the console like regular telnetsome regex/etc on the remote output, concurrent with open, unterminated streams.  This last requirement seems to make an odd beast for which I cannot envision the flow of control and data.
how to model a connection to a resource, with rudimentary event processing
java;design patterns;object oriented;mvc;observer pattern
If you wanted to simplify the nitty gritty implementation details into a class called TelnetConnection, I definitely think that would be a wise idea, however it may be that you cannot do it with simply one class.  You may need to have a secondary class which deals with the asynchronous aspect of this.  Lets call this class TelnetObserver which implements Observer.Now in this way, it is still asynchronous, which makes your life difficult, so lets make it synchronous.  Make TelnetObserver implement Future<String>.  The idea is that you call get() whenever you're ready for the next line of input (waiting until input is available if necessary).Of course this doesn't happen on its own, we must make it synchronous by using an instance of CountDownLatch.  The purpose of CountDownLatch is to make a thread wait for an asynchronous job to finish within a certain timeframe.  I found an excellent example of this implementation here.Once you have this, TelnetConnection will handle the connection logic.  From there, TelnetConnection could also handle the parsing of the individual lines, but I wouldn't recommend it.  I would create another class TelnetParser which does that for you, given the input from TelnetObserver.  The resulting Object would then be returned to any listeners for input.  Alternatively on output, you use the same TelnetParser to convert from an Object to a String which TelnetObserver could send.  The basic interface for TelnetParser would likely look something like this:public class TelnetParser {    public Object parseFromString(String) {        ...    }    public String parseToString(Object) {        ...    }}The end result is that you have a model object which you can call upon to receive input or to send output.  This returns control back to the caller, or in this case your class Controller!  I hope that helps.  Good luck in your endeavor!