001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.io.remotecontrol;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.io.IOException;
007    import java.net.BindException;
008    import java.net.ServerSocket;
009    import java.net.Socket;
010    import java.net.SocketException;
011    import java.net.InetAddress;
012    
013    /**
014     * Simple HTTP server that spawns a {@link RequestProcessor} for every
015     * connection.
016     *
017     * Taken from YWMS plugin by frsantos.
018     */
019    public class RemoteControlHttpServer extends Thread {
020    
021        /** Default port for the HTTP server */
022        public static final int DEFAULT_PORT = 8111;
023    
024        /** The server socket */
025        private ServerSocket server;
026    
027        private static RemoteControlHttpServer instance;
028    
029        /**
030         * Starts or restarts the HTTP server
031         */
032        public static void restartRemoteControlHttpServer() {
033            try {
034                if (instance != null) {
035                    instance.stopServer();
036                }
037    
038                instance = new RemoteControlHttpServer(DEFAULT_PORT);
039                instance.start();
040            } catch (BindException ex) {
041                System.err.println(tr("Warning: Cannot start remotecontrol server on port {0}: {1}",
042                        Integer.toString(DEFAULT_PORT), ex.getLocalizedMessage()));
043            } catch (IOException ioe) {
044                ioe.printStackTrace();
045            }
046        }
047    
048        /**
049         * Constructor
050         * @param port The port this server will listen on
051         * @throws IOException when connection errors
052         */
053        public RemoteControlHttpServer(int port)
054            throws IOException
055        {
056            super("RemoteControl HTTP Server");
057            this.setDaemon(true);
058            // Start the server socket with only 1 connection.
059            // Also make sure we only listen
060            // on the local interface so nobody from the outside can connect!
061            this.server = new ServerSocket(port, 1,
062                InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }));
063        }
064    
065        /**
066         * The main loop, spawns a {@link RequestProcessor} for each connection
067         */
068        public void run()
069        {
070            System.out.println("RemoteControl::Accepting connections on port " + server.getLocalPort());
071            while (true)
072            {
073                try
074                {
075                    Socket request = server.accept();
076                    RequestProcessor.processRequest(request);
077                }
078                catch( SocketException se)
079                {
080                    if( !server.isClosed() )
081                        se.printStackTrace();
082                    }
083                catch (IOException ioe)
084                {
085                    ioe.printStackTrace();
086                }
087            }
088        }
089    
090        /**
091         * Stops the HTTP server
092         *
093         * @throws IOException
094         */
095        public void stopServer() throws IOException
096        {
097            server.close();
098        }
099    }