Android Open Source - NetworkClipboardAndroid Http Server






From Project

Back to project page NetworkClipboardAndroid.

License

The source code is released under:

GNU General Public License

If you think the Android project NetworkClipboardAndroid listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 *//from w  w w  .j  a v  a 2 s .c o  m
 * ====================================================================
 * 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.adyrhan.networkclipboard;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.http.ConnectionClosedException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpServerConnection;
import org.apache.http.MethodNotSupportedException;
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.HttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.BasicHttpContext;
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 com.adyrsoft.framework.android.InputStreamUtils;

import android.util.Log;

/**
 * This HTTP/1.1 compliant server is a slightly improved version of the one available here,
 * https://svn.apache.org/repos/asf/httpcomponents/httpcore/tags/4.0.1/httpcore/src/examples/org/apache/http/examples/ElementalHttpServer.java
 * modified to receive remote clipboard data, and to log errors the Android way.
 * 
 * HttpServer is the main object here and replaces the class containing the main static method.
 */


public class HttpServer {
  public static final String TAG = "HttpServer";
  private AtomicBoolean mIsRunning;
  private RequestListenerThread mThread;
  private ServerSocket mSocket;
  
  public HttpServer() {
    mIsRunning = new AtomicBoolean(false);
  }
  
  public boolean isRunning() {
    return mIsRunning.get();
  }
  
  public void startServer(int port, NewDataListener listener) throws PortIOError {
    try {
      if(!mIsRunning.get()) {
        mThread = new RequestListenerThread(port, listener, mIsRunning);
        mSocket = mThread.serversocket;
        mThread.setDaemon(false);
        mThread.start();
        
        while(!mIsRunning.get()) {
          Thread.sleep(10);
        }
        
      }
    } catch (IOException e) {
      throw new PortIOError(port);
    } catch (InterruptedException e) {
      Log.e(TAG, null, e);
    }
    
  }
  
  public void stopServer() {
    try {
      Log.d(TAG, "HttpServer.stopServer() called! mIsRunning value is "+ Boolean.toString(mIsRunning.get()));
      if(mIsRunning.get() && mThread != null) {
        Log.d(TAG, "Trying to stop Http server...");
        mThread.interrupt();
        mSocket.close();  
        while(mIsRunning.get()) {
          Thread.sleep(10);
        }
      }
      
    } catch (IOException e) {
      Log.e(TAG, "Error while trying to close socket");
    } catch (InterruptedException e) {
      Log.e(TAG, null, e);
    }
  }
    
  public interface NewDataListener {
    public void onNewText(String text);
  }
  
    static class HttpClipboardHandler implements HttpRequestHandler  {
        
        public static final String TAG = "HttpClipboardHandler";
        private NewDataListener listener;
    public HttpClipboardHandler(NewDataListener listener) {
      if(listener == null) {
        throw new NullPointerException("NewDataListener cannot be null");
      }
      this.listener = listener;
    }

    public void handle(
                final HttpRequest request, 
                final HttpResponse response,
                final HttpContext context) throws HttpException, IOException {

            String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
            if (!method.equals("POST")) {
                throw new MethodNotSupportedException(method + " method not supported"); 
            }
            
            if (request instanceof HttpEntityEnclosingRequest) {
                HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
                String content = InputStreamUtils.toString(entity.getContent());
                String[] nameValue = content.split("\\s*=\\s*");
                if(nameValue.length == 2){
                  listener.onNewText(nameValue[1]);
                } else {
                  response.setStatusCode(422);
                }
            }
            
        }
        
    }
    
    static class RequestListenerThread extends Thread {

        private static final String TAG = "RequestListenerThread";
    public final ServerSocket serversocket;
        private final HttpParams params; 
        private final HttpService httpService;
        private final AtomicBoolean runningStatus;
        
        
        public RequestListenerThread(int port, NewDataListener listener, AtomicBoolean runningStatus) throws IOException  {
            this.serversocket = new ServerSocket(port);
            this.params = new BasicHttpParams();
            this.params
                .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, "HttpComponents/1.1");

            // Set up the HTTP protocol processor
            BasicHttpProcessor httpproc = new BasicHttpProcessor();
            httpproc.addInterceptor(new ResponseDate());
            httpproc.addInterceptor(new ResponseServer());
            httpproc.addInterceptor(new ResponseContent());
            httpproc.addInterceptor(new ResponseConnControl());
            
            // Set up request handlers
            HttpRequestHandlerRegistry registry = new HttpRequestHandlerRegistry();
            registry.register("*", new HttpClipboardHandler(listener));
            
            // Set up the HTTP service
            this.httpService = new HttpService(
                    httpproc, 
                    new DefaultConnectionReuseStrategy(), 
                    new DefaultHttpResponseFactory());
            this.httpService.setParams(this.params);
            this.httpService.setHandlerResolver(registry);
            
            this.runningStatus = runningStatus;
        }
        
        public void run() {
            Log.d(TAG, "Listening on port " + this.serversocket.getLocalPort());
            runningStatus.set(true);
            while (!Thread.interrupted()) {
                try {
                    // Set up HTTP connection
                    Socket socket = this.serversocket.accept();
                    DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
                    Log.d(TAG, "Incoming connection from " + socket.getInetAddress());
                    conn.bind(socket, this.params);

                    // Start worker thread
                    Thread t = new WorkerThread(this.httpService, conn);
                    t.setDaemon(true);
                    t.start();
                }  catch (IOException e) {
                    Log.w(TAG, "I/O error initialising connection thread: " 
                            + e.getMessage());
                    break;
                }
            }
            
            runningStatus.set(false);
            
        }
    }
    
    static class WorkerThread extends Thread {
      public static final String TAG = "WorkerThread";
        private final HttpService httpservice;
        private final HttpServerConnection conn;
        
        public WorkerThread(
                final HttpService httpservice, 
                final HttpServerConnection conn) {
            super();
            this.httpservice = httpservice;
            this.conn = conn;
        }
        
        public void run() {
            Log.d(TAG, "New connection thread");
            HttpContext context = new BasicHttpContext(null);
            try {
                while (!Thread.interrupted() && this.conn.isOpen()) {
                    this.httpservice.handleRequest(this.conn, context);
                }
            } catch (ConnectionClosedException ex) {
                Log.w(TAG, "Client closed connection");
            } catch (IOException ex) {
                Log.e(TAG, "I/O error: " + ex.getMessage());
            } catch (HttpException ex) {
                Log.e(TAG, "Unrecoverable HTTP protocol violation: " + ex.getMessage());
            } finally {
                try {
                    this.conn.shutdown();
                } catch (IOException ignore) {}
            }
        }

    }
    
}




Java Source Code List

com.adyrhan.networkclipboard.BootReceiver.java
com.adyrhan.networkclipboard.HttpServer.java
com.adyrhan.networkclipboard.NetworkClipboardService.java
com.adyrhan.networkclipboard.PortIOError.java
com.adyrhan.networkclipboard.ServiceControlActivity.java
com.adyrsoft.framework.android.InputStreamUtils.java