Package org.w3c.jigsaw.filters

Source Code of org.w3c.jigsaw.filters.LogFilter

// LogFilter.java
// $Id: LogFilter.java,v 1.4 2000/08/16 21:37:37 ylafon Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigsaw.filters;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Enumeration;
import org.w3c.tools.resources.Attribute;
import org.w3c.tools.resources.AttributeRegistry;
import org.w3c.tools.resources.FileAttribute;
import org.w3c.tools.resources.FramedResource;
import org.w3c.tools.resources.ProtocolException;
import org.w3c.tools.resources.ReplyInterface;
import org.w3c.tools.resources.RequestInterface;
import org.w3c.tools.resources.ResourceFilter;
import org.w3c.tools.resources.StringArrayAttribute;
import org.w3c.www.http.HeaderDescription;
import org.w3c.www.http.HeaderValue;
import org.w3c.www.http.HttpMessage;
import org.w3c.www.http.HttpReplyMessage;
import org.w3c.www.http.HttpRequestMessage;
import org.w3c.jigsaw.http.Reply;
import org.w3c.jigsaw.http.Request;

import org.w3c.tools.resources.ProtocolException;

/**
* This filter provides a very flexible logger.
* It is not designed as a logger, in order to be plugable only on
* a sub-tree of the URL space (a logger would log all site accesses).
* It provides as much details as you want, and uses a very simple format:
* each log entry (or <em>record</em> is made of several lines having
* the folowing format:
* <pre>variable=value</pre>
* A record starts with the special <code>url</code> variable value which
* provides the requested URL. The for each header that is to be logged,
* a variable is added in the record, prefixed by its <em>scope</em>. The
* scope can be either:
* <dl><dt>request<dd> to specify a request header,
* <dt>reply<dd> to specify a reply header,
* <dt>server<dd> to specify global server samples.
* </dl>
* As an example, if you configure that filter to log the request's referer
* and the reply content length, a sample record will look like:
* <pre>
* url=http://www.w3.org/pub/WWW/Jigsaw/
* request.referer=http://www.w3.org/pub/WWW
* reply.content-length=10
* </pre>
*/

public class LogFilter extends ResourceFilter {
    /**
     * Name of the state that when set on the request will prevent logging.
     */
    public static final
  String DONT_LOG = "org.w3c.jigsaw.filters.LogFilter.nolog";

    /**
     * Attribute index - The HTTP request headers to dump
     */
    protected static int ATTR_REQUEST_HEADERS = -1;
    /**
     * Attribute index - The HTTP reply headers to dump
     */
    protected static int ATTR_REPLY_HEADERS = -1;
    /**
     * Attribute index - The log file to use to emit log record.
     */
    protected static int ATTR_LOGFILE = -1;

    static {
  Class     c = null;
  Attribute a = null;

  try {
      c = Class.forName("org.w3c.jigsaw.filters.LogFilter");
  } catch (Exception ex) {
      ex.printStackTrace();
      System.exit(1);
  }
  // Register the request headers to be logged:
  a = new StringArrayAttribute("request-headers"
             , null
             , Attribute.EDITABLE);
  ATTR_REQUEST_HEADERS = AttributeRegistry.registerAttribute(c, a);
  // Register the reply headers to be logged:
  a = new StringArrayAttribute("reply-headers"
             , null
             , Attribute.EDITABLE);
  ATTR_REPLY_HEADERS = AttributeRegistry.registerAttribute(c, a);
  // Register the log file name:
  a = new FileAttribute("logfile"
            , null
            , Attribute.EDITABLE);
  ATTR_LOGFILE = AttributeRegistry.registerAttribute(c, a);
    }

    /**
     * Compiled index of the request headers to dump.
     */
    protected HeaderDescription reqheaders[] = null;
    /**
     * Compiled index of the reply headers to dump.
     */
    protected HeaderDescription repheaders[] = null;
    /**
     * Open log descriptor, to write to the log.
     */
    protected RandomAccessFile log = null;

    /**
     * Compile the given set of header names into header indexes.
     * @param kind An instance of the class whose headers are to be dumped.
     * @param headers The name of headers to compile.
     * @return An array of header description, which will allow fast fetch
     * of header values.
     */

    protected HeaderDescription[] compileHeaders(HttpMessage kind
             , String headers[]) {
  Enumeration       e   = kind.enumerateHeaderDescriptions(true);
  HeaderDescription r[] = new HeaderDescription[headers.length];
  while ( e.hasMoreElements() ) {
      HeaderDescription d = (HeaderDescription) e.nextElement();
      if ( d == null )
    continue;
      for (int i = 0 ; i < headers.length ; i++) {
    if (headers[i].equals(d.getName())) {
        r[i] = d;
        break;
    }
      }
  }
  return r;
    }

    /**
     * Write the given string to the log file.
     * @param record The string to write.
     */

    protected synchronized void writelog(String record) {
  try {
      if ( log != null )
    log.writeBytes(record);
  } catch (IOException ex) {
      FramedResource target = (FramedResource) getTargetResource();
      if (target != null) {
    String msg = ("IO error while writing to log file \""+
            ex.getMessage() + "\".");
    target.getServer().errlog(this, msg);
      }
  }
    }

    /**
     * Open the log stream, and make it available through <code>log</code>.
     * If opening the stream failed, an appropriate error message is emitted
     * and <code>log</code> remains set to <strong>null</strong>. If a log
     * stream was already opened, it is first closed.
     */

    protected synchronized void openLog() {
  // Close first if needed:
  if ( log != null ) {
      try {
    log.close();
      } catch (IOException ex) {
      }
      log = null;
  }
  // Try opening the log:
  File logfile = getLogfile();
  try {
      if (logfile != null) {
    log = new RandomAccessFile(logfile, "rw");
    log.seek(log.length());
      }
  } catch (Exception ex) {
  }
  // If failed, emit error message:
  if ( log == null ) {
      FramedResource target = (FramedResource) getTargetResource();
      if (target != null) {
    String msg = ("unable to open log file \""+
            logfile
            + "\".");
    target.getServer().errlog(this, msg);
      }
  }
    }

    /**
     * Get the log file.
     * @return A File instance, or <strong>null</strong> if not set.
     */

    public File getLogfile() {
  return (File) getValue(ATTR_LOGFILE, null);
    }

    /**
     * Get the list of request headers to dump.
     * @return An array of String containing the name of headers to dump, or
     * <strong>null</strong> if undefined.
     */

    public String[] getRequestHeaders() {
  return (String[]) getValue(ATTR_REQUEST_HEADERS, null);
    }

    /**
     * Get the list of reply headers to dump.
     * @return An array of String containing the name of headers to dump,
     * or <strong>null</strong> if undefined.
     */

    public String[] getReplyHeaders() {
  return (String[]) getValue(ATTR_REPLY_HEADERS, null);
    }

    /**
     * Traop setValue calls.
     * We maintain a compiled version of both the <code>request-headers</code>
     * and the <code>reply-headers</code> attributes, make sure they stay in
     * sync even when modified.
     */

    public void setValue(int idx, Object value) {
  super.setValue(idx, value);
  if ( idx == ATTR_REQUEST_HEADERS ) {
      synchronized(this) {
    reqheaders = compileHeaders(new HttpRequestMessage()
              , (String[]) value);
      }
  } else if (idx == ATTR_REPLY_HEADERS ) {
      synchronized(this) {
    repheaders = compileHeaders(new HttpReplyMessage()
              , (String[]) value);
      }
  } else if (idx == ATTR_LOGFILE ) {
      openLog();
  }
    }

    /**
     * Log the given request/reply transaction.
     * Dump a record for the given transaction.
     * @param request The request to log.
     * @param reply It's associated reply.
     */

    protected void log(Request request, Reply reply) {
  StringBuffer sb = new StringBuffer();
  // Start a new log record:
  sb.append("url=");
  sb.append(request.getURL().toString());
  sb.append('\n');
  // Then log all request headers:
  if ( reqheaders != null ) {
      for (int i = 0 ; i < reqheaders.length ; i++) {
    HeaderDescription d = reqheaders[i];
    if ( d == null )
        continue;
    HeaderValue v = request.getHeaderValue(d);
    if ( v != null ) {
        sb.append("request.");
        sb.append(d.getName());
        sb.append('=');
        sb.append(v.toString());
        sb.append('\n');
    }
      }
  }
  // The log all reply headers:
  if ( repheaders != null ) {
      for (int i = 0 ; i < repheaders.length ; i++) {
    HeaderDescription d = repheaders[i];
    if ( d == null )
        continue;
    HeaderValue v = reply.getHeaderValue(d);
    if ( v != null ) {
        sb.append("reply.");
        sb.append(d.getName());
        sb.append('=');
        sb.append(v.toString());
        sb.append('\n');
    }
      }
  }
  writelog(sb.toString());
    }

    /**
     * Log the request.
     * @param request The request that has been handled.
     * @param reply It's associated reply.
     * @exception org.w3c.tools.resources.ProtocolException
     * If processing should be interrupted, because an abnormal situation
     * occured.
     */

    public ReplyInterface outgoingFilter(RequestInterface req,
           ReplyInterface rep)
  throws ProtocolException
    {
  Reply   reply   = (Reply) rep;
  Request request = (Request) req;
  if ( ! reply.hasState(DONT_LOG) )
      log(request, reply);
  return null;
    }

    /**
     * Initialize the filter.
     */

    public void initialize(Object values[]) {
  super.initialize(values);
  // Open the log file, ready for working:
  if ( log == null )
      openLog();
  // Compile request and reply headers to dump:
  if ( reqheaders == null ) {
      String headers[] = getRequestHeaders();
      if ( headers != null )
    reqheaders = compileHeaders(new HttpRequestMessage(), headers);
  }
  if ( repheaders == null ) {
      String headers[] = getReplyHeaders();
      if ( headers != null )
    repheaders = compileHeaders(new HttpReplyMessage(), headers);
  }
    }

}
TOP

Related Classes of org.w3c.jigsaw.filters.LogFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.