1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.Checker.EXCEPTION_MSG;
24 import static com.puppycrawl.tools.checkstyle.DefaultLogger.AUDIT_FINISHED_MESSAGE;
25 import static com.puppycrawl.tools.checkstyle.DefaultLogger.AUDIT_STARTED_MESSAGE;
26 import static com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck.MSG_KEY_NO_NEWLINE_EOF;
27 import static com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck.MSG_KEY;
28
29 import java.io.BufferedReader;
30 import java.io.BufferedWriter;
31 import java.io.ByteArrayInputStream;
32 import java.io.ByteArrayOutputStream;
33 import java.io.File;
34 import java.io.IOError;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.InputStreamReader;
38 import java.io.LineNumberReader;
39 import java.io.OutputStream;
40 import java.io.UnsupportedEncodingException;
41 import java.lang.reflect.Field;
42 import java.lang.reflect.Method;
43 import java.nio.charset.StandardCharsets;
44 import java.nio.file.Files;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Collections;
48 import java.util.HashSet;
49 import java.util.List;
50 import java.util.Locale;
51 import java.util.Objects;
52 import java.util.Properties;
53 import java.util.Set;
54 import java.util.SortedSet;
55 import java.util.TreeSet;
56 import java.util.UUID;
57 import java.util.stream.Collectors;
58
59 import org.junit.jupiter.api.Test;
60 import org.junit.jupiter.api.io.TempDir;
61
62 import com.puppycrawl.tools.checkstyle.AbstractAutomaticBean.OutputStreamOptions;
63 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
64 import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
65 import com.puppycrawl.tools.checkstyle.api.AuditEvent;
66 import com.puppycrawl.tools.checkstyle.api.AuditListener;
67 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
68 import com.puppycrawl.tools.checkstyle.api.Configuration;
69 import com.puppycrawl.tools.checkstyle.api.Context;
70 import com.puppycrawl.tools.checkstyle.api.DetailAST;
71 import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder;
72 import com.puppycrawl.tools.checkstyle.api.FileText;
73 import com.puppycrawl.tools.checkstyle.api.Filter;
74 import com.puppycrawl.tools.checkstyle.api.FilterSet;
75 import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
76 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
77 import com.puppycrawl.tools.checkstyle.api.Violation;
78 import com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck;
79 import com.puppycrawl.tools.checkstyle.checks.TranslationCheck;
80 import com.puppycrawl.tools.checkstyle.checks.coding.HiddenFieldCheck;
81 import com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck;
82 import com.puppycrawl.tools.checkstyle.filefilters.BeforeExecutionExclusionFileFilter;
83 import com.puppycrawl.tools.checkstyle.filters.SuppressionFilter;
84 import com.puppycrawl.tools.checkstyle.internal.testmodules.CheckWhichThrowsError;
85 import com.puppycrawl.tools.checkstyle.internal.testmodules.DebugAuditAdapter;
86 import com.puppycrawl.tools.checkstyle.internal.testmodules.DebugFilter;
87 import com.puppycrawl.tools.checkstyle.internal.testmodules.TestBeforeExecutionFileFilter;
88 import com.puppycrawl.tools.checkstyle.internal.testmodules.TestFileSetCheck;
89 import com.puppycrawl.tools.checkstyle.internal.utils.CloseAndFlushTestByteArrayOutputStream;
90 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
91 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
92 import de.thetaphi.forbiddenapis.SuppressForbidden;
93
94
95
96
97
98
99
100
101 public class CheckerTest extends AbstractModuleTestSupport {
102
103 @TempDir
104 public File temporaryFolder;
105
106 private File createTempFile(String prefix) throws IOException {
107 return createTempFile(prefix, ".tmp");
108 }
109
110 private File createTempFile(String prefix, String suffix) throws IOException {
111 final String name = Objects.requireNonNull(prefix)
112 + UUID.randomUUID()
113 + Objects.requireNonNull(suffix);
114 return Files.createFile(temporaryFolder.toPath().resolve(name)).toFile();
115 }
116
117 private static Method getFireAuditFinished() throws NoSuchMethodException {
118 final Class<Checker> checkerClass = Checker.class;
119 final Method fireAuditFinished = checkerClass.getDeclaredMethod("fireAuditFinished");
120 fireAuditFinished.setAccessible(true);
121 return fireAuditFinished;
122 }
123
124 private static Method getFireAuditStartedMethod() throws NoSuchMethodException {
125 final Class<Checker> checkerClass = Checker.class;
126 final Method fireAuditStarted = checkerClass.getDeclaredMethod("fireAuditStarted");
127 fireAuditStarted.setAccessible(true);
128 return fireAuditStarted;
129 }
130
131 @Override
132 protected String getPackageLocation() {
133 return "com/puppycrawl/tools/checkstyle/checker";
134 }
135
136 @Test
137 public void testDestroy() throws Exception {
138 final Checker checker = new Checker();
139 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
140 checker.addListener(auditAdapter);
141 final TestFileSetCheck fileSet = new TestFileSetCheck();
142 checker.addFileSetCheck(fileSet);
143 final DebugFilter filter = new DebugFilter();
144 checker.addFilter(filter);
145 final TestBeforeExecutionFileFilter fileFilter = new TestBeforeExecutionFileFilter();
146 checker.addBeforeExecutionFileFilter(fileFilter);
147
148
149 checker.destroy();
150
151 final File tempFile = createTempFile("junit");
152 checker.process(Collections.singletonList(tempFile));
153 final SortedSet<Violation> violations = new TreeSet<>();
154 violations.add(new Violation(1, 0, "a Bundle", "message.key",
155 new Object[] {"arg"}, null, getClass(), null));
156 checker.fireErrors("Some File Name", violations);
157
158 assertWithMessage("Checker.destroy() doesn't remove listeners.")
159 .that(auditAdapter.wasCalled())
160 .isFalse();
161 assertWithMessage("Checker.destroy() doesn't remove file sets.")
162 .that(fileSet.wasCalled())
163 .isFalse();
164 assertWithMessage("Checker.destroy() doesn't remove filters.")
165 .that(filter.wasCalled())
166 .isFalse();
167 assertWithMessage("Checker.destroy() doesn't remove file filters.")
168 .that(fileFilter.wasCalled())
169 .isFalse();
170 }
171
172 @Test
173 public void testAddListener() throws Exception {
174 final Checker checker = new Checker();
175 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
176 checker.addListener(auditAdapter);
177
178
179 getFireAuditStartedMethod().invoke(checker);
180 assertWithMessage("Checker.fireAuditStarted() doesn't call listener")
181 .that(auditAdapter.wasCalled())
182 .isTrue();
183 assertWithMessage("Checker.fireAuditStarted() doesn't pass event")
184 .that(auditAdapter.wasEventPassed())
185 .isTrue();
186
187 auditAdapter.resetListener();
188 getFireAuditFinished().invoke(checker);
189 assertWithMessage("Checker.fireAuditFinished() doesn't call listener")
190 .that(auditAdapter.wasCalled())
191 .isTrue();
192 assertWithMessage("Checker.fireAuditFinished() doesn't pass event")
193 .that(auditAdapter.wasEventPassed())
194 .isTrue();
195
196 auditAdapter.resetListener();
197 checker.fireFileStarted("Some File Name");
198 assertWithMessage("Checker.fireFileStarted() doesn't call listener")
199 .that(auditAdapter.wasCalled())
200 .isTrue();
201 assertWithMessage("Checker.fireFileStarted() doesn't pass event")
202 .that(auditAdapter.wasEventPassed())
203 .isTrue();
204
205 auditAdapter.resetListener();
206 checker.fireFileFinished("Some File Name");
207 assertWithMessage("Checker.fireFileFinished() doesn't call listener")
208 .that(auditAdapter.wasCalled())
209 .isTrue();
210 assertWithMessage("Checker.fireFileFinished() doesn't pass event")
211 .that(auditAdapter.wasEventPassed())
212 .isTrue();
213
214 auditAdapter.resetListener();
215 final SortedSet<Violation> violations = new TreeSet<>();
216 violations.add(new Violation(1, 0, "a Bundle", "message.key",
217 new Object[] {"arg"}, null, getClass(), null));
218 checker.fireErrors("Some File Name", violations);
219 assertWithMessage("Checker.fireErrors() doesn't call listener")
220 .that(auditAdapter.wasCalled())
221 .isTrue();
222 assertWithMessage("Checker.fireErrors() doesn't pass event")
223 .that(auditAdapter.wasEventPassed())
224 .isTrue();
225 }
226
227 @Test
228 public void testRemoveListener() throws Exception {
229 final Checker checker = new Checker();
230 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
231 final DebugAuditAdapter aa2 = new DebugAuditAdapter();
232 checker.addListener(auditAdapter);
233 checker.addListener(aa2);
234 checker.removeListener(auditAdapter);
235
236
237 getFireAuditStartedMethod().invoke(checker);
238 assertWithMessage("Checker.fireAuditStarted() doesn't call listener")
239 .that(aa2.wasCalled())
240 .isTrue();
241 assertWithMessage("Checker.fireAuditStarted() does call removed listener")
242 .that(auditAdapter.wasCalled())
243 .isFalse();
244
245 aa2.resetListener();
246 getFireAuditFinished().invoke(checker);
247 assertWithMessage("Checker.fireAuditFinished() doesn't call listener")
248 .that(aa2.wasCalled())
249 .isTrue();
250 assertWithMessage("Checker.fireAuditFinished() does call removed listener")
251 .that(auditAdapter.wasCalled())
252 .isFalse();
253
254 aa2.resetListener();
255 checker.fireFileStarted("Some File Name");
256 assertWithMessage("Checker.fireFileStarted() doesn't call listener")
257 .that(aa2.wasCalled())
258 .isTrue();
259 assertWithMessage("Checker.fireFileStarted() does call removed listener")
260 .that(auditAdapter.wasCalled())
261 .isFalse();
262
263 aa2.resetListener();
264 checker.fireFileFinished("Some File Name");
265 assertWithMessage("Checker.fireFileFinished() doesn't call listener")
266 .that(aa2.wasCalled())
267 .isTrue();
268 assertWithMessage("Checker.fireFileFinished() does call removed listener")
269 .that(auditAdapter.wasCalled())
270 .isFalse();
271
272 aa2.resetListener();
273 final SortedSet<Violation> violations = new TreeSet<>();
274 violations.add(new Violation(1, 0, "a Bundle", "message.key",
275 new Object[] {"arg"}, null, getClass(), null));
276 checker.fireErrors("Some File Name", violations);
277 assertWithMessage("Checker.fireErrors() doesn't call listener")
278 .that(aa2.wasCalled())
279 .isTrue();
280 assertWithMessage("Checker.fireErrors() does call removed listener")
281 .that(auditAdapter.wasCalled())
282 .isFalse();
283 }
284
285 @Test
286 public void testAddBeforeExecutionFileFilter() throws Exception {
287 final Checker checker = new Checker();
288 final TestBeforeExecutionFileFilter filter = new TestBeforeExecutionFileFilter();
289
290 checker.addBeforeExecutionFileFilter(filter);
291
292 filter.resetFilter();
293 checker.process(Collections.singletonList(new File("dummy.java")));
294 assertWithMessage("Checker.acceptFileStarted() doesn't call filter")
295 .that(filter.wasCalled())
296 .isTrue();
297 }
298
299 @Test
300 public void testRemoveBeforeExecutionFileFilter() throws Exception {
301 final Checker checker = new Checker();
302 final TestBeforeExecutionFileFilter filter = new TestBeforeExecutionFileFilter();
303 final TestBeforeExecutionFileFilter f2 = new TestBeforeExecutionFileFilter();
304 checker.addBeforeExecutionFileFilter(filter);
305 checker.addBeforeExecutionFileFilter(f2);
306 checker.removeBeforeExecutionFileFilter(filter);
307
308 f2.resetFilter();
309 checker.process(Collections.singletonList(new File("dummy.java")));
310 assertWithMessage("Checker.acceptFileStarted() doesn't call filter")
311 .that(f2.wasCalled())
312 .isTrue();
313 assertWithMessage("Checker.acceptFileStarted() does call removed filter")
314 .that(filter.wasCalled())
315 .isFalse();
316 }
317
318 @Test
319 public void testAddFilter() {
320 final Checker checker = new Checker();
321 final DebugFilter filter = new DebugFilter();
322
323 checker.addFilter(filter);
324
325 filter.resetFilter();
326 final SortedSet<Violation> violations = new TreeSet<>();
327 violations.add(new Violation(1, 0, "a Bundle", "message.key",
328 new Object[] {"arg"}, null, getClass(), null));
329 checker.fireErrors("Some File Name", violations);
330 assertWithMessage("Checker.fireErrors() doesn't call filter")
331 .that(filter.wasCalled())
332 .isTrue();
333 }
334
335 @Test
336 public void testRemoveFilter() {
337 final Checker checker = new Checker();
338 final DebugFilter filter = new DebugFilter();
339 final DebugFilter f2 = new DebugFilter();
340 checker.addFilter(filter);
341 checker.addFilter(f2);
342 checker.removeFilter(filter);
343
344 f2.resetFilter();
345 final SortedSet<Violation> violations = new TreeSet<>();
346 violations.add(new Violation(1, 0, "a Bundle", "message.key",
347 new Object[] {"arg"}, null, getClass(), null));
348 checker.fireErrors("Some File Name", violations);
349 assertWithMessage("Checker.fireErrors() doesn't call filter")
350 .that(f2.wasCalled())
351 .isTrue();
352 assertWithMessage("Checker.fireErrors() does call removed filter")
353 .that(filter.wasCalled())
354 .isFalse();
355 }
356
357 @Test
358 public void testFileExtensions() throws Exception {
359 final DefaultConfiguration checkerConfig = new DefaultConfiguration("configuration");
360 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
361 checkerConfig.addProperty("cacheFile", createTempFile("junit").getPath());
362
363 final Checker checker = new Checker();
364 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
365 checker.configure(checkerConfig);
366
367 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
368 checker.addListener(auditAdapter);
369
370 final List<File> files = new ArrayList<>();
371 final File file = new File("file.pdf");
372 files.add(file);
373 final File otherFile = new File("file.java");
374 files.add(otherFile);
375 final String[] fileExtensions = {"java", "xml", "properties"};
376 checker.setFileExtensions(fileExtensions);
377 checker.setCacheFile(createTempFile("junit").getPath());
378 final int counter = checker.process(files);
379
380
381 final int numLegalFiles = 1;
382 final PropertyCacheFile cache = TestUtil.getInternalState(checker, "cacheFile");
383 assertWithMessage("There were more legal files than expected")
384 .that(counter)
385 .isEqualTo(numLegalFiles);
386 assertWithMessage("Audit was started on larger amount of files than expected")
387 .that(auditAdapter.getNumFilesStarted())
388 .isEqualTo(numLegalFiles);
389 assertWithMessage("Audit was finished on larger amount of files than expected")
390 .that(auditAdapter.getNumFilesFinished())
391 .isEqualTo(numLegalFiles);
392 assertWithMessage("Cache shout not contain any file")
393 .that(cache.get(new File("file.java").getCanonicalPath()))
394 .isNull();
395 }
396
397 @Test
398 public void testIgnoredFileExtensions() throws Exception {
399 final DefaultConfiguration checkerConfig = new DefaultConfiguration("configuration");
400 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
401 final File tempFile = createTempFile("junit");
402 checkerConfig.addProperty("cacheFile", tempFile.getPath());
403
404 final Checker checker = new Checker();
405 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
406 checker.configure(checkerConfig);
407
408 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
409 checker.addListener(auditAdapter);
410
411 final List<File> allIgnoredFiles = new ArrayList<>();
412 final File ignoredFile = new File("file.pdf");
413 allIgnoredFiles.add(ignoredFile);
414 final String[] fileExtensions = {"java", "xml", "properties"};
415 checker.setFileExtensions(fileExtensions);
416 checker.setCacheFile(createTempFile("junit").getPath());
417 final int counter = checker.process(allIgnoredFiles);
418
419
420 final int numLegalFiles = 0;
421 assertWithMessage("There were more legal files than expected")
422 .that(counter)
423 .isEqualTo(numLegalFiles);
424 assertWithMessage("Audit was started on larger amount of files than expected")
425 .that(auditAdapter.getNumFilesStarted())
426 .isEqualTo(numLegalFiles);
427 assertWithMessage("Audit was finished on larger amount of files than expected")
428 .that(auditAdapter.getNumFilesFinished())
429 .isEqualTo(numLegalFiles);
430 }
431
432 @Test
433 public void testSetters() {
434
435 final Checker checker = new Checker();
436 checker.setBasedir("some");
437 checker.setSeverity("ignore");
438
439 final PackageObjectFactory factory = new PackageObjectFactory(
440 new HashSet<>(), Thread.currentThread().getContextClassLoader());
441 checker.setModuleFactory(factory);
442
443 checker.setFileExtensions((String[]) null);
444 checker.setFileExtensions(".java", "xml");
445
446 try {
447 checker.setCharset("UNKNOWN-CHARSET");
448 assertWithMessage("Exception is expected").fail();
449 }
450 catch (UnsupportedEncodingException exc) {
451 assertWithMessage("Error message is not expected")
452 .that(exc.getMessage())
453 .isEqualTo("unsupported charset: 'UNKNOWN-CHARSET'");
454 }
455 }
456
457 @Test
458 public void testSetSeverity() throws Exception {
459 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
460
461 verifyWithInlineXmlConfig(getPath("InputCheckerTestSeverity.java"), expected);
462 }
463
464 @Test
465 public void testNoClassLoaderNoModuleFactory() {
466 final Checker checker = new Checker();
467
468 try {
469 checker.finishLocalSetup();
470 assertWithMessage("Exception is expected").fail();
471 }
472 catch (CheckstyleException exc) {
473 assertWithMessage("Error message is not expected")
474 .that(exc.getMessage())
475 .isEqualTo("if no custom moduleFactory is set,"
476 + " moduleClassLoader must be specified");
477 }
478 }
479
480 @Test
481 public void testNoModuleFactory() throws Exception {
482 final Checker checker = new Checker();
483 final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
484
485 checker.setModuleClassLoader(classLoader);
486 checker.finishLocalSetup();
487 final Context actualCtx = TestUtil.getInternalState(checker, "childContext");
488
489 assertWithMessage("Default module factory should be created when it is not specified")
490 .that(actualCtx.get("moduleFactory"))
491 .isNotNull();
492 }
493
494 @Test
495 public void testFinishLocalSetupFullyInitialized() throws Exception {
496 final Checker checker = new Checker();
497 final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
498 checker.setModuleClassLoader(contextClassLoader);
499 final PackageObjectFactory factory = new PackageObjectFactory(
500 new HashSet<>(), contextClassLoader);
501 checker.setModuleFactory(factory);
502 checker.setBasedir("testBaseDir");
503 checker.setLocaleLanguage("it");
504 checker.setLocaleCountry("IT");
505 checker.finishLocalSetup();
506
507 final Context context = TestUtil.getInternalState(checker, "childContext");
508 final String encoding = StandardCharsets.UTF_8.name();
509 assertWithMessage("Charset was different than expected")
510 .that(context.get("charset"))
511 .isEqualTo(encoding);
512 assertWithMessage("Severity is set to unexpected value")
513 .that(context.get("severity"))
514 .isEqualTo("error");
515 assertWithMessage("Basedir is set to unexpected value")
516 .that(context.get("basedir"))
517 .isEqualTo("testBaseDir");
518
519 final Field sLocale = LocalizedMessage.class.getDeclaredField("sLocale");
520 sLocale.setAccessible(true);
521 final Locale locale = (Locale) sLocale.get(null);
522 assertWithMessage("Locale is set to unexpected value")
523 .that(locale)
524 .isEqualTo(Locale.ITALY);
525 }
526
527 @Test
528 public void testSetupChildExceptions() {
529 final Checker checker = new Checker();
530 final PackageObjectFactory factory = new PackageObjectFactory(
531 new HashSet<>(), Thread.currentThread().getContextClassLoader());
532 checker.setModuleFactory(factory);
533
534 final Configuration config = new DefaultConfiguration("java.lang.String");
535 try {
536 checker.setupChild(config);
537 assertWithMessage("Exception is expected").fail();
538 }
539 catch (CheckstyleException exc) {
540 assertWithMessage("Error message is not expected")
541 .that(exc.getMessage())
542 .isEqualTo("java.lang.String is not allowed as a child in Checker");
543 }
544 }
545
546 @Test
547 public void testSetupChildInvalidProperty() throws Exception {
548 final DefaultConfiguration checkConfig = createModuleConfig(HiddenFieldCheck.class);
549 checkConfig.addProperty("$$No such property", null);
550 try {
551 createChecker(checkConfig);
552 assertWithMessage("Exception is expected").fail();
553 }
554 catch (CheckstyleException exc) {
555 assertWithMessage("Error message is not expected")
556 .that(exc.getMessage())
557 .isEqualTo("cannot initialize module com.puppycrawl.tools.checkstyle.TreeWalker"
558 + " - cannot initialize module " + checkConfig.getName()
559 + " - Property '$$No such property'"
560 + " does not exist, please check the documentation");
561 }
562 }
563
564 @Test
565 public void testSetupChildListener() throws Exception {
566 final Checker checker = new Checker();
567 final PackageObjectFactory factory = new PackageObjectFactory(
568 new HashSet<>(), Thread.currentThread().getContextClassLoader());
569 checker.setModuleFactory(factory);
570
571 final Configuration config = new DefaultConfiguration(
572 DebugAuditAdapter.class.getCanonicalName());
573 checker.setupChild(config);
574
575 final List<AuditListener> listeners = TestUtil.getInternalState(checker, "listeners");
576 assertWithMessage("Invalid child listener class")
577 .that(listeners.get(listeners.size() - 1) instanceof DebugAuditAdapter)
578 .isTrue();
579 }
580
581 @Test
582 public void testDestroyCheckerWithWrongCacheFileNameLength() throws Exception {
583 final Checker checker = new Checker();
584 final PackageObjectFactory factory = new PackageObjectFactory(
585 new HashSet<>(), Thread.currentThread().getContextClassLoader());
586 checker.setModuleFactory(factory);
587 checker.configure(new DefaultConfiguration("default config"));
588
589
590
591 checker.setCacheFile(String.format(Locale.ENGLISH, "%0300d", 0));
592 try {
593 checker.destroy();
594 assertWithMessage("Exception did not happen").fail();
595 }
596 catch (IllegalStateException exc) {
597 assertWithMessage("Cause of exception differs from IOException")
598 .that(exc.getCause())
599 .isInstanceOf(IOException.class);
600 }
601 }
602
603
604
605
606 @Test
607 public void testCacheAndCheckWhichDoesNotImplementExternalResourceHolderInterface()
608 throws Exception {
609 assertWithMessage("ExternalResourceHolder has changed his parent")
610 .that(ExternalResourceHolder.class.isAssignableFrom(HiddenFieldCheck.class))
611 .isFalse();
612 final DefaultConfiguration checkConfig = createModuleConfig(HiddenFieldCheck.class);
613
614 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
615 treeWalkerConfig.addChild(checkConfig);
616
617 final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
618 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
619
620 final File cacheFile = createTempFile("junit");
621 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
622
623 final File tmpFile = createTempFile("file", ".java");
624
625 execute(checkerConfig, tmpFile.getPath());
626 final Properties cacheAfterFirstRun = new Properties();
627 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
628 cacheAfterFirstRun.load(reader);
629 }
630
631
632 execute(checkerConfig, tmpFile.getPath());
633 final Properties cacheAfterSecondRun = new Properties();
634 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
635 cacheAfterSecondRun.load(reader);
636 }
637
638 assertWithMessage("Cache from first run differs from second run cache")
639 .that(cacheAfterSecondRun)
640 .isEqualTo(cacheAfterFirstRun);
641 }
642
643 @Test
644 public void testWithCacheWithNoViolation() throws Exception {
645 final Checker checker = new Checker();
646 final PackageObjectFactory factory = new PackageObjectFactory(
647 new HashSet<>(), Thread.currentThread().getContextClassLoader());
648 checker.setModuleFactory(factory);
649 checker.configure(createModuleConfig(TranslationCheck.class));
650
651 final File cacheFile = createTempFile("junit");
652 checker.setCacheFile(cacheFile.getPath());
653
654 checker.setupChild(createModuleConfig(TranslationCheck.class));
655 final File tmpFile = createTempFile("file", ".java");
656 final List<File> files = new ArrayList<>(1);
657 files.add(tmpFile);
658 checker.process(files);
659
660
661 checker.destroy();
662
663 final Properties cache = new Properties();
664 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
665 cache.load(reader);
666 }
667
668
669 final int expectedNumberOfObjectsInCache = 2;
670 assertWithMessage("Cache has unexpected size")
671 .that(cache)
672 .hasSize(expectedNumberOfObjectsInCache);
673
674 final String expectedConfigHash = "D581D4A2BD482D4E1EF1F82459356BA2D8A3B" + "FC3";
675 assertWithMessage("Cache has unexpected hash")
676 .that(cache.getProperty(PropertyCacheFile.CONFIG_HASH_KEY))
677 .isEqualTo(expectedConfigHash);
678
679 assertWithMessage("Cache file has null path")
680 .that(cache.getProperty(tmpFile.getPath()))
681 .isNotNull();
682 }
683
684 @Test
685 public void testClearExistingCache() throws Exception {
686 final DefaultConfiguration checkerConfig = createRootConfig(null);
687 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
688 final File cacheFile = createTempFile("junit");
689 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
690
691 final Checker checker = new Checker();
692 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
693 checker.configure(checkerConfig);
694 checker.addListener(getBriefUtLogger());
695
696 checker.clearCache();
697
698 checker.destroy();
699
700 final Properties cacheAfterClear = new Properties();
701 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
702 cacheAfterClear.load(reader);
703 }
704
705 assertWithMessage("Cache has unexpected size")
706 .that(cacheAfterClear)
707 .hasSize(1);
708 assertWithMessage("Cache has null hash")
709 .that(cacheAfterClear.getProperty(PropertyCacheFile.CONFIG_HASH_KEY))
710 .isNotNull();
711
712 final String pathToEmptyFile = createTempFile("file", ".java").getPath();
713
714
715 execute(checkerConfig, pathToEmptyFile);
716 final Properties cacheAfterSecondRun = new Properties();
717 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
718 cacheAfterSecondRun.load(reader);
719 }
720
721 assertWithMessage("Cache has null path")
722 .that(cacheAfterSecondRun.getProperty(pathToEmptyFile))
723 .isNotNull();
724 final String cacheHash = cacheAfterSecondRun.getProperty(PropertyCacheFile.CONFIG_HASH_KEY);
725 assertWithMessage("Cash have changed it hash")
726 .that(cacheHash)
727 .isEqualTo(cacheAfterClear.getProperty(PropertyCacheFile.CONFIG_HASH_KEY));
728 final int expectedNumberOfObjectsInCacheAfterSecondRun = 2;
729 assertWithMessage("Cache has changed number of items")
730 .that(cacheAfterSecondRun)
731 .hasSize(expectedNumberOfObjectsInCacheAfterSecondRun);
732 }
733
734 @Test
735 public void testClearCache() throws Exception {
736 final DefaultConfiguration violationCheck =
737 createModuleConfig(DummyFileSetViolationCheck.class);
738 final DefaultConfiguration checkerConfig = new DefaultConfiguration("myConfig");
739 checkerConfig.addProperty("charset", "UTF-8");
740 final File cacheFile = createTempFile("junit");
741 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
742 checkerConfig.addChild(violationCheck);
743 final Checker checker = new Checker();
744 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
745 checker.configure(checkerConfig);
746 checker.addListener(getBriefUtLogger());
747
748 checker.process(Collections.singletonList(new File("dummy.java")));
749 checker.clearCache();
750
751 final PropertyCacheFile cache = TestUtil.getInternalState(checker, "cacheFile");
752 cache.persist();
753
754 final Properties cacheAfterClear = new Properties();
755 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
756 cacheAfterClear.load(reader);
757 }
758
759 assertWithMessage("Cache has unexpected size")
760 .that(cacheAfterClear)
761 .hasSize(1);
762 }
763
764 @Test
765 public void setFileExtension() {
766 final Checker checker = new Checker();
767 checker.setFileExtensions(".test1", "test2");
768 final String[] actual = TestUtil.getInternalState(checker, "fileExtensions");
769 assertWithMessage("Extensions are not expected")
770 .that(actual)
771 .isEqualTo(new String[] {".test1", ".test2"});
772 }
773
774 @Test
775 public void testClearCacheWhenCacheFileIsNotSet() {
776
777
778 final Checker checker = new Checker();
779 checker.clearCache();
780 final PropertyCacheFile cache = TestUtil.getInternalState(checker, "cacheFile");
781 assertWithMessage("If cache file is not set the cache should default to null")
782 .that(cache)
783 .isNull();
784 }
785
786
787
788
789
790
791
792
793 @Test
794 public void testCatchErrorInProcessFilesMethod() throws Exception {
795
796 final String errorMessage = "Java Virtual Machine is broken"
797 + " or has run out of resources necessary for it to continue operating.";
798 final Error expectedError = new IOError(new InternalError(errorMessage));
799
800 final File mock = new File("testFile") {
801 private static final long serialVersionUID = 1L;
802
803
804
805
806
807
808
809
810 @Override
811 public long lastModified() {
812 throw expectedError;
813 }
814 };
815
816 final Checker checker = new Checker();
817 final List<File> filesToProcess = new ArrayList<>();
818 filesToProcess.add(mock);
819 try {
820 checker.process(filesToProcess);
821 assertWithMessage("IOError is expected!").fail();
822 }
823
824 catch (Error error) {
825 assertWithMessage("Error cause differs from IOError")
826 .that(error.getCause())
827 .isInstanceOf(IOError.class);
828 assertWithMessage("Error cause is not InternalError")
829 .that(error.getCause().getCause())
830 .isInstanceOf(InternalError.class);
831 assertWithMessage("Error message is not expected")
832 .that(error)
833 .hasCauseThat()
834 .hasCauseThat()
835 .hasMessageThat()
836 .isEqualTo(errorMessage);
837 }
838 }
839
840
841
842
843
844
845
846
847 @Test
848 public void testCatchErrorWithNoFileName() throws Exception {
849
850 final String errorMessage = "Java Virtual Machine is broken"
851 + " or has run out of resources necessary for it to continue operating.";
852 final Error expectedError = new IOError(new InternalError(errorMessage));
853
854 final File mock = new File("testFile") {
855 private static final long serialVersionUID = 1L;
856
857
858
859
860
861
862
863
864 @Override
865 public long lastModified() {
866 throw expectedError;
867 }
868
869 @Override
870 public String getAbsolutePath() {
871 return null;
872 }
873 };
874
875 final Checker checker = new Checker();
876 final List<File> filesToProcess = new ArrayList<>();
877 filesToProcess.add(mock);
878 try {
879 checker.process(filesToProcess);
880 assertWithMessage("IOError is expected!").fail();
881 }
882
883 catch (Error error) {
884 assertWithMessage("Error cause differs from IOError")
885 .that(error)
886 .hasCauseThat()
887 .isInstanceOf(IOError.class);
888 assertWithMessage("Error cause is not InternalError")
889 .that(error)
890 .hasCauseThat()
891 .hasCauseThat()
892 .isInstanceOf(InternalError.class);
893 assertWithMessage("Error message is not expected")
894 .that(error)
895 .hasCauseThat()
896 .hasCauseThat()
897 .hasMessageThat()
898 .isEqualTo(errorMessage);
899 }
900 }
901
902
903
904
905 @Test
906 public void testCacheAndFilterWhichDoesNotImplementExternalResourceHolderInterface()
907 throws Exception {
908 assertWithMessage("ExternalResourceHolder has changed its parent")
909 .that(ExternalResourceHolder.class.isAssignableFrom(DummyFilter.class))
910 .isFalse();
911 final DefaultConfiguration filterConfig = createModuleConfig(DummyFilter.class);
912
913 final DefaultConfiguration checkerConfig = createRootConfig(filterConfig);
914 final File cacheFile = createTempFile("junit");
915 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
916
917 final String pathToEmptyFile = createTempFile("file", ".java").getPath();
918
919 execute(checkerConfig, pathToEmptyFile);
920 final Properties cacheAfterFirstRun = new Properties();
921 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
922 cacheAfterFirstRun.load(reader);
923 }
924
925
926 execute(checkerConfig, pathToEmptyFile);
927 final Properties cacheAfterSecondRun = new Properties();
928 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
929 cacheAfterSecondRun.load(reader);
930 }
931
932 final String cacheFilePath = cacheAfterSecondRun.getProperty(pathToEmptyFile);
933 assertWithMessage("Cache file has changed its path")
934 .that(cacheFilePath)
935 .isEqualTo(cacheAfterFirstRun.getProperty(pathToEmptyFile));
936 final String cacheHash = cacheAfterSecondRun.getProperty(PropertyCacheFile.CONFIG_HASH_KEY);
937 assertWithMessage("Cache has changed its hash")
938 .that(cacheHash)
939 .isEqualTo(cacheAfterFirstRun.getProperty(PropertyCacheFile.CONFIG_HASH_KEY));
940 final int expectedNumberOfObjectsInCache = 2;
941 assertWithMessage("Number of items in cache differs from expected")
942 .that(cacheAfterFirstRun)
943 .hasSize(expectedNumberOfObjectsInCache);
944 assertWithMessage("Number of items in cache differs from expected")
945 .that(cacheAfterSecondRun)
946 .hasSize(expectedNumberOfObjectsInCache);
947 }
948
949
950
951
952
953 @Test
954 public void testCacheAndCheckWhichAddsNewResourceLocationButKeepsSameCheckerInstance()
955 throws Exception {
956
957
958
959
960
961
962 final DynamicalResourceHolderCheck check = new DynamicalResourceHolderCheck();
963 final String firstExternalResourceLocation = getPath("InputCheckerImportControlOne.xml");
964 final String firstExternalResourceKey = PropertyCacheFile.EXTERNAL_RESOURCE_KEY_PREFIX
965 + firstExternalResourceLocation;
966 check.setFirstExternalResourceLocation(firstExternalResourceLocation);
967
968 final DefaultConfiguration checkerConfig = createRootConfig(null);
969 final File cacheFile = createTempFile("junit");
970 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
971
972 final Checker checker = new Checker();
973 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
974 checker.addFileSetCheck(check);
975 checker.addFilter(new DummyFilterSet());
976 checker.configure(checkerConfig);
977 checker.addListener(getBriefUtLogger());
978
979 final String pathToEmptyFile = createTempFile("file", ".java").getPath();
980
981 execute(checker, pathToEmptyFile);
982 final Properties cacheAfterFirstRun = new Properties();
983 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
984 cacheAfterFirstRun.load(reader);
985 }
986
987 final int expectedNumberOfObjectsInCacheAfterFirstRun = 4;
988 assertWithMessage("Number of items in cache differs from expected")
989 .that(cacheAfterFirstRun)
990 .hasSize(expectedNumberOfObjectsInCacheAfterFirstRun);
991
992
993 final String secondExternalResourceLocation = "InputCheckerImportControlTwo.xml";
994 final String secondExternalResourceKey = PropertyCacheFile.EXTERNAL_RESOURCE_KEY_PREFIX
995 + secondExternalResourceLocation;
996 check.setSecondExternalResourceLocation(secondExternalResourceLocation);
997
998 checker.addFileSetCheck(check);
999 checker.configure(checkerConfig);
1000
1001 execute(checker, pathToEmptyFile);
1002 final Properties cacheAfterSecondRun = new Properties();
1003 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
1004 cacheAfterSecondRun.load(reader);
1005 }
1006
1007 final String cacheFilePath = cacheAfterSecondRun.getProperty(pathToEmptyFile);
1008 assertWithMessage("Cache file has changed its path")
1009 .that(cacheFilePath)
1010 .isEqualTo(cacheAfterFirstRun.getProperty(pathToEmptyFile));
1011 final String cacheHash = cacheAfterSecondRun.getProperty(PropertyCacheFile.CONFIG_HASH_KEY);
1012 assertWithMessage("Cache has changed its hash")
1013 .that(cacheHash)
1014 .isEqualTo(cacheAfterFirstRun.getProperty(PropertyCacheFile.CONFIG_HASH_KEY));
1015 final String resourceKey = cacheAfterSecondRun.getProperty(firstExternalResourceKey);
1016 assertWithMessage("Cache has changed its resource key")
1017 .that(resourceKey)
1018 .isEqualTo(cacheAfterFirstRun.getProperty(firstExternalResourceKey));
1019 assertWithMessage("Cache has null as a resource key")
1020 .that(cacheAfterFirstRun.getProperty(firstExternalResourceKey))
1021 .isNotNull();
1022 final int expectedNumberOfObjectsInCacheAfterSecondRun = 4;
1023 assertWithMessage("Number of items in cache differs from expected")
1024 .that(cacheAfterSecondRun)
1025 .hasSize(expectedNumberOfObjectsInCacheAfterSecondRun);
1026 assertWithMessage("Cache has not null as a resource key")
1027 .that(cacheAfterFirstRun.getProperty(secondExternalResourceKey))
1028 .isNull();
1029 assertWithMessage("Cache has null as a resource key")
1030 .that(cacheAfterSecondRun.getProperty(secondExternalResourceKey))
1031 .isNotNull();
1032 }
1033
1034 @Test
1035 public void testClearLazyLoadCacheInDetailAST() throws Exception {
1036
1037 final String filePath = getPath("InputCheckerClearDetailAstLazyLoadCache.java");
1038
1039 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
1040 verifyWithInlineConfigParser(filePath, expected);
1041 }
1042
1043 @Test
1044 public void testCacheOnViolationSuppression() throws Exception {
1045 final File cacheFile = createTempFile("junit");
1046 final DefaultConfiguration violationCheck =
1047 createModuleConfig(DummyFileSetViolationCheck.class);
1048
1049 final DefaultConfiguration filterConfig = createModuleConfig(SuppressionFilter.class);
1050 filterConfig.addProperty("file", getPath("InputCheckerSuppressAll.xml"));
1051
1052 final DefaultConfiguration checkerConfig = createRootConfig(violationCheck);
1053 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
1054 checkerConfig.addChild(filterConfig);
1055
1056 final String fileViolationPath = createTempFile("ViolationFile", ".java").getPath();
1057
1058 execute(checkerConfig, fileViolationPath);
1059
1060 try (InputStream input = Files.newInputStream(cacheFile.toPath())) {
1061 final Properties details = new Properties();
1062 details.load(input);
1063
1064 assertWithMessage("suppressed violation file saved in cache")
1065 .that(details.getProperty(fileViolationPath))
1066 .isNotNull();
1067 }
1068 }
1069
1070 @Test
1071 public void testHaltOnException() throws Exception {
1072 final DefaultConfiguration checkConfig =
1073 createModuleConfig(CheckWhichThrowsError.class);
1074 final String filePath = getPath("InputChecker.java");
1075 try {
1076 execute(checkConfig, filePath);
1077 assertWithMessage("Exception is expected").fail();
1078 }
1079 catch (CheckstyleException exc) {
1080 assertWithMessage("Error message is not expected")
1081 .that(exc.getMessage())
1082 .isEqualTo("Exception was thrown while processing " + filePath);
1083 }
1084 }
1085
1086 @Test
1087 public void testExceptionWithCache() throws Exception {
1088 final File cacheFile = createTempFile("junit");
1089
1090 final DefaultConfiguration checkConfig =
1091 createModuleConfig(CheckWhichThrowsError.class);
1092
1093 final DefaultConfiguration treewalkerConfig =
1094 createModuleConfig(TreeWalker.class);
1095 treewalkerConfig.addChild(checkConfig);
1096
1097 final DefaultConfiguration checkerConfig = createRootConfig(treewalkerConfig);
1098 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
1099 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
1100 checkerConfig.addChild(treewalkerConfig);
1101
1102 final Checker checker = createChecker(checkerConfig);
1103
1104 final String filePath = getPath("InputChecker.java");
1105 try {
1106 checker.process(Collections.singletonList(new File(filePath)));
1107 assertWithMessage("Exception is expected").fail();
1108 }
1109 catch (CheckstyleException exc) {
1110 assertWithMessage("Error message is not expected")
1111 .that(exc.getMessage())
1112 .isEqualTo("Exception was thrown while processing " + filePath);
1113
1114
1115 checker.destroy();
1116
1117 final Properties cache = new Properties();
1118 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
1119 cache.load(reader);
1120 }
1121
1122 assertWithMessage("Cache has unexpected size")
1123 .that(cache)
1124 .hasSize(1);
1125 assertWithMessage("testFile is not in cache")
1126 .that(cache.getProperty(filePath))
1127 .isNull();
1128 }
1129 }
1130
1131
1132
1133
1134
1135
1136
1137
1138 @Test
1139 public void testCatchErrorWithCache() throws Exception {
1140 final File cacheFile = createTempFile("junit");
1141
1142 final DefaultConfiguration checkerConfig = new DefaultConfiguration("configuration");
1143 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
1144 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
1145
1146 final String errorMessage = "Java Virtual Machine is broken"
1147 + " or has run out of resources necessary for it to continue operating.";
1148 final Error expectedError = new IOError(new InternalError(errorMessage));
1149
1150 final File mock = new File("testFile") {
1151 private static final long serialVersionUID = 1L;
1152
1153 @Override
1154 public String getAbsolutePath() {
1155 return "testFile";
1156 }
1157
1158
1159
1160
1161
1162
1163
1164
1165 @Override
1166 public File getAbsoluteFile() {
1167 throw expectedError;
1168 }
1169 };
1170
1171 final Checker checker = new Checker();
1172 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1173 checker.configure(checkerConfig);
1174 final List<File> filesToProcess = new ArrayList<>();
1175 filesToProcess.add(mock);
1176 try {
1177 checker.process(filesToProcess);
1178 assertWithMessage("IOError is expected!").fail();
1179 }
1180
1181 catch (Error error) {
1182 assertWithMessage("Error cause differs from IOError")
1183 .that(error.getCause())
1184 .isInstanceOf(IOError.class);
1185 assertWithMessage("Error message is not expected")
1186 .that(error)
1187 .hasCauseThat()
1188 .hasCauseThat()
1189 .hasMessageThat()
1190 .isEqualTo(errorMessage);
1191
1192
1193 checker.destroy();
1194
1195 final Properties cache = new Properties();
1196 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
1197 cache.load(reader);
1198 }
1199
1200 assertWithMessage("Cache has unexpected size")
1201 .that(cache)
1202 .hasSize(1);
1203 assertWithMessage("testFile is not in cache")
1204 .that(cache.getProperty("testFile"))
1205 .isNull();
1206 }
1207 }
1208
1209
1210
1211
1212
1213
1214
1215
1216 @Test
1217 public void testCatchErrorWithCacheWithNoFileName() throws Exception {
1218 final File cacheFile = createTempFile("junit");
1219
1220 final DefaultConfiguration checkerConfig = new DefaultConfiguration("configuration");
1221 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
1222 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
1223
1224 final String errorMessage = "Java Virtual Machine is broken"
1225 + " or has run out of resources necessary for it to continue operating.";
1226 final Error expectedError = new IOError(new InternalError(errorMessage));
1227
1228 final File mock = new File("testFile") {
1229 private static final long serialVersionUID = 1L;
1230
1231
1232
1233
1234
1235
1236
1237
1238 @Override
1239 public String getAbsolutePath() {
1240 throw expectedError;
1241 }
1242 };
1243
1244 final Checker checker = new Checker();
1245 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1246 checker.configure(checkerConfig);
1247 final List<File> filesToProcess = new ArrayList<>();
1248 filesToProcess.add(mock);
1249 try {
1250 checker.process(filesToProcess);
1251 assertWithMessage("IOError is expected!").fail();
1252 }
1253
1254 catch (Error error) {
1255 assertWithMessage("Error cause differs from IOError")
1256 .that(error)
1257 .hasCauseThat()
1258 .isInstanceOf(IOError.class);
1259 assertWithMessage("Error message is not expected")
1260 .that(error)
1261 .hasCauseThat()
1262 .hasCauseThat()
1263 .hasMessageThat()
1264 .isEqualTo(errorMessage);
1265
1266
1267 checker.destroy();
1268
1269 final Properties cache = new Properties();
1270 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
1271 cache.load(reader);
1272 }
1273
1274 assertWithMessage("Cache has unexpected size")
1275 .that(cache)
1276 .hasSize(1);
1277 }
1278 }
1279
1280
1281
1282
1283
1284
1285
1286
1287 @Test
1288 public void testExceptionWithNoFileName() {
1289 final String errorMessage = "Security Exception";
1290 final RuntimeException expectedError = new SecurityException(errorMessage);
1291
1292 final File mock = new File("testFile") {
1293 private static final long serialVersionUID = 1L;
1294
1295
1296
1297
1298
1299
1300
1301
1302 @Override
1303 public String getAbsolutePath() {
1304 throw expectedError;
1305 }
1306 };
1307
1308 final Checker checker = new Checker();
1309 final List<File> filesToProcess = new ArrayList<>();
1310 filesToProcess.add(mock);
1311 try {
1312 checker.process(filesToProcess);
1313 assertWithMessage("SecurityException is expected!").fail();
1314 }
1315 catch (CheckstyleException exc) {
1316 assertWithMessage("Error cause differs from SecurityException")
1317 .that(exc)
1318 .hasCauseThat()
1319 .isInstanceOf(SecurityException.class);
1320 assertWithMessage("Error message is not expected")
1321 .that(exc)
1322 .hasCauseThat()
1323 .hasMessageThat()
1324 .isEqualTo(errorMessage);
1325 }
1326 }
1327
1328
1329
1330
1331
1332
1333
1334
1335 @Test
1336 public void testExceptionWithCacheAndNoFileName() throws Exception {
1337 final File cacheFile = createTempFile("junit");
1338
1339 final DefaultConfiguration checkerConfig = new DefaultConfiguration("configuration");
1340 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
1341 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
1342
1343 final String errorMessage = "Security Exception";
1344 final RuntimeException expectedError = new SecurityException(errorMessage);
1345
1346 final File mock = new File("testFile") {
1347 private static final long serialVersionUID = 1L;
1348
1349
1350
1351
1352
1353
1354
1355
1356 @Override
1357 public String getAbsolutePath() {
1358 throw expectedError;
1359 }
1360 };
1361
1362 final Checker checker = new Checker();
1363 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1364 checker.configure(checkerConfig);
1365 final List<File> filesToProcess = new ArrayList<>();
1366 filesToProcess.add(mock);
1367 try {
1368 checker.process(filesToProcess);
1369 assertWithMessage("SecurityException is expected!").fail();
1370 }
1371 catch (CheckstyleException exc) {
1372 assertWithMessage("Error cause differs from SecurityException")
1373 .that(exc)
1374 .hasCauseThat()
1375 .isInstanceOf(SecurityException.class);
1376 assertWithMessage("Error message is not expected")
1377 .that(exc)
1378 .hasCauseThat()
1379 .hasMessageThat()
1380 .isEqualTo(errorMessage);
1381
1382
1383 checker.destroy();
1384
1385 final Properties cache = new Properties();
1386 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
1387 cache.load(reader);
1388 }
1389
1390 assertWithMessage("Cache has unexpected size")
1391 .that(cache)
1392 .hasSize(1);
1393 }
1394 }
1395
1396 @Test
1397 public void testHaltOnExceptionOff() throws Exception {
1398 final String filePath = getPath("InputChecker.java");
1399 final String[] expected = {
1400 "1: " + getCheckMessage(EXCEPTION_MSG, "java.lang.IndexOutOfBoundsException: test"),
1401 };
1402
1403 verifyWithInlineXmlConfig(filePath, expected);
1404 }
1405
1406 @Test
1407 public void testTabViolationDefault() throws Exception {
1408 final String[] expected = {
1409 "17:17: violation",
1410 "21:49: violation",
1411 };
1412 verifyWithInlineConfigParser(getPath("InputCheckerTabCharacter.java"),
1413 expected);
1414 }
1415
1416 @Test
1417 public void testTabViolationCustomWidth() throws Exception {
1418 final String[] expected = {
1419 "18:17: violation",
1420 "22:37: violation",
1421 };
1422
1423 verifyWithInlineXmlConfig(getPath("InputCheckerTabCharacterCustomWidth.java"), expected);
1424 }
1425
1426 @Test
1427 public void testCheckerProcessCallAllNeededMethodsOfFileSets() throws Exception {
1428 final DummyFileSet fileSet = new DummyFileSet();
1429 final Checker checker = new Checker();
1430 checker.addFileSetCheck(fileSet);
1431 checker.process(Collections.singletonList(new File("dummy.java")));
1432 final List<String> expected =
1433 Arrays.asList("beginProcessing", "finishProcessing", "destroy");
1434 assertWithMessage("Method calls were not expected")
1435 .that(fileSet.getMethodCalls())
1436 .isEqualTo(expected);
1437 }
1438
1439 @Test
1440 public void testSetFileSetCheckSetsMessageDispatcher() {
1441 final DummyFileSet fileSet = new DummyFileSet();
1442 final Checker checker = new Checker();
1443 checker.addFileSetCheck(fileSet);
1444 assertWithMessage("Message dispatcher was not expected")
1445 .that(fileSet.getInternalMessageDispatcher())
1446 .isEqualTo(checker);
1447 }
1448
1449 @Test
1450 public void testAddAuditListenerAsChild() throws Exception {
1451 final Checker checker = new Checker();
1452 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
1453 final PackageObjectFactory factory = new PackageObjectFactory(
1454 new HashSet<>(), Thread.currentThread().getContextClassLoader()) {
1455 @Override
1456 public Object createModule(String name) throws CheckstyleException {
1457 Object adapter = auditAdapter;
1458 if (!name.equals(DebugAuditAdapter.class.getName())) {
1459 adapter = super.createModule(name);
1460 }
1461 return adapter;
1462 }
1463 };
1464 checker.setModuleFactory(factory);
1465 checker.setupChild(createModuleConfig(DebugAuditAdapter.class));
1466
1467 checker.process(Collections.singletonList(new File("dummy.java")));
1468 assertWithMessage("Checker.fireAuditStarted() doesn't call listener")
1469 .that(auditAdapter.wasCalled())
1470 .isTrue();
1471 }
1472
1473 @Test
1474 public void testAddBeforeExecutionFileFilterAsChild() throws Exception {
1475 final Checker checker = new Checker();
1476 final TestBeforeExecutionFileFilter fileFilter = new TestBeforeExecutionFileFilter();
1477 final PackageObjectFactory factory = new PackageObjectFactory(
1478 new HashSet<>(), Thread.currentThread().getContextClassLoader()) {
1479 @Override
1480 public Object createModule(String name) throws CheckstyleException {
1481 Object filter = fileFilter;
1482 if (!name.equals(TestBeforeExecutionFileFilter.class.getName())) {
1483 filter = super.createModule(name);
1484 }
1485 return filter;
1486 }
1487 };
1488 checker.setModuleFactory(factory);
1489 checker.setupChild(createModuleConfig(TestBeforeExecutionFileFilter.class));
1490 checker.process(Collections.singletonList(new File("dummy.java")));
1491 assertWithMessage("Checker.acceptFileStarted() doesn't call listener")
1492 .that(fileFilter.wasCalled())
1493 .isTrue();
1494 }
1495
1496 @Test
1497 public void testFileSetCheckInitWhenAddedAsChild() throws Exception {
1498 final Checker checker = new Checker();
1499 final DummyFileSet fileSet = new DummyFileSet();
1500 final PackageObjectFactory factory = new PackageObjectFactory(
1501 new HashSet<>(), Thread.currentThread().getContextClassLoader()) {
1502 @Override
1503 public Object createModule(String name) throws CheckstyleException {
1504 Object check = fileSet;
1505 if (!name.equals(DummyFileSet.class.getName())) {
1506 check = super.createModule(name);
1507 }
1508 return check;
1509 }
1510 };
1511 checker.setModuleFactory(factory);
1512 checker.finishLocalSetup();
1513 checker.setupChild(createModuleConfig(DummyFileSet.class));
1514 assertWithMessage("FileSetCheck.init() wasn't called")
1515 .that(fileSet.isInitCalled())
1516 .isTrue();
1517 }
1518
1519
1520 @Test
1521 public void testDefaultLoggerClosesItStreams() throws Exception {
1522 final Checker checker = new Checker();
1523 try (CloseAndFlushTestByteArrayOutputStream testInfoOutputStream =
1524 new CloseAndFlushTestByteArrayOutputStream();
1525 CloseAndFlushTestByteArrayOutputStream testErrorOutputStream =
1526 new CloseAndFlushTestByteArrayOutputStream()) {
1527 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1528 checker.addListener(new DefaultLogger(testInfoOutputStream,
1529 OutputStreamOptions.CLOSE, testErrorOutputStream, OutputStreamOptions.CLOSE));
1530
1531 final File tmpFile = createTempFile("file", ".java");
1532
1533 execute(checker, tmpFile.getPath());
1534
1535 assertWithMessage("Output stream close count")
1536 .that(testInfoOutputStream.getCloseCount())
1537 .isEqualTo(1);
1538 assertWithMessage("Output stream flush count")
1539 .that(testInfoOutputStream.getFlushCount())
1540 .isEqualTo(TestUtil.adjustFlushCountForOutputStreamClose(3));
1541 assertWithMessage("Error stream close count")
1542 .that(testErrorOutputStream.getCloseCount())
1543 .isEqualTo(1);
1544 assertWithMessage("Error stream flush count")
1545 .that(testErrorOutputStream.getFlushCount())
1546 .isEqualTo(TestUtil.adjustFlushCountForOutputStreamClose(1));
1547 }
1548 }
1549
1550
1551 @Test
1552 public void testXmlLoggerClosesItStreams() throws Exception {
1553 final Checker checker = new Checker();
1554 try (CloseAndFlushTestByteArrayOutputStream testInfoOutputStream =
1555 new CloseAndFlushTestByteArrayOutputStream()) {
1556 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1557 checker.addListener(new XMLLogger(testInfoOutputStream, OutputStreamOptions.CLOSE));
1558
1559 final File tmpFile = createTempFile("file", ".java");
1560
1561 execute(checker, tmpFile.getPath(), tmpFile.getPath());
1562
1563 assertWithMessage("Output stream close count")
1564 .that(testInfoOutputStream.getCloseCount())
1565 .isEqualTo(1);
1566 assertWithMessage("Output stream flush count")
1567 .that(testInfoOutputStream.getFlushCount())
1568 .isEqualTo(TestUtil.adjustFlushCountForOutputStreamClose(0));
1569 }
1570 }
1571
1572 @Test
1573 public void testDuplicatedModule() throws Exception {
1574
1575 final DefaultConfiguration moduleConfig1 =
1576 createModuleConfig(NewlineAtEndOfFileCheck.class);
1577 final DefaultConfiguration moduleConfig2 =
1578 createModuleConfig(NewlineAtEndOfFileCheck.class);
1579 moduleConfig2.addProperty("id", "ModuleId");
1580 final DefaultConfiguration root = new DefaultConfiguration("root");
1581 root.addChild(moduleConfig1);
1582 root.addChild(moduleConfig2);
1583 final Checker checker = new Checker();
1584 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1585 checker.configure(root);
1586
1587
1588 final ByteArrayOutputStream out = TestUtil.getInternalState(this, "stream");
1589 final DefaultLogger logger = new DefaultLogger(out, OutputStreamOptions.CLOSE, out,
1590 OutputStreamOptions.NONE, new AuditEventDefaultFormatter());
1591 checker.addListener(logger);
1592
1593 final File tempFile = createTempFile("file", ".java");
1594 try (BufferedWriter bufferedWriter = Files.newBufferedWriter(tempFile.toPath())) {
1595 bufferedWriter.write(';');
1596 }
1597 final String path = tempFile.getPath();
1598 final String violationMessage =
1599 getCheckMessage(NewlineAtEndOfFileCheck.class, MSG_KEY_NO_NEWLINE_EOF);
1600 final String[] expected = {
1601 "1: " + violationMessage + " [NewlineAtEndOfFile]",
1602 "1: " + violationMessage + " [ModuleId]",
1603 };
1604
1605
1606 out.flush();
1607 final int errs = checker.process(Collections.singletonList(new File(path)));
1608 try (ByteArrayInputStream inputStream =
1609 new ByteArrayInputStream(out.toByteArray());
1610 LineNumberReader lnr = new LineNumberReader(
1611 new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
1612
1613 final List<String> actual = lnr.lines()
1614 .filter(line -> !getCheckMessage(AUDIT_STARTED_MESSAGE).equals(line))
1615 .filter(line -> !getCheckMessage(AUDIT_FINISHED_MESSAGE).equals(line))
1616 .limit(expected.length)
1617 .sorted()
1618 .collect(Collectors.toUnmodifiableList());
1619 Arrays.sort(expected);
1620
1621 for (int i = 0; i < expected.length; i++) {
1622 final String expectedResult = "[ERROR] " + path + ":" + expected[i];
1623 assertWithMessage("error message " + i)
1624 .that(actual.get(i))
1625 .isEqualTo(expectedResult);
1626 }
1627
1628 assertWithMessage("unexpected output: " + lnr.readLine())
1629 .that(errs)
1630 .isEqualTo(expected.length);
1631 }
1632
1633 checker.destroy();
1634 }
1635
1636 @Test
1637 public void testCachedFile() throws Exception {
1638 final Checker checker = createChecker(createModuleConfig(TranslationCheck.class));
1639 final OutputStream infoStream = new ByteArrayOutputStream();
1640 final OutputStream errorStream = new ByteArrayOutputStream();
1641 final DefaultLoggerWithCounter loggerWithCounter =
1642 new DefaultLoggerWithCounter(infoStream, OutputStreamOptions.CLOSE,
1643 errorStream, OutputStreamOptions.CLOSE);
1644 checker.addListener(loggerWithCounter);
1645 final File cacheFile = createTempFile("cacheFile", ".txt");
1646 checker.setCacheFile(cacheFile.getAbsolutePath());
1647
1648 final File testFile = createTempFile("testFile", ".java");
1649 final List<File> files = List.of(testFile, testFile);
1650 checker.process(files);
1651
1652 assertWithMessage("Cached file should not be processed twice")
1653 .that(loggerWithCounter.fileStartedCount)
1654 .isEqualTo(1);
1655
1656 checker.destroy();
1657 }
1658
1659 @Test
1660 public void testUnmappableCharacters() throws Exception {
1661 final String[] expected = {
1662 "14: " + getCheckMessage(LineLengthCheck.class, MSG_KEY, 80, 225),
1663 };
1664
1665 verifyWithInlineXmlConfig(getPath("InputCheckerTestCharset.java"),
1666 expected);
1667 }
1668
1669
1670
1671
1672
1673
1674
1675
1676 @SuppressForbidden
1677 @Test
1678 public void testViolationMessageOnIoException() throws Exception {
1679 final DefaultConfiguration checkConfig =
1680 createModuleConfig(CheckWhichThrowsError.class);
1681
1682 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
1683 treeWalkerConfig.addChild(checkConfig);
1684
1685 final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
1686 checkerConfig.addChild(treeWalkerConfig);
1687
1688 checkerConfig.addProperty("haltOnException", "false");
1689 final File file = new File("InputNonChecker.java");
1690 final String filePath = file.getAbsolutePath();
1691 final String[] expected = {
1692 "1: " + getCheckMessage(EXCEPTION_MSG, filePath
1693 + " (No such file or directory)"),
1694 };
1695
1696 verify(checkerConfig, filePath, expected);
1697 }
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707 @Test
1708 public void testRelativizedFileExclusion() throws Exception {
1709 final DefaultConfiguration newLineAtEndOfFileConfig =
1710 createModuleConfig(NewlineAtEndOfFileCheck.class);
1711
1712 final DefaultConfiguration beforeExecutionExclusionFileFilterConfig =
1713 createModuleConfig(BeforeExecutionExclusionFileFilter.class);
1714
1715 beforeExecutionExclusionFileFilterConfig.addProperty("fileNamePattern",
1716 "^(?!InputCheckerTestExcludeRelativizedFile.*\\.java).*");
1717
1718 final DefaultConfiguration checkerConfig = createRootConfig(null);
1719 checkerConfig.addChild(newLineAtEndOfFileConfig);
1720 checkerConfig.addChild(beforeExecutionExclusionFileFilterConfig);
1721
1722
1723 checkerConfig.addProperty("basedir",
1724 temporaryFolder.getPath());
1725
1726 final String violationMessage =
1727 getCheckMessage(NewlineAtEndOfFileCheck.class, MSG_KEY_NO_NEWLINE_EOF);
1728
1729 final String[] expected = {
1730 "1: " + violationMessage,
1731 };
1732
1733 final File tempFile = createTempFile("InputCheckerTestExcludeRelativizedFile", ".java");
1734 try (BufferedWriter bufferedWriter = Files.newBufferedWriter(tempFile.toPath())) {
1735 bufferedWriter.write(';');
1736 }
1737
1738 final File[] processedFiles = {tempFile};
1739
1740 verify(createChecker(checkerConfig), processedFiles,
1741 tempFile.getName(), expected);
1742 }
1743
1744 public static class DefaultLoggerWithCounter extends DefaultLogger {
1745
1746 private int fileStartedCount;
1747
1748 public DefaultLoggerWithCounter(OutputStream infoStream,
1749 OutputStreamOptions infoStreamOptions,
1750 OutputStream errorStream,
1751 OutputStreamOptions errorStreamOptions) {
1752 super(infoStream, infoStreamOptions, errorStream, errorStreamOptions);
1753 }
1754
1755 @Override
1756 public void fileStarted(AuditEvent event) {
1757 fileStartedCount++;
1758 }
1759 }
1760
1761 public static class DummyFilter implements Filter {
1762
1763 @Override
1764 public boolean accept(AuditEvent event) {
1765 return false;
1766 }
1767
1768 }
1769
1770 public static class DummyFileSetViolationCheck extends AbstractFileSetCheck
1771 implements ExternalResourceHolder {
1772
1773 @Override
1774 protected void processFiltered(File file, FileText fileText) {
1775 log(1, "test");
1776 }
1777
1778 @Override
1779 public Set<String> getExternalResourceLocations() {
1780 final Set<String> externalResourceLocation = new HashSet<>(1);
1781 externalResourceLocation.add("non_existent_external_resource.xml");
1782 return externalResourceLocation;
1783 }
1784
1785 }
1786
1787 public static class DummyFilterSet extends FilterSet implements ExternalResourceHolder {
1788
1789 @Override
1790 public Set<String> getExternalResourceLocations() {
1791 final Set<String> strings = new HashSet<>();
1792 strings.add("test");
1793 return strings;
1794 }
1795
1796 }
1797
1798 public static final class DynamicalResourceHolderCheck extends AbstractFileSetCheck
1799 implements ExternalResourceHolder {
1800
1801 private String firstExternalResourceLocation;
1802 private String secondExternalResourceLocation;
1803
1804 public void setFirstExternalResourceLocation(String firstExternalResourceLocation) {
1805 this.firstExternalResourceLocation = firstExternalResourceLocation;
1806 }
1807
1808 public void setSecondExternalResourceLocation(String secondExternalResourceLocation) {
1809 this.secondExternalResourceLocation = secondExternalResourceLocation;
1810 }
1811
1812 @Override
1813 protected void processFiltered(File file, FileText fileText) {
1814
1815 }
1816
1817 @Override
1818 public Set<String> getExternalResourceLocations() {
1819 final Set<String> locations = new HashSet<>();
1820 locations.add(firstExternalResourceLocation);
1821
1822 if (secondExternalResourceLocation != null) {
1823 locations.add(secondExternalResourceLocation);
1824 }
1825 return locations;
1826 }
1827
1828 }
1829
1830 public static class CheckWhichDoesNotRequireCommentNodes extends AbstractCheck {
1831
1832
1833 private static final int METHOD_DEF_CHILD_COUNT = 7;
1834
1835 @Override
1836 public int[] getDefaultTokens() {
1837 return new int[] {TokenTypes.METHOD_DEF};
1838 }
1839
1840 @Override
1841 public int[] getAcceptableTokens() {
1842 return new int[] {TokenTypes.METHOD_DEF};
1843 }
1844
1845 @Override
1846 public int[] getRequiredTokens() {
1847 return new int[] {TokenTypes.METHOD_DEF};
1848 }
1849
1850 @Override
1851 public void visitToken(DetailAST ast) {
1852 if (ast.findFirstToken(TokenTypes.MODIFIERS).findFirstToken(
1853 TokenTypes.BLOCK_COMMENT_BEGIN) != null) {
1854 log(ast, "AST has incorrect structure structure."
1855 + " The check does not require comment nodes but there were comment nodes"
1856 + " in the AST.");
1857 }
1858 final int childCount = ast.getChildCount();
1859 if (childCount != METHOD_DEF_CHILD_COUNT) {
1860 final String msg = String.format(Locale.ENGLISH,
1861 "AST node in no comment tree has wrong number of children. "
1862 + "Expected is %d but was %d",
1863 METHOD_DEF_CHILD_COUNT, childCount);
1864 log(ast, msg);
1865 }
1866
1867 int actualChildCount = 0;
1868 for (DetailAST child = ast.getFirstChild().getFirstChild(); child != null; child =
1869 child.getNextSibling()) {
1870 actualChildCount++;
1871 }
1872 final int cacheChildCount = ast.getFirstChild().getChildCount();
1873 if (cacheChildCount != actualChildCount) {
1874 final String msg = String.format(Locale.ENGLISH,
1875 "AST node with no comment has wrong number of children. "
1876 + "Expected is %d but was %d",
1877 cacheChildCount, actualChildCount);
1878 log(ast, msg);
1879 }
1880 }
1881
1882 }
1883
1884 public static class CheckWhichRequiresCommentNodes extends AbstractCheck {
1885
1886
1887 private static final int METHOD_DEF_CHILD_COUNT = 7;
1888
1889 @Override
1890 public boolean isCommentNodesRequired() {
1891 return true;
1892 }
1893
1894 @Override
1895 public int[] getDefaultTokens() {
1896 return new int[] {TokenTypes.METHOD_DEF};
1897 }
1898
1899 @Override
1900 public int[] getAcceptableTokens() {
1901 return new int[] {TokenTypes.METHOD_DEF};
1902 }
1903
1904 @Override
1905 public int[] getRequiredTokens() {
1906 return new int[] {TokenTypes.METHOD_DEF};
1907 }
1908
1909
1910 @Override
1911 public void visitToken(DetailAST ast) {
1912 if (ast.findFirstToken(TokenTypes.MODIFIERS).findFirstToken(
1913 TokenTypes.BLOCK_COMMENT_BEGIN) == null) {
1914 log(ast, "Incorrect AST structure.");
1915 }
1916 final int childCount = ast.getChildCount();
1917 if (childCount != METHOD_DEF_CHILD_COUNT) {
1918 final String msg = String.format(Locale.ENGLISH,
1919 "AST node in comment tree has wrong number of children. "
1920 + "Expected is %d but was %d",
1921 METHOD_DEF_CHILD_COUNT, childCount);
1922 log(ast, msg);
1923 }
1924
1925 int actualChildCount = 0;
1926 for (DetailAST child = ast.getFirstChild().getFirstChild(); child != null; child =
1927 child.getNextSibling()) {
1928 actualChildCount++;
1929 }
1930 final int cacheChildCount = ast.getFirstChild().getChildCount();
1931 if (cacheChildCount != actualChildCount) {
1932 final String msg = String.format(Locale.ENGLISH,
1933 "AST node with comment has wrong number of children. "
1934 + "Expected is %d but was %d",
1935 cacheChildCount, actualChildCount);
1936 log(ast, msg);
1937 }
1938 }
1939
1940 }
1941
1942 public static final class DummyFileSet extends AbstractFileSetCheck {
1943
1944 private final List<String> methodCalls = new ArrayList<>();
1945
1946 private boolean initCalled;
1947
1948 @Override
1949 public void init() {
1950 super.init();
1951 initCalled = true;
1952 }
1953
1954 @Override
1955 public void beginProcessing(String charset) {
1956 methodCalls.add("beginProcessing");
1957 super.beginProcessing(charset);
1958 }
1959
1960 @Override
1961 public void finishProcessing() {
1962 methodCalls.add("finishProcessing");
1963 super.finishProcessing();
1964 }
1965
1966 @Override
1967 protected void processFiltered(File file, FileText fileText) {
1968 methodCalls.add("processFiltered");
1969 }
1970
1971 @Override
1972 public void destroy() {
1973 methodCalls.add("destroy");
1974 super.destroy();
1975 }
1976
1977 public List<String> getMethodCalls() {
1978 return Collections.unmodifiableList(methodCalls);
1979 }
1980
1981 public boolean isInitCalled() {
1982 return initCalled;
1983 }
1984
1985 public MessageDispatcher getInternalMessageDispatcher() {
1986 return getMessageDispatcher();
1987 }
1988
1989 }
1990
1991 }