Mainline for the HTTP tracer tool : JSP Debug « JSP « Java






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

           
       








Related examples in the same category

1.HTTP Echo For testing
2.A command-line interface to a Web server