package org.apache.logging.log4j.core.appender.db.jdbc;

import java.io.Closeable;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AppenderLoggingException;
import org.apache.logging.log4j.core.appender.ManagerFactory;
import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.core.util.Closer;

public final class JdbcDatabaseManager extends AbstractDatabaseManager {
   private static final JdbcDatabaseManager.JDBCDatabaseManagerFactory FACTORY = new JdbcDatabaseManager.JDBCDatabaseManagerFactory();
   private final List<JdbcDatabaseManager.Column> columns;
   private final ConnectionSource connectionSource;
   private final String sqlStatement;
   private Connection connection;
   private PreparedStatement statement;

   private JdbcDatabaseManager(String name, int bufferSize, ConnectionSource connectionSource, String sqlStatement, List<JdbcDatabaseManager.Column> columns) {
      super(name, bufferSize);
      this.connectionSource = connectionSource;
      this.sqlStatement = sqlStatement;
      this.columns = columns;
   }

   protected void startupInternal() {
   }

   protected void shutdownInternal() {
      if (this.connection != null || this.statement != null) {
         this.commitAndClose();
      }

   }

   protected void connectAndStart() {
      try {
         this.connection = this.connectionSource.getConnection();
         this.connection.setAutoCommit(false);
         this.statement = this.connection.prepareStatement(this.sqlStatement);
      } catch (SQLException var2) {
         throw new AppenderLoggingException("Cannot write logging event or flush buffer; JDBC manager cannot connect to the database.", var2);
      }
   }

   protected void writeInternal(LogEvent event) {
      StringReader reader = null;

      try {
         if (!this.isRunning() || this.connection == null || this.connection.isClosed() || this.statement == null || this.statement.isClosed()) {
            throw new AppenderLoggingException("Cannot write logging event; JDBC manager not connected to the database.");
         } else {
            int i = 1;
            Iterator i$ = this.columns.iterator();

            while(i$.hasNext()) {
               JdbcDatabaseManager.Column column = (JdbcDatabaseManager.Column)i$.next();
               if (column.isEventTimestamp) {
                  this.statement.setTimestamp(i++, new Timestamp(event.getTimeMillis()));
               } else if (column.isClob) {
                  reader = new StringReader(column.layout.toSerializable(event));
                  if (column.isUnicode) {
                     this.statement.setNClob(i++, reader);
                  } else {
                     this.statement.setClob(i++, reader);
                  }
               } else if (column.isUnicode) {
                  this.statement.setNString(i++, column.layout.toSerializable(event));
               } else {
                  this.statement.setString(i++, column.layout.toSerializable(event));
               }
            }

            if (this.statement.executeUpdate() == 0) {
               throw new AppenderLoggingException("No records inserted in database table for log event in JDBC manager.");
            }
         }
      } catch (SQLException var9) {
         throw new AppenderLoggingException("Failed to insert record for log event in JDBC manager: " + var9.getMessage(), var9);
      } finally {
         Closer.closeSilently((Closeable)reader);
      }
   }

   protected void commitAndClose() {
      try {
         if (this.connection != null && !this.connection.isClosed()) {
            this.connection.commit();
         }
      } catch (SQLException var62) {
         throw new AppenderLoggingException("Failed to commit transaction logging event or flushing buffer.", var62);
      } finally {
         try {
            Closer.close((Statement)this.statement);
         } catch (Exception var60) {
            LOGGER.warn((String)"Failed to close SQL statement logging event or flushing buffer.", (Throwable)var60);
         } finally {
            this.statement = null;
         }

         try {
            Closer.close(this.connection);
         } catch (Exception var58) {
            LOGGER.warn((String)"Failed to close database connection logging event or flushing buffer.", (Throwable)var58);
         } finally {
            this.connection = null;
         }

      }

   }

   public static JdbcDatabaseManager getJDBCDatabaseManager(String name, int bufferSize, ConnectionSource connectionSource, String tableName, ColumnConfig[] columnConfigs) {
      return (JdbcDatabaseManager)AbstractDatabaseManager.getManager(name, new JdbcDatabaseManager.FactoryData(bufferSize, connectionSource, tableName, columnConfigs), FACTORY);
   }

   // $FF: synthetic method
   JdbcDatabaseManager(String x0, int x1, ConnectionSource x2, String x3, List x4, Object x5) {
      this(x0, x1, x2, x3, x4);
   }

   private static final class Column {
      private final PatternLayout layout;
      private final boolean isEventTimestamp;
      private final boolean isUnicode;
      private final boolean isClob;

      private Column(PatternLayout layout, boolean isEventDate, boolean isUnicode, boolean isClob) {
         this.layout = layout;
         this.isEventTimestamp = isEventDate;
         this.isUnicode = isUnicode;
         this.isClob = isClob;
      }

      // $FF: synthetic method
      Column(PatternLayout x0, boolean x1, boolean x2, boolean x3, Object x4) {
         this(x0, x1, x2, x3);
      }
   }

   private static final class JDBCDatabaseManagerFactory implements ManagerFactory<JdbcDatabaseManager, JdbcDatabaseManager.FactoryData> {
      private JDBCDatabaseManagerFactory() {
      }

      public JdbcDatabaseManager createManager(String name, JdbcDatabaseManager.FactoryData data) {
         StringBuilder columnPart = new StringBuilder();
         StringBuilder valuePart = new StringBuilder();
         List<JdbcDatabaseManager.Column> columns = new ArrayList();
         int i = 0;
         ColumnConfig[] arr$ = data.columnConfigs;
         int len$ = arr$.length;

         for(int i$ = 0; i$ < len$; ++i$) {
            ColumnConfig config = arr$[i$];
            if (i++ > 0) {
               columnPart.append(',');
               valuePart.append(',');
            }

            columnPart.append(config.getColumnName());
            if (config.getLiteralValue() != null) {
               valuePart.append(config.getLiteralValue());
            } else {
               columns.add(new JdbcDatabaseManager.Column(config.getLayout(), config.isEventTimestamp(), config.isUnicode(), config.isClob()));
               valuePart.append('?');
            }
         }

         String sqlStatement = "INSERT INTO " + data.tableName + " (" + columnPart + ") VALUES (" + valuePart + ')';
         return new JdbcDatabaseManager(name, data.getBufferSize(), data.connectionSource, sqlStatement, columns);
      }

      // $FF: synthetic method
      JDBCDatabaseManagerFactory(Object x0) {
         this();
      }
   }

   private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
      private final ColumnConfig[] columnConfigs;
      private final ConnectionSource connectionSource;
      private final String tableName;

      protected FactoryData(int bufferSize, ConnectionSource connectionSource, String tableName, ColumnConfig[] columnConfigs) {
         super(bufferSize);
         this.connectionSource = connectionSource;
         this.tableName = tableName;
         this.columnConfigs = columnConfigs;
      }
   }
}
