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ülcü
+ * @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