/* License * * Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistribution of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. */ import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import javax.microedition.io.*; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; /** * Demonstrates the telnet framework by connecting to the public * 'weather underground' service to retrieve the latest forecast. */ public class MIDTerm extends MIDlet implements CommandListener, Runnable { String host, port, city; TelnetCanvas canvas; TelnetConnection connection; InputStream input; OutputStream output; Command connectCommand, disconnectCommand, exitCommand; public MIDTerm() { host = getAppProperty( "MIDTerm-Host" ); if ( host == null ) host = "rainmaker.wunderground.com"; port = getAppProperty( "MIDTerm-Port" ); if ( port == null ) port = "3000"; city = getAppProperty( "MIDTerm-City" ); if ( city == null ) city = "DCA"; // washington dc connection = null; canvas = new TelnetCanvas(); Display.getDisplay(this).setCurrent( canvas ); connectCommand = new Command( "Start", Command.OK, 0 ); disconnectCommand = new Command( "Stop", Command.OK, 0 ); exitCommand = new Command( "Exit", Command.EXIT, 0 ); canvas.addCommand( exitCommand ); canvas.setCommandListener( this ); } /** * Connects on start up. */ public void startApp() { connect(); } /** * We don't know when we'll be resumed, * so we disconnect on pause. */ public void pauseApp() { disconnect(); } /** * Disconnects on exit. */ public void destroyApp( boolean unconditional ) { disconnect(); } /** * Disconnects any existing connection and * establishes a new connection on a new thread. */ public void connect() { disconnect(); canvas.removeCommand( connectCommand ); canvas.addCommand( disconnectCommand ); new Thread( this ).start(); } /** * Disconnects any existing connection. */ public void disconnect() { canvas.removeCommand( disconnectCommand ); canvas.addCommand( connectCommand ); if ( input != null ) { try { input.close(); input = null; } catch ( IOException ioe ) { System.err.println( "Error while disconnecting input: " + ioe.toString() ); canvas.receive( toASCII( "Error while disconnecting input: " + ioe.toString() ) ); } } if ( output != null ) { try { output.close(); output = null; } catch ( IOException ioe ) { System.err.println( "Error while disconnecting output: " + ioe.toString() ); canvas.receive( toASCII( "Error while disconnecting output: " + ioe.toString() ) ); } } if ( connection != null ) { try { connection.close(); connection = null; } catch ( IOException ioe ) { System.err.println( "Error while disconnecting: " + ioe.toString() ); canvas.receive( toASCII( "Error while disconnecting: " + ioe.toString() ) ); } } } // interface CommandListener public void commandAction( Command aCommand, Displayable aDisplayable ) { if ( aCommand == connectCommand ) { connect(); } else if ( aCommand == disconnectCommand ) { disconnect(); } else if ( aCommand == exitCommand ) { destroyApp( true ); notifyDestroyed(); } } // interface Runnable /** * This gets called on a separate thread to establish the connection, * communicate with the server, and read the content. */ public void run() { String connectString = "socket://" + host + ':' + port; try { canvas.receive( toASCII( "Connecting...\n" ) ); connection = new TelnetConnection( (StreamConnection) Connector.open( connectString, Connector.READ_WRITE, true ) ); input = connection.openInputStream(); output = connection.openOutputStream(); // server interaction script try { // suppress content until first "continue:" prompt waitUntil( input, new String[] { "ontinue:" }, false ); output.write( toASCII( "\n" ) ); output.flush(); // show content until city code prompt waitUntil( input, new String[] { "code--" }, true ); output.write( toASCII( city + '\n' ) ); canvas.receive( toASCII( city + '\n' ) ); output.flush(); // keep advancing pages until we find the "Selection:" prompt while ( !"Selection:".equals( waitUntil( input, new String[] { "X to exit:", "Selection:" }, true ) ) ) { output.write( toASCII( "\n" ) ); output.flush(); canvas.receive( toASCII( "\n" ) ); } // exit will cause disconnect output.write( toASCII( "X\n" ) ); output.flush(); canvas.receive( toASCII( "X\n" ) ); // we'll keep reading until we see "Done" or disconnected waitUntil( input, new String[] { "Done" }, true ); } catch ( IOException ioe ) { System.err.println( "Error while communicating: " + ioe.toString() ); canvas.receive( toASCII( "\nLost connection." ) ); } catch ( Throwable t ) { System.err.println( "Unexpected error while communicating: " + t.toString() ); canvas.receive( toASCII( "\nUnexpected error: " + t.toString() ) ); } } catch ( IllegalArgumentException iae ) { System.err.println( "Invalid host: " + host ); canvas.receive( toASCII( "Invalid host: " + host ) ); } catch ( ConnectionNotFoundException cnfe ) { System.err.println( "Connection not found: " + connectString ); canvas.receive( toASCII( "Connection not found: " + connectString ) ); } catch ( IOException ioe ) { System.err.println( "Error on connect: " + ioe.toString() ); canvas.receive( toASCII( "Error on connect: " + ioe.toString() ) ); } catch ( Throwable t ) { System.err.println( "Unexpected error on connect: " + t.toString() ); canvas.receive( toASCII( "Unexpected error on connect: " + t.toString() ) ); } // clean up disconnect(); canvas.receive( toASCII( "\nDisconnected.\n" ) ); } /** * Returns the String that matched, or null if end of input. */ private String waitUntil( InputStream inInput, String[] inMatches, boolean append ) throws IOException { int c, i; // no input or zero matches returns immediately if ( inInput == null || inMatches == null || inMatches.length == 0 ) { return null; } // zero-length strings return immediately for ( i = 0; i < inMatches.length; i++ ) { if ( inMatches[i].length() == 0 ) return inMatches[i]; } // create match trackers (init to zeroes) int[] lastMatch = new int[ inMatches.length ]; // now read input and check for match while ( ( c = inInput.read() ) != -1 ) { if ( append ) canvas.receive( (byte) c ); for ( i = 0; i < inMatches.length; i++ ) { if ( inMatches[i].charAt( lastMatch[i] ) == c ) { // increment match count if ( ++lastMatch[i] == inMatches[i].length() ) { // matched complete string: return return inMatches[i]; } } else // no match { // reset match count lastMatch[i] = 0; } } } // end of input return null; } /** * Convenience to convert String to ASCII bytes. */ private final static byte[] toASCII( String inString ) { char[] chars = inString.toCharArray(); byte[] bytes = new byte[ chars.length ]; for ( int i = 0; i < bytes.length; i++ ) bytes[i] = (byte) chars[i]; return bytes; } }