001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.access.sift;
015
016import javax.servlet.http.HttpServletRequest;
017import javax.servlet.http.HttpSession;
018
019import ch.qos.logback.access.spi.IAccessEvent;
020import ch.qos.logback.core.sift.AbstractDiscriminator;
021
022/**
023 * 
024 * AccessEventDiscriminator's job is to return the value of a designated field
025 * in an {@link IAccessEvent} instance.
026 * 
027 * <p>The field is specified via the {@link FieldName} property.
028 * 
029 * @author Ceki G&uuml;lc&uuml;
030 * 
031 */
032public class AccessEventDiscriminator extends AbstractDiscriminator<IAccessEvent> {
033
034    /**
035     * At present time the followed fields can be designated: COOKIE,
036     * REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS,
037     * LOCAL_PORT,REQUEST_URI
038     * 
039     * <p> The first three fields require an additional key. For the
040     * SESSION_ATTRIBUTE field, the additional key named "id" has special meaning
041     * as it is mapped to the session id of the current http request.
042     */
043    public enum FieldName {
044        COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT, REQUEST_URI
045    }
046
047    String defaultValue;
048    String key;
049    FieldName fieldName;
050    String additionalKey;
051
052    @Override
053    public String getDiscriminatingValue(IAccessEvent acccessEvent) {
054        String rawValue = getRawDiscriminatingValue(acccessEvent);
055        if (rawValue == null || rawValue.length() == 0) {
056            return defaultValue;
057        } else {
058            return rawValue;
059        }
060    }
061
062    public String getRawDiscriminatingValue(IAccessEvent acccessEvent) {
063        switch (fieldName) {
064        case COOKIE:
065            // tested
066            return acccessEvent.getCookie(additionalKey);
067        case LOCAL_PORT:
068            return String.valueOf(acccessEvent.getLocalPort());
069        case REQUEST_ATTRIBUTE:
070            // tested
071            return getRequestAttribute(acccessEvent);
072        case SESSION_ATTRIBUTE:
073            return getSessionAttribute(acccessEvent);
074        case REMOTE_ADDRESS:
075            return acccessEvent.getRemoteAddr();
076        case REQUEST_URI:
077            // tested
078            return getRequestURI(acccessEvent);
079        default:
080            return null;
081        }
082    }
083
084    private String getRequestAttribute(IAccessEvent acccessEvent) {
085        String attr = acccessEvent.getAttribute(additionalKey);
086        if (IAccessEvent.NA.equals(attr)) {
087            return null;
088        } else {
089            return attr;
090        }
091    }
092
093    private String getRequestURI(IAccessEvent acccessEvent) {
094        String uri = acccessEvent.getRequestURI();
095        if (uri != null && uri.length() >= 1 && uri.charAt(0) == '/') {
096            return uri.substring(1);
097        } else {
098            return uri;
099        }
100    }
101
102    private String getSessionAttribute(IAccessEvent acccessEvent) {
103        HttpServletRequest req = acccessEvent.getRequest();
104        if (req != null) {
105            HttpSession session = req.getSession(false);
106            if (session != null) {
107                if ("id".equalsIgnoreCase(additionalKey)) {
108                    return session.getId();
109                } else {
110                    Object v = session.getAttribute(additionalKey);
111                    if (v != null) {
112                        return v.toString();
113                    }
114                }
115            }
116        }
117        return null;
118    }
119
120    @Override
121    public void start() {
122
123        int errorCount = 0;
124
125        if (defaultValue == null) {
126            addError("\"DefaultValue\" property must be set.");
127        }
128        if (fieldName == null) {
129            addError("\"FieldName\" property must be set.");
130            errorCount++;
131        }
132
133        switch (fieldName) {
134        case SESSION_ATTRIBUTE:
135        case REQUEST_ATTRIBUTE:
136        case COOKIE:
137            if (additionalKey == null) {
138                addError("\"OptionalKey\" property is mandatory for field name " + fieldName.toString());
139                errorCount++;
140            }
141        }
142
143        if (errorCount == 0) {
144            started = true;
145        }
146    }
147
148    public void setFieldName(FieldName fieldName) {
149        this.fieldName = fieldName;
150    }
151
152    public FieldName getFieldName() {
153        return fieldName;
154    }
155
156    public String getAdditionalKey() {
157        return additionalKey;
158    }
159
160    public void setAdditionalKey(String additionalKey) {
161        this.additionalKey = additionalKey;
162    }
163
164    /**
165     * @see #setDefaultValue(String)
166     * @return
167     */
168    public String getDefaultValue() {
169        return defaultValue;
170    }
171
172    /**
173     * The default value returned by this discriminator in case it cannot compute
174     * the discriminating value from the access event.
175     * 
176     * @param defaultValue
177     */
178    public void setDefaultValue(String defaultValue) {
179        this.defaultValue = defaultValue;
180    }
181
182    public String getKey() {
183        return key;
184    }
185
186    public void setKey(String key) {
187        this.key = key;
188    }
189
190}