Mega Code Archive

 
Categories / Java / JSP
 

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); }