logback-dev
Threads by month
- ----- 2025 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
September 2006
- 8 participants
- 123 discussions

svn commit: r599 - logback/trunk/logback-skin/src/main/resources/css
by noreply.seb@qos.ch 25 Sep '06
by noreply.seb@qos.ch 25 Sep '06
25 Sep '06
Author: seb
Date: Mon Sep 25 16:10:02 2006
New Revision: 599
Modified:
logback/trunk/logback-skin/src/main/resources/css/site.css
Log:
- updated source css style
Modified: logback/trunk/logback-skin/src/main/resources/css/site.css
==============================================================================
--- logback/trunk/logback-skin/src/main/resources/css/site.css (original)
+++ logback/trunk/logback-skin/src/main/resources/css/site.css Mon Sep 25 16:10:02 2006
@@ -249,7 +249,7 @@
padding-top: 0.5ex;
padding-left: 1ex;
white-space: pre;
- width: 60em;
+ width: 55em;
}
1
0

svn commit: r598 - in logback/trunk/logback-classic/src: main/java/ch/qos/logback/classic/db main/java/ch/qos/logback/classic/db/dialect test/input/db test/java/ch/qos/logback/classic/db
by noreply.seb@qos.ch 22 Sep '06
by noreply.seb@qos.ch 22 Sep '06
22 Sep '06
Author: seb
Date: Fri Sep 22 17:12:36 2006
New Revision: 598
Added:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/ConnectionSource.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/ConnectionSourceBase.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBHelper.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DataSourceConnectionSource.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DriverManagerConnectionSource.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/JNDIConnectionSource.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/DBUtil.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/HSQLDBDialect.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/MsSQLDialect.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/MySQLDialect.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/OracleDialect.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/PostgreSQLDialect.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/SQLDialect.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/db2.sql
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/db2l.sql
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/hsqldb.sql
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/mssql.sql
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/mysql.sql
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/oracle.sql
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/postgresql.sql
logback/trunk/logback-classic/src/test/input/db/
logback/trunk/logback-classic/src/test/input/db/dbAppenderUsingConnectionSource.xml
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/db/
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTest.java
Log:
Work in progress:
- added DBAppender and related classes.
- added a configuration example
- added a empty-for-now test case.
A simple logback to mysql test worked with this first version
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/ConnectionSource.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/ConnectionSource.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.qos.logback.classic.db;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import ch.qos.logback.core.spi.LifeCycle;
+
+
+/**
+ * The <id>ConnectionSource</id> interface provides a pluggable means of
+ * transparently obtaining JDBC {@link java.sql.Connection}s for log4j classes
+ * that require the use of a {@link java.sql.Connection}.
+ *
+ * @author <a href="mailto:rdecampo@twcny.rr.com">Ray DeCampo</a>
+ */
+public interface ConnectionSource extends LifeCycle {
+
+ final int UNKNOWN_DIALECT = 0;
+ final int POSTGRES_DIALECT = 1;
+ final int MYSQL_DIALECT = 2;
+ final int ORACLE_DIALECT = 3;
+ final int MSSQL_DIALECT = 4;
+ final int HSQL_DIALECT = 5;
+ /**
+ * Obtain a {@link java.sql.Connection} for use. The client is
+ * responsible for closing the {@link java.sql.Connection} when it is no
+ * longer required.
+ *
+ * @throws SQLException if a {@link java.sql.Connection} could not be
+ * obtained
+ */
+ Connection getConnection() throws SQLException;
+
+ /**
+ * Get the SQL dialect that should be used for this connection. Note that the
+ * dialect is not needed if the JDBC driver supports the getGeneratedKeys
+ * method.
+ */
+ int getSQLDialectCode();
+
+ /**
+ * If the connection supports the JDBC 3.0 getGeneratedKeys method, then
+ * we do not need any specific dialect support.
+ */
+ boolean supportsGetGeneratedKeys();
+
+ /**
+ * If the connection does not support batch updates, we will avoid using them.
+ */
+ public boolean supportsBatchUpdates();
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/ConnectionSourceBase.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/ConnectionSourceBase.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,126 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.qos.logback.classic.db;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+import ch.qos.logback.classic.db.dialect.DBUtil;
+import ch.qos.logback.core.spi.ContextAwareBase;
+
+
+/**
+ * @author Ceki Gülcü
+ */
+public abstract class ConnectionSourceBase extends ContextAwareBase implements ConnectionSource {
+
+ private boolean started;
+
+ private String user = null;
+ private String password = null;
+
+ // initially we have an unkonw dialect
+ private int dialectCode = UNKNOWN_DIALECT;
+ private boolean supportsGetGeneratedKeys = false;
+ private boolean supportsBatchUpdates = false;
+
+
+ /**
+ * Learn relevant information about this connection source.
+ *
+ */
+ public void discoverConnnectionProperties() {
+ try {
+ Connection connection = getConnection();
+ if (connection == null) {
+ addWarn("Could not get a conneciton");
+ return;
+ }
+ DatabaseMetaData meta = connection.getMetaData();
+ DBUtil util = new DBUtil();
+ util.setContext(getContext());
+ supportsGetGeneratedKeys = util.supportsGetGeneratedKeys(meta);
+ supportsBatchUpdates = util.supportsBatchUpdates(meta);
+ dialectCode = DBUtil.discoverSQLDialect(meta);
+ } catch (SQLException se) {
+ addWarn("Could not discover the dialect to use.", se);
+ }
+ }
+
+ /**
+ * Does this connection support the JDBC Connection.getGeneratedKeys method?
+ */
+ public final boolean supportsGetGeneratedKeys() {
+ return supportsGetGeneratedKeys;
+ }
+
+ public final int getSQLDialectCode() {
+ return dialectCode;
+ }
+
+ /**
+ * Get the password for this connection source.
+ */
+ public final String getPassword() {
+ return password;
+ }
+
+ /**
+ * Sets the password.
+ * @param password The password to set
+ */
+ public final void setPassword(final String password) {
+ this.password = password;
+ }
+
+ /**
+ * Get the user for this connection source.
+ */
+ public final String getUser() {
+ return user;
+ }
+
+ /**
+ * Sets the username.
+ * @param username The username to set
+ */
+ public final void setUser(final String username) {
+ this.user = username;
+ }
+
+ /**
+ * Does this connection support batch updates?
+ */
+ public final boolean supportsBatchUpdates() {
+ return supportsBatchUpdates;
+ }
+
+ public boolean isStarted() {
+ return started;
+ }
+
+ public void start() {
+ started = true;
+ }
+
+ public void stop() {
+ started = false;
+ }
+
+
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,394 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.classic.db;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import ch.qos.logback.classic.db.dialect.DBUtil;
+import ch.qos.logback.classic.db.dialect.SQLDialect;
+import ch.qos.logback.classic.spi.CallerData;
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.classic.spi.ThrowableInformation;
+import ch.qos.logback.core.AppenderBase;
+import ch.qos.logback.core.Layout;
+
+/**
+ * The DBAppender inserts loggin events into three database tables in a format
+ * independent of the Java programming language. The three tables that
+ * DBAppender inserts to must exists before DBAppender can be used. These tables
+ * may be created with the help of SQL scripts found in the
+ * <em>src/main/java/ch/qos/logback/classic/db/dialect</em> directory. There
+ * is a specific script for each of the most popular database systems. If the
+ * script for your particular type of database system is missing, it should be
+ * quite easy to write one, taking example on the already existing scripts. If
+ * you send them to us, we will gladly include missing scripts in future
+ * releases.
+ *
+ * <p>
+ * If the JDBC driver you are using supports the
+ * {@link java.sql.Statement#getGeneratedKeys}method introduced in JDBC 3.0
+ * specification, then you are all set. Otherwise, there must be an
+ * {@link SQLDialect}appropriate for your database system. Currently, we have
+ * dialects for PostgreSQL, MySQL, Oracle and MsSQL. As mentioed previously, an
+ * SQLDialect is required only if the JDBC driver for your database system does
+ * not support the {@link java.sql.Statement#getGeneratedKeys getGeneratedKeys}
+ * method.
+ * </p>
+ *
+ * <table border="1" cellpadding="4">
+ * <tr>
+ * <th>RDBMS</th>
+ * <th>supports <br/><code>getGeneratedKeys()</code> method</th>
+ * <th>specific <br/>SQLDialect support</th>
+ * <tr>
+ * <tr>
+ * <td>PostgreSQL</td>
+ * <td align="center">NO</td>
+ * <td>present and used</td>
+ * <tr>
+ * <tr>
+ * <td>MySQL</td>
+ * <td align="center">YES</td>
+ * <td>present, but not actually needed or used</td>
+ * <tr>
+ * <tr>
+ * <td>Oracle</td>
+ * <td align="center">YES</td>
+ * <td>present, but not actually needed or used</td>
+ * <tr>
+ * <tr>
+ * <td>DB2</td>
+ * <td align="center">YES</td>
+ * <td>not present, and not needed or used</td>
+ * <tr>
+ * <tr>
+ * <td>MsSQL</td>
+ * <td align="center">YES</td>
+ * <td>not present, and not needed or used</td>
+ * <tr>
+ * <tr>
+ * <td>HSQL</td>
+ * <td align="center">NO</td>
+ * <td>present and used</td>
+ * <tr>
+ *
+ * </table>
+ * <p>
+ * <b>Performance: </b> Experiments show that writing a single event into the
+ * database takes approximately 50 milliseconds, on a "standard" PC. If pooled
+ * connections are used, this figure drops to under 10 milliseconds. Note that
+ * most JDBC drivers already ship with connection pooling support.
+ * </p>
+ *
+ *
+ *
+ * <p>
+ * <b>Configuration </b> DBAppender can be configured programmatically, or using
+ * {@link ch.qos.logback.classic.joran.JoranConfigurator JoranConfigurator}.
+ * Example scripts can be found in the <em>tests/input/db</em> directory.
+ *
+ * @author Ceki Gülcü
+ * @author Ray DeCampo
+ * @author Sébastien Pennec
+ */
+public class DBAppender extends AppenderBase {
+ static final String insertPropertiesSQL = "INSERT INTO logging_event_property (event_id, mapped_key, mapped_value) VALUES (?, ?, ?)";
+ static final String insertExceptionSQL = "INSERT INTO logging_event_exception (event_id, i, trace_line) VALUES (?, ?, ?)";
+ static final String insertSQL;
+ private static final Method GET_GENERATED_KEYS_METHOD;
+
+ static {
+ StringBuffer sql = new StringBuffer();
+ sql.append("INSERT INTO logging_event (");
+ sql.append("timestmp, ");
+ sql.append("formatted_message, ");
+ sql.append("logger_name, ");
+ sql.append("level_string, ");
+ sql.append("thread_name, ");
+ sql.append("reference_flag, ");
+ sql.append("caller_filename, ");
+ sql.append("caller_class, ");
+ sql.append("caller_method, ");
+ sql.append("caller_line) ");
+ sql.append(" VALUES (?, ?, ? ,?, ?, ?, ?, ?, ?,?)");
+ insertSQL = sql.toString();
+ //
+ // PreparedStatement.getGeneratedKeys added in JDK 1.4
+ //
+ Method getGeneratedKeysMethod;
+ try {
+ getGeneratedKeysMethod = PreparedStatement.class.getMethod(
+ "getGeneratedKeys", (Class[]) null);
+ } catch (Exception ex) {
+ getGeneratedKeysMethod = null;
+ }
+ GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
+ }
+
+ ConnectionSource connectionSource;
+ boolean cnxSupportsGetGeneratedKeys = false;
+ boolean cnxSupportsBatchUpdates = false;
+ SQLDialect sqlDialect;
+ boolean locationInfo = false;
+
+ public DBAppender() {
+ }
+
+ @Override
+ public void start() {
+
+ if (connectionSource == null) {
+ throw new IllegalStateException(
+ "DBAppender cannot function without a connection source");
+ }
+
+ sqlDialect = DBUtil
+ .getDialectFromCode(connectionSource.getSQLDialectCode());
+ if (GET_GENERATED_KEYS_METHOD != null) {
+ cnxSupportsGetGeneratedKeys = connectionSource.supportsGetGeneratedKeys();
+ } else {
+ cnxSupportsGetGeneratedKeys = false;
+ }
+ cnxSupportsBatchUpdates = connectionSource.supportsBatchUpdates();
+ if (!cnxSupportsGetGeneratedKeys && (sqlDialect == null)) {
+ throw new IllegalStateException(
+ "DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method *and* without a specific SQL dialect");
+ }
+
+ // all nice and dandy on the eastern front
+ super.start();
+ }
+
+ /**
+ * @return Returns the connectionSource.
+ */
+ public ConnectionSource getConnectionSource() {
+ return connectionSource;
+ }
+
+ /**
+ * @param connectionSource
+ * The connectionSource to set.
+ */
+ public void setConnectionSource(ConnectionSource connectionSource) {
+ this.connectionSource = connectionSource;
+ }
+
+ @Override
+ protected void append(Object eventObject) {
+ LoggingEvent event = (LoggingEvent) eventObject;
+ Connection connection = null;
+ try {
+ connection = connectionSource.getConnection();
+ connection.setAutoCommit(false);
+
+ PreparedStatement insertStatement = connection
+ .prepareStatement(insertSQL);
+
+ addLoggingEvent(insertStatement, event);
+ // This is very expensive... should we do it every time?
+ addCallerData(insertStatement, event.getCallerData());
+
+ int updateCount = insertStatement.executeUpdate();
+ if (updateCount != 1) {
+ addWarn("Failed to insert loggingEvent");
+ }
+
+ int eventId = getEventId(insertStatement, connection);
+
+ // we no longer need the insertStatement
+ if (insertStatement != null) {
+ insertStatement.close();
+ insertStatement = null;
+ }
+
+ Map<String, String> mergedMap = mergePropertyMaps(event);
+ insertProperties(mergedMap, connection, eventId);
+
+ insertThrowable(event.getThrowableInformation(), connection, eventId);
+
+ connection.commit();
+ } catch (Throwable sqle) {
+ addError("problem appending event", sqle);
+ } finally {
+ DBHelper.closeConnection(connection);
+ }
+ }
+
+ void addLoggingEvent(PreparedStatement stmt, LoggingEvent event)
+ throws SQLException {
+ stmt.setLong(1, event.getTimeStamp());
+ stmt.setString(2, event.getFormattedMessage());
+ stmt.setString(3, event.getLoggerRemoteView().getName());
+ stmt.setString(4, event.getLevel().toString());
+ stmt.setString(5, event.getThreadName());
+ stmt.setShort(6, DBHelper.computeReferenceMask(event));
+ }
+
+ void addCallerData(PreparedStatement stmt, CallerData[] callerDataArray)
+ throws SQLException {
+ CallerData callerData = callerDataArray[0];
+ if (callerData != null) {
+ stmt.setString(7, callerData.getFileName());
+ stmt.setString(8, callerData.getClassName());
+ stmt.setString(9, callerData.getMethodName());
+ stmt.setString(10, Integer.toString(callerData.getLineNumber()));
+ }
+ }
+
+ int getEventId(PreparedStatement insertStatement, Connection connection)
+ throws SQLException, InvocationTargetException {
+ ResultSet rs = null;
+ Statement idStatement = null;
+ boolean gotGeneratedKeys = false;
+ if (cnxSupportsGetGeneratedKeys) {
+ try {
+ rs = (ResultSet) GET_GENERATED_KEYS_METHOD.invoke(insertStatement,
+ (Object[]) null);
+ gotGeneratedKeys = true;
+ } catch (InvocationTargetException ex) {
+ Throwable target = ex.getTargetException();
+ if (target instanceof SQLException) {
+ throw (SQLException) target;
+ }
+ throw ex;
+ } catch (IllegalAccessException ex) {
+ addWarn(
+ "IllegalAccessException invoking PreparedStatement.getGeneratedKeys",
+ ex);
+ }
+ }
+
+ if (!gotGeneratedKeys) {
+ insertStatement.close();
+ insertStatement = null;
+
+ idStatement = connection.createStatement();
+ idStatement.setMaxRows(1);
+ rs = idStatement.executeQuery(sqlDialect.getSelectInsertId());
+ }
+
+ // A ResultSet cursor is initially positioned before the first row;
+ // the
+ // first call to the method next makes the first row the current row
+ rs.next();
+ int eventId = rs.getInt(1);
+
+ rs.close();
+
+ if (idStatement != null) {
+ idStatement.close();
+ idStatement = null;
+ }
+
+ return eventId;
+ }
+
+ Map<String, String> mergePropertyMaps(LoggingEvent event) {
+ Map<String, String> mergedMap = new HashMap<String, String>();
+ // we add the context properties first, then the event properties, since
+ // we consider that event-specific properties should have priority over
+ // context-wide
+ // properties.
+ Map<String, String> loggerContextMap = event.getLoggerRemoteView()
+ .getLoggerContextView().getPropertyMap();
+ Map<String, String> mdcMap = event.getMDCPropertyMap();
+ if (loggerContextMap != null) {
+ mergedMap.putAll(loggerContextMap);
+ }
+ if (mdcMap != null) {
+ mergedMap.putAll(mdcMap);
+ }
+
+ return mergedMap;
+ }
+
+ void insertProperties(Map<String, String> mergedMap, Connection connection,
+ int eventId) throws SQLException {
+ Set propertiesKeys = mergedMap.keySet();
+ if (propertiesKeys.size() > 0) {
+ PreparedStatement insertPropertiesStatement = connection
+ .prepareStatement(insertPropertiesSQL);
+
+ for (Iterator i = propertiesKeys.iterator(); i.hasNext();) {
+ String key = (String) i.next();
+ String value = (String) mergedMap.get(key);
+
+ insertPropertiesStatement.setInt(1, eventId);
+ insertPropertiesStatement.setString(2, key);
+ insertPropertiesStatement.setString(3, value);
+
+ if (cnxSupportsBatchUpdates) {
+ insertPropertiesStatement.addBatch();
+ } else {
+ insertPropertiesStatement.execute();
+ }
+ }
+
+ if (cnxSupportsBatchUpdates) {
+ insertPropertiesStatement.executeBatch();
+ }
+
+ insertPropertiesStatement.close();
+ insertPropertiesStatement = null;
+ }
+ }
+
+ void insertThrowable(ThrowableInformation ti, Connection connection,
+ int eventId) throws SQLException {
+ String[] strRep = null;
+ if (ti != null) {
+ strRep = ti.getThrowableStrRep();
+
+ PreparedStatement insertExceptionStatement = connection
+ .prepareStatement(insertExceptionSQL);
+
+ for (short i = 0; i < strRep.length; i++) {
+ insertExceptionStatement.setInt(1, eventId);
+ insertExceptionStatement.setShort(2, i);
+ insertExceptionStatement.setString(3, strRep[i]);
+ if (cnxSupportsBatchUpdates) {
+ insertExceptionStatement.addBatch();
+ } else {
+ insertExceptionStatement.execute();
+ }
+ }
+ if (cnxSupportsBatchUpdates) {
+ insertExceptionStatement.executeBatch();
+ }
+ insertExceptionStatement.close();
+ insertExceptionStatement = null;
+ }
+ }
+
+ @Override
+ public void stop() {
+ super.stop();
+ }
+
+ public Layout getLayout() {
+ return null;
+ }
+
+ public void setLayout(Layout layout) {
+ }
+
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBHelper.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBHelper.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,72 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.classic.db;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+
+/**
+ * @author Ceki Gülcü
+ *
+ */
+public class DBHelper {
+
+ public static short PROPERTIES_EXIST = 0x01;
+ public static short EXCEPTION_EXISTS = 0x02;
+
+ public static short computeReferenceMask(LoggingEvent event) {
+ short mask = 0;
+
+ int mdcPropSize = 0;
+ if (event.getMDCPropertyMap() != null) {
+ mdcPropSize = event.getMDCPropertyMap().keySet().size();
+ }
+ int contextPropSize = 0;
+ if (event.getLoggerRemoteView().getLoggerContextView().getPropertyMap() != null) {
+ contextPropSize = event.getLoggerRemoteView().getLoggerContextView()
+ .getPropertyMap().size();
+ }
+
+ if (mdcPropSize > 0 || contextPropSize > 0) {
+ mask = PROPERTIES_EXIST;
+ }
+ if (event.getThrowableInformation() != null) {
+ String[] strRep = event.getThrowableInformation().getThrowableStrRep();
+ if (strRep != null) {
+ mask |= EXCEPTION_EXISTS;
+ }
+ }
+ return mask;
+ }
+
+ static public void closeConnection(Connection connection) {
+ if (connection != null) {
+ try {
+ connection.close();
+ } catch (SQLException sqle) {
+ // static utility classes should not log without an explicit repository
+ // reference
+ }
+ }
+ }
+
+ public static void closeStatement(Statement statement) {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (SQLException sqle) {
+ }
+ }
+ }
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DataSourceConnectionSource.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DataSourceConnectionSource.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,78 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.classic.db;
+
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
+
+/**
+ * The DataSourceConnectionSource is an implementation of {@link ConnectionSource}
+ * that obtains the Connection in the recommended JDBC manner based on
+ * a {@link javax.sql.DataSource DataSource}.
+ * <p>
+ *
+ * @author Ray DeCampo
+ * @author Ceki Gülcü
+ */
+public class DataSourceConnectionSource extends ConnectionSourceBase {
+
+ private DataSource dataSource;
+
+ @Override
+ public void start() {
+ //LogLog.debug("**********DataSourceConnectionSource.activateOptions called");
+ if (dataSource == null) {
+ addWarn("WARNING: No data source specified");
+ } else {
+ Connection connection = null;
+ try {
+ connection = getConnection();
+ } catch(SQLException se) {
+ addWarn("Could not get a connection to discover the dialect to use.", se);
+ }
+ if(connection != null) {
+ discoverConnnectionProperties();
+ }
+ if(!supportsGetGeneratedKeys() && getSQLDialectCode() == ConnectionSource.UNKNOWN_DIALECT) {
+ addWarn("Connection does not support GetGeneratedKey method and could not discover the dialect.");
+ }
+ }
+ super.start();
+ }
+
+ /**
+ * @see org.apache.log4j.db.ConnectionSource#getConnection()
+ */
+ public Connection getConnection() throws SQLException {
+ if (dataSource == null) {
+ addError("WARNING: No data source specified");
+ return null;
+ }
+
+ if (getUser() == null) {
+ return dataSource.getConnection();
+ } else {
+ return dataSource.getConnection(getUser(), getPassword());
+ }
+ }
+
+ public DataSource getDataSource() {
+ return dataSource;
+ }
+
+ public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DriverManagerConnectionSource.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DriverManagerConnectionSource.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,129 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.classic.db;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * The DriverManagerConnectionSource is an implementation of
+ * {@link ConnectionSource} that obtains the Connection in the traditional JDBC
+ * manner based on the connection URL.
+ * <p>
+ * Note that this class will establish a new Connection for each call to
+ * {@link #getConnection()}. It is recommended that you either use a JDBC
+ * driver that natively supported Connection pooling or that you create your own
+ * implementation of {@link ConnectionSource} that taps into whatever pooling
+ * mechanism you are already using. (If you have access to a JNDI implementation
+ * that supports {@link javax.sql.DataSource}s, e.g. within a J2EE application
+ * server, see {@link JNDIConnectionSource}). See <a href="#dbcp">below</a>
+ * for a configuration example that uses the <a
+ * href="http://jakarta.apache.org/commons/dbcp/index.html">commons-dbcp</a>
+ * package from Apache.
+ * <p>
+ * Sample configuration:<br>
+ *
+ * <pre>
+ * <connectionSource class="org.apache.log4j.jdbc.DriverManagerConnectionSource">
+ * <param name="driver" value="com.mysql.jdbc.Driver" />
+ * <param name="url" value="jdbc:mysql://localhost:3306/mydb" />
+ * <param name="username" value="myUser" />
+ * <param name="password" value="myPassword" />
+ * </connectionSource>
+ * </pre>
+ *
+ * <p>
+ * <a name="dbcp">If</a> you do not have another connection pooling mechanism
+ * built into your application, you can use the <a
+ * href="http://jakarta.apache.org/commons/dbcp/index.html">commons-dbcp</a>
+ * package from Apache:<br>
+ *
+ * <pre>
+ * <connectionSource class="org.apache.log4j.jdbc.DriverManagerConnectionSource">
+ * <param name="driver" value="org.apache.commons.dbcp.PoolingDriver" />
+ * <param name="url" value="jdbc:apache:commons:dbcp:/myPoolingDriver" />
+ * </connectionSource>
+ * </pre>
+ *
+ * Then the configuration information for the commons-dbcp package goes into the
+ * file myPoolingDriver.jocl and is placed in the classpath. See the <a
+ * href="http://jakarta.apache.org/commons/dbcp/index.html">commons-dbcp</a>
+ * documentation for details.
+ *
+ * @author <a href="mailto:rdecampo@twcny.rr.com">Ray DeCampo</a>
+ */
+public class DriverManagerConnectionSource extends ConnectionSourceBase {
+ private String driverClass = null;
+ private String url = null;
+
+ public void start() {
+ try {
+ if (driverClass != null) {
+ Class.forName(driverClass);
+ discoverConnnectionProperties();
+ } else {
+ addError("WARNING: No JDBC driver specified for log4j DriverManagerConnectionSource.");
+ }
+ } catch (final ClassNotFoundException cnfe) {
+ addError("Could not load JDBC driver class: " + driverClass, cnfe);
+ }
+ }
+
+ /**
+ * @see org.apache.log4j.db.ConnectionSource#getConnection()
+ */
+ public Connection getConnection() throws SQLException {
+ if (getUser() == null) {
+ return DriverManager.getConnection(url);
+ } else {
+ return DriverManager.getConnection(url, getUser(), getPassword());
+ }
+ }
+
+ /**
+ * Returns the url.
+ *
+ * @return String
+ */
+ public String getUrl() {
+ return url;
+ }
+
+ /**
+ * Sets the url.
+ *
+ * @param url
+ * The url to set
+ */
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ /**
+ * Returns the name of the driver class.
+ *
+ * @return String
+ */
+ public String getDriverClass() {
+ return driverClass;
+ }
+
+ /**
+ * Sets the driver class.
+ *
+ * @param driverClass
+ * The driver class to set
+ */
+ public void setDriverClass(String driverClass) {
+ this.driverClass = driverClass;
+ }
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/JNDIConnectionSource.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/JNDIConnectionSource.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,140 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.db;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+// PortableRemoteObject was introduced in JDK 1.3. We won't use it.
+// import javax.rmi.PortableRemoteObject;
+import javax.sql.DataSource;
+
+/**
+ * The <id>JNDIConnectionSource</id> is an implementation of
+ * {@link ConnectionSource} that obtains a {@link javax.sql.DataSource} from a
+ * JNDI provider and uses it to obtain a {@link java.sql.Connection}. It is
+ * primarily designed to be used inside of J2EE application servers or
+ * application server clients, assuming the application server supports remote
+ * access of {@link javax.sql.DataSource}s. In this way one can take advantage
+ * of connection pooling and whatever other goodies the application server
+ * provides.
+ * <p>
+ * Sample configuration:<br>
+ *
+ * <pre>
+ * <connectionSource class="org.apache.log4j.jdbc.JNDIConnectionSource">
+ * <param name="jndiLocation" value="jdbc/MySQLDS" />
+ * </connectionSource>
+ * </pre>
+ *
+ * <p>
+ * Sample configuration (with username and password):<br>
+ *
+ * <pre>
+ * <connectionSource class="org.apache.log4j.jdbc.JNDIConnectionSource">
+ * <param name="jndiLocation" value="jdbc/MySQLDS" />
+ * <param name="username" value="myUser" />
+ * <param name="password" value="myPassword" />
+ * </connectionSource>
+ * </pre>
+ *
+ * <p>
+ * Note that this class will obtain an {@link javax.naming.InitialContext} using
+ * the no-argument constructor. This will usually work when executing within a
+ * J2EE environment. When outside the J2EE environment, make sure that you
+ * provide a jndi.properties file as described by your JNDI provider's
+ * documentation.
+ *
+ * @author <a href="mailto:rdecampo@twcny.rr.com">Ray DeCampo</a>
+ */
+public class JNDIConnectionSource extends ConnectionSourceBase {
+ private String jndiLocation = null;
+ private DataSource dataSource = null;
+
+ /**
+ * @see org.apache.log4j.spi.OptionHandler#activateOptions()
+ */
+ public void start() {
+ if (jndiLocation == null) {
+ addError("No JNDI location specified for JNDIConnectionSource.");
+ }
+
+ discoverConnnectionProperties();
+
+ }
+
+ /**
+ * @see org.apache.log4j.db.ConnectionSource#getConnection()
+ */
+ public Connection getConnection() throws SQLException {
+ Connection conn = null;
+ try {
+
+ if (dataSource == null) {
+ dataSource = lookupDataSource();
+ }
+ if (getUser() == null) {
+ conn = dataSource.getConnection();
+ } else {
+ conn = dataSource.getConnection(getUser(), getPassword());
+ }
+ } catch (final NamingException ne) {
+ addError("Error while getting data source", ne);
+ throw new SQLException("NamingException while looking up DataSource: "
+ + ne.getMessage());
+ } catch (final ClassCastException cce) {
+ addError("ClassCastException while looking up DataSource.", cce);
+ throw new SQLException("ClassCastException while looking up DataSource: "
+ + cce.getMessage());
+ }
+
+ return conn;
+ }
+
+ /**
+ * Returns the jndiLocation.
+ *
+ * @return String
+ */
+ public String getJndiLocation() {
+ return jndiLocation;
+ }
+
+ /**
+ * Sets the jndiLocation.
+ *
+ * @param jndiLocation
+ * The jndiLocation to set
+ */
+ public void setJndiLocation(String jndiLocation) {
+ this.jndiLocation = jndiLocation;
+ }
+
+ private DataSource lookupDataSource() throws NamingException, SQLException {
+ DataSource ds;
+ Context ctx = new InitialContext();
+ Object obj = ctx.lookup(jndiLocation);
+
+ // PortableRemoteObject was introduced in JDK 1.3. We won't use it.
+ // ds = (DataSource)PortableRemoteObject.narrow(obj, DataSource.class);
+ ds = (DataSource) obj;
+
+ if (ds == null) {
+ throw new SQLException("Failed to obtain data source from JNDI location "
+ + jndiLocation);
+ } else {
+ return ds;
+ }
+ }
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/DBUtil.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/DBUtil.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,125 @@
+/*
+ * Copyright 1999,2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.qos.logback.classic.db.dialect;
+
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+import ch.qos.logback.classic.db.ConnectionSource;
+import ch.qos.logback.core.spi.ContextAwareBase;
+
+/**
+ *
+ * @author Ceki Gulcu
+ *
+ */
+public class DBUtil extends ContextAwareBase {
+ private static final String POSTGRES_PART = "postgresql";
+ private static final String MYSQL_PART = "mysql";
+ private static final String ORACLE_PART = "oracle";
+ // private static final String MSSQL_PART = "mssqlserver4";
+ private static final String MSSQL_PART = "microsoft";
+ private static final String HSQL_PART = "hsql";
+
+ public static int discoverSQLDialect(DatabaseMetaData meta) {
+ int dialectCode = 0;
+
+ try {
+
+ String dbName = meta.getDatabaseProductName().toLowerCase();
+
+ if (dbName.indexOf(POSTGRES_PART) != -1) {
+ return ConnectionSource.POSTGRES_DIALECT;
+ } else if (dbName.indexOf(MYSQL_PART) != -1) {
+ return ConnectionSource.MYSQL_DIALECT;
+ } else if (dbName.indexOf(ORACLE_PART) != -1) {
+ return ConnectionSource.ORACLE_DIALECT;
+ } else if (dbName.indexOf(MSSQL_PART) != -1) {
+ return ConnectionSource.MSSQL_DIALECT;
+ } else if (dbName.indexOf(HSQL_PART) != -1) {
+ return ConnectionSource.HSQL_DIALECT;
+ } else {
+ return ConnectionSource.UNKNOWN_DIALECT;
+ }
+ } catch (SQLException sqle) {
+ // we can't do much here
+ }
+
+ return dialectCode;
+ }
+
+ public static SQLDialect getDialectFromCode(int dialectCode) {
+ SQLDialect sqlDialect = null;
+
+ switch (dialectCode) {
+ case ConnectionSource.POSTGRES_DIALECT:
+ sqlDialect = new PostgreSQLDialect();
+
+ break;
+ case ConnectionSource.MYSQL_DIALECT:
+ sqlDialect = new MySQLDialect();
+
+ break;
+ case ConnectionSource.ORACLE_DIALECT:
+ sqlDialect = new OracleDialect();
+
+ break;
+ case ConnectionSource.MSSQL_DIALECT:
+ sqlDialect = new MsSQLDialect();
+
+ break;
+ case ConnectionSource.HSQL_DIALECT:
+ sqlDialect = new HSQLDBDialect();
+
+ break;
+ }
+ return sqlDialect;
+ }
+
+ /**
+ * This method handles cases where the
+ * {@link DatabaseMetaData#supportsGetGeneratedKeys} method is missing in the
+ * JDBC driver implementation.
+ */
+ public boolean supportsGetGeneratedKeys(DatabaseMetaData meta) {
+ try {
+ //
+ // invoking JDK 1.4 method by reflection
+ //
+ return ((Boolean) DatabaseMetaData.class.getMethod(
+ "supportsGetGeneratedKeys", (Class[]) null).invoke(meta,
+ (Object[]) null)).booleanValue();
+ } catch (Throwable e) {
+ addInfo("Could not call supportsGetGeneratedKeys method. This may be recoverable");
+ return false;
+ }
+ }
+
+ /**
+ * This method handles cases where the
+ * {@link DatabaseMetaData#supportsBatchUpdates} method is missing in the JDBC
+ * driver implementation.
+ */
+ public boolean supportsBatchUpdates(DatabaseMetaData meta) {
+ try {
+ return meta.supportsBatchUpdates();
+ } catch (Throwable e) {
+ addInfo("Missing DatabaseMetaData.supportsBatchUpdates method.");
+ return false;
+ }
+ }
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/HSQLDBDialect.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/HSQLDBDialect.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,23 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.db.dialect;
+
+/**
+ * The HSQLDB dialect.
+ *
+ * @author <a href="http://www.qos.ch/log4j/">Ceki Gülcü</a>
+*/
+public class HSQLDBDialect implements SQLDialect {
+ public static final String SELECT_CURRVAL = "CALL IDENTITY()";
+
+ public String getSelectInsertId() {
+ return SELECT_CURRVAL;
+ }
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/MsSQLDialect.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/MsSQLDialect.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,27 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.classic.db.dialect;
+
+/**
+* The MS SQL Server dialect is untested.
+*
+* Note that the dialect is not needed if your JDBC driver supports
+* the getGeneratedKeys method introduced in JDBC 3.0 specification.
+*
+* @author James Stauffer
+*/
+public class MsSQLDialect implements SQLDialect {
+ public static final String SELECT_CURRVAL = "SELECT @@identity id";
+
+ public String getSelectInsertId() {
+ return SELECT_CURRVAL;
+ }
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/MySQLDialect.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/MySQLDialect.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,24 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.db.dialect;
+
+/**
+ *
+ *
+ * @author Ceki
+ *
+ */
+public class MySQLDialect implements SQLDialect {
+ public static final String SELECT_LAST_INSERT_ID = "SELECT LAST_INSERT_ID()";
+
+ public String getSelectInsertId() {
+ return SELECT_LAST_INSERT_ID;
+ }
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/OracleDialect.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/OracleDialect.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,26 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.classic.db.dialect;
+
+/**
+ * The Oracle dialect. Tested successfully on Oracle9i Release 9.2.0.3.0 by
+ * James Stauffer.
+ *
+ * @author Ceki Gülcü
+ */
+public class OracleDialect implements SQLDialect {
+ public static final String SELECT_CURRVAL = "SELECT logging_event_id_seq.currval from dual";
+
+ public String getSelectInsertId() {
+ return SELECT_CURRVAL;
+ }
+
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/PostgreSQLDialect.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/PostgreSQLDialect.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,28 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.classic.db.dialect;
+
+
+/**
+ *
+ * @author ceki
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class PostgreSQLDialect
+ implements SQLDialect {
+ public static final String SELECT_CURRVAL = "SELECT currval('logging_event_id_seq')";
+
+ public String getSelectInsertId() {
+ return SELECT_CURRVAL;
+ }
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/SQLDialect.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/SQLDialect.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,20 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.db.dialect;
+
+/**
+ * @author ceki
+ *
+ */
+public interface SQLDialect {
+
+ public String getSelectInsertId();
+
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/db2.sql
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/db2.sql Fri Sep 22 17:12:36 2006
@@ -0,0 +1,49 @@
+# This SQL script creates the required tables by org.apache.log4j.db.DBAppender and
+# org.apache.log4j.db.DBReceiver.
+#
+# It is intended for IBM DB2 databases.
+#
+# WARNING WARNING WARNING WARNING
+# =================================
+# This SQL script has not been tested on an actual DB2
+# instance. It may contain errors or even invalid SQL
+# statements.
+
+DROP TABLE logging_event_property;
+DROP TABLE logging_event_exception;
+DROP TABLE logging_event;
+
+CREATE TABLE logging_event
+ (
+ sequence_number BIGINT NOT NULL,
+ timestamp BIGINT NOT NULL,
+ rendered_message VARCHAR(4000) NOT NULL,
+ logger_name VARCHAR(254) NOT NULL,
+ level_string VARCHAR(254) NOT NULL,
+ ndc VARCHAR(4000),
+ thread_name VARCHAR(254),
+ reference_flag SMALLINT,
+ caller_filename VARCHAR(254) NOT NULL,
+ caller_class VARCHAR(254) NOT NULL,
+ caller_method VARCHAR(254) NOT NULL,
+ caller_line CHAR(4) NOT NULL,
+ event_id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1)
+ );
+
+CREATE TABLE logging_event_property
+ (
+ event_id INTEGER NOT NULL,
+ mapped_key VARCHAR(254) NOT NULL,
+ mapped_value VARCHAR(1024),
+ PRIMARY KEY(event_id, mapped_key),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
+
+CREATE TABLE logging_event_exception
+ (
+ event_id INTEGER NOT NULL,
+ i SMALLINT NOT NULL,
+ trace_line VARCHAR(254) NOT NULL,
+ PRIMARY KEY(event_id, i),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/db2l.sql
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/db2l.sql Fri Sep 22 17:12:36 2006
@@ -0,0 +1,47 @@
+# This SQL script creates the required tables by org.apache.log4j.db.DBAppender and
+# org.apache.log4j.db.DBReceiver.
+#
+# It is intended for PostgreSQL databases.
+
+DROP TABLE logging_event_property;
+DROP TABLE logging_event_exception;
+DROP TABLE logging_event;
+
+
+CREATE SEQUENCE logging_event_id_seq MINVALUE 1 START 1;
+
+
+CREATE TABLE logging_event
+ (
+ sequence_number BIGINT NOT NULL,
+ timestamp BIGINT NOT NULL,
+ rendered_message TEXT NOT NULL,
+ logger_name VARCHAR(254) NOT NULL,
+ level_string VARCHAR(254) NOT NULL,
+ ndc TEXT,
+ thread_name VARCHAR(254),
+ reference_flag SMALLINT,
+ caller_filename VARCHAR(254) NOT NULL,
+ caller_class VARCHAR(254) NOT NULL,
+ caller_method VARCHAR(254) NOT NULL,
+ caller_line CHAR(4) NOT NULL,
+ event_id INT IDENTITY GENERATED ALWAYS PRIMARY KEY
+ );
+
+CREATE TABLE logging_event_property
+ (
+ event_id INT NOT NULL,
+ mapped_key VARCHAR(254) NOT NULL,
+ mapped_value VARCHAR(1024),
+ PRIMARY KEY(event_id, mapped_key),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
+
+CREATE TABLE logging_event_exception
+ (
+ event_id INT NOT NULL,
+ i SMALLINT NOT NULL,
+ trace_line VARCHAR(254) NOT NULL,
+ PRIMARY KEY(event_id, i),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/hsqldb.sql
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/hsqldb.sql Fri Sep 22 17:12:36 2006
@@ -0,0 +1,46 @@
+// This SQL script creates the required tables by
+// org.apache.log4j.db.DBAppender and org.apache.log4j.db.DBReceiver.
+//
+// It is intended for HSQLDB.
+//
+
+DROP TABLE logging_event_exception IF EXISTS;
+DROP TABLE logging_event_property IF EXISTS;
+DROP TABLE logging_event IF EXISTS;
+
+
+CREATE TABLE logging_event
+ (
+ sequence_number BIGINT NOT NULL,
+ timestamp BIGINT NOT NULL,
+ rendered_message LONGVARCHAR NOT NULL,
+ logger_name VARCHAR NOT NULL,
+ level_string VARCHAR NOT NULL,
+ ndc LONGVARCHAR,
+ thread_name VARCHAR,
+ reference_flag SMALLINT,
+ caller_filename VARCHAR,
+ caller_class VARCHAR,
+ caller_method VARCHAR,
+ caller_line CHAR(4),
+ event_id INT NOT NULL IDENTITY
+ );
+
+
+CREATE TABLE logging_event_property
+ (
+ event_id INT NOT NULL,
+ mapped_key VARCHAR(254) NOT NULL,
+ mapped_value LONGVARCHAR,
+ PRIMARY KEY(event_id, mapped_key),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
+
+CREATE TABLE logging_event_exception
+ (
+ event_id INT NOT NULL,
+ i SMALLINT NOT NULL,
+ trace_line VARCHAR NOT NULL,
+ PRIMARY KEY(event_id, i),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/mssql.sql
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/mssql.sql Fri Sep 22 17:12:36 2006
@@ -0,0 +1,45 @@
+-- This SQL script creates the required tables by org.apache.log4j.db.DBAppender and
+-- org.apache.log4j.db.DBReceiver.
+--
+-- It is intended for MS SQL Server databases. This has been tested with version 7.0.
+
+DROP TABLE logging_event_property
+DROP TABLE logging_event_exception
+DROP TABLE logging_event
+
+CREATE TABLE logging_event
+ (
+ sequence_number DECIMAL(20) NOT NULL,
+ timestamp DECIMAL(20) NOT NULL,
+ rendered_message VARCHAR(4000) NOT NULL,
+ logger_name VARCHAR(254) NOT NULL,
+ level_string VARCHAR(254) NOT NULL,
+ ndc VARCHAR(4000),
+ thread_name VARCHAR(254),
+ reference_flag SMALLINT,
+ caller_filename VARCHAR(254) NOT NULL,
+ caller_class VARCHAR(254) NOT NULL,
+ caller_method VARCHAR(254) NOT NULL,
+ caller_line CHAR(4) NOT NULL,
+ event_id INT NOT NULL identity,
+ PRIMARY KEY(event_id)
+ )
+
+CREATE TABLE logging_event_property
+ (
+ event_id INT NOT NULL,
+ mapped_key VARCHAR(254) NOT NULL,
+ mapped_value VARCHAR(1024),
+ PRIMARY KEY(event_id, mapped_key),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ )
+
+CREATE TABLE logging_event_exception
+ (
+ event_id INT NOT NULL,
+ i SMALLINT NOT NULL,
+ trace_line VARCHAR(254) NOT NULL,
+ PRIMARY KEY(event_id, i),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ )
+
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/mysql.sql
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/mysql.sql Fri Sep 22 17:12:36 2006
@@ -0,0 +1,54 @@
+# This SQL script creates the required tables by org.apache.log4j.db.DBAppender and
+# org.apache.log4j.db.DBReceiver.
+#
+# It is intended for MySQL databases. It has been tested on MySQL 4.1.1 with
+# INNODB tables.
+
+
+BEGIN;
+DROP TABLE IF EXISTS logging_event_property;
+DROP TABLE IF EXISTS logging_event_exception;
+DROP TABLE IF EXISTS logging_event;
+COMMIT;
+
+
+BEGIN;
+CREATE TABLE logging_event
+ (
+ sequence_number BIGINT NOT NULL,
+ timestamp BIGINT NOT NULL,
+ rendered_message TEXT NOT NULL,
+ logger_name VARCHAR(254) NOT NULL,
+ level_string VARCHAR(254) NOT NULL,
+ ndc TEXT,
+ thread_name VARCHAR(254),
+ reference_flag SMALLINT,
+ caller_filename VARCHAR(254) NOT NULL,
+ caller_class VARCHAR(254) NOT NULL,
+ caller_method VARCHAR(254) NOT NULL,
+ caller_line CHAR(4) NOT NULL,
+ event_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
+ );
+COMMIT;
+
+BEGIN;
+CREATE TABLE logging_event_property
+ (
+ event_id INT NOT NULL,
+ mapped_key VARCHAR(254) NOT NULL,
+ mapped_value TEXT,
+ PRIMARY KEY(event_id, mapped_key),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
+COMMIT;
+
+BEGIN;
+CREATE TABLE logging_event_exception
+ (
+ event_id INT NOT NULL,
+ i SMALLINT NOT NULL,
+ trace_line VARCHAR(254) NOT NULL,
+ PRIMARY KEY(event_id, i),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
+COMMIT;
\ No newline at end of file
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/oracle.sql
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/oracle.sql Fri Sep 22 17:12:36 2006
@@ -0,0 +1,67 @@
+-- This SQL script creates the required tables by org.apache.log4j.db.DBAppender and
+-- org.apache.log4j.db.DBReceiver.
+--
+-- It is intended for Oracle databases.
+
+-- Tested successfully on Oracle9i Release 9.2.0.3.0 by James Stauffer
+
+-- The following lines are useful in cleaning any previous tables
+
+--drop TRIGGER logging_event_id_seq_trig;
+--drop SEQUENCE logging_event_id_seq;
+--drop table logging_event_property;
+--drop table logging_event_exception;
+--drop table logging_event;
+
+
+CREATE SEQUENCE logging_event_id_seq MINVALUE 1 START WITH 1;
+
+CREATE TABLE logging_event
+ (
+ sequence_number NUMBER(20) NOT NULL,
+ timestamp NUMBER(20) NOT NULL,
+ rendered_message VARCHAR2(4000) NOT NULL,
+ logger_name VARCHAR2(254) NOT NULL,
+ level_string VARCHAR2(254) NOT NULL,
+ ndc VARCHAR2(4000),
+ thread_name VARCHAR2(254),
+ reference_flag SMALLINT,
+ caller_filename VARCHAR2(254) NOT NULL,
+ caller_class VARCHAR2(254) NOT NULL,
+ caller_method VARCHAR2(254) NOT NULL,
+ caller_line CHAR(4) NOT NULL,
+ event_id NUMBER(10) PRIMARY KEY
+ );
+
+
+CREATE TRIGGER logging_event_id_seq_trig
+ BEFORE INSERT ON logging_event
+ FOR EACH ROW
+ BEGIN
+ SELECT logging_event_id_seq.NEXTVAL
+ INTO :NEW.event_id
+ FROM DUAL;
+ END logging_event_id_seq_trig;
+
+
+CREATE TABLE logging_event_property
+ (
+ event_id NUMBER(10) NOT NULL,
+ mapped_key VARCHAR2(254) NOT NULL,
+ mapped_value VARCHAR2(1024),
+ PRIMARY KEY(event_id, mapped_key),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
+
+CREATE TABLE logging_event_exception
+ (
+ event_id NUMBER(10) NOT NULL,
+ i SMALLINT NOT NULL,
+ trace_line VARCHAR2(254) NOT NULL,
+ PRIMARY KEY(event_id, i),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
+
+
+
+
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/postgresql.sql
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/dialect/postgresql.sql Fri Sep 22 17:12:36 2006
@@ -0,0 +1,48 @@
+# This SQL script creates the required tables by org.apache.log4j.db.DBAppender and
+# org.apache.log4j.db.DBReceiver.
+#
+# It is intended for PostgreSQL databases.
+
+DROP TABLE logging_event_property;
+DROP TABLE logging_event_exception;
+DROP SEQUENCE logging_event_id_seq;
+DROP TABLE logging_event;
+
+
+CREATE SEQUENCE logging_event_id_seq MINVALUE 1 START 1;
+
+
+CREATE TABLE logging_event
+ (
+ sequence_number BIGINT NOT NULL,
+ timestamp BIGINT NOT NULL,
+ rendered_message TEXT NOT NULL,
+ logger_name VARCHAR(254) NOT NULL,
+ level_string VARCHAR(254) NOT NULL,
+ ndc TEXT,
+ thread_name VARCHAR(254),
+ reference_flag SMALLINT,
+ caller_filename VARCHAR(254) NOT NULL,
+ caller_class VARCHAR(254) NOT NULL,
+ caller_method VARCHAR(254) NOT NULL,
+ caller_line CHAR(4) NOT NULL,
+ event_id INT DEFAULT nextval('logging_event_id_seq') PRIMARY KEY
+ );
+
+CREATE TABLE logging_event_property
+ (
+ event_id INT NOT NULL,
+ mapped_key VARCHAR(254) NOT NULL,
+ mapped_value VARCHAR(1024),
+ PRIMARY KEY(event_id, mapped_key),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
+
+CREATE TABLE logging_event_exception
+ (
+ event_id INT NOT NULL,
+ i SMALLINT NOT NULL,
+ trace_line VARCHAR(254) NOT NULL,
+ PRIMARY KEY(event_id, i),
+ FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+ );
Added: logback/trunk/logback-classic/src/test/input/db/dbAppenderUsingConnectionSource.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/input/db/dbAppenderUsingConnectionSource.xml Fri Sep 22 17:12:36 2006
@@ -0,0 +1,23 @@
+<configuration>
+
+ <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
+ <connectionSource class="ch.qos.logback.classic.db.DriverManagerConnectionSource">
+ <param name="driverClass" value="com.mysql.jdbc.Driver"/>
+ <param name="url" value="jdbc:mysql://host_name:3306/datebase_name"/>
+ <param name="user" value="logback"/>
+ <param name="password" value="logback"/>
+ </connectionSource>
+ </appender>
+
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <param name="pattern" value="%p %t %c - %m%n"/>
+ </layout>
+ </appender>
+ <root>
+ <level value="debug"/>
+ <appender-ref ref="STDOUT"/>
+ <appender-ref ref="DB"/>
+ </root>
+</configuration>
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderTest.java Fri Sep 22 17:12:36 2006
@@ -0,0 +1,7 @@
+package ch.qos.logback.classic.db;
+
+import junit.framework.TestCase;
+
+public class DBAppenderTest extends TestCase {
+
+}
1
0

21 Sep '06
Author: seb
Date: Thu Sep 21 15:57:39 2006
New Revision: 597
Added:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CssBuilder.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/NOPThrowableRenderer.java
Removed:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/helpers/CssBuilder.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/IThrowableRenderer.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/NOPThrowableRenderer.java
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java
Log:
- created HTMLLayoutBase
- updated HTMLLayout accordingly
- moved some classes to core module when appropriate.
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java Thu Sep 21 15:57:39 2006
@@ -4,6 +4,7 @@
import ch.qos.logback.classic.helpers.Transform;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.classic.spi.ThrowableInformation;
+import ch.qos.logback.core.html.IThrowableRenderer;
public class DefaultThrowableRenderer implements IThrowableRenderer {
@@ -37,7 +38,8 @@
}
}
- public void render(StringBuffer sbuf, LoggingEvent event) {
+ public void render(StringBuffer sbuf, Object eventObject) {
+ LoggingEvent event = (LoggingEvent)eventObject;
ThrowableInformation ti = event.getThrowableInformation();
if (ti != null) {
render(sbuf, ti.getThrowableStrRep());
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java Thu Sep 21 15:57:39 2006
@@ -10,16 +10,13 @@
package ch.qos.logback.classic.html;
+import java.util.Map;
+
import ch.qos.logback.classic.ClassicLayout;
import ch.qos.logback.classic.PatternLayout;
-import ch.qos.logback.classic.helpers.CssBuilder;
import ch.qos.logback.classic.spi.LoggingEvent;
-import ch.qos.logback.core.LayoutBase;
+import ch.qos.logback.core.html.HTMLLayoutBase;
import ch.qos.logback.core.pattern.Converter;
-import ch.qos.logback.core.pattern.DynamicConverter;
-import ch.qos.logback.core.pattern.parser.Node;
-import ch.qos.logback.core.pattern.parser.Parser;
-import ch.qos.logback.core.pattern.parser.ScanException;
/**
*
@@ -83,7 +80,7 @@
* @author Ceki Gülcü
* @author Sébastien Pennec
*/
-public class HTMLLayout extends LayoutBase implements ClassicLayout {
+public class HTMLLayout extends HTMLLayoutBase implements ClassicLayout {
/**
* Default pattern string for log output. Currently set to the string <b>"%m"
@@ -91,21 +88,6 @@
*/
static final String DEFAULT_CONVERSION_PATTERN = "%date%thread%level%logger%mdc%msg";
- private String pattern;
-
- private Converter head;
-
- private String title = "Logback Log Messages";
-
- private CssBuilder cssBuilder;
-
- IThrowableRenderer throwableRenderer = new DefaultThrowableRenderer();
-
- // counter keeping track of the rows output
- private long counter = 0;
- // max number of rows before we close the table and create a new one
- private static final int ROW_LIMIT = 10000;
-
/**
* Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN.
*
@@ -114,167 +96,9 @@
public HTMLLayout() {
pattern = DEFAULT_CONVERSION_PATTERN;
}
-
- /**
- * Set the <b>ConversionPattern </b> option. This is the string which controls
- * formatting and consists of a mix of literal content and conversion
- * specifiers.
- */
- public void setPattern(String conversionPattern) {
- pattern = conversionPattern;
- }
-
- /**
- * Returns the value of the <b>ConversionPattern </b> option.
- */
- public String getPattern() {
- return pattern;
- }
-
- public CssBuilder getCssBuilder() {
- return cssBuilder;
- }
-
- public void setCssBuilder(CssBuilder cssBuilder) {
- this.cssBuilder = cssBuilder;
- }
-
- /**
- * Parses the pattern and creates the Converter linked list.
- */
- @Override
- public void start() {
- int errorCount = 0;
-
- if (throwableRenderer == null) {
- addError("ThrowableRender cannot be null.");
- errorCount++;
- }
-
- try {
- Parser p = new Parser(pattern);
- if (getContext() != null) {
- p.setStatusManager(getContext().getStatusManager());
- }
- Node t = p.parse();
- this.head = p.compile(t, PatternLayout.defaultConverterMap);
- DynamicConverter.startConverters(this.head);
- } catch (ScanException ex) {
- addError("Incorrect pattern found", ex);
- errorCount++;
- }
-
- if (errorCount == 0) {
- started = true;
- }
- }
-
- /**
- * The <b>Title </b> option takes a String value. This option sets the
- * document title of the generated HTML document.
- *
- * <p>
- * Defaults to 'Logback Log Messages'.
- */
- public void setTitle(String title) {
- this.title = title;
- }
-
- /**
- * Returns the current value of the <b>Title </b> option.
- */
- public String getTitle() {
- return title;
- }
-
- /**
- * Returns the content type output by this layout, i.e "text/html".
- */
- @Override
- public String getContentType() {
- return "text/html";
- }
-
- /**
- * Returns appropriate HTML headers.
- */
- @Override
- public String getHeader() {
- StringBuffer sbuf = new StringBuffer();
- sbuf.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"");
- sbuf.append(" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
- sbuf.append(LINE_SEP);
- sbuf.append("<html>");
- sbuf.append(LINE_SEP);
- sbuf.append("<head>");
- sbuf.append(LINE_SEP);
- sbuf.append("<title>");
- sbuf.append(title);
- sbuf.append("</title>");
- sbuf.append(LINE_SEP);
- if (cssBuilder == null) {
- CssBuilder.addDefaultCSS(sbuf);
- } else {
- cssBuilder.addExternalCSS(sbuf);
- }
- sbuf.append(LINE_SEP);
- sbuf.append("</head>");
- sbuf.append(LINE_SEP);
- sbuf.append("<body>");
- sbuf.append(LINE_SEP);
-
- sbuf.append("<hr size=\"1\" noshade=\"true\" />");
- sbuf.append(LINE_SEP);
-
- sbuf.append("Log session start time ");
- sbuf.append(new java.util.Date());
- sbuf.append("<br />");
- sbuf.append(LINE_SEP);
- sbuf.append("<br />");
- sbuf.append(LINE_SEP);
- sbuf.append("<table cellspacing=\"0\">");
- sbuf.append(LINE_SEP);
-
- createTableHeader(sbuf);
-
- return sbuf.toString();
- }
-
- private void createTableHeader(StringBuffer sbuf) {
- Converter c = head;
- String name;
- sbuf.append("<tr class=\"header\">");
- sbuf.append(LINE_SEP);
- while (c != null) {
- name = computeConverterName(c);
- if (name == null) {
- c = c.getNext();
- continue;
- }
- sbuf.append("<td class=\"");
- sbuf.append(computeConverterName(c));
- sbuf.append("\">");
- sbuf.append(computeConverterName(c));
- sbuf.append("</td>");
- sbuf.append(LINE_SEP);
- c = c.getNext();
- }
- sbuf.append("</tr>");
- sbuf.append(LINE_SEP);
- }
-
- /**
- * Returns the appropriate HTML footers.
- */
- @Override
- public String getFooter() {
- StringBuffer sbuf = new StringBuffer();
- sbuf.append("</table>");
- sbuf.append(LINE_SEP);
- sbuf.append("<br>");
- sbuf.append(LINE_SEP);
- sbuf.append("</body></html>");
- return sbuf.toString();
+
+ protected Map<String, String> getDefaultConverterMap() {
+ return PatternLayout.defaultConverterMap;
}
public String doLayout(Object event) {
@@ -316,18 +140,6 @@
return buf.toString();
}
- private void handleTableClosing(StringBuffer sbuf) {
- if (this.counter >= ROW_LIMIT) {
- counter = 0;
- sbuf.append("</table>");
- sbuf.append(LINE_SEP);
- sbuf.append("<br />");
- sbuf.append("<table cellspacing=\"0\">");
- sbuf.append(LINE_SEP);
- createTableHeader(sbuf);
- }
- }
-
private void appendEventToBuffer(StringBuffer buf, Converter c,
LoggingEvent event) {
buf.append("<td class=\"");
@@ -337,24 +149,4 @@
buf.append("</td>");
buf.append(LINE_SEP);
}
-
- private String computeConverterName(Converter c) {
- String className = c.getClass().getSimpleName();
- int index = className.indexOf("Converter");
- if (index == -1) {
- return className;
- } else {
- return className.substring(0, index);
- }
- }
-
- public IThrowableRenderer getThrowableRenderer() {
- return throwableRenderer;
- }
-
- public void setThrowableRenderer(IThrowableRenderer throwableRenderer) {
- this.throwableRenderer = throwableRenderer;
- }
-
-
}
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java Thu Sep 21 15:57:39 2006
@@ -66,7 +66,7 @@
public void testAppendThrowable() throws Exception {
StringBuffer buf = new StringBuffer();
String[] strArray = { "test1", "test2" };
- DefaultThrowableRenderer renderer = (DefaultThrowableRenderer)layout.throwableRenderer;
+ DefaultThrowableRenderer renderer = (DefaultThrowableRenderer)layout.getThrowableRenderer();
renderer.render(buf, strArray);
System.out.println(buf.toString());
String[] result = buf.toString().split(HTMLLayout.LINE_SEP);
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CssBuilder.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CssBuilder.java Thu Sep 21 15:57:39 2006
@@ -0,0 +1,81 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.core.helpers;
+
+import static ch.qos.logback.core.Layout.LINE_SEP;
+
+/**
+ * This class helps the HTMLLayout build the CSS link.
+ * It either provides the HTMLLayout with a default css file,
+ * or builds the link to an external, user-specified, file.
+ *
+ * @author Sébastien Pennec
+ */
+public class CssBuilder {
+
+ String url;
+
+ public CssBuilder() {
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public void addExternalCSS(StringBuffer sbuf) {
+ sbuf.append("<LINK REL=StyleSheet HREF=\"");
+ sbuf.append(url);
+ sbuf.append("\" TITLE=\"Basic\" />");
+ }
+
+ public static void addDefaultCSS(StringBuffer buf) {
+ buf.append("<STYLE type=\"text/css\">");
+ buf.append(LINE_SEP);
+ buf.append("table { margin-left: 2em; margin-right: 2em; border-left: 2px solid #AAA; }");
+ buf.append(LINE_SEP);
+
+ buf.append("TR.even { background: #FFFFFF; }");
+ buf.append(LINE_SEP);
+
+ buf.append("TR.odd { background: #DADADA; }");
+ buf.append(LINE_SEP);
+
+ buf.append("TR.warn TD.level, TR.error TD.level, TR.fatal TD.level {font-weight: bold; color: #FF4040 }");
+ buf.append(LINE_SEP);
+
+ buf.append("TD { padding-right: 1ex; padding-left: 1ex; border-right: 2px solid #AAA; }");
+ buf.append(LINE_SEP);
+
+ buf.append("TD.Time, TD.Date { text-align: right; font-family: courier, monospace; font-size: smaller; }");
+ buf.append(LINE_SEP);
+
+ buf.append("TD.Thread { text-align: left; }");
+ buf.append(LINE_SEP);
+
+ buf.append("TD.Level { text-align: right; }");
+ buf.append(LINE_SEP);
+
+ buf.append("TD.Logger { text-align: left; }");
+ buf.append(LINE_SEP);
+
+ buf.append("TR.header { background: #9090FF; color: #FFF; font-weight: bold; font-size: larger; }");
+ buf.append(LINE_SEP);
+
+ buf.append("TD.Exception { background: #C0C0F0; font-family: courier, monospace;}");
+ buf.append(LINE_SEP);
+
+ buf.append("</STYLE>");
+ buf.append(LINE_SEP);
+ }
+}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java Thu Sep 21 15:57:39 2006
@@ -0,0 +1,232 @@
+package ch.qos.logback.core.html;
+
+import java.util.Map;
+
+import ch.qos.logback.core.LayoutBase;
+import ch.qos.logback.core.helpers.CssBuilder;
+import ch.qos.logback.core.pattern.Converter;
+import ch.qos.logback.core.pattern.DynamicConverter;
+import ch.qos.logback.core.pattern.parser.Node;
+import ch.qos.logback.core.pattern.parser.Parser;
+import ch.qos.logback.core.pattern.parser.ScanException;
+
+/**
+ * This class is a base class for logback component-specific HTMLLayout classes
+ *
+ * @author Sébastien Pennec
+ */
+public abstract class HTMLLayoutBase extends LayoutBase {
+
+ protected String pattern;
+
+ protected Converter head;
+
+ protected String title = "Logback Log Messages";
+
+ protected CssBuilder cssBuilder;
+
+ protected IThrowableRenderer throwableRenderer; //no more initialization ??????
+
+ // counter keeping track of the rows output
+ protected long counter = 0;
+ // max number of rows before we close the table and create a new one
+ protected static final int ROW_LIMIT = 10000;
+
+ /**
+ * Set the <b>ConversionPattern </b> option. This is the string which controls
+ * formatting and consists of a mix of literal content and conversion
+ * specifiers.
+ */
+ public void setPattern(String conversionPattern) {
+ pattern = conversionPattern;
+ }
+
+ /**
+ * Returns the value of the <b>ConversionPattern </b> option.
+ */
+ public String getPattern() {
+ return pattern;
+ }
+
+ public CssBuilder getCssBuilder() {
+ return cssBuilder;
+ }
+
+ public void setCssBuilder(CssBuilder cssBuilder) {
+ this.cssBuilder = cssBuilder;
+ }
+
+ /**
+ * Parses the pattern and creates the Converter linked list.
+ */
+ @Override
+ public void start() {
+ int errorCount = 0;
+
+ if (throwableRenderer == null) {
+ addError("ThrowableRender cannot be null.");
+ errorCount++;
+ }
+
+ try {
+ Parser p = new Parser(pattern);
+ if (getContext() != null) {
+ p.setStatusManager(getContext().getStatusManager());
+ }
+ Node t = p.parse();
+ this.head = p.compile(t, getDefaultConverterMap());
+ DynamicConverter.startConverters(this.head);
+ } catch (ScanException ex) {
+ addError("Incorrect pattern found", ex);
+ errorCount++;
+ }
+
+ if (errorCount == 0) {
+ started = true;
+ }
+ }
+
+ protected abstract Map<String, String> getDefaultConverterMap();
+
+ /**
+ * The <b>Title </b> option takes a String value. This option sets the
+ * document title of the generated HTML document.
+ *
+ * <p>
+ * Defaults to 'Logback Log Messages'.
+ */
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ /**
+ * Returns the current value of the <b>Title </b> option.
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * Returns the content type output by this layout, i.e "text/html".
+ */
+ @Override
+ public String getContentType() {
+ return "text/html";
+ }
+
+ /**
+ * Returns appropriate HTML headers.
+ */
+ @Override
+ public String getHeader() {
+ StringBuffer sbuf = new StringBuffer();
+ sbuf.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"");
+ sbuf.append(" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
+ sbuf.append(LINE_SEP);
+ sbuf.append("<html>");
+ sbuf.append(LINE_SEP);
+ sbuf.append("<head>");
+ sbuf.append(LINE_SEP);
+ sbuf.append("<title>");
+ sbuf.append(title);
+ sbuf.append("</title>");
+ sbuf.append(LINE_SEP);
+ if (cssBuilder == null) {
+ CssBuilder.addDefaultCSS(sbuf);
+ } else {
+ cssBuilder.addExternalCSS(sbuf);
+ }
+ sbuf.append(LINE_SEP);
+ sbuf.append("</head>");
+ sbuf.append(LINE_SEP);
+ sbuf.append("<body>");
+ sbuf.append(LINE_SEP);
+
+ sbuf.append("<hr size=\"1\" noshade=\"true\" />");
+ sbuf.append(LINE_SEP);
+
+ sbuf.append("Log session start time ");
+ sbuf.append(new java.util.Date());
+ sbuf.append("<br />");
+ sbuf.append(LINE_SEP);
+ sbuf.append("<br />");
+ sbuf.append(LINE_SEP);
+ sbuf.append("<table cellspacing=\"0\">");
+ sbuf.append(LINE_SEP);
+
+ createTableHeader(sbuf);
+
+ return sbuf.toString();
+ }
+
+
+ private void createTableHeader(StringBuffer sbuf) {
+ Converter c = head;
+ String name;
+ sbuf.append("<tr class=\"header\">");
+ sbuf.append(LINE_SEP);
+ while (c != null) {
+ name = computeConverterName(c);
+ if (name == null) {
+ c = c.getNext();
+ continue;
+ }
+ sbuf.append("<td class=\"");
+ sbuf.append(computeConverterName(c));
+ sbuf.append("\">");
+ sbuf.append(computeConverterName(c));
+ sbuf.append("</td>");
+ sbuf.append(LINE_SEP);
+ c = c.getNext();
+ }
+ sbuf.append("</tr>");
+ sbuf.append(LINE_SEP);
+ }
+
+ /**
+ * Returns the appropriate HTML footers.
+ */
+ @Override
+ public String getFooter() {
+ StringBuffer sbuf = new StringBuffer();
+ sbuf.append("</table>");
+ sbuf.append(LINE_SEP);
+ sbuf.append("<br>");
+ sbuf.append(LINE_SEP);
+ sbuf.append("</body></html>");
+ return sbuf.toString();
+ }
+
+ protected void handleTableClosing(StringBuffer sbuf) {
+ if (this.counter >= ROW_LIMIT) {
+ counter = 0;
+ sbuf.append("</table>");
+ sbuf.append(LINE_SEP);
+ sbuf.append("<br />");
+ sbuf.append("<table cellspacing=\"0\">");
+ sbuf.append(LINE_SEP);
+ createTableHeader(sbuf);
+ }
+ }
+
+ protected String computeConverterName(Converter c) {
+ String className = c.getClass().getSimpleName();
+ int index = className.indexOf("Converter");
+ if (index == -1) {
+ return className;
+ } else {
+ return className.substring(0, index);
+ }
+ }
+
+ public IThrowableRenderer getThrowableRenderer() {
+ return throwableRenderer;
+ }
+
+ public void setThrowableRenderer(IThrowableRenderer throwableRenderer) {
+ this.throwableRenderer = throwableRenderer;
+ }
+
+
+
+}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java Thu Sep 21 15:57:39 2006
@@ -0,0 +1,8 @@
+package ch.qos.logback.core.html;
+
+
+public interface IThrowableRenderer {
+
+ public void render(StringBuffer sbuf, Object event);
+
+}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/NOPThrowableRenderer.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/NOPThrowableRenderer.java Thu Sep 21 15:57:39 2006
@@ -0,0 +1,12 @@
+package ch.qos.logback.core.html;
+
+import ch.qos.logback.core.html.IThrowableRenderer;
+
+
+public class NOPThrowableRenderer implements IThrowableRenderer {
+
+ public void render(StringBuffer sbuf, Object event) {
+ return;
+ }
+
+}
1
0
I've already contacted them by leaving a comment on their website.
--
Ceki Gülcü
1
0
Boris,
Thank you for bringing the existence of the logbag prokect to our attention.
I had not heard of it before. The logback and logback projets are not
related in any way, except the sound of their names. We should contact them,
asking them politely whether they know about our project (logback) and
whether they would not mind renaming theirs (logbag).
Cheers,
--
Ceki Gülcü
1
0

svn commit: r596 - in logback/trunk/logback-access/src: main/java/ch/qos/logback/access/jetty main/java/ch/qos/logback/access/spi test/java/ch/qos/logback/access/pattern test/java/ch/qos/logback/access/pattern/helpers
by noreply.seb@qos.ch 20 Sep '06
by noreply.seb@qos.ch 20 Sep '06
20 Sep '06
Author: seb
Date: Wed Sep 20 17:03:16 2006
New Revision: 596
Added:
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/JettyServerAdapter.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/ServerAdapter.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyValuesAdapter.java
Modified:
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java
Log:
- added a ServerAdapter interface to allow the server-independent AccessEvent to reach server-specific methods
- impemented this interface in JettyServerAdapter and DummyValuesAdapter, the latter used for testing only.
- updated ConverterTest.
Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/JettyServerAdapter.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/JettyServerAdapter.java Wed Sep 20 17:03:16 2006
@@ -0,0 +1,35 @@
+package ch.qos.logback.access.jetty;
+
+import org.mortbay.jetty.Request;
+import org.mortbay.jetty.Response;
+
+import ch.qos.logback.access.spi.ServerAdapter;
+
+/**
+ * A jetty specific implementation of the {@link ServerAdapter} interface.
+ *
+ * @author Sébastien Pennec
+ */
+public class JettyServerAdapter implements ServerAdapter {
+
+ Request request;
+ Response response;
+
+ public JettyServerAdapter(Request jettyRequest, Response jettyResponse) {
+ this.request = jettyRequest;
+ this.response = jettyResponse;
+ }
+
+ public long getContentLength() {
+ return response.getContentCount();
+ }
+
+ public int getStatusCode() {
+ return response.getStatus();
+ }
+
+ public String getResponseHeader(String key) {
+ return response.getHeader(key);
+ }
+
+}
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java Wed Sep 20 17:03:16 2006
@@ -27,7 +27,8 @@
String filename;
public void log(Request jettyRequest, Response jettyResponse) {
- AccessEvent accessEvent = new AccessEvent(jettyRequest, jettyResponse);
+ JettyServerAdapter adapter = new JettyServerAdapter(jettyRequest, jettyResponse);
+ AccessEvent accessEvent = new AccessEvent(jettyRequest, jettyResponse, adapter);
// TODO better exception handling
aai.appendLoopOnAppenders(accessEvent);
}
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java Wed Sep 20 17:03:16 2006
@@ -9,8 +9,6 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.mortbay.jetty.Response;
-
import ch.qos.logback.access.pattern.AccessConverter;
public class AccessEvent implements Serializable {
@@ -31,26 +29,27 @@
String protocol;
String method;
String serverName;
-
- Map requestHeaderMap;
+
+ Map<String, Object> requestHeaderMap;
long contentLength = SENTINEL;
int statusCode = SENTINEL;
int localPort = SENTINEL;
+ ServerAdapter serverAdapter;
+
/**
* The number of milliseconds elapsed from 1/1/1970 until logging event was
* created.
*/
private long timeStamp = 0;
-
-
public AccessEvent(HttpServletRequest httpRequest,
- HttpServletResponse httpResponse) {
+ HttpServletResponse httpResponse, ServerAdapter adapter) {
this.httpRequest = httpRequest;
this.httpResponse = httpResponse;
this.timeStamp = System.currentTimeMillis();
+ this.serverAdapter = adapter;
}
public long getTimeStamp() {
@@ -159,7 +158,6 @@
return serverName;
}
-
public String getRemoteAddr() {
if (remoteAddr == null) {
if (httpRequest != null) {
@@ -190,25 +188,18 @@
}
public void buildRequestHeaderMap() {
- requestHeaderMap = new HashMap();
+ requestHeaderMap = new HashMap<String, Object>();
Enumeration e = httpRequest.getHeaderNames();
- while(e.hasMoreElements()) {
+ while (e.hasMoreElements()) {
String key = (String) e.nextElement();
requestHeaderMap.put(key, httpRequest.getHeader(key));
}
}
-
+
public String getResponseHeader(String key) {
- //TODO buildMap
- if (httpResponse instanceof org.mortbay.jetty.Response) {
- return ((org.mortbay.jetty.Response)httpResponse).getHeader(key);
- }
- if (httpResponse instanceof ch.qos.logback.access.pattern.helpers.DummyResponse) {
- return ((ch.qos.logback.access.pattern.helpers.DummyResponse)httpResponse).getHeader(key);
- }
-
- return null;
+ return serverAdapter.getResponseHeader(key);
}
+
/**
* Attributes are not serialized
*
@@ -248,15 +239,20 @@
public long getContentLength() {
if (contentLength == SENTINEL) {
if (httpResponse != null) {
- if (httpResponse instanceof org.mortbay.jetty.Response) {
- // TODO
- } else if (httpResponse instanceof com.caucho.server.connection.AbstractHttpResponse) {
- contentLength = ((com.caucho.server.connection.AbstractHttpResponse) httpResponse)
- .getContentLength();
- } else if (httpResponse instanceof org.apache.catalina.connector.Response) {
- contentLength = ((org.apache.catalina.connector.Response) httpResponse)
- .getContentLength();
- }
+ return serverAdapter.getContentLength();
+ // if (httpResponse instanceof org.mortbay.jetty.Response) {
+ // // TODO
+ // } else if (httpResponse instanceof
+ // com.caucho.server.connection.AbstractHttpResponse) {
+ // contentLength = ((com.caucho.server.connection.AbstractHttpResponse)
+ // httpResponse)
+ // .getContentLength();
+ // } else if (httpResponse instanceof
+ // org.apache.catalina.connector.Response) {
+ // contentLength = ((org.apache.catalina.connector.Response)
+ // httpResponse)
+ // .getContentLength();
+ // }
}
}
return contentLength;
@@ -265,15 +261,19 @@
public int getStatusCode() {
if (statusCode == SENTINEL) {
if (httpResponse != null) {
- if (httpResponse instanceof org.mortbay.jetty.Response) {
- statusCode = ((org.mortbay.jetty.Response) httpResponse).getStatus();
- } else if (httpResponse instanceof com.caucho.server.connection.AbstractHttpResponse) {
- statusCode = ((com.caucho.server.connection.AbstractHttpResponse) httpResponse)
- .getStatusCode();
- } else if (httpResponse instanceof org.apache.catalina.connector.Response) {
- statusCode = ((org.apache.catalina.connector.Response) httpResponse)
- .getStatus();
- }
+ return serverAdapter.getStatusCode();
+ // if (httpResponse instanceof org.mortbay.jetty.Response) {
+ // statusCode = ((org.mortbay.jetty.Response) httpResponse).getStatus();
+ // } else if (httpResponse instanceof
+ // com.caucho.server.connection.AbstractHttpResponse) {
+ // statusCode = ((com.caucho.server.connection.AbstractHttpResponse)
+ // httpResponse)
+ // .getStatusCode();
+ // } else if (httpResponse instanceof
+ // org.apache.catalina.connector.Response) {
+ // statusCode = ((org.apache.catalina.connector.Response) httpResponse)
+ // .getStatus();
+ // }
}
}
return statusCode;
@@ -288,4 +288,8 @@
}
return localPort;
}
+
+ public ServerAdapter getServerAdapter() {
+ return serverAdapter;
+ }
}
\ No newline at end of file
Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/ServerAdapter.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/ServerAdapter.java Wed Sep 20 17:03:16 2006
@@ -0,0 +1,15 @@
+package ch.qos.logback.access.spi;
+
+/**
+ * An interface to access server-specific methods from
+ * the server-independent AccessEvent.
+ *
+ * @author Ceki Gülcü
+ * @author Sébastien Pennec
+ */
+public interface ServerAdapter {
+
+ long getContentLength();
+ int getStatusCode();
+ String getResponseHeader(String key);
+}
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java Wed Sep 20 17:03:16 2006
@@ -10,6 +10,7 @@
import junit.framework.TestCase;
import ch.qos.logback.access.pattern.helpers.DummyRequest;
import ch.qos.logback.access.pattern.helpers.DummyResponse;
+import ch.qos.logback.access.pattern.helpers.DummyValuesAdapter;
import ch.qos.logback.access.spi.AccessEvent;
public class ConverterTest extends TestCase {
@@ -33,7 +34,10 @@
}
public void testContentLengthConverter() {
- // TODO when AccessEvent has been modified
+ ContentLengthConverter converter = new ContentLengthConverter();
+ converter.start();
+ String result = converter.convert(event);
+ assertEquals(Long.toString(event.getServerAdapter().getContentLength()), result);
}
public void testDateConverter() {
@@ -150,11 +154,15 @@
}
public void testStatusCodeConverter() {
- //TODO
+ StatusCodeConverter converter = new StatusCodeConverter();
+ converter.start();
+ String result = converter.convert(event);
+ assertEquals(Integer.toString(event.getServerAdapter().getStatusCode()), result);
}
private AccessEvent createEvent() {
- AccessEvent ae = new AccessEvent(request, response);
+ DummyValuesAdapter dummyAdapter = new DummyValuesAdapter(request, response);
+ AccessEvent ae = new AccessEvent(request, response, dummyAdapter);
return ae;
}
Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyValuesAdapter.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyValuesAdapter.java Wed Sep 20 17:03:16 2006
@@ -0,0 +1,35 @@
+package ch.qos.logback.access.pattern.helpers;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import ch.qos.logback.access.spi.ServerAdapter;
+
+/**
+ * A test-only implementation of the {@link ServerAdapter} interface.
+ *
+ * @author Sébastien Pennec
+ */
+public class DummyValuesAdapter implements ServerAdapter {
+
+ DummyRequest request;
+ DummyResponse response;
+
+ public DummyValuesAdapter(HttpServletRequest request, HttpServletResponse response) {
+ this.request = (DummyRequest)request;
+ this.response = (DummyResponse)response;
+ }
+
+ public long getContentLength() {
+ return 123L;
+ }
+
+ public String getResponseHeader(String key) {
+ return response.getHeader(key);
+ }
+
+ public int getStatusCode() {
+ return 1;
+ }
+
+}
1
0

svn commit: r595 - logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling
by noreply.seb@qos.ch 19 Sep '06
by noreply.seb@qos.ch 19 Sep '06
19 Sep '06
Author: seb
Date: Tue Sep 19 16:53:10 2006
New Revision: 595
Modified:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java
Log:
- corrected javadoc
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java Tue Sep 19 16:53:10 2006
@@ -24,13 +24,13 @@
* <configuration>
* <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
* <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
- * <param name="ActiveFile" value="outputFile.log" />
+ * <param name="ActiveFileName" value="outputFile.log" />
* <param name="FileNamePattern" value="logFile.%i.log" />
* <param name="MinIndex" value="1" />
* <param name="MaxIndex" value="3" />
* </rollingPolicy>
*
- * <b><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedRollingPolicy">
+ * <b><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
* <param name="MaxFileSize" value="5MB" />
* </triggeringPolicy></b>
*
1
0

svn commit: r594 - logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling
by noreply.seb@qos.ch 19 Sep '06
by noreply.seb@qos.ch 19 Sep '06
19 Sep '06
Author: seb
Date: Tue Sep 19 16:02:04 2006
New Revision: 594
Modified:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java
Log:
- added a configuration example in the javadoc
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java Tue Sep 19 16:02:04 2006
@@ -14,7 +14,38 @@
/**
* SizeBasedTriggeringPolicy looks at size of the file being
- * currently written to.
+ * currently written to. If it grows bigger than the specified size,
+ * the FileAppender using the SizeBasedTriggeringPolicy rolls the file
+ * and creates a new one.
+ * <p>
+ * Here is an example of a configuration using SizeBasedTriggeringPolicy.
+ * <p>
+ * <pre>
+ * <configuration>
+ * <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ * <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ * <param name="ActiveFile" value="outputFile.log" />
+ * <param name="FileNamePattern" value="logFile.%i.log" />
+ * <param name="MinIndex" value="1" />
+ * <param name="MaxIndex" value="3" />
+ * </rollingPolicy>
+ *
+ * <b><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedRollingPolicy">
+ * <param name="MaxFileSize" value="5MB" />
+ * </triggeringPolicy></b>
+ *
+ * <layout class="ch.qos.logback.classic.PatternLayout">
+ * <param name="pattern" value="%-4relative [%thread] %-5level %class - %msg%n" />
+ * </layout>
+ * </appender>
+ *
+ * <root>
+ * <level value="debug" />
+ * <appender-ref ref="FILE" />
+ * </root>
+ * </configuration>
+ * </pre>
+ *
*
* @author Ceki Gülcü
*
1
0

svn commit: r593 - logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic
by noreply.seb@qos.ch 19 Sep '06
by noreply.seb@qos.ch 19 Sep '06
19 Sep '06
Author: seb
Date: Tue Sep 19 15:36:32 2006
New Revision: 593
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java
Log:
- improved javadoc
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java Tue Sep 19 15:36:32 2006
@@ -34,90 +34,412 @@
import ch.qos.logback.core.pattern.PatternLayoutBase;
/**
+ * <p>
+ * A flexible layout configurable with pattern string. The goal of this class is
+ * to {@link #format format} a {@link LoggingEvent} and return the results in a
+ * {#link String}. The format of the result depends on the
+ * <em>conversion pattern</em>.
+ * <p>
+ *
+ * <p>
+ * The conversion pattern is closely related to the conversion pattern of the
+ * printf function in C. A conversion pattern is composed of literal text and
+ * format control expressions called <em>conversion specifiers</em>.
+ *
+ * <p>
+ * <i>Note that you are free to insert any literal text within the conversion
+ * pattern.</i>
+ * </p>
+ *
+ * <p>
+ * Each conversion specifier starts with a percent sign (%) and is followed by
+ * optional <em>format modifiers</em> and a <em>conversion character</em> or
+ * <em>conversion word</em>. The conversion character or word specifies the
+ * type of data, e.g. logger, level, date, thread name. The format modifiers
+ * control such things as field width, padding, left and right justification.
+ * The following is a simple example.
+ *
+ * <p>
+ * Let the conversion pattern be <b>"%-5level [%thread]: %message%n"</b> and
+ * assume that the logback environment was set to use a PatternLayout. Then the
+ * statements
+ *
+ * <pre>
+ * Logger logger = LoggerFactory.getLogger("root");
+ * root.debug("Message 1");
+ * root.warn("Message 2");
+ * </pre>
+ *
+ * would yield the output
+ *
+ * <pre>
+ * DEBUG [main]: Message 1
+ * WARN [main]: Message 2
+ * </pre>
+ *
+ * <p>
+ * Note that there is no explicit separator between text and conversion
+ * specifiers. The pattern parser knows when it has reached the end of a
+ * conversion specifier when it reads a conversion character. In the example
+ * above the conversion specifier <b>%-5level</b> means the level of the
+ * logging event should be left justified to a width of five characters.
+ *
+ * The recognized conversion characters and words are
+ *
+ * <p>
+ * <table border="1" CELLPADDING="8">
+ * <th>Conversion Character or Word</th>
+ * <th>Effect</th>
+ *
+ * <tr>
+ * <td align=center><b>c / l / lo / logger</b></td>
+ *
+ * <td>Used to output the logger of the logging event. The logger conversion
+ * specifier can be optionally followed by <em>precision specifier</em>, that
+ * is a decimal constant in brackets.
+ *
+ * <p>
+ * If a precision specifier is given, then only the corresponding number of
+ * right most components of the logger name will be printed. By default the
+ * logger name is printed in full.
*
- * PatternLayout is a simple yet powerfull way to turn a LoggingEvent into
- * a String.
* <p>
- * The returned String can be modified by specifying a pattern to the layout.
- * A pattern is composed of literal text and format control expressions called
- * conversion specifiers. Any literal can be inserted between the conversions
- * specifiers. When literals are inserted, PatternLayout is able to differentiate
- * which part of the pattern are conversion specifiers and which should be
- * added as-is to the output string.
- * <p>
- * A conversion specifier starts with a percent sign (%) and is followed by
- * a letter or a word, describing the type of data that will be displayed.
- * A format modifier can be added to the conversion specifier. It will tweak
- * the way that the conversion specifier will display the data.
- * <p>
- * Here are a few quick examples:
- * <p>
- * <table cellpadding=10>
- * <tr>
- * <th>Conversion pattern</th>
- * <th>Result</th>
- * <th>Explanation</th>
- * </tr>
- * <tr>
- * <td>%level [%thread]: %message</td>
- * <td>DEBUG [main]: Message 1</td>
- * <td>Simple pattern</td>
- * </tr>
- * <tr>
- * <td>%level [%logger]: %message</td>
- * <td>DEBUG [org.foo.bar.SampleClass]: Message 2</td>
- * <td>With <em>%logger</em>, the fully qualified name is displayed</td>
- * </tr>
- * <tr>
- * <td>%level [%logger{10}]: %message</td>
- * <td>DEBUG [o.f.b.SampleClass]: Message 2</td>
- * <td>A format modifier has been added to the conversion specifier, thus
- * modifying the string displayed.</td>
- * </tr>
+ * For example, for the category name "a.b.c" the pattern <b>%logger{2}</b>
+ * will output "b.c". See more examples of name abbreviations further down this
+ * document.
+ *
+ * </td>
+ * </tr>
+ *
+ * <tr>
+ * <td align=center><b>C / class</b></td>
+ *
+ * <td>Used to output the fully qualified class name of the caller issuing the
+ * logging request. This conversion specifier can be optionally followed by
+ * <em>precision specifier</em>, that is a decimal constant in brackets.
+ *
+ * <p>
+ * If a precision specifier is given, then only the corresponding number of
+ * right most components of the class name will be printed. By default the class
+ * name is output in fully qualified form.
+ *
+ * <p>
+ * For example, for the class name "org.apache.xyz.SomeClass", the pattern
+ * <b>%class{1}</b> will output "SomeClass". See more examples of name
+ * abbreviations further down this document.
+ *
+ * <p>
+ * <b>WARNING</b> Generating the caller class information is slow. Thus, it's
+ * use should be avoided unless execution speed is not an issue.
+ *
+ * </td>
+ * </tr>
+ *
+ * <tr>
+ * <td align=center><b>d / date</b></td>
+ * <td>Used to output the date of the logging event. The date conversion
+ * specifier may be followed by a set of braces containing a date and time
+ * pattern strings {@link java.text.SimpleDateFormat}, <em>ABSOLUTE</em>,
+ * <em>DATE</em> or <em>ISO8601</em>. For example, <b>%d{HH:mm:ss,SSS}</b>,
+ * <b>%d{dd MMM yyyy HH:mm:ss,SSS}</b> or <b>%d{DATE}</b>. If
+ * no date format specifier is given then ISO8601 format is assumed. </td>
+ * </tr>
+ *
+ * <tr>
+ * <td align=center><b>F / file</b></td>
+ *
+ * <td>Used to output the file name where the logging request was issued.
+ *
+ * <p>
+ * <b>WARNING</b> Generating caller file information is extremely slow. Its use
+ * should be avoided unless execution speed is not an issue.
+ *
+ * </tr>
+ *
+ * <tr>
+ * <td align=center><b>caller</b></td>
+ *
+ * <td>Used to output location information of the caller which generated the
+ * logging event.
+ *
+ * <p>
+ * The location information depends on the JVM implementation but usually
+ * consists of the fully qualified name of the calling method followed by the
+ * callers source the file name and line number between parentheses.
+ *
+ * <p>
+ * The location information can be very useful. However, it's generation is
+ * <em>extremely</em> slow. It's use should be avoided unless execution speed
+ * is not an issue.
+ *
+ * </td>
+ * </tr>
+ *
+ * <tr>
+ * <td align=center><b>L / line</b></td>
+ *
+ * <td>Used to output the line number from where the logging request was
+ * issued.
+ *
+ * <p>
+ * <b>WARNING</b> Generating caller location information is extremely slow.
+ * It's use should be avoided unless execution speed is not an issue.
+ *
+ * </tr>
+ *
+ *
+ * <tr>
+ * <td align=center><b>m / msg / message</b></td>
+ * <td>Used to output the application supplied message associated with the
+ * logging event.</td>
+ * </tr>
+ *
+ * <tr>
+ * <td align=center><b>M / method</b></td>
+ *
+ * <td>Used to output the method name where the logging request was issued.
+ *
+ * <p>
+ * <b>WARNING</b> Generating caller location information is extremely slow.
+ * It's use should be avoided unless execution speed is not an issue.
+ *
+ * </tr>
+ *
+ * <tr>
+ * <td align=center><b>n</b></td>
+ *
+ * <td>Outputs the platform dependent line separator character or characters.
+ *
+ * <p>
+ * This conversion character offers practically the same performance as using
+ * non-portable line separator strings such as "\n", or "\r\n". Thus, it is the
+ * preferred way of specifying a line separator.
+ *
+ *
+ * </tr>
+ *
+ * <tr>
+ * <td align=center><b>p / le / level</b></td>
+ * <td>Used to output the level of the logging event.</td>
+ * </tr>
+ *
+ * <tr>
+ *
+ * <td align=center><b>r / relative</b></td>
+ *
+ * <td>Used to output the number of milliseconds elapsed since the start of the
+ * application until the creation of the logging event.</td>
+ * </tr>
+ *
+ *
+ * <tr>
+ * <td align=center><b>t / thread</b></td>
+ *
+ * <td>Used to output the name of the thread that generated the logging event.</td>
+ *
+ * </tr>
+ *
+ * <tr>
+ * <td align=center><b>X</b></td>
+ *
+ * <td>
+ *
+ * <p>
+ * Used to output the MDC (mapped diagnostic context) associated with the thread
+ * that generated the logging event. The <b>X</b> conversion character can be
+ * followed by the key for the map placed between braces, as in
+ * <b>%X{clientNumber}</b> where <code>clientNumber</code> is the key. The
+ * value in the MDC corresponding to the key will be output. If no additional
+ * sub-option is specified, then the entire contents of the MDC key value pair
+ * set is output using a format key1=val1, key2=val2
+ * </p>
+ *
+ * <p>
+ * See {@link MDC} class for more details.
+ * </p>
+ *
+ * </td>
+ * </tr>
+ * <tr>
+ * <td align=center><b>throwable</b></td>
+ *
+ * <td>
+ * <p>
+ * Used to output the Throwable trace that has been bound to the LoggingEvent,
+ * by default this will output the full trace as one would normally find by a
+ * call to Throwable.printStackTrace(). The throwable conversion word can be
+ * followed by an option in the form <b>%throwable{short}</b> which will only
+ * output the first line of the ThrowableInformation.
+ * </p>
+ * </td>
+ * </tr>
+ *
+ * <tr>
+ *
+ * <td align=center><b>%</b></td>
+ *
+ * <td>The sequence %% outputs a single percent sign. </td>
+ * </tr>
+ *
+ * </table>
+ *
+ * <p>
+ * By default the relevant information is output as is. However, with the aid of
+ * format modifiers it is possible to change the minimum field width, the
+ * maximum field width and justification.
+ *
+ * <p>
+ * The optional format modifier is placed between the percent sign and the
+ * conversion character or word.
+ *
+ * <p>
+ * The first optional format modifier is the <em>left justification flag</em>
+ * which is just the minus (-) character. Then comes the optional
+ * <em>minimum field width</em> modifier. This is a decimal constant that
+ * represents the minimum number of characters to output. If the data item
+ * requires fewer characters, it is padded on either the left or the right until
+ * the minimum width is reached. The default is to pad on the left (right
+ * justify) but you can specify right padding with the left justification flag.
+ * The padding character is space. If the data item is larger than the minimum
+ * field width, the field is expanded to accommodate the data. The value is
+ * never truncated.
+ *
+ * <p>
+ * This behavior can be changed using the <em>maximum field width</em>
+ * modifier which is designated by a period followed by a decimal constant. If
+ * the data item is longer than the maximum field, then the extra characters are
+ * removed from the <em>beginning</em> of the data item and not from the end.
+ * For example, it the maximum field width is eight and the data item is ten
+ * characters long, then the first two characters of the data item are dropped.
+ * This behavior deviates from the printf function in C where truncation is done
+ * from the end.
+ *
+ * <p>
+ * Below are various format modifier examples for the logger conversion
+ * specifier.
+ *
+ * <p>
+ * <TABLE BORDER=1 CELLPADDING=8>
+ * <th>Format modifier
+ * <th>Left justify
+ * <th>Minimum width
+ * <th>Maximum width
+ * <th>Comment
+ *
+ * <tr>
+ * <td align=center>%20c</td>
+ * <td align=center>false</td>
+ * <td align=center>20</td>
+ * <td align=center>none</td>
+ *
+ * <td>Left pad with spaces if the category name is less than 20 characters
+ * long.
+ *
+ * <tr>
+ * <td align=center>%-20c</td>
+ * <td align=center>true</td>
+ * <td align=center>20</td>
+ * <td align=center>none</td>
+ * <td>Right pad with spaces if the logger name is less than 20 characters
+ * long.
+ *
+ * <tr>
+ * <td align=center>%.30c</td>
+ * <td align=center>NA</td>
+ * <td align=center>none</td>
+ * <td align=center>30</td>
+ *
+ * <td>Truncate from the beginning if the logger name is longer than 30
+ * characters.
+ *
+ * <tr>
+ * <td align=center>%20.30c</td>
+ * <td align=center>false</td>
+ * <td align=center>20</td>
+ * <td align=center>30</td>
+ *
+ * <td>Left pad with spaces if the logger name is shorter than 20 characters.
+ * However, if logger name is longer than 30 characters, then truncate from the
+ * beginning.
+ *
+ * <tr>
+ * <td align=center>%-20.30c</td>
+ * <td align=center>true</td>
+ * <td align=center>20</td>
+ * <td align=center>30</td>
+ *
+ * <td>Right pad with spaces if the logger name is shorter than 20 characters.
+ * However, if logger name is longer than 30 characters, then truncate from the
+ * beginning.
+ *
* </table>
+ *
* <p>
- * When a conversion specifier is used in conjunction with a format modifier,
- * the resulting string is modified. It is modified in a way that one can still
- * read the class name, and deduce its fully qualified name by looking at the
- * packages' first letter.
- * <p>
- * The format modifier can have a milder effect on the resulting string. If a
- * larger number is specified, a longer part of the fully qualified name will be
- * displayed without modification. In that case, the name of deeper packages
- * are displayed first.
- * <p>
- * Here are a few more examples of the format modifier behaviour.
- * <p>
- * <table cellpadding=10>
- * <tr>
- * <th>Conversion Pattern</th>
- * <th>Class name</th>
- * <th>Result</th>
- * </tr>
- * <tr>
- * <td>%logger{10}</td>
- * <td>mainPackage.sub.sample.Bar</td>
- * <td>m.s.s.Bar</td>
- * </tr>
- * <tr>
- * <td>%logger{15}</td>
- * <td>mainPackage.sub.sample.Bar</td>
- * <td>m.s.sample.Bar</td>
- * </tr>
- * <tr>
- * <td>%logger{16}</td>
- * <td>mainPackage.sub.sample.Bar</td>
- * <td>m.sub.sample.Bar</td>
- * </tr>
- * <tr>
- * <td>%logger{26}</td>
- * <td>mainPackage.sub.sample.Bar</td>
- * <td>mainPackage.sub.sample.Bar</td>
- * </tr>
+ * Below are some examples of conversion patterns.
+ *
+ * <dl>
+ *
+ * <p>
+ * <dt><b>%relative [%thread] %-5level %logger %mdc - %message\n</b>
+ * <p>
+ * <dd>This is essentially the TTCC layout.
+ *
+ * <p>
+ * <dt><b>%-6relative [%15.15thread] %-5level %30.30logger %mdc - %message\n</b>
+ *
+ * <p>
+ * <dd>Similar to the TTCC layout except that the relative time is right padded
+ * if less than 6 digits, thread name is right padded if less than 15 characters
+ * and truncated if longer and the logger name is left padded if shorter than 30
+ * characters and truncated if longer.
+ *
+ * </dl>
+ * <p> Here are a few more examples of the format modifier behaviour, with emphasis on
+ * the way it affects class names.
+ * <p>
+ *
+ * <table BORDER=1 CELLPADDING=8>
+ *
+ * <tr>
+ * <th>Conversion Pattern</th>
+ * <th>Class name</th>
+ * <th>Result</th>
+ * </tr>
+ *
+ * <tr>
+ * <td>%logger{10}</td>
+ * <td>mainPackage.sub.sample.Bar</td>
+ * <td>m.s.s.Bar</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>%logger{15}</td>
+ * <td>mainPackage.sub.sample.Bar</td>
+ * <td>m.s.sample.Bar</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>%logger{16}</td>
+ * <td>mainPackage.sub.sample.Bar</td>
+ * <td>m.sub.sample.Bar</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>%logger{26}</td>
+ * <td>mainPackage.sub.sample.Bar</td>
+ * <td>mainPackage.sub.sample.Bar</td>
+ * </tr>
+ *
* </table>
- *<p>
+ *
+ * <p>
+ * The above text is largely inspired from Peter A. Darnell and Philip E.
+ * Margolis' highly recommended book "C -- a Software Engineering Approach",
+ * ISBN 0-387-97389-3.
+ *
*
*/
+
public class PatternLayout extends PatternLayoutBase implements ClassicLayout {
// FIXME fix exception handling
@@ -135,14 +457,14 @@
defaultConverterMap.put("level", LevelConverter.class.getName());
defaultConverterMap.put("le", LevelConverter.class.getName());
defaultConverterMap.put("p", LevelConverter.class.getName());
-
+
defaultConverterMap.put("t", ThreadConverter.class.getName());
defaultConverterMap.put("thread", ThreadConverter.class.getName());
defaultConverterMap.put("lo", LoggerConverter.class.getName());
defaultConverterMap.put("logger", LoggerConverter.class.getName());
defaultConverterMap.put("c", LoggerConverter.class.getName());
-
+
defaultConverterMap.put("m", MessageConverter.class.getName());
defaultConverterMap.put("msg", MessageConverter.class.getName());
defaultConverterMap.put("message", MessageConverter.class.getName());
@@ -158,10 +480,10 @@
defaultConverterMap.put("F", FileOfCallerConverter.class.getName());
defaultConverterMap.put("file", FileOfCallerConverter.class.getName());
-
+
defaultConverterMap.put("X", MDCConverter.class.getName());
defaultConverterMap.put("mdc", MDCConverter.class.getName());
-
+
defaultConverterMap
.put("ex", ThrowableInformationConverter.class.getName());
defaultConverterMap.put("exception", ThrowableInformationConverter.class
1
0

svn commit: r592 - in logback/trunk: . logback-access/src/main/java/ch/qos/logback/access/pattern logback-access/src/main/java/ch/qos/logback/access/spi logback-access/src/test/java/ch/qos/logback/access/pattern logback-access/src/test/java/ch/qos/logback/access/pattern/helpers
by noreply.seb@qos.ch 19 Sep '06
by noreply.seb@qos.ch 19 Sep '06
19 Sep '06
Author: seb
Date: Tue Sep 19 10:32:01 2006
New Revision: 592
Modified:
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestHeaderConverter.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseHeaderConverter.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyRequest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyResponse.java
logback/trunk/pom.xml
Log:
- updated dependencies to use jetty 6.0.0
- modified AccessEvent method getHeader to getRequestHeader
- added getResponseHeader to AccessEvent
- updated DummyResponse to provide header access
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestHeaderConverter.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestHeaderConverter.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/pattern/RequestHeaderConverter.java Tue Sep 19 10:32:01 2006
@@ -22,7 +22,7 @@
return "INACTIVE_HEADER_CONV";
}
- return accessEvent.getHeader(key);
+ return accessEvent.getRequestHeader(key);
}
}
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseHeaderConverter.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseHeaderConverter.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/pattern/ResponseHeaderConverter.java Tue Sep 19 10:32:01 2006
@@ -22,7 +22,8 @@
return "INACTIVE_REPONSE_HEADER_CONV";
}
- return null;
+ return accessEvent.getResponseHeader(key);
+ //return null;
// HttpServletResponse response = accessEvent.getHttpResponse();
//
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java Tue Sep 19 10:32:01 2006
@@ -9,6 +9,8 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.mortbay.jetty.Response;
+
import ch.qos.logback.access.pattern.AccessConverter;
public class AccessEvent implements Serializable {
@@ -30,7 +32,7 @@
String method;
String serverName;
- Map headerMap;
+ Map requestHeaderMap;
long contentLength = SENTINEL;
int statusCode = SENTINEL;
@@ -169,15 +171,15 @@
return remoteAddr;
}
- public String getHeader(String key) {
+ public String getRequestHeader(String key) {
String result = null;
- if (headerMap == null) {
+ if (requestHeaderMap == null) {
if (httpRequest != null) {
- buildHeaderMap();
- result = (String) headerMap.get(key);
+ buildRequestHeaderMap();
+ result = (String) requestHeaderMap.get(key);
}
} else {
- result = (String) headerMap.get(key);
+ result = (String) requestHeaderMap.get(key);
}
if (result != null) {
@@ -187,15 +189,26 @@
}
}
- public void buildHeaderMap() {
- headerMap = new HashMap();
+ public void buildRequestHeaderMap() {
+ requestHeaderMap = new HashMap();
Enumeration e = httpRequest.getHeaderNames();
while(e.hasMoreElements()) {
String key = (String) e.nextElement();
- headerMap.put(key, httpRequest.getHeader(key));
+ requestHeaderMap.put(key, httpRequest.getHeader(key));
}
}
-
+
+ public String getResponseHeader(String key) {
+ //TODO buildMap
+ if (httpResponse instanceof org.mortbay.jetty.Response) {
+ return ((org.mortbay.jetty.Response)httpResponse).getHeader(key);
+ }
+ if (httpResponse instanceof ch.qos.logback.access.pattern.helpers.DummyResponse) {
+ return ((ch.qos.logback.access.pattern.helpers.DummyResponse)httpResponse).getHeader(key);
+ }
+
+ return null;
+ }
/**
* Attributes are not serialized
*
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java Tue Sep 19 10:32:01 2006
@@ -133,14 +133,13 @@
}
public void testResponseHeaderConverter() {
- // TODO
- // ResponseHeaderConverter converter = new ResponseHeaderConverter();
- // List<String> optionList = new ArrayList<String>();
- // optionList.add("headerName1");
- // converter.setOptionList(optionList);
- // converter.start();
- // String result = converter.convert(event);
- // assertEquals(request.getHeader("headerName1"), result);
+ ResponseHeaderConverter converter = new ResponseHeaderConverter();
+ List<String> optionList = new ArrayList<String>();
+ optionList.add("headerName1");
+ converter.setOptionList(optionList);
+ converter.start();
+ String result = converter.convert(event);
+ assertEquals(request.getHeader("headerName1"), result);
}
public void testServerNameConverter() {
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyRequest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyRequest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyRequest.java Tue Sep 19 10:32:01 2006
@@ -18,13 +18,13 @@
public class DummyRequest implements HttpServletRequest {
Hashtable<String, String> headerNames;
-
+
public DummyRequest() {
headerNames = new Hashtable<String, String>();
headerNames.put("headerName1", "headerValue1");
headerNames.put("headerName2", "headerValue2");
}
-
+
public String getAuthType() {
return null;
}
@@ -35,7 +35,7 @@
public Cookie[] getCookies() {
Cookie cookie = new Cookie("testName", "testCookie");
- return new Cookie[] {cookie};
+ return new Cookie[] { cookie };
}
public long getDateHeader(String arg0) {
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyResponse.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyResponse.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/helpers/DummyResponse.java Tue Sep 19 10:32:01 2006
@@ -2,8 +2,9 @@
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.Hashtable;
+import java.util.HashMap;
import java.util.Locale;
+import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
@@ -11,19 +12,18 @@
public class DummyResponse implements HttpServletResponse {
- Hashtable<String, String> headerNames;
-
+ Map<String, String> headerMap;
public DummyResponse() {
- headerNames = new Hashtable<String, String>();
- headerNames.put("headerName1", "headerValue1");
- headerNames.put("headerName2", "headerValue2");
+ headerMap = new HashMap<String, String>();
+ headerMap.put("headerName1", "headerValue1");
+ headerMap.put("headerName2", "headerValue2");
}
-
+
public void addCookie(Cookie arg0) {
-
+
}
- public void addDateHeader(String arg0, long arg1) {
+ public void addDateHeader(String arg0, long arg1) {
}
public void addHeader(String arg0, String arg1) {
@@ -52,7 +52,7 @@
return null;
}
- public void sendError(int arg0) throws IOException {
+ public void sendError(int arg0) throws IOException {
}
public void sendError(int arg0, String arg1) throws IOException {
@@ -64,19 +64,19 @@
public void setDateHeader(String arg0, long arg1) {
}
- public void setHeader(String arg0, String arg1) {
+ public void setHeader(String arg0, String arg1) {
}
- public void setIntHeader(String arg0, int arg1) {
+ public void setIntHeader(String arg0, int arg1) {
}
- public void setStatus(int arg0) {
+ public void setStatus(int arg0) {
}
- public void setStatus(int arg0, String arg1) {
+ public void setStatus(int arg0, String arg1) {
}
- public void flushBuffer() throws IOException {
+ public void flushBuffer() throws IOException {
}
public int getBufferSize() {
@@ -110,10 +110,10 @@
public void reset() {
}
- public void resetBuffer() {
+ public void resetBuffer() {
}
- public void setBufferSize(int arg0) {
+ public void setBufferSize(int arg0) {
}
public void setCharacterEncoding(String arg0) {
@@ -122,10 +122,14 @@
public void setContentLength(int arg0) {
}
- public void setContentType(String arg0) {
+ public void setContentType(String arg0) {
}
public void setLocale(Locale arg0) {
}
+
+ public String getHeader(String key) {
+ return headerMap.get(key);
+ }
}
Modified: logback/trunk/pom.xml
==============================================================================
--- logback/trunk/pom.xml (original)
+++ logback/trunk/pom.xml Tue Sep 19 10:32:01 2006
@@ -85,7 +85,7 @@
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
- <version>6.0.0beta9</version>
+ <version>6.0.0</version>
</dependency>
<dependency>
@@ -97,7 +97,7 @@
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api-2.5</artifactId>
- <version>6.0.0beta9</version>
+ <version>6.0.0</version>
</dependency>
</dependencies>
1
0