1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.access.common.sift;
15  
16  import ch.qos.logback.access.common.spi.IAccessEvent;
17  import jakarta.servlet.http.HttpServletRequest;
18  import jakarta.servlet.http.HttpSession;
19  
20  import ch.qos.logback.core.sift.AbstractDiscriminator;
21  
22  /**
23   * 
24   * AccessEventDiscriminator's job is to return the value of a designated field
25   * in an {@link IAccessEvent} instance.
26   * 
27   * <p>The field is specified via the {@link FieldName} property.
28   * 
29   * @author Ceki G&uuml;lc&uuml;
30   * 
31   */
32  public class AccessEventDiscriminator extends AbstractDiscriminator<IAccessEvent> {
33  
34      /**
35       * At present time the followed fields can be designated: COOKIE,
36       * REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS,
37       * LOCAL_PORT,REQUEST_URI
38       * 
39       * <p> The first three fields require an additional key. For the
40       * SESSION_ATTRIBUTE field, the additional key named "id" has special meaning
41       * as it is mapped to the session id of the current http request.
42       */
43      public enum FieldName {
44          COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT, REQUEST_URI
45      }
46  
47      String defaultValue;
48      String key;
49      FieldName fieldName;
50      String additionalKey;
51  
52      @Override
53      public String getDiscriminatingValue(IAccessEvent acccessEvent) {
54          String rawValue = getRawDiscriminatingValue(acccessEvent);
55          if (rawValue == null || rawValue.length() == 0) {
56              return defaultValue;
57          } else {
58              return rawValue;
59          }
60      }
61  
62      public String getRawDiscriminatingValue(IAccessEvent acccessEvent) {
63          switch (fieldName) {
64          case COOKIE:
65              // tested
66              return acccessEvent.getCookie(additionalKey);
67          case LOCAL_PORT:
68              return String.valueOf(acccessEvent.getLocalPort());
69          case REQUEST_ATTRIBUTE:
70              // tested
71              return getRequestAttribute(acccessEvent);
72          case SESSION_ATTRIBUTE:
73              return getSessionAttribute(acccessEvent);
74          case REMOTE_ADDRESS:
75              return acccessEvent.getRemoteAddr();
76          case REQUEST_URI:
77              // tested
78              return getRequestURI(acccessEvent);
79          default:
80              return null;
81          }
82      }
83  
84      private String getRequestAttribute(IAccessEvent acccessEvent) {
85          String attr = acccessEvent.getAttribute(additionalKey);
86          if (IAccessEvent.NA.equals(attr)) {
87              return null;
88          } else {
89              return attr;
90          }
91      }
92  
93      private String getRequestURI(IAccessEvent acccessEvent) {
94          String uri = acccessEvent.getRequestURI();
95          if (uri != null && uri.length() >= 1 && uri.charAt(0) == '/') {
96              return uri.substring(1);
97          } else {
98              return uri;
99          }
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 }