View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * 
4    * Copyright (C) 2000-2008, QOS.ch
5    * 
6    * This library is free software, you can redistribute it and/or modify it under
7    * the terms of the GNU Lesser General Public License as published by the Free
8    * Software Foundation.
9    */
10  
11  package ch.qos.logback.core.db;
12  
13  import java.lang.reflect.InvocationTargetException;
14  import java.lang.reflect.Method;
15  import java.sql.Connection;
16  import java.sql.PreparedStatement;
17  import java.sql.ResultSet;
18  import java.sql.SQLException;
19  import java.sql.Statement;
20  
21  import ch.qos.logback.core.AppenderBase;
22  import ch.qos.logback.core.db.dialect.DBUtil;
23  import ch.qos.logback.core.db.dialect.SQLDialect;
24  
25  /**
26   * @author Ceki Gülcü
27   * @author Ray DeCampo
28   * @author Sébastien Pennec
29   */
30  public abstract class DBAppenderBase<E> extends AppenderBase<E> {
31  
32    protected ConnectionSource connectionSource;
33    protected boolean cnxSupportsGetGeneratedKeys = false;
34    protected boolean cnxSupportsBatchUpdates = false;
35    protected SQLDialect sqlDialect;
36  
37    protected abstract Method getGeneratedKeysMethod();
38  
39    protected abstract String getInsertSQL();
40  
41    @Override
42    public void start() {
43  
44      if (connectionSource == null) {
45        throw new IllegalStateException(
46            "DBAppender cannot function without a connection source");
47      }
48  
49      System.out.println(connectionSource.supportsGetGeneratedKeys());
50      sqlDialect = DBUtil
51          .getDialectFromCode(connectionSource.getSQLDialectCode());
52      if (getGeneratedKeysMethod() != null) {
53        cnxSupportsGetGeneratedKeys = connectionSource.supportsGetGeneratedKeys();
54      } else {
55        cnxSupportsGetGeneratedKeys = false;
56      }
57      cnxSupportsBatchUpdates = connectionSource.supportsBatchUpdates();
58      if (!cnxSupportsGetGeneratedKeys && (sqlDialect == null)) {
59        throw new IllegalStateException(
60            "DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method *and* without a specific SQL dialect");
61      }
62  
63      // all nice and dandy on the eastern front
64      super.start();
65    }
66  
67    /**
68     * @return Returns the connectionSource.
69     */
70    public ConnectionSource getConnectionSource() {
71      return connectionSource;
72    }
73  
74    /**
75     * @param connectionSource
76     *                The connectionSource to set.
77     */
78    public void setConnectionSource(ConnectionSource connectionSource) {
79      this.connectionSource = connectionSource;
80    }
81  
82    @Override
83    public void append(E eventObject) {
84      Connection connection = null;
85      try {
86        connection = connectionSource.getConnection();
87        connection.setAutoCommit(false);
88        PreparedStatement insertStatement;
89        if (cnxSupportsGetGeneratedKeys) {
90          insertStatement = connection.prepareStatement(getInsertSQL(),
91              new String[] {"EVENT_ID"});
92        } else {
93          insertStatement = connection.prepareStatement(getInsertSQL());
94        }
95        subAppend(eventObject, connection, insertStatement);
96  
97        // we no longer need the insertStatement
98        if (insertStatement != null) {
99          insertStatement.close();
100         insertStatement = null;
101       }
102       connection.commit();
103     } catch (Throwable sqle) {
104       addError("problem appending event", sqle);
105     } finally {
106       DBHelper.closeConnection(connection);
107     }
108   }
109 
110   protected abstract void subAppend(Object eventObject, Connection connection,
111       PreparedStatement statement) throws Throwable;
112 
113   protected int selectEventId(PreparedStatement insertStatement,
114       Connection connection) throws SQLException, InvocationTargetException {
115     ResultSet rs = null;
116     Statement idStatement = null;
117     boolean gotGeneratedKeys = false;
118     if (cnxSupportsGetGeneratedKeys) {
119       try {
120         rs = (ResultSet) getGeneratedKeysMethod().invoke(insertStatement,
121             (Object[]) null);
122         gotGeneratedKeys = true;
123       } catch (InvocationTargetException ex) {
124         Throwable target = ex.getTargetException();
125         if (target instanceof SQLException) {
126           throw (SQLException) target;
127         }
128         throw ex;
129       } catch (IllegalAccessException ex) {
130         addWarn(
131             "IllegalAccessException invoking PreparedStatement.getGeneratedKeys",
132             ex);
133       }
134     }
135 
136     if (!gotGeneratedKeys) {
137       insertStatement.close();
138       insertStatement = null;
139 
140       idStatement = connection.createStatement();
141       idStatement.setMaxRows(1);
142       rs = idStatement.executeQuery(sqlDialect.getSelectInsertId());
143     }
144 
145     // A ResultSet cursor is initially positioned before the first row;
146     // the first call to the method next makes the first row the current row
147     rs.next();
148     int eventId = rs.getInt(1);
149 
150     rs.close();
151 
152     if (idStatement != null) {
153       idStatement.close();
154       idStatement = null;
155     }
156 
157     return eventId;
158   }
159 
160   @Override
161   public void stop() {
162     super.stop();
163   }
164 }