-
Notifications
You must be signed in to change notification settings - Fork 8
/
writinglisteners.html
539 lines (465 loc) · 23 KB
/
writinglisteners.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.11.1 from src/xdocs/writinglisteners.xml.vm at 2024-12-12
| Rendered using Apache Maven Default Skin
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="generator" content="Apache Maven Doxia Site Renderer 1.11.1" />
<title>checkstyle – Writing Listeners</title>
<link rel="stylesheet" href="./css/maven-base.css" />
<link rel="stylesheet" href="./css/maven-theme.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script type="text/javascript" src="./js/checkstyle.js"></script>
<script type="text/javascript"
src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript" src="./js/anchors.js"></script>
<script type="text/javascript" src="./js/google-analytics.js"></script>
<link rel="icon" href="./images/favicon.png" type="image/x-icon" />
<link rel="shortcut icon" href="./images/favicon.ico" type="image/ico" />
</head>
<body class="composite">
<div id="banner">
<a href="./" id="bannerLeft" title="Checkstyle"><img src="images/header-checkstyle-logo.png" alt="Checkstyle"/></a><a href="./" id="bannerRight" title="Checkstyle"><img src="images/header-right-ruller.png" alt="Checkstyle"/></a> <div class="clear">
<hr/>
</div>
</div>
<div id="breadcrumbs">
<div class="xright"><a href="" title="toTop">toTop</a> | <span id="publishDate">Last Published: 2024-12-12</span>
| <span id="projectVersion">Version: 10.21.0</span>
</div>
<div class="clear">
<hr/>
</div>
</div>
<div id="leftColumn">
<div id="navcolumn">
<h5>About</h5>
<ul>
<li class="none"><a href="index.html" title="Checkstyle">Checkstyle</a></li>
<li class="none"><a href="releasenotes.html" title="Release Notes">Release Notes</a></li>
<li class="none"><a href="consulting.html" title="Consulting">Consulting</a></li>
<li class="none"><a href="sponsoring.html" title="Sponsoring">Sponsoring</a></li>
</ul>
<h5>Documentation</h5>
<ul>
<li class="expanded"><a href="config.html" title="Configuration">Configuration</a>
<ul>
<li class="none"><a href="property_types.html" title="Property Types">Property Types</a></li>
<li class="none"><a href="config_system_properties.html" title="System Properties">System Properties</a></li>
</ul></li>
<li class="expanded"><a href="running.html" title="Running">Running</a>
<ul>
<li class="none"><a href="anttask.html" title="Ant Task">Ant Task</a></li>
<li class="none"><a href="cmdline.html" title="Command Line">Command Line</a></li>
</ul></li>
<li class="expanded"><a href="checks.html" title="Checks">Checks</a>
<ul>
<li class="collapsed"><a href="checks/annotation/index.html" title="Annotations">Annotations</a></li>
<li class="collapsed"><a href="checks/blocks/index.html" title="Block Checks">Block Checks</a></li>
<li class="collapsed"><a href="checks/design/index.html" title="Class Design">Class Design</a></li>
<li class="collapsed"><a href="checks/coding/index.html" title="Coding">Coding</a></li>
<li class="collapsed"><a href="checks/header/index.html" title="Headers">Headers</a></li>
<li class="collapsed"><a href="checks/imports/index.html" title="Imports">Imports</a></li>
<li class="collapsed"><a href="checks/javadoc/index.html" title="Javadoc Comments">Javadoc Comments</a></li>
<li class="collapsed"><a href="checks/metrics/index.html" title="Metrics">Metrics</a></li>
<li class="collapsed"><a href="checks/misc/index.html" title="Miscellaneous">Miscellaneous</a></li>
<li class="collapsed"><a href="checks/modifier/index.html" title="Modifiers">Modifiers</a></li>
<li class="collapsed"><a href="checks/naming/index.html" title="Naming Conventions">Naming Conventions</a></li>
<li class="collapsed"><a href="checks/regexp/index.html" title="Regexp">Regexp</a></li>
<li class="collapsed"><a href="checks/sizes/index.html" title="Size Violations">Size Violations</a></li>
<li class="collapsed"><a href="checks/whitespace/index.html" title="Whitespace">Whitespace</a></li>
</ul></li>
<li class="collapsed"><a href="filters/index.html" title="Filters">Filters</a></li>
<li class="collapsed"><a href="filefilters/index.html" title="File Filters">File Filters</a></li>
<li class="expanded"><a href="style_configs.html" title="Style Configurations">Style Configurations</a>
<ul>
<li class="none"><a href="google_style.html" title="Google's Style">Google's Style</a></li>
<li class="none"><a href="sun_style.html" title="Sun's Style">Sun's Style</a></li>
</ul></li>
</ul>
<h5>Developers</h5>
<ul>
<li class="expanded"><a href="extending.html" title="Extending Checkstyle">Extending Checkstyle</a>
<ul>
<li class="none"><a href="writingchecks.html" title="Writing Checks">Writing Checks</a></li>
<li class="none"><a href="writingjavadocchecks.html" title="Writing Javadoc Checks">Writing Javadoc Checks</a></li>
<li class="none"><a href="writingfilters.html" title="Writing Filters">Writing Filters</a></li>
<li class="none"><a href="writingfilefilters.html" title="Writing File Filters">Writing File Filters</a></li>
<li class="none"><strong>Writing Listeners</strong></li>
</ul></li>
<li class="none"><a href="contributing.html" title="Contributing">Contributing</a></li>
<li class="expanded"><a href="beginning_development.html" title="Beginning Development">Beginning Development</a>
<ul>
<li class="none"><a href="eclipse.html" title="Eclipse IDE">Eclipse IDE</a></li>
<li class="none"><a href="netbeans.html" title="NetBeans IDE">NetBeans IDE</a></li>
<li class="none"><a href="idea.html" title="IntelliJ IDE">IntelliJ IDE</a></li>
</ul></li>
<li class="none"><a href="apidocs/index.html" title="Javadoc">Javadoc</a></li>
</ul>
<h5>Project Documentation</h5>
<ul>
<li class="collapsed"><a href="project-info.html" title="Project Information">Project Information</a></li>
<li class="collapsed"><a href="project-reports.html" title="Project Reports">Project Reports</a></li>
</ul>
<a href="https://github.com/checkstyle/checkstyle" title="GitHub" class="poweredBy">
<img class="poweredBy" alt="GitHub" src="images/github_logo_social_coding_outlined.png" />
</a>
<a href="https://twitter.com/checkstyle_java/" title="Twitter" class="poweredBy">
<img class="poweredBy" alt="Twitter" src="images/twitter_button.png" />
</a>
<a href="https://stackoverflow.com/questions/tagged/checkstyle" title="Stackoverflow" class="poweredBy">
<img class="poweredBy" alt="Stackoverflow" src="images/stackoverflow.jpeg" />
</a>
<a href="https://groups.google.com/forum/#!forum/checkstyle" title="GoogleGroups" class="poweredBy">
<img class="poweredBy" alt="GoogleGroups" src="images/groups.png" />
</a>
<a href="https://www.ej-technologies.com/products/jprofiler/overview.html" title="JProfiler" class="poweredBy">
<img class="poweredBy" alt="JProfiler" src="https://www.ej-technologies.com/images/product_banners/jprofiler_medium.png" />
</a>
</div>
</div>
<div id="bodyColumn">
<div id="contentBox">
<section>
<h2><a name="Overview"></a>Overview</h2>
<p>
A Checkstyle listener monitors the progress of a <code>Checker</code> during the audit
of files. The <code>Checker</code> notifies its attached listeners of
significant events such as the start of the audit of a file and
the logging of a Check violation, and the listeners respond
appropriately. Any number of listeners can be attached to a
<code> Checker</code>. An audit always adds one of
the distribution listeners, <a href="apidocs/com/puppycrawl/tools/checkstyle/DefaultLogger.html">DefaultLogger</a>
or <a href="apidocs/com/puppycrawl/tools/checkstyle/XMLLogger.html">XMLLogger</a>,
to report events. A <code>DefaultLogger</code>
produces simple text output for the events it receives, and a
<code>XMLLogger</code> produces an XML document for
its events.
</p>
<p>
Listeners <code>DefaultLogger</code> and <code> XMLLogger</code> are sufficient for most
Checkstyle users, but you may find a need for a custom
listener. For example, a user has requested verbose output of
progress information during a Checkstyle run. Another user would
like to filter violation events. This document explains how to write
listeners for such tasks and how to integrate them in a Checker
module. It also describes two custom listeners that are inspired
by ANT listeners: a listener that is a wrapper for the Jakarta
Commons Logging API, and a listener that sends its results via
email.
</p>
<p>
A listener is an implementation of the <a href="apidocs/com/puppycrawl/tools/checkstyle/api/AuditListener.html">AuditListener</a>
interface. During an audit, a <code>Checker</code>
informs its attached <code>AuditListeners</code> of
six kinds of events: audit started/ended, file started/ended,
and logging of an error(violation)/exception.
</p>
<p>
An audit passes an event to a listener as an <a href="apidocs/com/puppycrawl/tools/checkstyle/api/AuditEvent.html">AuditEvent</a>.
A file-related <code>AuditEvent</code> contains the
name of that file. An <code>AuditEvent</code> for
violation logging has a message, a severity level, a message source
such as the name of a <code>Check</code>, and file
line and column numbers that may be relevant to the violation. The
notification of an exception to a <code>AuditListener</code> includes a violation
<code>AuditEvent</code> and the details of the exception. Here is a UML diagram for
classes <code>AuditListener</code> and <code>AuditEvent</code>.
</p>
<span class="wrapper">
<img src="images/AuditListener.gif" width="381" height="488" alt="AuditListener UML diagram" />
</span>
</section>
<section>
<h2><a name="Writing_Listeners"></a>Writing Listeners</h2>
<p>
A custom listener is an implementation of the <a href="apidocs/com/puppycrawl/tools/checkstyle/api/AuditListener.html">AuditListener</a>
interface. If the listener has properties that can be set from a
configuration, the listener must extend <a href="apidocs/com/puppycrawl/tools/checkstyle/api/AutomaticBean.html">AutomaticBean</a>.
An <code>AutomaticBean</code> uses JavaBean
introspection to set JavaBean properties.
</p>
<p>
The custom listener that we demonstrate here is a verbose
listener that simply prints each event notification to an output
stream, and reports the number of violations per audited file and
the total number of violations. The default output stream is <code>System.out</code>.
In order to enable the specification of output to a file through property
<code>file</code>, the class extends <code>AutomaticBean</code> and defines method
<code>setFile(String)</code>.
</p>
<div class="source">
<pre>
package com.mycompany.listeners;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import com.puppycrawl.tools.checkstyle.api.AuditEvent;
import com.puppycrawl.tools.checkstyle.api.AuditListener;
import com.puppycrawl.tools.checkstyle.AbstractAutomaticBean;
import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
public class VerboseListener
extends AutomaticBean
implements AuditListener
{
private PrintWriter mWriter = new PrintWriter(System.out);
private boolean mCloseOut = false;
private int mTotalErrors;
private int mErrors;
public void setFile(String aFileName)
throws FileNotFoundException
{
final OutputStream out = new FileOutputStream(aFileName);
mWriter = new PrintWriter(out);
mCloseOut = true;
}
public void auditStarted(AuditEvent aEvt)
{
mTotalErrors = 0;
mWriter.println("Audit started.");
}
public void auditFinished(AuditEvent aEvt)
{
mWriter.println("Audit finished. Total errors: " + mTotalErrors);
mWriter.flush();
if (mCloseOut) {
mWriter.close();
}
}
public void fileStarted(AuditEvent aEvt)
{
mErrors = 0;
mWriter.println(
"Started checking file '" + aEvt.getFileName() + "'.");
}
public void fileFinished(AuditEvent aEvt)
{
mWriter.println("Finished checking file '" + aEvt.getFileName()
+ "'. Errors: " + mErrors);
}
public void addError(AuditEvent aEvt)
{
printEvent(aEvt);
if (SeverityLevel.ERROR.equals(aEvt.getSeverityLevel())) {
mErrors++;
mTotalErrors++;
}
}
public void addException(AuditEvent aEvt, Throwable aThrowable)
{
printEvent(aEvt);
aThrowable.printStackTrace(System.out);
mErrors++;
mTotalErrors++;
}
private void printEvent(AuditEvent aEvt)
{
mWriter.println("Logging error -"
+ " file: '" + aEvt.getFileName() + "'"
+ " line: " + aEvt.getLine()
+ " column: " + aEvt.getColumn()
+ " severity: " + aEvt.getSeverityLevel()
+ " message: " + aEvt.getMessage()
+ " source: " + aEvt.getSourceName());
}
}
</pre></div>
<p>
A listener that filters error events could perform the filtering
in methods <code> addError</code> and <code>addException</code>. As further examples of
listeners, <a href="#CommonsLoggingListener">CommonsLoggingListener</a>
reports its events through the Commons Logging API, and <a href="#MailLogger">MailLogger</a> e-mails the audit report of a
<code>DefaultLogger</code>.
</p>
</section>
<section>
<h2><a name="Using_Listeners"></a>Using Listeners</h2>
<p>
To incorporate a custom listener in the set of listeners for a
<code>Checker</code>, include a module element for
the listener in the <a href="config.html#Audit_Listeners">configuration file</a>. For
example, to configure a <code>Checker</code> so
that it uses custom listener
<a class="externalLink" href="https://github.com/checkstyle/contribution/blob/master/examples/listeners/com/mycompany/listeners/VerboseListener.java">
VerboseListener</a>
to print audit messages to a
file named "audit.txt", include the following module
in the configuration file:
</p>
<div class="source">
<pre>
<module name="com.mycompany.listeners.VerboseListener">
<property name="file" value="audit.txt"/>
</module>
</pre></div>
<p>
Here is a truncated example of audit output from a <code> VerboseListener</code>:
</p>
<div class="source">
<pre>
Audit started.
Started checking file 'CommonsLoggingListener.java'.
Finished checking file 'CommonsLoggingListener.java'. Errors: 0
Started checking file 'MailLogger.java'.
Finished checking file 'MailLogger.java'. Errors: 0
Started checking file 'VerboseListener.java'.
Logging error - file: 'VerboseListener.java' line: 23 ...
Finished checking file 'VerboseListener.java'. Errors: 1
Audit finished. Total errors: 1
</pre></div>
</section>
<section>
<h2><a name="Examples"></a>Examples</h2>
<p>
This section describes two examples based on <a class="externalLink" href="https://ant.apache.org/">ANT</a> listeners. The first
listener, <code> CommonsLoggingListener</code>,
hands off events to the <a class="externalLink" href="https://commons.apache.org/proper/commons-logging/">Apache
Commons Logging</a> facade and the second, <code>MailLogger</code>,
sends a report of an audit via
e-mail. The discussion of these examples and how to use them is
derived from material in <a class="externalLink" href="https://www.manning.com/books/java-development-with-ant">"Java Development
with Ant"</a> by Eric Hatcher and Steve Loughran, an
excellent ANT book.
</p>
<a name="CommonsLoggingListener"></a>
<section><section>
<h4><a name="CommonsLoggingListener"></a>CommonsLoggingListener</h4>
<p>
<a class="externalLink" href="https://commons.apache.org/proper/commons-logging/">Apache
Commons Logging</a> provides a facade for logging tools
<a class="externalLink" href="https://logging.apache.org/log4j/2.x/index.html">log4j</a>,
J2SE 1.4, and others. Checkstyle listener <code>CommonsLoggingListener</code>
responds to an AuditEvent by handing it off to the current Commons Logging Log.
</p>
<p>
The source code for
<a class="externalLink" href="https://github.com/checkstyle/contribution/blob/master/examples/listeners/com/mycompany/listeners/CommonsLoggingListener.java">
CommonsLoggingListener</a>. Notice that
each <code>AuditListener</code> method that
receives an <code> AuditEvent</code> calls a method
for the Commons Logging log level corresponding to the
Checkstyle <code>SeverityLevel</code> of the <code> AuditEvent</code>.
</p>
<p>
The easiest way to use <code>CommonsLoggingListener</code> is to include
<code>checkstyle-10.21.0-all.jar</code>
in the classpath because that jar file contains all the Commons
Logging classes. The default Log under J2SE 1.4 is wrapper
class <a class="externalLink" href="https://commons.apache.org/proper/commons-logging/apidocs/org/apache/commons/logging/impl/Jdk14Logger.html">
Jdk14Logger</a>.
Under earlier Java versions, the default Log is a simple wrapper
class, <a class="externalLink" href="https://commons.apache.org/proper/commons-logging/apidocs/org/apache/commons/logging/impl/SimpleLog.html">
SimpleLog</a>.
Both default logging tools can be used directly from Commons
Logging; if you need to use other tools such as log4j, then you
must include the appropriate jar file(s) in the classpath.
</p>
<p>
Logging configuration details for Jakarta Commons Logging are in
the <a class="externalLink" href="https://commons.apache.org/proper/commons-logging/">documentation</a>.
As a simple example, assume that <code>log4j.jar</code> is in the classpath and the
following <code>log4j.properties</code> file is
in the current directory:
</p>
<div class="source">
<pre>
# Set root logger level to INFO and its only appender to A1.
log4j.rootLogger=INFO, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-5p %c %x- %m%n
</pre></div>
<p>
Running a Checkstyle audit with a <code>CommonsLoggingListener</code> yields this
(abbreviated) output:
</p>
<div class="source">
<pre>
INFO com.puppycrawl...Checker - Audit started.
INFO com.puppycrawl...Checker - File "CommonsLoggingListener.java" started.
INFO com.puppycrawl...Checker - File "CommonsLoggingListener.java" finished.
INFO com.puppycrawl...Checker - File "MailLogger.java" started.
INFO com.puppycrawl...Checker - File "MailLogger.java" finished.
INFO com.puppycrawl...Checker - File "VerboseListener.java" started.
ERROR com.puppycrawl...ParenPadCheck - Line: 23 Column: 28 ...
INFO com.puppycrawl...Checker - File "VerboseListener.java" finished.
INFO com.puppycrawl...Checker - Audit finished.
</pre></div>
<a name="MailLogger"></a>
</section><section>
<h4><a name="MailLogger"></a>MailLogger</h4>
<p>
<a class="externalLink" href="https://github.com/checkstyle/contribution/blob/master/examples/listeners/com/mycompany/listeners/MailLogger.java">
MailLogger</a>
sends an audit report in an
email message. The listener uses a <code>DefaultLogger</code> to prepare the text of the
message. The listener obtains other message parameters such as
<code>to</code> and <code>subject</code> from environment properties that
can be read from a properties file.
</p>
<p>
This
implementation uses the <a class="externalLink" href="https://www.oracle.com/java/technologies/javamail.html">JavaMail API</a> as
the mail system, and you must include appropriate jar files in
the classpath.
</p>
<p>
As an example of using <code>MailLogger</code>, set
system property <code>-DMailLogger.properties.file=MailLogger.properties</code>,
so that <code>MailLogger</code> reads message
parameters from file <code>MailLogger.properties</code> of the current
directory:
</p>
<div class="source">
<pre>
MailLogger.mailhost=localhost
</pre></div>
</section></section></section>
<section>
<h2><a name="Huh.3F_I_can.27t_figure_it_out.21"></a>Huh? I can't figure it out!</h2>
<p>
That's probably our fault, and it means that we have to
provide better documentation. Please do not hesitate to ask
questions on the user mailing list, this will help us to improve
this document. Please ask your questions as precisely as
possible. We will not be able to answer questions like "I
want to write a listener but I don't know how, can you help
me?". Tell us what you are trying to do (the purpose of the
listener), what you have understood so far, and what exactly you
are getting stuck on.
</p>
</section>
<section>
<h2><a name="Contributing"></a>Contributing</h2>
<p>
We need <i>your</i> help to keep improving Checkstyle.
Whenever you write a listener that you think is generally
useful, please consider <a href="contributing.html">contributing</a> it to the Checkstyle
community and submit it for inclusion in the next release of
Checkstyle.
</p>
</section>
</div>
</div>
<div class="clear">
<hr/>
</div>
<div id="footer">
<div class="xright">
Copyright © 2001–2024.. </div>
<div class="clear">
<hr/>
</div>
</div>
</body>
</html>