sunlabs.brazil.handler.ChainSawHandler Maven / Gradle / Ivy
Show all versions of sunlabs.brazil Show documentation
/*
* ChainSawHandler.java
*
* Brazil project web application toolkit,
* export version: 2.3
* Copyright (c) 1999-2002 Sun Microsystems, Inc.
*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License Version
* 1.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is included as the file "license.terms",
* and also available at http://www.sun.com/
*
* The Original Code is from:
* Brazil project web application toolkit release 2.3.
* The Initial Developer of the Original Code is: suhler.
* Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
* All Rights Reserved.
*
* Contributor(s): cstevens, suhler.
*
* Version: 2.1
* Created by suhler on 99/04/08
* Last modified by suhler on 02/10/01 16:36:27
*
* Version Histories:
*
* 2.1 02/10/01-16:36:27 (suhler)
* version change
*
* 1.16 02/03/06-11:14:43 (suhler)
* fixed output format as per rinaldos instructions
*
* 1.15 00/12/11-18:45:10 (suhler)
* typo
* .
*
* 1.14 00/12/11-13:27:24 (suhler)
* add class=props for automatic property extraction
*
* 1.13 00/12/08-16:45:22 (suhler)
* doc fixes
* .
*
* 1.12 00/12/05-13:11:13 (suhler)
* changed semantics of bytesWritten
*
* 1.11 00/06/29-10:45:12 (suhler)
* Remove private outputStream.
* Counting capability is now in request.HttpOutputStream
*
* 1.10 00/06/26-10:13:11 (suhler)
* Make compatible (I hope) with FilterHandler
*
* 1.9 00/04/20-11:50:08 (cstevens)
* copyright.
*
* 1.8 00/03/10-17:03:42 (cstevens)
* Eliminated DataOutputStream from Request.java.
*
* 1.7 99/10/26-18:52:14 (cstevens)
* header must be spelled as "Referer".
*
* 1.6 99/10/26-17:10:46 (cstevens)
* Get rid of public variables Request.server and Request.sock:
* A. In all cases, Request.server was not necessary; it was mainly used for
* constructing the absolute URL for a redirect, so Request.redirect() was
* rewritten to take an absolute or relative URL and do the right thing.
* B. Request.sock was changed to Request.getSock(); it is still rarely used
* for diagnostics and logging (e.g., ChainSawHandler).
*
* 1.5 99/10/01-11:26:30 (cstevens)
* Change logging to show prefix of Handler generating the log message.
*
* 1.4 99/09/15-14:40:20 (cstevens)
* Rewritign http server to make it easier to proxy requests.
*
* 1.3 99/05/06-15:22:37 (suhler)
* lint (for jikes)
*
* 1.2 99/04/09-12:43:45 (suhler)
* fixed wild-carded imports
* allow for buffering output
* permit log file rotations
*
* 1.2 99/04/08-09:51:42 (Codemgr)
* SunPro Code Manager data about conflicts, renames, etc...
* Name history : 1 0 handlers/ChainSawHandler.java
*
* 1.1 99/04/08-09:51:41 (suhler)
* date and time created 99/04/08 09:51:41 by suhler
*
*/
package sunlabs.brazil.handler;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import sunlabs.brazil.server.ChainHandler;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
/**
* Variant of the chain handler for doing standard logging.
* Don't use on fine furniture.
*
* Output is a variant of the common logfile format.
* The common logfile format is as follows:
*
* remotehost rfc931 authuser [date] "request" status bytes
*
*
* - remotehost
*
- Remote hostname (or IP number if DNS hostname is not available, or if DNSLookup is Off.
*
- rfc931
*
- The remote logname of the user.
*
- authuser
*
- The username as which the user has authenticated himself.
*
- [date]
*
- Date and time of the request.
*
- "request"
*
- The request line exactly as it came from the client.
*
- status
*
- The HTTP status code returned to the client.
*
- bytes
*
- The content-length of the document transferred.
*
- "referrer" (optional)
*
- the referring url
*
- "user agent" (optional)
*
- "The user agent making the request
*
*
* Additional Configuration options:
*
* - logFile
- The name of the file to write the logs to.
*
- flush
- The number of requests between flushes to the file
*
* If the logFile is removed, the server creates a new one.
* Thus logs may be truncated by periodically moving them to
* another name (at least on unix).
*
* See the {@link LogHandler} handler for generating logs whose
* contents are configurable.
*
* @author Stephen Uhler
* @version 2.1, 02/10/01
*/
public class ChainSawHandler extends ChainHandler {
static public final String LOG = "logFile";
static public final String FLUSH = "flush";
static public final int BUFSIZE = 4096;
static SimpleDateFormat sdf; // standard log format date string
DataOutputStream log; // where to log the output to
File file;
int count = 0; // count flushing interval
int flush = 1; // how may requests to flush at
static {
sdf = new SimpleDateFormat("dd/MMM/yyyy:hh:mm:ss Z");
}
public boolean
init(Server server, String prefix) {
String logFile = server.props.getProperty(prefix + LOG,
server.hostName + "-" + server.listen.getLocalPort() + ".log");
try {
flush = Integer.parseInt(
server.props.getProperty(prefix + FLUSH, "1"));
} catch (NumberFormatException e) {
// ignore
}
try {
file = new File(logFile);
log = new DataOutputStream(new BufferedOutputStream(
new FileOutputStream(file),BUFSIZE));
} catch (IOException e) {
server.log(Server.LOG_WARNING, prefix, e.toString());
return false;
}
server.log(Server.LOG_DIAGNOSTIC, prefix, "Log file: " + logFile);
return super.init(server, prefix);
}
/**
* Run the chain-handler, counting the # of bytes of output generated
* by its chained handlers.
*/
public boolean
respond(Request request) throws IOException {
String req = "\"" + request.method + " " + request.url + " " +
request.protocol + "\"";
String now = sdf.format(new Date());
boolean result = false;
IOException oops = null;
try {
result = super.respond(request);
} catch (IOException e) {
oops = e;
}
int code = 200;
if (!result) {
code = 404;
}
request.out.flush();
String refer;
if (request.headers.get("Referer") != null) {
refer = "\"" + request.headers.get("Referer") + "\"";
} else {
refer = "-";
}
String agent;
if (request.headers.get("User-Agent") != null) {
agent = "\"" + request.headers.get("User-Agent") + "\"";
} else {
agent = "-";
}
count = request.out.bytesWritten;
String msg = request.getSocket().getInetAddress().getHostAddress() +
" - - [" + now + "]" + " " + req + " " +
code + " " + count + " " + refer + " " + agent + "\n";
/*
* Write to the log file. If there's a problem, try to open
* the file again.
*/
if (!file.exists()) {
log.flush();
request.log(Server.LOG_WARNING, "Log file went away!");
log = new DataOutputStream(new BufferedOutputStream(
new FileOutputStream(file), BUFSIZE));
count = 0;
}
log.writeBytes(msg);
request.log(Server.LOG_DIAGNOSTIC, msg);
if (count++ >= flush) {
log.flush();
count = 0;
}
if (oops != null) {
throw oops;
}
return result;
}
}