comikit.droidscript.DroidScriptServer.java Source code

Java tutorial

Introduction

Here is the source code for comikit.droidscript.DroidScriptServer.java

Source

package comikit.droidscript;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.http.util.EntityUtils;

import android.util.Log;

/**
 * Small http-server that accepts JavaScript PUT requests. 
 * Based on: http://hc.apache.org/
 * 
 * @author Mikael Kindborg
 * Email: mikael.kindborg@gmail.com
 * Blog: divineprogrammer@blogspot.com
 * Twitter: @divineprog
 * Copyright (c) Mikael Kindborg 2010
 * Source code license: MIT
 */
public class DroidScriptServer {
    static boolean loggingIsOn = true;
    int port = 4042;
    HttpHandler httpHandler;
    ServerThread server;

    public interface IRequestHandler {
        String handle(String requestType, String uri, String data);
    }

    public static DroidScriptServer create() {
        return new DroidScriptServer();
    }

    public static void log(String s) {
        if (loggingIsOn) {
            Log.i("DroidScriptServer", s);
        }
    }

    public static void setLoggingIsOn(boolean isOn) {
        loggingIsOn = isOn;
    }

    private DroidScriptServer() {
        httpHandler = new HttpHandler();
    }

    public DroidScriptServer setPort(int thePort) {
        port = thePort;
        return this;
    }

    public DroidScriptServer setRequestHandler(IRequestHandler handler) {
        httpHandler.setHandler(handler);
        return this;
    }

    public DroidScriptServer startServer() {
        try {
            server = new ServerThread(port, httpHandler);
            new Thread(server).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    public DroidScriptServer stopServer() {
        server.exit();
        return this;
    }

    public static String[] getIpAddresses() {
        try {
            List<String> ipaddresses = new ArrayList<String>();
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            while (interfaces.hasMoreElements()) {
                NetworkInterface interf = interfaces.nextElement();
                Enumeration<InetAddress> adresses = interf.getInetAddresses();
                while (adresses.hasMoreElements()) {
                    InetAddress address = adresses.nextElement();
                    if (!address.isLoopbackAddress()) {
                        ipaddresses.add(address.getHostAddress().toString());
                    }
                }
            }

            if (0 < ipaddresses.size()) {
                return ipaddresses.toArray(new String[1]);
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getIpAddressesAsString() {
        String[] ipaddresses = getIpAddresses();
        if (null != ipaddresses) {
            String addresses = "";
            boolean first = true;
            for (String ipaddress : ipaddresses) {
                if (!first) {
                    addresses = addresses + ", ";
                }
                addresses = addresses + ipaddress;
                first = false;
            }
            return addresses;
        }
        return "No ip-addresses found";
    }

    static class HttpHandler implements HttpRequestHandler {
        IRequestHandler handler;

        public HttpHandler() {
        }

        public HttpHandler setHandler(IRequestHandler handler) {
            this.handler = handler;
            return this;
        }

        public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws IOException {
            log("Request line: " + request.getRequestLine());
            for (Header h : request.getAllHeaders()) {
                log("Header: " + h.getName() + "=" + h.getValue());
            }

            String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
            if (method.equals("OPTIONS")) {
                response.setStatusCode(HttpStatus.SC_OK);
                response.addHeader("Access-Control-Allow-Origin", "*");
                response.addHeader("Access-Control-Allow-Methods", "GET, PUT, OPTIONS");
                response.addHeader("Access-Control-Max-Age", "1728000");
                Header header = request.getFirstHeader("Access-Control-Request-Headers");
                if (null != header) {
                    response.addHeader("Access-Control-Allow-Headers", header.getValue());
                }

                log("Responding to OPTIONS");

                return;
            }

            if (method.equals("PUT")) {
                log("Start PUT");

                response.setStatusCode(HttpStatus.SC_OK);
                // response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
                response.addHeader("Access-Control-Allow-Origin", "*");
                response.addHeader("Connection", "close");

                if (request instanceof HttpEntityEnclosingRequest) {
                    HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
                    String content = EntityUtils.toString(entity, "UTF-8");
                    String result = handler.handle("PUT", request.getRequestLine().getUri(), content);
                    response.setEntity(createBody(result));
                }

                log("End PUT");

                return;
            }

            if (method.equals("GET")) {
                log("Start GET");

                response.setStatusCode(HttpStatus.SC_OK);
                response.addHeader("Access-Control-Allow-Origin", "*");
                response.addHeader("Connection", "close");

                String result = handler.handle("GET", URLDecoder.decode(request.getRequestLine().getUri(), "UTF-8"),
                        "");

                response.setEntity(createBody(result));

                log("End GET");

                return;
            }
        }

        EntityTemplate createBody(final String text) {
            EntityTemplate body = new EntityTemplate(new ContentProducer() {
                public void writeTo(final OutputStream outstream) throws IOException {
                    OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8");
                    writer.write(text);
                    writer.flush();
                }
            });
            body.setContentType("text/html; charset=UTF-8");
            return body;
        }
    }

    static class ServerThread implements Runnable {
        int serverPort;
        HttpParams httpParams;
        HttpService httpService;
        ServerSocket serversocket = null;

        public ServerThread(int port, HttpRequestHandler requestHandler) throws IOException {
            serverPort = port;

            // Set HTTP parameters.
            httpParams = new BasicHttpParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
                    .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
                    .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
                    .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
                    .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "RhinoDroid/1.1");

            // Set up the HTTP protocol processor.
            BasicHttpProcessor httpProcessor = new BasicHttpProcessor();
            httpProcessor.addInterceptor(new ResponseDate());
            httpProcessor.addInterceptor(new ResponseServer());
            httpProcessor.addInterceptor(new ResponseContent());
            httpProcessor.addInterceptor(new ResponseConnControl());

            // Set up request handler.
            HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
            reqistry.register("*", requestHandler);

            // Set up the HTTP service.
            httpService = new HttpService(httpProcessor, new DefaultConnectionReuseStrategy(),
                    new DefaultHttpResponseFactory());
            httpService.setParams(httpParams);
            httpService.setHandlerResolver(reqistry);

            // Create server socket.
            serversocket = new ServerSocket(serverPort);
        }

        public void exit() {
            try {
                serversocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void run() {
            Socket socket = null;
            DefaultHttpServerConnection connection = null;

            // TODO: Kolla hur detta aar gjort i webbservern i kodexemplet:
            // http://svn.apache.org/repos/asf/httpcomponents/httpcore/branches/4.0.x/httpcore/src/examples/org/apache/http/examples/ElementalHttpServer.java

            try {
                log("Listening on port " + serversocket.getLocalPort());

                while (!serversocket.isClosed() && !Thread.interrupted()) {
                    log("Waiting for connection");

                    try {
                        // Set up HTTP connection.
                        socket = serversocket.accept();
                        connection = new DefaultHttpServerConnection();
                        log("Incoming connection from " + socket.getInetAddress());
                        connection.bind(socket, httpParams);

                        while (!serversocket.isClosed() && connection.isOpen() && !Thread.interrupted()) {
                            httpService.handleRequest(connection, new BasicHttpContext(null));
                        }

                        log("Exit request handler loop");
                    } catch (Exception e) {
                        e.printStackTrace();
                        // throw e;
                    } finally {
                        log("Closing connection - about to");
                        if (null != connection) {
                            log("Closing connection");
                            connection.close();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    log("Closing server socket");
                    serversocket.close();
                } catch (IOException ignore) {
                    ignore.printStackTrace();
                }
            }

            log("Exit server thread");
        }
    }
}

//              
// });
// body.setContentType("text/html; charset=UTF-8");
// response.setEntity(body);

// String method =
// request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
// if (!method.equals("GET") && !method.equals("HEAD") &&
// !method.equals("POST")) {
// throw new MethodNotSupportedException(method + " method not supported");
// }
// String target = request.getRequestLine().getUri();
//
// if (request instanceof HttpEntityEnclosingRequest) {
// HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
// byte[] entityContent = EntityUtils.toByteArray(entity);
// System.out.println("Incoming entity content (bytes): " +
// entityContent.length);
// }
//            
// final File file = new File(this.docRoot, URLDecoder.decode(target));
// if (!file.exists()) {
//
// response.setStatusCode(HttpStatus.SC_NOT_FOUND);
// EntityTemplate body = new EntityTemplate(new ContentProducer()
// {
// public void writeTo(final OutputStream outstream) throws IOException {
// OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8");
// writer.write("<html><body><h1>");
// writer.write("File ");
// writer.write(file.getPath());
// writer.write(" not found");
// writer.write("</h1></body></html>");
// writer.flush();
// }
// });
// body.setContentType("text/html; charset=UTF-8");
// response.setEntity(body);
// System.out.println("File " + file.getPath() + " not found");
//                
// } else if (!file.canRead() || file.isDirectory()) {
//                
// response.setStatusCode(HttpStatus.SC_FORBIDDEN);
// EntityTemplate body = new EntityTemplate(new ContentProducer() {
//                    
// public void writeTo(final OutputStream outstream) throws IOException {
// OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8");
// writer.write("<html><body><h1>");
// writer.write("Access denied");
// writer.write("</h1></body></html>");
// writer.flush();
// }
//                    
// });
// body.setContentType("text/html; charset=UTF-8");
// response.setEntity(body);
// System.out.println("Cannot read file " + file.getPath());
//                
// } else {
//                
// response.setStatusCode(HttpStatus.SC_OK);
// FileEntity body = new FileEntity(file, "text/html");
// response.setEntity(body);
//                
// }

// static class StreamWriter
// {
// public void write(OutputStream out, String data)
// {
// try
// {
// DataOutputStream stream = new DataOutputStream(out);
// stream.writeChars(data);
// stream.flush();
// }
// catch (Exception e)
// {
// e.printStackTrace();
// }
// }
// }

// static class ServerOld implements Runnable
// {
// Object theActivity;
// Evaluator theEvaluator;
//        
// public ServerOld(Object activity, Evaluator evaluator)
// {
// theActivity = activity;
// theEvaluator = evaluator;
// }
//        
// public void run()
// {
// boolean shutdown = false;
// while (!shutdown)
// {
// print("Welcome to JavaScript on Android!");
// try
// {
// //Evaluator theEvaluator = new Evaluator(theActivity);
// ServerSocket serversocket = new ServerSocket(4042);
//                    
// boolean restart = false;
// while (!restart)
// {
// print("Waiting for connection...");
// Socket socket = serversocket.accept();
// print("Connected!");
//                        
// // Read from socket
// InputStream in = socket.getInputStream();
// OutputStream out = socket.getOutputStream();
// HttpRequest request = new HttpRequest(in);
// request.parseHeader();
// String data = request.readContents();
//                        
// print("data: " + data);
//                        
// if (data.startsWith("restart"))
// {
// restart = true;
// socket.close();
// break;
// }
//                        
// if (data.startsWith("shutdown"))
// {
// restart = true;
// shutdown = true;
// socket.close();
// break;
// }
//                        
// // Evaluate
// Object result = theEvaluator.evalInUiThread(data);
// // Object result = new String("Android here!");
//                        
// // Send reply.
// PrintStream output = new PrintStream(out);
// output.print(result.toString());
// output.close();
// request.close();
// socket.close();
// } // while
//                    
// serversocket.close();
// theEvaluator.exit();
// }
// catch (Exception e)
// {
// e.printStackTrace();
// }
// } // while
// } // run
// } // class Server