| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.sling.engine.impl.log; |
| |
| import javax.servlet.http.Cookie; |
| |
| import java.text.CharacterIterator; |
| import java.text.DecimalFormat; |
| import java.text.SimpleDateFormat; |
| import java.text.StringCharacterIterator; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.Date; |
| import java.util.Enumeration; |
| import java.util.List; |
| import java.util.Locale; |
| |
| import org.apache.sling.engine.impl.request.RequestData; |
| |
| /** |
| * The <code>CustomLogFormat</code> class implements the support for log format |
| * strings similar to the Apache httpd CustomLog configuration. |
| * |
| * @see <a |
| * href="http://sling.apache.org/site/client-request-logging.html">Client |
| * Request Logging</a> for documentation of supported formats. |
| */ |
| class CustomLogFormat { |
| |
| /* |
| * NOTE: Documentation at |
| * https://cwiki.apache.org/confluence/display/SLINGxSITE |
| * /Client+Request+Logging should be kept in sync with this class ! |
| */ |
| |
| /** |
| * The parsed list of log format parts whose <code>print</code> method is |
| * called when building the log message line. |
| */ |
| Parameter[] logParameters; |
| |
| /** |
| * Creates a new instance from of this class parsing the log format pattern. |
| * |
| * @param pattern The pattern to be parsed. |
| */ |
| CustomLogFormat(String pattern) { |
| this.logParameters = this.parse(pattern); |
| if (this.logParameters.length == 0) { |
| this.logParameters = null; |
| } |
| } |
| |
| /** |
| * Creates a log message from the given <code>request</code> and |
| * <code>response</code> objects according to the log format from which this |
| * instance has been created. |
| * |
| * @param request The {@link RequestLoggerRequest} used to extract values |
| * for the log message. |
| * @param response The {@link RequestLoggerResponse} used to extract values |
| * for the log message. |
| * @return The formatted log message or <code>null</code> if this log |
| * formatter has not been initialized with a valid log format |
| * pattern. |
| */ |
| String format(RequestLoggerRequest request, RequestLoggerResponse response) { |
| if (this.logParameters != null) { |
| StringBuilder buf = new StringBuilder(); |
| for (int i = 0; i < this.logParameters.length; i++) { |
| this.logParameters[i].print(buf, request, response); |
| } |
| return buf.toString(); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns a string representation of this log format instance. The returned |
| * String is actually rebuilt from the parsed format string and may be used |
| * to create another instance of this class with the same format string. |
| * |
| * @return String representation of this instance. |
| */ |
| public String toString() { |
| StringBuilder buf = new StringBuilder(); |
| for (int i = 0; this.logParameters != null && i < this.logParameters.length; i++) { |
| buf.append(this.logParameters[i]); |
| } |
| return buf.toString(); |
| } |
| |
| // ---------- Parsing the format pattern ----------------------------------- |
| |
| private Parameter[] parse(String pattern) { |
| |
| List<Parameter> parameterList = new ArrayList<Parameter>(); |
| StringBuilder buf = new StringBuilder(); |
| |
| CharacterIterator sr = new StringCharacterIterator(pattern); |
| |
| for (int c = sr.first(); c != CharacterIterator.DONE; c = sr.next()) { |
| if (c == '%') { |
| int c1 = sr.next(); |
| if (c1 != '%') { |
| if (buf.length() > 0) { |
| Parameter text = new PlainTextParameter(buf.toString()); |
| parameterList.add(text); |
| buf.setLength(0); |
| } |
| |
| Parameter param = this.parseFormatString(sr, c1); |
| if (param != null) { |
| parameterList.add(param); |
| } |
| continue; |
| } |
| } |
| |
| buf.append((char) c); |
| } |
| |
| // append any remaining plain text |
| if (buf.length() > 0) { |
| Parameter text = new PlainTextParameter(buf.toString()); |
| parameterList.add(text); |
| buf.setLength(0); |
| } |
| |
| return parameterList.toArray(new Parameter[parameterList.size()]); |
| } |
| |
| private Parameter parseFormatString(CharacterIterator sr, int c) { |
| |
| // read all modifiers |
| boolean required = true; |
| int[] statCodes = null; |
| while (c != CharacterIterator.DONE) { |
| if (c == '!') { |
| required = false; |
| } else if (c >= '0' && c <= '9') { |
| statCodes = this.parseStatusCodes(sr, c); |
| } else if (c == '>' || c == '<') { |
| // ignore first/last modifiers |
| } else { |
| break; |
| } |
| |
| c = sr.next(); |
| } |
| |
| // read name |
| String name; |
| if (c == '{') { |
| StringBuilder nameBuf = new StringBuilder(); |
| for (c = sr.next(); c != CharacterIterator.DONE && c != '}'; c = sr.next()) { |
| nameBuf.append((char) c); |
| } |
| name = (nameBuf.length() > 0) ? nameBuf.toString() : null; |
| |
| // get the format indicator |
| c = sr.next(); |
| } else { |
| name = null; |
| } |
| |
| Parameter param; |
| switch (c) { |
| case 'a': |
| param = new RemoteIPParameter(); |
| break; |
| |
| case 'A': |
| param = new LocalIPParameter(); |
| break; |
| |
| case 'b': |
| case 'B': |
| param = new ByteCountParameter(); |
| break; |
| |
| case 'C': |
| param = (name == null) ? null : new CookieParameter(name, true); |
| break; |
| |
| case 'D': |
| param = new DurationParameter(false); |
| break; |
| |
| case 'f': |
| // we assume the path to the content the request resolved to |
| param = new ContentPathParameter(); |
| break; |
| |
| case 'h': |
| param = new RemoteHostParameter(); |
| break; |
| |
| case 'H': |
| param = new ProtocolParameter(); |
| break; |
| |
| case 'i': |
| param = (name == null) ? null : new HeaderParameter(name, true); |
| break; |
| |
| case 'm': |
| param = new MethodParameter(); |
| break; |
| |
| case 'M': |
| param = new ParamParameter(name); |
| break; |
| |
| case 'o': |
| param = (name == null) ? null : new HeaderParameter(name, false); |
| break; |
| |
| case 'p': |
| param = new LocalPortParameter(); |
| break; |
| |
| case 'P': |
| // %{format}P form is not currently supported |
| param = new ThreadParameter(name); |
| break; |
| |
| case 'q': |
| param = new QueryParameter(); |
| break; |
| |
| case 'r': |
| param = new FirstRequestLineParameter(); |
| break; |
| |
| case 'R': |
| param = new IdParameter(); |
| break; |
| |
| case 's': |
| param = new StatusParameter(); |
| break; |
| |
| case 't': |
| // %{format}t form is not currently supported |
| param = new TimeParameter(name); |
| break; |
| |
| case 'T': |
| param = new DurationParameter(true); |
| break; |
| |
| case 'u': |
| param = new UserParameter(); |
| break; |
| |
| case 'U': |
| param = new RequestParameter(); |
| break; |
| |
| case 'v': |
| case 'V': |
| param = new ServerNameParameter(); |
| break; |
| |
| case 'y': |
| param = new AuthTypeParameter(); |
| break; |
| |
| case 'X': // no supported fall through to default |
| case 'I': // no supported fall through to default |
| case 'O': // no supported fall through to default |
| case 'n': // no supported fall through to default |
| case 'l': // no supported fall through to default |
| case 'e': // no supported fall through to default |
| default: |
| param = new NonImplementedParameter(name); |
| break; |
| } |
| |
| if (param instanceof BaseParameter) { |
| BaseParameter baseParam = (BaseParameter) param; |
| baseParam.setParName((char) c); |
| baseParam.setRequired(required); |
| baseParam.setStatusLimits(statCodes); |
| } |
| |
| return param; |
| } |
| |
| private int[] parseStatusCodes(CharacterIterator sr, int c) { |
| StringBuilder buf = new StringBuilder(); |
| buf.append((char) c); |
| |
| List<Integer> numbers = new ArrayList<Integer>(); |
| for (c = sr.next(); c != CharacterIterator.DONE; c = sr.next()) { |
| if (c == ',') { |
| int num = 0; |
| try { |
| num = Integer.parseInt(buf.toString()); |
| } catch (NumberFormatException nfe) { |
| // don't care |
| } |
| if (num >= 100 && num <= 999) { |
| numbers.add(num); |
| } |
| buf.setLength(0); |
| } else if (c >= '0' && c <= '9') { |
| buf.append((char) c); |
| } else { |
| // end of number list |
| break; |
| } |
| } |
| |
| // reset to the last mark |
| sr.previous(); |
| |
| // get the last number |
| int num = 0; |
| try { |
| num = Integer.parseInt(buf.toString()); |
| } catch (NumberFormatException nfe) { |
| // don't care |
| } |
| if (num >= 100 && num <= 999) { |
| numbers.add(num); |
| } |
| |
| if (numbers.isEmpty()) { |
| return null; |
| } |
| |
| int[] statusCodes = new int[numbers.size()]; |
| for (int i = 0; i < numbers.size(); i++) { |
| statusCodes[i] = (numbers.get(i)).intValue(); |
| } |
| return statusCodes; |
| } |
| |
| // ---------- Parameter support -------------------------------------------- |
| |
| static interface Parameter { |
| void print(StringBuilder dest, RequestLoggerRequest request, RequestLoggerResponse response); |
| } |
| |
| static class PlainTextParameter implements Parameter { |
| private String value; |
| |
| PlainTextParameter(String value) { |
| this.value = value; |
| } |
| |
| public void print(StringBuilder dest, RequestLoggerRequest request, RequestLoggerResponse response) { |
| dest.append(this.value); |
| } |
| |
| public String toString() { |
| return this.value; |
| } |
| } |
| |
| abstract static class BaseParameter implements Parameter { |
| private int[] statusLimits; |
| |
| private boolean required; |
| |
| private char parName; |
| |
| private final String parParam; |
| |
| private final boolean isRequest; |
| |
| protected BaseParameter(String parParam, boolean isRequest) { |
| this.parParam = parParam; |
| this.isRequest = isRequest; |
| } |
| |
| public void setParName(char parName) { |
| this.parName = parName; |
| } |
| |
| public void setStatusLimits(int[] statusLimits) { |
| this.statusLimits = statusLimits; |
| } |
| |
| public void setRequired(boolean required) { |
| this.required = required; |
| } |
| |
| protected abstract String getValue(RequestLoggerRequest request); |
| |
| protected abstract String getValue(RequestLoggerResponse response); |
| |
| public final void print(StringBuilder dest, RequestLoggerRequest request, RequestLoggerResponse response) { |
| if (this.printOk(response.getStatus())) { |
| String value = this.isRequest ? this.getValue(request) : this.getValue(response); |
| dest.append((value == null) ? "-" : value); |
| } |
| } |
| |
| protected boolean printOk(int status) { |
| if (this.statusLimits == null) { |
| return true; |
| } |
| |
| for (int i = 0; i < this.statusLimits.length; i++) { |
| if (status == this.statusLimits[i]) { |
| return this.required; |
| } |
| } |
| |
| return !this.required; |
| } |
| |
| protected char getParName() { |
| return this.parName; |
| } |
| |
| protected String getParParam() { |
| return this.parParam; |
| } |
| |
| public String toString() { |
| StringBuilder result = new StringBuilder("%"); |
| |
| if (this.statusLimits != null) { |
| if (!this.required) { |
| result.append('!'); |
| } |
| |
| for (int i = 0; i < this.statusLimits.length; i++) { |
| if (i > 0) { |
| result.append(','); |
| } |
| result.append(this.statusLimits[i]); |
| } |
| } |
| |
| if (this.parParam != null) { |
| result.append('{').append(this.parParam).append('}'); |
| } |
| result.append(this.parName); |
| |
| return result.toString(); |
| } |
| |
| // --------- helper ---------------------------------------------------- |
| |
| private static boolean isPrint(char c) { |
| return c >= 0x20 && c < 0x7f && c != '\\' && c != '"'; |
| } |
| |
| static String escape(String value) { |
| // nothing to do for empty values |
| if (value == null || value.length() == 0) { |
| return value; |
| } |
| |
| // find the first non-printable |
| int i = 0; |
| while (i < value.length() && isPrint(value.charAt(i))) { |
| i++; |
| } |
| |
| // if none has been found, just return the value |
| if (i >= value.length()) { |
| return value; |
| } |
| |
| // otherwise copy the printable first part in a string buffer |
| // and start encoding |
| StringBuilder buf = new StringBuilder(value.substring(0, i)); |
| while (i < value.length()) { |
| char c = value.charAt(i); |
| if (isPrint(c)) { |
| buf.append(c); |
| } else if (c == '\n') { // LF |
| buf.append("\\n"); |
| } else if (c == '\r') { // CR |
| buf.append("\\r"); |
| } else if (c == '\t') { // HTAB |
| buf.append("\\t"); |
| } else if (c == '\f') { // VTAB |
| buf.append("\\f"); |
| } else if (c == '\b') { // BSP |
| buf.append("\\b"); |
| } else if (c == '"') { // " |
| buf.append("\\\""); |
| } else if (c == '\\') { // \ |
| buf.append("\\\\"); |
| } else { // encode |
| buf.append("\\u"); |
| if (c < 0x10) { |
| buf.append('0'); // leading zero |
| } |
| if (c < 0x100) { |
| buf.append('0'); // leading zero |
| } |
| if (c < 0x1000) { |
| buf.append('0'); // leading zero |
| } |
| buf.append(Integer.toHexString(c)); |
| } |
| i++; |
| } |
| |
| // return the encoded string value |
| return buf.toString(); |
| } |
| } |
| |
| static class NonImplementedParameter extends BaseParameter { |
| |
| NonImplementedParameter(String parParam) { |
| super(parParam, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return null; |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class ThreadParameter extends BaseParameter { |
| public ThreadParameter(String parParam) { |
| super(parParam, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return Thread.currentThread().getName(); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class ParamParameter extends BaseParameter { |
| public ParamParameter(String parParam) { |
| super(parParam, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return request.getParameter(this.getParParam()); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class IdParameter extends BaseParameter { |
| public IdParameter() { |
| super(null, false); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return null; |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return String.valueOf(response.getRequestId()); |
| } |
| } |
| |
| static class ByteCountParameter extends BaseParameter { |
| public ByteCountParameter() { |
| super(null, false); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return null; |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| int count = response.getCount(); |
| if (count == 0) { |
| return (this.getParName() == 'b') ? "-" : "0"; |
| } |
| |
| return String.valueOf(count); |
| } |
| } |
| |
| static class TimeParameter extends BaseParameter { |
| |
| /** date format - see access logging in service() */ |
| private static final SimpleDateFormat accessLogFmt = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss ", Locale.US); |
| |
| /** time format for GMT offset - see access logging in service() */ |
| private static final DecimalFormat dfmt = new DecimalFormat("+0000;-0000"); |
| |
| /** the timezone for the timezone offset calculation */ |
| private static final Calendar calendar = Calendar.getInstance(); |
| |
| /** last zone offset (cached by hours) */ |
| private static String lastZoneOffset = ""; |
| |
| private static long lastZoneOffsetHour = -1; |
| |
| /** last formatted time (cached in seconds) */ |
| private static String lastTimeFormatted = ""; |
| |
| private static long lastTimeFormattedSeconds = -1; |
| |
| private final boolean requestStart; |
| |
| public TimeParameter(String parParam) { |
| super(parParam, false); |
| |
| this.requestStart = parParam == null || !parParam.equals("end"); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return null; |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| long time = this.requestStart ? response.getRequestStart() : response.getRequestEnd(); |
| return timeFormatted(time); |
| } |
| |
| // ---------- internal |
| // ----------------------------------------------------- |
| |
| static String timeFormatted(long time) { |
| if (time / 1000 != lastTimeFormattedSeconds) { |
| lastTimeFormattedSeconds = time / 1000; |
| Date date = new Date(time); |
| StringBuilder buf = new StringBuilder(accessLogFmt.format(date)); |
| if (time / 3600000 != lastZoneOffsetHour) { |
| lastZoneOffsetHour = time / 3600000; |
| calendar.setTime(date); |
| int tzOffset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); |
| tzOffset /= (60 * 1000); |
| tzOffset = ((tzOffset / 60) * 100) + (tzOffset % 60); |
| |
| lastZoneOffset = dfmt.format(tzOffset); |
| } |
| buf.append(lastZoneOffset); |
| lastTimeFormatted = buf.toString(); |
| } |
| return lastTimeFormatted; |
| } |
| } |
| |
| static class DurationParameter extends BaseParameter { |
| private final boolean seconds; |
| |
| public DurationParameter(boolean seconds) { |
| super(null, false); |
| this.seconds = seconds; |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return null; |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| long time = response.getRequestDuration(); |
| if (this.seconds) { |
| time /= 1000; |
| } |
| return String.valueOf(time); |
| } |
| } |
| |
| static class RemoteIPParameter extends BaseParameter { |
| public RemoteIPParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return request.getRemoteAddr(); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class RemoteHostParameter extends BaseParameter { |
| public RemoteHostParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return request.getRemoteHost(); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class LocalIPParameter extends BaseParameter { |
| public LocalIPParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return request.getLocalAddr(); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class LocalPortParameter extends BaseParameter { |
| public LocalPortParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return String.valueOf(request.getServerPort()); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class ServerNameParameter extends BaseParameter { |
| public ServerNameParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return request.getServerName(); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class ContentPathParameter extends BaseParameter { |
| public ContentPathParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| final Object resourcePath = request.getAttribute(RequestData.REQUEST_RESOURCE_PATH_ATTR); |
| if (resourcePath instanceof String) { |
| return (String) resourcePath; |
| } |
| return null; |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class FirstRequestLineParameter extends BaseParameter { |
| public FirstRequestLineParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| String query = request.getQueryString(); |
| query = (query == null || query.length() == 0) ? "" : "?" + query; |
| |
| return request.getMethod() + " " + request.getRequestURI() + query + " " + request.getProtocol(); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class ProtocolParameter extends BaseParameter { |
| public ProtocolParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return request.getProtocol(); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class MethodParameter extends BaseParameter { |
| public MethodParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return request.getMethod(); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class RequestParameter extends BaseParameter { |
| public RequestParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return request.getRequestURI(); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class QueryParameter extends BaseParameter { |
| public QueryParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| String query = request.getQueryString(); |
| return (query == null || query.length() == 0) ? "" : "?" + query; |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class UserParameter extends BaseParameter { |
| public UserParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| final String user = request.getRemoteUser(); |
| return (user == null) ? null : escape(user); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class AuthTypeParameter extends BaseParameter { |
| public AuthTypeParameter() { |
| super(null, true); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| final String authType = request.getAuthType(); |
| return (authType == null) ? null : escape(authType); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return null; |
| } |
| } |
| |
| static class StatusParameter extends BaseParameter { |
| public StatusParameter() { |
| super(null, false); |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return null; |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return String.valueOf(response.getStatus()); |
| } |
| } |
| |
| static class CookieParameter extends BaseParameter { |
| private String cookieName; |
| |
| CookieParameter(String cookieName, boolean isRequest) { |
| super(cookieName, isRequest); |
| this.cookieName = cookieName; |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| return getValue(request.getCookie(this.cookieName)); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return getValue(response.getCookie(this.cookieName)); |
| } |
| |
| private String getValue(final Cookie cookie) { |
| return (cookie == null) ? null : escape(cookie.getValue()); |
| } |
| } |
| |
| static class HeaderParameter extends BaseParameter { |
| private String headerName; |
| |
| HeaderParameter(String headerName, boolean isRequest) { |
| super(headerName, isRequest); |
| this.headerName = headerName; |
| } |
| |
| protected String getValue(RequestLoggerRequest request) { |
| Enumeration<?> values = request.getHeaders(this.headerName); |
| if (values == null || !values.hasMoreElements()) { |
| return null; |
| } |
| |
| String value = (String) values.nextElement(); |
| while (values.hasMoreElements()) { |
| value += "," + values.nextElement(); |
| } |
| return escape(value); |
| } |
| |
| protected String getValue(RequestLoggerResponse response) { |
| return escape(response.getHeadersString(this.headerName)); |
| } |
| } |
| } |