Java/JSP/JSP Debug
A command-line interface to a Web server
/**
* Copyright (c) 2002 by Phil Hanna
* All rights reserved.
*
* You may study, use, modify, and distribute this
* software for any purpose provided that this
* copyright notice appears in all copies.
*
* This software is provided without warranty
* either expressed or implied.
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Mainline for running the Web client
*/
public class MainWebClient
{
/**
* Reads command line parameters, creates a new
* <code>WebClient</code> object, then invokes it.
*/
public static void main(String[] args)
throws IOException
{
// Default values
String host = "localhost";
int port = 80;
// Use values from command line, if specified
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.equals("-h") || arg.equals("-help")) {
showUsage();
return;
}
else
if (arg.equals("-host") && ++i < args.length)
host = args[i];
else
if (arg.equals("-port") && ++i < args.length)
port = Integer.parseInt(args[i]);
}
// Create and start the Web client
new WebClient(host, port).run();
}
/**
* Displays the calling syntax
*/
private static void showUsage()
{
String[] text = {
"usage: java com.jspcr.debug.webclient.Main"
+ " [-host <hostName>]"
+ " [-port <portNumber>]",
};
for (int i = 0; i < text.length; i++)
System.out.println(text[i]);
}
}
/**
* Copyright (c) 2002 by Phil Hanna
* All rights reserved.
*
* You may study, use, modify, and distribute this
* software for any purpose provided that this
* copyright notice appears in all copies.
*
* This software is provided without warranty
* either expressed or implied.
*/
/**
* A command-line interface to a Web server
*/
class WebClient
{
// Instance variables
private String host;
private int port;
/**
* Creates a new Web client
* @param host the HTTP server
* @param port the server port number
*/
public WebClient(String host, int port)
{
this.host = host;
this.port = port;
}
/**
* Runs the Web client
* @throws IOException if a socket error occurs
*/
public void run() throws IOException
{
int contentLength = 0;
// Open a socket to the Web host
Socket socket = new Socket(host, port);
// Set up to read input from the user
// and echo it to Web host
BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
PrintWriter out =
new PrintWriter(socket.getOutputStream(), true);
// The first line is the HTTP request
// e.g., "GET /path HTTP/1.0"
String line = in.readLine();
out.println(line);
// Read and echo any other headers, stopping
// when a blank line is encountered.
while ((line = in.readLine()) != null) {
line = line.trim();
out.println(line);
if (line.equals(""))
break;
// Check for a Content-Length header
Pattern p = Pattern.rupile
("^\\s*([^:]+):\\s+(.*\\S)\\s*$");
Matcher m = p.matcher(line);
if (m.matches()) {
String name = m.group(1);
String value = m.group(2);
if (name.equalsIgnoreCase("Content-Length"))
contentLength = Integer.parseInt(value);
}
}
// If a non-zero content length header was used,
// read and echo that many bytes to the Web host.
if (contentLength > 0) {
for (int i = 0; i < contentLength; i++)
out.print((char) in.read());
out.flush();
}
// The server is now working on the request.
// Read its output and dump to stdout
in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(System.out);
for (;;) {
line = in.readLine();
if (line == null)
break;
out.println(line);
}
// Close files
in.close();
out.close();
socket.close();
}
}
HTTP Echo For testing
import java.net.Socket;
import java.net.ServerSocket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedInputStream;
public class HTTPEcho {
private static final int BUF_SIZE = 1024;
private Socket browserSocket = null;
private Socket webServerSocket = null;
private ServerSocket browserListenerSocket = null;
private OutputStream toWebServer = null;
private BufferedInputStream fromWebServer = null;
private OutputStream toBrowser = null;
private BufferedInputStream fromBrowser = null;
private ServerSocket createListenerSocket(int portNum) {
ServerSocket socket = null;
try {
socket = new ServerSocket(portNum);
}
catch (IOException ioe) {
System.out.println(ioe.getMessage());
System.exit(-1);
}
return socket;
}
private Socket createClientSocket(String host, int portNum) {
Socket socket = null;
try {
socket = new Socket(host, portNum);
toWebServer = socket.getOutputStream();
fromWebServer =
new BufferedInputStream(socket.getInputStream());
}
catch (IOException ioe) {
System.out.println(ioe.getMessage());
System.exit(-1);
}
return socket;
}
private Socket accept () {
Socket socket = null;
try {
socket = browserListenerSocket.accept();
toBrowser = socket.getOutputStream();
fromBrowser =
new BufferedInputStream(socket.getInputStream());
}
catch (IOException e) {
System.out.println("Accept failed: " + e.getMessage());
System.exit(-1);
}
return socket;
}
private void setBrowserListenerSocket(ServerSocket socket) {
browserListenerSocket = socket;
}
private void setWebServerSocket(Socket socket) {
webServerSocket = socket;
}
private void setBrowserSocket(Socket socket) {
browserSocket = socket;
}
private int readLine(InputStream in, byte[] b, int off, int len) throws IOException {
if (len <= 0) {
return 0;
}
int count = 0, c;
while ((c = in.read()) != -1 && count < len) {
b[off++] = (byte)c;
count++;
if (c == "\n") {
break;
}
}
return count > 0 ? count : -1;
}
private void echoBuffer(BufferedInputStream in, OutputStream out) {
byte[] readBuf = new byte[BUF_SIZE];
try {
int rlen = -1;
int bodyLen = 0;
String line = null;
do {
line = null;
rlen = readLine(in, readBuf, 0, BUF_SIZE);
if (rlen > 0) {
line = new String(readBuf, 0, rlen);
System.out.print(line);
if (line.startsWith("Content-Length: ")) {
String size =
line.substring("Content-Length: ".length(),
line.length());
bodyLen = Integer.parseInt(size.trim());
}
out.write(readBuf, 0, rlen);
}
} while ((rlen > 0) && !(line.equals("\r\n")));
if (bodyLen > 0) {
System.out.println("<Entity-Body>");
int count = 0;
do {
rlen = in.read(readBuf, 0, BUF_SIZE);
if (rlen > 0) {
out.write(readBuf, 0, rlen);
count += rlen;
}else break;
} while (count < bodyLen);
}
out.flush();
}
catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
finally {
readBuf = null;
}
}
private void echo() {
System.out.println("\nHTTP REQUEST:");
echoBuffer(fromBrowser, toWebServer);
System.out.println("\nHTTP REPLY:");
echoBuffer(fromWebServer, toBrowser);
}
private void closeClientDescriptors() {
try {
fromWebServer.close();
toWebServer.close();
webServerSocket.close();
fromBrowser.close();
toBrowser.close();
browserSocket.close();
}
catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
}
public static void main(String [] args) {
HTTPEcho echo = new HTTPEcho();
if (args.length > 1) {
System.out.println("Starting HTTPEcho on port: " + args[0] + ". ");
System.out.println("Web server host: " + args[1] + ".");
System.out.println("Web server is on port: " + args[2] + ".");
int interceptorPort = Integer.parseInt(args[0]);
String webServerHost = args[1];
int webServerPort = Integer.parseInt(args[2]);
echo.setBrowserListenerSocket(echo.createListenerSocket(interceptorPort));
while (true) {
echo.setBrowserSocket(echo.accept());
echo.setWebServerSocket(echo.createClientSocket(webServerHost,
webServerPort));
echo.echo();
echo.closeClientDescriptors();
}
}
else {
System.out.println("Usage: java HTTPEcho " +
"interceptorPort " +
"webServerHost webServerPort");
}
}
}
Mainline for the HTTP tracer tool
/**
* Copyright (c) 2002 by Phil Hanna
* All rights reserved.
*
* You may study, use, modify, and distribute this
* software for any purpose provided that this
* copyright notice appears in all copies.
*
* This software is provided without warranty
* either expressed or implied.
*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
/**
* Mainline for the HTTP tracer tool
*/
public class MainHTTPTracerTool {
public static void main(String[] args) throws IOException {
String opt_host = null;
String opt_port = null;
String opt_tracerPort = null;
String opt_log = null;
try {
// Parse command line arguments
for (int i = 0, n = args.length; i < n; i++) {
String arg = args[i];
if (arg.equals("-h")) {
showUsage();
return;
}
if (arg.equals("-host") && (i + 1 < n))
opt_host = args[++i];
else if (arg.equals("-port") && (i + 1 < n))
opt_port = args[++i];
else if (arg.equals("-tracerPort") && (i + 1 < n))
opt_tracerPort = args[++i];
else if (arg.equals("-log") && (i + 1 < n))
opt_log = args[++i];
else
throw new IllegalArgumentException("Unrecognized option "
+ arg);
}
// Verify that there is no port conflict
int testTracerPort = (opt_tracerPort == null) ? Tracer.DEFAULT_PORT
: Integer.parseInt(opt_tracerPort);
int testHostPort = (opt_port == null) ? RequestHandler.DEFAULT_PORT
: Integer.parseInt(opt_port);
if (testTracerPort == testHostPort)
throw new IllegalArgumentException(
"Cannot assign port and tracerPort both to "
+ testHostPort);
} catch (IllegalArgumentException e) {
System.err.println(e.getMessage());
return;
}
// Create the tracer and set its properties
Tracer tracer = new Tracer();
if (opt_host != null)
tracer.setHost(opt_host);
if (opt_port != null)
tracer.setPort(Integer.parseInt(opt_port));
if (opt_tracerPort != null)
tracer.setTracerPort(Integer.parseInt(opt_tracerPort));
if (opt_log != null)
tracer.setLogWriter(new FileWriter(opt_log));
// Start it running
tracer.start();
}
public static final void showUsage() {
String[] text = { "", "usage: java -jar tracer.jar [options]", "",
"where options are:", "",
"-host <hostName> (default is localhost)",
"-port <hostPort> (default is 80)",
"-tracerPort <localPort> (default is 8601)",
"-log <fileName> (default is stdout)", };
for (int i = 0; i < text.length; i++)
System.out.println(text[i]);
}
}
/**
* Copyright (c) 2002 by Phil Hanna All rights reserved.
*
* You may study, use, modify, and distribute this software for any purpose
* provided that this copyright notice appears in all copies.
*
* This software is provided without warranty either expressed or implied.
*/
/**
* Acts as a proxy web server, capturing requests and responses and echoing the
* headers to a log stream.
*/
class Tracer extends Thread implements Logger {
public static final int DEFAULT_PORT = 8601;
private String host;
private int port;
private int tracerPort;
private PrintWriter logWriter;
public void run() {
// Set defaults if not otherwise specified
if (tracerPort == 0)
tracerPort = DEFAULT_PORT;
if (logWriter == null)
logWriter = new PrintWriter(System.out);
// Start proxy server
try {
log("M: Opening tracer server on tracerPort " + tracerPort);
ServerSocket server = new ServerSocket(tracerPort);
// Loop forever
while (true) {
// Wait for connection
log("M: Waiting for connections");
Socket client = server.accept();
log("M: Connection received from " + client);
// Dispatch it to a request handler thread
RequestHandler rh = new RequestHandler(client);
rh.setLogger(this);
if (host != null)
rh.setHost(host);
if (port != 0)
rh.setPort(port);
rh.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// ===========================================
// Implementation of Logger
// ===========================================
/**
* Writes a message to the log
*
* @param message
* the message
*/
public synchronized void log(String message) {
logWriter.println(message);
logWriter.flush();
}
// ===========================================
// Property setters
// ===========================================
/**
* Sets the host.
*
* @param host
* the host.
*/
public void setHost(String host) {
this.host = host;
}
/**
* Sets the port.
*
* @param port
* the port.
*/
public void setPort(int port) {
this.port = port;
}
/**
* Sets the tracerPort.
*
* @param tracerPort
* the tracerPort.
*/
public void setTracerPort(int tracerPort) {
this.tracerPort = tracerPort;
}
/**
* Sets the logWriter.
*
* @param logWriter
* the logWriter.
*/
public void setLogWriter(Writer logWriter) throws IOException {
this.logWriter = new PrintWriter(logWriter);
}
}
/**
* Copyright (c) 2002 by Phil Hanna All rights reserved.
*
* You may study, use, modify, and distribute this software for any purpose
* provided that this copyright notice appears in all copies.
*
* This software is provided without warranty either expressed or implied.
*/
/**
* A proxy HTTP server that handles a single request
*/
class RequestHandler extends Thread {
public static final String DEFAULT_HOST = "localhost";
public static final int DEFAULT_PORT = 80;
private Socket client;
private Logger logger;
private String host;
private int port;
// ===========================================
// Constructors
// ===========================================
/**
* Creates a new <code>RequestHandler</code> for the specified client
*/
public RequestHandler(Socket client) {
this.client = client;
}
// ===========================================
// Instance methods
// ===========================================
/**
* Copies the request from the client to the server and copies the response
* back to the client.
*/
public void run() {
try {
// Open a socket to the web server
if (host == null)
host = DEFAULT_HOST;
if (port <= 0)
port = DEFAULT_PORT;
Socket server = new Socket(host, port);
// Open I/O streams to the client
InputStream cin = new BufferedInputStream(client.getInputStream());
OutputStream cout = new BufferedOutputStream(client
.getOutputStream());
// Open I/O streams to the server
InputStream sin = new BufferedInputStream(server.getInputStream());
OutputStream sout = new BufferedOutputStream(server
.getOutputStream());
// Copy request line and headers from client to server,
// echoing to logger if specified. Stop after the
// first empty line (end of headers)
int contentLength = 0;
StringBuffer sb = new StringBuffer();
for (;;) {
// Read a byte from client
// and copy it to server
int c = cin.read();
sout.write(c);
// Ignore CR at end of line
if (c == "\r")
continue;
// If LF, process the line
if (c == "\n") {
String line = sb.toString();
sb = new StringBuffer();
// Log the line
logger.log("C: " + line);
// If this is an empty line,
// there are no more headers
if (line.length() == 0)
break;
// If it is a content length header,
// save the content length
int p = line.indexOf(":");
if (p != -1) {
String key = line.substring(0, p).trim();
String value = line.substring(p + 1).trim();
if (key.equalsIgnoreCase("content-length"))
contentLength = Integer.parseInt(value);
}
}
// Otherwise, append char to string buffer
else
sb.append((char) c);
}
sout.flush();
// If content length was specified, read input stream
// and copy to server
if (contentLength > 0) {
for (int i = 0; i < contentLength; i++) {
int c = cin.read();
sout.write(c);
}
sout.flush();
}
// Echo the response back to the client
sb = new StringBuffer();
while (true) {
// Read a byte from server
// and copy it to client
int c = sin.read();
cout.write(c);
// Ignore CR at end of line
if (c == "\r")
continue;
// If LF, process the line
if (c == "\n") {
String line = sb.toString();
sb = new StringBuffer();
// Log the line
logger.log("S: " + line);
// If this is an empty line,
// there are no more headers
if (line.length() == 0)
break;
}
// Otherwise, append char to string buffer
else
sb.append((char) c);
}
cout.flush();
// Copy remaining bytes to client
int bytesCopied = 0;
while (true) {
int c = sin.read();
if (c == -1)
break;
cout.write(c);
bytesCopied++;
}
if (bytesCopied > 0)
cout.flush();
// Close streams and sockets
cin.close();
cout.close();
client.close();
sin.close();
sout.close();
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// ===========================================
// Property setters
// ===========================================
/**
* Sets the logger.
*
* @param logger
* the logger.
*/
public void setLogger(Logger logger) {
this.logger = logger;
}
/**
* Sets the host.
*
* @param host
* the host.
*/
public void setHost(String host) {
this.host = host;
}
/**
* Sets the port.
*
* @param port
* the port.
*/
public void setPort(int port) {
this.port = port;
}
}
/**
* Copyright (c) 2002 by Phil Hanna All rights reserved.
*
* You may study, use, modify, and distribute this software for any purpose
* provided that this copyright notice appears in all copies.
*
* This software is provided without warranty either expressed or implied.
*/
/**
* The set of methods that must be implemented by a class that logs message
*/
interface Logger {
/**
* Logs a message
*/
public void log(String s);
}