You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gr...@apache.org on 2012/06/02 13:41:11 UTC

svn commit: r1345492 [10/18] - in /logging/log4j/branches/log4j12modules: ./ contribs/ contribs/CekiGulcu/ contribs/EirikLygre/ contribs/JamesHouse/ contribs/Jamie Tsao/ contribs/JimMoore/ contribs/KevinSteppe/ contribs/KitchingSimon/ contribs/LeosLite...

Copied: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/LeosLiterak/mail (from r1345481, logging/log4j/branches/log4j12modules/contribs/LeosLiterak/mail)
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/LeosLiterak/mail?p2=logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/LeosLiterak/mail&p1=logging/log4j/branches/log4j12modules/contribs/LeosLiterak/mail&r1=1345481&r2=1345492&rev=1345492&view=diff
==============================================================================
    (empty)

Copied: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/MarkDouglas/Log.txt (from r1345481, logging/log4j/branches/log4j12modules/contribs/MarkDouglas/Log.txt)
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/MarkDouglas/Log.txt?p2=logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/MarkDouglas/Log.txt&p1=logging/log4j/branches/log4j12modules/contribs/MarkDouglas/Log.txt&r1=1345481&r2=1345492&rev=1345492&view=diff
==============================================================================
    (empty)

Propchange: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/MarkDouglas/Log.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/MarkDouglas/Log.txt
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/MarkDouglas/mail-2001-01-17 (from r1345481, logging/log4j/branches/log4j12modules/contribs/MarkDouglas/mail-2001-01-17)
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/MarkDouglas/mail-2001-01-17?p2=logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/MarkDouglas/mail-2001-01-17&p1=logging/log4j/branches/log4j12modules/contribs/MarkDouglas/mail-2001-01-17&r1=1345481&r2=1345492&rev=1345492&view=diff
==============================================================================
    (empty)

Copied: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/VolkerMentzner/mail-03-05-2001 (from r1345481, logging/log4j/branches/log4j12modules/contribs/VolkerMentzner/mail-03-05-2001)
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/VolkerMentzner/mail-03-05-2001?p2=logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/contribs/VolkerMentzner/mail-03-05-2001&p1=logging/log4j/branches/log4j12modules/contribs/VolkerMentzner/mail-03-05-2001&r1=1345481&r2=1345492&rev=1345492&view=diff
==============================================================================
    (empty)

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/AppenderTable.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/AppenderTable.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/AppenderTable.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/AppenderTable.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,248 @@
+/*
+ * 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 org.apache.log4j.helpers.CyclicBuffer;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Layout;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.spi.LoggingEvent;
+
+import javax.swing.JFrame;
+import javax.swing.JButton;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.JScrollPane;
+import javax.swing.BoxLayout;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.Container;
+
+/**
+   The AppenderTable illustrates one possible implementation of
+   an Table possibly containing a great many number of rows.
+
+   <p>In this particular example we use a fixed size buffer
+   (CyclicBuffer) although this data structure could be easily
+   replaced by dynamically growing one, such as a Vector. The required
+   properties of the data structure is 1) support for indexed element
+   access 2) support for the insertion of new elements at the end.
+
+   <p>Experimentation on my 1400Mhz AMD machine show that it takes
+   about 45 micro-seconds to insert an element in the table. This
+   number does not depend on the size of the buffer. It takes as much
+   (or as little) time to insert one million elements to a buffer of
+   size 10 as to a buffer of size 10'000. It takes about 4 seconds to
+   insert a total of 100'000 elements into the table.
+
+   <p>On windows NT the test will run about twice as fast if you give
+   the focus to the window that runs "java AppenderTable" and not the
+   window that contains the Swing JFrame.  
+   
+   @author CekiGulcu */
+public class AppenderTable extends JTable {
+
+
+  static Logger logger = Logger.getLogger(AppenderTable.class);
+
+  static public void main(String[] args) {
+
+    if(args.length != 2) {
+      System.err.println(
+      "Usage: java AppenderTable bufferSize runLength\n"
+      +"  where bufferSize is the size of the cyclic buffer in the TableModel\n"
+      +"  and runLength is the total number of elements to add to the table in\n"
+      +"  this test run.");
+      return;
+    }
+
+    JFrame frame = new JFrame("JTableAppennder test");
+    Container container = frame.getContentPane();
+
+    AppenderTable tableAppender = new AppenderTable();
+    
+    int bufferSize = Integer.parseInt(args[0]);
+    AppenderTableModel model = new AppenderTableModel(bufferSize);
+    tableAppender.setModel(model);
+
+    int runLength = Integer.parseInt(args[1]);
+
+    JScrollPane sp = new JScrollPane(tableAppender);
+    sp.setPreferredSize(new Dimension(250, 80));
+    
+    container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
+    container.add(sp);
+
+    // The "ADD" button is intended for manual testing. It will
+    // add one new logging event to the table.
+    JButton button = new JButton("ADD");
+    container.add(button);
+    button.addActionListener(new AppTableJTableAddAction(tableAppender));
+
+    frame.setSize(new Dimension(500,300));
+    frame.setVisible(true);
+
+    long before = System.currentTimeMillis();
+
+    int i = 0;
+    while(i++ < runLength) {      
+      LoggingEvent event = new LoggingEvent("x", logger, Level.ERROR, 
+					    "Message "+i, null);
+      tableAppender.doAppend(event);
+    }
+
+    long after = System.currentTimeMillis();
+
+    long totalTime = (after-before);
+    
+    System.out.println("Total time :"+totalTime+ " milliseconds for "+
+		       "runLength insertions.");
+    System.out.println("Average time per insertion :"
+		       +(totalTime*1000/runLength)+ " micro-seconds.");
+
+
+  }
+
+  public
+  AppenderTable() {
+    this.setDefaultRenderer(Object.class, new Renderer());
+  }
+
+  /**
+     When asked to append we just insert directly into the model. In a
+     real appender we would use two buffers one for accumulating
+     events and another to accumalte events but after filtering. Only
+     the second buffer would be displayed in the table and made
+     visible to the user.*/
+  public
+  void doAppend(LoggingEvent event) {
+    ((AppenderTableModel)getModel()).insert(event);
+  }
+
+  /**
+     The Renderer is required to display object in a friendlier from.
+     This particular renderer is just a JTextArea.
+
+     <p>The important point to note is that we only need *one*
+     renderer. */
+  class Renderer extends JTextArea implements TableCellRenderer {
+
+    PatternLayout layout;
+
+    public
+    Renderer() {
+      layout = new PatternLayout("%r %p %c [%t] -  %m");
+    }
+
+    public Component getTableCellRendererComponent(JTable table,
+						   Object value,
+						   boolean isSelected,
+						   boolean hasFocus,
+						   int row,
+						   int column) {
+
+      // If its a LoggingEvent than format it using our layout.
+      if(value instanceof LoggingEvent) {
+	LoggingEvent event = (LoggingEvent) value;
+	String str = layout.format(event);
+	setText(str);
+      } else {
+	setText(value.toString());
+      }
+      return this;
+    }
+  }
+}
+
+class AppenderTableModel extends AbstractTableModel {
+
+  CyclicBuffer cb;
+  
+  AppenderTableModel(int size) {
+    cb = new CyclicBuffer(size);
+  }
+
+  /**
+     Insertion to the model always results in a fireTableDataChanged
+     method call. Suprisingly enough this has no crippling impact on
+     performance.  */
+  public
+  void insert(LoggingEvent event) {
+    cb.add(event);
+    fireTableDataChanged();
+  }
+
+  /**
+     We assume only one column.
+  */
+  public 
+  int getColumnCount() { 
+    return 1; 
+  }
+  
+  /**
+     The row count is given by the number of elements in the
+     buffer. This number is guaranteed to be between 0 and the buffer
+     size (inclusive). */
+  public int getRowCount() { 
+    return cb.length();
+  }
+  
+  /**
+     Get the value in a given row and column. We suppose that there is
+     only one colemn so we are only concerned with the row.
+
+     <p>Interesting enough this method returns an object. This leaves
+     the door open for a TableCellRenderer to render the object in
+     a variety of ways.
+  */
+  public 
+  Object getValueAt(int row, int col) {
+    return cb.get(row);
+  }
+}
+
+
+/**
+   The JTableAddAction is called when the user clicks on the "ADD"
+   button.
+*/
+class AppTableJTableAddAction implements ActionListener {
+    
+  AppenderTable appenderTable;
+  Logger dummy = Logger.getLogger("x");
+  int counter = 0;
+  public
+  AppTableJTableAddAction(AppenderTable appenderTable) {
+    this.appenderTable = appenderTable;
+  }
+    
+  public
+  void actionPerformed(ActionEvent e) {
+    counter++;
+    LoggingEvent event = new LoggingEvent("x", dummy, Level.DEBUG, 
+					  "Message "+counter, null);    
+    appenderTable.doAppend(event);
+  }
+}

Propchange: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/AppenderTable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/JListView.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/JListView.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/JListView.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/JListView.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,368 @@
+/*
+ * 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 org.apache.log4j.helpers.CyclicBuffer;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.Priority;
+import org.apache.log4j.Category;
+import org.apache.log4j.Layout;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.spi.LoggingEvent;
+
+import javax.swing.JList;
+import javax.swing.AbstractListModel;
+import javax.swing.JFrame;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.JScrollPane;
+import javax.swing.ListCellRenderer;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+import javax.swing.BoxLayout;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.Container;
+import javax.swing.ImageIcon;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.net.URL;
+import java.awt.Rectangle;
+
+/**
+ * @author Sven Reimers
+ */
+public class JListView extends JList {
+
+
+  static Category cat = Category.getInstance(JListView.class.getName());
+
+
+  //JListViewModel model;
+  PatternLayout layout;
+
+  static LoggingEvent proto = new LoggingEvent("x", cat, Priority.ERROR, 
+					       "Message ", new Throwable());
+
+  public
+  JListView(JListViewModel model) {
+    super(model);
+    layout = new PatternLayout("%r %p %c [%t] -  %m");
+    //this.setModel(model);
+    this.setCellRenderer(new MyCellRenderer());
+    //    setFixedCellWidth(10);
+    //setFixedCellHeight(20);
+
+  }
+
+  public
+  void add(LoggingEvent event) {
+    ((JListViewModel)getModel()).add(event);
+  }
+
+  /*
+  public
+  Dimension getPreferredSize() {
+    System.out.println("getPreferredSize() called");
+    return super.getPreferredSize();
+  }
+
+
+  public
+  int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
+				 int direction) {
+    System.out.println("getScrollableUnitIncrement called with " + visibleRect +
+		       "orientation: "+orientation+", direction: "+direction);
+    return super.getScrollableUnitIncrement(visibleRect, orientation, 
+    				    direction);
+  }
+
+  public
+  int getScrollableBlockIncrement(Rectangle visibleRect, int orientation,
+				  int direction) {
+    System.out.println("getScrollableBlockIncrement called with " + 
+		       visibleRect + "orientation: "+orientation+
+		       ", direction: "+direction);
+    return super.getScrollableBlockIncrement(visibleRect, orientation, 
+    				     direction);
+  }
+  */
+
+  //public
+  //boolean getScrollableTracksViewportWidth() {
+  //System.out.println("getScrollableTracksViewportWidth called.");
+  //return true;
+    //boolean b = super.getScrollableTracksViewportWidth();
+    //System.out.println("result is: "+b);
+    //return b;
+  //}
+  
+  //public
+  //boolean getScrollableTracksViewportHeight() { 
+  // System.out.println("getScrollableTracksViewportHeight called.");
+  // return true;
+     //boolean b = super.getScrollableTracksViewportHeight();
+     //System.out.println("result is: "+b);
+     //return b;
+  //}
+
+  //public 
+  //int getFirstVisibleIndex() {
+  //int r = getFirstVisibleIndex(); 
+  // System.out.println("----------getFirstVisibleIndex called, result: "+r);
+  //return r;
+  //}
+
+  //public
+  //Object getPrototypeCellValue() {
+  //return proto;
+  //}
+
+  
+  
+  static public void main(String[] args) {
+
+    JFrame frame = new JFrame("JListView test");
+    Container container = frame.getContentPane();
+
+    JListView view = new JListView(new JListViewModel(Integer.parseInt(args[0])));
+
+
+    JScrollPane sp = new JScrollPane(view);
+    sp.setPreferredSize(new Dimension(250, 80));
+    
+    container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
+    //container.add(view);
+    container.add(sp);
+
+    JButton b1 = new JButton("Add 1");
+    JButton b10 = new JButton("Add 10");
+    JButton b100 = new JButton("Add 100");
+    JButton b1000 = new JButton("Add 1000");
+    JButton b10000 = new JButton("Add 10000");
+
+    JPanel panel = new JPanel(new GridLayout(0,1));
+    container.add(panel);
+
+    panel.add(b1);
+    panel.add(b10);
+    panel.add(b100);
+    panel.add(b1000);
+    panel.add(b10000);
+    
+
+    AddAction a1 = new AddAction(view, 1);
+    AddAction a10 = new AddAction(view, 10);
+    AddAction a100 = new AddAction(view, 100);
+    AddAction a1000 = new AddAction(view, 1000);
+    AddAction a10000 = new AddAction(view, 10000);
+
+    b1.addActionListener(a1);
+    b10.addActionListener(a10);
+    b100.addActionListener(a100);
+    b1000.addActionListener(a1000);
+    b10000.addActionListener(a10000);
+
+    frame.setVisible(true);
+    frame.setSize(new Dimension(700,700));
+
+    long before = System.currentTimeMillis();
+
+    int RUN = 1000;
+    int i = 0;
+    while(i++ < RUN) {      
+      LoggingEvent event0 = new LoggingEvent("x", cat, Priority.ERROR, 
+					     "Message "+i, null);
+      
+      Throwable t = new Exception("hello "+i);
+      LoggingEvent event1 = new LoggingEvent("x", cat, Priority.ERROR, 
+					     "Message "+i, t);
+      
+
+      if(i % 10 == 0) {	
+	event1.getThreadName();
+	view.add(event1);
+      } else {
+	event0.getThreadName();
+	view.add(event0);
+      }
+    }
+
+    long after = System.currentTimeMillis();
+    System.out.println("Time taken :"+ ((after-before)*1000/RUN));
+
+  }
+
+  class MyCellRenderer extends JTextArea implements ListCellRenderer {
+
+    Object o = new Object();
+    int i = 0;
+    final ImageIcon longIcon = new ImageIcon("RedFlag.gif");
+
+    public
+    MyCellRenderer() {
+      System.out.println("----------------------");
+      
+    }
+
+
+
+    public
+    int getTabSize()  {
+      return 2;
+    }
+
+    public 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 Component getListCellRendererComponent(JList list,
+						Object value, 
+						int index, // cell index
+						boolean isSelected, 
+						boolean cellHasFocus) {
+
+      //      System.out.println(o + " ============== " + i++);
+      //LogLog.error("=======", new Exception());
+      //setIcon(longIcon);
+      if(value instanceof LoggingEvent) {
+	LoggingEvent event = (LoggingEvent) value;
+	String str = layout.format(event);
+	String t = event.getThrowableInformation().toString();
+
+	if(t != null) {
+	  setText(str + Layout.LINE_SEP + t);
+	} else {	
+	  setText(str);
+	}
+	
+      } else {
+	setText(value.toString());
+      }
+
+
+      return this;
+    }
+  }
+}
+
+
+
+class JListViewModel extends AbstractListModel {
+
+  CyclicBuffer cb;
+  
+  JListViewModel(int size) {
+    cb = new CyclicBuffer(size);
+  }
+
+  public
+  void add(LoggingEvent event) {
+    //System.out.println("JListViewModel.add called");
+    cb.add(event);
+    int j = cb.length();
+    fireContentsChanged(this, 0, j);
+  }
+    
+
+
+  public
+  Object getElementAt(int index) {
+    return cb.get(index);
+  }
+
+  public
+  int getSize() {
+    return cb.length();
+  }
+  
+}
+
+class AddAction implements ActionListener {
+
+  Thread t;
+
+  static int counter = 0;
+
+  public
+  AddAction(JListView view, int burst) {
+    this.t = new AddThread(view, burst);
+    t.start();
+  }
+    
+  public
+  void actionPerformed(ActionEvent e) {
+    System.out.println("Action occured");
+    synchronized(t) {
+      t.notify();
+    }
+  }
+
+  class AddThread extends Thread {
+    int burst;
+    JListView view;
+
+    Category cat = Category.getInstance("x");
+    
+    AddThread(JListView view, int burst) {
+      super();
+      this.burst = burst;
+      this.view = view;
+      setName("AddThread"+burst);
+    }
+
+    public
+    void run() {
+
+      while(true) {
+	synchronized(this) {
+	  try {
+	    this.wait();
+	  } catch(Exception e) {
+	  }
+	}
+	for(int i = 0; i < burst; i++) {
+	  LoggingEvent event = new LoggingEvent("x", cat, Priority.DEBUG, 
+						"Message "+counter, null);
+
+	  event.getThreadName();    
+	  if(counter % 50 == 0) {
+	    //event.throwable = new Exception("hello "+counter);
+	  }
+	  counter++;
+	  view.add(event);
+	}
+      }
+    }
+  }
+}

Propchange: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/JListView.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/JTableAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/JTableAppender.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/JTableAppender.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/JTableAppender.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,239 @@
+/*
+ * 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 org.apache.log4j.helpers.CyclicBuffer;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.Priority;
+import org.apache.log4j.Category;
+import org.apache.log4j.Layout;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.spi.LoggingEvent;
+
+import javax.swing.JList;
+import javax.swing.AbstractListModel;
+import javax.swing.JFrame;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.JScrollPane;
+import javax.swing.ListCellRenderer;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import javax.swing.BoxLayout;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.Container;
+import javax.swing.ImageIcon;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.net.URL;
+import java.awt.Rectangle;
+
+/**
+ * @author Sven Reimers
+ */
+public class JTableAppender extends JTable {
+
+  static Category cat = Category.getInstance(JTableAppender.class.getName());
+
+  PatternLayout layout;
+
+  public
+  JTableAppender() {
+    layout = new PatternLayout("%r %p %c [%t] -  %m");
+    this.setDefaultRenderer(Object.class, new Renderer());
+
+  }
+
+  public
+  void add(LoggingEvent event) {
+    ((JTableAppenderModel)getModel()).add(event);
+  }
+
+  public
+  Dimension getPreferredSize() {
+    System.out.println("getPreferredSize() called");
+    return super.getPreferredSize();
+  }
+
+  static public void main(String[] args) {
+
+    JFrame frame = new JFrame("JListView test");
+    Container container = frame.getContentPane();
+
+    JTableAppender appender = new JTableAppender();
+    
+    JTableAppenderModel model = new 
+                              JTableAppenderModel(Integer.parseInt(args[0]));
+    appender.setModel(model);
+    //appender.createDefaultColumnsFromModel();    
+
+
+    JScrollPane sp = new JScrollPane(appender);
+    sp.setPreferredSize(new Dimension(250, 80));
+    
+    container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
+    //container.add(view);
+    container.add(sp);
+
+    JButton button = new JButton("ADD");
+    container.add(button);
+    
+
+    button.addActionListener(new JTableAppenderJTableAddAction(appender));
+
+    frame.setVisible(true);
+    frame.setSize(new Dimension(700,700));
+
+    long before = System.currentTimeMillis();
+
+    int RUN = 10000;
+    int i = 0;
+    while(i++ < RUN) {      
+      LoggingEvent event = new LoggingEvent("x", cat, Priority.ERROR, 
+					    "Message "+i, null);
+      event.getThreadName();
+      if(i % 10 == 0) {
+	//event.throwable = new Exception("hello "+i);
+      }
+      appender.add(event);
+    }
+
+    long after = System.currentTimeMillis();
+    System.out.println("Time taken :"+ ((after-before)*1000/RUN));
+
+  }
+
+  class Renderer extends JTextArea implements TableCellRenderer {
+
+    Object o = new Object();
+    int i = 0;
+
+    public
+    Renderer() {
+      System.out.println("Render() called ----------------------");      
+    }
+
+    public Component getTableCellRendererComponent(JTable table,
+						   Object value,
+						   boolean isSelected,
+						   boolean hasFocus,
+						   int row,
+						   int column) {
+
+      System.out.println(o + " ============== " + i++);
+      //LogLog.error("=======", new Exception());
+      //setIcon(longIcon);
+      if(value instanceof LoggingEvent) {
+	LoggingEvent event = (LoggingEvent) value;
+	String str = layout.format(event);
+	String t = event.getThrowableInformation().toString();
+	
+	if(t != null) {
+	  System.out.println("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
+	  setText(str + Layout.LINE_SEP + t);
+	} else {	
+	  setText(str);
+	}
+	
+      } else {
+	setText(value.toString());
+      }
+
+
+      return this;
+    }
+  }
+}
+
+
+
+class JTableAppenderModel extends AbstractTableModel {
+
+  CyclicBuffer cb;
+  
+  JTableAppenderModel(int size) {
+    cb = new CyclicBuffer(size);
+  }
+
+  public
+  void add(LoggingEvent event) {
+    //System.out.println("JListViewModel.add called");
+    cb.add(event);
+    int j = cb.length();
+
+    fireTableDataChanged();
+
+  }
+  public 
+  int getColumnCount() { 
+    return 1; 
+  }
+
+  public int getRowCount() { 
+    return cb.length();
+  }
+
+  //public
+  //Class getColumnClass(int index) {
+  //  System.out.println("getColumnClass called " + index);
+  //  return LoggingEvent.class;
+  //}
+
+  public 
+  Object getValueAt(int row, int col) {
+    return cb.get(row);
+  }
+}
+
+
+class JTableAppenderJTableAddAction implements ActionListener {
+    
+  int j;
+  JTableAppender appender;
+
+  Category cat = Category.getInstance("x");
+  
+  public
+  JTableAppenderJTableAddAction(JTableAppender appender) {
+    this.appender = appender;
+    j = 0;
+  }
+    
+  public
+  void actionPerformed(ActionEvent e) {
+    System.out.println("Action occured");
+
+    LoggingEvent event = new LoggingEvent("x", cat, Priority.DEBUG, 
+					    "Message "+j, null);
+    
+    if(j % 5 == 0) {
+      //event.throwable = new Exception("hello "+j);
+    }
+    j++;
+    appender.add(event);
+  }
+}

Propchange: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/gui/JTableAppender.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/DatagramStringWriter.java (from r1345481, logging/log4j/branches/log4j12modules/contribs/KitchingSimon/DatagramStringWriter.java)
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/DatagramStringWriter.java?p2=logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/DatagramStringWriter.java&p1=logging/log4j/branches/log4j12modules/contribs/KitchingSimon/DatagramStringWriter.java&r1=1345481&r2=1345492&rev=1345492&view=diff
==============================================================================
    (empty)

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

Propchange: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/DatagramStringWriter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/HTTPRequestHandler.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/HTTPRequestHandler.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/HTTPRequestHandler.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/HTTPRequestHandler.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,75 @@
+/*
+ * 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.*;
+
+/**
+ * This interface defines all methods that have to be implemented for a HTTPRequestHandler for the
+ * PluggableHTTPServer.
+ *
+ * @author <a HREF="mailto:V.Mentzner@psi-bt.de">Volker Mentzner</a>
+ */
+public interface HTTPRequestHandler {
+
+ /**
+   * Gets the title for html page
+   */
+  public String getTitle();
+
+ /**
+   * Sets the title for html page
+   */
+  public void setTitle(String title);
+
+ /**
+   * Gets the description for html page
+   */
+  public String getDescription();
+
+ /**
+   * Sets the description for html page
+   */
+  public void setDescription(String description);
+
+ /**
+   * Gets the virtual path in the HTTP server that ist handled in this HTTPRequestHandler.
+   * So the root path handler will return "/" (without brackets) because it handles the path
+   * "http://servername/" or a handler for "http://servername/somepath/" will return "/somepath/"
+   * It is important to include the trailing "/" because all HTTPRequestHandler have to serve a path!
+   */
+  public String getHandledPath();
+
+ /**
+   * Sets the virtual path in the HTTP server that ist handled in this HTTPRequestHandler.
+   * So set the path to "/" for the root path handler because it handles the path
+   * "http://servername/" or set it to "/somepath/" for a handler for "http://servername/somepath/".
+   * It is important to include the trailing "/" because all HTTPRequestHandler have to serve a path!
+   */
+  public void setHandledPath(String path);
+
+ /**
+   * Handles the given request and writes the reply to the given out-stream. Every handler has to check
+   * the request for the right path info.
+   *
+   * @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);
+}
\ No newline at end of file

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

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCAppender.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCAppender.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCAppender.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,601 @@
+/*
+ * 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.*;
+
+/**
+The JDBCAppender, writes messages into a database
+
+<p><b>The JDBCAppender is configurable at runtime by setting options in two alternatives : </b></p>
+<dir>
+	<p><b>1. Use a configuration-file</b></p>
+	<p>Define the options in a file (<A HREF="configfile_example.txt">example</A>) and call a <code>PropertyConfigurator.configure(filename)</code> in your code.</p>
+	<p><b>2. Use the methods of JDBCAppender to do it</b></p>
+	<p>Call <code>JDBCAppender::setOption(JDBCAppender.xxx_OPTION, String value)</code> to do it analogically without a configuration-file (<A HREF="code_example2.java">example</A>)</p>
+</dir>
+
+<p>All available options are defined as static String-constants in JDBCAppender named xxx_OPTION.</p>
+
+<p><b>Here is a description of all available options :</b></p>
+<dir>
+	<p><b>1. Database-options to connect to the database</b></p>
+	<p>- <b>URL_OPTION</b>			: a database url of the form jdbc:subprotocol:subname</p>
+	<p>- <b>USERNAME_OPTION</b>	: the database user on whose behalf the connection is being made</p>
+	<p>- <b>PASSWORD_OPTION</b>	: the user's password</p>
+
+	<p><b>2. Connector-option to specify your own JDBCConnectionHandler</b></p>
+	<p>- <b>CONNECTOR_OPTION</b>	: a classname which is implementing the JDBCConnectionHandler-interface</p>
+	<p>This interface is used to get a customized connection.</p>
+	<p>If in addition the database-options are given, these options will be used as arguments for the JDBCConnectionHandler-interface to get a connection.</p>
+	<p>Else if no database-options are given, the JDBCConnectionHandler-interface is called without them.</p>
+	<p>Else if this option is not defined, the database-options are required to open a connection by the JDBCAppender.</p>
+
+	<p><b>3. SQL-option to specify a static sql-statement which will be performed with every occuring message-event</b></p>
+	<p>- <b>SQL_OPTION</b>			: a sql-statement which will be used to write to the database</p>
+	<p>Use the variable <b>@MSG@</b> on a location in the statement, which has to be dynamically replaced by the message-text.</p>
+	<p>If you give this option, the table-option and columns-option will be ignored !</p>
+
+	<p><b>4. Table-option to specify a table contained by the database</b></p>
+	<p>- <b>TABLE_OPTION</b>		: the table in which the logging will be done</p>
+
+	<p><b>5. Columns-option to describe the important columns of the table (Not nullable columns are mandatory to describe!)</b></p>
+	<p>- <b>COLUMNS_OPTION</b>		: a formatted list of column-descriptions</p>
+	<p>Each column description consists of</p>
+	<dir>
+		<p>- the <b><i>name</i></b> of the column (required)</p>
+		<p>- a <b><i>logtype</i></b> which is a static constant of class LogType (required)</p>
+		<p>- and a <b><i>value</i></b> which depends by the LogType (optional/required, depending by logtype)</p>
+	</dir>
+	<p>Here is a description of the available logtypes of class <b>{@link LogType}</b> and how to handle the <b><i>value</i></b>:</p>
+	<dir>
+		<p>o <b>MSG</b>			= a value will be ignored, the column will get the message. (One columns need to be of this type!)</p>
+		<p>o <b>STATIC</b>		= 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!)</p>
+		<p>o <b>ID</b>			= value must be a classname, which implements the JDBCIDHandler-interface.</p>
+		<p>o <b>TIMESTAMP</b>	= a value will be ignored, the column will be filled with a actually timestamp with every logged message.</p>
+		<p>o <b>EMPTY</b>		= 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!)</p>
+	</dir>
+	<p>If there are more than one column to describe, the columns must be separated by a Tabulator-delimiter (unicode0008) !</p>
+	<p>The arguments of a column-description must be separated by the delimiter '~' !</p>
+	<p><i>(Example :  name1~logtype1~value1   name2~logtype2~value2...)</i></p>
+
+	<p><b>6. Layout-options to define the layout of the messages (optional)</b></p>
+	<p>- <b>_</b> : the layout wont be set by a xxx_OPTION</p>
+	<p>See the configuration-file and code examples below...</p>
+	<p>The default is a layout of the class {@link org.apache.log4j.PatternLayout} with the pattern=%m which representate only the message.</p>
+
+	<p><b>7. Buffer-option to define the size of the message-event-buffer (optional)</b></p>
+	<p>- <b>BUFFER_OPTION</b>		: define how many messages will be buffered until they will be updated to the database.</p>
+	<p>The default is buffer=1, which will do a update with every happened message-event.</p>
+
+	<p><b>8. Commit-option to define a auto-commitment</b></p>
+	<p>- <b>COMMIT_OPTION</b>		: define whether updated messages should be committed to the database (Y) or not (N).</p>
+	<p>The default is commit=Y.</p>
+</dir>
+
+<p><b>The sequence of some options is important :</b></p>
+<dir>
+	<p><b>1. Connector-option OR/AND Database-options</b></p>
+	<p>Any database connection is required !</p>
+	<p><b>2. (Table-option AND Columns-option) OR SQL-option</b></p>
+	<p>Anything of that is required ! Whether where to write something OR what to write somewhere...;-)</p>
+	<p><b>3. All other options can be set at any time...</b></p>
+	<p>The other options are optional and have a default initialization, which can be customized.</p>
+</dir>
+
+<p><b>Here is a <b>configuration-file example</b>, which can be used as argument for the <b>PropertyConfigurator</b> : </b><A HREF="configfile_example.txt"> configfile_example.txt</A></p>
+
+<p><b>Here is a <b>code-example</b> to configure the JDBCAppender <b>with a configuration-file</b> : </b><A HREF="code_example1.java"> code_example1.java</A></p>
+
+<p><b>Here is a <b>another code-example</b> to configure the JDBCAppender <b>without a configuration-file</b> : </b><A HREF="code_example2.java"> code_example2.java</A></p>
+
+
+
+<p><b>Author : </b><A HREF="mailto:t.fenner@klopotek.de">Thomas Fenner</A></p>
+
+@since 1.0
+*/
+public class JDBCAppender extends AppenderSkeleton
+{
+	/**
+	A database-option to to set a database url of the form jdbc:subprotocol:subname.
+	*/
+	public static final String URL_OPTION			= "url";
+
+	/**
+	A database-option to set the database user on whose behalf the connection is being made.
+	*/
+	public static final String USERNAME_OPTION	= "username";
+
+	/**
+	A database-option to set the user's password.
+	*/
+	public static final String PASSWORD_OPTION	= "password";
+
+	/**
+	A table-option to specify a table contained by the database
+	*/
+	public static final String TABLE_OPTION		= "table";
+
+	/**
+	A connector-option to specify your own JDBCConnectionHandler
+	*/
+	public static final String CONNECTOR_OPTION	= "connector";
+
+	/**
+   A columns-option to describe the important columns of the table
+	*/
+	public static final String COLUMNS_OPTION		= "columns";
+
+	/**
+	A sql-option to specify a static sql-statement which will be performed with every occuring message-event
+   */
+	public static final String SQL_OPTION			= "sql";
+
+	/**
+   A buffer-option to define the size of the message-event-buffer
+	*/
+	public static final String BUFFER_OPTION		= "buffer";
+
+	/**
+   A commit-option to define a auto-commitment
+	*/
+	public static final String COMMIT_OPTION		= "commit";
+
+
+	//Variables to store the options values setted by setOption() :
+	private String url		= null;
+	private String username	= null;
+	private String password	= null;
+	private String table		= null;
+	private String connection_class = null;
+	private String sql		= null;
+	private boolean docommit = true;
+	private int buffer_size	= 1;
+   private JDBCConnectionHandler connectionHandler = null;
+
+	//This buffer stores message-events.
+   //When the buffer_size is reached, the buffer will be flushed and the messages will updated to the database.
+	private ArrayList buffer = new ArrayList();
+
+   //Database-connection
+	private Connection con = null;
+
+	//This class encapsulate the logic which is necessary to log into a table
+	private JDBCLogger jlogger = new JDBCLogger();
+
+   //Flags :
+   //A flag to indicate a established database connection
+	private boolean connected = false;
+   //A flag to indicate configuration status
+	private boolean configured = false;
+   //A flag to indicate that everything is ready to get append()-commands.
+	private boolean ready = false;
+
+	/**
+	If program terminates close the database-connection and flush the buffer
+   */
+	public void finalize()
+	{
+		close();
+      super.finalize();
+	}
+
+	/**
+	Internal method. Returns a array of strings containing the available options which can be set with method setOption()
+	*/
+	public String[] getOptionStrings()
+   {
+   	// The sequence of options in this string is important, because setOption() is called this way ...
+		return new String[]{CONNECTOR_OPTION, URL_OPTION, USERNAME_OPTION, PASSWORD_OPTION, SQL_OPTION, TABLE_OPTION, COLUMNS_OPTION, BUFFER_OPTION, COMMIT_OPTION};
+	}
+
+
+	/**
+     Sets all necessary options
+	*/
+	public void setOption(String _option, String _value)
+	{
+   	_option = _option.trim();
+      _value = _value.trim();
+
+		if(_option == null || _value == null) return;
+		if(_option.length() == 0 || _value.length() == 0) return;
+
+      _value = _value.trim();
+
+		if(_option.equals(CONNECTOR_OPTION))
+      {
+      	if(!connected) connection_class = _value;
+      }
+		else if(_option.equals(URL_OPTION))
+		{
+			if(!connected) url = _value;
+		}
+		else if(_option.equals(USERNAME_OPTION))
+		{
+			if(!connected) username = _value;
+		}
+		else if(_option.equals(PASSWORD_OPTION))
+		{
+			if(!connected) password = _value;
+		}
+		else if(_option.equals(SQL_OPTION))
+      {
+			sql = _value;
+      }
+		else if(_option.equals(TABLE_OPTION))
+      {
+      	if(sql != null) return;
+      	table = _value;
+      }
+		else if(_option.equals(COLUMNS_OPTION))
+      {
+      	if(sql != null) return;
+
+			String name = null;
+         int logtype = -1;
+         String value = null;
+         String column = null;
+         String arg = null;
+         int num_args = 0;
+         int num_columns = 0;
+			StringTokenizer st_col;
+			StringTokenizer st_arg;
+
+         //Columns are TAB-separated
+			st_col = new StringTokenizer(_value,  "	");
+
+			num_columns = st_col.countTokens();
+
+         if(num_columns < 1)
+  	      {
+     	   	errorHandler.error("JDBCAppender::setOption(), Invalid COLUMN_OPTION value : " + _value + " !");
+            return;
+        	}
+
+         for(int i=1; i<=num_columns; i++)
+         {
+				column = st_col.nextToken();
+
+            //Arguments are ~-separated
+				st_arg = new StringTokenizer(column, "~");
+
+				num_args = st_arg.countTokens();
+
+	         if(num_args < 2)
+   	      {
+      	   	errorHandler.error("JDBCAppender::setOption(), Invalid COLUMN_OPTION value : " + _value + " !");
+               return;
+         	}
+
+	         for(int j=1; j<=num_args; j++)
+   	      {
+					arg = st_arg.nextToken();
+
+					if(j == 1) name = arg;
+					else if(j == 2)
+      	      {
+         	   	try
+            	   {
+							logtype = Integer.parseInt(arg);
+	               }
+   	            catch(Exception e)
+      	         {
+         	      	logtype = LogType.parseLogType(arg);
+	               }
+
+						if(!LogType.isLogType(logtype))
+   	            {
+	   	            errorHandler.error("JDBCAppender::setOption(), Invalid COLUMN_OPTION LogType : " + arg + " !");
+                     return;
+         	      }
+            	}
+					else if(j == 3) value = arg;
+   	      }
+
+	         if(!setLogType(name, logtype, value)) return;
+         }
+      }
+		else if(_option.equals(BUFFER_OPTION))
+      {
+        	try
+         {
+				buffer_size = Integer.parseInt(_value);
+         }
+         catch(Exception e)
+         {
+	         errorHandler.error("JDBCAppender::setOption(), Invalid BUFFER_OPTION value : " + _value + " !");
+				return;
+         }
+      }
+		else if(_option.equals(COMMIT_OPTION))
+      {
+      	docommit = _value.equals("Y");
+      }
+
+      if(_option.equals(SQL_OPTION) || _option.equals(TABLE_OPTION))
+      {
+			if(!configured) configure();
+      }
+	}
+
+	/**
+	Internal method. Returns true, you may define your own layout...
+	*/
+	public boolean requiresLayout()
+	{
+		return true;
+	}
+
+
+	/**
+	Internal method. Close the database connection & flush the buffer.
+	*/
+	public void close()
+	{
+	   flush_buffer();
+      if(connection_class == null)
+      {
+			try{con.close();}catch(Exception e){errorHandler.error("JDBCAppender::close(), " + e);}
+      }
+		this.closed = true;
+	}
+
+
+	/**
+	You have to call this function for all provided columns of your log-table !
+   */
+	public boolean setLogType(String _name, int _logtype, Object _value)
+	{
+   	if(sql != null) return true;
+
+		if(!configured)
+		{
+			if(!configure()) return false;
+		}
+
+		try
+		{
+			jlogger.setLogType(_name, _logtype, _value);
+		}
+		catch(Exception e)
+		{
+			errorHandler.error("JDBCAppender::setLogType(), " + e);
+			return false;
+		}
+
+		return true;
+	}
+
+
+	/**
+	Internal method. Appends the message to the database table.
+	*/
+	public void append(LoggingEvent event)
+	{
+		if(!ready)
+      {
+      	if(!ready())
+         {
+				errorHandler.error("JDBCAppender::append(), Not ready to append !");
+         	return;
+			}
+      }
+
+		buffer.add(event);
+
+		if(buffer.size() >= buffer_size) flush_buffer();
+	}
+
+
+	/**
+	Internal method. Flushes the buffer.
+	*/
+   public void flush_buffer()
+   {
+   	try
+      {
+      	int size = buffer.size();
+
+         if(size < 1) return;
+
+        	for(int i=0; i<size; i++)
+         {
+				LoggingEvent event = (LoggingEvent)buffer.get(i);
+
+				//Insert message into database
+				jlogger.append(layout.format(event));
+         }
+
+         buffer.clear();
+
+			if(docommit) con.commit();
+      }
+		catch(Exception e)
+		{
+			errorHandler.error("JDBCAppender::flush_buffer(), " + e + " : " + jlogger.getErrorMsg());
+			try{con.rollback();} catch(Exception ex){}
+			return;
+		}
+   }
+
+
+	/**
+	Internal method. Returns true, when the JDBCAppender is ready to append messages to the database, else false.
+	*/
+	public boolean ready()
+	{
+   	if(ready) return true;
+
+		if(!configured) return false;
+
+		ready = jlogger.ready();
+
+      if(!ready){errorHandler.error(jlogger.getErrorMsg());}
+
+      return ready;
+	}
+
+
+	/**
+	Internal method. Connect to the database.
+	*/
+	protected void connect() throws Exception
+	{
+   	if(connected) return;
+
+		try
+		{
+      	if(connection_class == null)
+         {
+				if(url == null)		throw new Exception("JDBCAppender::connect(), No URL defined.");
+
+				if(username == null)	throw new Exception("JDBCAppender::connect(), No USERNAME defined.");
+
+				if(password == null)	throw new Exception("JDBCAppender::connect(), No PASSWORD defined.");
+
+				connectionHandler = new DefaultConnectionHandler();
+			}
+         else
+         {
+				connectionHandler = (JDBCConnectionHandler)(Class.forName(connection_class).newInstance());
+         }
+
+         if(url != null && username != null && password != null)
+         {
+				con = connectionHandler.getConnection(url, username, password);
+         }
+         else
+         {
+	     		con = connectionHandler.getConnection();
+         }
+
+         if(con.isClosed())
+         {
+         	throw new Exception("JDBCAppender::connect(), JDBCConnectionHandler returns no connected Connection !");
+			}
+		}
+		catch(Exception e)
+		{
+			throw new Exception("JDBCAppender::connect(), " + e);
+		}
+
+      connected = true;
+	}
+
+	/**
+	Internal method. Configures for appending...
+	*/
+	protected boolean configure()
+	{
+		if(configured) return true;
+
+		if(!connected)
+		{
+      	if((connection_class == null) && (url == null || username == null || password == null))
+			{
+				errorHandler.error("JDBCAppender::configure(), Missing database-options or connector-option !");
+				return false;
+         }
+
+         try
+         {
+				connect();
+         }
+         catch(Exception e)
+         {
+         	connection_class = null;
+            url = null;
+				errorHandler.error("JDBCAppender::configure(), " + e);
+            return false;
+         }
+		}
+
+		if(sql == null && table == null)
+		{
+			errorHandler.error("JDBCAppender::configure(), No SQL_OPTION or TABLE_OPTION given !");
+			return false;
+		}
+
+		if(!jlogger.isConfigured())
+		{
+			try
+         {
+         	jlogger.setConnection(con);
+
+         	if(sql == null)
+            {
+	         	jlogger.configureTable(table);
+            }
+            else jlogger.configureSQL(sql);
+         }
+         catch(Exception e)
+         {
+	         errorHandler.error("JDBCAppender::configure(), " + e);
+         	return false;
+         }
+		}
+
+      //Default Message-Layout
+      if(layout == null)
+      {
+      	layout = new PatternLayout("%m");
+      }
+
+      configured = true;
+
+		return true;
+	}
+}
+
+/**
+This is a default JDBCConnectionHandler used by JDBCAppender
+*/
+class DefaultConnectionHandler implements JDBCConnectionHandler
+{
+	Connection con = null;
+
+   public Connection getConnection()
+   {
+   	return con;
+   }
+
+   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;
+   }
+}
+
+
+
+
+
+

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

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCConnectionHandler.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCConnectionHandler.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCConnectionHandler.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCConnectionHandler.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,38 @@
+/*
+ * 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.*;
+
+
+/**
+This interface has to be implemented for your own database-connection-handling and its used in class JDBCLogger.
+
+<p><b>Author : </b><A HREF="mailto:t.fenner@klopotek.de">Thomas Fenner</A></p>
+
+@since 1.0
+*/
+public interface JDBCConnectionHandler
+{
+	/**Get a connection*/
+	Connection getConnection();
+	/**Get a defined connection*/
+   Connection getConnection(String _url, String _username, String _password);
+}
+
+

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

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCIDHandler.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCIDHandler.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCIDHandler.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCIDHandler.java Sat Jun  2 11:40:31 2012
@@ -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.net;
+
+
+/**
+This interface has to be implemented to provide ID-columns with unique IDs and its used in class JDBCLogger.
+
+<p><b>Author : </b><A HREF="mailto:t.fenner@klopotek.de">Thomas Fenner</A></p>
+
+@since 1.0
+*/
+public interface JDBCIDHandler
+{
+	/**Get a unique ID*/
+	Object getID();
+}
+
+
+

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

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCLogger.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCLogger.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCLogger.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCLogger.java Sat Jun  2 11:40:31 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/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JDBCLogger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JMSQueueAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JMSQueueAppender.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JMSQueueAppender.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JMSQueueAppender.java Sat Jun  2 11:40:31 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/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/JMSQueueAppender.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/Log4jRequestHandler.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/Log4jRequestHandler.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/Log4jRequestHandler.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/Log4jRequestHandler.java Sat Jun  2 11:40:31 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/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/Log4jRequestHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/LogType.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/LogType.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/LogType.java (added)
+++ logging/log4j/branches/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/LogType.java Sat Jun  2 11:40:31 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/log4j12modules/modules/contribs/src/main/java/org/apache/log4j/net/LogType.java
------------------------------------------------------------------------------
    svn:eol-style = native