com.simba.demo.airplay.lab.SimbaHttpServer.java Source code

Java tutorial

Introduction

Here is the source code for com.simba.demo.airplay.lab.SimbaHttpServer.java

Source

/*
 * ====================================================================
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */

package com.simba.demo.airplay.lab;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.InetSocketAddress;
import java.nio.charset.CodingErrorAction;
import java.util.Locale;

import simba.org.apache.http.HttpException;
import simba.org.apache.http.HttpRequest;
import simba.org.apache.http.HttpResponse;
import simba.org.apache.http.HttpResponseInterceptor;
import simba.org.apache.http.MethodNotSupportedException;
import simba.org.apache.http.impl.DefaultConnectionReuseStrategy;
import simba.org.apache.http.impl.nio.DefaultHttpServerIODispatch;
import simba.org.apache.http.impl.nio.DefaultNHttpServerConnection;
import simba.org.apache.http.impl.nio.DefaultNHttpServerConnectionFactory;
import simba.org.apache.http.impl.nio.reactor.DefaultListeningIOReactor;
import simba.org.apache.http.nio.NHttpConnectionFactory;
import simba.org.apache.http.nio.NHttpServerConnection;
import simba.org.apache.http.nio.protocol.BasicAsyncRequestConsumer;
import simba.org.apache.http.nio.protocol.BasicAsyncResponseProducer;
import simba.org.apache.http.nio.protocol.HttpAsyncExchange;
import simba.org.apache.http.nio.protocol.HttpAsyncRequestConsumer;
import simba.org.apache.http.nio.protocol.HttpAsyncRequestHandler;
import simba.org.apache.http.nio.protocol.HttpAsyncRequestHandlerRegistry;
import simba.org.apache.http.nio.protocol.HttpAsyncService;
import simba.org.apache.http.nio.reactor.IOEventDispatch;
import simba.org.apache.http.nio.reactor.ListeningIOReactor;
import simba.org.apache.http.params.BasicHttpParams;
import simba.org.apache.http.params.CoreConnectionPNames;
import simba.org.apache.http.params.CoreProtocolPNames;
import simba.org.apache.http.params.HttpParams;
import simba.org.apache.http.protocol.HttpContext;
import simba.org.apache.http.protocol.HttpProcessor;
import simba.org.apache.http.protocol.ImmutableHttpProcessor;
import simba.org.apache.http.protocol.ResponseConnControl;
import simba.org.apache.http.protocol.ResponseContent;
import simba.org.apache.http.protocol.ResponseDate;
import simba.org.apache.http.protocol.ResponseServer;
import android.util.Log;

/**
 * HTTP/1.1 file server based on the non-blocking I/O model and capable of
 * direct channel (zero copy) data transfer.
 */
public class SimbaHttpServer extends Thread {
    private static final String tag = "SimbaHttpServer";
    private int mPort = -1;
    private RequestCallback mRC;

    public interface RequestCallback {
        public void onPOST(HttpRequest request, HttpResponse response, HttpContext context);

        public void onGET(HttpRequest request, HttpResponse response, HttpContext context);

        public void onHEAD(HttpRequest request, HttpResponse response, HttpContext context);
    }

    public SimbaHttpServer(int port) {
        mPort = port;
    }

    public SimbaHttpServer(int port, RequestCallback rc) {
        this(port);
        mRC = rc;
    }

    @Override
    public void run() {
        // HTTP parameters for the server
        HttpParams params = new BasicHttpParams();
        params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
        params.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024);
        params.setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpTest/1.1");
        params.setParameter(CoreProtocolPNames.HTTP_MALFORMED_INPUT_ACTION, CodingErrorAction.IGNORE);
        // Create HTTP protocol processing chain
        HttpProcessor httpproc = new ImmutableHttpProcessor(new HttpResponseInterceptor[] {
                // Use standard server-side protocol interceptors
                new ResponseDate(), new ResponseServer(), new ResponseContent(), new ResponseConnControl() });
        // Create request handler registry
        HttpAsyncRequestHandlerRegistry reqistry = new HttpAsyncRequestHandlerRegistry();
        // Register the default handler for all URIs
        reqistry.register("*", new SimbaHttpHandler());
        // Create server-side HTTP protocol handler
        HttpAsyncService protocolHandler = new HttpAsyncService(httpproc, new DefaultConnectionReuseStrategy(),
                reqistry, params) {

            @Override
            public void connected(final NHttpServerConnection conn) {
                LOGD(conn + ": connection open");
                super.connected(conn);
            }

            @Override
            public void closed(final NHttpServerConnection conn) {
                LOGD(conn + ": connection closed");
                super.closed(conn);
            }

        };
        // Create HTTP connection factory
        NHttpConnectionFactory<DefaultNHttpServerConnection> connFactory = new DefaultNHttpServerConnectionFactory(
                params);

        // Create server-side I/O event dispatch
        IOEventDispatch ioEventDispatch = new DefaultHttpServerIODispatch(protocolHandler, connFactory);
        // Create server-side I/O reactor
        try {
            ListeningIOReactor ioReactor = new DefaultListeningIOReactor();
            // Listen of the given port
            InetSocketAddress isa = new InetSocketAddress(mPort);
            ioReactor.listen(isa);
            // Ready to go!
            ioReactor.execute(ioEventDispatch);
        } catch (InterruptedIOException ex) {
            LOGE("Interrupted");
        } catch (IOException e) {
            LOGE("I/O error: " + e.getMessage());
        }
        LOGD("Shutdown");
    }

    private class SimbaHttpHandler implements HttpAsyncRequestHandler<HttpRequest> {

        public SimbaHttpHandler() {
            super();
        }

        public HttpAsyncRequestConsumer<HttpRequest> processRequest(final HttpRequest request,
                final HttpContext context) {
            // Buffer request content in memory for simplicity
            return new BasicAsyncRequestConsumer();
        }

        public void handle(final HttpRequest request, final HttpAsyncExchange httpexchange,
                final HttpContext context) throws HttpException, IOException {
            HttpResponse response = httpexchange.getResponse();
            String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
            if (method.equals("GET")) {
                if (mRC != null) {
                    mRC.onGET(request, response, context);
                }
            } else if (method.equals("POST")) {
                if (mRC != null) {
                    mRC.onPOST(request, response, context);
                }
            } else if (method.equals("HEAD")) {
                if (mRC != null) {
                    mRC.onHEAD(request, response, context);
                }
            } else {
                throw new MethodNotSupportedException(method + " method not supported");
            }

            // response
            httpexchange.submitResponse(new BasicAsyncResponseProducer(response));
        }

    }

    private static void LOGW(String msg) {
        Log.w(tag, msg);
    }

    private static void LOGD(String msg) {
        Log.d(tag, msg);
    }

    public static void LOGE(String msg) {
        Log.e(tag, msg);
    }
}