View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.log4j.lf5.util;
    18
    19  import org.apache.log4j.lf5.Log4JLogRecord;
    20  import org.apache.log4j.lf5.LogLevel;
    21  import org.apache.log4j.lf5.LogLevelFormatException;
    22  import org.apache.log4j.lf5.LogRecord;
    23  import org.apache.log4j.lf5.viewer.LogBrokerMonitor;
    24  import org.apache.log4j.lf5.viewer.LogFactor5ErrorDialog;
    25  import org.apache.log4j.lf5.viewer.LogFactor5LoadingDialog;
    26
    27  import javax.swing.*;
    28  import java.io.*;
    29  import java.text.ParseException;
    30  import java.text.SimpleDateFormat;
    31  import java.util.Date;
    32
    33  /***
    34   * Provides utility methods for input and output streams.
    35   *
    36   * @author Brad Marlborough
    37   * @author Richard Hurst
    38   */
    39
    40  // Contributed by ThoughtWorks Inc.
    41
    42  public class LogFileParser implements Runnable {
    43    //--------------------------------------------------------------------------
    44    //   Constants:
    45    //--------------------------------------------------------------------------
    46    public static final String RECORD_DELIMITER = "[slf5s.start]";
    47    public static final String ATTRIBUTE_DELIMITER = "[slf5s.";
    48    public static final String DATE_DELIMITER = ATTRIBUTE_DELIMITER + "DATE]";
    49    public static final String THREAD_DELIMITER = ATTRIBUTE_DELIMITER + "THREAD]";
    50    public static final String CATEGORY_DELIMITER = ATTRIBUTE_DELIMITER + "CATEGORY]";
    51    public static final String LOCATION_DELIMITER = ATTRIBUTE_DELIMITER + "LOCATION]";
    52    public static final String MESSAGE_DELIMITER = ATTRIBUTE_DELIMITER + "MESSAGE]";
    53    public static final String PRIORITY_DELIMITER = ATTRIBUTE_DELIMITER + "PRIORITY]";
    54    public static final String NDC_DELIMITER = ATTRIBUTE_DELIMITER + "NDC]";
    55
    56    //--------------------------------------------------------------------------
    57    //   Protected Variables:
    58    //--------------------------------------------------------------------------
    59
    60    //--------------------------------------------------------------------------
    61    //   Private Variables:
    62    //--------------------------------------------------------------------------
    63    private static SimpleDateFormat _sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss,S");
    64    private LogBrokerMonitor _monitor;
    65    LogFactor5LoadingDialog _loadDialog;
    66    private InputStream _in = null;
    67
    68    //--------------------------------------------------------------------------
    69    //   Constructors:
    70    //--------------------------------------------------------------------------
    71    public LogFileParser(File file) throws IOException,
    72        FileNotFoundException {
    73      this(new FileInputStream(file));
    74    }
    75
    76    public LogFileParser(InputStream stream) throws IOException {
    77      _in = stream;
    78    }
    79    //--------------------------------------------------------------------------
    80    //   Public Methods:
    81    //--------------------------------------------------------------------------
    82
    83    /***
    84     * Starts a new thread to parse the log file and create a LogRecord.
    85     * See run().
    86     * @param monitor LogBrokerMonitor
    87     */
    88    public void parse(LogBrokerMonitor monitor) throws RuntimeException {
    89      _monitor = monitor;
    90      Thread t = new Thread(this);
    91      t.start();
    92    }
    93
    94    /***
    95     * Parses the file and creates new log records and adds the record
    96     * to the monitor.
    97     */
    98    public void run() {
    99
    100     int index = 0;
    101     int counter = 0;
    102     LogRecord temp;
    103     boolean isLogFile = false;
    104
    105     _loadDialog = new LogFactor5LoadingDialog(
    106         _monitor.getBaseFrame(), "Loading file...");
    107
    108
    109     try {
    110       String logRecords = loadLogFile(_in);
    111
    112       while ((counter = logRecords.indexOf(RECORD_DELIMITER, index)) != -1) {
    113         temp = createLogRecord(logRecords.substring(index, counter));
    114         isLogFile = true;
    115
    116         if (temp != null) {
    117           _monitor.addMessage(temp);
    118         }
    119
    120         index = counter + RECORD_DELIMITER.length();
    121       }
    122
    123       if (index < logRecords.length() && isLogFile) {
    124         temp = createLogRecord(logRecords.substring(index));
    125
    126         if (temp != null) {
    127           _monitor.addMessage(temp);
    128         }
    129       }
    130
    131       if (isLogFile == false) {
    132         throw new RuntimeException("Invalid log file format");
    133       }
    134       SwingUtilities.invokeLater(new Runnable() {
    135         public void run() {
    136           destroyDialog();
    137         }
    138       });
    139
    140     } catch (RuntimeException e) {
    141       destroyDialog();
    142       displayError("Error - Invalid log file format.\nPlease see documentation"
    143           + " on how to load log files.");
    144     } catch (IOException e) {
    145       destroyDialog();
    146       displayError("Error - Unable to load log file!");
    147     }
    148
    149     _in = null;
    150   }
    151
    152   //--------------------------------------------------------------------------
    153   //   Protected Methods:
    154   //--------------------------------------------------------------------------
    155   protected void displayError(String message) {
    156     LogFactor5ErrorDialog error = new LogFactor5ErrorDialog(
    157         _monitor.getBaseFrame(), message);
    158
    159   }
    160
    161   //--------------------------------------------------------------------------
    162   //   Private Methods:
    163   //--------------------------------------------------------------------------
    164   private void destroyDialog() {
    165     _loadDialog.hide();
    166     _loadDialog.dispose();
    167   }
    168
    169   /***
    170    * Loads a log file from a web server into the LogFactor5 GUI.
    171    */
    172   private String loadLogFile(InputStream stream) throws IOException {
    173     BufferedInputStream br = new BufferedInputStream(stream);
    174
    175     int count = 0;
    176     int size = br.available();
    177
    178     StringBuffer sb = null;
    179     if (size > 0) {
    180       sb = new StringBuffer(size);
    181     } else {
    182       sb = new StringBuffer(1024);
    183     }
    184
    185     while ((count = br.read()) != -1) {
    186       sb.append((char) count);
    187     }
    188
    189     br.close();
    190     br = null;
    191     return sb.toString();
    192
    193   }
    194
    195   private String parseAttribute(String name, String record) {
    196
    197     int index = record.indexOf(name);
    198
    199     if (index == -1) {
    200       return null;
    201     }
    202
    203     return getAttribute(index, record);
    204   }
    205
    206   private long parseDate(String record) {
    207     try {
    208       String s = parseAttribute(DATE_DELIMITER, record);
    209
    210       if (s == null) {
    211         return 0;
    212       }
    213
    214       Date d = _sdf.parse(s);
    215
    216       return d.getTime();
    217     } catch (ParseException e) {
    218       return 0;
    219     }
    220   }
    221
    222   private LogLevel parsePriority(String record) {
    223     String temp = parseAttribute(PRIORITY_DELIMITER, record);
    224
    225     if (temp != null) {
    226       try {
    227         return LogLevel.valueOf(temp);
    228       } catch (LogLevelFormatException e) {
    229         return LogLevel.DEBUG;
    230       }
    231
    232     }
    233
    234     return LogLevel.DEBUG;
    235   }
    236
    237   private String parseThread(String record) {
    238     return parseAttribute(THREAD_DELIMITER, record);
    239   }
    240
    241   private String parseCategory(String record) {
    242     return parseAttribute(CATEGORY_DELIMITER, record);
    243   }
    244
    245   private String parseLocation(String record) {
    246     return parseAttribute(LOCATION_DELIMITER, record);
    247   }
    248
    249   private String parseMessage(String record) {
    250     return parseAttribute(MESSAGE_DELIMITER, record);
    251   }
    252
    253   private String parseNDC(String record) {
    254     return parseAttribute(NDC_DELIMITER, record);
    255   }
    256
    257   private String parseThrowable(String record) {
    258     return getAttribute(record.length(), record);
    259   }
    260
    261   private LogRecord createLogRecord(String record) {
    262     if (record == null || record.trim().length() == 0) {
    263       return null;
    264     }
    265
    266     LogRecord lr = new Log4JLogRecord();
    267     lr.setMillis(parseDate(record));
    268     lr.setLevel(parsePriority(record));
    269     lr.setCategory(parseCategory(record));
    270     lr.setLocation(parseLocation(record));
    271     lr.setThreadDescription(parseThread(record));
    272     lr.setNDC(parseNDC(record));
    273     lr.setMessage(parseMessage(record));
    274     lr.setThrownStackTrace(parseThrowable(record));
    275
    276     return lr;
    277   }
    278
    279
    280   private String getAttribute(int index, String record) {
    281     int start = record.lastIndexOf(ATTRIBUTE_DELIMITER, index - 1);
    282
    283     if (start == -1) {
    284       return record.substring(0, index);
    285     }
    286
    287     start = record.indexOf("]", start);
    288
    289     return record.substring(start + 1, index).trim();
    290   }
    291   //--------------------------------------------------------------------------
    292   //   Nested Top-Level Classes or Interfaces
    293   //--------------------------------------------------------------------------
    294
    295 }