//////////////////////////////////////////////////////////////////////////////// // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation; either version 3 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 Lesser General Public // License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with this program; if not, see <http://www.gnu.org/copyleft/lesser.html>. // //////////////////////////////////////////////////////////////////////////////// package org.merapi.internal; import java.io.BufferedInputStream; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.HashMap; import java.util.Properties; import java.util.logging.Level; //import org.merapi.internal.config.BridgeConfig; import org.merapi.handlers.IMessageHandler; import org.merapi.internal.io.amf.AMF3Reader; import org.merapi.internal.io.amf.AMF3Writer; import org.merapi.internal.io.reader.IReader; import org.merapi.internal.io.writer.IWriter; import org.merapi.messages.IMessage; import org.merapi.internal.systemexecute.handlers.SystemExecuteMessageHandler; import org.apache.log4j.Logger; import org.merapi.BridgeService; //import org.springframework.context.ApplicationContext; import org.merapi.io.utils.MessageLengthWriter; /** * The <code>Bridge</code> class is a singleton gateway to the Flex Merapi bridge. * IMessages are exchanged between this Java bridge object and the Flex bridge object. * * @see org.merapi.messages.IMessage; */ public class Bridge implements Runnable, BridgeService { //-------------------------------------------------------------------------- // // Class Constants // //-------------------------------------------------------------------------- public static final String CONFIG_PATH = "./config/merapi-native-config.xml"; public static final String READER_STRING = "reader"; public static final String WRITER_STRING = "writer"; public static final String PORT_STRING = "port"; //-------------------------------------------------------------------------- // // Class Properties // //-------------------------------------------------------------------------- /** * The port used to connect Merapi */ public static int PORT = 12345; //-------------------------------------------------------------------------- // // Class Methods // //-------------------------------------------------------------------------- /** * The single instance of the Merapi <code>Bridge</code> */ public static Bridge getInstance() { if ( instance == null ) { instance = new Bridge(); instance.registerHandlers(); } return instance; } /** * Opens the Merapi server socket */ public static void open() { if ( thread == null ) { Bridge.thread = new Thread( Bridge.getInstance() ); Bridge.thread.start(); Bridge.isRunning = true; } } /** * Closes the Merapi server socket */ public static void close() { Bridge.isRunning = false; Bridge.thread = null; try { instance.__server.close(); } catch ( IOException exception ) { Bridge.instance.__logger.error( exception ); } } //-------------------------------------------------------------------------- // // Class Variables // //-------------------------------------------------------------------------- private static Bridge instance = null; private static Thread thread = null; private static boolean isRunning = true; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. */ private Bridge() { // super(); readConfig(); __handlers = new HashMap<String, ArrayList<IMessageHandler>>(); } //-------------------------------------------------------------------------- // // Methods // //-------------------------------------------------------------------------- /** * Called by start() from the Threading API. */ public void run() { try { // Open the server socket __server = new ServerSocket( PORT ); // __server = new ServerSocket(PORT, 1, InetAddress.getByName("127.0.0.1")); __logger.info( "Merapi started on port: " + PORT ); System.out.println("LocalSocketAddress: " + __server.getLocalSocketAddress() + " InetAddress: " + __server.getInetAddress() + " Port: " + __server.getLocalPort()); if(Bridge.isRunning == true) System.out.println("Bridge is running"); else System.out.println("Bridge is not running"); while( Bridge.isRunning == true ) { // Get the first client that connects Socket temp = __server.accept(); __client = temp; System.out.println("Local Socket Address: " + __client.getLocalSocketAddress()); System.out.println("Remote Socket Address: " + __client.getRemoteSocketAddress()); System.out.println("InetAddress: " + __client.getInetAddress()); System.out.println("Reader: " + __reader.toString()); //outcommented in funzt // BufferedInputStream bin = new BufferedInputStream(__client.getInputStream()); // int b; // while ( ( b = bin.read() ) != -1 ) // { // // char c = (char)b; // // System.out.print(""+(char)b); //This prints out content that is unreadable. // //Isn't it supposed to print out html tag? // } //outcommented in funzt // Instantiate a listener thread that will listen and read the input stream // of the first client that connects and start the thread __clientListenerThread = new BridgeListenerThread( __client.getInputStream(), __reader ); System.out.println("Reader: " + __clientListenerThread.toString() + " StackTrace: " + __clientListenerThread.getStackTrace()); __clientListenerThread.start(); //outcommented in funzt // try { // Thread.sleep(250); // } catch (InterruptedException ex) { // java.util.logging.Logger.getLogger(Bridge.class.getName()).log(Level.SEVERE, null, ex); // } //outcommented in funzt } } catch ( IOException e ) { __logger.error( e.getMessage() ); } } /** * Dispatches an <code>IMessage</code> to registered listeners. */ public void dispatchMessage( IMessage message ) { // Get the list of handlers registered for the event type ArrayList<IMessageHandler> list = __handlers.get( message.getType() ); System.out.println("Message type received: (before Message Creation) --- " + message.getType()); // If the list is not null and not empty notify the registered event handlers if ( list != null && list.size() > 0 ) { for ( IMessageHandler handler : list ) { if ( handler != null ) { handler.handleMessage( message ); } } } } /** * Registers an <code>IMessageHandler</code> to be notified when messages of type * <code>type<code> are dispatched from the <code>Bridge</code>. */ public void registerMessageHandler( String type, IMessageHandler handler ) { // Get the list of handlers registered for the event type ArrayList<IMessageHandler> list = __handlers.get( type ); // If the list is null, create a new list to add 'handler' to if ( list == null ) { list = new ArrayList<IMessageHandler>(); __handlers.put( type, list ); } // Add the handler to the list list.add( handler ); } /** * Sends a <code>message</code> to the Flex side of the Merapi bridge. */ public void sendMessage( IMessage message ) throws Exception { if ( __client == null || __client.isClosed() ) return; byte[] bytes = __writer.write( message ); System.out.println( "Sending " + bytes.length + " bytes." ); // Send the length of the message first // __client.getOutputStream().write( bytes.length >> 24 ); // __client.getOutputStream().write( bytes.length >> 16 ); // __client.getOutputStream().write( bytes.length >> 8 ); // __client.getOutputStream().write( bytes.length ); __messageLengthWriter.write(__client, bytes.length); // Send the message __client.getOutputStream().write( bytes ); } /** * Unregisters a given handler. */ public void unRegisterMessageHandler( String type, IMessageHandler handler ) { // Get the list of handlers registered for the event type ArrayList<IMessageHandler> list = __handlers.get( type ); // If the list is not null and not empty, look for handler in the list and remove it // if a match is found if ( list != null && list.size() > 0 ) { for ( IMessageHandler activeHandler : list ) { if ( activeHandler == handler ) { list.remove( handler ); } } } } /** * @protected * * Instantiates the framework <code>IMessageHandlers</code>. */ protected void registerHandlers() { // Registers SystemExecuteHandler as the IMessageHandler of the // SystemExecuteMessage.SYSTEM_EXECUTE message type. new SystemExecuteMessageHandler(); } /** * @protected * * Loads the Bridge config via the BridgeConfig object. */ protected void readConfig() { // try // { // BridgeConfig bridgeConfig = new BridgeConfig( CONFIG_PATH ); // Properties config = bridgeConfig.getProps(); // ApplicationContext ctx = bridgeConfig.getContext(); // // __reader = (IReader) ctx.getBean( config.getProperty( READER_STRING ) ); // __writer = (IWriter) ctx.getBean( config.getProperty( WRITER_STRING ) ); // // PORT = Integer.parseInt( config.getProperty( PORT_STRING ) ); // // bridgeConfig = null; // } // // catch ( Exception e ) // { // __logger.error( e.getMessage() ); // } if ( __reader == null ) __reader = new AMF3Reader(); if ( __writer == null ) __writer = new AMF3Writer(); } //-------------------------------------------------------------------------- // // Variables // //-------------------------------------------------------------------------- /** * @private * * The socket that open connections to the Flex Merapi bridge. */ private ServerSocket __server = null; /** * @private * * The socket that connected to the Flex Merapi bridge. */ private Socket __client = null; /** * @private * * The thread that listens for messages from the Flex client socket. */ private BridgeListenerThread __clientListenerThread = null; /** * @private * * The <code>IWriter</code> used to serialize data sent across the bridge to Flex. */ private IWriter __writer = null; /** * @private * * The <code>IReader</code> used to deserialize data that comes across the bridge from Flex. */ private IReader __reader = null; /** * @private * * An instance of the log4j logger to handle the logging. */ private Logger __logger = Logger.getLogger( Bridge.class ); /** * @private * * A HashMap of registered event handlers. */ private HashMap<String, ArrayList<IMessageHandler>> __handlers = null; private MessageLengthWriter __messageLengthWriter = new MessageLengthWriter(); }