The version of Apache log4j used by SoundHelix.

[[ 🗃 ^aEp6o apache-log4j ]] :: [📥 Inbox] [📤 Outbox] [🐤 Followers] [🤝 Collaborators] [🛠 Commits]

Clone

HTTPS: git clone https://vervis.peers.community/repos/aEp6o

SSH: git clone USERNAME@vervis.peers.community:aEp6o

Branches

Tags

v1_3alpha_1 :: contribs / CekiGulcu /

AppenderTable.java

/*
 * Copyright 1999,2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.helpers.CyclicBuffer;
import org.apache.log4j.spi.LoggingEvent;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;


/**
 * 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>
 * 
 * <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>
 * 
 * <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.
 * </p>
 */
public class AppenderTable extends JTable {
  static Logger logger = Logger.getLogger(AppenderTable.class);

  public AppenderTable() {
    this.setDefaultRenderer(Object.class, new Renderer());
  }

  public static 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 JTableAddAction(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.");
  }

  /**
   * 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.
   * </p>
   */
  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.
   * </p>
   */
  public Object getValueAt(int row, int col) {
    return cb.get(row);
  }
}


/**
 * The JTableAddAction is called when the user clicks on the "ADD" button.
 */
class JTableAddAction implements ActionListener {
  AppenderTable appenderTable;
  Logger dummy = Logger.getLogger("x");
  int counter = 0;

  public JTableAddAction(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);
  }
}

[See repo JSON]