View Javadoc
1   package net.logAnalyzer.handlers;
2   
3   import java.util.Vector;
4   
5   import net.logAnalyzer.analysis.LAAnalyzer;
6   import net.logAnalyzer.converters.LAConverter;
7   import net.logAnalyzer.converters.UnknownOrLiteralConverterException;
8   import net.logAnalyzer.gui.messages.filters.LAMessagesFilter;
9   
10  /***
11   * This class implents a filtering log handler under another log handler. For
12   * example, the underlaying log handler can be a
13   * {@link net.logAnalyzer.handlers.OnDemandLogHandler}parsing one or more log
14   * files, and the filtered log handler applies filters to accept or not each
15   * messageLabel of the underlaying log handler.
16   * 
17   * @author Karim REFEYTON
18   * @version 0.1
19   */
20  public class FilteredLogHandler implements LALogHandler {
21  
22      /***
23       * Filter to apply.
24       */
25      private LAMessagesFilter filter;
26  
27      /***
28       * Last exception thrown by the parsing or analysis processes.
29       */
30      private Exception lastException = null;
31  
32      /***
33       * Filtered log handler.
34       */
35      private LALogHandler logHandler;
36  
37      /***
38       * Number of records to parse; <tt>0</tt> for no limitation.
39       */
40      private int maxRecords = 0;
41  
42      /***
43       * <tt>true</tt> if the handler is currently parsing the log.
44       */
45      private boolean parsing = false;
46  
47      /***
48       * Real index of underlaying log handler messages.
49       */
50      private Vector realIndex;
51  
52      /***
53       * Creates a log handler by filtering the specified log handler.
54       * 
55       * @param loghandler
56       *            Log handler to filter.
57       */
58      public FilteredLogHandler(LALogHandler loghandler) {
59          if (loghandler == null) {
60              throw new NullPointerException("Handler must not be null");
61          }
62          this.logHandler = loghandler;
63      }
64  
65      /***
66       * Returns the applied filter.
67       * 
68       * @return Applied filter.
69       */
70      public LAMessagesFilter getFilter() {
71          return this.filter;
72      }
73  
74      /***
75       * Sets the filter used to accept or not the messages of the underlaying
76       * filter.
77       * 
78       * @param filter
79       *            Filter to apply.
80       */
81      public void setFilter(LAMessagesFilter filter) {
82          this.filter = filter;
83      }
84  
85      /***
86       * Returns the real index associated to the specified filtered index. No
87       * change if no filter apply.
88       * 
89       * @param filteredIndex
90       *            Filterer index.
91       * @return Real index of the messageLabel in the real log handler.
92       */
93      public int getRealIndex(int filteredIndex) {
94          if (realIndex == null) {
95              return filteredIndex;
96          } else if (filteredIndex < realIndex.size()) {
97              return ((Integer) realIndex.get(filteredIndex)).intValue();
98          } else if (realIndex.size() > 0) {
99              return ((Integer) realIndex.get(realIndex.size() - 1)).intValue();
100         } else {
101             return 0;
102         }
103     }
104 
105     /***
106      * Delegated method.
107      * 
108      * @see net.logAnalyzer.handlers.LALogHandler#getAnalyzers()
109      */
110     public LAAnalyzer[] getAnalyzers() {
111         return logHandler.getAnalyzers();
112     }
113 
114     /***
115      * Delegated method.
116      * 
117      * @see net.logAnalyzer.handlers.LALogHandler#getConverter(int)
118      */
119     public LAConverter getConverter(int index) {
120         return logHandler.getConverter(index);
121     }
122 
123     /***
124      * Delegated method.
125      * 
126      * @see net.logAnalyzer.handlers.LALogHandler#getConverter(java.lang.String)
127      */
128     public LAConverter getConverter(String literal)
129             throws UnknownOrLiteralConverterException {
130         return logHandler.getConverter(literal);
131     }
132 
133     /***
134      * Delegated method.
135      * 
136      * @see net.logAnalyzer.handlers.LALogHandler#getConverterIndex(java.lang.String)
137      */
138     public int getConverterIndex(String literal)
139             throws UnknownOrLiteralConverterException {
140         return logHandler.getConverterIndex(literal);
141     }
142 
143     /***
144      * Delegated method.
145      * 
146      * @see net.logAnalyzer.handlers.LALogHandler#getConverters()
147      */
148     public LAConverter[] getConverters() {
149         return logHandler.getConverters();
150     }
151 
152     /***
153      * Delegated method.
154      * 
155      * @see net.logAnalyzer.handlers.LALogHandler#getLastException()
156      */
157     public Exception getLastException() {
158         return lastException;
159     }
160 
161     /***
162      * Delegated method.
163      * 
164      * @see net.logAnalyzer.handlers.LALogHandler#getMaxRecords()
165      */
166     public int getMaxRecords() {
167         return maxRecords;
168     }
169 
170     /***
171      * Returns the current messageLabel converter used to extend messageLabel text with
172      * unparsed lines.
173      * 
174      * @return Message converter.
175      * @see #parse()
176      * @see LAMessage#extendsMessage(String)
177      */
178     public LAConverter getMessageConverter() {
179         return logHandler.getMessageConverter();
180     }
181 
182     /***
183      * Returns the messageLabel at the specified position after filtering.
184      * 
185      * @param index
186      *            Physical index of the messageLabel in the log file.
187      * @return Message.
188      */
189     public LAMessage getMessage(int index) {
190         return logHandler.getMessage(getRealIndex(index));
191     }
192 
193     /***
194      * Returns the filtered messages between specified filtered positions. Uses
195      * {@link #getMessage(int)}to read messageLabel from the log file.
196      * 
197      * @param start
198      *            start filtered index (included in the result).
199      * @param end
200      *            end filtered index (included in the result).
201      * @return messages.
202      * @see net.logAnalyzer.handlers.LALogHandler#getMessages(int, int)
203      */
204     public LAMessage[] getMessages(int start, int end) {
205         if (realIndex == null) {
206             return logHandler.getMessages(start, end);
207         } else {
208             if (end >= getSize()) {
209                 end = getSize() - 1;
210             }
211             LAMessage[] messages = new LAMessage[end - start + 1];
212             for (int i = start; i <= end; i++) {
213                 messages[i - start] = logHandler.getMessage(getRealIndex(i));
214             }
215             return messages;
216         }
217     }
218 
219     /***
220      * Delegated method.
221      * 
222      * @see net.logAnalyzer.handlers.LALogHandler#getPercentDone()
223      */
224     public int getPercentDone() {
225         int percentage = 0;
226         if (isParsing()) {
227             if (maxRecords != 0) {
228                 percentage = 100 * currentIndex / maxRecords;
229             } else {
230                 percentage = 100 * currentIndex / logHandler.getSize();
231             }
232             if (percentage > 100) {
233                 percentage = 100;
234             }
235         }
236         return percentage;
237     }
238 
239     /***
240      * Delegated method.
241      * 
242      * @see net.logAnalyzer.handlers.LALogHandler#getSize()
243      */
244     public int getSize() {
245         if (realIndex == null && filter == null) {
246             return logHandler.getSize();
247         } else if (realIndex == null && filter != null) {
248             return 0;
249         } else {
250             return realIndex.size();
251         }
252     }
253 
254     /***
255      * Delegated method.
256      * 
257      * @see net.logAnalyzer.handlers.LALogHandler#isParsing()
258      */
259     public boolean isParsing() {
260         return this.parsing;
261     }
262 
263     /***
264      * NOP.
265      * 
266      * @see net.logAnalyzer.handlers.LALogHandler#setAnalyzers(net.logAnalyzer.analysis.LAAnalyzer[])
267      */
268     public void setAnalyzers(LAAnalyzer[] newAnalyzers) {
269         // NOP
270     }
271 
272     /***
273      * Delegated method.
274      * 
275      * @see net.logAnalyzer.handlers.LALogHandler#setMaxRecords(int)
276      */
277     public void setMaxRecords(int maxRecords) {
278         logHandler.setMaxRecords(maxRecords);
279     }
280 
281     private int currentIndex = 0;
282 
283     /***
284      * Parses the log content of the current {@link LALogHandler}. Calls, in
285      * order :
286      * <ul>
287      * <li>{@link #fireStartParsing()}</li>
288      * <li>{@link LALogHandler#getMessage(int)}</li>
289      * <li>{@link LAMessagesFilter#accept(LAMessage)} on each
290      * {@link LAMessagesFilter} for each {@link LAMessage}</li>
291      * <li>{@link #fireStepParsing()}</li>
292      * <li>{@link #fireEndParsing()}</li>
293      * </ul>
294      * <p>
295      * Because a {@link LALogHandler} is a {@link Runnable}, for a threaded
296      * parsing you must start it in a new {@link Thread} :
297      * 
298      * <pre>
299      * handler.addLogHandlerListener(myLALogHandlerListener);
300      * Thread handlerThread = new Thread(handler);
301      * handlerThread.start();
302      * </pre>
303      * 
304      * </p>
305      * 
306      * @throws ParsingException
307      *             If can't parse messageLabel.
308      */
309     public void parse() throws ParsingException {
310         // Starts parsing
311         parsing = true;
312         fireStartParsing();
313 
314         realIndex = null;
315         if (filter != null) {
316             realIndex = new Vector();
317             int percents = 0;
318             int newPercents = 0;
319             for (currentIndex = 0; parsing
320                     && (maxRecords == 0 || currentIndex < maxRecords)
321                     && currentIndex < logHandler.getSize(); currentIndex++) {
322                 LAMessage message = logHandler.getMessage(currentIndex);
323                 newPercents = getPercentDone();
324                 if (newPercents - percents >= 1) {
325                     percents = newPercents;
326                     fireStepParsing();
327                 }
328                 // Checks if the messageLabel is accepted by the current filter
329                 if (filter.accept(message)) {
330                     // Message is accepted by all the filters
331                     realIndex.add(new Integer(currentIndex));
332                 }
333             }
334         }
335         // Ends parsing
336         parsing = false;
337         fireEndParsing();
338     }
339 
340     /***
341      * Delegated method.
342      * 
343      * @see java.lang.Runnable#run()
344      */
345     public void run() {
346         try {
347             parsing = true;
348             parse();
349         } catch (ParsingException e) {
350             lastException = e;
351         } finally {
352             parsing = false;
353         }
354     }
355 
356     /***
357      * Stop the filtering. A
358      * {@link LALogHandlerListener#endParsing(LALogHandler)} is received by all
359      * {@link LALogHandlerListener}.
360      */
361     public void stopFiltering() {
362         if (isParsing()) {
363             // Ends parsing
364             parsing = false;
365         }
366     }
367 
368     private Vector logHandlerListeners = new Vector();
369 
370     /***
371      * Adds a listener.
372      * 
373      * @param listener
374      *            Lister to add.
375      * @see LALogHandler#addLogHandlerListener(LALogHandlerListener)
376      */
377     public void addLogHandlerListener(LALogHandlerListener listener) {
378         if (!logHandlerListeners.contains(listener)) {
379             logHandlerListeners.add(listener);
380         }
381     }
382 
383     /***
384      * Removes a listener.
385      * 
386      * @param listener
387      *            Lister to remove.
388      * @see LALogHandler#removeLogHandlerListener(LALogHandlerListener)
389      */
390     public void removeLogHandlerListener(LALogHandlerListener listener) {
391         logHandlerListeners.remove(listener);
392     }
393 
394     /***
395      * Fires a start parsing event.
396      */
397     public void fireStartParsing() {
398         for (int i = 0; i < logHandlerListeners.size(); i++) {
399             ((LALogHandlerListener) logHandlerListeners.get(i))
400                     .startParsing(this);
401         }
402     }
403 
404     /***
405      * Fires a step parsing event.
406      */
407     public void fireStepParsing() {
408         for (int i = 0; i < logHandlerListeners.size(); i++) {
409             ((LALogHandlerListener) logHandlerListeners.get(i))
410                     .stepParsing(this);
411         }
412     }
413 
414     /***
415      * Fires an end parsing event.
416      */
417     public void fireEndParsing() {
418         for (int i = 0; i < logHandlerListeners.size(); i++) {
419             ((LALogHandlerListener) logHandlerListeners.get(i))
420                     .endParsing(this);
421         }
422     }
423 }