View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.core.logic.audit;
20  
21  import java.sql.Connection;
22  import java.sql.SQLException;
23  import java.sql.Timestamp;
24  import java.util.Optional;
25  import javax.sql.DataSource;
26  import org.apache.logging.log4j.LogManager;
27  import org.apache.logging.log4j.core.Appender;
28  import org.apache.logging.log4j.core.LoggerContext;
29  import org.apache.logging.log4j.core.appender.db.ColumnMapping;
30  import org.apache.logging.log4j.core.appender.db.jdbc.AbstractConnectionSource;
31  import org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender;
32  import org.apache.syncope.core.persistence.api.dao.AuditConfDAO;
33  import org.springframework.jdbc.datasource.DataSourceUtils;
34  
35  public class JdbcAuditAppender extends DefaultAuditAppender {
36  
37      public JdbcAuditAppender(final String domain, final DataSource domainDataSource) {
38          super(domain);
39  
40          LoggerContext logCtx = (LoggerContext) LogManager.getContext(false);
41  
42          ColumnMapping[] columnMappings = {
43              ColumnMapping.newBuilder().
44              setConfiguration(logCtx.getConfiguration()).setName("EVENT_DATE").setColumnType(Timestamp.class).build(),
45              ColumnMapping.newBuilder().
46              setConfiguration(logCtx.getConfiguration()).setName("LOGGER_LEVEL").setPattern("%level").build(),
47              ColumnMapping.newBuilder().
48              setConfiguration(logCtx.getConfiguration()).setName("LOGGER").setPattern("%logger").build(),
49              ColumnMapping.newBuilder().
50              setConfiguration(logCtx.getConfiguration()).
51              setName(AuditConfDAO.AUDIT_ENTRY_MESSAGE_COLUMN).setPattern("%message").build(),
52              ColumnMapping.newBuilder().
53              setConfiguration(logCtx.getConfiguration()).setName("THROWABLE").setPattern("%ex{full}").build()
54          };
55  
56          targetAppender = Optional.ofNullable(logCtx.getConfiguration().<Appender>getAppender(getTargetAppenderName())).
57                  orElseGet(() -> {
58                      JdbcAppender a = JdbcAppender.newBuilder().
59                              setName(getTargetAppenderName()).
60                              setIgnoreExceptions(false).
61                              setConnectionSource(new DataSourceConnectionSource(domain, domainDataSource)).
62                              setBufferSize(0).
63                              setTableName(AuditConfDAO.AUDIT_ENTRY_TABLE).
64                              setColumnMappings(columnMappings).
65                              build();
66                      a.start();
67                      logCtx.getConfiguration().addAppender(a);
68                      return a;
69                  });
70      }
71  
72      @Override
73      public String getTargetAppenderName() {
74          return "audit_for_" + domain;
75      }
76  
77      protected static class DataSourceConnectionSource extends AbstractConnectionSource {
78  
79          private final String description;
80  
81          private final DataSource dataSource;
82  
83          DataSourceConnectionSource(final String domain, final DataSource dataSource) {
84              this.description = "dataSource{ domain=" + domain + ", value=" + dataSource + " }";
85              this.dataSource = dataSource;
86          }
87  
88          @Override
89          public Connection getConnection() throws SQLException {
90              return DataSourceUtils.getConnection(dataSource);
91          }
92  
93          @Override
94          public String toString() {
95              return this.description;
96          }
97      }
98  }