package ring.comms.telnet; import java.io.PrintStream; import java.util.Scanner; import ring.comms.CommunicationException; import ring.comms.Communicator; import ring.util.TextParser; public class TelnetStreamCommunicator implements Communicator { private TelnetInputStream lowlevelInput; private TelnetOutputStream lowlevelOutput; private Scanner in; private PrintStream out; private String suffix = ""; private boolean error = false; private boolean screenWidthParsing = true; private boolean newlineOnDataReceived = true; public TelnetStreamCommunicator(TelnetInputStream in, TelnetOutputStream out) { lowlevelInput = in; lowlevelOutput = out; this.in = new Scanner(in); this.out = new PrintStream(out); } @Override public void close() { in.close(); out.close(); } /** * Tells whether this Communicator has experienced an error in communicating * with its client or not. This variable gets set when different things * happen. For example: the player disconnects immediately instead of using * the quit command. * * @return */ public boolean isCommunicationError() { return error; } public boolean isSecure() { //TODO later, return true if connection is from localhost. return false; } public void setScreenWidthParsing(boolean val) { screenWidthParsing = val; } public boolean getScreenWidthParsing() { return screenWidthParsing; } private void doSendln(String data) throws CommunicationException { out.println(data); } private void doSend(String data) throws CommunicationException { out.print(data); } private boolean isValid(String data) { //return (!data.equals("") && data.length() > 0); return true; } private String formatData(String data, boolean useSuffix) { data = TextParser.trimNewlines(data); if (useSuffix) { StringBuilder sb = new StringBuilder(data); sb.append(getSuffix()); data = sb.toString(); } data = TextParser.parseOutgoingData(data, screenWidthParsing); return data; } /** * Basic method that sends data without a newline on the end. * * @param data */ public void print(String data) throws CommunicationException { if (isValid(data)) { data = formatData(data, true); doSend(data); } } /** * Sends a line of text to the client. * * @param data */ public void println(String data) throws CommunicationException { if (isValid(data)) { data = formatData(data, true); doSendln(data); } } /** * Sends a newline character to the client without the suffix. */ public void println() throws CommunicationException { out.println(); } public void printSuffix() { //This weirdness works because the low level input stream //echoes newlines. So, there is a newline generated when enter //is pressed, and thus one \n between two empty suffixes. out.print(formatData(getSuffix(), false)); } /** * Sends some text without appending the suffix. * * @param data */ public void printNoSuffix(String data) throws CommunicationException { if (isValid(data)) { data = formatData(data, false); doSend(data); } } /** * Sends a line of text without appending the suffix. * * @param data */ public void printlnNoSuffix(String data) { if (isValid(data)) { data = formatData(data, false); doSendln(data); } } /** * Prepends a newline character to the data after having parsed it normally * as per the send method. Also appends the suffix. This is mostly used for * sending data to the user from code external to the shell. Instead of the text * appearing in the middle of their command line it appears below it. * * @param data */ public void printWithPreline(String data) throws CommunicationException { if (isValid(data)) { data = formatData(data, true); data = "\n" + data; doSend(data); } } public void printNoSuffixWithPreline(String data) throws CommunicationException { if (isValid(data)) { data = formatData(data, false); data = "\n" + data; doSend(data); } } /** * Interjects a message into the client's screen, and then re-prints the suffix along * with any text the client had already typed. This provides for a clean, non-interrupted * interface when lots of external data is coming in. * @param message */ public void interject(String message) throws CommunicationException { String currentText = lowlevelInput.getCurrentBuffer(); currentText = TextParser.trimNewlines(currentText); message = TextParser.trimNewlines(message); message = message + getSuffix() + currentText; message = formatData(message, false); doSend(message); } /** * Sets the suffix that is appended to outgoing data in most versions of the * send command. In general, the suffix is a command prompt of some kind. * However, it can be used for other things. * * @param s - The suffix to use. */ public void setSuffix(String s) { suffix = s; } public String getSuffix() { return suffix; } /** * Waits for the user on the other end of this Communicator to send us some * data. The wait is indefinite until the idle timeout. After a while the * server will terminate the connection and the communication error variable * will be set. * * @return The received data. */ public String receiveData() throws CommunicationException { String s = in.nextLine(); if (getEchoReturn()) { println(); } return s; } public boolean isConnected() { //Terrible implementation. try { out.print(""); return true; } catch (Exception e) { return false; } } public TelnetInputStream getInputStream() { return lowlevelInput; } public TelnetOutputStream getOutputStream() { return lowlevelOutput; } public boolean getEchoReturn() { return newlineOnDataReceived; } public void setEchoReturn(boolean val) { newlineOnDataReceived = val; } }