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