package net.sf.jacclog.api.domain; import java.net.HttpCookie; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.Set; import net.sf.jacclog.api.domain.http.HttpConnectionStatus; import net.sf.jacclog.api.domain.http.HttpRequestMethod; import net.sf.jacclog.api.domain.http.HttpStatus; import net.sf.jacclog.api.domain.http.ReadableHttpRequestHeaderField; import net.sf.jacclog.api.domain.http.ReadableHttpResponseHeaderField; /** * LogEntry is the standard implementation of an immutable access log entry.<br> * <br> * It is recommended to use the related <code>LogEntryBuilder</code> to create instances of this class. * * @see net.sf.jacclog.api.domain.LogEntryBuilder * * @author André Rouél */ public class LogEntry implements ReadonlyLogEntry { /** * Represents an empty log entry. */ public static final LogEntry EMPTY = new LogEntry(0l, 0l, HttpConnectionStatus.UNKNOWN, new HashSet<HttpCookie>(), "", HttpStatus.UNKNOWN, "", 0, "", "", "", "", "", new HashSet<ReadableHttpRequestHeaderField>(), 0l, HttpRequestMethod.UNKNOWN, "", new Date(0), new HashSet<ReadableHttpResponseHeaderField>(), 0l, "", 0, HttpStatus.UNKNOWN, ""); /** * Bytes received, including request and headers */ private final Long bytesReceived; /** * Bytes sent, including headers */ private final Long bytesSent; /** * Connection status when response was completed. */ private final HttpConnectionStatus connectionStatus; /** * The contents of cookies in the request sent to the server. */ private final Set<HttpCookie> cookies; /** * Filename */ private final String filename; /** * Status for the last request */ private final HttpStatus lastStatusCode; /** * Local IP address */ private final String localIpAddress; /** * The process ID of the child that serviced the request. */ private final Integer processId; /** * The query string (prepended with a <code>?</code> if a query string exists, otherwise an empty string) */ private final String queryString; /** * The client IP address (like 93.71.122.14) or the corresponding hostname (like jacclog.sf.net) of the remote user * requesting the page. For performance reasons, many web servers are configured not to do hostname lookups on the * remote host. This means that all you end up with in the log file is a bunch of IP addresses. */ private final String remoteHost; /** * The client IP address of the request */ private final String remoteIpAddress; /** * Remote logname (from identd, if supplied). This will return a dash unless IdentityCheck is set On. */ private final String remoteLogname; /** * Remote user (from auth; may be bogus if return status (%s) is 401) */ private final String remoteUser; /** * The contents of the header line(s) in the request sent to the server. */ private final Set<ReadableHttpRequestHeaderField> requestHeaders; /** * The time taken to serve the request in microseconds. */ private final Long requestInMillis; /** * The request method. */ private final HttpRequestMethod requestMethod; /** * The request protocol. */ private final String requestProtocol; /** * Time the request was received. */ private final Date requestTime; /** * The contents of Foobar: header line(s) in the reply. */ private final Set<ReadableHttpResponseHeaderField> responseHeaders; /** * Size of response in bytes, excluding HTTP headers.<br> * In CLF format the value '-' will be interpreted as 0 (when no bytes are sent). */ private final Long responseInBytes; /** * The server name according to the UseCanonicalName setting. */ private final String serverName; /** * The canonical port of the server serving the request. */ private final Integer serverPort; /** * Status. For requests that got internally redirected, this is the status of the *original* request --- %...>s for * the last. */ private final HttpStatus statusCode; /** * The URL path requested, not including any query string.<br> * <br> * Placeholder: <code>%U</code> */ private final String urlPath; /** * Constructs a log entry * * @param bytesReceived * @param bytesSent * @param connectionStatus * @param cookies * @param filename * @param lastStatusCode * @param localIpAddress * @param processId * @param queryString * @param remoteHost * @param remoteIpAddress * @param remoteLogname * @param remoteUser * @param requestHeaders * @param requestInMillis * @param requestMethod * @param requestProtocol * @param requestTime * @param responseHeaders * @param responseInBytes * @param serverName * @param serverPort * @param statusCode * @param urlPath * @throws IllegalArgumentException * if some of the given arguments invalid */ public LogEntry(final Long bytesReceived, final Long bytesSent, final HttpConnectionStatus connectionStatus, final Set<HttpCookie> cookies, final String filename, final HttpStatus lastStatusCode, final String localIpAddress, final Integer processId, final String queryString, final String remoteHost, final String remoteIpAddress, final String remoteLogname, final String remoteUser, final Set<ReadableHttpRequestHeaderField> requestHeaders, final Long requestInMillis, final HttpRequestMethod requestMethod, final String requestProtocol, final Date requestTime, final Set<ReadableHttpResponseHeaderField> responseHeaders, final Long responseInBytes, final String serverName, final Integer serverPort, final HttpStatus statusCode, final String urlPath) { if (bytesReceived == null) { throw new IllegalArgumentException("Argument 'bytesReceived' can not be null."); } if (bytesReceived < 0) { throw new IllegalArgumentException("Argument 'bytesReceived' can not be smaller than 0."); } if (bytesSent == null) { throw new IllegalArgumentException("Argument 'bytesSent' can not be null."); } if (bytesSent < 0) { throw new IllegalArgumentException("Argument 'bytesSent' can not be smaller than 0."); } if (connectionStatus == null) { throw new IllegalArgumentException("Argument 'connectionStatus' can not be null."); } if (cookies == null) { throw new IllegalArgumentException("Argument 'cookies' can not be null."); } if (filename == null) { throw new IllegalArgumentException("Argument 'filename' can not be null."); } if (lastStatusCode == null) { throw new IllegalArgumentException("Argument 'lastStatusCode' can not be null."); } if (localIpAddress == null) { throw new IllegalArgumentException("Argument 'localIpAddress' can not be null."); } if (processId == null) { throw new IllegalArgumentException("Argument 'processId' can not be null."); } if (processId < 0) { throw new IllegalArgumentException("Argument 'processId' can not be smaller than 0."); } if (queryString == null) { throw new IllegalArgumentException("Argument 'queryString' can not be null."); } if (remoteHost == null) { throw new IllegalArgumentException("Argument 'remoteHost' can not be null."); } if (remoteIpAddress == null) { throw new IllegalArgumentException("Argument 'remoteIpAddress' can not be null."); } if (remoteLogname == null) { throw new IllegalArgumentException("Argument 'remoteLogname' can not be null."); } if (remoteUser == null) { throw new IllegalArgumentException("Argument 'remoteUser' can not be null."); } if (requestHeaders == null) { throw new IllegalArgumentException("Argument 'requestHeaders' can not be null."); } if (requestInMillis == null) { throw new IllegalArgumentException("Argument 'requestInMillis' can not be null."); } if (requestInMillis < 0) { throw new IllegalArgumentException("Argument 'requestInMillis' can not be smaller than 0."); } if (requestMethod == null) { throw new IllegalArgumentException("Argument 'requestMethod' can not be null."); } if (requestProtocol == null) { throw new IllegalArgumentException("Argument 'requestProtocol' can not be null."); } if (requestTime == null) { throw new IllegalArgumentException("Argument 'requestTime' can not be null."); } if (responseHeaders == null) { throw new IllegalArgumentException("Argument 'responseHeaders' can not be null."); } if (responseInBytes == null) { throw new IllegalArgumentException("Argument 'responseInBytes' can not be null."); } if (responseInBytes < 0) { throw new IllegalArgumentException("Argument 'responseInBytes' can not be smaller than 0."); } if (serverName == null) { throw new IllegalArgumentException("Argument 'serverName' can not be null."); } if (serverPort == null) { throw new IllegalArgumentException("Argument 'serverPort' can not be null."); } if (statusCode == null) { throw new IllegalArgumentException("Argument 'statusCode' can not be null."); } if (urlPath == null) { throw new IllegalArgumentException("Argument 'urlPath' can not be null."); } this.bytesReceived = bytesReceived; this.bytesSent = bytesSent; this.connectionStatus = connectionStatus; this.cookies = cookies; this.filename = filename; this.lastStatusCode = lastStatusCode; this.localIpAddress = localIpAddress; this.processId = processId; this.queryString = queryString; this.remoteHost = remoteHost; this.remoteIpAddress = remoteIpAddress; this.remoteLogname = remoteLogname; this.remoteUser = remoteUser; this.requestHeaders = requestHeaders; this.requestInMillis = requestInMillis; this.requestMethod = requestMethod; this.requestProtocol = requestProtocol; this.requestTime = requestTime; this.responseHeaders = responseHeaders; this.responseInBytes = responseInBytes; this.serverName = serverName; this.serverPort = serverPort; this.statusCode = statusCode; this.urlPath = urlPath; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final LogEntry other = (LogEntry) obj; if (bytesReceived == null) { if (other.bytesReceived != null) { return false; } } else if (!bytesReceived.equals(other.bytesReceived)) { return false; } if (bytesSent == null) { if (other.bytesSent != null) { return false; } } else if (!bytesSent.equals(other.bytesSent)) { return false; } if (connectionStatus != other.connectionStatus) { return false; } if (cookies == null) { if (other.cookies != null) { return false; } } else if (!cookies.equals(other.cookies)) { return false; } if (filename == null) { if (other.filename != null) { return false; } } else if (!filename.equals(other.filename)) { return false; } if (lastStatusCode != other.lastStatusCode) { return false; } if (localIpAddress == null) { if (other.localIpAddress != null) { return false; } } else if (!localIpAddress.equals(other.localIpAddress)) { return false; } if (processId == null) { if (other.processId != null) { return false; } } else if (!processId.equals(other.processId)) { return false; } if (queryString == null) { if (other.queryString != null) { return false; } } else if (!queryString.equals(other.queryString)) { return false; } if (remoteHost == null) { if (other.remoteHost != null) { return false; } } else if (!remoteHost.equals(other.remoteHost)) { return false; } if (remoteIpAddress == null) { if (other.remoteIpAddress != null) { return false; } } else if (!remoteIpAddress.equals(other.remoteIpAddress)) { return false; } if (remoteLogname == null) { if (other.remoteLogname != null) { return false; } } else if (!remoteLogname.equals(other.remoteLogname)) { return false; } if (remoteUser == null) { if (other.remoteUser != null) { return false; } } else if (!remoteUser.equals(other.remoteUser)) { return false; } if (requestHeaders == null) { if (other.requestHeaders != null) { return false; } } else if (!requestHeaders.equals(other.requestHeaders)) { return false; } if (requestInMillis == null) { if (other.requestInMillis != null) { return false; } } else if (!requestInMillis.equals(other.requestInMillis)) { return false; } if (requestMethod == null) { if (other.requestMethod != null) { return false; } } else if (!requestMethod.equals(other.requestMethod)) { return false; } if (requestProtocol == null) { if (other.requestProtocol != null) { return false; } } else if (!requestProtocol.equals(other.requestProtocol)) { return false; } if (requestTime == null) { if (other.requestTime != null) { return false; } } else if (!requestTime.equals(other.requestTime)) { return false; } if (responseHeaders == null) { if (other.responseHeaders != null) { return false; } } else if (!responseHeaders.equals(other.responseHeaders)) { return false; } if (responseInBytes == null) { if (other.responseInBytes != null) { return false; } } else if (!responseInBytes.equals(other.responseInBytes)) { return false; } if (serverName == null) { if (other.serverName != null) { return false; } } else if (!serverName.equals(other.serverName)) { return false; } if (serverPort == null) { if (other.serverPort != null) { return false; } } else if (!serverPort.equals(other.serverPort)) { return false; } if (statusCode != other.statusCode) { return false; } if (urlPath == null) { if (other.urlPath != null) { return false; } } else if (!urlPath.equals(other.urlPath)) { return false; } return true; } /** * Gets the received bytes including the request and headers. If zero returns, then no received bytes were logged. * * @return the bytes received or <code>0</code> */ @Override public Long getBytesReceived() { return bytesReceived; } /** * Gets the sent bytes including the headers. If zero returns, then no sent bytes were logged. * * @return the bytes sent or <code>0</code> */ @Override public Long getBytesSent() { return bytesSent; } /** * Gets the connection status when response was completed. * * @return the connection status */ @Override public HttpConnectionStatus getConnectionStatus() { return connectionStatus; } /** * Gets the filename of the log file. * * @return the filename the log file */ @Override public String getFilename() { return filename; } /** * Gets the status code of the last HTTP request. When internal redirects are made​​, the final status will be * returned. * * @return the status code of the last HTTP request */ @Override public HttpStatus getLastStatusCode() { return lastStatusCode; } /** * Gets the local (usually the servers) IP address. * * @return the local IP address */ @Override public String getLocalIpAddress() { return localIpAddress; } /** * Gets the ID of the process that serviced the request. * * @return the ID of the process */ @Override public Integer getProcessId() { return processId; } /** * Gets the query string (prepended with a <code>?</code> if a query string exists, otherwise an empty string) of * the requested URL.<br> * <br> * The query string is the part of a Uniform Resource Locator (URL) that contains data to be passed to web * applications.<br> * <br> * For example: <code>http://server/path/program?query_string</code> * * @return the query string */ @Override public String getQueryString() { return queryString; } /** * Gets the client IP address (like 93.71.122.14) or the corresponding hostname (like <code>jacclog.sf.net</code>) * of the remote user requesting the resource.<br> * <br> * For performance reasons, many web servers are configured not to do hostname lookups on the remote host. This * means that all you end up within the log file is a bunch of IP addresses. * * @return the remote IP address or hostname */ @Override public String getRemoteHost() { return remoteHost; } /** * Gets the client IP address (like 93.71.122.14) of the remote user requesting the resource. * * @return the remote IP address */ @Override public String getRemoteIpAddress() { return remoteIpAddress; } /** * Gets the remote logname (from identd, if supplied). * * @return the remote logname */ @Override public String getRemoteLogname() { return remoteLogname; } /** * Gets the remote user name. * * @return the remote user name */ @Override public String getRemoteUser() { return remoteUser; } /** * Gets the logged header lines of the HTTP request. If the set is empty no header informations were logged. * * @return the set of request headers */ @Override public Set<ReadableHttpRequestHeaderField> getRequestHeaders() { return Collections.unmodifiableSet(requestHeaders); } /** * Gets the request in milliseconds. * * @return the request in milliseconds */ @Override public Long getRequestInMillis() { return requestInMillis; } /** * Gets the logged HTTP request method. If it is a valid method the type will be a field of * <code>HttpRequestMethod</code>, otherwise it will be an instance of <code>UnknownHttpRequestMethod</code>. * * @return the HTTP request method */ @Override public HttpRequestMethod getRequestMethod() { return requestMethod; } /** * Gets the used HTTP protocol of the request. * * @return the HTTP protocol */ @Override public String getRequestProtocol() { return requestProtocol; } /** * Gets the time the request was received. * * @return the request time */ @Override public Date getRequestTime() { return requestTime; } /** * Gets the logged header lines of the HTTP response. If the set is empty no header informations were logged. * * @return the set of response headers */ @Override public Set<ReadableHttpResponseHeaderField> getResponseHeaders() { return Collections.unmodifiableSet(responseHeaders); } /** * Gets the size of response in bytes, excluding HTTP headers. * * @return the response in bytes */ @Override public Long getResponseInBytes() { return responseInBytes; } /** * Gets the server name according to the UseCanonicalName setting. * * @return the server name */ @Override public String getServerName() { return serverName; } /** * Gets the canonical port of the server serving the request. * * @return the server port */ @Override public Integer getServerPort() { return serverPort; } /** * Gets the status code of the <strong>original</code> request not of the redirected one. * * @return the status code */ @Override public HttpStatus getStatusCode() { return statusCode; } /** * Gets the URL path requested, not including any query string. * * @return the URL path */ @Override public String getUrlPath() { return urlPath; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((bytesReceived == null) ? 0 : bytesReceived.hashCode()); result = prime * result + ((bytesSent == null) ? 0 : bytesSent.hashCode()); result = prime * result + ((connectionStatus == null) ? 0 : connectionStatus.hashCode()); result = prime * result + ((cookies == null) ? 0 : cookies.hashCode()); result = prime * result + ((filename == null) ? 0 : filename.hashCode()); result = prime * result + ((lastStatusCode == null) ? 0 : lastStatusCode.hashCode()); result = prime * result + ((localIpAddress == null) ? 0 : localIpAddress.hashCode()); result = prime * result + ((processId == null) ? 0 : processId.hashCode()); result = prime * result + ((queryString == null) ? 0 : queryString.hashCode()); result = prime * result + ((remoteHost == null) ? 0 : remoteHost.hashCode()); result = prime * result + ((remoteIpAddress == null) ? 0 : remoteIpAddress.hashCode()); result = prime * result + ((remoteLogname == null) ? 0 : remoteLogname.hashCode()); result = prime * result + ((remoteUser == null) ? 0 : remoteUser.hashCode()); result = prime * result + ((requestHeaders == null) ? 0 : requestHeaders.hashCode()); result = prime * result + ((requestInMillis == null) ? 0 : requestInMillis.hashCode()); result = prime * result + ((requestMethod == null) ? 0 : requestMethod.hashCode()); result = prime * result + ((requestProtocol == null) ? 0 : requestProtocol.hashCode()); result = prime * result + ((requestTime == null) ? 0 : requestTime.hashCode()); result = prime * result + ((responseHeaders == null) ? 0 : responseHeaders.hashCode()); result = prime * result + ((responseInBytes == null) ? 0 : responseInBytes.hashCode()); result = prime * result + ((serverName == null) ? 0 : serverName.hashCode()); result = prime * result + ((serverPort == null) ? 0 : serverPort.hashCode()); result = prime * result + ((statusCode == null) ? 0 : statusCode.hashCode()); result = prime * result + ((urlPath == null) ? 0 : urlPath.hashCode()); return result; } @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append("LogEntry [bytesReceived="); builder.append(bytesReceived); builder.append(", bytesSent="); builder.append(bytesSent); builder.append(", connectionStatus="); builder.append(connectionStatus); builder.append(", cookies="); builder.append(cookies); builder.append(", filename="); builder.append(filename); builder.append(", lastStatusCode="); builder.append(lastStatusCode); builder.append(", localIpAddress="); builder.append(localIpAddress); builder.append(", processId="); builder.append(processId); builder.append(", queryString="); builder.append(queryString); builder.append(", remoteHost="); builder.append(remoteHost); builder.append(", remoteIpAddress="); builder.append(remoteIpAddress); builder.append(", remoteLogname="); builder.append(remoteLogname); builder.append(", remoteUser="); builder.append(remoteUser); builder.append(", requestHeaders="); builder.append(requestHeaders); builder.append(", requestInMillis="); builder.append(requestInMillis); builder.append(", requestMethod="); builder.append(requestMethod); builder.append(", requestProtocol="); builder.append(requestProtocol); builder.append(", requestTime="); builder.append(requestTime); builder.append(", responseHeaders="); builder.append(responseHeaders); builder.append(", responseInBytes="); builder.append(responseInBytes); builder.append(", serverName="); builder.append(serverName); builder.append(", serverPort="); builder.append(serverPort); builder.append(", statusCode="); builder.append(statusCode); builder.append(", urlPath="); builder.append(urlPath); builder.append("]"); return builder.toString(); } }