[Git][java-team/apache-log4j1.2][buster] 10 commits: Import Debian changes 1.2.17-7

Markus Koschany (@apo) gitlab at salsa.debian.org
Sat Feb 12 10:17:59 GMT 2022



Markus Koschany pushed to branch buster at Debian Java Maintainers / apache-log4j1.2


Commits:
5397a7a9 by Markus Koschany at 2020-05-02T16:36:11+02:00
Import Debian changes 1.2.17-7

apache-log4j1.2 (1.2.17-7) unstable; urgency=medium

  * Team upload.
  * Transition to bnd 2.1.0.
  * Vcs-Browser: Use https.

- - - - -
a0103883 by Markus Koschany at 2020-05-02T16:38:13+02:00
Add CVE-2019-17571.patch

- - - - -
8596f85b by Markus Koschany at 2020-05-02T16:39:30+02:00
Update changelog

- - - - -
a529695e by Markus Koschany at 2022-01-31T13:16:06+01:00
Really apply the patches

- - - - -
9710d682 by Markus Koschany at 2022-01-31T13:18:33+01:00
Mitigate the impact of CVE-2022-23302 CVE-2022-23305 CVE-2022-23307

- - - - -
a21c0e08 by Markus Koschany at 2022-01-31T13:19:37+01:00
Really apply the patches

- - - - -
a8f7a6fe by Markus Koschany at 2022-01-31T13:20:05+01:00
Mitigate against CVE-2021-4104

- - - - -
4215efaf by Markus Koschany at 2022-01-31T13:28:23+01:00
Update changelog

- - - - -
feec4213 by Markus Koschany at 2022-02-12T10:39:25+01:00
Merge branch 'stretch' into buster

- - - - -
406287eb by Markus Koschany at 2022-02-12T10:43:36+01:00
Update changelog

- - - - -


6 changed files:

- debian/changelog
- + debian/patches/CVE-2021-4104.patch
- + debian/patches/CVE-2022-23302.patch
- + debian/patches/CVE-2022-23305.patch
- + debian/patches/CVE-2022-23307.patch
- debian/patches/series


Changes:

=====================================
debian/changelog
=====================================
@@ -1,3 +1,17 @@
+apache-log4j1.2 (1.2.17-8+deb10u2) buster; urgency=medium
+
+  * Team upload.
+  * Fix CVE-2021-4104, CVE-2022-23302, CVE-2022-23305 and CVE-2022-23307.
+    Multiple security vulnerabilities have been discovered in
+    Apache Log4j 1.2 when it is configured to use JMSSink, JDBCAppender and
+    JMSAppender or Apache Chainsaw. Note that a possible attacker requires
+    write access to the Log4j configuration and the aforementioned features are
+    not enabled by default. In order to completely mitigate against these
+    vulnerabilities the related classes have been removed from the resulting
+    jar file.
+
+ -- Markus Koschany <apo at debian.org>  Sat, 12 Feb 2022 10:40:19 +0100
+
 apache-log4j1.2 (1.2.17-8+deb10u1) buster-security; urgency=high
 
   * Team upload.


=====================================
debian/patches/CVE-2021-4104.patch
=====================================
@@ -0,0 +1,463 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sun, 30 Jan 2022 22:34:52 +0100
+Subject: CVE-2021-4104
+
+Bug-Debian: https://bugs.debian.org/1004482
+
+This change mitigates the impact of CVE-2021-4104. Apache Log4j 1.2 has
+reached end of life in August 2015. No further updates will be available.
+---
+ .../java/org/apache/log4j/net/JMSAppender.java     | 444 ---------------------
+ 1 file changed, 444 deletions(-)
+ delete mode 100644 src/main/java/org/apache/log4j/net/JMSAppender.java
+
+diff --git a/src/main/java/org/apache/log4j/net/JMSAppender.java b/src/main/java/org/apache/log4j/net/JMSAppender.java
+deleted file mode 100644
+index 3482702..0000000
+--- a/src/main/java/org/apache/log4j/net/JMSAppender.java
++++ /dev/null
+@@ -1,444 +0,0 @@
+-/*
+- * 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.helpers.LogLog;
+-import org.apache.log4j.spi.ErrorCode;
+-import org.apache.log4j.spi.LoggingEvent;
+-
+-import javax.jms.JMSException;
+-import javax.jms.ObjectMessage;
+-import javax.jms.Session;
+-import javax.jms.Topic;
+-import javax.jms.TopicConnection;
+-import javax.jms.TopicConnectionFactory;
+-import javax.jms.TopicPublisher;
+-import javax.jms.TopicSession;
+-import javax.naming.Context;
+-import javax.naming.InitialContext;
+-import javax.naming.NameNotFoundException;
+-import javax.naming.NamingException;
+-import java.util.Properties;
+-
+-/**
+- * A simple appender that publishes events to a JMS Topic. The events
+- * are serialized and transmitted as JMS message type {@link
+- * ObjectMessage}.
+-
+- * <p>JMS {@link Topic topics} and {@link TopicConnectionFactory topic
+- * connection factories} are administered objects that are retrieved
+- * using JNDI messaging which in turn requires the retrieval of a JNDI
+- * {@link Context}.
+-
+- * <p>There are two common methods for retrieving a JNDI {@link
+- * Context}. If a file resource named <em>jndi.properties</em> is
+- * available to the JNDI API, it will use the information found
+- * therein to retrieve an initial JNDI context. To obtain an initial
+- * context, your code will simply call:
+-
+-   <pre>
+-   InitialContext jndiContext = new InitialContext();
+-   </pre>
+-  
+- * <p>Calling the no-argument <code>InitialContext()</code> method
+- * will also work from within Enterprise Java Beans (EJBs) because it
+- * is part of the EJB contract for application servers to provide each
+- * bean an environment naming context (ENC).
+-    
+- * <p>In the second approach, several predetermined properties are set
+- * and these properties are passed to the <code>InitialContext</code>
+- * constructor to connect to the naming service provider. For example,
+- * to connect to JBoss naming service one would write:
+-
+-<pre>
+-   Properties env = new Properties( );
+-   env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
+-   env.put(Context.PROVIDER_URL, "jnp://hostname:1099");
+-   env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
+-   InitialContext jndiContext = new InitialContext(env);
+-</pre>
+-
+-   * where <em>hostname</em> is the host where the JBoss application
+-   * server is running.
+-   *
+-   * <p>To connect to the the naming service of Weblogic application
+-   * server one would write:
+-
+-<pre>
+-   Properties env = new Properties( );
+-   env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
+-   env.put(Context.PROVIDER_URL, "t3://localhost:7001");
+-   InitialContext jndiContext = new InitialContext(env);
+-</pre>
+-
+-  * <p>Other JMS providers will obviously require different values.
+-  * 
+-  * The initial JNDI context can be obtained by calling the
+-  * no-argument <code>InitialContext()</code> method in EJBs. Only
+-  * clients running in a separate JVM need to be concerned about the
+-  * <em>jndi.properties</em> file and calling {@link
+-  * InitialContext#InitialContext()} or alternatively correctly
+-  * setting the different properties before calling {@link
+-  * InitialContext#InitialContext(java.util.Hashtable)} method.
+-
+-
+-   @author Ceki Gülcü */
+-public class JMSAppender extends AppenderSkeleton {
+-
+-  String securityPrincipalName;
+-  String securityCredentials;
+-  String initialContextFactoryName;
+-  String urlPkgPrefixes;
+-  String providerURL;
+-  String topicBindingName;
+-  String tcfBindingName;
+-  String userName;
+-  String password;
+-  boolean locationInfo;
+-
+-  TopicConnection  topicConnection;
+-  TopicSession topicSession;
+-  TopicPublisher  topicPublisher;
+-
+-  public
+-  JMSAppender() {
+-  }
+-
+-  /**
+-     The <b>TopicConnectionFactoryBindingName</b> option takes a
+-     string value. Its value will be used to lookup the appropriate
+-     <code>TopicConnectionFactory</code> from the JNDI context.
+-   */
+-  public
+-  void setTopicConnectionFactoryBindingName(String tcfBindingName) {
+-    this.tcfBindingName = tcfBindingName;
+-  }
+-
+-  /**
+-     Returns the value of the <b>TopicConnectionFactoryBindingName</b> option.
+-   */
+-  public
+-  String getTopicConnectionFactoryBindingName() {
+-    return tcfBindingName;
+-  }
+-
+-  /**
+-     The <b>TopicBindingName</b> option takes a
+-     string value. Its value will be used to lookup the appropriate
+-     <code>Topic</code> from the JNDI context.
+-   */
+-  public
+-  void setTopicBindingName(String topicBindingName) {
+-    this.topicBindingName = topicBindingName;
+-  }
+-
+-  /**
+-     Returns the value of the <b>TopicBindingName</b> option.
+-   */
+-  public
+-  String getTopicBindingName() {
+-    return topicBindingName;
+-  }
+-
+-
+-  /**
+-     Returns value of the <b>LocationInfo</b> property which
+-     determines whether location (stack) info is sent to the remote
+-     subscriber. */
+-  public
+-  boolean getLocationInfo() {
+-    return locationInfo;
+-  }
+-
+-  /**
+-   *  Options are activated and become effective only after calling
+-   *  this method.*/
+-  public void activateOptions() {
+-    TopicConnectionFactory  topicConnectionFactory;
+-
+-    try {
+-      Context jndi;
+-
+-      LogLog.debug("Getting initial context.");
+-      if(initialContextFactoryName != null) {
+-	Properties env = new Properties( );
+-	env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName);
+-	if(providerURL != null) {
+-	  env.put(Context.PROVIDER_URL, providerURL);
+-	} else {
+-	  LogLog.warn("You have set InitialContextFactoryName option but not the "
+-		     +"ProviderURL. This is likely to cause problems.");
+-	}
+-	if(urlPkgPrefixes != null) {
+-	  env.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
+-	}
+-	
+-	if(securityPrincipalName != null) {
+-	  env.put(Context.SECURITY_PRINCIPAL, securityPrincipalName);
+-	  if(securityCredentials != null) {
+-	    env.put(Context.SECURITY_CREDENTIALS, securityCredentials);
+-	  } else {
+-	    LogLog.warn("You have set SecurityPrincipalName option but not the "
+-			+"SecurityCredentials. This is likely to cause problems.");
+-	  }
+-	}	
+-	jndi = new InitialContext(env);
+-      } else {
+-	jndi = new InitialContext();
+-      }
+-
+-      LogLog.debug("Looking up ["+tcfBindingName+"]");
+-      topicConnectionFactory = (TopicConnectionFactory) lookup(jndi, tcfBindingName);
+-      LogLog.debug("About to create TopicConnection.");
+-      if(userName != null) {
+-	topicConnection = topicConnectionFactory.createTopicConnection(userName, 
+-								       password); 
+-      } else {
+-	topicConnection = topicConnectionFactory.createTopicConnection();
+-      }
+-
+-      LogLog.debug("Creating TopicSession, non-transactional, "
+-		   +"in AUTO_ACKNOWLEDGE mode.");
+-      topicSession = topicConnection.createTopicSession(false,
+-							Session.AUTO_ACKNOWLEDGE);
+-
+-      LogLog.debug("Looking up topic name ["+topicBindingName+"].");
+-      Topic topic = (Topic) lookup(jndi, topicBindingName);
+-
+-      LogLog.debug("Creating TopicPublisher.");
+-      topicPublisher = topicSession.createPublisher(topic);
+-      
+-      LogLog.debug("Starting TopicConnection.");
+-      topicConnection.start();
+-
+-      jndi.close();
+-    } catch(JMSException e) {
+-      errorHandler.error("Error while activating options for appender named ["+name+
+-			 "].", e, ErrorCode.GENERIC_FAILURE);
+-    } catch(NamingException e) {
+-      errorHandler.error("Error while activating options for appender named ["+name+
+-			 "].", e, ErrorCode.GENERIC_FAILURE);
+-    } catch(RuntimeException e) {
+-      errorHandler.error("Error while activating options for appender named ["+name+
+-			 "].", e, ErrorCode.GENERIC_FAILURE);
+-    }
+-  }
+-
+-  protected Object lookup(Context ctx, String name) throws NamingException {
+-    try {
+-      return ctx.lookup(name);
+-    } catch(NameNotFoundException e) {
+-      LogLog.error("Could not find name ["+name+"].");
+-      throw e;
+-    }
+-  }
+-
+-  protected boolean checkEntryConditions() {
+-    String fail = null;
+-
+-    if(this.topicConnection == null) {
+-      fail = "No TopicConnection";
+-    } else if(this.topicSession == null) {
+-      fail = "No TopicSession";
+-    } else if(this.topicPublisher == null) {
+-      fail = "No TopicPublisher";
+-    }
+-
+-    if(fail != null) {
+-      errorHandler.error(fail +" for JMSAppender named ["+name+"].");
+-      return false;
+-    } else {
+-      return true;
+-    }
+-  }
+-
+-  /**
+-     Close this JMSAppender. Closing releases all resources used by the
+-     appender. A closed appender cannot be re-opened. */
+-  public synchronized void close() {
+-    // The synchronized modifier avoids concurrent append and close operations
+-
+-    if(this.closed)
+-      return;
+-
+-    LogLog.debug("Closing appender ["+name+"].");
+-    this.closed = true;
+-
+-    try {
+-      if(topicSession != null)
+-	topicSession.close();
+-      if(topicConnection != null)
+-	topicConnection.close();
+-    } catch(JMSException e) {
+-      LogLog.error("Error while closing JMSAppender ["+name+"].", e);
+-    } catch(RuntimeException e) {
+-      LogLog.error("Error while closing JMSAppender ["+name+"].", e);
+-    }
+-    // Help garbage collection
+-    topicPublisher = null;
+-    topicSession = null;
+-    topicConnection = null;
+-  }
+-
+-  /**
+-     This method called by {@link AppenderSkeleton#doAppend} method to
+-     do most of the real appending work.  */
+-  public void append(LoggingEvent event) {
+-    if(!checkEntryConditions()) {
+-      return;
+-    }
+-
+-    try {
+-      ObjectMessage msg = topicSession.createObjectMessage();
+-      if(locationInfo) {
+-	event.getLocationInformation();
+-      }
+-      msg.setObject(event);
+-      topicPublisher.publish(msg);
+-    } catch(JMSException e) {
+-      errorHandler.error("Could not publish message in JMSAppender ["+name+"].", e,
+-			 ErrorCode.GENERIC_FAILURE);
+-    } catch(RuntimeException e) {
+-      errorHandler.error("Could not publish message in JMSAppender ["+name+"].", e,
+-			 ErrorCode.GENERIC_FAILURE);
+-    }
+-  }
+-
+-  /**
+-   * Returns the value of the <b>InitialContextFactoryName</b> option.
+-   * See {@link #setInitialContextFactoryName} for more details on the
+-   * meaning of this option.
+-   * */
+-  public String getInitialContextFactoryName() {
+-    return initialContextFactoryName;    
+-  }
+-  
+-  /**
+-   * Setting the <b>InitialContextFactoryName</b> method will cause
+-   * this <code>JMSAppender</code> instance to use the {@link
+-   * InitialContext#InitialContext(Hashtable)} method instead of the
+-   * no-argument constructor. If you set this option, you should also
+-   * at least set the <b>ProviderURL</b> option.
+-   * 
+-   * <p>See also {@link #setProviderURL(String)}.
+-   * */
+-  public void setInitialContextFactoryName(String initialContextFactoryName) {
+-    this.initialContextFactoryName = initialContextFactoryName;
+-  }
+-
+-  public String getProviderURL() {
+-    return providerURL;    
+-  }
+-
+-  public void setProviderURL(String providerURL) {
+-    this.providerURL = providerURL;
+-  }
+-
+-  String getURLPkgPrefixes( ) {
+-    return urlPkgPrefixes;
+-  }
+-
+-  public void setURLPkgPrefixes(String urlPkgPrefixes ) {
+-    this.urlPkgPrefixes = urlPkgPrefixes;
+-  }
+-  
+-  public String getSecurityCredentials() {
+-    return securityCredentials;    
+-  }
+-
+-  public void setSecurityCredentials(String securityCredentials) {
+-    this.securityCredentials = securityCredentials;
+-  }
+-  
+-  
+-  public String getSecurityPrincipalName() {
+-    return securityPrincipalName;    
+-  }
+-
+-  public void setSecurityPrincipalName(String securityPrincipalName) {
+-    this.securityPrincipalName = securityPrincipalName;
+-  }
+-
+-  public String getUserName() {
+-    return userName;    
+-  }
+-
+-  /**
+-   * The user name to use when {@link
+-   * TopicConnectionFactory#createTopicConnection(String, String)
+-   * creating a topic session}.  If you set this option, you should
+-   * also set the <b>Password</b> option. See {@link
+-   * #setPassword(String)}.
+-   * */
+-  public void setUserName(String userName) {
+-    this.userName = userName;
+-  }
+-
+-  public String getPassword() {
+-    return password;    
+-  }
+-
+-  /**
+-   * The paswword to use when creating a topic session.  
+-   */
+-  public void setPassword(String password) {
+-    this.password = password;
+-  }
+-
+-
+-  /**
+-      If true, the information sent to the remote subscriber will
+-      include caller's location information. By default no location
+-      information is sent to the subscriber.  */
+-  public void setLocationInfo(boolean locationInfo) {
+-    this.locationInfo = locationInfo;
+-  }
+-
+-  /**
+-   * Returns the TopicConnection used for this appender.  Only valid after
+-   * activateOptions() method has been invoked.
+-   */
+-  protected TopicConnection  getTopicConnection() {
+-    return topicConnection;
+-  }
+-
+-  /**
+-   * Returns the TopicSession used for this appender.  Only valid after
+-   * activateOptions() method has been invoked.
+-   */
+-  protected TopicSession  getTopicSession() {
+-    return topicSession;
+-  }
+-
+-  /**
+-   * Returns the TopicPublisher used for this appender.  Only valid after
+-   * activateOptions() method has been invoked.
+-   */
+-  protected TopicPublisher  getTopicPublisher() {
+-    return topicPublisher;
+-  }
+-  
+-  /** 
+-   * The JMSAppender sends serialized events and consequently does not
+-   * require a layout.
+-   */
+-  public boolean requiresLayout() {
+-    return false;
+-  }
+-}


=====================================
debian/patches/CVE-2022-23302.patch
=====================================
@@ -0,0 +1,172 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sun, 30 Jan 2022 22:16:04 +0100
+Subject: CVE-2022-23302
+
+Bug-Debian: https://bugs.debian.org/1004482
+
+This change mitigates the impact of CVE-2022-23302. Apache Log4j 1.2 has
+reached end of life in August 2015. No further updates will be available.
+---
+ src/main/java/org/apache/log4j/net/JMSSink.java | 153 ------------------------
+ 1 file changed, 153 deletions(-)
+ delete mode 100644 src/main/java/org/apache/log4j/net/JMSSink.java
+
+diff --git a/src/main/java/org/apache/log4j/net/JMSSink.java b/src/main/java/org/apache/log4j/net/JMSSink.java
+deleted file mode 100644
+index 6a02831..0000000
+--- a/src/main/java/org/apache/log4j/net/JMSSink.java
++++ /dev/null
+@@ -1,153 +0,0 @@
+-/*
+- * 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.Logger;
+-import org.apache.log4j.PropertyConfigurator;
+-import org.apache.log4j.spi.LoggingEvent;
+-import org.apache.log4j.xml.DOMConfigurator;
+-
+-import javax.jms.JMSException;
+-import javax.jms.ObjectMessage;
+-import javax.jms.Session;
+-import javax.jms.Topic;
+-import javax.jms.TopicConnection;
+-import javax.jms.TopicConnectionFactory;
+-import javax.jms.TopicSession;
+-import javax.jms.TopicSubscriber;
+-import javax.naming.Context;
+-import javax.naming.InitialContext;
+-import javax.naming.NameNotFoundException;
+-import javax.naming.NamingException;
+-import java.io.BufferedReader;
+-import java.io.InputStreamReader;
+-
+-/**
+- * A simple application that consumes logging events sent by a {@link
+- * JMSAppender}.
+- *
+- *
+- * @author Ceki Gülcü 
+- * */
+-public class JMSSink implements javax.jms.MessageListener {
+-
+-  static Logger logger = Logger.getLogger(JMSSink.class);
+-
+-  static public void main(String[] args) throws Exception {
+-    if(args.length != 5) {
+-      usage("Wrong number of arguments.");
+-    }
+-    
+-    String tcfBindingName = args[0];
+-    String topicBindingName = args[1];
+-    String username = args[2];
+-    String password = args[3];
+-    
+-    
+-    String configFile = args[4];
+-
+-    if(configFile.endsWith(".xml")) {
+-      DOMConfigurator.configure(configFile);
+-    } else {
+-      PropertyConfigurator.configure(configFile);
+-    }
+-    
+-    new JMSSink(tcfBindingName, topicBindingName, username, password);
+-
+-    BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+-    // Loop until the word "exit" is typed
+-    System.out.println("Type \"exit\" to quit JMSSink.");
+-    while(true){
+-      String s = stdin.readLine( );
+-      if (s.equalsIgnoreCase("exit")) {
+-	System.out.println("Exiting. Kill the application if it does not exit "
+-			   + "due to daemon threads.");
+-	return; 
+-      }
+-    } 
+-  }
+-
+-  public JMSSink( String tcfBindingName, String topicBindingName, String username,
+-		  String password) {
+-    
+-    try {
+-      Context ctx = new InitialContext();
+-      TopicConnectionFactory topicConnectionFactory;
+-      topicConnectionFactory = (TopicConnectionFactory) lookup(ctx,
+-                                                               tcfBindingName);
+-
+-      TopicConnection topicConnection =
+-	                        topicConnectionFactory.createTopicConnection(username,
+-									     password);
+-      topicConnection.start();
+-
+-      TopicSession topicSession = topicConnection.createTopicSession(false,
+-                                                       Session.AUTO_ACKNOWLEDGE);
+-
+-      Topic topic = (Topic)ctx.lookup(topicBindingName);
+-
+-      TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic);
+-    
+-      topicSubscriber.setMessageListener(this);
+-
+-    } catch(JMSException e) {
+-      logger.error("Could not read JMS message.", e);
+-    } catch(NamingException e) {
+-      logger.error("Could not read JMS message.", e);
+-    } catch(RuntimeException e) {
+-      logger.error("Could not read JMS message.", e);
+-    }
+-  }
+-
+-  public void onMessage(javax.jms.Message message) {
+-    LoggingEvent event;
+-    Logger remoteLogger;
+-
+-    try {
+-      if(message instanceof  ObjectMessage) {
+-	ObjectMessage objectMessage = (ObjectMessage) message;
+-	event = (LoggingEvent) objectMessage.getObject();
+-	remoteLogger = Logger.getLogger(event.getLoggerName());
+-	remoteLogger.callAppenders(event);
+-      } else {
+-	logger.warn("Received message is of type "+message.getJMSType()
+-		    +", was expecting ObjectMessage.");
+-      }      
+-    } catch(JMSException jmse) {
+-      logger.error("Exception thrown while processing incoming message.", 
+-		   jmse);
+-    }
+-  }
+-
+-
+-  protected static Object lookup(Context ctx, String name) throws NamingException {
+-    try {
+-      return ctx.lookup(name);
+-    } catch(NameNotFoundException e) {
+-      logger.error("Could not find name ["+name+"].");
+-      throw e;
+-    }
+-  }
+-
+-  static void usage(String msg) {
+-    System.err.println(msg);
+-    System.err.println("Usage: java " + JMSSink.class.getName()
+-            + " TopicConnectionFactoryBindingName TopicBindingName username password configFile");
+-    System.exit(1);
+-  }
+-}


=====================================
debian/patches/CVE-2022-23305.patch
=====================================
@@ -0,0 +1,417 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sun, 30 Jan 2022 22:18:18 +0100
+Subject: CVE-2022-23305
+
+Bug-Debian: https://bugs.debian.org/1004482
+
+This change mitigates the impact of CVE-2022-23305. Apache Log4j 1.2 has
+reached end of life in August 2015. No further updates will be available.
+---
+ .../java/org/apache/log4j/jdbc/JDBCAppender.java   | 398 ---------------------
+ 1 file changed, 398 deletions(-)
+ delete mode 100644 src/main/java/org/apache/log4j/jdbc/JDBCAppender.java
+
+diff --git a/src/main/java/org/apache/log4j/jdbc/JDBCAppender.java b/src/main/java/org/apache/log4j/jdbc/JDBCAppender.java
+deleted file mode 100644
+index ad35f65..0000000
+--- a/src/main/java/org/apache/log4j/jdbc/JDBCAppender.java
++++ /dev/null
+@@ -1,398 +0,0 @@
+-/*
+- * 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.jdbc;
+-
+-import java.sql.Connection;
+-import java.sql.DriverManager;
+-import java.sql.SQLException;
+-import java.sql.Statement;
+-import java.util.ArrayList;
+-import java.util.Iterator;
+-
+-import org.apache.log4j.PatternLayout;
+-import org.apache.log4j.spi.ErrorCode;
+-import org.apache.log4j.spi.LoggingEvent;
+-
+-
+-/**
+-  The JDBCAppender provides for sending log events to a database.
+-  
+- <p><b><font color="#FF2222">WARNING: This version of JDBCAppender
+- is very likely to be completely replaced in the future. Moreoever,
+- it does not log exceptions</font></b>.
+-
+-  <p>Each append call adds to an <code>ArrayList</code> buffer.  When
+-  the buffer is filled each log event is placed in a sql statement
+-  (configurable) and executed.
+-
+-  <b>BufferSize</b>, <b>db URL</b>, <b>User</b>, & <b>Password</b> are
+-  configurable options in the standard log4j ways.
+-
+-  <p>The <code>setSql(String sql)</code> sets the SQL statement to be
+-  used for logging -- this statement is sent to a
+-  <code>PatternLayout</code> (either created automaticly by the
+-  appender or added by the user).  Therefore by default all the
+-  conversion patterns in <code>PatternLayout</code> can be used
+-  inside of the statement.  (see the test cases for examples)
+-
+-  <p>Overriding the {@link #getLogStatement} method allows more
+-  explicit control of the statement used for logging.
+-
+-  <p>For use as a base class:
+-
+-    <ul>
+-
+-    <li>Override <code>getConnection()</code> to pass any connection
+-    you want.  Typically this is used to enable application wide
+-    connection pooling.
+-
+-     <li>Override <code>closeConnection(Connection con)</code> -- if
+-     you override getConnection make sure to implement
+-     <code>closeConnection</code> to handle the connection you
+-     generated.  Typically this would return the connection to the
+-     pool it came from.
+-
+-     <li>Override <code>getLogStatement(LoggingEvent event)</code> to
+-     produce specialized or dynamic statements. The default uses the
+-     sql option value.
+-
+-    </ul>
+-
+-    @author Kevin Steppe (<A HREF="mailto:ksteppe at pacbell.net">ksteppe at pacbell.net</A>)
+-
+-*/
+-public class JDBCAppender extends org.apache.log4j.AppenderSkeleton
+-    implements org.apache.log4j.Appender {
+-
+-  /**
+-   * URL of the DB for default connection handling
+-   */
+-  protected String databaseURL = "jdbc:odbc:myDB";
+-
+-  /**
+-   * User to connect as for default connection handling
+-   */
+-  protected String databaseUser = "me";
+-
+-  /**
+-   * User to use for default connection handling
+-   */
+-  protected String databasePassword = "mypassword";
+-
+-  /**
+-   * Connection used by default.  The connection is opened the first time it
+-   * is needed and then held open until the appender is closed (usually at
+-   * garbage collection).  This behavior is best modified by creating a
+-   * sub-class and overriding the <code>getConnection</code> and
+-   * <code>closeConnection</code> methods.
+-   */
+-  protected Connection connection = null;
+-
+-  /**
+-   * Stores the string given to the pattern layout for conversion into a SQL
+-   * statement, eg: insert into LogTable (Thread, Class, Message) values
+-   * ("%t", "%c", "%m").
+-   *
+-   * Be careful of quotes in your messages!
+-   *
+-   * Also see PatternLayout.
+-   */
+-  protected String sqlStatement = "";
+-
+-  /**
+-   * size of LoggingEvent buffer before writting to the database.
+-   * Default is 1.
+-   */
+-  protected int bufferSize = 1;
+-
+-  /**
+-   * ArrayList holding the buffer of Logging Events.
+-   */
+-  protected ArrayList buffer;
+-
+-  /**
+-   * Helper object for clearing out the buffer
+-   */
+-  protected ArrayList removes;
+-  
+-  private boolean locationInfo = false;
+-
+-  public JDBCAppender() {
+-    super();
+-    buffer = new ArrayList(bufferSize);
+-    removes = new ArrayList(bufferSize);
+-  }
+-
+-  /**
+-   * Gets whether the location of the logging request call
+-   * should be captured.
+-   *
+-   * @since 1.2.16
+-   * @return the current value of the <b>LocationInfo</b> option.
+-   */
+-  public boolean getLocationInfo() {
+-    return locationInfo;
+-  }
+-  
+-  /**
+-   * The <b>LocationInfo</b> option takes a boolean value. By default, it is
+-   * set to false which means there will be no effort to extract the location
+-   * information related to the event. As a result, the event that will be
+-   * ultimately logged will likely to contain the wrong location information
+-   * (if present in the log format).
+-   * <p/>
+-   * <p/>
+-   * Location information extraction is comparatively very slow and should be
+-   * avoided unless performance is not a concern.
+-   * </p>
+-   * @since 1.2.16
+-   * @param flag true if location information should be extracted.
+-   */
+-  public void setLocationInfo(final boolean flag) {
+-    locationInfo = flag;
+-  }
+-  
+-
+-  /**
+-   * Adds the event to the buffer.  When full the buffer is flushed.
+-   */
+-  public void append(LoggingEvent event) {
+-    event.getNDC();
+-    event.getThreadName();
+-    // Get a copy of this thread's MDC.
+-    event.getMDCCopy();
+-    if (locationInfo) {
+-      event.getLocationInformation();
+-    }
+-    event.getRenderedMessage();
+-    event.getThrowableStrRep();
+-    buffer.add(event);
+-
+-    if (buffer.size() >= bufferSize)
+-      flushBuffer();
+-  }
+-
+-  /**
+-   * By default getLogStatement sends the event to the required Layout object.
+-   * The layout will format the given pattern into a workable SQL string.
+-   *
+-   * Overriding this provides direct access to the LoggingEvent
+-   * when constructing the logging statement.
+-   *
+-   */
+-  protected String getLogStatement(LoggingEvent event) {
+-    return getLayout().format(event);
+-  }
+-
+-  /**
+-   *
+-   * Override this to provide an alertnate method of getting
+-   * connections (such as caching).  One method to fix this is to open
+-   * connections at the start of flushBuffer() and close them at the
+-   * end.  I use a connection pool outside of JDBCAppender which is
+-   * accessed in an override of this method.
+-   * */
+-  protected void execute(String sql) throws SQLException {
+-
+-    Connection con = null;
+-    Statement stmt = null;
+-
+-    try {
+-        con = getConnection();
+-
+-        stmt = con.createStatement();
+-        stmt.executeUpdate(sql);
+-    } finally {
+-        if(stmt != null) {
+-            stmt.close();
+-        }
+-        closeConnection(con);
+-    }
+-
+-    //System.out.println("Execute: " + sql);
+-  }
+-
+-
+-  /**
+-   * Override this to return the connection to a pool, or to clean up the
+-   * resource.
+-   *
+-   * The default behavior holds a single connection open until the appender
+-   * is closed (typically when garbage collected).
+-   */
+-  protected void closeConnection(Connection con) {
+-  }
+-
+-  /**
+-   * Override this to link with your connection pooling system.
+-   *
+-   * By default this creates a single connection which is held open
+-   * until the object is garbage collected.
+-   */
+-  protected Connection getConnection() throws SQLException {
+-      if (!DriverManager.getDrivers().hasMoreElements())
+-	     setDriver("sun.jdbc.odbc.JdbcOdbcDriver");
+-
+-      if (connection == null) {
+-        connection = DriverManager.getConnection(databaseURL, databaseUser,
+-					databasePassword);
+-      }
+-
+-      return connection;
+-  }
+-
+-  /**
+-   * Closes the appender, flushing the buffer first then closing the default
+-   * connection if it is open.
+-   */
+-  public void close()
+-  {
+-    flushBuffer();
+-
+-    try {
+-      if (connection != null && !connection.isClosed())
+-          connection.close();
+-    } catch (SQLException e) {
+-        errorHandler.error("Error closing connection", e, ErrorCode.GENERIC_FAILURE);
+-    }
+-    this.closed = true;
+-  }
+-
+-  /**
+-   * loops through the buffer of LoggingEvents, gets a
+-   * sql string from getLogStatement() and sends it to execute().
+-   * Errors are sent to the errorHandler.
+-   *
+-   * If a statement fails the LoggingEvent stays in the buffer!
+-   */
+-  public void flushBuffer() {
+-    //Do the actual logging
+-    removes.ensureCapacity(buffer.size());
+-    for (Iterator i = buffer.iterator(); i.hasNext();) {
+-      LoggingEvent logEvent = (LoggingEvent)i.next();
+-      try {
+-	    String sql = getLogStatement(logEvent);
+-	    execute(sql);
+-      }
+-      catch (SQLException e) {
+-	    errorHandler.error("Failed to excute sql", e,
+-			   ErrorCode.FLUSH_FAILURE);
+-      } finally {
+-        removes.add(logEvent);
+-      }
+-    }
+-    
+-    // remove from the buffer any events that were reported
+-    buffer.removeAll(removes);
+-    
+-    // clear the buffer of reported events
+-    removes.clear();
+-  }
+-
+-
+-  /** closes the appender before disposal */
+-  public void finalize() {
+-    close();
+-  }
+-
+-
+-  /**
+-   * JDBCAppender requires a layout.
+-   * */
+-  public boolean requiresLayout() {
+-    return true;
+-  }
+-
+-
+-  /**
+-   *
+-   */
+-  public void setSql(String s) {
+-    sqlStatement = s;
+-    if (getLayout() == null) {
+-        this.setLayout(new PatternLayout(s));
+-    }
+-    else {
+-        ((PatternLayout)getLayout()).setConversionPattern(s);
+-    }
+-  }
+-
+-
+-  /**
+-   * Returns pre-formated statement eg: insert into LogTable (msg) values ("%m")
+-   */
+-  public String getSql() {
+-    return sqlStatement;
+-  }
+-
+-
+-  public void setUser(String user) {
+-    databaseUser = user;
+-  }
+-
+-
+-  public void setURL(String url) {
+-    databaseURL = url;
+-  }
+-
+-
+-  public void setPassword(String password) {
+-    databasePassword = password;
+-  }
+-
+-
+-  public void setBufferSize(int newBufferSize) {
+-    bufferSize = newBufferSize;
+-    buffer.ensureCapacity(bufferSize);
+-    removes.ensureCapacity(bufferSize);
+-  }
+-
+-
+-  public String getUser() {
+-    return databaseUser;
+-  }
+-
+-
+-  public String getURL() {
+-    return databaseURL;
+-  }
+-
+-
+-  public String getPassword() {
+-    return databasePassword;
+-  }
+-
+-
+-  public int getBufferSize() {
+-    return bufferSize;
+-  }
+-
+-
+-  /**
+-   * Ensures that the given driver class has been loaded for sql connection
+-   * creation.
+-   */
+-  public void setDriver(String driverClass) {
+-    try {
+-      Class.forName(driverClass);
+-    } catch (Exception e) {
+-      errorHandler.error("Failed to load driver", e,
+-			 ErrorCode.GENERIC_FAILURE);
+-    }
+-  }
+-}
+-


=====================================
debian/patches/CVE-2022-23307.patch
=====================================
@@ -0,0 +1,1797 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sun, 30 Jan 2022 22:23:12 +0100
+Subject: CVE-2022-23307
+
+Bug-Debian: https://bugs.debian.org/1004482
+
+This change mitigates the impact of CVE-2022-23307. Apache Log4j 1.2 has
+reached end of life in August 2015. No further updates will be available.
+---
+ .../org/apache/log4j/chainsaw/ControlPanel.java    | 222 ------------
+ .../org/apache/log4j/chainsaw/DetailPanel.java     | 170 ---------
+ .../org/apache/log4j/chainsaw/EventDetails.java    | 135 -------
+ .../java/org/apache/log4j/chainsaw/ExitAction.java |  48 ---
+ .../org/apache/log4j/chainsaw/LoadXMLAction.java   | 139 --------
+ .../org/apache/log4j/chainsaw/LoggingReceiver.java | 121 -------
+ src/main/java/org/apache/log4j/chainsaw/Main.java  | 192 ----------
+ .../org/apache/log4j/chainsaw/MyTableModel.java    | 390 ---------------------
+ .../org/apache/log4j/chainsaw/XMLFileHandler.java  | 170 ---------
+ .../java/org/apache/log4j/chainsaw/package.html    | 118 -------
+ 10 files changed, 1705 deletions(-)
+ delete mode 100644 src/main/java/org/apache/log4j/chainsaw/ControlPanel.java
+ delete mode 100644 src/main/java/org/apache/log4j/chainsaw/DetailPanel.java
+ delete mode 100644 src/main/java/org/apache/log4j/chainsaw/EventDetails.java
+ delete mode 100644 src/main/java/org/apache/log4j/chainsaw/ExitAction.java
+ delete mode 100644 src/main/java/org/apache/log4j/chainsaw/LoadXMLAction.java
+ delete mode 100644 src/main/java/org/apache/log4j/chainsaw/LoggingReceiver.java
+ delete mode 100644 src/main/java/org/apache/log4j/chainsaw/Main.java
+ delete mode 100644 src/main/java/org/apache/log4j/chainsaw/MyTableModel.java
+ delete mode 100644 src/main/java/org/apache/log4j/chainsaw/XMLFileHandler.java
+ delete mode 100644 src/main/java/org/apache/log4j/chainsaw/package.html
+
+diff --git a/src/main/java/org/apache/log4j/chainsaw/ControlPanel.java b/src/main/java/org/apache/log4j/chainsaw/ControlPanel.java
+deleted file mode 100644
+index 53b0b1b..0000000
+--- a/src/main/java/org/apache/log4j/chainsaw/ControlPanel.java
++++ /dev/null
+@@ -1,222 +0,0 @@
+-/*
+- * 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.chainsaw;
+-
+-import java.awt.GridBagConstraints;
+-import java.awt.GridBagLayout;
+-import java.awt.event.ActionEvent;
+-import java.awt.event.ActionListener;
+-import javax.swing.BorderFactory;
+-import javax.swing.JButton;
+-import javax.swing.JComboBox;
+-import javax.swing.JLabel;
+-import javax.swing.JPanel;
+-import javax.swing.JTextField;
+-import javax.swing.event.DocumentEvent;
+-import javax.swing.event.DocumentListener;
+-import org.apache.log4j.Logger;
+-import org.apache.log4j.Priority;
+-import org.apache.log4j.Level;
+-
+-/**
+- * Represents the controls for filtering, pausing, exiting, etc.
+- *
+- * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+- */
+-class ControlPanel extends JPanel {
+-    /** use the log messages **/
+-    private static final Logger LOG = 
+-                                  Logger.getLogger(ControlPanel.class);
+-
+-    /**
+-     * Creates a new <code>ControlPanel</code> instance.
+-     *
+-     * @param aModel the model to control
+-     */
+-    ControlPanel(final MyTableModel aModel) {
+-        setBorder(BorderFactory.createTitledBorder("Controls: "));
+-        final GridBagLayout gridbag = new GridBagLayout();
+-        final GridBagConstraints c = new GridBagConstraints();
+-        setLayout(gridbag);
+-
+-        // Pad everything
+-        c.ipadx = 5;
+-        c.ipady = 5;
+-
+-        // Add the 1st column of labels
+-        c.gridx = 0;
+-        c.anchor = GridBagConstraints.EAST;
+-
+-        c.gridy = 0;
+-        JLabel label = new JLabel("Filter Level:");
+-        gridbag.setConstraints(label, c);
+-        add(label);
+-
+-        c.gridy++;
+-        label = new JLabel("Filter Thread:");
+-        gridbag.setConstraints(label, c);
+-        add(label);
+-
+-        c.gridy++;
+-        label = new JLabel("Filter Logger:");
+-        gridbag.setConstraints(label, c);
+-        add(label);
+-
+-        c.gridy++;
+-        label = new JLabel("Filter NDC:");
+-        gridbag.setConstraints(label, c);
+-        add(label);
+-
+-        c.gridy++;
+-        label = new JLabel("Filter Message:");
+-        gridbag.setConstraints(label, c);
+-        add(label);
+-
+-        // Add the 2nd column of filters
+-        c.weightx = 1;
+-        //c.weighty = 1;
+-        c.gridx = 1;
+-        c.anchor = GridBagConstraints.WEST;
+-
+-        c.gridy = 0;
+-        final Level[] allPriorities = new Level[] {Level.FATAL, 
+-               Level.ERROR, 
+-               Level.WARN, 
+-			   Level.INFO, 
+-			   Level.DEBUG, 
+-			   Level.TRACE };
+-        
+-        final JComboBox priorities = new JComboBox(allPriorities);
+-        final Level lowest = allPriorities[allPriorities.length - 1];
+-        priorities.setSelectedItem(lowest);
+-        aModel.setPriorityFilter(lowest);
+-        gridbag.setConstraints(priorities, c);
+-        add(priorities);
+-        priorities.setEditable(false);
+-        priorities.addActionListener(new ActionListener() {
+-                public void actionPerformed(ActionEvent aEvent) {
+-                    aModel.setPriorityFilter(
+-                        (Priority) priorities.getSelectedItem());
+-                }
+-            });
+-
+-
+-        c.fill = GridBagConstraints.HORIZONTAL;
+-        c.gridy++;
+-        final JTextField threadField = new JTextField("");
+-        threadField.getDocument().addDocumentListener(new DocumentListener () {
+-                public void insertUpdate(DocumentEvent aEvent) {
+-                    aModel.setThreadFilter(threadField.getText());
+-                }
+-                public void removeUpdate(DocumentEvent aEvente) {
+-                    aModel.setThreadFilter(threadField.getText());
+-                }
+-                public void changedUpdate(DocumentEvent aEvent) {
+-                    aModel.setThreadFilter(threadField.getText());
+-                }
+-            });
+-        gridbag.setConstraints(threadField, c);
+-        add(threadField);
+-
+-        c.gridy++;
+-        final JTextField catField = new JTextField("");
+-        catField.getDocument().addDocumentListener(new DocumentListener () {
+-                public void insertUpdate(DocumentEvent aEvent) {
+-                    aModel.setCategoryFilter(catField.getText());
+-                }
+-                public void removeUpdate(DocumentEvent aEvent) {
+-                    aModel.setCategoryFilter(catField.getText());
+-                }
+-                public void changedUpdate(DocumentEvent aEvent) {
+-                    aModel.setCategoryFilter(catField.getText());
+-                }
+-            });
+-        gridbag.setConstraints(catField, c);
+-        add(catField);
+-
+-        c.gridy++;
+-        final JTextField ndcField = new JTextField("");
+-        ndcField.getDocument().addDocumentListener(new DocumentListener () {
+-                public void insertUpdate(DocumentEvent aEvent) {
+-                    aModel.setNDCFilter(ndcField.getText());
+-                }
+-                public void removeUpdate(DocumentEvent aEvent) {
+-                    aModel.setNDCFilter(ndcField.getText());
+-                }
+-                public void changedUpdate(DocumentEvent aEvent) {
+-                    aModel.setNDCFilter(ndcField.getText());
+-                }
+-            });
+-        gridbag.setConstraints(ndcField, c);
+-        add(ndcField);
+-
+-        c.gridy++;
+-        final JTextField msgField = new JTextField("");
+-        msgField.getDocument().addDocumentListener(new DocumentListener () {
+-                public void insertUpdate(DocumentEvent aEvent) {
+-                    aModel.setMessageFilter(msgField.getText());
+-                }
+-                public void removeUpdate(DocumentEvent aEvent) {
+-                    aModel.setMessageFilter(msgField.getText());
+-                }
+-                public void changedUpdate(DocumentEvent aEvent) {
+-                    aModel.setMessageFilter(msgField.getText());
+-                }
+-            });
+-
+-
+-        gridbag.setConstraints(msgField, c);
+-        add(msgField);
+-
+-        // Add the 3rd column of buttons
+-        c.weightx = 0;
+-        c.fill = GridBagConstraints.HORIZONTAL;
+-        c.anchor = GridBagConstraints.EAST;
+-        c.gridx = 2;
+-
+-        c.gridy = 0;
+-        final JButton exitButton = new JButton("Exit");
+-        exitButton.setMnemonic('x');
+-        exitButton.addActionListener(ExitAction.INSTANCE);
+-        gridbag.setConstraints(exitButton, c);
+-        add(exitButton);
+-
+-        c.gridy++;
+-        final JButton clearButton = new JButton("Clear");
+-        clearButton.setMnemonic('c');
+-        clearButton.addActionListener(new ActionListener() {
+-                public void actionPerformed(ActionEvent aEvent) {
+-                    aModel.clear();
+-                }
+-            });
+-        gridbag.setConstraints(clearButton, c);
+-        add(clearButton);
+-
+-        c.gridy++;
+-        final JButton toggleButton = new JButton("Pause");
+-        toggleButton.setMnemonic('p');
+-        toggleButton.addActionListener(new ActionListener() {
+-                public void actionPerformed(ActionEvent aEvent) {
+-                    aModel.toggle();
+-                    toggleButton.setText(
+-                        aModel.isPaused() ? "Resume" : "Pause");
+-                }
+-            });
+-        gridbag.setConstraints(toggleButton, c);
+-        add(toggleButton);
+-    }
+-}
+diff --git a/src/main/java/org/apache/log4j/chainsaw/DetailPanel.java b/src/main/java/org/apache/log4j/chainsaw/DetailPanel.java
+deleted file mode 100644
+index 1f5dfe2..0000000
+--- a/src/main/java/org/apache/log4j/chainsaw/DetailPanel.java
++++ /dev/null
+@@ -1,170 +0,0 @@
+-/*
+- * 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.chainsaw;
+-
+-import java.awt.BorderLayout;
+-import java.text.MessageFormat;
+-import java.util.Date;
+-import javax.swing.BorderFactory;
+-import javax.swing.JEditorPane;
+-import javax.swing.JPanel;
+-import javax.swing.JScrollPane;
+-import javax.swing.JTable;
+-import javax.swing.ListSelectionModel;
+-import javax.swing.event.ListSelectionEvent;
+-import javax.swing.event.ListSelectionListener;
+-import org.apache.log4j.Logger;
+-
+-/**
+- * A panel for showing a stack trace.
+- *
+- * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+- */
+-class DetailPanel
+-    extends JPanel
+-    implements ListSelectionListener
+-{
+-    /** used to log events **/
+-    private static final Logger LOG =
+-        Logger.getLogger(DetailPanel.class);
+-
+-    /** used to format the logging event **/
+-    private static final MessageFormat FORMATTER = new MessageFormat(
+-        "<b>Time:</b> <code>{0,time,medium}</code>" +
+-        "  <b>Priority:</b> <code>{1}</code>" +
+-        "  <b>Thread:</b> <code>{2}</code>" +
+-        "  <b>NDC:</b> <code>{3}</code>" +
+-        "<br><b>Logger:</b> <code>{4}</code>" +
+-        "<br><b>Location:</b> <code>{5}</code>" +
+-        "<br><b>Message:</b>" +
+-        "<pre>{6}</pre>" +
+-        "<b>Throwable:</b>" +
+-        "<pre>{7}</pre>");
+-
+-    /** the model for the data to render **/
+-    private final MyTableModel mModel;
+-    /** pane for rendering detail **/
+-    private final JEditorPane mDetails;
+-
+-    /**
+-     * Creates a new <code>DetailPanel</code> instance.
+-     *
+-     * @param aTable the table to listen for selections on
+-     * @param aModel the model backing the table
+-     */
+-    DetailPanel(JTable aTable, final MyTableModel aModel) {
+-        mModel = aModel;
+-        setLayout(new BorderLayout());
+-        setBorder(BorderFactory.createTitledBorder("Details: "));
+-
+-        mDetails = new JEditorPane();
+-        mDetails.setEditable(false);
+-        mDetails.setContentType("text/html");
+-        add(new JScrollPane(mDetails), BorderLayout.CENTER);
+-
+-        final ListSelectionModel rowSM = aTable.getSelectionModel();
+-        rowSM.addListSelectionListener(this);
+-    }
+-
+-    /** @see ListSelectionListener **/
+-    public void valueChanged(ListSelectionEvent aEvent) {
+-        //Ignore extra messages.
+-        if (aEvent.getValueIsAdjusting()) {
+-            return;
+-        }
+-
+-        final ListSelectionModel lsm = (ListSelectionModel) aEvent.getSource();
+-        if (lsm.isSelectionEmpty()) {
+-            mDetails.setText("Nothing selected");
+-        } else {
+-            final int selectedRow = lsm.getMinSelectionIndex();
+-            final EventDetails e = mModel.getEventDetails(selectedRow);
+-            final Object[] args =
+-            {
+-                new Date(e.getTimeStamp()),
+-                e.getPriority(),
+-                escape(e.getThreadName()),
+-                escape(e.getNDC()),
+-                escape(e.getCategoryName()),
+-                escape(e.getLocationDetails()),
+-                escape(e.getMessage()),
+-                escape(getThrowableStrRep(e))
+-            };
+-            mDetails.setText(FORMATTER.format(args));
+-            mDetails.setCaretPosition(0);
+-        }
+-    }
+-
+-    ////////////////////////////////////////////////////////////////////////////
+-    // Private methods
+-    ////////////////////////////////////////////////////////////////////////////
+-
+-    /**
+-     * Returns a string representation of a throwable.
+-     *
+-     * @param aEvent contains the throwable information
+-     * @return a <code>String</code> value
+-     */
+-    private static String getThrowableStrRep(EventDetails aEvent) {
+-        final String[] strs = aEvent.getThrowableStrRep();
+-        if (strs == null) {
+-            return null;
+-        }
+-
+-        final StringBuffer sb = new StringBuffer();
+-        for (int i = 0; i < strs.length; i++) {
+-            sb.append(strs[i]).append("\n");
+-        }
+-
+-        return sb.toString();
+-    }
+-
+-    /**
+-     * Escape <, > & and " as their entities. It is very
+-     * dumb about & handling.
+-     * @param aStr the String to escape.
+-     * @return the escaped String
+-     */
+-    private String escape(String aStr) {
+-        if (aStr == null) {
+-            return null;
+-        }
+-
+-        final StringBuffer buf = new StringBuffer();
+-        for (int i = 0; i < aStr.length(); i++) {
+-            char c = aStr.charAt(i);
+-            switch (c) {
+-            case '<':
+-                buf.append("<");
+-                break;
+-            case '>':
+-                buf.append(">");
+-                break;
+-            case '\"':
+-                buf.append(""");
+-                break;
+-            case '&':
+-                buf.append("&");
+-                break;
+-            default:
+-                buf.append(c);
+-                break;
+-            }
+-        }
+-        return buf.toString();
+-    }
+-}
+diff --git a/src/main/java/org/apache/log4j/chainsaw/EventDetails.java b/src/main/java/org/apache/log4j/chainsaw/EventDetails.java
+deleted file mode 100644
+index 4b3ad94..0000000
+--- a/src/main/java/org/apache/log4j/chainsaw/EventDetails.java
++++ /dev/null
+@@ -1,135 +0,0 @@
+-/*
+- * 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.chainsaw;
+-
+-import org.apache.log4j.Priority;
+-import org.apache.log4j.spi.LoggingEvent;
+-
+-/**
+- * Represents the details of a logging event. It is intended to overcome the
+- * problem that a LoggingEvent cannot be constructed with purely fake data.
+- *
+- * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+- * @version 1.0
+- */
+-class EventDetails {
+-
+-    /** the time of the event **/
+-    private final long mTimeStamp;
+-    /** the priority of the event **/
+-    private final Priority mPriority;
+-    /** the category of the event **/
+-    private final String mCategoryName;
+-    /** the NDC for the event **/
+-    private final String mNDC;
+-    /** the thread for the event **/
+-    private final String mThreadName;
+-    /** the msg for the event **/
+-    private final String mMessage;
+-    /** the throwable details the event **/
+-    private final String[] mThrowableStrRep;
+-    /** the location details for the event **/
+-    private final String mLocationDetails;
+-
+-    /**
+-     * Creates a new <code>EventDetails</code> instance.
+-     * @param aTimeStamp a <code>long</code> value
+-     * @param aPriority a <code>Priority</code> value
+-     * @param aCategoryName a <code>String</code> value
+-     * @param aNDC a <code>String</code> value
+-     * @param aThreadName a <code>String</code> value
+-     * @param aMessage a <code>String</code> value
+-     * @param aThrowableStrRep a <code>String[]</code> value
+-     * @param aLocationDetails a <code>String</code> value
+-     */
+-    EventDetails(long aTimeStamp,
+-                 Priority aPriority,
+-                 String aCategoryName,
+-                 String aNDC,
+-                 String aThreadName,
+-                 String aMessage,
+-                 String[] aThrowableStrRep,
+-                 String aLocationDetails)
+-    {
+-        mTimeStamp = aTimeStamp;
+-        mPriority = aPriority;
+-        mCategoryName = aCategoryName;
+-        mNDC = aNDC;
+-        mThreadName = aThreadName;
+-        mMessage = aMessage;
+-        mThrowableStrRep = aThrowableStrRep;
+-        mLocationDetails = aLocationDetails;
+-    }
+-
+-    /**
+-     * Creates a new <code>EventDetails</code> instance.
+-     *
+-     * @param aEvent a <code>LoggingEvent</code> value
+-     */
+-    EventDetails(LoggingEvent aEvent) {
+-
+-        this(aEvent.timeStamp,
+-             aEvent.getLevel(),
+-             aEvent.getLoggerName(),
+-             aEvent.getNDC(),
+-             aEvent.getThreadName(),
+-             aEvent.getRenderedMessage(),
+-             aEvent.getThrowableStrRep(),
+-             (aEvent.getLocationInformation() == null)
+-             ? null : aEvent.getLocationInformation().fullInfo);
+-    }
+-
+-    /** @see #mTimeStamp **/
+-    long getTimeStamp() {
+-        return mTimeStamp;
+-    }
+-
+-    /** @see #mPriority **/
+-    Priority getPriority() {
+-        return mPriority;
+-    }
+-
+-    /** @see #mCategoryName **/
+-    String getCategoryName() {
+-        return mCategoryName;
+-    }
+-
+-    /** @see #mNDC **/
+-    String getNDC() {
+-        return mNDC;
+-    }
+-
+-    /** @see #mThreadName **/
+-    String getThreadName() {
+-        return mThreadName;
+-    }
+-
+-    /** @see #mMessage **/
+-    String getMessage() {
+-        return mMessage;
+-    }
+-
+-    /** @see #mLocationDetails **/
+-    String getLocationDetails(){
+-        return mLocationDetails;
+-    }
+-
+-    /** @see #mThrowableStrRep **/
+-    String[] getThrowableStrRep() {
+-        return mThrowableStrRep;
+-    }
+-}
+diff --git a/src/main/java/org/apache/log4j/chainsaw/ExitAction.java b/src/main/java/org/apache/log4j/chainsaw/ExitAction.java
+deleted file mode 100644
+index 55a100e..0000000
+--- a/src/main/java/org/apache/log4j/chainsaw/ExitAction.java
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/*
+- * 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.chainsaw;
+-
+-import java.awt.event.ActionEvent;
+-import javax.swing.AbstractAction;
+-import org.apache.log4j.Logger;
+-
+-/**
+- * Encapsulates the action to exit.
+- *
+- * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+- * @version 1.0
+- */
+-class ExitAction
+-    extends AbstractAction
+-{
+-    /** use to log messages **/
+-    private static final Logger LOG = Logger.getLogger(ExitAction.class);
+-    /** The instance to share **/
+-    public static final ExitAction INSTANCE = new ExitAction();
+-
+-    /** Stop people creating instances **/
+-    private ExitAction() {}
+-
+-    /**
+-     * Will shutdown the application.
+-     * @param aIgnore ignored
+-     */
+-    public void actionPerformed(ActionEvent aIgnore) {
+-        LOG.info("shutting down");
+-        System.exit(0);
+-    }
+-}
+diff --git a/src/main/java/org/apache/log4j/chainsaw/LoadXMLAction.java b/src/main/java/org/apache/log4j/chainsaw/LoadXMLAction.java
+deleted file mode 100644
+index 33e5d13..0000000
+--- a/src/main/java/org/apache/log4j/chainsaw/LoadXMLAction.java
++++ /dev/null
+@@ -1,139 +0,0 @@
+-/*
+- * 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.chainsaw;
+-
+-import java.awt.event.ActionEvent;
+-import java.io.File;
+-import java.io.IOException;
+-import java.io.StringReader;
+-import javax.swing.AbstractAction;
+-import javax.swing.JFileChooser;
+-import javax.swing.JFrame;
+-import javax.swing.JOptionPane;
+-import javax.xml.parsers.ParserConfigurationException;
+-import javax.xml.parsers.SAXParserFactory;
+-import org.apache.log4j.Logger;
+-import org.xml.sax.InputSource;
+-import org.xml.sax.SAXException;
+-import org.xml.sax.XMLReader;
+-
+-/**
+- * Encapsulates the action to load an XML file.
+- *
+- * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+- * @version 1.0
+- */
+-class LoadXMLAction
+-    extends AbstractAction
+-{
+-    /** use to log messages **/
+-    private static final Logger LOG = Logger.getLogger(LoadXMLAction.class);
+-
+-    /** the parent frame **/
+-    private final JFrame mParent;
+-
+-    /**
+-     * the file chooser - configured to allow only the selection of a
+-     * single file.
+-     */
+-    private final JFileChooser mChooser = new JFileChooser();
+-    {
+-        mChooser.setMultiSelectionEnabled(false);
+-        mChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+-    }
+-
+-    /** parser to read XML files **/
+-    private final XMLReader mParser;
+-    /** the content handler **/
+-    private final XMLFileHandler mHandler;
+-
+-
+-    /**
+-     * Creates a new <code>LoadXMLAction</code> instance.
+-     *
+-     * @param aParent the parent frame
+-     * @param aModel the model to add events to
+-     * @exception SAXException if an error occurs
+-     * @throws ParserConfigurationException if an error occurs
+-     */
+-    LoadXMLAction(JFrame aParent, MyTableModel aModel)
+-        throws SAXException, ParserConfigurationException
+-    {
+-        mParent = aParent;
+-        mHandler = new XMLFileHandler(aModel);
+-        mParser = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
+-        mParser.setContentHandler(mHandler);
+-    }
+-
+-    /**
+-     * Prompts the user for a file to load events from.
+-     * @param aIgnore an <code>ActionEvent</code> value
+-     */
+-    public void actionPerformed(ActionEvent aIgnore) {
+-        LOG.info("load file called");
+-        if (mChooser.showOpenDialog(mParent) == JFileChooser.APPROVE_OPTION) {
+-            LOG.info("Need to load a file");
+-            final File chosen = mChooser.getSelectedFile();
+-            LOG.info("loading the contents of " + chosen.getAbsolutePath());
+-            try {
+-                final int num = loadFile(chosen.getAbsolutePath());
+-                JOptionPane.showMessageDialog(
+-                    mParent,
+-                    "Loaded " + num + " events.",
+-                    "CHAINSAW",
+-                    JOptionPane.INFORMATION_MESSAGE);
+-            } catch (Exception e) {
+-                LOG.warn("caught an exception loading the file", e);
+-                JOptionPane.showMessageDialog(
+-                    mParent,
+-                    "Error parsing file - " + e.getMessage(),
+-                    "CHAINSAW",
+-                    JOptionPane.ERROR_MESSAGE);
+-            }
+-        }
+-    }
+-
+-    /**
+-     * Loads the contents of file into the model
+-     *
+-     * @param aFile the file to extract events from
+-     * @return the number of events loaded
+-     * @throws SAXException if an error occurs
+-     * @throws IOException if an error occurs
+-     */
+-    private int loadFile(String aFile)
+-        throws SAXException, IOException
+-    {
+-        synchronized (mParser) {
+-            // Create a dummy document to parse the file
+-            final StringBuffer buf = new StringBuffer();
+-            buf.append("<?xml version=\"1.0\" standalone=\"yes\"?>\n");
+-            buf.append("<!DOCTYPE log4j:eventSet ");
+-            buf.append("[<!ENTITY data SYSTEM \"file:///");
+-            buf.append(aFile);
+-            buf.append("\">]>\n");
+-            buf.append("<log4j:eventSet xmlns:log4j=\"Claira\">\n");
+-            buf.append("&data;\n");
+-            buf.append("</log4j:eventSet>\n");
+-
+-            final InputSource is =
+-                new InputSource(new StringReader(buf.toString()));
+-            mParser.parse(is);
+-            return mHandler.getNumEvents();
+-        }
+-    }
+-}
+diff --git a/src/main/java/org/apache/log4j/chainsaw/LoggingReceiver.java b/src/main/java/org/apache/log4j/chainsaw/LoggingReceiver.java
+deleted file mode 100644
+index ca087ad..0000000
+--- a/src/main/java/org/apache/log4j/chainsaw/LoggingReceiver.java
++++ /dev/null
+@@ -1,121 +0,0 @@
+-/*
+- * 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.chainsaw;
+-
+-import java.io.EOFException;
+-import java.io.IOException;
+-import java.io.ObjectInputStream;
+-import java.net.ServerSocket;
+-import java.net.Socket;
+-import java.net.SocketException;
+-import org.apache.log4j.Logger;
+-import org.apache.log4j.spi.LoggingEvent;
+-
+-/**
+- * A daemon thread the processes connections from a
+- * <code>org.apache.log4j.net.SocketAppender.html</code>.
+- *
+- * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+- */
+-class LoggingReceiver extends Thread {
+-    /** used to log messages **/
+-    private static final Logger LOG = Logger.getLogger(LoggingReceiver.class);
+-
+-    /**
+-     * Helper that actually processes a client connection. It receives events
+-     * and adds them to the supplied model.
+-     *
+-     * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+-     */
+-    private class Slurper implements Runnable {
+-        /** socket connection to read events from **/
+-        private final Socket mClient;
+-
+-        /**
+-         * Creates a new <code>Slurper</code> instance.
+-         *
+-         * @param aClient socket to receive events from
+-         */
+-        Slurper(Socket aClient) {
+-            mClient = aClient;
+-        }
+-
+-        /** loops getting the events **/
+-        public void run() {
+-            LOG.debug("Starting to get data");
+-            try {
+-                final ObjectInputStream ois =
+-                    new ObjectInputStream(mClient.getInputStream());
+-                while (true) {
+-                    final LoggingEvent event = (LoggingEvent) ois.readObject();
+-                    mModel.addEvent(new EventDetails(event));
+-                }
+-            } catch (EOFException e) {
+-                LOG.info("Reached EOF, closing connection");
+-            } catch (SocketException e) {
+-                LOG.info("Caught SocketException, closing connection");
+-            } catch (IOException e) {
+-                LOG.warn("Got IOException, closing connection", e);
+-            } catch (ClassNotFoundException e) {
+-                LOG.warn("Got ClassNotFoundException, closing connection", e);
+-            }
+-
+-            try {
+-                mClient.close();
+-            } catch (IOException e) {
+-                LOG.warn("Error closing connection", e);
+-            }
+-        }
+-    }
+-
+-    /** where to put the events **/
+-    private MyTableModel mModel;
+-
+-    /** server for listening for connections **/
+-    private ServerSocket mSvrSock;
+-    
+-    /**
+-     * Creates a new <code>LoggingReceiver</code> instance.
+-     *
+-     * @param aModel model to place put received into
+-     * @param aPort port to listen on
+-     * @throws IOException if an error occurs
+-     */
+-    LoggingReceiver(MyTableModel aModel, int aPort) throws IOException {
+-        setDaemon(true);
+-        mModel = aModel;
+-        mSvrSock = new ServerSocket(aPort);
+-    }
+-
+-    /** Listens for client connections **/
+-    public void run() {
+-        LOG.info("Thread started");
+-        try {
+-            while (true) {
+-                LOG.debug("Waiting for a connection");
+-                final Socket client = mSvrSock.accept();
+-                LOG.debug("Got a connection from " +
+-                          client.getInetAddress().getHostName());
+-                final Thread t = new Thread(new Slurper(client));
+-                t.setDaemon(true);
+-                t.start();
+-            }
+-        } catch (IOException e) {
+-            LOG.error("Error in accepting connections, stopping.", e);
+-        }
+-    }
+-}
+diff --git a/src/main/java/org/apache/log4j/chainsaw/Main.java b/src/main/java/org/apache/log4j/chainsaw/Main.java
+deleted file mode 100644
+index c0c9aad..0000000
+--- a/src/main/java/org/apache/log4j/chainsaw/Main.java
++++ /dev/null
+@@ -1,192 +0,0 @@
+-/*
+- * 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.chainsaw;
+-
+-import java.awt.BorderLayout;
+-import java.awt.Dimension;
+-import java.awt.event.WindowAdapter;
+-import java.awt.event.WindowEvent;
+-import java.io.IOException;
+-import java.util.Properties;
+-import javax.swing.BorderFactory;
+-import javax.swing.JFrame;
+-import javax.swing.JMenu;
+-import javax.swing.JMenuBar;
+-import javax.swing.JMenuItem;
+-import javax.swing.JOptionPane;
+-import javax.swing.JPanel;
+-import javax.swing.JScrollPane;
+-import javax.swing.JSplitPane;
+-import javax.swing.JTable;
+-import javax.swing.ListSelectionModel;
+-import org.apache.log4j.Logger;
+-import org.apache.log4j.PropertyConfigurator;
+-
+-/**
+- * The main application.
+- *
+- * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+- */
+-public class Main
+-    extends JFrame
+-{
+-    /** the default port number to listen on **/
+-    private static final int DEFAULT_PORT = 4445;
+-
+-    /** name of property for port name **/
+-    public static final String PORT_PROP_NAME = "chainsaw.port";
+-
+-    /** use to log messages **/
+-    private static final Logger LOG = Logger.getLogger(Main.class);
+-
+-
+-    /**
+-     * Creates a new <code>Main</code> instance.
+-     */
+-    private Main() {
+-        super("CHAINSAW - Log4J Log Viewer");
+-        // create the all important model
+-        final MyTableModel model = new MyTableModel();
+-
+-        //Create the menu bar.
+-        final JMenuBar menuBar = new JMenuBar();
+-        setJMenuBar(menuBar);
+-        final JMenu menu = new JMenu("File");
+-        menuBar.add(menu);
+-
+-        try {
+-            final LoadXMLAction lxa = new LoadXMLAction(this, model);
+-            final JMenuItem loadMenuItem = new JMenuItem("Load file...");
+-            menu.add(loadMenuItem);
+-            loadMenuItem.addActionListener(lxa);
+-        } catch (NoClassDefFoundError e) {
+-            LOG.info("Missing classes for XML parser", e);
+-            JOptionPane.showMessageDialog(
+-                this,
+-                "XML parser not in classpath - unable to load XML events.",
+-                "CHAINSAW",
+-                JOptionPane.ERROR_MESSAGE);
+-        } catch (Exception e) {
+-            LOG.info("Unable to create the action to load XML files", e);
+-            JOptionPane.showMessageDialog(
+-                this,
+-                "Unable to create a XML parser - unable to load XML events.",
+-                "CHAINSAW",
+-                JOptionPane.ERROR_MESSAGE);
+-        }
+-
+-        final JMenuItem exitMenuItem = new JMenuItem("Exit");
+-        menu.add(exitMenuItem);
+-        exitMenuItem.addActionListener(ExitAction.INSTANCE);
+-
+-        // Add control panel
+-        final ControlPanel cp = new ControlPanel(model);
+-        getContentPane().add(cp, BorderLayout.NORTH);
+-
+-        // Create the table
+-        final JTable table = new JTable(model);
+-        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+-        final JScrollPane scrollPane = new JScrollPane(table);
+-        scrollPane.setBorder(BorderFactory.createTitledBorder("Events: "));
+-        scrollPane.setPreferredSize(new Dimension(900, 300));
+-
+-        // Create the details
+-        final JPanel details = new DetailPanel(table, model);
+-        details.setPreferredSize(new Dimension(900, 300));
+-
+-        // Add the table and stack trace into a splitter
+-        final JSplitPane jsp =
+-            new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPane, details);
+-        getContentPane().add(jsp, BorderLayout.CENTER);
+-
+-        addWindowListener(new WindowAdapter() {
+-                public void windowClosing(WindowEvent aEvent) {
+-                    ExitAction.INSTANCE.actionPerformed(null);
+-                }
+-            });
+-
+-        pack();
+-        setVisible(true);
+-
+-        setupReceiver(model);
+-    }
+-
+-    /**
+-     * Setup recieving messages.
+-     *
+-     * @param aModel a <code>MyTableModel</code> value
+-     */
+-    private void setupReceiver(MyTableModel aModel) {
+-        int port = DEFAULT_PORT;
+-        final String strRep = System.getProperty(PORT_PROP_NAME);
+-        if (strRep != null) {
+-            try {
+-                port = Integer.parseInt(strRep);
+-            } catch (NumberFormatException nfe) {
+-                LOG.fatal("Unable to parse " + PORT_PROP_NAME +
+-                          " property with value " + strRep + ".");
+-                JOptionPane.showMessageDialog(
+-                    this,
+-                    "Unable to parse port number from '" + strRep +
+-                    "', quitting.",
+-                    "CHAINSAW",
+-                    JOptionPane.ERROR_MESSAGE);
+-                System.exit(1);
+-            }
+-        }
+-
+-        try {
+-            final LoggingReceiver lr = new LoggingReceiver(aModel, port);
+-            lr.start();
+-        } catch (IOException e) {
+-            LOG.fatal("Unable to connect to socket server, quiting", e);
+-            JOptionPane.showMessageDialog(
+-                this,
+-                "Unable to create socket on port " + port + ", quitting.",
+-                "CHAINSAW",
+-                JOptionPane.ERROR_MESSAGE);
+-            System.exit(1);
+-        }
+-    }
+-
+-
+-    ////////////////////////////////////////////////////////////////////////////
+-    // static methods
+-    ////////////////////////////////////////////////////////////////////////////
+-
+-
+-    /** initialise log4j **/
+-    private static void initLog4J() {
+-        final Properties props = new Properties();
+-        props.setProperty("log4j.rootLogger", "DEBUG, A1");
+-        props.setProperty("log4j.appender.A1",
+-                          "org.apache.log4j.ConsoleAppender");
+-        props.setProperty("log4j.appender.A1.layout",
+-                          "org.apache.log4j.TTCCLayout");
+-        PropertyConfigurator.configure(props);
+-    }
+-
+-    /**
+-     * The main method.
+-     *
+-     * @param aArgs ignored
+-     */
+-    public static void main(String[] aArgs) {
+-        initLog4J();
+-        new Main();
+-    }
+-}
+diff --git a/src/main/java/org/apache/log4j/chainsaw/MyTableModel.java b/src/main/java/org/apache/log4j/chainsaw/MyTableModel.java
+deleted file mode 100644
+index 0d43272..0000000
+--- a/src/main/java/org/apache/log4j/chainsaw/MyTableModel.java
++++ /dev/null
+@@ -1,390 +0,0 @@
+-/*
+- * 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.chainsaw;
+-
+-import java.text.DateFormat;
+-import java.util.ArrayList;
+-import java.util.Comparator;
+-import java.util.Date;
+-import java.util.Iterator;
+-import java.util.List;
+-import java.util.SortedSet;
+-import java.util.TreeSet;
+-import javax.swing.table.AbstractTableModel;
+-import org.apache.log4j.Priority;
+-import org.apache.log4j.Logger;
+-
+-/**
+- * Represents a list of <code>EventDetails</code> objects that are sorted on
+- * logging time. Methods are provided to filter the events that are visible.
+- *
+- * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+- */
+-class MyTableModel
+-    extends AbstractTableModel
+-{
+-
+-    /** used to log messages **/
+-    private static final Logger LOG = Logger.getLogger(MyTableModel.class);
+-
+-    /** use the compare logging events **/
+-    private static final Comparator MY_COMP = new Comparator()
+-    {
+-        /** @see Comparator **/
+-        public int compare(Object aObj1, Object aObj2) {
+-            if ((aObj1 == null) && (aObj2 == null)) {
+-                return 0; // treat as equal
+-            } else if (aObj1 == null) {
+-                return -1; // null less than everything
+-            } else if (aObj2 == null) {
+-                return 1; // think about it. :->
+-            }
+-
+-            // will assume only have LoggingEvent
+-            final EventDetails le1 = (EventDetails) aObj1;
+-            final EventDetails le2 = (EventDetails) aObj2;
+-
+-            if (le1.getTimeStamp() < le2.getTimeStamp()) {
+-                return 1;
+-            }
+-            // assume not two events are logged at exactly the same time
+-            return -1;
+-        }
+-        };
+-
+-    /**
+-     * Helper that actually processes incoming events.
+-     * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+-     */
+-    private class Processor
+-        implements Runnable
+-    {
+-        /** loops getting the events **/
+-        public void run() {
+-            while (true) {
+-                try {
+-                    Thread.sleep(1000);
+-                } catch (InterruptedException e) {
+-                    // ignore
+-                }
+-
+-                synchronized (mLock) {
+-                    if (mPaused) {
+-                        continue;
+-                    }
+-
+-                    boolean toHead = true; // were events added to head
+-                    boolean needUpdate = false;
+-                    final Iterator it = mPendingEvents.iterator();
+-                    while (it.hasNext()) {
+-                        final EventDetails event = (EventDetails) it.next();
+-                        mAllEvents.add(event);
+-                        toHead = toHead && (event == mAllEvents.first());
+-                        needUpdate = needUpdate || matchFilter(event);
+-                    }
+-                    mPendingEvents.clear();
+-
+-                    if (needUpdate) {
+-                        updateFilteredEvents(toHead);
+-                    }
+-                }
+-            }
+-
+-        }
+-    }
+-
+-
+-    /** names of the columns in the table **/
+-    private static final String[] COL_NAMES = {
+-        "Time", "Priority", "Trace", "Category", "NDC", "Message"};
+-
+-    /** definition of an empty list **/
+-    private static final EventDetails[] EMPTY_LIST =  new EventDetails[] {};
+-
+-    /** used to format dates **/
+-    private static final DateFormat DATE_FORMATTER =
+-        DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM);
+-
+-    /** the lock to control access **/
+-    private final Object mLock = new Object();
+-    /** set of all logged events - not filtered **/
+-    private final SortedSet mAllEvents = new TreeSet(MY_COMP);
+-    /** events that are visible after filtering **/
+-    private EventDetails[] mFilteredEvents = EMPTY_LIST;
+-    /** list of events that are buffered for processing **/
+-    private final List mPendingEvents = new ArrayList();
+-    /** indicates whether event collection is paused to the UI **/
+-    private boolean mPaused = false;
+-
+-    /** filter for the thread **/
+-    private String mThreadFilter = "";
+-    /** filter for the message **/
+-    private String mMessageFilter = "";
+-    /** filter for the NDC **/
+-    private String mNDCFilter = "";
+-    /** filter for the category **/
+-    private String mCategoryFilter = "";
+-    /** filter for the priority **/
+-    private Priority mPriorityFilter = Priority.DEBUG;
+-
+-
+-    /**
+-     * Creates a new <code>MyTableModel</code> instance.
+-     *
+-     */
+-    MyTableModel() {
+-        final Thread t = new Thread(new Processor());
+-        t.setDaemon(true);
+-        t.start();
+-    }
+-
+-
+-    ////////////////////////////////////////////////////////////////////////////
+-    // Table Methods
+-    ////////////////////////////////////////////////////////////////////////////
+-
+-    /** @see javax.swing.table.TableModel **/
+-    public int getRowCount() {
+-        synchronized (mLock) {
+-            return mFilteredEvents.length;
+-        }
+-    }
+-
+-    /** @see javax.swing.table.TableModel **/
+-    public int getColumnCount() {
+-        // does not need to be synchronized
+-        return COL_NAMES.length;
+-    }
+-
+-    /** @see javax.swing.table.TableModel **/
+-    public String getColumnName(int aCol) {
+-        // does not need to be synchronized
+-        return COL_NAMES[aCol];
+-    }
+-
+-    /** @see javax.swing.table.TableModel **/
+-    public Class getColumnClass(int aCol) {
+-        // does not need to be synchronized
+-        return (aCol == 2) ? Boolean.class : Object.class;
+-    }
+-
+-    /** @see javax.swing.table.TableModel **/
+-    public Object getValueAt(int aRow, int aCol) {
+-        synchronized (mLock) {
+-            final EventDetails event = mFilteredEvents[aRow];
+-
+-            if (aCol == 0) {
+-                return DATE_FORMATTER.format(new Date(event.getTimeStamp()));
+-            } else if (aCol == 1) {
+-                return event.getPriority();
+-            } else if (aCol == 2) {
+-                return (event.getThrowableStrRep() == null)
+-                    ? Boolean.FALSE : Boolean.TRUE;
+-            } else if (aCol == 3) {
+-                return event.getCategoryName();
+-            } else if (aCol == 4) {
+-                return event.getNDC();
+-            }
+-            return event.getMessage();
+-        }
+-    }
+-
+-    ////////////////////////////////////////////////////////////////////////////
+-    // Public Methods
+-    ////////////////////////////////////////////////////////////////////////////
+-
+-    /**
+-     * Sets the priority to filter events on. Only events of equal or higher
+-     * property are now displayed.
+-     *
+-     * @param aPriority the priority to filter on
+-     */
+-    public void setPriorityFilter(Priority aPriority) {
+-        synchronized (mLock) {
+-            mPriorityFilter = aPriority;
+-            updateFilteredEvents(false);
+-        }
+-    }
+-
+-    /**
+-     * Set the filter for the thread field.
+-     *
+-     * @param aStr the string to match
+-     */
+-    public void setThreadFilter(String aStr) {
+-        synchronized (mLock) {
+-            mThreadFilter = aStr.trim();
+-            updateFilteredEvents(false);
+-        }
+-    }
+-
+-    /**
+-     * Set the filter for the message field.
+-     *
+-     * @param aStr the string to match
+-     */
+-    public void setMessageFilter(String aStr) {
+-        synchronized (mLock) {
+-            mMessageFilter = aStr.trim();
+-            updateFilteredEvents(false);
+-        }
+-    }
+-
+-    /**
+-     * Set the filter for the NDC field.
+-     *
+-     * @param aStr the string to match
+-     */
+-    public void setNDCFilter(String aStr) {
+-        synchronized (mLock) {
+-            mNDCFilter = aStr.trim();
+-            updateFilteredEvents(false);
+-        }
+-    }
+-
+-    /**
+-     * Set the filter for the category field.
+-     *
+-     * @param aStr the string to match
+-     */
+-    public void setCategoryFilter(String aStr) {
+-        synchronized (mLock) {
+-            mCategoryFilter = aStr.trim();
+-            updateFilteredEvents(false);
+-        }
+-    }
+-
+-    /**
+-     * Add an event to the list.
+-     *
+-     * @param aEvent a <code>EventDetails</code> value
+-     */
+-    public void addEvent(EventDetails aEvent) {
+-        synchronized (mLock) {
+-            mPendingEvents.add(aEvent);
+-        }
+-    }
+-
+-    /**
+-     * Clear the list of all events.
+-     */
+-    public void clear() {
+-        synchronized (mLock) {
+-            mAllEvents.clear();
+-            mFilteredEvents = new EventDetails[0];
+-            mPendingEvents.clear();
+-            fireTableDataChanged();
+-        }
+-    }
+-
+-    /** Toggle whether collecting events **/
+-    public void toggle() {
+-        synchronized (mLock) {
+-            mPaused = !mPaused;
+-        }
+-    }
+-
+-    /** @return whether currently paused collecting events **/
+-    public boolean isPaused() {
+-        synchronized (mLock) {
+-            return mPaused;
+-        }
+-    }
+-
+-    /**
+-     * Get the throwable information at a specified row in the filtered events.
+-     *
+-     * @param aRow the row index of the event
+-     * @return the throwable information
+-     */
+-    public EventDetails getEventDetails(int aRow) {
+-        synchronized (mLock) {
+-            return mFilteredEvents[aRow];
+-        }
+-    }
+-
+-    ////////////////////////////////////////////////////////////////////////////
+-    // Private methods
+-    ////////////////////////////////////////////////////////////////////////////
+-
+-    /**
+-     * Update the filtered events data structure.
+-     * @param aInsertedToFront indicates whether events were added to front of
+-     *        the events. If true, then the current first event must still exist
+-     *        in the list after the filter is applied.
+-     */
+-    private void updateFilteredEvents(boolean aInsertedToFront) {
+-        final long start = System.currentTimeMillis();
+-        final List filtered = new ArrayList();
+-        final int size = mAllEvents.size();
+-        final Iterator it = mAllEvents.iterator();
+-
+-        while (it.hasNext()) {
+-            final EventDetails event = (EventDetails) it.next();
+-            if (matchFilter(event)) {
+-                filtered.add(event);
+-            }
+-        }
+-
+-        final EventDetails lastFirst = (mFilteredEvents.length == 0)
+-            ? null
+-            : mFilteredEvents[0];
+-        mFilteredEvents = (EventDetails[]) filtered.toArray(EMPTY_LIST);
+-
+-        if (aInsertedToFront && (lastFirst != null)) {
+-            final int index = filtered.indexOf(lastFirst);
+-            if (index < 1) {
+-                LOG.warn("In strange state");
+-                fireTableDataChanged();
+-            } else {
+-                fireTableRowsInserted(0, index - 1);
+-            }
+-        } else {
+-            fireTableDataChanged();
+-        }
+-
+-        final long end = System.currentTimeMillis();
+-        LOG.debug("Total time [ms]: " + (end - start)
+-                  + " in update, size: " + size);
+-    }
+-
+-    /**
+-     * Returns whether an event matches the filters.
+-     *
+-     * @param aEvent the event to check for a match
+-     * @return whether the event matches
+-     */
+-    private boolean matchFilter(EventDetails aEvent) {
+-        if (aEvent.getPriority().isGreaterOrEqual(mPriorityFilter) &&
+-            (aEvent.getThreadName().indexOf(mThreadFilter) >= 0) &&
+-            (aEvent.getCategoryName().indexOf(mCategoryFilter) >= 0) &&
+-            ((mNDCFilter.length() == 0) ||
+-             ((aEvent.getNDC() != null) &&
+-              (aEvent.getNDC().indexOf(mNDCFilter) >= 0))))
+-        {
+-            final String rm = aEvent.getMessage();
+-            if (rm == null) {
+-                // only match if we have not filtering in place
+-                return (mMessageFilter.length() == 0);
+-            } else {
+-                return (rm.indexOf(mMessageFilter) >= 0);
+-            }
+-        }
+-
+-        return false; // by default not match
+-    }
+-}
+diff --git a/src/main/java/org/apache/log4j/chainsaw/XMLFileHandler.java b/src/main/java/org/apache/log4j/chainsaw/XMLFileHandler.java
+deleted file mode 100644
+index 2f9af51..0000000
+--- a/src/main/java/org/apache/log4j/chainsaw/XMLFileHandler.java
++++ /dev/null
+@@ -1,170 +0,0 @@
+-/*
+- * 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.chainsaw;
+-
+-import java.util.StringTokenizer;
+-import org.apache.log4j.Level;
+-import org.xml.sax.Attributes;
+-import org.xml.sax.SAXException;
+-import org.xml.sax.helpers.DefaultHandler;
+-
+-/**
+- * A content handler for document containing Log4J events logged using the
+- * XMLLayout class. It will create events and add them to a supplied model.
+- *
+- * @author <a href="mailto:oliver at puppycrawl.com">Oliver Burn</a>
+- * @version 1.0
+- */
+-class XMLFileHandler
+-    extends DefaultHandler
+-{
+-    /** represents the event tag **/
+-    private static final String TAG_EVENT = "log4j:event";
+-    /** represents the message tag **/
+-    private static final String TAG_MESSAGE = "log4j:message";
+-    /** represents the ndc tag **/
+-    private static final String TAG_NDC = "log4j:NDC";
+-    /** represents the throwable tag **/
+-    private static final String TAG_THROWABLE = "log4j:throwable";
+-    /** represents the location info tag **/
+-    private static final String TAG_LOCATION_INFO = "log4j:locationInfo";
+-
+-    /** where to put the events **/
+-    private final MyTableModel mModel;
+-    /** the number of events in the document **/
+-    private int mNumEvents;
+-
+-    /** the time of the event **/
+-    private long mTimeStamp;
+-    /** the priority (level) of the event **/
+-    private Level mLevel;
+-    /** the category of the event **/
+-    private String mCategoryName;
+-    /** the NDC for the event **/
+-    private String mNDC;
+-    /** the thread for the event **/
+-    private String mThreadName;
+-    /** the msg for the event **/
+-    private String mMessage;
+-    /** the throwable details the event **/
+-    private String[] mThrowableStrRep;
+-    /** the location details for the event **/
+-    private String mLocationDetails;
+-    /** buffer for collecting text **/
+-    private final StringBuffer mBuf = new StringBuffer();
+-
+-    /**
+-     * Creates a new <code>XMLFileHandler</code> instance.
+-     *
+-     * @param aModel where to add the events
+-     */
+-    XMLFileHandler(MyTableModel aModel) {
+-        mModel = aModel;
+-    }
+-
+-    /** @see DefaultHandler **/
+-    public void startDocument()
+-        throws SAXException
+-    {
+-        mNumEvents = 0;
+-    }
+-
+-    /** @see DefaultHandler **/
+-    public void characters(char[] aChars, int aStart, int aLength) {
+-        mBuf.append(String.valueOf(aChars, aStart, aLength));
+-    }
+-
+-    /** @see DefaultHandler **/
+-    public void endElement(String aNamespaceURI,
+-                           String aLocalName,
+-                           String aQName)
+-    {
+-        if (TAG_EVENT.equals(aQName)) {
+-            addEvent();
+-            resetData();
+-        } else if (TAG_NDC.equals(aQName)) {
+-            mNDC = mBuf.toString();
+-        } else if (TAG_MESSAGE.equals(aQName)) {
+-            mMessage = mBuf.toString();
+-        } else if (TAG_THROWABLE.equals(aQName)) {
+-            final StringTokenizer st =
+-                new StringTokenizer(mBuf.toString(), "\n\t");
+-            mThrowableStrRep = new String[st.countTokens()];
+-            if (mThrowableStrRep.length > 0) {
+-                mThrowableStrRep[0] = st.nextToken();
+-                for (int i = 1; i < mThrowableStrRep.length; i++) {
+-                    mThrowableStrRep[i] = "\t" + st.nextToken();
+-                }
+-            }
+-        }
+-    }
+-
+-    /** @see DefaultHandler **/
+-    public void startElement(String aNamespaceURI,
+-                             String aLocalName,
+-                             String aQName,
+-                             Attributes aAtts)
+-    {
+-        mBuf.setLength(0);
+-
+-        if (TAG_EVENT.equals(aQName)) {
+-            mThreadName = aAtts.getValue("thread");
+-            mTimeStamp = Long.parseLong(aAtts.getValue("timestamp"));
+-            mCategoryName = aAtts.getValue("logger");
+-            mLevel = Level.toLevel(aAtts.getValue("level"));
+-        } else if (TAG_LOCATION_INFO.equals(aQName)) {
+-            mLocationDetails = aAtts.getValue("class") + "."
+-                + aAtts.getValue("method")
+-                + "(" + aAtts.getValue("file") + ":" + aAtts.getValue("line")
+-                + ")";
+-        }
+-    }
+-
+-    /** @return the number of events in the document **/
+-    int getNumEvents() {
+-        return mNumEvents;
+-    }
+-
+-    ////////////////////////////////////////////////////////////////////////////
+-    // Private methods
+-    ////////////////////////////////////////////////////////////////////////////
+-
+-    /** Add an event to the model **/
+-    private void addEvent() {
+-        mModel.addEvent(new EventDetails(mTimeStamp,
+-                                         mLevel,
+-                                         mCategoryName,
+-                                         mNDC,
+-                                         mThreadName,
+-                                         mMessage,
+-                                         mThrowableStrRep,
+-                                         mLocationDetails));
+-        mNumEvents++;
+-    }
+-
+-    /** Reset the data for an event **/
+-    private void resetData() {
+-        mTimeStamp = 0;
+-        mLevel = null;
+-        mCategoryName = null;
+-        mNDC = null;
+-        mThreadName = null;
+-        mMessage = null;
+-        mThrowableStrRep = null;
+-        mLocationDetails = null;
+-    }
+-}
+diff --git a/src/main/java/org/apache/log4j/chainsaw/package.html b/src/main/java/org/apache/log4j/chainsaw/package.html
+deleted file mode 100644
+index 5b01480..0000000
+--- a/src/main/java/org/apache/log4j/chainsaw/package.html
++++ /dev/null
+@@ -1,118 +0,0 @@
+-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+-<!--
+- Licensed to the Apache Software Foundation (ASF) under one or more
+- contributor license agreements.  See the NOTICE file distributed with
+- this work for additional information regarding copyright ownership.
+- The ASF licenses this file to You under the Apache License, Version 2.0
+- (the "License"); you may not use this file except in compliance with
+- the License.  You may obtain a copy of the License at
+-
+-      http://www.apache.org/licenses/LICENSE-2.0
+-
+- Unless required by applicable law or agreed to in writing, software
+- distributed under the License is distributed on an "AS IS" BASIS,
+- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+- See the License for the specific language governing permissions and
+- limitations under the License.
+-
+--->
+-
+-<HTML>
+-  <HEAD>
+-    <TITLE>Chainsaw Tool</TITLE>
+-  </head>
+-    
+-  <BODY>
+-
+-    <P>Chainsaw is a GUI log viewer and filter for the log4j
+-package. By default it listens for <a
+-href="../spi/LoggingEvent.html">LoggingEvent</A> objects sent using
+-the <A href="../net/SocketAppender.html">SocketAppender</A> and
+-displays them in a table. The events can be filtered based on:</P>
+-
+-    <UL>
+-      <LI>Level </li>
+-
+-      <LI>Thread name</li>
+-
+-      <LI>Logger</li>
+-      <LI>Message</li>
+-
+-      <LI>NDC</LI>
+-    </UL>
+-
+-    <P>All the details for each event can be displayed by selecting
+-      the event in the table.</P> 
+-
+-    <P>Chainsaw also supports loading a events logged to a file using
+-      the <A href="../xml/XMLLayout.html">XMLLayout</A> format. This
+-      is great for analysing log files, and means you do not need to
+-      keep Chainsaw running continously. It is easy to add support
+-      for loading events from other sources like JDBC.</P> 
+-
+-    <P>A picture is worth a thousand words: </P>
+-
+-    <P align=center><A
+-      href="doc-files/screen_01.png"><IMG
+-      height="50%" alt="Screen shot of chainsaw"
+-      src="doc-files/screen_01.png"
+-      width="50%"></A>.</P> 
+-
+-    <P>Finally, why is it called chainsaw?
+-      Because it cuts your log (file) down to size. :-)
+-    </P>
+-
+-
+-    <H2>Requirements</H2> 
+-
+-    <P>Chainsaw is based on the Swing API which requires JDK 1.2 or later.</P>
+-
+-
+-    <H2>Running chainsaw</H2>
+-
+-    <H3>Setup</H3>
+-    <P>You need to include the <code>log4j.jar</code> in the classpath.
+-
+-    <H3>Usage</H3>
+-
+-    <P>The command line usage is:</P>
+-
+-    <PRE>  java -D<property>=<value> org.apache.log4j.chainsaw.Main </PRE>
+-
+-    <P>The default behaviour of chainsaw can be changed by setting system properties 
+-      using the <CODE>-D<property>=<value></CODE> arguments to java. The 
+-      following table describes what properties can be set:</P>
+-
+-    <TABLE cellSpacing=0 cellPadding=2 border=1>
+-
+-      <TR>
+-	<TD vAlign=top><B>Property</B></TD>
+-	<TD vAlign=top><B>Description</B></TD></TR>
+-      <TR>
+-	<TD vAlign=top>chainsaw.port</TD>
+-	<TD vAlign=top>Indicates which port to listen for connections on. Defaults 
+-	  to <SPAN class=default>"4445"</SPAN>.
+-	</TD>
+-      </TR>
+-    </TBODY>
+-    </TABLE>
+-
+-    <H2>Configuring Log4J</H2>
+-
+-    <P>You will need to configure log4j to send logging events to
+-      Chainsaw.  Here is a sample <CODE>log4j.properties</CODE> file
+-      for sending logging events to Chainsaw.</P>
+-
+-<PRE>
+-log4j.rootLogger=DEBUG, CHAINSAW_CLIENT
+-
+-log4j.appender.CHAINSAW_CLIENT=org.apache.log4j.net.SocketAppender
+-log4j.appender.CHAINSAW_CLIENT.RemoteHost=localhost
+-log4j.appender.CHAINSAW_CLIENT.Port=4445
+-log4j.appender.CHAINSAW_CLIENT.LocationInfo=true
+-</PRE>
+-
+-
+-
+-  </body>
+-</html>
+\ No newline at end of file


=====================================
debian/patches/series
=====================================
@@ -1,5 +1,8 @@
 build_fix.patch
-
 remove-activation-framework-dependency.patch
 add-missing-classes.patch
 CVE-2019-17571.patch
+CVE-2022-23305.patch
+CVE-2022-23302.patch
+CVE-2022-23307.patch
+CVE-2021-4104.patch



View it on GitLab: https://salsa.debian.org/java-team/apache-log4j1.2/-/compare/f3b7ea09e881ab3dbdf111152ba7bf339416822c...406287ebf5aabc20330e8130d96b1e2af410b948

-- 
View it on GitLab: https://salsa.debian.org/java-team/apache-log4j1.2/-/compare/f3b7ea09e881ab3dbdf111152ba7bf339416822c...406287ebf5aabc20330e8130d96b1e2af410b948
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20220212/078e5b69/attachment.htm>


More information about the pkg-java-commits mailing list