读书人

让Log4j支持数据源-国外好手的封装

发布时间: 2013-02-24 17:58:56 作者: rapoo

让Log4j支持数据源--国外高手的封装

package nl.iprofs.blogs.log4j.databaselogging; import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import java.util.ArrayList;import java.util.regex.Matcher;import java.util.regex.Pattern;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import javax.sql.DataSource;import org.apache.log4j.jdbc.JDBCAppender;import org.apache.log4j.spi.ErrorCode; /** * Extension of the log4j {@link JDBCAppender} to allow using a JNDI data source * rather than a direct connection. * * <p> * Example configuration: * <pre> *   <appender name="database" value="java:comp/jdbc/datasource" /> *     <layout value="INSERT INTO logging (timestamp, level, location, message) VALUES ('%d{yyyy-MM-dd HH:mm:ss.sss}','%p','%c{1}','%m')" /> *     </layout> *   </appender> * </pre> * * @author Bart Bakker */public class JndiCapableJdbcAppender extends JDBCAppender {     private static final Pattern SQL_VALUE_PATTERN = Pattern.compile("'(.*?)'(?=\\s*[,)])", Pattern.MULTILINE);    private String jndiDataSource;     /** {@inheritDoc} */    @Override    protected Connection getConnection() throws SQLException {        if (jndiDataSource == null) {            return super.getConnection();        } else {            return lookupDataSource().getConnection();        }    }     /**     * Looks up the datasource in the naming context specified by the     * {@link #jndiDataSource}.     *     * @return the datasource.     */    private DataSource lookupDataSource() {        try {            Context context = new InitialContext();            return (DataSource) context.lookup(jndiDataSource);        } catch (NamingException e) {            throw new RuntimeException("Cannot find JNDI DataSource: " + jndiDataSource, e);        }    }     /** {@inheritDoc} */    @Override    protected void closeConnection(Connection con) {        try {            con.close();        } catch (SQLException e) {            errorHandler.error("Failed to close connection", e, ErrorCode.CLOSE_FAILURE);        }    }     /**     * Executes the specified SQL statement, by parsing its values and turning     * them into parameters, so that characters that must be escaped in a SQL     * statement are supported.     */    @Override    protected void execute(String sql) throws SQLException {        String statement = sql;        ArrayList<String> args = new ArrayList<String>();        Matcher m = SQL_VALUE_PATTERN.matcher(sql);        while (m.find()) {            args.add(m.group(1));            statement = statement.replace(m.group(), "?");        }         executeStatement(statement, args.toArray(new String[args.size()]));    }     /**     * Executes the statement settings its parameters to the specified arguments.     *      * @param statement     *            the statement to execute.     * @param args     *            the parameter values.     */    protected void executeStatement(String statement, String[] args) throws SQLException {        Connection con = getConnection();        PreparedStatement stmt = null;        try {            stmt = con.prepareStatement(statement);            for (int i = 0; i < args.length; i++) {                stmt.setString(i + 1, args[i]);            }            stmt.executeUpdate();        } catch (SQLException e) {            if (stmt != null) {                stmt.close();            }            throw e;        }        stmt.close();        closeConnection(con);    }     public String getJndiDataSource() {        return jndiDataSource;    }     public void setJndiDataSource(String jndiDataSource) {        this.jndiDataSource = jndiDataSource;    }}

?

读书人网 >编程

热点推荐