View Javadoc
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.db;
15  
16  import java.lang.reflect.Method;
17  import java.sql.Connection;
18  import java.sql.PreparedStatement;
19  import java.sql.SQLException;
20  import java.util.Enumeration;
21  
22  import ch.qos.logback.access.spi.IAccessEvent;
23  import ch.qos.logback.core.db.DBAppenderBase;
24  
25  /**
26   * The DBAppender inserts access events into three database tables in a format
27   * independent of the Java programming language. 
28   * 
29   * For more information about this appender, please refer to the online manual at
30   * http://logback.qos.ch/manual/appenders.html#AccessDBAppender
31   * 
32   * @author Ceki Gülcü
33   * @author Ray DeCampo
34   * @author Sébastien Pennec
35   */
36  public class DBAppender extends DBAppenderBase<IAccessEvent> {
37      protected static final String insertSQL;
38      protected final String insertHeaderSQL = "INSERT INTO  access_event_header (event_id, header_key, header_value) VALUES (?, ?, ?)";
39      protected static final Method GET_GENERATED_KEYS_METHOD;
40  
41      private boolean insertHeaders = false;
42  
43      static {
44          StringBuilder sql = new StringBuilder();
45          sql.append("INSERT INTO access_event (");
46          sql.append("timestmp, ");
47          sql.append("requestURI, ");
48          sql.append("requestURL, ");
49          sql.append("remoteHost, ");
50          sql.append("remoteUser, ");
51          sql.append("remoteAddr, ");
52          sql.append("protocol, ");
53          sql.append("method, ");
54          sql.append("serverName, ");
55          sql.append("postContent) ");
56          sql.append(" VALUES (?, ?, ? ,?, ?, ?, ?, ?, ?, ?)");
57          insertSQL = sql.toString();
58  
59          Method getGeneratedKeysMethod;
60          try {
61              getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);
62          } catch (Exception ex) {
63              getGeneratedKeysMethod = null;
64          }
65          GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
66      }
67  
68      @Override
69      protected void subAppend(IAccessEvent event, Connection connection, PreparedStatement insertStatement) throws Throwable {
70  
71          addAccessEvent(insertStatement, event);
72  
73          int updateCount = insertStatement.executeUpdate();
74          if (updateCount != 1) {
75              addWarn("Failed to insert access event");
76          }
77      }
78  
79      @Override
80      protected void secondarySubAppend(IAccessEvent event, Connection connection, long eventId) throws Throwable {
81          if (insertHeaders) {
82              addRequestHeaders(event, connection, eventId);
83          }
84      }
85  
86      void addAccessEvent(PreparedStatement stmt, IAccessEvent event) throws SQLException {
87          stmt.setLong(1, event.getTimeStamp());
88          stmt.setString(2, event.getRequestURI());
89          stmt.setString(3, event.getRequestURL());
90          stmt.setString(4, event.getRemoteHost());
91          stmt.setString(5, event.getRemoteUser());
92          stmt.setString(6, event.getRemoteAddr());
93          stmt.setString(7, event.getProtocol());
94          stmt.setString(8, event.getMethod());
95          stmt.setString(9, event.getServerName());
96          stmt.setString(10, event.getRequestContent());
97      }
98  
99      void addRequestHeaders(IAccessEvent event, Connection connection, long eventId) throws SQLException {
100         Enumeration names = event.getRequestHeaderNames();
101         if (names.hasMoreElements()) {
102             PreparedStatement insertHeaderStatement = connection.prepareStatement(insertHeaderSQL);
103 
104             while (names.hasMoreElements()) {
105                 String key = (String) names.nextElement();
106                 String value = (String) event.getRequestHeader(key);
107 
108                 insertHeaderStatement.setLong(1, eventId);
109                 insertHeaderStatement.setString(2, key);
110                 insertHeaderStatement.setString(3, value);
111 
112                 if (cnxSupportsBatchUpdates) {
113                     insertHeaderStatement.addBatch();
114                 } else {
115                     insertHeaderStatement.execute();
116                 }
117             }
118 
119             if (cnxSupportsBatchUpdates) {
120                 insertHeaderStatement.executeBatch();
121             }
122 
123             insertHeaderStatement.close();
124         }
125     }
126 
127     @Override
128     protected Method getGeneratedKeysMethod() {
129         return GET_GENERATED_KEYS_METHOD;
130     }
131 
132     @Override
133     protected String getInsertSQL() {
134         return insertSQL;
135     }
136 
137     public void setInsertHeaders(boolean insertHeaders) {
138         this.insertHeaders = insertHeaders;
139     }
140 }