/*
* Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
* Distributed under the terms of either:
* - the common development and distribution license (CDDL), v1.0; or
* - the GNU Lesser General Public License, v2.1 or later
*/
package winstone.accesslog;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import winstone.Logger;
import winstone.WinstoneResourceBundle;
import winstone.cmdline.Option;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
/**
* Simulates an apache "combined" style logger, which logs User-Agent, Referer, etc
*
* @author <a href="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
* @version $Id: SimpleAccessLogger.java,v 1.5 2006/03/24 17:24:19 rickknowles Exp $
*/
public class SimpleAccessLogger extends AbstractLifeCycle implements RequestLog {
public static final WinstoneResourceBundle ACCESSLOG_RESOURCES =
new WinstoneResourceBundle("winstone.accesslog.LocalStrings");
private static final DateFormat DF = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z");
private static final String COMMON = "###ip### - ###user### ###time### \"###uriLine###\" ###status### ###size###";
private static final String COMBINED = COMMON + " \"###referer###\" \"###userAgent###\"";
private static final String RPROXYCOMBINED = "###x-forwarded-for### " + COMBINED;
private static final String RESIN = COMMON + " \"###userAgent###\"";
private OutputStream outStream;
private PrintWriter outWriter;
private String pattern;
private String fileName;
public SimpleAccessLogger(String webAppName, Map startupArgs)
throws IOException {
// Get pattern
String patternType = Option.SIMPLE_ACCESS_LOGGER_FORMAT.get(startupArgs);
if (patternType.equalsIgnoreCase("combined")) {
this.pattern = COMBINED;
} else if (patternType.equalsIgnoreCase("common")) {
this.pattern = COMMON;
} else if (patternType.equalsIgnoreCase("resin")) {
this.pattern = RESIN;
} else if (patternType.equalsIgnoreCase("rproxycombined")) {
this.pattern = RPROXYCOMBINED;
} else {
this.pattern = patternType;
}
// Get filename
String filePattern = Option.SIMPLE_ACCESS_LOGGER_FILE.get(startupArgs);
this.fileName = WinstoneResourceBundle.globalReplace(filePattern,
new String [][] {
{"###webapp###", webAppName}});
File file = new File(this.fileName);
file.getParentFile().mkdirs();
this.outStream = new FileOutputStream(file, true);
this.outWriter = new PrintWriter(this.outStream, true);
Logger.log(Logger.DEBUG, ACCESSLOG_RESOURCES, "SimpleAccessLogger.Init",
this.fileName, patternType);
}
public void log(Request request, Response response) {
String uriLine = request.getMethod() + " " + request.getRequestURI() + " " + request.getProtocol();
int status = response.getStatus();
long size = response.getContentCount();
String date;
synchronized (DF) {
date = DF.format(new Date());
}
// mimic https://github.com/eclipse/jetty.project/blob/jetty-9.4.0.v20161208/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java#L130
Authentication authentication = request.getAuthentication();
String remoteUser;
if (authentication instanceof Authentication.User) {
Authentication.User user = (Authentication.User) authentication;
remoteUser = user.getUserIdentity().getUserPrincipal().getName();
} else {
remoteUser = null;
}
String logLine = WinstoneResourceBundle.globalReplace(this.pattern, new String[][] {
{"###x-forwarded-for###", nvl(request.getHeader("X-Forwarded-For"))},
{"###x-forwarded-host###", nvl(request.getHeader("X-Forwarded-Host"))},
{"###x-forwarded-proto###", nvl(request.getHeader("X-Forwarded-Proto"))},
{"###x-forwarded-protocol###", nvl(request.getHeader("X-Forwarded-Protocol"))},
{"###x-forwarded-server###", nvl(request.getHeader("X-Forwarded-Server"))},
{"###x-forwarded-ssl###", nvl(request.getHeader("X-Forwarded-Ssl"))},
{"###x-requested-with###", nvl(request.getHeader("X-Requested-With"))},
{"###x-do-not-track###", nvl(request.getHeader("X-Do-Not-Track"))},
{"###dnt###", nvl(request.getHeader("DNT"))},
{"###via###", nvl(request.getHeader("Via"))},
{"###ip###", request.getRemoteHost()},
{"###user###", nvl(remoteUser)},
{"###time###", "[" + date + "]"},
{"###uriLine###", uriLine},
{"###status###", "" + status},
{"###size###", "" + size},
{"###referer###", nvl(request.getHeader("Referer"))},
{"###userAgent###", nvl(request.getHeader("User-Agent"))}
});
this.outWriter.println(logLine);
}
private static String nvl(String input) {
return input == null ? "-" : input;
}
@Override
protected void doStop() throws Exception {
Logger.log(Logger.DEBUG, ACCESSLOG_RESOURCES, "SimpleAccessLogger.Close", this.fileName);
if (this.outWriter != null) {
this.outWriter.flush();
this.outWriter.close();
this.outWriter = null;
}
if (this.outStream != null) {
try {
this.outStream.close();
} catch (IOException err) {}
this.outStream = null;
}
this.fileName = null;
// this.webAppConfig = null;
}
}