logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From grobme...@apache.org
Subject svn commit: r1345524 [10/17] - in /logging/log4j/branches/log4j12-bz53299: ./ contribs/ contribs/CekiGulcu/ contribs/EirikLygre/ contribs/JamesHouse/ contribs/Jamie Tsao/ contribs/JimMoore/ contribs/KevinSteppe/ contribs/KitchingSimon/ contribs/LeosLit...
Date Sat, 02 Jun 2012 15:36:26 GMT
Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/JDBCLogger.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/JDBCLogger.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/JDBCLogger.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/JDBCLogger.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,421 @@
+/*
+ * 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.sql.*;
+import java.util.*;
+import org.apache.log4j.*;
+import org.apache.log4j.helpers.*;
+import org.apache.log4j.spi.*;
+
+
+/**
+This class encapsulate the logic which is necessary to log into a table.
+Used by JDBCAppender
+
+<p><b>Author : </b><A HREF="mailto:t.fenner@klopotek.de">Thomas Fenner</A></p>
+
+@since 1.0
+*/
+public class JDBCLogger
+{
+	//All columns of the log-table
+	private ArrayList logcols = null;
+   //Only columns which will be provided by logging
+   private String column_list = null;
+   //Number of all columns
+	private int num = 0;
+   //Status for successful execution of method configure()
+	private boolean isconfigured = false;
+   //Status for ready to do logging with method append()
+	private boolean ready = false;
+   //This message will be filled with a error-string when method ready() failes, and can be got by calling getMsg()
+   private String errormsg = "";
+
+	private Connection con = null;
+	private Statement stmt = null;
+	private ResultSet rs = null;
+   private String table = null;
+
+   //Variables for static SQL-statement logging
+   private String sql = null;
+	private String new_sql = null;
+   private String new_sql_part1 = null;
+   private String new_sql_part2 = null;
+   private static final String msg_wildcard = "@MSG@";
+	private int msg_wildcard_pos = 0;
+
+	/**
+	Writes a message into the database table.
+	Throws an exception, if an database-error occurs !
+	*/
+	public void append(String _msg) throws Exception
+	{
+		if(!ready) if(!ready()) throw new Exception("JDBCLogger::append(), Not ready to append !");
+
+      if(sql != null)
+      {
+      	appendSQL(_msg);
+         return;
+      }
+
+		LogColumn logcol;
+
+		rs.moveToInsertRow();
+
+		for(int i=0; i<num; i++)
+		{
+        	logcol = (LogColumn)logcols.get(i);
+
+			if(logcol.logtype == LogType.MSG)
+			{
+				rs.updateObject(logcol.name, _msg);
+			}
+			else if(logcol.logtype == LogType.ID)
+			{
+				rs.updateObject(logcol.name, logcol.idhandler.getID());
+			}
+			else if(logcol.logtype == LogType.STATIC)
+			{
+				rs.updateObject(logcol.name, logcol.value);
+			}
+			else if(logcol.logtype == LogType.TIMESTAMP)
+			{
+				rs.updateObject(logcol.name, new Timestamp((new java.util.Date()).getTime()));
+			}
+		}
+
+		rs.insertRow();
+	}
+
+	/**
+	Writes a message into the database using a given sql-statement.
+	Throws an exception, if an database-error occurs !
+	*/
+	public void appendSQL(String _msg) throws Exception
+	{
+		if(!ready) if(!ready()) throw new Exception("JDBCLogger::appendSQL(), Not ready to append !");
+
+      if(sql == null) throw new Exception("JDBCLogger::appendSQL(), No SQL-Statement configured !");
+
+      if(msg_wildcard_pos > 0)
+      {
+			new_sql = new_sql_part1 + _msg + new_sql_part2;
+      }
+		else new_sql = sql;
+
+      try
+      {
+			stmt.executeUpdate(new_sql);
+      }
+      catch(Exception e)
+      {
+      	errormsg = new_sql;
+         throw e;
+		}
+	}
+
+
+	/**
+	Configures this class, by reading in the structure of the log-table
+	Throws an exception, if an database-error occurs !
+	*/
+	public void configureTable(String _table) throws Exception
+	{
+   	if(isconfigured) return;
+
+		//Fill logcols with META-informations of the table-columns
+		stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
+		rs = stmt.executeQuery("SELECT * FROM " + _table + " WHERE 1 = 2");
+
+		LogColumn logcol;
+
+		ResultSetMetaData rsmd = rs.getMetaData();
+
+		num = rsmd.getColumnCount();
+
+		logcols = new ArrayList(num);
+
+		for(int i=1; i<=num; i++)
+		{
+			logcol = new LogColumn();
+			logcol.name = rsmd.getColumnName(i).toUpperCase();
+			logcol.type = rsmd.getColumnTypeName(i);
+			logcol.nullable = (rsmd.isNullable(i) == rsmd.columnNullable);
+         logcol.isWritable = rsmd.isWritable(i);
+         if(!logcol.isWritable) logcol.ignore = true;
+         logcols.add(logcol);
+		}
+
+      table = _table;
+
+		isconfigured = true;
+	}
+
+	/**
+	Configures this class, by storing and parsing the given sql-statement.
+	Throws an exception, if somethings wrong !
+	*/
+	public void configureSQL(String _sql) throws Exception
+	{
+   	if(isconfigured) return;
+
+		if(!isConnected()) throw new Exception("JDBCLogger::configureSQL(), Not connected to database !");
+
+		if(_sql == null || _sql.trim().equals("")) throw new Exception("JDBCLogger::configureSQL(), Invalid SQL-Statement !");
+
+		sql = _sql.trim();
+
+      stmt = con.createStatement();
+
+		msg_wildcard_pos = sql.indexOf(msg_wildcard);
+
+      if(msg_wildcard_pos > 0)
+      {
+			new_sql_part1 = sql.substring(0, msg_wildcard_pos-1) + "'";
+         //between the message...
+         new_sql_part2 = "'" + sql.substring(msg_wildcard_pos+msg_wildcard.length());
+		}
+
+		isconfigured = true;
+	}
+
+	/**
+   Sets a connection. Throws an exception, if the connection is not open !
+	*/
+	public void setConnection(Connection _con) throws Exception
+	{
+		con = _con;
+
+		if(!isConnected()) throw new Exception("JDBCLogger::setConnection(), Given connection isnt connected to database !");
+	}
+
+
+	/**
+	Sets a columns logtype (LogTypes) and value, which depends on that logtype.
+	Throws an exception, if the given arguments arent correct !
+   */
+	public void setLogType(String _name, int _logtype, Object _value) throws Exception
+	{
+		if(!isconfigured) throw new Exception("JDBCLogger::setLogType(), Not configured !");
+
+		//setLogType() makes only sense for further configuration of configureTable()
+      if(sql != null) return;
+
+      _name = _name.toUpperCase();
+
+		if(_name == null || !(_name.trim().length() > 0)) throw new Exception("JDBCLogger::setLogType(), Missing argument name !");
+		if(!LogType.isLogType(_logtype)) throw new Exception("JDBCLogger::setLogType(), Invalid logtype '" + _logtype + "' !");
+		if((_logtype != LogType.MSG && _logtype != LogType.EMPTY) && _value == null) throw new Exception("JDBCLogger::setLogType(), Missing argument value !");
+
+  		LogColumn logcol;
+
+		for(int i=0; i<num; i++)
+		{
+        	logcol = (LogColumn)logcols.get(i);
+
+			if(logcol.name.equals(_name))
+			{
+         	if(!logcol.isWritable) throw new Exception("JDBCLogger::setLogType(), Column " + _name + " is not writeable !");
+
+				//Column gets the message
+				if(_logtype == LogType.MSG)
+            {
+            	logcol.logtype = _logtype;
+               return;
+				}
+				//Column will be provided by JDBCIDHandler::getID()
+				else if(_logtype == LogType.ID)
+				{
+					logcol.logtype = _logtype;
+
+               try
+               {
+               	//Try to cast directly Object to JDBCIDHandler
+						logcol.idhandler = (JDBCIDHandler)_value;
+               }
+               catch(Exception e)
+               {
+               	try
+                  {
+                  	//Assuming _value is of class string which contains the classname of a JDBCIDHandler
+							logcol.idhandler = (JDBCIDHandler)(Class.forName((String)_value).newInstance());
+                  }
+                  catch(Exception e2)
+                  {
+							throw new Exception("JDBCLogger::setLogType(), Cannot cast value of class " + _value.getClass() + " to class JDBCIDHandler !");
+                  }
+               }
+
+               return;
+				}
+
+				//Column will be statically defined with Object _value
+				else if(_logtype == LogType.STATIC)
+				{
+					logcol.logtype = _logtype;
+					logcol.value = _value;
+               return;
+				}
+
+				//Column will be provided with a actually timestamp
+				else if(_logtype == LogType.TIMESTAMP)
+				{
+					logcol.logtype = _logtype;
+               return;
+				}
+
+            //Column will be fully ignored during process.
+            //If this column is not nullable, the column has to be filled by a database trigger,
+            //else a database error occurs !
+            //Columns which are not nullable, but should be not filled, must be explicit assigned with LogType.EMPTY,
+            //else a value is required !
+				else if(_logtype == LogType.EMPTY)
+				{
+					logcol.logtype = _logtype;
+					logcol.ignore = true;
+               return;
+				}
+			}
+		}
+	}
+
+
+	/**
+	Return true, if this class is ready to append(), else false.
+	When not ready, a reason-String is stored in the instance-variable msg.
+	*/
+	public boolean ready()
+	{
+   	if(ready) return true;
+
+		if(!isconfigured){ errormsg = "Not ready to append ! Call configure() first !"; return false;}
+
+      //No need to doing the whole rest...
+      if(sql != null)
+      {
+      	ready = true;
+         return true;
+      }
+
+		boolean msgcol_defined = false;
+
+		LogColumn logcol;
+
+		for(int i=0; i<num; i++)
+		{
+      	logcol = (LogColumn)logcols.get(i);
+
+         if(logcol.ignore || !logcol.isWritable) continue;
+			if(!logcol.nullable && logcol.logtype == LogType.EMPTY)
+         {
+         	errormsg = "Not ready to append ! Column " + logcol.name + " is not nullable, and must be specified by setLogType() !";
+            return false;
+         }
+			if(logcol.logtype == LogType.ID && logcol.idhandler == null)
+         {
+         	errormsg = "Not ready to append ! Column " + logcol.name + " is specified as an ID-column, and a JDBCIDHandler has to be set !";
+            return false;
+         }
+			else if(logcol.logtype == LogType.STATIC && logcol.value == null)
+         {
+         	errormsg = "Not ready to append ! Column " + logcol.name + " is specified as a static field, and a value has to be set !";
+            return false;
+         }
+         else if(logcol.logtype == LogType.MSG) msgcol_defined = true;
+		}
+
+      if(!msgcol_defined) return false;
+
+      //create the column_list
+		for(int i=0; i<num; i++)
+		{
+      	logcol = (LogColumn)logcols.get(i);
+
+			if(logcol.ignore || !logcol.isWritable) continue;
+
+         if(logcol.logtype != LogType.EMPTY)
+         {
+				if(column_list == null)
+            {
+            	column_list = logcol.name;
+            }
+            else column_list += ", " + logcol.name;
+         }
+		}
+
+      try
+      {
+			rs = stmt.executeQuery("SELECT " + column_list + " FROM " + table + " WHERE 1 = 2");
+		}
+      catch(Exception e)
+      {
+			errormsg = "Not ready to append ! Cannot select columns '" + column_list + "' of table " + table + " !";
+      	return false;
+      }
+
+		ready = true;
+
+		return true;
+	}
+
+	/**
+	Return true, if this class is configured, else false.
+	*/
+	public boolean isConfigured(){ return isconfigured;}
+
+	/**
+	Return true, if this connection is open, else false.
+	*/
+	public boolean isConnected()
+   {
+   	try
+      {
+   		return (con != null && !con.isClosed());
+      }
+      catch(Exception e){return false;}
+   }
+
+	/**
+	Return the internal error message stored in instance variable msg.
+	*/
+   public String getErrorMsg(){String r = new String(errormsg); errormsg = null; return r;}
+}
+
+
+/**
+This class encapsulate all by class JDBCLogger needed data around a column
+*/
+class LogColumn
+{
+	//column name
+	String name = null;
+   //column type
+	String type = null;
+   //not nullability means that this column is mandatory
+	boolean nullable = false;
+   //isWritable means that the column can be updated, else column is only readable
+   boolean isWritable = false;
+   //if ignore is true, this column will be ignored by building sql-statements.
+   boolean ignore = false;
+
+	//Must be filled for not nullable columns ! In other case it is optional.
+	int logtype = LogType.EMPTY;
+	Object value = null;				//Generic storage for typewrapper-classes Long, String, etc...
+	JDBCIDHandler idhandler = null;
+}
\ No newline at end of file

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/JDBCLogger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/JMSQueueAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/JMSQueueAppender.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/JMSQueueAppender.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/JMSQueueAppender.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,243 @@
+/*
+ * 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 org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.spi.ErrorHandler;
+import org.apache.log4j.spi.ErrorCode;
+import org.apache.log4j.helpers.LogLog;
+
+import java.util.Hashtable;
+import java.util.Properties;
+import javax.jms.*;
+import javax.naming.InitialContext;
+import javax.naming.Context;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+
+/**
+ * A Simple JMS (P2P) Queue Appender. 
+ *
+ * @author Ceki G&uuml;lc&uuml;
+ * @author Jamie Tsao
+*/
+public class JMSQueueAppender extends AppenderSkeleton {
+
+    protected QueueConnection queueConnection;
+    protected QueueSession queueSession;
+    protected QueueSender queueSender;
+    protected Queue queue;
+    
+    String initialContextFactory;
+    String providerUrl;
+    String queueBindingName;
+    String queueConnectionFactoryBindingName;
+    
+    public 
+	JMSQueueAppender() {
+    }
+
+  
+    /**
+     * The <b>InitialContextFactory</b> option takes a string value.
+     * Its value, along with the <b>ProviderUrl</b> option will be used
+     * to get the InitialContext.
+     */
+    public void setInitialContextFactory(String initialContextFactory) {
+	this.initialContextFactory = initialContextFactory;
+    }
+
+    /**
+     * Returns the value of the <b>InitialContextFactory</b> option.
+     */
+    public String getInitialContextFactory() {
+	return initialContextFactory;
+    }
+
+    /**
+     * The <b>ProviderUrl</b> option takes a string value.
+     * Its value, along with the <b>InitialContextFactory</b> option will be used
+     * to get the InitialContext.
+     */
+    public void setProviderUrl(String providerUrl) {
+	this.providerUrl = providerUrl;
+    }
+
+    /**
+     * Returns the value of the <b>ProviderUrl</b> option.
+     */
+    public String getProviderUrl() {
+	return providerUrl;
+    }
+
+    /**
+     * The <b>QueueConnectionFactoryBindingName</b> option takes a
+     * string value. Its value will be used to lookup the appropriate
+     * <code>QueueConnectionFactory</code> from the JNDI context.
+     */
+    public void setQueueConnectionFactoryBindingName(String queueConnectionFactoryBindingName) {
+	this.queueConnectionFactoryBindingName = queueConnectionFactoryBindingName;
+    }
+  
+    /**
+     * Returns the value of the <b>QueueConnectionFactoryBindingName</b> option.
+     */
+    public String getQueueConnectionFactoryBindingName() {
+	return queueConnectionFactoryBindingName;
+    }
+    
+    /**
+     * The <b>QueueBindingName</b> option takes a
+     * string value. Its value will be used to lookup the appropriate
+     * destination <code>Queue</code> from the JNDI context.
+     */
+    public void setQueueBindingName(String queueBindingName) {
+	this.queueBindingName = queueBindingName;
+    }
+  
+    /**
+       Returns the value of the <b>QueueBindingName</b> option.
+    */
+    public String getQueueBindingName() {
+	return queueBindingName;
+    }
+    
+
+    /**
+     * Overriding this method to activate the options for this class
+     * i.e. Looking up the Connection factory ...
+     */
+    public void activateOptions() {
+	
+	QueueConnectionFactory queueConnectionFactory;
+	
+	try {
+
+	    Context ctx = getInitialContext();      
+	    queueConnectionFactory = (QueueConnectionFactory) ctx.lookup(queueConnectionFactoryBindingName);
+	    queueConnection = queueConnectionFactory.createQueueConnection();
+    
+	    queueSession = queueConnection.createQueueSession(false,
+							      Session.AUTO_ACKNOWLEDGE);
+      
+	    Queue queue = (Queue) ctx.lookup(queueBindingName);
+	    queueSender = queueSession.createSender(queue);
+	    
+	    queueConnection.start();
+
+	    ctx.close();      
+
+	} catch(Exception e) {
+	    errorHandler.error("Error while activating options for appender named ["+name+
+			       "].", e, ErrorCode.GENERIC_FAILURE);
+	}
+    }
+ 
+    protected InitialContext getInitialContext() throws NamingException {
+	try {
+	    Hashtable ht = new Hashtable();
+	    
+	    //Populate property hashtable with data to retrieve the context.
+	    ht.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
+	    ht.put(Context.PROVIDER_URL, providerUrl);
+	    
+	    return (new InitialContext(ht));
+	    
+	} catch (NamingException ne) {
+	    LogLog.error("Could not get initial context with ["+initialContextFactory + "] and [" + providerUrl + "]."); 
+	    throw ne;
+	}
+    }
+
+  
+    protected boolean checkEntryConditions() {
+	
+	String fail = null;
+	
+	if(this.queueConnection == null) {
+	    fail = "No QueueConnection";
+	} else if(this.queueSession == null) {
+	    fail = "No QueueSession";
+	} else if(this.queueSender == null) {
+	    fail = "No QueueSender";
+	} 
+	
+	if(fail != null) {
+	    errorHandler.error(fail +" for JMSQueueAppender named ["+name+"].");      
+	    return false;
+	} else {
+	    return true;
+	}
+    }
+
+  /**
+   * Close this JMSQueueAppender. Closing releases all resources used by the
+   * appender. A closed appender cannot be re-opened. 
+   */
+    public synchronized // avoid concurrent append and close operations
+	void close() {
+
+	if(this.closed) 
+	    return;
+	
+	LogLog.debug("Closing appender ["+name+"].");
+	this.closed = true;    
+	
+	try {
+	    if(queueSession != null) 
+		queueSession.close();	
+	    if(queueConnection != null) 
+		queueConnection.close();
+	} catch(Exception e) {
+	    LogLog.error("Error while closing JMSQueueAppender ["+name+"].", e);	
+	}   
+
+	// Help garbage collection
+	queueSender = null;
+	queueSession = null;
+	queueConnection = null;
+    }
+    
+    /**
+     * This method called by {@link AppenderSkeleton#doAppend} method to
+     * do most of the real appending work.  The LoggingEvent will be
+     * be wrapped in an ObjectMessage to be put on the JMS queue.
+     */
+    public void append(LoggingEvent event) {
+
+	if(!checkEntryConditions()) {
+	    return;
+	}
+	
+	try {
+
+	    ObjectMessage msg = queueSession.createObjectMessage();
+	    msg.setObject(event);
+	    queueSender.send(msg);
+
+	} catch(Exception e) {
+	    errorHandler.error("Could not send message in JMSQueueAppender ["+name+"].", e, 
+			       ErrorCode.GENERIC_FAILURE);
+	}
+    }
+    
+    public boolean requiresLayout() {
+	return false;
+    }  
+}
\ No newline at end of file

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/JMSQueueAppender.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/Log4jRequestHandler.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/Log4jRequestHandler.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/Log4jRequestHandler.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/Log4jRequestHandler.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,177 @@
+/*
+ * 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.*;
+import java.net.*;
+import java.util.*;
+import org.apache.log4j.*;
+
+/**
+ * This class implements a RequestHandler for log4j configuration. It serves the "/log4j/" path
+ * in the PluggableHTTPServer. If this path is requested a list of all current log4j categories
+ * with their current priorities is created. All priority settings can be changed by the user
+ * and can be submitted and taken over.
+ *
+ * @author <a HREF="mailto:V.Mentzner@psi-bt.de">Volker Mentzner</a>
+ */
+public class Log4jRequestHandler extends RootRequestHandler {
+
+  private Priority[] prios = Priority.getAllPossiblePriorities();
+
+ /**
+   * Creates a new Log4jRequestHandler object
+   */
+  public Log4jRequestHandler() {
+    this.setTitle("log4j");
+    this.setDescription("log4j configuration");
+    this.setHandledPath("/log4j/");
+  }
+
+ /**
+   * Handles the given request and writes the reply to the given out-stream.
+   *
+   * @param request - client browser request
+   * @param out - Out stream for sending data to client browser
+   * @return if the request was handled by this handler : true, else : false
+   */
+  public boolean handleRequest(String request, Writer out) {
+    String path = "";
+    String query = null;
+    String name;
+    try {
+      // check request url
+      URL url = new URL("http://localhost"+request);
+      path = url.getPath();
+      query = url.getQuery();
+      if (path.startsWith(this.getHandledPath()) == false) {
+        return false;
+      }
+
+      out.write("HTTP/1.0 200 OK\r\n");
+      out.write("Content-type: text/html\r\n\r\n");
+      out.write("<HTML><HEAD><TITLE>" + this.getTitle() + "</TITLE></HEAD>\r\n");
+      out.write("<BODY><H1>log4j</H1>\r\n");
+      out.write(this.getDescription() + "<br><br>\r\n");
+
+      // handle a request with query
+      if ((query != null) && (query.length() >= 0)) {
+        StringTokenizer st = new StringTokenizer(query, "&");
+        String cmd;
+        String catname;
+        String catval;
+        int idx;
+        while (st.hasMoreTokens()) {
+          cmd = st.nextToken();
+          idx = cmd.indexOf("=");
+          catname = cmd.substring(0, idx);
+          catval = cmd.substring(idx+1, cmd.length());
+          if (catname.equalsIgnoreCase("root"))
+            Category.getRoot().setPriority(Priority.toPriority(catval));
+          else
+            Category.getInstance(catname).setPriority(Priority.toPriority(catval));
+        }
+      }
+
+      // output category information in a form with a simple table
+      out.write("<form name=\"Formular\" ACTION=\""+this.getHandledPath()+"\" METHOD=\"PUT\">");
+      out.write("<table cellpadding=4>\r\n");
+      out.write(" <tr>\r\n");
+      out.write("  <td><b>Category</b></td>\r\n");
+      out.write("  <td><b>Priority</b></td>\r\n");
+      out.write("  <td><b>Appender</b></td>\r\n");
+      out.write(" </tr>\r\n");
+
+      // output for root category
+      Category cat = Category.getRoot();
+      out.write(" <tr><td>root</td>\r\n");
+      out.write("  <td>\r\n");
+      out.write("   <select size=1 name=\""+ cat.getName() +"\">");
+      for (int i = 0; i < prios.length; i++) {
+        if (cat.getChainedPriority().toString().equals(prios[i].toString()))
+          out.write("<option selected>"+prios[i].toString());
+        else
+          out.write("<option>"+prios[i].toString());
+      }
+      out.write("</select>\r\n");
+      out.write("  </td>\r\n");
+      out.write("  <td>\r\n");
+      for (Enumeration apds = cat.getAllAppenders(); apds.hasMoreElements();) {
+        Appender apd = (Appender)apds.nextElement();
+        name = apd.getName();
+        if (name == null)
+          name = "<i>(no name)</i>";
+        out.write(name);
+        if (apd instanceof AppenderSkeleton) {
+          try {
+            AppenderSkeleton apskel = (AppenderSkeleton)apd;
+            out.write(" [" + apskel.getThreshold().toString() + "]");
+          } catch (Exception ex) {
+          }
+        }
+        if (apds.hasMoreElements())
+          out.write(",  ");
+      }
+      out.write("  </td>\r\n");
+      out.write(" </tr>\r\n");
+
+      // output for all other categories
+      for (Enumeration en = Category.getCurrentCategories(); en.hasMoreElements();) {
+        cat = (Category)en.nextElement();
+        out.write(" <tr>\r\n");
+        out.write("  <td>" + cat.getName() + "</td>\r\n");
+        out.write("  <td>\r\n");
+        out.write("   <select size=1 name=\""+ cat.getName() +"\">");
+        for (int i = 0; i < prios.length; i++) {
+          if (cat.getChainedPriority().toString().equals(prios[i].toString()))
+            out.write("<option selected>"+prios[i].toString());
+          else
+            out.write("<option>"+prios[i].toString());
+        }
+        out.write("</select>\r\n");
+        out.write("  </td>\r\n");
+        out.write("  <td>\r\n");
+        for (Enumeration apds = cat.getAllAppenders(); apds.hasMoreElements();) {
+          Appender apd = (Appender)apds.nextElement();
+          name = apd.getName();
+          if (name == null)
+            name = "<i>(no name)</i>";
+          out.write(name);
+          if (apd instanceof AppenderSkeleton) {
+            try {
+              AppenderSkeleton apskel = (AppenderSkeleton)apd;
+              out.write(" [" + apskel.getThreshold().toString() + "]");
+            } catch (Exception ex) {
+            }
+          }
+          if (apds.hasMoreElements())
+            out.write(",  ");
+        }
+        out.write("  </td>\r\n");
+        out.write(" </tr>\r\n");
+      }
+      out.write("</table>\r\n");
+      out.write("<input type=submit value=\"Submit\">");
+      out.write("</form>");
+      out.write("</BODY></HTML>\r\n");
+      out.flush();
+      return true;
+    } catch (Exception ex) {
+      return false;
+    }
+  }
+}
\ No newline at end of file

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/Log4jRequestHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/LogType.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/LogType.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/LogType.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/LogType.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,42 @@
+package org.apache.log4j.net;
+
+/**
+This class contains all constants which are necessary to define a columns log-type.
+*/
+public class LogType
+{
+  //A column of this type will receive the message.
+  public static final int MSG = 1;
+
+  //A column of this type will be a unique identifier of the logged row.
+  public static final int ID = 2;
+
+  //A column of this type will contain a static, one-time-defined value.
+  public static final int STATIC = 3;
+
+    //A column of this type will be filled with an actual timestamp depending by the time the logging will be done.
+  public static final int TIMESTAMP = 4;
+
+  //A column of this type will contain no value and will not be included in logging insert-statement.
+   //This could be a column which will be filled not by creation but otherwhere...
+  public static final int EMPTY = 5;
+
+
+  public static boolean isLogType(int _lt)
+  {
+    if(_lt == MSG || _lt == STATIC || _lt == ID || _lt == TIMESTAMP || _lt == EMPTY) return true;
+
+    return false;
+  }
+
+   public static int parseLogType(String _lt)
+   {
+    if(_lt.equals("MSG")) return MSG;
+    if(_lt.equals("ID")) return ID;
+    if(_lt.equals("STATIC")) return STATIC;
+    if(_lt.equals("TIMESTAMP")) return TIMESTAMP;
+    if(_lt.equals("EMPTY")) return EMPTY;
+
+      return -1;
+   }
+}
\ No newline at end of file

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/LogType.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/RootRequestHandler.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/RootRequestHandler.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/RootRequestHandler.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/RootRequestHandler.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,159 @@
+/*
+ * 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.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * This class implements a RequestHandler for the root path "/" in the PluggableHTTPServer.
+ * A simple HTML message will be replied to the client.
+ *
+ * @author <a HREF="mailto:V.Mentzner@psi-bt.de">Volker Mentzner</a>
+ */
+public class RootRequestHandler implements HTTPRequestHandler {
+
+  private String title;
+  private String description;
+  private String handledPath;
+  private String ReplyType = "Content-type: text/html\r\n\r\n";
+  private String ReplyHTML = "<HTML><HEAD><TITLE>Root</TITLE></HEAD>\r\n"
+                           + "<BODY><H1>Root</H1>\r\n"
+                           + "</BODY></HTML>\r\n";
+
+ /**
+   * Creates a new RootRequestHandler object
+   */
+  public RootRequestHandler() {
+    this.setTitle("root page");
+    this.setDescription("root page");
+    this.setHandledPath("/");
+  }
+
+  /**
+   * Gets the content type of the reply HTTP message
+   *
+   * @return content type as String
+   */
+  public String getReplyType() {
+    return this.ReplyType;
+  }
+
+  /**
+   * Sets the content type of the reply HTTP message
+   *
+   * @param ReplyType - content type as String
+   */
+  public void setReplyType(String ReplyType) {
+    this.ReplyType = ReplyType;
+  }
+
+  /**
+   * Gets the HTML data of the reply HTTP message
+   *
+   * @return HTML message as String
+   */
+  public String getReplyHTML() {
+    return this.ReplyHTML;
+  }
+
+  /**
+   * Sets the HTML data of the reply HTTP message
+   *
+   * @param ReplyHTML - HTML message as String
+   */
+  public void setReplyHTML(String ReplyHTML) {
+    this.ReplyHTML = ReplyHTML;
+  }
+
+ /**
+   * Gets the title for html page
+   */
+  public String getTitle() {
+    return this.title;
+  }
+
+ /**
+   * Sets the title for html page
+   */
+  public void setTitle(String title) {
+    this.title = title;
+  }
+
+ /**
+   * Gets the description for html page
+   */
+  public String getDescription() {
+    return this.description;
+  }
+
+ /**
+   * Sets the description for html page
+   */
+  public void setDescription(String description) {
+    this.description = description;
+  }
+
+  /**
+   * Gets the server path
+   *
+   * @return the server path
+   */
+  public String getHandledPath() {
+    return this.handledPath;
+  }
+
+  /**
+   * Sets the server path
+   *
+   * @param path - the server path
+   */
+  public void setHandledPath(String path) {
+    this.handledPath = path;
+  }
+
+ /**
+   * Handles the given request and writes the reply to the given out-stream.
+   *
+   * @param request - client browser request
+   * @param out - Out stream for sending data to client browser
+   * @return if the request was handled by this handler : true, else : false
+   */
+  public boolean handleRequest(String request, Writer out) {
+    String path = "";
+    String query = null;
+    try {
+      URL url = new URL("http://localhost"+request);
+      path = url.getPath();
+      query = url.getPath();
+      if (path.equals(handledPath) == false) {
+        return false;
+      }
+
+      out.write("HTTP/1.0 200 OK\r\n");
+      if (ReplyType != null)
+        out.write(ReplyType);
+      if (ReplyHTML != null)
+        out.write(ReplyHTML);
+      out.flush();
+      return true;
+    } catch (Exception ex) {
+      return false;
+    }
+  }
+}
\ No newline at end of file

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/main/java/org/apache/log4j/net/RootRequestHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderLog4JTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderLog4JTest.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderLog4JTest.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderLog4JTest.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,53 @@
+package org.apache.log4j.contribs.ThomasFenner;
+/*
+ * 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.
+ */
+
+// Here is a code example to configure the JDBCAppender with a configuration-file
+
+import org.apache.log4j.*;
+
+import java.sql.*;
+
+public class JDBCAppenderLog4JTest
+{
+   // Create a category instance for this class
+   static Category cat = Category.getInstance(JDBCAppenderLog4JTest.class.getName());
+
+   public static void main(String[] args)
+   {
+      // Ensure to have all necessary drivers installed !
+      try
+      {
+         Driver d = (Driver)(Class.forName("oracle.jdbc.driver.OracleDriver").newInstance());
+         DriverManager.registerDriver(d);
+      }
+      catch(Exception e){}
+
+      // Set the priority which messages have to be logged
+      cat.setPriority(Priority.INFO);
+
+      // Configuration with configuration-file
+      PropertyConfigurator.configure("log4jtestprops.txt");
+
+      // These messages with Priority >= setted priority will be logged to the database.
+      cat.debug("debug");  //this not, because Priority DEBUG is less than INFO
+      cat.info("info");
+      cat.error("error");
+      cat.fatal("fatal");
+   }
+}
+

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderLog4JTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderNoConfigFileLog4JTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderNoConfigFileLog4JTest.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderNoConfigFileLog4JTest.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderNoConfigFileLog4JTest.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,134 @@
+package org.apache.log4j.contribs.ThomasFenner;
+/*
+ * 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.
+ */
+
+// Here is a code example to configure the JDBCAppender without a configuration-file
+
+import org.apache.log4j.*;
+import org.apache.log4j.net.JDBCAppender;
+import org.apache.log4j.net.JDBCConnectionHandler;
+import org.apache.log4j.net.JDBCIDHandler;
+import org.apache.log4j.net.LogType;
+
+import java.sql.*;
+import java.util.*;
+
+public class JDBCAppenderNoConfigFileLog4JTest
+{
+	// Create a category instance for this class
+	static Category cat = Category.getInstance(JDBCAppenderNoConfigFileLog4JTest.class.getName());
+
+	public static void main(String[] args)
+	{
+		// A JDBCIDHandler
+		MyIDHandler idhandler = new MyIDHandler();
+
+		// Ensure to have all necessary drivers installed !
+		try
+		{
+			Driver d = (Driver)(Class.forName("oracle.jdbc.driver.OracleDriver").newInstance());
+			DriverManager.registerDriver(d);
+		}
+		catch(Exception e){}
+
+		// Set the priority which messages have to be logged
+		cat.setPriority(Priority.DEBUG);
+
+		// Create a new instance of JDBCAppender
+		JDBCAppender ja = new JDBCAppender();
+
+		// Set options with method setOption()
+		ja.setOption(JDBCAppender.CONNECTOR_OPTION, "MyConnectionHandler");
+		ja.setOption(JDBCAppender.URL_OPTION, "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1521))(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1526)))(CONNECT_DATA=(SID=LENZI)))");
+		ja.setOption(JDBCAppender.USERNAME_OPTION, "mex_pr_dev60");
+		ja.setOption(JDBCAppender.PASSWORD_OPTION, "mex_pr_dev60");
+
+		ja.setOption(JDBCAppender.TABLE_OPTION, "logtest");
+
+		// There are two ways to setup the column-descriptions :
+		// 1. Use the the method setOption(JDBCAppender.COLUMNS_OPTION, column-description)
+		//ja.setOption(JDBCAppender.COLUMNS_OPTION, "id_seq~EMPTY	id~ID~MyIDHandler	msg~MSG	created_on~TIMESTAMP	created_by~STATIC~:-) Thomas Fenner (t.fenner@klopotek.de)");
+
+		// 2. Use the better way of coding with method setLogType(String columnname, int LogType.xxx, Object xxx)
+		ja.setLogType("id_seq", LogType.EMPTY, "");
+		ja.setLogType("id", LogType.ID, idhandler);
+		ja.setLogType("msg", LogType.MSG, "");
+		ja.setLogType("created_on", LogType.TIMESTAMP, "");
+		ja.setLogType("created_by", LogType.STATIC, "FEN");
+
+		// If you just want to perform a static sql-statement, forget about the table- and columns-options,
+		// and use this one :
+		//ja.setOption(JDBCAppender.SQL_OPTION, "INSERT INTO LOGTEST (id, msg, created_on, created_by) VALUES (1, @MSG@, sysdate, 'me')");
+
+		// other options
+		//ja.setOption(JDBCAppender.BUFFER_OPTION, "1");
+		//ja.setOption(JDBCAppender.COMMIT_OPTION, "Y");
+
+		// Define a layout
+		//ja.setLayout(new PatternLayout("%m"));
+
+		// Add the appender to a category
+		cat.addAppender(ja);
+
+		// These messages with Priority >= setted priority will be logged to the database.
+		cat.debug("debug");
+		cat.info("info");
+		cat.error("error");
+		cat.fatal("fatal");
+	}
+}
+
+// Implement a sample JDBCConnectionHandler
+class MyConnectionHandler implements JDBCConnectionHandler
+{
+	Connection con = null;
+   //Default connection
+	String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1521))(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1526)))(CONNECT_DATA=(SID=LENZI)))";
+   String username = "mex_pr_dev60";
+   String password = "mex_pr_dev60";
+
+   public Connection getConnection()
+   {
+	return getConnection(url, username, password);
+   }
+
+   public Connection getConnection(String _url, String _username, String _password)
+   {
+	try
+	  {
+		if(con != null && !con.isClosed()) con.close();
+			con = DriverManager.getConnection(_url, _username, _password);
+			con.setAutoCommit(false);
+	  }
+	  catch(Exception e){}
+
+	return con;
+   }
+}
+
+
+// Implement a sample JDBCIDHandler
+class MyIDHandler implements JDBCIDHandler
+{
+	private static long id = 0;
+
+	public synchronized Object getID()
+   {
+		return new Long(++id);
+   }
+}
+

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderNoConfigFileLog4JTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderWithConfigFileLog4JTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderWithConfigFileLog4JTest.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderWithConfigFileLog4JTest.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderWithConfigFileLog4JTest.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,274 @@
+package org.apache.log4j.contribs.ThomasFenner;
+/*
+ * 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.
+ */
+/**
+// Class JDBCAppender, writes messages into a database
+
+// The JDBCAppender is configurable at runtime in two alternatives :
+// 1. Configuration-file
+//    Define the options in a file and call a PropertyConfigurator.configure(file)-method.
+// 2. method JDBCAppender::setOption(JDBCAppender.xxx_OPTION, String value)
+
+// The sequence of some options is important :
+// 1. Connector-option OR/AND Database-options
+//    Any database connection is required !
+// 2. (Table-option AND Columns-option) OR SQL-option
+//		Any statement is required !
+// 3. All other options can be set at any time...
+//    The other options are optional and have a default initialization, which can be custumized.
+
+// All available options are defined as static String-constants in JDBCAppender named xxx_OPTION.
+
+// Here is a description of all available options :
+// 1. Database-options to connect to the database
+//    - URL_OPTION			: a database url of the form jdbc:subprotocol:subname
+//    - USERNAME_OPTION		: the database user on whose behalf the connection is being made
+//    - PASSWORD_OPTION		: the user's password
+//
+// 2. Connector-option to specify your own JDBCConnectionHandler
+//    - CONNECTOR_OPTION	: a classname which is implementing the JDBCConnectionHandler-interface
+//    This interface is used to get a customized connection.
+//    If in addition the database-options are given, these options will be used
+//    for invocation of the JDBCConnectionHandler-interface to get a connection.
+//    Else if no database-options are given, the JDBCConnectionHandler-interface is called without these options.
+//
+// 3. SQL-option to specify a static sql-statement which will be performed with every occuring message-event
+//    - SQL_OPTION			: a sql-statement which will be used to write to the database
+//    If you give this option, the table-option and columns-option will be ignored !
+//    Use the variable @MSG@ on that location in the statement, which has to be dynamically replaced by the message.
+//
+// 4. Table-option to specify one table contained by the database
+//    - TABLE_OPTION			: the table in which the logging will be done
+//
+// 5. Columns-option to describe the important columns of the table (Not nullable columns are mandatory to describe!)
+//    - COLUMNS_OPTION		: a formatted list of column-descriptions
+//    Each column description consists of
+//       - the name of the column (required)
+//			- a logtype which is a static constant of class LogType (required)
+//       - and a value which depends by the LogType (optional/required, depending by logtype)
+//    Here is a description of the available logtypes of class LogType :
+//       o MSG			= a value will be ignored, the column will get the message. (One columns need to be of this type!)
+//       o STATIC		= the value will be filled into the column with every logged message. (Ensure that the type of value can be casted into the sql-type of the column!)
+//       o ID			= value must be a classname, which implements the JDBCIDHandler-interface.
+//       o TIMESTAMP	= a value will be ignored, the column will be filled with a actually timestamp with every logged message.
+//       o EMPTY		= a value will be ignored, the column will be ignored when writing to the database (Ensure to fill not nullable columns by a database trigger!)
+//    If there are more than one column to describe, the columns must be separated by a TAB-delimiter ('	') !
+//    The arguments of a column-description must be separated by the delimiter '~' !
+//		(Example :  name1~logtype1~value1	name2~logtype2~value2...)
+//
+// 6. Layout-options to define the layout of the messages (optional)
+//    - the layout wont be set by a xxx_OPTION
+//    Configuration-file			: see at the following configuration-file example
+//    JDBCAppender::setOption()	: see at the following code example
+//    The default is a layout of class org.apache.log4j.PatternLayout with ConversionPattern=%m
+//
+// 7. Buffer-option to define the size of the message-event-buffer (optional)
+//    - BUFFER_OPTION		: define how many messages will be buffered until they will be updated to the database.
+//    The default is a update on every message (buffer=1=no buffer).
+//
+// 8. Commit-option to define a auto-commitment
+//    - COMMIT_OPTION		: define whether updated messages should be committed to the database (Y) or not (N).
+//    The default is a commit on every buffer-flush.
+
+
+// Here is a Configuration-file example, which can be used with the PropertyConfigurator :
+//
+// Declare a appender variable named JDBC
+log4j.rootCategory=JDBC
+
+// JDBC is a class of JDBCAppender, which writes messages into a database
+log4j.appender.JDBC=JDBCAppender
+
+// 1. Database-options to connect to the database
+log4j.appender.JDBC.url=jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1521))(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1526)))(CONNECT_DATA=(SID=LENZI)))
+log4j.appender.JDBC.username=mex_pr_dev60
+log4j.appender.JDBC.password=mex_pr_dev60
+
+// 2. Connector-option to specify your own JDBCConnectionHandler
+log4j.appender.JDBC.connector=MyConnectionHandler
+
+// 3. SQL-option to specify a static sql-statement which will be performed with every occuring message-event
+log4j.appender.JDBC.sql=INSERT INTO LOGTEST (id, msg, created_on, created_by) VALUES (1, @MSG@, sysdate, 'me')
+
+// 4. Table-option to specify one table contained by the database
+log4j.appender.JDBC.table=logtest
+
+// 5. Columns-option to describe the important columns of the table (Not nullable columns are mandatory to describe!)
+log4j.appender.JDBC.columns=id_seq~EMPTY	id~ID~MyIDHandler	msg~MSG	created_on~TIMESTAMP	created_by~STATIC~Thomas Fenner (t.fenner@klopotek.de)
+
+// 6. Layout-options to define the layout of the messages (optional)
+log4j.appender.JDBC.layout=org.apache.log4j.PatternLayout
+log4j.appender.JDBC.layout.ConversionPattern=%m
+
+// 7. Buffer-option to define the size of the message-event-buffer (optional)
+log4j.appender.JDBC.buffer=1
+
+// 8. Commit-option to define a auto-commitment
+log4j.appender.JDBC.commit=Y
+*/
+
+// Here is a code example to configure the JDBCAppender with a configuration-file :
+
+import org.apache.log4j.*;
+import org.apache.log4j.net.JDBCConnectionHandler;
+import org.apache.log4j.net.JDBCIDHandler;
+
+import java.sql.*;
+import java.util.*;
+
+public class JDBCAppenderWithConfigFileLog4JTest
+{
+	// Create a category instance for this class
+   static Category cat = Category.getInstance(JDBCAppenderWithConfigFileLog4JTest.class.getName());
+
+   public static void main(String[] args)
+   {
+      // Ensure to have all necessary drivers installed !
+   	try
+      {
+			Driver d = (Driver)(Class.forName("oracle.jdbc.driver.OracleDriver").newInstance());
+			DriverManager.registerDriver(d);
+		}
+      catch(Exception e){}
+
+      // Set the priority which messages have to be logged
+		cat.setPriority(Priority.INFO);
+
+		// Configuration with configuration-file
+		PropertyConfigurator.configure("log4jtestprops.txt");
+
+      // These messages with Priority >= setted priority will be logged to the database.
+  		cat.debug("debug");  //this not, because Priority DEBUG is less than INFO
+      cat.info("info");
+      cat.error("error");
+      cat.fatal("fatal");
+   }
+}
+
+// Here is a code example to configure the JDBCAppender without a configuration-file :
+/*
+import org.apache.log4j.*;
+import java.sql.*;
+import java.lang.*;
+import java.util.*;
+
+public class Log4JTest
+{
+	// Create a category instance for this class
+   static Category cat = Category.getInstance(Log4JTest.class.getName());
+
+   public static void main(String[] args)
+   {
+   	// A JDBCIDHandler
+	   MyIDHandler idhandler = new MyIDHandler();
+
+      // Ensure to have all necessary drivers installed !
+   	try
+      {
+			Driver d = (Driver)(Class.forName("oracle.jdbc.driver.OracleDriver").newInstance());
+			DriverManager.registerDriver(d);
+		}
+      catch(Exception e){}
+
+      // Set the priority which messages have to be logged
+		cat.setPriority(Priority.DEBUG);
+
+      // Create a new instance of JDBCAppender
+      JDBCAppender ja = new JDBCAppender();
+
+      // Set options with method setOption()
+      ja.setOption(JDBCAppender.CONNECTOR_OPTION, "MyConnectionHandler");
+      ja.setOption(JDBCAppender.URL_OPTION, "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1521))(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1526)))(CONNECT_DATA=(SID=LENZI)))");
+      ja.setOption(JDBCAppender.USERNAME_OPTION, "mex_pr_dev60");
+      ja.setOption(JDBCAppender.PASSWORD_OPTION, "mex_pr_dev60");
+
+		ja.setOption(JDBCAppender.TABLE_OPTION, "logtest");
+
+      // There are two ways to setup the column-descriptions :
+      // 1. Use the the method setOption(JDBCAppender.COLUMNS_OPTION, column-description)
+		//ja.setOption(JDBCAppender.COLUMNS_OPTION, "id_seq~EMPTY	id~ID~MyIDHandler	msg~MSG	created_on~TIMESTAMP	created_by~STATIC~:-) Thomas Fenner (t.fenner@klopotek.de)");
+		// 2. Use the better way of coding with method setLogType(String columnname, int LogType.xxx, Object xxx)
+		ja.setLogType("id_seq", LogType.EMPTY, "");
+		ja.setLogType("id", LogType.ID, idhandler);
+		ja.setLogType("msg", LogType.MSG, "");
+		ja.setLogType("created_on", LogType.TIMESTAMP, "");
+		ja.setLogType("created_by", LogType.STATIC, "FEN");
+
+      // If you just want to perform a static sql-statement, forget about the table- and columns-options,
+      // and use this one :
+		//ja.setOption(JDBCAppender.SQL_OPTION, "INSERT INTO LOGTEST (id, msg, created_on, created_by) VALUES (1, @MSG@, sysdate, 'me')");
+
+      // other options
+		//ja.setOption(JDBCAppender.BUFFER_OPTION, "1");
+		//ja.setOption(JDBCAppender.COMMIT_OPTION, "Y");
+
+      // Define a layout
+		//ja.setLayout(new PatternLayout("%m"));
+
+      // Add the appender to a category
+      cat.addAppender(ja);
+
+      // These messages with Priority >= setted priority will be logged to the database.
+		cat.debug("debug");
+      cat.info("info");
+      cat.error("error");
+      cat.fatal("fatal");
+	}
+}
+*/
+
+// Implement a sample JDBCConnectionHandler
+class JDBCAppenderWithConfigFileLog4JTestConnectionHandler implements JDBCConnectionHandler
+{
+	Connection con = null;
+   //Default connection
+	String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1521))(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1526)))(CONNECT_DATA=(SID=LENZI)))";
+   String username = "mex_pr_dev60";
+   String password = "mex_pr_dev60";
+
+   public Connection getConnection()
+   {
+   	return getConnection(url, username, password);
+   }
+
+   public Connection getConnection(String _url, String _username, String _password)
+   {
+   	try
+      {
+   		if(con != null && !con.isClosed()) con.close();
+			con = DriverManager.getConnection(_url, _username, _password);
+			con.setAutoCommit(false);
+      }
+      catch(Exception e){}
+
+   	return con;
+   }
+}
+
+
+// Implement a sample JDBCIDHandler
+class JDBCAppenderWithConfigFileIDHandler implements JDBCIDHandler
+{
+	private static long id = 0;
+
+	public synchronized Object getID()
+   {
+		return new Long(++id);
+   }
+}
+
+

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/JDBCAppenderWithConfigFileLog4JTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/configfile_example.txt (from r1345516, logging/log4j/branches/log4j12-bz53299/contribs/ThomasFenner/configfile_example.txt)
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/configfile_example.txt?p2=logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/configfile_example.txt&p1=logging/log4j/branches/log4j12-bz53299/contribs/ThomasFenner/configfile_example.txt&r1=1345516&r2=1345524&rev=1345524&view=diff
==============================================================================
    (empty)

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/configfile_example.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/java/org/apache/log4j/contribs/ThomasFenner/configfile_example.txt
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/CompositeRollingAppender.java (from r1345516, logging/log4j/branches/log4j12-bz53299/contribs/KevinSteppe/CompositeRollingAppender.java)
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/CompositeRollingAppender.java?p2=logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/CompositeRollingAppender.java&p1=logging/log4j/branches/log4j12-bz53299/contribs/KevinSteppe/CompositeRollingAppender.java&r1=1345516&r2=1345524&rev=1345524&view=diff
==============================================================================
    (empty)

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/CompositeRollingAppender.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/CompositeRollingAppender.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/DailyFileAppender.java (from r1345516, logging/log4j/branches/log4j12-bz53299/contribs/EirikLygre/DailyFileAppender1.java)
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/DailyFileAppender.java?p2=logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/DailyFileAppender.java&p1=logging/log4j/branches/log4j12-bz53299/contribs/EirikLygre/DailyFileAppender1.java&r1=1345516&r2=1345524&rev=1345524&view=diff
==============================================================================
    (empty)

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/DailyFileAppender.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/DailyFileAppender.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/TempFileAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/TempFileAppender.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/TempFileAppender.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/TempFileAppender.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,198 @@
+/*
+ * 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;
+ 
+import java.io.File;
+import java.io.Writer;
+import java.io.FileWriter;
+import java.io.BufferedWriter;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.helpers.OptionConverter;
+import org.apache.log4j.spi.ErrorHandler;
+
+/**
+   TempFileAppender creates new unique file for each logging statement.
+ 
+   @author <a HREF="mailto:leos.literak@12snap.com">Leos Literak</a>
+   @author Ceki G&uuml;lc&uuml;
+ 
+*/
+public class TempFileAppender extends AppenderSkeleton {
+ 
+  /**
+     A string constant used in naming the option for setting the
+     directory where the log files will be created. Current value 
+     of this string constant is <b>Path</b>. java.io.tmpdir directory
+     will be used, if ommited.
+   */
+  static final public String PATH_OPTION = "Path";
+  
+  /**
+     The default path is actual directory.
+  */
+  protected String path = null;
+ 
+  /**
+     A string constant used in naming the option for setting the
+     prefix of the log files. It has to have at least 3 characters!
+     Current value of this string constant is <b>Prefix</b>.
+   */
+  static final public String PREFIX_OPTION = "Prefix";
+  
+  /**
+     The default path is actual directory.
+  */
+  protected String prefix = "l4j_";
+ 
+  /**
+     A string constant used in naming the option for setting the
+     suffix of the log files. Current value of this string constant 
+     is <b>Suffix</b>.
+   */
+  static final public String SUFFIX_OPTION = "Suffix";
+  
+  /**
+     The default path is actual directory.
+  */
+  protected String suffix = ".tmp";
+  
+  /**
+     Default dir
+  */
+  
+  protected File dir = null;
+
+
+
+
+  /**
+     The default constructor simply calls its parent's constructor. 
+  */
+  public TempFileAppender() {
+      super();
+  }
+ 
+  /**
+     Retuns the option names for this component
+  */
+  public String[] getOptionStrings() {
+      return OptionConverter.concatanateArrays(super.getOptionStrings(),
+                 new String[] {PATH_OPTION,PREFIX_OPTION,SUFFIX_OPTION});
+  }  
+
+  /**
+     Set TempFileAppender specific options.
+ 
+     The recognized options are <b>Path</b>, <b>Prefix</b> and <b>Suffix</b>,
+     i.e. the values of the string constants {@link #PATH_OPTION}, 
+     {@link #PREFIX_OPTION} and respectively {@link #SUFFIX_OPTION}. 
+     The options of the super class {@link AppenderSkeleton} are also 
+     recognized.
+  */
+  
+  public void setOption(String key, String value) {
+      super.setOption(key, value);
+      if(key.equalsIgnoreCase(PATH_OPTION)) {
+	  path = value;
+	  if(path==null) {
+              errorHandler.error("Path cannot be empty!",null,0);
+	  }
+
+	  dir = new File(path);
+	  if(!(dir.exists() && dir.isDirectory() && dir.canWrite())) {
+              errorHandler.error("Cannot write to directory " + path + "!",null,0);
+	  }
+      }
+      else if(key.equalsIgnoreCase(PREFIX_OPTION)) {
+          if(value!=null && value.length()>=3) {
+	      prefix = value;
+	  } else {
+              errorHandler.error("Prefix cannot be shorter than 3 characters!",
+	                         null,0);
+	  }
+      }
+      else if(key.equalsIgnoreCase(SUFFIX_OPTION)) {
+          if(value!=null && value.length()>=1) {
+	      suffix = value;
+	  } else {
+              errorHandler.error("Suffix cannot be empty!",null,0);
+	  }
+      }
+  }
+
+  /**
+     This method is called by {@link AppenderSkeleton#doAppend}
+     method.
+ 
+     <p>Whenever this method is called, new unique file is created
+     with specified prefix and suffix. The file is closed afterwards.
+ 
+     <p>The format of the output will depend on this appender's
+     layout.
+ 
+  */ 
+  public void append(LoggingEvent event) { 
+      if(!checkEntryConditions()) {
+          return;
+      }
+      subAppend(event);
+  }
+ 
+  /**
+     This method determines if there is a sense in attempting to append.
+  */
+  protected boolean checkEntryConditions() {
+      return true;
+  }   
+
+  /**
+     This method does actual writing
+  */
+  protected void subAppend(LoggingEvent event) {
+      try {
+          File tmp = File.createTempFile(prefix,suffix,dir);
+	  Writer out = new BufferedWriter(new FileWriter(tmp));
+	  out.write(event.message);
+	  out.close();
+ /* this Appender is not supposed to be used for logging of Exceptions */
+      } catch (Exception e) {
+          errorHandler.error("Error during creation of temporary File!",e,1);
+      }
+  }
+  
+  public boolean requiresLayout() {
+      return false;
+  }
+  
+  public void close() {
+  /* nothing to do */
+  }
+} 
+/*
+ * @author $Author$
+ * @version $Revision$
+ * @since $Date$
+ *
+ * $Log$
+ * Revision 1.1.2.1  2005/05/27 03:27:54  mwomack
+ * Fix for #35032.  Added license header to .java files that did not already have a license.
+ *
+ * Revision 1.1  2001/04/20 17:38:31  ceki
+ *
+ * Added LeosLiterak's TempFileAppender.java
+ *
+*/

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/TempFileAppender.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/gui/LogTextPanel.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/gui/LogTextPanel.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/gui/LogTextPanel.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/gui/LogTextPanel.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,191 @@
+/*
+ * 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.gui;
+
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.BorderLayout;
+
+import javax.swing.*;
+import javax.swing.text.StyledDocument;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.StyleConstants;
+
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Enumeration;
+import java.util.ArrayList;
+
+import org.apache.log4j.*;
+
+/**
+ * @author James House
+ */
+public class LogTextPanel extends JPanel {
+
+  private JScrollBar scrollBar;
+  private JTextPane textPane;
+  private JCheckBox cbxTail;
+  private StyledDocument doc;
+
+  private Hashtable fontAttributes;
+
+  private int eventBufferMaxSize = 10000;
+  private ArrayList eventBuffer = new ArrayList(eventBufferMaxSize);
+  private int eventViewIndex = 0;
+
+  public LogTextPanel() {
+    constructComponents();
+    createDefaultFontAttributes();
+  }
+
+  private void constructComponents() {
+      // setup the panel's additional components...
+    this.setLayout(new BorderLayout());
+
+    cbxTail = new JCheckBox();
+    cbxTail.setSelected(true);
+    cbxTail.setText("Tail log events");
+
+    JPanel bottomPanel = new JPanel();
+    bottomPanel.add(cbxTail, null);
+
+    textPane = new JTextPane();
+    textPane.setEditable(false);
+    textPane.setText("");
+    doc = textPane.getStyledDocument();
+
+    scrollBar = new JScrollBar(JScrollBar.VERTICAL);
+
+    this.add(bottomPanel, BorderLayout.SOUTH);
+    this.add(scrollBar, BorderLayout.EAST);
+    this.add(textPane, BorderLayout.CENTER);
+  }
+
+  public
+  void setTextBackground(Color color) {
+    textPane.setBackground(color);
+  }
+
+  public
+  void setTextBackground(String v) {
+    textPane.setBackground(parseColor(v));
+  }
+
+  private void createDefaultFontAttributes() {
+    Priority[] prio = Priority.getAllPossiblePriorities();
+
+    fontAttributes = new Hashtable();
+    for (int i=0; i<prio.length;i++) {
+      MutableAttributeSet att = new SimpleAttributeSet();
+      fontAttributes.put(prio[i], att);
+      //StyleConstants.setFontSize(att,11);
+    }
+
+    setTextColor(Priority.FATAL, Color.red);
+    setTextColor(Priority.ERROR, Color.magenta);
+    setTextColor(Priority.WARN, Color.orange);
+    setTextColor(Priority.INFO, Color.blue);
+    setTextColor(Priority.DEBUG, Color.black);
+  }
+
+  private
+  Color parseColor (String v) {
+    StringTokenizer st = new StringTokenizer(v,",");
+    int val[] = {255,255,255,255};
+    int i=0;
+    while (st.hasMoreTokens()) {
+      val[i]=Integer.parseInt(st.nextToken());
+      i++;
+    }
+    return new Color(val[0],val[1],val[2],val[3]);
+  }
+
+  void setTextColor(Priority p, String v) {
+    StyleConstants.setForeground(
+          (MutableAttributeSet)fontAttributes.get(p),parseColor(v));
+  }
+
+  void setTextColor(Priority p, Color c) {
+    StyleConstants.setForeground(
+          (MutableAttributeSet)fontAttributes.get(p),c);
+  }
+
+  void setTextFontSize(int size) {
+    Enumeration e = fontAttributes.elements();
+    while (e.hasMoreElements()) {
+      StyleConstants.setFontSize((MutableAttributeSet)e.nextElement(),size);
+    }
+    return;
+  }
+
+  void setTextFontName(String name) {
+    Enumeration e = fontAttributes.elements();
+    while (e.hasMoreElements()) {
+      StyleConstants.setFontFamily((MutableAttributeSet)e.nextElement(),name);
+    }
+    return;
+  }
+
+  void setEventBufferSize(int bufferSize) {
+    eventBufferMaxSize = bufferSize;
+  }
+
+  void newEvents(EventBufferElement[] evts) {
+
+    if((eventBuffer.size() + evts.length) >= eventBufferMaxSize) {
+      for(int i=0; i < evts.length; i++) {
+        eventBuffer.remove(0);
+      }
+      eventViewIndex -= evts.length;
+      if(eventViewIndex < 0)
+        eventViewIndex = 0;
+    }
+    for(int i=0; i < evts.length; i++)
+      eventBuffer.add(evts[i]);
+
+    if((eventBuffer.size() > maxR) && cbxTail.isSelected()) {
+      eventViewIndex = (eventBuffer.size() - maxR);
+    }
+
+    // only redraw if new line is visible...
+    if((maxR < 0) || (eventBuffer.size() >= eventViewIndex && eventBuffer.size() <= (eventViewIndex + maxR)))
+      drawText();
+  }
+
+  int maxR = -1;
+
+  void drawText() {
+    if(maxR < 0)
+      maxR =  textPane.getHeight() / textPane.getFontMetrics(textPane.getFont()).getHeight();
+    try {
+      doc.remove(0, doc.getLength());
+    } catch(Exception e) { e.printStackTrace(); }
+
+    for(int i=eventViewIndex; (i < eventBuffer.size()) && (i < (eventViewIndex + maxR)); i++) {
+      EventBufferElement evt = (EventBufferElement)eventBuffer.get(i);
+
+      try {
+        doc.insertString(doc.getLength(), evt.text, (MutableAttributeSet)fontAttributes.get(evt.prio));
+      } catch(Exception e) { e.printStackTrace(); }
+    }
+  }
+
+
+}
\ No newline at end of file

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/gui/LogTextPanel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/gui/TextPaneAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/gui/TextPaneAppender.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/gui/TextPaneAppender.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/gui/TextPaneAppender.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,354 @@
+/*
+ * 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.gui;
+
+
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.io.*;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Hashtable;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JTextPane;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyledDocument;
+import javax.swing.text.TabSet;
+import javax.swing.text.TabStop;
+
+import org.apache.log4j.*;
+
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.helpers.Loader;
+import org.apache.log4j.helpers.QuietWriter;
+import org.apache.log4j.helpers.TracerPrintWriter;
+import org.apache.log4j.helpers.OptionConverter;
+
+
+/**
+ * <b>Experimental</b> TextPaneAppender. <br>
+ *
+ *
+ * Created: Sat Feb 26 18:50:27 2000 <br>
+ *
+ * @author Sven Reimers
+ */
+public class TextPaneAppender extends AppenderSkeleton {
+    
+  JTextPane textpane;
+  StyledDocument doc;
+  TracerPrintWriter tp;
+  StringWriter sw;
+  QuietWriter qw;
+  Hashtable attributes;
+  Hashtable icons;
+  
+  private String label;
+  
+  private boolean fancy;
+    
+  final String LABEL_OPTION = "Label";
+  final String COLOR_OPTION_FATAL = "Color.Emerg";
+  final String COLOR_OPTION_ERROR = "Color.Error";
+  final String COLOR_OPTION_WARN = "Color.Warn";
+  final String COLOR_OPTION_INFO = "Color.Info";
+  final String COLOR_OPTION_DEBUG = "Color.Debug";
+  final String COLOR_OPTION_BACKGROUND = "Color.Background";
+  final String FANCY_OPTION = "Fancy";
+  final String FONT_NAME_OPTION = "Font.Name";
+  final String FONT_SIZE_OPTION = "Font.Size";
+  
+  public static Image loadIcon ( String path ) {
+    Image img = null;
+    try {
+      URL url = ClassLoader.getSystemResource(path);
+      img = (Image) (Toolkit.getDefaultToolkit()).getImage(url);
+    } catch (Exception e) {
+      System.out.println("Exception occured: " + e.getMessage() + 
+			 " - " + e );   
+    }	
+    return (img);
+  }
+  
+  public TextPaneAppender(Layout layout, String name) {
+    this();
+    this.layout = layout;
+    this.name = name;
+    setTextPane(new JTextPane());
+    createAttributes();
+    createIcons();
+  }
+    
+  public TextPaneAppender() {
+    super();
+    setTextPane(new JTextPane());
+    createAttributes();
+    createIcons();
+    this.label="";
+    this.sw = new StringWriter();
+    this.qw = new QuietWriter(sw, errorHandler);
+    this.tp = new TracerPrintWriter(qw);
+    this.fancy =true;
+  }
+
+  public
+  void close() {
+    
+  }
+  
+  private void createAttributes() {	
+    Priority prio[] = Priority.getAllPossiblePriorities();
+    
+    attributes = new Hashtable();
+    for (int i=0; i<prio.length;i++) {
+      MutableAttributeSet att = new SimpleAttributeSet();
+      attributes.put(prio[i], att);
+      StyleConstants.setFontSize(att,14);
+    }
+    StyleConstants.setForeground((MutableAttributeSet)attributes.get(Priority.ERROR),Color.red);
+    StyleConstants.setForeground((MutableAttributeSet)attributes.get(Priority.WARN),Color.orange);
+    StyleConstants.setForeground((MutableAttributeSet)attributes.get(Priority.INFO),Color.gray);
+    StyleConstants.setForeground((MutableAttributeSet)attributes.get(Priority.DEBUG),Color.black);
+  }
+
+  private void createIcons() {
+    Priority prio[] = Priority.getAllPossiblePriorities();
+    
+    icons = new Hashtable();
+    for (int i=0; i<prio.length;i++) {
+      if (prio[i].equals(Priority.FATAL))
+	icons.put(prio[i],new ImageIcon(loadIcon("icons/RedFlag.gif")));
+      if (prio[i].equals(Priority.ERROR))		
+	icons.put(prio[i],new ImageIcon(loadIcon("icons/RedFlag.gif")));
+      if (prio[i].equals(Priority.WARN))		
+	icons.put(prio[i],new ImageIcon(loadIcon("icons/BlueFlag.gif")));
+      if (prio[i].equals(Priority.INFO))		
+	icons.put(prio[i],new ImageIcon(loadIcon("icons/GreenFlag.gif")));
+      if (prio[i].equals(Priority.DEBUG))		
+	icons.put(prio[i],new ImageIcon(loadIcon("icons/GreenFlag.gif")));
+    }
+  }
+
+  public void append(LoggingEvent event) {
+    String text = this.layout.format(event);
+    String trace="";
+    // Print Stacktrace
+    // Quick Hack maybe there is a better/faster way?
+    if (event.throwable!=null) {
+      event.throwable.printStackTrace(tp);
+      for (int i=0; i< sw.getBuffer().length(); i++) {
+	if (sw.getBuffer().charAt(i)=='\t')
+	  sw.getBuffer().replace(i,i+1,"        ");
+      }
+      trace = sw.toString();
+      sw.getBuffer().delete(0,sw.getBuffer().length());
+    }
+    try {
+      if (fancy) {
+	textpane.setEditable(true);
+	textpane.insertIcon((ImageIcon)icons.get(event.priority));
+	textpane.setEditable(false);
+      }
+      doc.insertString(doc.getLength(),text+trace,
+		       (MutableAttributeSet)attributes.get(event.priority));
+	}	
+    catch (BadLocationException badex) {
+      System.err.println(badex);
+    }	
+    textpane.setCaretPosition(doc.getLength());
+  }
+  
+  public
+  JTextPane getTextPane() {
+    return textpane;
+  }
+  
+  private
+  static
+  Color parseColor (String v) {
+    StringTokenizer st = new StringTokenizer(v,",");
+    int val[] = {255,255,255,255};
+    int i=0;
+    while (st.hasMoreTokens()) {
+      val[i]=Integer.parseInt(st.nextToken());
+      i++;
+    }
+    return new Color(val[0],val[1],val[2],val[3]);
+  }
+  
+  private
+  static
+  String colorToString(Color c) {
+    // alpha component emitted only if not default (255)
+    String res = ""+c.getRed()+","+c.getGreen()+","+c.getBlue();
+    return c.getAlpha() >= 255 ? res : res + ","+c.getAlpha();
+  }
+
+  public
+  void setLayout(Layout layout) {
+    this.layout=layout;
+  }
+  
+  public
+  void setName(String name) {
+    this.name = name;
+  }
+  
+    
+  public
+  void setTextPane(JTextPane textpane) {
+    this.textpane=textpane;
+    textpane.setEditable(false);
+    textpane.setBackground(Color.lightGray);
+    this.doc=textpane.getStyledDocument();
+  }
+          
+  private
+  void setColor(Priority p, String v) {
+    StyleConstants.setForeground(
+		      (MutableAttributeSet)attributes.get(p),parseColor(v));	
+  }
+  
+  private
+  String getColor(Priority p) {
+    Color c =  StyleConstants.getForeground(
+		      (MutableAttributeSet)attributes.get(p));
+    return c == null ? null : colorToString(c);
+  }
+  
+  /////////////////////////////////////////////////////////////////////
+  // option setters and getters
+  
+  public
+  void setLabel(String label) {
+    this.label = label;
+  }
+  public
+  String getLabel() {
+    return label;
+  }
+  
+  public
+  void setColorEmerg(String color) {
+    setColor(Priority.FATAL, color);
+  }
+  public
+  String getColorEmerg() {
+    return getColor(Priority.FATAL);
+  }
+  
+  public
+  void setColorError(String color) {
+    setColor(Priority.ERROR, color);
+  }
+  public
+  String getColorError() {
+    return getColor(Priority.ERROR);
+  }
+  
+  public
+  void setColorWarn(String color) {
+    setColor(Priority.WARN, color);
+  }
+  public
+  String getColorWarn() {
+    return getColor(Priority.WARN);
+  }
+  
+  public
+  void setColorInfo(String color) {
+    setColor(Priority.INFO, color);
+  }
+  public
+  String getColorInfo() {
+    return getColor(Priority.INFO);
+  }
+  
+  public
+  void setColorDebug(String color) {
+    setColor(Priority.DEBUG, color);
+  }
+  public
+  String getColorDebug() {
+    return getColor(Priority.DEBUG);
+  }
+  
+  public
+  void setColorBackground(String color) {
+    textpane.setBackground(parseColor(color));
+  }
+  public
+  String getColorBackground() {
+    return colorToString(textpane.getBackground());
+  }
+  
+  public
+  void setFancy(boolean fancy) {
+    this.fancy = fancy;
+  }
+  public
+  boolean getFancy() {
+    return fancy;
+  }
+  
+  public
+  void setFontSize(int size) {
+    Enumeration e = attributes.elements();
+    while (e.hasMoreElements()) {
+      StyleConstants.setFontSize((MutableAttributeSet)e.nextElement(),size);
+    }
+    return;
+  }
+  
+  public
+  int getFontSize() {
+    AttributeSet attrSet = (AttributeSet) attributes.get(Priority.INFO);
+    return StyleConstants.getFontSize(attrSet);
+  }
+  
+  public
+  void setFontName(String name) {
+    Enumeration e = attributes.elements();
+    while (e.hasMoreElements()) {
+      StyleConstants.setFontFamily((MutableAttributeSet)e.nextElement(),name);
+    }
+    return;
+  }
+  
+  public
+  String getFontName() {
+    AttributeSet attrSet = (AttributeSet) attributes.get(Priority.INFO);
+    return StyleConstants.getFontFamily(attrSet);
+  }
+
+  public
+  boolean requiresLayout() {
+    return true;
+  }
+} // TextPaneAppender
+
+
+

Propchange: logging/log4j/branches/log4j12-bz53299/modules/contribs/src/stale/org/apache/log4j/gui/TextPaneAppender.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message