|
Android example source code file (TestWebServer.java)
The TestWebServer.java Android example source code
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed 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.
*/
package android.core;
import android.util.Log;
import java.io.*;
import java.lang.Thread;
import java.net.*;
import java.util.*;
/**
* TestWebServer is a simulated controllable test server that
* can respond to requests from HTTP clients.
*
* The server can be controlled to change how it reacts to any
* requests, and can be told to simulate various events (such as
* network failure) that would happen in a real environment.
*/
class TestWebServer implements HttpConstants {
/* static class data/methods */
/* The ANDROID_LOG_TAG */
private final static String LOGTAG = "httpsv";
/* Where worker threads stand idle */
Vector threads = new Vector();
/* List of all active worker threads */
Vector activeThreads = new Vector();
/* timeout on client connections */
int timeout = 0;
/* max # worker threads */
int workers = 5;
/* Default port for this server to listen on */
final static int DEFAULT_PORT = 8080;
/* Default socket timeout value */
final static int DEFAULT_TIMEOUT = 5000;
/* Version string (configurable) */
protected String HTTP_VERSION_STRING = "HTTP/1.1";
/* Indicator for whether this server is configured as a HTTP/1.1
* or HTTP/1.0 server
*/
private boolean http11 = true;
/* The thread handling new requests from clients */
private AcceptThread acceptT;
/* timeout on client connections */
int mTimeout;
/* Server port */
int mPort;
/* Switch on/off logging */
boolean mLog = false;
/* If set, this will keep connections alive after a request has been
* processed.
*/
boolean keepAlive = true;
/* If set, this will cause response data to be sent in 'chunked' format */
boolean chunked = false;
/* If set, this will indicate a new redirection host */
String redirectHost = null;
/* If set, this indicates the reason for redirection */
int redirectCode = -1;
/* Set the number of connections the server will accept before shutdown */
int acceptLimit = 100;
/* Count of number of accepted connections */
int acceptedConnections = 0;
public TestWebServer() {
}
/**
* Initialize a new server with default port and timeout.
* @param log Set true if you want trace output
*/
public void initServer(boolean log) throws Exception {
initServer(DEFAULT_PORT, DEFAULT_TIMEOUT, log);
}
/**
* Initialize a new server with default timeout.
* @param port Sets the server to listen on this port
* @param log Set true if you want trace output
*/
public void initServer(int port, boolean log) throws Exception {
initServer(port, DEFAULT_TIMEOUT, log);
}
/**
* Initialize a new server with default port and timeout.
* @param port Sets the server to listen on this port
* @param timeout Indicates the period of time to wait until a socket is
* closed
* @param log Set true if you want trace output
*/
public void initServer(int port, int timeout, boolean log) throws Exception {
mPort = port;
mTimeout = timeout;
mLog = log;
keepAlive = true;
if (acceptT == null) {
acceptT = new AcceptThread();
acceptT.init();
acceptT.start();
}
}
/**
* Print to the log file (if logging enabled)
* @param s String to send to the log
*/
protected void log(String s) {
if (mLog) {
Log.d(LOGTAG, s);
}
}
/**
* Set the server to be an HTTP/1.0 or HTTP/1.1 server.
* This should be called prior to any requests being sent
* to the server.
* @param set True for the server to be HTTP/1.1, false for HTTP/1.0
*/
public void setHttpVersion11(boolean set) {
http11 = set;
if (set) {
HTTP_VERSION_STRING = "HTTP/1.1";
} else {
HTTP_VERSION_STRING = "HTTP/1.0";
}
}
/**
* Call this to determine whether server connection should remain open
* @param value Set true to keep connections open after a request
* completes
*/
public void setKeepAlive(boolean value) {
keepAlive = value;
}
/**
* Call this to indicate whether chunked data should be used
* @param value Set true to make server respond with chunk encoded
* content data.
*/
public void setChunked(boolean value) {
chunked = value;
}
/**
* Call this to specify the maximum number of sockets to accept
* @param limit The number of sockets to accept
*/
public void setAcceptLimit(int limit) {
acceptLimit = limit;
}
/**
* Call this to indicate redirection port requirement.
* When this value is set, the server will respond to a request with
* a redirect code with the Location response header set to the value
* specified.
* @param redirect The location to be redirected to
* @param redirectCode The code to send when redirecting
*/
public void setRedirect(String redirect, int code) {
redirectHost = redirect;
redirectCode = code;
log("Server will redirect output to "+redirect+" code "+code);
}
/**
* Cause the thread accepting connections on the server socket to close
*/
public void close() {
/* Stop the Accept thread */
if (acceptT != null) {
log("Closing AcceptThread"+acceptT);
acceptT.close();
acceptT = null;
}
}
/**
* The AcceptThread is responsible for initiating worker threads
* to handle incoming requests from clients.
*/
class AcceptThread extends Thread {
ServerSocket ss = null;
boolean running = false;
public void init() {
// Networking code doesn't support ServerSocket(port) yet
InetSocketAddress ia = new InetSocketAddress(mPort);
while (true) {
try {
ss = new ServerSocket();
// Socket timeout functionality is not available yet
//ss.setSoTimeout(5000);
ss.setReuseAddress(true);
ss.bind(ia);
break;
} catch (IOException e) {
log("IOException in AcceptThread.init()");
e.printStackTrace();
// wait and retry
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
/**
* Main thread responding to new connections
*/
public synchronized void run() {
running = true;
try {
while (running) {
// Log.d(LOGTAG, "TestWebServer run() calling accept()");
Socket s = ss.accept();
acceptedConnections++;
if (acceptedConnections >= acceptLimit) {
running = false;
}
Worker w = null;
synchronized (threads) {
if (threads.isEmpty()) {
Worker ws = new Worker();
ws.setSocket(s);
activeThreads.addElement(ws);
(new Thread(ws, "additional worker")).start();
} else {
w = (Worker) threads.elementAt(0);
threads.removeElementAt(0);
w.setSocket(s);
}
}
}
} catch (SocketException e) {
log("SocketException in AcceptThread: probably closed during accept");
running = false;
} catch (IOException e) {
log("IOException in AcceptThread");
e.printStackTrace();
running = false;
}
log("AcceptThread terminated" + this);
}
// Close this socket
public void close() {
try {
running = false;
/* Stop server socket from processing further. Currently
this does not cause the SocketException from ss.accept
therefore the acceptLimit functionality has been added
to circumvent this limitation */
ss.close();
// Stop worker threads from continuing
for (Enumeration e = activeThreads.elements(); e.hasMoreElements();) {
Worker w = (Worker)e.nextElement();
w.close();
}
activeThreads.clear();
} catch (IOException e) {
/* We are shutting down the server, so we expect
* things to die. Don't propagate.
*/
log("IOException caught by server socket close");
}
}
}
// Size of buffer for reading from the connection
final static int BUF_SIZE = 2048;
/* End of line byte sequence */
static final byte[] EOL = {(byte)'\r', (byte)'\n' };
/**
* The worker thread handles all interactions with a current open
* connection. If pipelining is turned on, this will allow this
* thread to continuously operate on numerous requests before the
* connection is closed.
*/
class Worker implements HttpConstants, Runnable {
/* buffer to use to hold request data */
byte[] buf;
/* Socket to client we're handling */
private Socket s;
/* Reference to current request method ID */
private int requestMethod;
/* Reference to current requests test file/data */
private String testID;
/* Reference to test number from testID */
private int testNum;
/* Reference to whether new request has been initiated yet */
private boolean readStarted;
/* Indicates whether current request has any data content */
private boolean hasContent = false;
boolean running = false;
/* Request headers are stored here */
private Hashtable<String, String> headers = new Hashtable
Other Android examples (source code examples)Here is a short list of links related to this Android TestWebServer.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.