sdeboy      2004/12/05 02:17:37

  Modified:    src/java/org/apache/log4j/chainsaw/receivers known.receivers
               src/java/org/apache/log4j/rule ExpressionRule.java
                        LevelInequalityRule.java
               src/java/org/apache/log4j/chainsaw LogPanel.java
                        TableColorizingRenderer.java LogUI.java
                        log4j-receiver-sample.xml
                        LogPanelPreferenceModel.java
                        ApplicationPreferenceModelPanel.java
                        ChainsawAppenderHandler.java
               src/java/org/apache/log4j/chainsaw/help release-notes.html
  Added:       src/java/org/apache/log4j/db CustomSQLDBReceiver.java
  Log:
  - initialization of the logging framework from inside Chainsaw is now 
deferred to as late as possible in order to allow the internal event handlers 
to be configured and added to the logger hierarchy.  This meant deferring the 
creation of loggers in helper classes and changing helper classes to not use 
static loggers where necessary
  - improved level inequality rule logic to trigger an illegalargumentexception 
if an unknown level is passed in
  - added customsqldbreceiver and included access to javadoc in Chainsaw's help 
menu, added xml config example to Chainsaw's sample receiver config file
  - added empty string check in expressionrule to prevent string out of bounds 
errors
  - modified tablecolorizingrenderer in an attempt to simplify the code and 
prevent null pointer exceptions when a null value was received by the renderer
  
  Revision  Changes    Path
  1.7       +1 -0      
logging-log4j/src/java/org/apache/log4j/chainsaw/receivers/known.receivers
  
  Index: known.receivers
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/chainsaw/receivers/known.receivers,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- known.receivers   19 Aug 2004 22:36:44 -0000      1.6
  +++ known.receivers   5 Dec 2004 10:17:36 -0000       1.7
  @@ -8,4 +8,5 @@
   org.apache.log4j.net.XMLSocketReceiver
   org.apache.log4j.net.JMSReceiver
   org.apache.log4j.db.DBReceiver
  +org.apache.log4j.db.CustomSQLDBReceiver
   org.apache.log4j.varia.LogFilePatternReceiver
  
  
  
  1.9       +6 -2      
logging-log4j/src/java/org/apache/log4j/rule/ExpressionRule.java
  
  Index: ExpressionRule.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/rule/ExpressionRule.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- ExpressionRule.java       29 Nov 2004 09:18:11 -0000      1.8
  +++ ExpressionRule.java       5 Dec 2004 10:17:36 -0000       1.9
  @@ -100,7 +100,9 @@
                 token = token + " " + tokenizer.nextToken();
                 inText = !(token.endsWith("'"));
             }
  -          token = token.substring(0, token.length() - 1);
  +          if (token.length() > 0) {
  +              token = token.substring(0, token.length() - 1);
  +          }
           }
   
           //if a symbol is found, pop 2 off the stack, evaluate and push the 
result 
  @@ -109,7 +111,9 @@
             stack.push(r);
           } else {
             //variables or constants are pushed onto the stack
  -          stack.push(token);
  +          if (token.length() > 0) {
  +              stack.push(token);
  +          }
           }
         }
         
  
  
  
  1.9       +20 -1     
logging-log4j/src/java/org/apache/log4j/rule/LevelInequalityRule.java
  
  Index: LevelInequalityRule.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/rule/LevelInequalityRule.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- LevelInequalityRule.java  29 Nov 2004 18:50:38 -0000      1.8
  +++ LevelInequalityRule.java  5 Dec 2004 10:17:36 -0000       1.9
  @@ -31,6 +31,7 @@
    */
   public class LevelInequalityRule {
       private static List levelList;
  +    private static List utilLoggingLevelList;
   
       static {
           populateLevels();
  @@ -48,16 +49,34 @@
           levelList.add(Level.INFO.toString());
           levelList.add(Level.DEBUG.toString());
           levelList.add(Level.TRACE.toString());
  +        
  +        utilLoggingLevelList = new LinkedList();
  +
  +        utilLoggingLevelList.add(UtilLoggingLevel.SEVERE.toString());
  +        utilLoggingLevelList.add(UtilLoggingLevel.WARNING.toString());
  +        utilLoggingLevelList.add(UtilLoggingLevel.INFO.toString());
  +        utilLoggingLevelList.add(UtilLoggingLevel.CONFIG.toString());
  +        utilLoggingLevelList.add(UtilLoggingLevel.FINE.toString());
  +        utilLoggingLevelList.add(UtilLoggingLevel.FINER.toString());
  +        utilLoggingLevelList.add(UtilLoggingLevel.FINEST.toString());
  +
       }
   
       public static Rule getRule(String inequalitySymbol, String value) {
   
           Level thisLevel = null;
           
  +        //if valid util.logging levels are used against events with log4j 
levels, the 
  +        //DEBUG level is used and an illegalargumentexception won't be 
generated
  +        
  +        //an illegalargumentexception is only generated if the user types a 
level name
  +        //that doesn't exist as either a log4j or util.logging level name
           if (levelList.contains(value.toUpperCase())) {
               thisLevel = Level.toLevel(value.toUpperCase());
  -        } else {
  +        } else if (utilLoggingLevelList.contains(value.toUpperCase())){
               thisLevel = UtilLoggingLevel.toLevel(value.toUpperCase());
  +        } else {
  +            throw new IllegalArgumentException("Invalid level inequality 
rule - " + value + " is not a supported level");
           }
   
           if ("<".equals(inequalitySymbol)) {
  
  
  
  1.92      +1 -0      
logging-log4j/src/java/org/apache/log4j/chainsaw/LogPanel.java
  
  Index: LogPanel.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/chainsaw/LogPanel.java,v
  retrieving revision 1.91
  retrieving revision 1.92
  diff -u -r1.91 -r1.92
  --- LogPanel.java     1 Dec 2004 07:58:07 -0000       1.91
  +++ LogPanel.java     5 Dec 2004 10:17:36 -0000       1.92
  @@ -245,6 +245,7 @@
     public LogPanel(final ChainsawStatusBar statusBar, final String 
identifier, int cyclicBufferSize) {
       this.identifier = identifier;
       this.statusBar = statusBar;
  +    logger.debug("creating logpanel for " + identifier);
   
       setLayout(new BorderLayout());
       scroll = true;
  
  
  
  1.17      +29 -44    
logging-log4j/src/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
  
  Index: TableColorizingRenderer.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- TableColorizingRenderer.java      24 Nov 2004 08:17:01 -0000      1.16
  +++ TableColorizingRenderer.java      5 Dec 2004 10:17:36 -0000       1.17
  @@ -85,10 +85,7 @@
       int row, int col) {
       value = formatField(value);
   
  -    Color background = null;
  -    Color foreground = null;
  -
  -    Component c = super.getTableCellRendererComponent(table, value, 
  +    JLabel c = (JLabel)super.getTableCellRendererComponent(table, value, 
           isSelected, hasFocus, row, col);
       int colIndex = table.getColumnModel().getColumn(col).getModelIndex() + 1;
   
  @@ -102,26 +99,25 @@
   
       case ChainsawColumns.INDEX_THROWABLE_COL_NAME:
         if (value instanceof String[]) {
  -        ((JLabel) c).setText(((String[]) value)[0]);
  +        c.setText(((String[]) value)[0]);
         }
         break;
   
       case ChainsawColumns.INDEX_LOGGER_COL_NAME:
         if (loggerPrecision == 0) {
           break;
  -      } else {
  -        String logger = value.toString();
  -        int startPos = -1;
  +      }
  +      String logger = value.toString();
  +      int startPos = -1;
   
  -        for (int i = 0; i < loggerPrecision; i++) {
  -          startPos = logger.indexOf(".", startPos + 1);
  -          if (startPos < 0) {
  -              break;
  -          }
  +      for (int i = 0; i < loggerPrecision; i++) {
  +        startPos = logger.indexOf(".", startPos + 1);
  +        if (startPos < 0) {
  +          break;
           }
  -
  -        ((JLabel) c).setText(logger.substring(startPos + 1));
         }
  +
  +    c.setText(logger.substring(startPos + 1));
         break;
   
       case ChainsawColumns.INDEX_LEVEL_COL_NAME:
  @@ -131,15 +127,18 @@
           if (levelComponent.getIcon() != null) {
             levelComponent.setText("");
           }
  -
  -        if (toolTipsVisible) {
  -            levelComponent.setToolTipText(((JLabel)c).getToolTipText());
  -        } else {
  -            levelComponent.setToolTipText(value.toString());
  -        } 
  +        if (!toolTipsVisible) {
  +          levelComponent.setToolTipText(value.toString());
  +        }
         } else {
           levelComponent.setIcon(null);
           levelComponent.setText(value.toString());
  +        if (!toolTipsVisible) {
  +            levelComponent.setToolTipText(null);
  +        }
  +      }
  +      if (toolTipsVisible) {
  +          levelComponent.setToolTipText(c.getToolTipText());
         }
         levelComponent.setForeground(c.getForeground());
         levelComponent.setBackground(c.getBackground());
  @@ -155,7 +154,10 @@
         return c;
       }
   
  -    if (getColorizer() != null) {
  +    Color background = null;
  +    Color foreground = null;
  +
  +    if (colorizer != null) {
         EventContainer container = (EventContainer) table.getModel();
         LoggingEvent event = container.getRow(row);
   
  @@ -163,8 +165,8 @@
           //ignore...probably changed displayed cols
           return c;
         }
  -      background = getColorizer().getBackgroundColor(event);
  -      foreground = getColorizer().getForegroundColor(event);
  +      background = colorizer.getBackgroundColor(event);
  +      foreground = colorizer.getForegroundColor(event);
       }
   
       /**
  @@ -217,10 +219,9 @@
      */
     private Object formatField(Object o) {
       if (!(o instanceof Date)) {
  -      return o;
  -    } else {
  -      return dateFormatInUse.format((Date) o);
  +      return (o == null ? "" : o);
       }
  +    return dateFormatInUse.format((Date) o);
     }
   
     /**
  @@ -230,23 +231,7 @@
       this.colorizer = colorizer;
     }
   
  -  /**
  -   * @return colorizer
  -   */
  -  public Colorizer getColorizer() {
  -    return colorizer;
  -  }
  -
  -  /**
  -   * Returns true if this renderer will use Icons to render the Level
  -   * column, otherwise false.
  -   * @return level use icons flag
  -   */
  -  public boolean isLevelUseIcons() {
  -    return levelUseIcons;
  -  }
  -
  -  /**
  +   /**
      * Sets the property which determines whether to use Icons or text
      * for the Level column
      * @param levelUseIcons
  
  
  
  1.112     +32 -34    
logging-log4j/src/java/org/apache/log4j/chainsaw/LogUI.java
  
  Index: LogUI.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/chainsaw/LogUI.java,v
  retrieving revision 1.111
  retrieving revision 1.112
  diff -u -r1.111 -r1.112
  --- LogUI.java        1 Dec 2004 16:53:39 -0000       1.111
  +++ LogUI.java        5 Dec 2004 10:17:36 -0000       1.112
  @@ -123,7 +123,13 @@
    * that is used to display a Welcome panel, and any other panels that are
    * generated because Logging Events are streamed via a Receiver, or other
    * mechanism.
  - *
  + * 
  + * NOTE: Some of Chainsaw's application initialization should be performed 
prior 
  + * to activating receivers and the logging framework used to perform 
self-logging.  
  + * 
  + * DELAY as much as possible the logging framework initialization process,
  + * currently initialized by the creation of a ChainsawAppenderHandler.
  + * 
    * @author Scott Deboy <[EMAIL PROTECTED]>
    * @author Paul Smith  <[EMAIL PROTECTED]>
    *
  @@ -143,8 +149,7 @@
     private ChainsawStatusBar statusBar;
     private final ApplicationPreferenceModel applicationPreferenceModel =
       new ApplicationPreferenceModel();
  -  private final ApplicationPreferenceModelPanel 
applicationPreferenceModelPanel =
  -    new ApplicationPreferenceModelPanel(applicationPreferenceModel);
  +  private ApplicationPreferenceModelPanel applicationPreferenceModelPanel;
     private final Map tableModelMap = new HashMap();
     private final Map tableMap = new HashMap();
     private final List filterableColumns = new ArrayList();
  @@ -160,12 +165,8 @@
     private final List identifierPanels = new ArrayList();
     private int dividerSize;
     private int cyclicBufferSize;
  -  private static final Logger logger = LogManager.getLogger(LogUI.class);
  +  private static Logger logger;
   
  -  static {
  -      LogManager.getRootLogger().setLevel(Level.TRACE);
  -  }
  -  
     /**
      * Set to true, if and only if the GUI has completed it's full
      * initialization. Any logging events that come in must wait until this is
  @@ -285,8 +286,6 @@
                                }
                        });
       }
  -    logger.info("SecurityManager is now: " + System.getSecurityManager());
  -    
       
       LogUI logUI = new LogUI();
   
  @@ -295,12 +294,17 @@
       }
       logUI.cyclicBufferSize = model.getCyclicBufferSize();
   
  -    logUI.handler = new ChainsawAppenderHandler();
       PropertyFilter propFilter = new PropertyFilter();
       
propFilter.setProperties(Constants.HOSTNAME_KEY+"=chainsaw,"+Constants.APPLICATION_KEY+"=log");
  +
  +    logUI.handler = new ChainsawAppenderHandler();
       logUI.handler.addFilter(propFilter);
  +
       logUI.handler.addEventBatchListener(logUI.new 
NewTabEventBatchReceiver());
  -    
  +    //NOTE: this next line MUST be the first place where the logging 
framework is initialized
  +    //if started from the 'main' method
  +    LogManager.getRootLogger().setLevel(Level.TRACE);
  +    logger = LogManager.getLogger(LogUI.class);
       /**
        * TODO until we work out how JoranConfigurator might be able to have
        * configurable class loader, if at all.  For now we temporarily replace 
the
  @@ -312,8 +316,8 @@
       String config = model.getConfigurationURL();
       if(config!=null && (!(config.trim().equals("")))) {
           config = config.trim();
  +        logger.info("Using '" + config + "' for auto-configuration");
           try {
  -          logger.info("Using '" + config + "' for auto-configuration");
             URL configURL = new URL(config);
             logUI.loadConfigurationUsingPluginClassLoader(configURL);
           }catch(MalformedURLException e) {
  @@ -328,6 +332,8 @@
   
       logUI.getApplicationPreferenceModel().apply(model);
   
  +    logger.info("SecurityManager is now: " + System.getSecurityManager());
  +
       logUI.checkForNewerVersion();
       
       if (newShutdownAction != null) {
  @@ -349,6 +355,8 @@
      *
      */
     public void activateViewer(ChainsawAppender appender) {
  +    //if Chainsaw is launched as an appender, ensure the root logger level 
is TRACE
  +    LogManager.getRootLogger().setLevel(Level.TRACE);
       ApplicationPreferenceModel model = new ApplicationPreferenceModel();
       SettingsManager.getInstance().configure(model);
   
  @@ -359,8 +367,8 @@
       PropertyFilter propFilter = new PropertyFilter();
       
propFilter.setProperties(Constants.HOSTNAME_KEY+"=chainsaw,"+Constants.APPLICATION_KEY+"=log");
       handler.addFilter(propFilter);
  -
       handler.addEventBatchListener(new NewTabEventBatchReceiver());
  +
       LogManager.getRootLogger().addAppender(appender);
   
       setShutdownAction(
  @@ -430,6 +438,7 @@
       getTabbedPane().setEnabledAt(getTabbedPane().indexOfTab(dndTitle), 
false);
       ensureWelcomePanelVisible();
       
  +    applicationPreferenceModelPanel = new 
ApplicationPreferenceModelPanel(applicationPreferenceModel);
       applicationPreferenceModelPanel.setOkCancelActionListener(
         new ActionListener() {
           public void actionPerformed(ActionEvent e) {
  @@ -1600,23 +1609,6 @@
       return getCurrentLogPanel().isLogTreeVisible();
     }
   
  -  /*
  -   * (non-Javadoc)
  -   *
  -   * @see 
org.apache.log4j.chainsaw.EventBatchListener#getInterestedIdentifier()
  -   */
  -
  -  /**
  -   * DOCUMENT ME!
  -   *
  -   * @return DOCUMENT ME!
  -   */
  -  public String getIntereXstedIdentifier() {
  -    //    this instance is interested in ALL event batches, as we determine 
how to
  -    // route things
  -    return null;
  -  }
  -
     /**
      * DOCUMENT ME!
      *
  @@ -1787,6 +1779,11 @@
           }
         });
   
  +    logger.debug("adding logpanel to tabbed pane: " + ident);
  +    SwingUtilities.invokeLater(new Runnable() {
  +        public void run() {
  +    }
  +    });
       getTabbedPane().add(ident, thisPanel);
       getPanelMap().put(ident, thisPanel);
   
  @@ -1847,7 +1844,6 @@
           ClassLoader previousTCCL = 
Thread.currentThread().getContextClassLoader();
           
           if(url!=null) {
  -            logger.info("Using '" + url.toExternalForm()+ "' for 
auto-configuration");
               try {
                 // we temporarily swap the TCCL so that plugins can find 
resources
                 Thread.currentThread().setContextClassLoader(classLoader);
  @@ -1857,8 +1853,6 @@
                   // now switch it back...
                   Thread.currentThread().setContextClassLoader(previousTCCL);
               }
  -        }else {
  -            logger.info("auto-configuration file has not been provided");
           }
           ensureChainsawAppenderHandlerAdded();
       }
  @@ -1906,16 +1900,20 @@
                            */
               try {
                 initializationLock.wait(1000);
  +              logger.debug("waiting for initialization to complete");
               } catch (InterruptedException e) {
               }
             }
  +          logger.debug("out of system initialization wait loop");
           }
         }
   
         if (!getPanelMap().containsKey(ident)) {
  +          logger.debug("panel " + ident + " does not exist - creating");
           try {
             buildLogPanel(false, ident, events);
           } catch (IllegalArgumentException iae) {
  +            logger.error("error creating log panel", iae);
             //should not happen - not a custom expression panel
           }
         }
  
  
  
  1.4       +13 -0     
logging-log4j/src/java/org/apache/log4j/chainsaw/log4j-receiver-sample.xml
  
  Index: log4j-receiver-sample.xml
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/chainsaw/log4j-receiver-sample.xml,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- log4j-receiver-sample.xml 1 Dec 2004 07:58:07 -0000       1.3
  +++ log4j-receiver-sample.xml 5 Dec 2004 10:17:36 -0000       1.4
  @@ -31,6 +31,19 @@
        <param name="tailing" value="true"/> 
      </plugin>
   
  +   <plugin name="CustomDBReceiver" 
class="org.apache.log4j.db.CustomSQLDBReceiver">
  +      <connectionSource 
class="org.apache.log4j.db.DriverManagerConnectionSource">
  +        <param name="password" value="somepassword"/>
  +        <param name="user" value="someuser"/>
  +        <param name="driverClass" value="org.gjt.mm.mysql.Driver"/>
  +        <param name="url" value="jdbc:mysql://127.0.0.1/logs"/>
  +       </connectionSource>
  +      <param name="refreshMillis" value="5000"/>
  +      <param name="sql" value='select logger as LOGGER, timestamp as 
TIMESTAMP, level as LEVEL, thread as THREAD, message as MESSAGE, ndc as NDC, 
mdc as MDC, class as CLASS, method as METHOD, file as FILE, line as LINE, 
concat("{{application,databaselogs,hostname,mymachine,log4jid,", COUNTER, "}}") 
as PROPERTIES, "" as EXCEPTION from logtable'/> 
  +      <param name="IDField" value="COUNTER"/>
  +   </plugin>
  +
  +
      <root>
         <level value="debug"/>
      </root>
  
  
  
  1.13      +1 -2      
logging-log4j/src/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java
  
  Index: LogPanelPreferenceModel.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- LogPanelPreferenceModel.java      24 Nov 2004 08:17:01 -0000      1.12
  +++ LogPanelPreferenceModel.java      5 Dec 2004 10:17:36 -0000       1.13
  @@ -186,9 +186,8 @@
      * @param levelIcons
      */
     public void setLevelIcons(boolean levelIcons) {
  -    boolean oldVal = this.levelIcons;
       this.levelIcons = levelIcons;
  -    propertySupport.firePropertyChange("levelIcons", oldVal, 
this.levelIcons);
  +    propertySupport.firePropertyChange("levelIcons", !levelIcons, 
levelIcons);
     }
   
     /**
  
  
  
  1.19      +3 -2      
logging-log4j/src/java/org/apache/log4j/chainsaw/ApplicationPreferenceModelPanel.java
  
  Index: ApplicationPreferenceModelPanel.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/chainsaw/ApplicationPreferenceModelPanel.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- ApplicationPreferenceModelPanel.java      24 Nov 2004 08:17:01 -0000      
1.18
  +++ ApplicationPreferenceModelPanel.java      5 Dec 2004 10:17:36 -0000       
1.19
  @@ -66,10 +66,11 @@
     private JTextField toolTipDisplayMillis;
     private JTextField cyclicBufferSize;    
     private final JTextField configurationURL = new JTextField(35);
  -  private static final Logger logger = 
LogManager.getLogger(ApplicationPreferenceModelPanel.class);
  +  private final Logger logger;
   
     ApplicationPreferenceModelPanel(ApplicationPreferenceModel model) {
       this.committedPreferenceModel = model;
  +    logger = LogManager.getLogger(ApplicationPreferenceModelPanel.class);
       initComponents();
       getOkButton().addActionListener(
         new ActionListener() {
  @@ -113,7 +114,7 @@
       model.addPropertyChangeListener(
         new PropertyChangeListener() {
           public void propertyChange(PropertyChangeEvent evt) {
  -          logger.warn(evt.toString());
  +          System.out.println(evt);
           }
         });
       panel.setOkCancelActionListener(
  
  
  
  1.26      +74 -107   
logging-log4j/src/java/org/apache/log4j/chainsaw/ChainsawAppenderHandler.java
  
  Index: ChainsawAppenderHandler.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/chainsaw/ChainsawAppenderHandler.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- ChainsawAppenderHandler.java      1 Dec 2004 07:58:07 -0000       1.25
  +++ ChainsawAppenderHandler.java      5 Dec 2004 10:17:36 -0000       1.26
  @@ -13,7 +13,6 @@
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
  -
   package org.apache.log4j.chainsaw;
   
   import java.beans.PropertyChangeListener;
  @@ -23,12 +22,9 @@
   import java.util.Iterator;
   import java.util.List;
   import java.util.Map;
  -
   import javax.swing.event.EventListenerList;
  -
   import org.apache.log4j.AppenderSkeleton;
   import org.apache.log4j.LogManager;
  -import org.apache.log4j.Logger;
   import org.apache.log4j.helpers.Constants;
   import org.apache.log4j.net.SocketReceiver;
   import org.apache.log4j.rule.ExpressionRule;
  @@ -36,15 +32,14 @@
   import org.apache.log4j.spi.LoggingEvent;
   import org.apache.log4j.spi.LoggingEventFieldResolver;
   
  -
   /**
  - * A handler class that either extends a particular appender hierarchy or 
can be bound
  - * into the Log4j appender framework, and queues events, to be later
  + * A handler class that either extends a particular appender hierarchy or 
can be
  + * bound into the Log4j appender framework, and queues events, to be later
    * dispatched to registered/interested parties.
  - *
  + * 
    * @author Scott Deboy <[EMAIL PROTECTED]>
    * @author Paul Smith <[EMAIL PROTECTED]>
  - *
  + * 
    */
   public class ChainsawAppenderHandler extends AppenderSkeleton {
     private static final String DEFAULT_IDENTIFIER = "Unknown";
  @@ -54,12 +49,11 @@
     private EventListenerList listenerList = new EventListenerList();
     private double dataRate = 0.0;
     private String identifierExpression;
  -  private final LoggingEventFieldResolver resolver =
  -    LoggingEventFieldResolver.getInstance();
  -  private PropertyChangeSupport propertySupport =
  -    new PropertyChangeSupport(this);
  +  private final LoggingEventFieldResolver resolver = 
LoggingEventFieldResolver
  +      .getInstance();
  +  private PropertyChangeSupport propertySupport = new PropertyChangeSupport(
  +      this);
     private Map customExpressionRules = new HashMap();
  -  private static final Logger logger = 
LogManager.getLogger(ChainsawAppenderHandler.class);
   
     public ChainsawAppenderHandler(ChainsawAppender appender) {
       appender.setAppender(this);
  @@ -81,8 +75,8 @@
       return identifierExpression;
     }
   
  -  public void addCustomEventBatchListener(
  -    String identifier, EventBatchListener l) throws IllegalArgumentException 
{
  +  public void addCustomEventBatchListener(String identifier,
  +      EventBatchListener l) throws IllegalArgumentException {
       customExpressionRules.put(identifier, 
ExpressionRule.getRule(identifier));
       listenerList.add(EventBatchListener.class, l);
     }
  @@ -99,8 +93,7 @@
       worker.enqueue(event);
     }
   
  -  public void close() {
  -  }
  +  public void close() {}
   
     public void activateOptions() {
       worker = new WorkQueue();
  @@ -119,39 +112,34 @@
     }
   
     /**
  -   * Determines an appropriate title for the Tab for the Tab Pane
  -   * by locating a the hostname property
  +   * Determines an appropriate title for the Tab for the Tab Pane by 
locating a
  +   * the hostname property
  +   * 
      * @param event
      * @return identifier
      */
     String getTabIdentifier(LoggingEvent e) {
       String ident = resolver.applyFields(identifierExpression, e);
  -
       return ((ident != null) ? ident : DEFAULT_IDENTIFIER);
     }
   
     /**
      * A little test bed
  +   * 
      * @param args
      */
     public static void main(String[] args) throws InterruptedException {
       ChainsawAppenderHandler handler = new ChainsawAppenderHandler();
  -    handler.addEventBatchListener(
  -      new EventBatchListener() {
  -        public String getInterestedIdentifier() {
  -          return null;
  -        }
  +    handler.addEventBatchListener(new EventBatchListener() {
  +      public String getInterestedIdentifier() {
  +        return null;
  +      }
   
  -        public void receiveEventBatch(
  -          String identifier, List events) {
  -          logger.debug(
  -            "received batch for '" + identifier + "', list.size()="
  -            + events.size());
  -          logger.debug(events.toString());
  -        }
  -      });
  +      public void receiveEventBatch(String identifier, List events) {
  +        System.out.println("received " + events.size());
  +      }
  +    });
       LogManager.getRootLogger().addAppender(handler);
  -
       SocketReceiver receiver = new SocketReceiver(4445);
       LogManager.getLoggerRepository().getPluginRegistry().addPlugin(receiver);
       receiver.activateOptions();
  @@ -159,12 +147,13 @@
     }
   
     /**
  -   * Exposes the current Data rate calculated.  This is periodically updated
  -   * by an internal Thread as is the number of events that have
  -   * been processed, and dispatched to all listeners since the last sample 
period
  -   * divided by the number of seconds since the last sample period.
  -   *
  +   * Exposes the current Data rate calculated. This is periodically updated 
by
  +   * an internal Thread as is the number of events that have been processed, 
and
  +   * dispatched to all listeners since the last sample period divided by the
  +   * number of seconds since the last sample period.
  +   * 
      * This method fires a PropertyChange event so listeners can monitor the 
rate
  +   * 
      * @return double # of events processed per second
      */
     public double getDataRate() {
  @@ -177,15 +166,15 @@
     void setDataRate(double dataRate) {
       double oldValue = this.dataRate;
       this.dataRate = dataRate;
  -    propertySupport.firePropertyChange(
  -      "dataRate", new Double(oldValue), new Double(this.dataRate));
  +    propertySupport.firePropertyChange("dataRate", new Double(oldValue),
  +        new Double(this.dataRate));
     }
   
     /**
      * @param listener
      */
     public synchronized void addPropertyChangeListener(
  -    PropertyChangeListener listener) {
  +      PropertyChangeListener listener) {
       propertySupport.addPropertyChangeListener(listener);
     }
   
  @@ -193,8 +182,8 @@
      * @param propertyName
      * @param listener
      */
  -  public synchronized void addPropertyChangeListener(
  -    String propertyName, PropertyChangeListener listener) {
  +  public synchronized void addPropertyChangeListener(String propertyName,
  +      PropertyChangeListener listener) {
       propertySupport.addPropertyChangeListener(propertyName, listener);
     }
   
  @@ -202,7 +191,7 @@
      * @param listener
      */
     public synchronized void removePropertyChangeListener(
  -    PropertyChangeListener listener) {
  +      PropertyChangeListener listener) {
       propertySupport.removePropertyChangeListener(listener);
     }
   
  @@ -210,15 +199,15 @@
      * @param propertyName
      * @param listener
      */
  -  public synchronized void removePropertyChangeListener(
  -    String propertyName, PropertyChangeListener listener) {
  +  public synchronized void removePropertyChangeListener(String propertyName,
  +      PropertyChangeListener listener) {
       propertySupport.removePropertyChangeListener(propertyName, listener);
     }
   
     /**
  -   * Queue of Events are placed in here, which are picked up by an
  -   * asychronous thread.  The WorkerThread looks for events once a second and
  -   * processes all events accumulated during that time..
  +   * Queue of Events are placed in here, which are picked up by an 
asychronous
  +   * thread. The WorkerThread looks for events once a second and processes 
all
  +   * events accumulated during that time..
      */
     class WorkQueue {
       final ArrayList queue = new ArrayList();
  @@ -243,8 +232,8 @@
       }
   
       /**
  -     * The worker thread converts each queued event
  -     * to a vector and forwards the vector on to the UI.
  +     * The worker thread converts each queued event to a vector and forwards 
the
  +     * vector on to the UI.
        */
       private class WorkerThread extends Thread {
         public WorkerThread() {
  @@ -254,81 +243,65 @@
   
         public void run() {
           List innerList = new ArrayList();
  -
           while (true) {
             long timeStart = System.currentTimeMillis();
  -
             synchronized (mutex) {
               try {
                 while ((queue.size() == 0) || (identifierExpression == null)) {
                   setDataRate(0);
                   mutex.wait();
                 }
  -
                 if (queue.size() > 0) {
                   innerList.addAll(queue);
                   queue.clear();
                 }
  -            } catch (InterruptedException ie) {
               }
  +            catch (InterruptedException ie) {}
             }
  -
             int size = innerList.size();
  -
             if (size > 0) {
               Iterator iter = innerList.iterator();
               ChainsawEventBatch eventBatch = new ChainsawEventBatch();
  -
               while (iter.hasNext()) {
                 LoggingEvent e = (LoggingEvent) iter.next();
  -              //attempt to set the host name (without port), from 
remoteSourceInfo
  -              //if 'hostname' property not provided
  +              // attempt to set the host name (without port), from
  +              // remoteSourceInfo
  +              // if 'hostname' property not provided
                 if (e.getProperty(Constants.HOSTNAME_KEY) == null) {
  -                             String remoteHost =
  -                             
e.getProperty(ChainsawConstants.LOG4J_REMOTEHOST_KEY);
  -                             
  -                             if (remoteHost != null) {
  -                                     int colonIndex = 
remoteHost.indexOf(":");
  -                             if (colonIndex == -1) {
  -                             colonIndex = remoteHost.length();
  -                             }
  -                             
  -                             e.setProperty(Constants.HOSTNAME_KEY, 
remoteHost.substring(0, colonIndex));
  -                     }               
  +                String remoteHost = e
  +                    .getProperty(ChainsawConstants.LOG4J_REMOTEHOST_KEY);
  +                if (remoteHost != null) {
  +                  int colonIndex = remoteHost.indexOf(":");
  +                  if (colonIndex == -1) {
  +                    colonIndex = remoteHost.length();
  +                  }
  +                  e.setProperty(Constants.HOSTNAME_KEY, 
remoteHost.substring(0,
  +                      colonIndex));
  +                }
                 }
  -
  -              for (
  -                Iterator itery = customExpressionRules.entrySet().iterator();
  -                  itery.hasNext();) {
  +              for (Iterator itery = 
customExpressionRules.entrySet().iterator(); itery
  +                  .hasNext();) {
                   Map.Entry entry = (Map.Entry) itery.next();
                   Rule rule = (Rule) entry.getValue();
  -
                   if (rule.evaluate(e)) {
  -                  eventBatch.addEvent(
  -                    (String) entry.getKey(), e);
  +                  eventBatch.addEvent((String) entry.getKey(), e);
                   }
                 }
  -
  -              eventBatch.addEvent(
  -                getTabIdentifier(e), e);
  +              eventBatch.addEvent(getTabIdentifier(e), e);
               }
  -
               dispatchEventBatch(eventBatch);
  -
               innerList.clear();
             }
  -
             if (getQueueInterval() > 1000) {
  -               try {
  -                 synchronized (this) {
  -                   wait(getQueueInterval());
  -                 }
  -               } catch (InterruptedException ie) {
  -               }
  +            try {
  +              synchronized (this) {
  +                wait(getQueueInterval());
  +              }
  +            }
  +            catch (InterruptedException ie) {}
             } else {
  -             Thread.yield();
  +            Thread.yield();
             }
  -
             if (size == 0) {
               setDataRate(0.0);
             } else {
  @@ -341,34 +314,28 @@
         }
   
         /**
  -      * Dispatches the event batches contents to all the interested parties
  -      * by iterating over each identifier and dispatching the
  -      * ChainsawEventBatchEntry object to each listener that is interested.
  +       * Dispatches the event batches contents to all the interested parties 
by
  +       * iterating over each identifier and dispatching the
  +       * ChainsawEventBatchEntry object to each listener that is interested.
  +       * 
          * @param eventBatch
          */
         private void dispatchEventBatch(ChainsawEventBatch eventBatch) {
  -        EventBatchListener[] listeners =
  -          (EventBatchListener[]) listenerList.getListeners(
  -            EventBatchListener.class);
  -
  +        EventBatchListener[] listeners = (EventBatchListener[]) listenerList
  +            .getListeners(EventBatchListener.class);
           for (Iterator iter = eventBatch.identifierIterator(); 
iter.hasNext();) {
             String identifier = (String) iter.next();
             List eventList = null;
  -
             for (int i = 0; i < listeners.length; i++) {
               EventBatchListener listener = listeners[i];
  -
  -            if (
  -              (listener.getInterestedIdentifier() == null)
  +            if ((listener.getInterestedIdentifier() == null)
                   || listener.getInterestedIdentifier().equals(identifier)) {
                 if (eventList == null) {
                   eventList = eventBatch.entrySet(identifier);
                 }
  -
                 listener.receiveEventBatch(identifier, eventList);
               }
             }
  -
             eventList = null;
           }
         }
  
  
  
  1.1                  
logging-log4j/src/java/org/apache/log4j/db/CustomSQLDBReceiver.java
  
  Index: CustomSQLDBReceiver.java
  ===================================================================
  /*
   * Copyright 1999,2004 The Apache Software Foundation.
   * 
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.apache.log4j.db;
  
  import java.sql.Connection;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.sql.Statement;
  import java.util.Hashtable;
  import java.util.StringTokenizer;
  
  import org.apache.log4j.Level;
  import org.apache.log4j.LogManager;
  import org.apache.log4j.Logger;
  import org.apache.log4j.plugins.Pauseable;
  import org.apache.log4j.plugins.Receiver;
  import org.apache.log4j.scheduler.Job;
  import org.apache.log4j.scheduler.Scheduler;
  import org.apache.log4j.spi.LoggingEvent;
  import org.apache.log4j.spi.ThrowableInformation;
  import org.apache.log4j.spi.location.LocationInfo;
  
  /**
   * Converts log data stored in a database into LoggingEvents.
   * <p>
   * <b>NOTE:</b> This receiver cannot yet be created through Chainsaw's 
receiver panel.  
   * It must be created through an XML configuration file.
   * <p>
   * This receiver supports database configuration via ConnectionSource, in the
   * org.apache.log4j.db package: DriverManagerConnectionSource,
   * DataSourceConnectionSource, JNDIConnectionSource
   * <p>
   * This database receiver differs from DBReceiver in that this receiver relies
   * on custom SQL to retrieve logging event data, where DBReceiver requires the
   * use of a log4j-defined schema.
   * <p>
   * A 'refreshMillis' int parameter controls SQL execution. If 'refreshMillis' 
is
   * zero (the default), the receiver will run only one time. If it is set to 
any
   * other numeric value, the SQL will be executed on a recurring basis every
   * 'refreshMillis' milliseconds.
   * <p>
   * The receiver closes the connection and acquires a new connection on each 
   * execution of the SQL (use pooled connections if possible).
   * <p>
   * If the SQL will be executing on a recurring basis, specify the IDField 
param -
   * the column name holding the unique identifier (int) representing the 
logging
   * event.
   * <p>
   * As events are retrieved, the column represented by IDField is examined and
   * the largest value is held and used by the next execution of the SQL 
statement
   * to avoid retrieving previously processed events.
   * <p>
   * As an example, the IDField references a 'COUNTER' (int, auto-increment,
   * unique) column. The first execution of the SQL statement returns 500 rows,
   * with a final value in the COUNTER field of 500.
   * <p>
   * The SQL statement is manipulated prior to the next execution, adding ' 
WHERE
   * COUNTER > 500' to the statement to avoid retrieval of previously processed
   * events.
   * <p>
   * The select statement must provide ALL fields which define a LoggingEvent.
   * <p>
   * The SQL statement MUST include the columns: LOGGER, TIMESTAMP, LEVEL, 
THREAD,
   * MESSAGE, NDC, MDC, CLASS, METHOD, FILE, LINE, PROPERTIES, EXCEPTION
   * <p>
   * Use ' AS ' in the SQL statement to alias the SQL's column names to match 
your
   * database schema. (see example below).
   * <p>
   * Include all fields in the SQL statement, even if you don't have data for 
the
   * field (specify an empty string as the value for columns which you don't 
have
   * data).
   * <p>
   * The TIMESTAMP column must be a datetime.
   * <p>
   * Both a PROPERTIES column and an MDC column are supported. These fields
   * represent Maps on the logging event, but require the use of string
   * concatenation database functions to hold the (possibly multiple) name/value
   * pairs in the column.
   * <p>
   * For example, to include both 'userid' and 'lastname' properties in the
   * logging event (from either the PROPERTIES or MDC columns), the name/value
   * pairs must be concatenated together by your database.
   * <p>
   * The resulting PROPERTIES or MDC column must have data in this format: 
{{name,
   * value, name2, value2}}
   * <p>
   * The resulting PROPERTIES column would contain this text: {{userid, someone,
   * lastname, mylastname}}
   * <p>
   * Here is an example of concatenating a PROPERTIES or MDC column using 
MySQL's
   * concat function, where the 'application' and 'hostname' parameters were 
fixed
   * text, but the 'log4jid' key's value is the value of the COUNTER column:
   * <p>
   * concat("{{application,databaselogs,hostname,mymachine,log4jid,", COUNTER,
   * "}}") as PROPERTIES
   * <p>
   * log4jid is a special property that is used by Chainsaw to represent an 'ID'
   * field. Specify this property to ensure you can map events in Chainsaw to
   * events in the database if you need to go back and view events at a later 
time
   * or save the events to XML for later analysis.
   * <p>
   * Here is a complete MySQL SQL statement which can be used to provide events 
to
   * Chainsaw:
   * <p>
   * select logger as LOGGER, timestamp as TIMESTAMP, level as LEVEL, thread as
   * THREAD, message as MESSAGE, ndc as NDC, mdc as MDC, class as CLASS, method 
as
   * METHOD, file as FILE, line as LINE,
   * concat("{{application,databaselogs,hostname,mymachine, log4jid,",
   * COUNTER,"}}") as PROPERTIES, "" as EXCEPTION from logtable
   * <p>
   * @author Scott Deboy <[EMAIL PROTECTED]>
   * <p>
   */
  public class CustomSQLDBReceiver extends Receiver implements Pauseable {
  
      protected volatile Connection connection = null;
  
      protected String sqlStatement = "";
  
      /**
       * By default we refresh data every 1000 milliseconds.
       * 
       * @see #setRefreshMillis
       */
      static int DEFAULT_REFRESH_MILLIS = 1000;
  
      int refreshMillis = DEFAULT_REFRESH_MILLIS;
  
      protected String idField = null;
  
      int lastID = -1;
  
      private static final String WHERE_CLAUSE = " WHERE ";
  
      private static final String AND_CLAUSE = " AND ";
  
      private boolean whereExists = false;
  
      private boolean paused = false;
  
      private ConnectionSource connectionSource;
  
      public static final String LOG4J_ID_KEY = "log4jid";
  
      private Thread receiverThread;
  
      private Job customReceiverJob;
  
      public void activateOptions() {
          if (connectionSource != null) {
              customReceiverJob = new CustomReceiverJob();
  
              Scheduler scheduler = LogManager.getSchedulerInstance();
              if (refreshMillis > 0) {
                  scheduler.schedule(customReceiverJob, System
                          .currentTimeMillis() + 500, refreshMillis);
              } else {
                  scheduler.schedule(customReceiverJob, System
                          .currentTimeMillis() + 500);
              }
          } else {
              throw new IllegalStateException(
                      "CustomSQLDBReceiver cannot function without a connection 
source");
          }
      }
  
      void closeConnection(Connection connection) {
          if (connection != null) {
              try {
                  // LogLog.warn("closing the connection. ", new 
Exception("x"));
                  connection.close();
              } catch (SQLException sqle) {
                  // nothing we can do here
              }
          }
      }
  
      public void setRefreshMillis(int refreshMillis) {
          this.refreshMillis = refreshMillis;
      }
  
      public int getRefreshMillis() {
          return refreshMillis;
      }
  
      /**
       * @return Returns the connectionSource.
       */
      public ConnectionSource getConnectionSource() {
          return connectionSource;
      }
  
      /**
       * @param connectionSource
       *            The connectionSource to set.
       */
      public void setConnectionSource(ConnectionSource connectionSource) {
          this.connectionSource = connectionSource;
      }
  
      public void close() {
          try {
              if ((connection != null) && !connection.isClosed()) {
                  connection.close();
              }
          } catch (SQLException e) {
              e.printStackTrace();
          } finally {
              connection = null;
          }
      }
  
      public void finalize() {
          close();
      }
  
      /*
       * (non-Javadoc)
       * 
       * @see org.apache.log4j.plugins.Plugin#shutdown()
       */
      public void shutdown() {
          getLogger().info("removing receiverJob from the Scheduler.");
  
          Scheduler scheduler = LogManager.getSchedulerInstance();
          scheduler.delete(customReceiverJob);
          lastID = -1;
      }
  
      public void setSql(String s) {
          sqlStatement = s;
      }
  
      public String getSql() {
          return sqlStatement;
      }
  
      public void setIDField(String id) {
          idField = id;
      }
  
      public String getIDField() {
          return idField;
      }
  
      public synchronized void setPaused(boolean p) {
          paused = p;
      }
  
      public synchronized boolean isPaused() {
          return paused;
      }
  
      class CustomReceiverJob implements Job {
          public void execute() {
              Connection connection = null;
  
              int oldLastID = lastID;
              try {
                  connection = connectionSource.getConnection();
                  Statement statement = connection.createStatement();
  
                  Logger eventLogger = null;
                  long timeStamp = 0L;
                  String level = null;
                  String threadName = null;
                  Object message = null;
                  String ndc = null;
                  Hashtable mdc = null;
                  String[] exception = null;
                  String className = null;
                  String methodName = null;
                  String fileName = null;
                  String lineNumber = null;
                  Hashtable properties = null;
  
                  String currentSQLStatement = sqlStatement;
                  if (whereExists) {
                      currentSQLStatement = sqlStatement + AND_CLAUSE + idField
                              + " > " + lastID;
                  } else {
                      currentSQLStatement = sqlStatement + WHERE_CLAUSE + 
idField
                              + " > " + lastID;
                  }
  
                  ResultSet rs = statement.executeQuery(currentSQLStatement);
  
                  int i = 0;
                  while (rs.next()) {
                      // add a small break every 1000 received events
                      if (++i == 1000) {
                          synchronized (this) {
                              try {
                                  // add a delay
                                  wait(300);
                              } catch (InterruptedException ie) {
                              }
                              i = 0;
                          }
                      }
                      eventLogger = Logger.getLogger(rs.getString("LOGGER"));
                      timeStamp = rs.getTimestamp("TIMESTAMP").getTime();
  
                      level = rs.getString("LEVEL");
                      threadName = rs.getString("THREAD");
                      message = rs.getString("MESSAGE");
                      ndc = rs.getString("NDC");
  
                      String mdcString = rs.getString("MDC");
                      mdc = new Hashtable();
  
                      if (mdcString != null) {
                          // support MDC being wrapped in {{name, value}}
                          // or
                          // just name, value
                          if ((mdcString.indexOf("{{") > -1)
                                  && (mdcString.indexOf("}}") > -1)) {
                              mdcString = mdcString
                                      .substring(mdcString.indexOf("{{") + 2,
                                              mdcString.indexOf("}}"));
                          }
  
                          StringTokenizer tok = new StringTokenizer(mdcString,
                                  ",");
  
                          while (tok.countTokens() > 1) {
                              mdc.put(tok.nextToken(), tok.nextToken());
                          }
                      }
  
                      exception = new String[] { rs.getString("EXCEPTION") };
                      className = rs.getString("CLASS");
                      methodName = rs.getString("METHOD");
                      fileName = rs.getString("FILE");
                      lineNumber = rs.getString("LINE");
  
                      // if properties are provided in the
                      // SQL they can be used here (for example, to route
                      // events to a unique tab in
                      // Chainsaw if the machinename and/or appname
                      // property
                      // are set)
                      String propertiesString = rs.getString("PROPERTIES");
                      properties = new Hashtable();
  
                      if (propertiesString != null) {
                          // support properties being wrapped in {{name,
                          // value}} or just name, value
                          if ((propertiesString.indexOf("{{") > -1)
                                  && (propertiesString.indexOf("}}") > -1)) {
                              propertiesString = propertiesString.substring(
                                      propertiesString.indexOf("{{") + 2,
                                      propertiesString.indexOf("}}"));
                          }
  
                          StringTokenizer tok2 = new StringTokenizer(
                                  propertiesString, ",");
                          while (tok2.countTokens() > 1) {
                              String name = tok2.nextToken();
                              String value = tok2.nextToken();
                              if (name.equals(LOG4J_ID_KEY)) {
                                  try {
                                      int thisInt = Integer.parseInt(value);
                                      value = String.valueOf(thisInt);
                                      if (thisInt > lastID) {
                                          lastID = thisInt;
                                      }
                                  } catch (Exception e) {
                                  }
                              }
                              properties.put(name, value);
                          }
                      }
  
                      Level levelImpl = Level.toLevel(level);
                      LoggingEvent event = new LoggingEvent(
                              eventLogger.getName(), eventLogger, levelImpl,
                              message, null);
                      event.setLocationInformation(new LocationInfo(fileName,
                              className, methodName, lineNumber));
                      properties.putAll(mdc);
                      event.setTimeStamp(timeStamp);
                      event.setThrowableInformation(new ThrowableInformation(
                              exception));
  
                      event.setProperties(properties);
                      event.setThreadName(threadName);
                      event.setNDC(ndc);
                      doPost(event);
                  }
                  //log when rows are retrieved
                  if (lastID != oldLastID) {
                      getLogger().debug("lastID: " + lastID);
                      oldLastID = lastID;
                  }
  
                  statement.close();
                  statement = null;
              } catch (SQLException sqle) {
                  getLogger()
                          .error("*************Problem receiving events", sqle);
              } finally {
                  closeConnection(connection);
              }
  
              // if paused, loop prior to executing sql query
              synchronized (this) {
                  while (isPaused()) {
                      try {
                          wait(1000);
                      } catch (InterruptedException ie) {
                      }
                  }
              }
          }
      }
  }
  
  
  
  1.47      +7 -0      
logging-log4j/src/java/org/apache/log4j/chainsaw/help/release-notes.html
  
  Index: release-notes.html
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/chainsaw/help/release-notes.html,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- release-notes.html        1 Dec 2004 16:53:39 -0000       1.46
  +++ release-notes.html        5 Dec 2004 10:17:36 -0000       1.47
  @@ -9,6 +9,13 @@
   
   <h1>1.99.99</h2>
   
  +<h2>5 December 2004</h2>
  +<ul>
  +<li>Added CustomSQLDBReceiver example to log4j-receiver-sample config file, 
Javadoc help menu and receiver panel.</li>
  +<li><b>NOTE:</b> CustomSQLDBReceiver cannot yet be created through 
Chainsaw's receiver panel.  It must be created through an XML configuration 
file.</li>
  +<li>Improved Chainsaw logging framework initialization logic to ensure 
receivers are started only after Chainsaw can process the events</li>
  +</ul>
  +
   <h2>1 December 2004</h2>
   <ul>
   <li>TRACE level now fully supported in Chainsaw</li>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to