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
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
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
329 if (filter.accept(message)) {
330
331 realIndex.add(new Integer(currentIndex));
332 }
333 }
334 }
335
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
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 }