logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sde...@apache.org
Subject svn commit: r1178304 [2/6] - in /logging/chainsaw/trunk: ./ src/main/java/org/apache/log4j/ src/main/java/org/apache/log4j/db/ src/main/java/org/apache/log4j/db/dialect/ src/main/java/org/apache/log4j/helpers/ src/main/java/org/apache/log4j/net/ src/ma...
Date Mon, 03 Oct 2011 06:15:43 GMT
Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/MySQLDialect.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/MySQLDialect.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/MySQLDialect.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/MySQLDialect.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.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: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/OracleDialect.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/OracleDialect.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/OracleDialect.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/OracleDialect.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.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: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/PostgreSQLDialect.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/PostgreSQLDialect.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/PostgreSQLDialect.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/PostgreSQLDialect.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.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: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/SQLDialect.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/SQLDialect.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/SQLDialect.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/SQLDialect.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.db.dialect;
+
+/**
+ * @author ceki
+ *
+ */
+public interface SQLDialect {
+  
+  public String getSelectInsertId();
+  
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/SybaseDialect.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/SybaseDialect.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/SybaseDialect.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/SybaseDialect.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.log4j.db.dialect; 
+
+/** 
+ * The Sybase dialect. 
+ * 
+*/ 
+public class SybaseDialect implements SQLDialect { 
+ public static final String SELECT_CURRVAL = "select @@identity"; 
+
+ public String getSelectInsertId() { 
+   return SELECT_CURRVAL; 
+ } 
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/Util.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/Util.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/Util.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/Util.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.db.dialect;
+
+import org.apache.log4j.db.ConnectionSource;
+import org.apache.log4j.spi.ComponentBase;
+
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+
+/**
+ * 
+ * @author Ceki Gulcu
+ *
+ */
+public class Util extends ComponentBase {
+  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", null).invoke(meta, null)).booleanValue();
+    } catch(Throwable e) {
+      getLogger().info("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) {
+      getLogger().info("Missing DatabaseMetaData.supportsBatchUpdates method.");
+      return false;
+    }
+  }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/db2.sql
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/db2.sql?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/db2.sql (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/db2.sql Mon Oct  3 06:15:40 2011
@@ -0,0 +1,64 @@
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You 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.
+#
+# 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: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/db2l.sql
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/db2l.sql?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/db2l.sql (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/db2l.sql Mon Oct  3 06:15:40 2011
@@ -0,0 +1,61 @@
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You 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.
+# 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: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/hsqldb.sql
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/hsqldb.sql?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/hsqldb.sql (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/hsqldb.sql Mon Oct  3 06:15:40 2011
@@ -0,0 +1,60 @@
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You 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.
+// 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: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/mssql.sql
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/mssql.sql?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/mssql.sql (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/mssql.sql Mon Oct  3 06:15:40 2011
@@ -0,0 +1,61 @@
+--  Licensed to the Apache Software Foundation (ASF) under one or more
+--  contributor license agreements.  See the NOTICE file distributed with
+--  this work for additional information regarding copyright ownership.
+--  The ASF licenses this file to You 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.
+--
+--
+-- 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: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/mysql.sql
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/mysql.sql?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/mysql.sql (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/mysql.sql Mon Oct  3 06:15:40 2011
@@ -0,0 +1,71 @@
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You 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.
+#
+#
+#
+# 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;

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/oracle.sql
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/oracle.sql?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/oracle.sql (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/oracle.sql Mon Oct  3 06:15:40 2011
@@ -0,0 +1,77 @@
+--  Licensed to the Apache Software Foundation (ASF) under one or more
+--  contributor license agreements.  See the NOTICE file distributed with
+--  this work for additional information regarding copyright ownership.
+--  The ASF licenses this file to You 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.
+--
+--
+-- 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
+-- Tested successfully on Oracle9i Release by Elias Ross
+
+-- 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    NUMBER(5),
+    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 OR REPLACE TRIGGER logging_event_id_seq_trig
+BEFORE INSERT ON logging_event
+FOR EACH ROW
+BEGIN
+   SELECT logging_event_id_seq.nextval
+   INTO :new.sequence_number FROM dual;
+END;
+
+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                NUMBER(5)  NOT NULL,
+    trace_line       VARCHAR2(254) NOT NULL,
+    PRIMARY KEY(event_id, i),
+    FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
+  );
+  

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/postgresql.sql
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/postgresql.sql?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/postgresql.sql (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/postgresql.sql Mon Oct  3 06:15:40 2011
@@ -0,0 +1,63 @@
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You 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.
+#
+## 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: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/package.html
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/package.html?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/package.html (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/package.html Mon Oct  3 06:15:40 2011
@@ -0,0 +1,36 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+
+<html>
+<body>
+
+<p>The org.apache.log4j.db package provides means to append logging events 
+into various databases. The persisted data can be later read back using
+{@link org.apache.log4j.db.DBReceiver}.
+</p>
+
+<p>Most popular database systems, such as PostgreSQL, MySQL, Oracle, DB2 and MsSQL
+are supported.
+</p>
+
+<p>Just as importantly, the way for obtaining JDBC connections is pluggable. Connections can
+be obtained through the tradinal way of DriverManager, or alternatively as a DataSource. 
+A DataSource can be instantiated directly or it can obtained through JNDI.
+</p>
+
+</body>
+</html>

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/Constants.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/Constants.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/Constants.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/Constants.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.helpers;
+
+
+/**
+ * Constants used internally throughout log4j.
+ *
+ */
+public interface Constants {
+
+    /**
+     * log4j package name string literal.
+     */
+  String LOG4J_PACKAGE_NAME = "org.apache.log4j";
+
+  /**
+   *  The name of the default repository is "default" (without the quotes).
+   */
+  String DEFAULT_REPOSITORY_NAME  = "default";
+
+    /**
+     * application string literal.
+     */
+  String APPLICATION_KEY = "application";
+    /**
+     * hostname string literal.
+     */
+  String HOSTNAME_KEY = "hostname";
+    /**
+     * receiver string literal.
+     */
+  String RECEIVER_NAME_KEY = "receiver";
+    /**
+     * log4jid string literal.
+     */
+  String LOG4J_ID_KEY = "log4jid";
+    /**
+     * time stamp pattern string literal.
+     */
+  String TIMESTAMP_RULE_FORMAT = "yyyy/MM/dd HH:mm:ss";
+
+  /**
+   * The default property file name for automatic configuration.
+   */
+  String DEFAULT_CONFIGURATION_FILE = "log4j.properties";
+  /**
+   * The default XML configuration file name for automatic configuration.
+   */
+  String DEFAULT_XML_CONFIGURATION_FILE = "log4j.xml";
+    /**
+     * log4j.configuration string literal.
+     */
+  String DEFAULT_CONFIGURATION_KEY = "log4j.configuration";
+    /**
+     * log4j.configuratorClass string literal.
+     */
+  String CONFIGURATOR_CLASS_KEY = "log4j.configuratorClass";
+
+    /**
+     * JNDI context name string literal.
+     */
+  String JNDI_CONTEXT_NAME = "java:comp/env/log4j/context-name";
+
+    /**
+     * TEMP_LIST_APPENDER string literal.
+     */
+  String TEMP_LIST_APPENDER_NAME = "TEMP_LIST_APPENDER";
+    /**
+     * TEMP_CONSOLE_APPENDER string literal.
+     */
+  String TEMP_CONSOLE_APPENDER_NAME = "TEMP_CONSOLE_APPENDER";
+    /**
+     * Codes URL string literal.
+     */
+  String CODES_HREF =
+          "http://logging.apache.org/log4j/docs/codes.html";
+
+
+    /**
+     * ABSOLUTE string literal.
+     */
+  String ABSOLUTE_FORMAT = "ABSOLUTE";
+    /**
+     * SimpleTimePattern for ABSOLUTE.
+     */
+  String ABSOLUTE_TIME_PATTERN = "HH:mm:ss,SSS";
+
+    /**
+     * SimpleTimePattern for ABSOLUTE.
+     */
+  String SIMPLE_TIME_PATTERN = "HH:mm:ss";
+
+    /**
+     * DATE string literal.
+     */
+  String DATE_AND_TIME_FORMAT = "DATE";
+    /**
+     * SimpleTimePattern for DATE.
+     */
+  String DATE_AND_TIME_PATTERN = "dd MMM yyyy HH:mm:ss,SSS";
+
+    /**
+     * ISO8601 string literal.
+     */
+  String ISO8601_FORMAT = "ISO8601";
+    /**
+     * SimpleTimePattern for ISO8601.
+     */
+  String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS";
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/MessageFormatter.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/MessageFormatter.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/MessageFormatter.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/MessageFormatter.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.helpers;
+
+
+/**
+ * Formats messages according to very simple rules.
+ * See {@link #format(String,Object)} and
+ * {@link #format(String,Object,Object)} for more details.
+ *
+ * @author Ceki G&uuml;lc&uuml;
+ */
+public final class MessageFormatter {
+    /**
+     * Private formatter since all methods and members are static.
+     */
+    private MessageFormatter() {
+        super();
+    }
+
+    /**
+     * Start of replacement block.
+     */
+    private static final char DELIM_START = '{';
+    /**
+     * End of replacement block.
+     */
+    private static final char DELIM_STOP = '}';
+
+    /**
+     * Performs single argument substitution for the 'messagePattern' passed as
+     * parameter.
+     * <p/>
+     * For example, <code>MessageFormatter.format("Hi {}.", "there");</code>
+     * will return the string "Hi there.".
+     * <p/>
+     * The {} pair is called the formatting element. It serves to designate the
+     * location where the argument needs to be inserted within the pattern.
+     *
+     * @param messagePattern
+     *     The message pattern which will be parsed and formatted
+     * @param argument
+     *     The argument to be inserted instead of the formatting element
+     * @return The formatted message
+     */
+    public static String format(final String messagePattern,
+                                final Object argument) {
+        int j = messagePattern.indexOf(DELIM_START);
+        int len = messagePattern.length();
+        char escape = 'x';
+
+        // if there are no { characters or { is the last character
+        // then we just return messagePattern
+        if (j == -1 || (j + 1 == len)) {
+            return messagePattern;
+        } else {
+            char delimStop = messagePattern.charAt(j + 1);
+            if (j > 0) {
+                escape = messagePattern.charAt(j - 1);
+            }
+            if ((delimStop != DELIM_STOP) || (escape == '\\')) {
+                // invalid DELIM_START/DELIM_STOP pair or espace character is
+                // present
+                return messagePattern;
+            } else {
+                StringBuffer sbuf = new StringBuffer(len + 20);
+                sbuf.append(messagePattern.substring(0, j));
+                sbuf.append(argument);
+                sbuf.append(messagePattern.substring(j + 2));
+                return sbuf.toString();
+            }
+        }
+    }
+
+    /**
+     * /**
+     * Performs a two argument substitution for the 'messagePattern' passed as
+     * parameter.
+     * <p/>
+     * For example, <code>MessageFormatter.format("Hi {}. My name is {}.",
+     * "there", "David");</code> will return the string
+     * "Hi there. My name is David.".
+     * <p/>
+     * The '{}' pair is called a formatting element. It serves to designate the
+     * location where the arguments need to be inserted within
+     * the message pattern.
+     *
+     * @param messagePattern
+     *     The message pattern which will be parsed and formatted
+     * @param arg1
+     *     The first argument to replace the first formatting element
+     * @param arg2
+     *     The second argument to replace the second formatting element
+     * @return The formatted message
+     */
+    public static String format(final String messagePattern,
+                                final Object arg1,
+                                final Object arg2) {
+        int i = 0;
+        int len = messagePattern.length();
+
+        StringBuffer sbuf = new StringBuffer(messagePattern.length() + 50);
+
+        for (int l = 0; l < 2; l++) {
+            int j = messagePattern.indexOf(DELIM_START, i);
+
+            if (j == -1 || (j + 1 == len)) {
+                // no more variables
+                if (i == 0) { // this is a simple string
+                    return messagePattern;
+                } else {
+                    // add the tail string which contains no variables
+                    // and return the result.
+                    sbuf.append(messagePattern.substring(i,
+                                    messagePattern.length()));
+                    return sbuf.toString();
+                }
+            } else {
+                char delimStop = messagePattern.charAt(j + 1);
+                if ((delimStop != DELIM_STOP)) {
+                    // invalid DELIM_START/DELIM_STOP pair
+                    sbuf.append(messagePattern.substring(i,
+                            messagePattern.length()));
+                    return sbuf.toString();
+                }
+                sbuf.append(messagePattern.substring(i, j));
+                if (l == 0) {
+                    sbuf.append(arg1);
+                } else {
+                    sbuf.append(arg2);
+                }
+                i = j + 2;
+            }
+        }
+        // append the characters following the second {} pair.
+        sbuf.append(messagePattern.substring(i, messagePattern.length()));
+        return sbuf.toString();
+    }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/AddressBased.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/AddressBased.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/AddressBased.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/AddressBased.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.net;
+
+
+/**
+ * Net based entities that 'work with' an Address
+ * should consider implementing this
+ * interface so that they can be treated generically.
+ *
+ * @author Paul Smith (psmith@apache.org)
+ *
+ */
+public interface AddressBased extends NetworkBased {
+  /**
+   * Returns a String representation of the Address this instance
+   * encompasses.
+   * @return String representation of the Address
+   */
+  String getAddress();
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/JMSReceiver.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/JMSReceiver.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/JMSReceiver.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/JMSReceiver.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.net;
+
+import java.io.FileInputStream;
+import java.util.Properties;
+
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.TopicConnection;
+import javax.jms.Topic;
+import javax.jms.TopicConnectionFactory;
+import javax.jms.TopicSubscriber;
+import javax.jms.Session;
+import javax.jms.TopicSession;
+import javax.jms.ObjectMessage;
+
+import javax.naming.InitialContext;
+import javax.naming.Context;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.plugins.Plugin;
+import org.apache.log4j.plugins.Receiver;
+
+/**
+  JMSReceiver receives a remote logging event on a configured
+  JSM topic and "posts" it to a LoggerRepository as if the event was 
+  generated locally. This class is designed to receive events from 
+  the JMSAppender class (or classes that send compatible events).
+  
+  <p>Once the event has been "posted", it will be handled by the 
+  appenders currently configured in the LoggerRespository.
+  
+  <p>This implementation borrows heavily from the JMSSink
+  implementation.
+  
+  @author Mark Womack
+  @author Paul Smith
+  @author Stephen Pain
+*/
+public class JMSReceiver extends Receiver implements MessageListener {
+
+  private boolean active = false;
+
+  protected String topicFactoryName;
+  protected String topicName;
+  protected String userId;
+  protected String password;
+  protected TopicConnection topicConnection;
+  protected String jndiPath;
+  
+  private String remoteInfo;
+  private String providerUrl;
+
+  public JMSReceiver() { }
+
+  public JMSReceiver(String _topicFactoryName, String _topicName,
+          String _userId, String _password, String _jndiPath) {      
+      topicFactoryName = _topicFactoryName;
+      topicName = _topicName;
+      userId = _userId;
+      password = _password;
+      jndiPath = _jndiPath;
+  }
+
+  /**
+         * Sets the path to a properties file containing
+         * the initial context and jndi provider url
+         */
+    public void setJndiPath(String _jndiPath) {
+          jndiPath = _jndiPath;
+    }
+  
+     /**
+         * Gets the path to a properties file containing
+         * the initial context and jndi provider url
+         */
+     public String getJndiPath() {
+          return jndiPath;
+     }
+  
+  /**
+    Sets the JMS topic factory name to use when creating the 
+    JMS connection. */
+  public void setTopicFactoryName(String _topicFactoryName) {
+    topicFactoryName = _topicFactoryName;
+  }
+  
+  /**
+    Gets the curernt JMS topic factory name property. */
+  public String getTopicFactoryName() {
+    return topicFactoryName;
+  }
+  
+  /**
+   * Sets the JMS topic name to use when creating the
+   * JMS connection.
+   */
+  public void setTopicName(String _topicName) {
+    topicName = _topicName;
+  }
+  
+  /**
+   * Gets the curernt JMS topic name property.
+   */
+  public String getTopicName() {
+    return topicName;
+  }
+
+  /**
+    Sets the user id to use when creating the 
+    JMS connection. */
+  public void setUserId(String _userId) {
+    userId = _userId;
+  }
+  
+  /**
+   * Gets the current user id property.
+   */
+  public String getUserId() {
+    return userId;
+  }
+
+  /**
+   * Sets the password to use when creating the
+   * JMS connection.
+   */
+  public void setPassword(String _password) {
+    password = _password;
+  }
+  
+  /**
+   * Gets the curernt password property.
+   */
+  public String getPassword() {
+    return password;
+  }
+ 
+  /**
+   * Returns true if the receiver is the same class and they are
+   * configured for the same properties, and super class also considers
+   * them to be equivalent. This is used by PluginRegistry when determining
+   * if the a similarly configured receiver is being started.
+   * 
+   * @param testPlugin The plugin to test equivalency against.
+   * @return boolean True if the testPlugin is equivalent to this plugin.
+   */
+  public boolean isEquivalent(Plugin testPlugin) {
+    // only do full check if an instance of this class
+    if (testPlugin instanceof JMSReceiver) {
+ 
+      JMSReceiver receiver = (JMSReceiver)testPlugin;
+      
+      // check for same topic name and super class equivalency
+      return (
+            topicFactoryName.equals(receiver.getTopicFactoryName()) && 
+            (jndiPath == null || jndiPath.equals(receiver.getJndiPath())) && 
+            super.isEquivalent(testPlugin)
+            );
+    }
+    
+    return false;
+  }
+  
+  /**
+    Returns true if this receiver is active. */
+  public synchronized boolean isActive() {
+    return active;
+  }
+  
+  /**
+    Sets the flag to indicate if receiver is active or not. */
+  protected synchronized void setActive(boolean _active) {
+    active = _active;
+  }
+  
+  /**
+    Starts the JMSReceiver with the current options. */
+  public void activateOptions() {
+    if (!isActive()) {
+      try {
+        remoteInfo = topicFactoryName + ":" + topicName;
+
+        Context ctx = null;
+        if (jndiPath == null || jndiPath.equals("")) {
+                ctx = new InitialContext();
+        } else {
+                FileInputStream is = new FileInputStream(jndiPath);
+                Properties p = new Properties();
+                p.load(is);
+                is.close();
+                ctx = new InitialContext(p);
+        }
+
+        // give some more flexibility about the choice of a tab name
+        providerUrl = (String)ctx.getEnvironment().get(Context.PROVIDER_URL);
+        TopicConnectionFactory topicConnectionFactory;
+        topicConnectionFactory = 
+          (TopicConnectionFactory) lookup(ctx, topicFactoryName);
+        
+        if (userId != null && password != null) {
+          topicConnection =
+    	       topicConnectionFactory.createTopicConnection(userId, password);
+        } else {
+          topicConnection =
+    	       topicConnectionFactory.createTopicConnection();
+        }
+  	       
+        TopicSession topicSession =
+          topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
+  
+        Topic topic = (Topic)ctx.lookup(topicName);
+  
+        TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic);
+      
+        topicSubscriber.setMessageListener(this);
+ 
+        topicConnection.start();
+ 
+        setActive(true);
+      } catch(Exception e) {
+        setActive(false);
+        if (topicConnection != null) {
+          try {
+            topicConnection.close();
+          } catch (Exception e2) {
+            // do nothing
+          }
+          topicConnection = null;
+        }
+        getLogger().error("Could not start JMSReceiver.", e);
+      }
+    }
+  }
+  
+  /**
+    Called when the receiver should be stopped. */
+  public synchronized void shutdown() {
+    if (isActive()) {
+      // mark this as no longer running
+      setActive(false);
+    
+      if (topicConnection != null) {
+        try {
+          topicConnection.close();
+        } catch (Exception e) {
+          // do nothing
+        }
+        topicConnection = null;
+      }
+    }
+  }
+
+  public void onMessage(Message message) {
+    try {
+      if(message instanceof  ObjectMessage) {
+        // get the logging event and post it to the repository
+      	ObjectMessage objectMessage = (ObjectMessage) message;
+      	LoggingEvent event = (LoggingEvent) objectMessage.getObject();
+      	
+      	// store the known remote info in an event property
+      	event.setProperty("log4j.remoteSourceInfo", remoteInfo);
+        event.setProperty("log4j.jmsProviderUrl", providerUrl);
+        
+      	doPost(event);
+      } else {
+      	getLogger().warn("Received message is of type "+message.getJMSType()
+		    +", was expecting ObjectMessage.");
+      }      
+    } catch(Exception e) {
+      getLogger().error("Exception thrown while processing incoming message.", e);
+    }
+  }
+
+  protected Object lookup(Context ctx, String name) throws NamingException {
+    try {
+      return ctx.lookup(name);
+    } catch(NameNotFoundException e) {
+      getLogger().error("Could not find name ["+name+"].");
+      throw e;
+    }
+  }
+
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/JMSReceiverBeanInfo.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/JMSReceiverBeanInfo.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/JMSReceiverBeanInfo.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/JMSReceiverBeanInfo.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.net;
+
+import java.beans.PropertyDescriptor;
+import java.beans.SimpleBeanInfo;
+
+
+/**
+ * BeanInfo class for the JMSReceiver.
+ *
+ * @author Paul Smith <psmith@apache.org>
+ *
+ */
+public class JMSReceiverBeanInfo extends SimpleBeanInfo {
+
+    /* (non-Javadoc)
+     * @see java.beans.BeanInfo#getPropertyDescriptors()
+     */
+    public PropertyDescriptor[] getPropertyDescriptors() {
+
+        try {
+
+            return new PropertyDescriptor[] {
+                new PropertyDescriptor("name", JMSReceiver.class),
+                new PropertyDescriptor("topicFactoryName", JMSReceiver.class),
+                new PropertyDescriptor("topicName", JMSReceiver.class),
+                new PropertyDescriptor("threshold", JMSReceiver.class),
+                new PropertyDescriptor("jndiPath", JMSReceiver.class),
+                new PropertyDescriptor("userId",
+                        JMSReceiver.class),
+            };
+        } catch (Exception e) {
+        }
+
+        return null;
+    }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastAppender.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastAppender.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastAppender.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastAppender.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,345 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.net;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.helpers.Constants;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.xml.XMLLayout;
+
+
+/**
+ *  Multicast-based Appender.  Works in conjunction with the MulticastReceiver, which expects
+ *  a LoggingEvent encoded using XMLLayout. 
+ * 
+ *  Sends log information as a multicast datagrams.
+ *
+ *  <p>Messages are not sent as LoggingEvent objects but as text after
+ *  applying XMLLayout.
+ *
+ *  <p>The port and remoteHost properties can be set in configuration properties.
+ *  By setting the remoteHost to a broadcast address any number of clients can
+ *  listen for log messages.
+ *
+ *  <p>This was inspired and really extended/copied from {@link SocketAppender}.  Please
+ *  see the docs for the proper credit to the authors of that class.
+ *
+ *  @author  <a href="mailto:kbrown@versatilesolutions.com">Kevin Brown</a>
+ *  @author Scott Deboy <sdeboy@apache.org>
+ * 
+ */
+public class MulticastAppender extends AppenderSkeleton implements PortBased {
+  /**
+     The default port number for the multicast packets. (9991).
+  */
+  static final int DEFAULT_PORT = 9991;
+
+  /**
+   * The MulticastDNS zone advertised by a MulticastAppender
+   * the MulticastAppender also adds a 'multicastAddress' property with the multicast address value as a string
+   */
+  public static final String ZONE = "_log4j_xml_mcast_appender.local.";
+
+  /**
+     We remember host name as String in addition to the resolved
+     InetAddress so that it can be returned via getOption().
+  */
+  String hostname;
+  String remoteHost;
+  String application;
+  int timeToLive;
+  InetAddress address;
+  int port = DEFAULT_PORT;
+  MulticastSocket outSocket;
+  private String encoding;
+
+  private boolean locationInfo = false;
+  private boolean advertiseViaMulticastDNS;
+  private ZeroConfSupport zeroConf;
+
+  public MulticastAppender() {
+     super(false);
+  }
+
+  /**
+     Open the multicast sender for the <b>RemoteHost</b> and <b>Port</b>.
+  */
+  public void activateOptions() {
+    try {
+      hostname = InetAddress.getLocalHost().getHostName();
+    } catch (UnknownHostException uhe) {
+      try {
+        hostname = InetAddress.getLocalHost().getHostAddress();
+      } catch (UnknownHostException uhe2) {
+        hostname = "unknown";
+      }
+    }
+
+    //allow system property of application to be primary
+    if (application == null) {
+      application = System.getProperty(Constants.APPLICATION_KEY);
+    } else {
+      if (System.getProperty(Constants.APPLICATION_KEY) != null) {
+        application = application + "-" + System.getProperty(Constants.APPLICATION_KEY);
+      }
+    }
+
+    if(remoteHost != null) {
+      address = getAddressByName(remoteHost);
+    } else {
+      String err = "The RemoteHost property is required for MulticastAppender named "+ name;
+      LogLog.error(err);
+      throw new IllegalStateException(err);
+    }
+
+    if (layout == null) {
+        layout = new XMLLayout();
+    }
+      
+    if (advertiseViaMulticastDNS) {
+        Map properties = new HashMap();
+        properties.put("multicastAddress", remoteHost);
+        zeroConf = new ZeroConfSupport(ZONE, port, getName(), properties);
+        zeroConf.advertise();
+    }
+    connect();
+    super.activateOptions();
+  }
+
+  /**
+     Close this appender.
+     <p>This will mark the appender as closed and
+     call then {@link #cleanUp} method.
+  */
+  public synchronized void close() {
+    if (closed) {
+      return;
+    }
+
+    this.closed = true;
+    if (advertiseViaMulticastDNS) {
+        zeroConf.unadvertise();
+    }
+    cleanUp();
+  }
+
+  /**
+     Close the Socket and release the underlying
+     connector thread if it has been created
+   */
+  public void cleanUp() {
+    if (outSocket != null) {
+      try {
+        outSocket.close();
+      } catch (Exception e) {
+        LogLog.error("Could not close outSocket.", e);
+      }
+
+      outSocket = null;
+    }
+  }
+
+  void connect() {
+    if (this.address == null) {
+      return;
+    }
+
+    try {
+      // First, close the previous connection if any.
+      cleanUp();
+      outSocket = new MulticastSocket();
+      outSocket.setTimeToLive(timeToLive);
+    } catch (IOException e) {
+      LogLog.error("Error in connect method of MulticastAppender named "+name, e);
+    }
+  }
+
+  public void append(LoggingEvent event) {
+    if (event == null) {
+      return;
+    }
+
+    if(locationInfo) {
+	   event.getLocationInformation();
+	}
+
+    if (outSocket != null) {
+        event.setProperty(Constants.HOSTNAME_KEY, hostname);
+
+        if (application != null) {
+          event.setProperty(Constants.APPLICATION_KEY, application);
+        }
+      
+		if(locationInfo) {
+		   event.getLocationInformation();
+		}
+
+
+      try {
+        StringBuffer buf = new StringBuffer(layout.format(event));
+
+        byte[] payload;
+        if(encoding == null) {
+          payload = buf.toString().getBytes();
+        } else {
+          payload = buf.toString().getBytes(encoding);
+        }
+
+        DatagramPacket dp =
+           new DatagramPacket(payload, payload.length, address, port);
+        outSocket.send(dp);
+      } catch (IOException e) {
+        outSocket = null;
+        LogLog.warn("Detected problem with Multicast connection: " + e);
+      }
+    }
+  }
+
+  InetAddress getAddressByName(String host) {
+    try {
+      return InetAddress.getByName(host);
+    } catch (Exception e) {
+      LogLog.error("Could not find address of [" + host + "].", e);
+      return null;
+    }
+  }
+
+  /**
+     The <b>RemoteHost</b> option takes a string value which should be
+     the host name or ipaddress to send the multicast packets.
+   */
+  public void setRemoteHost(String host) {
+    remoteHost = host;
+  }
+
+  /**
+     Returns value of the <b>RemoteHost</b> option.
+   */
+  public String getRemoteHost() {
+    return remoteHost;
+  }
+
+  /**
+  The <b>LocationInfo</b> option takes a boolean value. If true,
+  the information sent to the remote host will include location
+  information. By default no location information is sent to the server.
+   */
+  public void setLocationInfo(boolean locationInfo) {
+	  this.locationInfo = locationInfo;
+  }
+
+  /**
+   * Returns value of the <b>LocationInfo</b> option.
+   */
+  public boolean getLocationInfo() {
+	  return locationInfo;
+  }
+
+  /**
+      The <b>Encoding</b> option specifies how the bytes are encoded.  If this option is not specified, 
+      the System encoding is used.
+    */
+   public void setEncoding(String encoding) {
+     this.encoding = encoding;
+   }
+
+   /**
+      Returns value of the <b>Encoding</b> option.
+    */
+   public String getEncoding() {
+     return encoding;
+   }
+  /**
+     The <b>App</b> option takes a string value which should be the name of the application getting logged.
+     If property was already set (via system property), don't set here.
+   */
+  public void setApplication(String app) {
+    this.application = app;
+  }
+
+  /**
+     Returns value of the <b>App</b> option.
+   */
+  public String getApplication() {
+    return application;
+  }
+
+  /**
+     The <b>Time to live</b> option takes a positive integer representing
+     the time to live value.
+   */
+  public void setTimeToLive(int timeToLive) {
+    this.timeToLive = timeToLive;
+  }
+
+  /**
+     Returns value of the <b>Time to Live</b> option.
+   */
+  public int getTimeToLive() {
+    return timeToLive;
+  }
+
+  /**
+     The <b>Port</b> option takes a positive integer representing
+     the port where multicast packets will be sent.
+   */
+  public void setPort(int port) {
+    this.port = port;
+  }
+
+  /**
+     Returns value of the <b>Port</b> option.
+   */
+  public int getPort() {
+    return port;
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.log4j.net.NetworkBased#isActive()
+   */
+  public boolean isActive() {
+    // TODO handle active/inactive
+    return true;
+  }
+
+    /**
+     * Gets whether appender requires a layout.
+     * @return false
+     */
+  public boolean requiresLayout() {
+      return true;
+  }
+
+  public boolean isAdvertiseViaMulticastDNS() {
+      return advertiseViaMulticastDNS;
+  }
+
+  public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
+      this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
+  }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastReceiver.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastReceiver.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastReceiver.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastReceiver.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.net;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.plugins.Pauseable;
+import org.apache.log4j.plugins.Receiver;
+import org.apache.log4j.spi.Decoder;
+import org.apache.log4j.spi.LoggingEvent;
+
+
+/**
+ *  Multicast-based receiver.  Accepts LoggingEvents encoded using
+ *  MulticastAppender and XMLLayout. The the XML data is converted
+ *  back to a LoggingEvent and is posted.
+ *
+ *  @author Scott Deboy <sdeboy@apache.org>
+ *
+ */
+public class MulticastReceiver extends Receiver implements PortBased,
+  AddressBased, Pauseable {
+  private static final int PACKET_LENGTH = 16384;
+  private int port;
+  private String address;
+  private String encoding;
+  private MulticastSocket socket = null;
+
+  //default to log4j xml decoder
+  private String decoder = "org.apache.log4j.xml.XMLDecoder";
+  private Decoder decoderImpl;
+  private MulticastHandlerThread handlerThread;
+  private MulticastReceiverThread receiverThread;
+  private boolean paused;
+  private boolean advertiseViaMulticastDNS;
+  private ZeroConfSupport zeroConf;
+
+  /**
+   * The MulticastDNS zone advertised by a MulticastReceiver
+   */
+  public static final String ZONE = "_log4j_xml_mcast_receiver.local.";
+
+  public String getDecoder() {
+    return decoder;
+  }
+
+  public void setDecoder(String decoder) {
+    this.decoder = decoder;
+  }
+
+  public int getPort() {
+    return port;
+  }
+
+  public void setPort(int port) {
+    this.port = port;
+  }
+
+  public String getAddress() {
+    return address;
+  }
+
+  /**
+      The <b>Encoding</b> option specifies how the bytes are encoded.  If this option is not specified,
+      the system encoding will be used.
+    */
+  public void setEncoding(String encoding) {
+    this.encoding = encoding;
+  }
+
+  /**
+     Returns value of the <b>Encoding</b> option.
+   */
+  public String getEncoding() {
+    return encoding;
+  }
+
+  public synchronized void shutdown() {
+    active = false;
+    if (advertiseViaMulticastDNS) {
+        zeroConf.unadvertise();
+    }
+    if (handlerThread != null) {
+        handlerThread.interrupt();
+    }
+    if (receiverThread != null) {
+        receiverThread.interrupt();
+    }
+    if (socket != null) {
+        socket.close();
+    }
+  }
+
+  public void setAddress(String address) {
+    this.address = address;
+  }
+
+  public boolean isPaused() {
+    return paused;
+  }
+
+  public void setPaused(boolean b) {
+    paused = b;
+  }
+
+  public void activateOptions() {
+    InetAddress addr = null;
+
+    try {
+      Class c = Class.forName(decoder);
+      Object o = c.newInstance();
+
+      if (o instanceof Decoder) {
+        this.decoderImpl = (Decoder) o;
+      }
+    } catch (ClassNotFoundException cnfe) {
+      getLogger().warn("Unable to find decoder", cnfe);
+    } catch (IllegalAccessException iae) {
+      getLogger().warn("Could not construct decoder", iae);
+    } catch (InstantiationException ie) {
+      getLogger().warn("Could not construct decoder", ie);
+    }
+
+    try {
+      addr = InetAddress.getByName(address);
+    } catch (UnknownHostException uhe) {
+      uhe.printStackTrace();
+    }
+
+    try {
+      active = true;
+      socket = new MulticastSocket(port);
+      socket.joinGroup(addr);
+      receiverThread = new MulticastReceiverThread();
+      receiverThread.start();
+      handlerThread = new MulticastHandlerThread();
+      handlerThread.start();
+      if (advertiseViaMulticastDNS) {
+        zeroConf = new ZeroConfSupport(ZONE, port, getName());
+        zeroConf.advertise();
+      }
+
+    } catch (IOException ioe) {
+      ioe.printStackTrace();
+    }
+  }
+
+    public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
+        this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
+    }
+
+    public boolean isAdvertiseViaMulticastDNS() {
+        return advertiseViaMulticastDNS;
+    }
+
+    class MulticastHandlerThread extends Thread {
+    private List list = new ArrayList();
+
+    public MulticastHandlerThread() {
+      setDaemon(true);
+    }
+
+    public void append(String data) {
+      synchronized (list) {
+        list.add(data);
+        list.notify();
+      }
+    }
+
+    public void run() {
+      ArrayList list2 = new ArrayList();
+
+      while (isAlive()) {
+        synchronized (list) {
+          try {
+            while (list.size() == 0) {
+              list.wait();
+            }
+
+            if (list.size() > 0) {
+              list2.addAll(list);
+              list.clear();
+            }
+          } catch (InterruptedException ie) {
+          }
+        }
+
+        if (list2.size() > 0) {
+          Iterator iter = list2.iterator();
+
+          while (iter.hasNext()) {
+            String data = (String) iter.next();
+            List v = decoderImpl.decodeEvents(data.trim());
+
+            if (v != null) {
+              Iterator eventIter = v.iterator();
+
+              while (eventIter.hasNext()) {
+                if (!isPaused()) {
+                  doPost((LoggingEvent) eventIter.next());
+                }
+              }
+            }
+          }
+
+          list2.clear();
+        } else {
+          try {
+            synchronized (this) {
+              wait(1000);
+            }
+          } catch (InterruptedException ie) {
+          }
+        }
+      }
+    }
+  }
+
+  class MulticastReceiverThread extends Thread {
+    public MulticastReceiverThread() {
+      setDaemon(true);
+    }
+
+    public void run() {
+      active = true;
+
+      byte[] b = new byte[PACKET_LENGTH];
+      DatagramPacket p = new DatagramPacket(b, b.length);
+
+      while (active) {
+        try {
+          socket.receive(p);
+
+          //this string constructor which accepts a charset throws an exception if it is 
+          //null
+            if (encoding == null) {
+            handlerThread.append(
+              new String(p.getData(), 0, p.getLength()));
+          } else {
+            handlerThread.append(
+              new String(p.getData(), 0, p.getLength(), encoding));
+          }
+        } catch (SocketException se) {
+          //disconnected
+        } catch (IOException ioe) {
+          ioe.printStackTrace();
+        }
+      }
+
+      getLogger().debug("{}'s thread is ending.", MulticastReceiver.this.getName());
+    }
+  }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastReceiverBeanInfo.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastReceiverBeanInfo.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastReceiverBeanInfo.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastReceiverBeanInfo.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.net;
+
+import java.beans.PropertyDescriptor;
+import java.beans.SimpleBeanInfo;
+
+
+/**
+ * BeanInfo class for the meta-data of the MulticastReceiver.
+ *
+ * @author Paul Smith <psmith@apache.org>
+ *
+ */
+public class MulticastReceiverBeanInfo extends SimpleBeanInfo {
+
+    /* (non-Javadoc)
+     * @see java.beans.BeanInfo#getPropertyDescriptors()
+     */
+    public PropertyDescriptor[] getPropertyDescriptors() {
+
+        try {
+
+            return new PropertyDescriptor[] {
+                new PropertyDescriptor("name", MulticastReceiver.class),
+                new PropertyDescriptor("address", MulticastReceiver.class),
+                new PropertyDescriptor("port", MulticastReceiver.class),
+                new PropertyDescriptor("threshold", MulticastReceiver.class),
+                new PropertyDescriptor("decoder", MulticastReceiver.class),
+                new PropertyDescriptor("advertiseViaMulticastDNS", MulticastReceiver.class),
+            };
+        } catch (Exception e) {
+        }
+
+        return null;
+    }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/NetworkBased.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/NetworkBased.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/NetworkBased.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/NetworkBased.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.net;
+
+/**
+ * The parent of all the Network based interfaces.
+ *
+ * @author Paul Smith (psmith@apache.org)
+ *
+ */
+public interface NetworkBased {
+
+    /**
+     * Get name.
+     * @return name.
+     */
+  String getName();
+
+    /**
+     * Get if item is active.
+     * @return if true, item is active.
+     */
+  boolean isActive();
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/PortBased.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/PortBased.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/PortBased.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/PortBased.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j.net;
+
+
+/**
+ * Net based entities that 'work with' a Port should consider implementing this
+ * interface so that they can be treated generically.
+ *
+ * @author Paul Smith (psmith@apache.org)
+ *
+ */
+public interface PortBased extends NetworkBased {
+  /**
+   * Returns the Port # that this net based thing is using.
+   * @return int port number
+   */
+  int getPort();
+}



Mime
View raw message