Coverage Report - com.puppycrawl.tools.checkstyle.Checker
 
Classes in this File Line Coverage Branch Coverage Complexity
Checker
100%
229/229
100%
64/64
0
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2017 the original author or authors.
 4  
 //
 5  
 // This library is free software; you can redistribute it and/or
 6  
 // modify it under the terms of the GNU Lesser General Public
 7  
 // License as published by the Free Software Foundation; either
 8  
 // version 2.1 of the License, or (at your option) any later version.
 9  
 //
 10  
 // This library is distributed in the hope that it will be useful,
 11  
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 // Lesser General Public License for more details.
 14  
 //
 15  
 // You should have received a copy of the GNU Lesser General Public
 16  
 // License along with this library; if not, write to the Free Software
 17  
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18  
 ////////////////////////////////////////////////////////////////////////////////
 19  
 
 20  
 package com.puppycrawl.tools.checkstyle;
 21  
 
 22  
 import java.io.File;
 23  
 import java.io.IOException;
 24  
 import java.io.PrintWriter;
 25  
 import java.io.StringWriter;
 26  
 import java.io.UnsupportedEncodingException;
 27  
 import java.nio.charset.Charset;
 28  
 import java.nio.charset.StandardCharsets;
 29  
 import java.util.ArrayList;
 30  
 import java.util.HashSet;
 31  
 import java.util.List;
 32  
 import java.util.Locale;
 33  
 import java.util.Set;
 34  
 import java.util.SortedSet;
 35  
 import java.util.TreeSet;
 36  
 
 37  
 import org.apache.commons.logging.Log;
 38  
 import org.apache.commons.logging.LogFactory;
 39  
 
 40  
 import com.puppycrawl.tools.checkstyle.api.AuditEvent;
 41  
 import com.puppycrawl.tools.checkstyle.api.AuditListener;
 42  
 import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
 43  
 import com.puppycrawl.tools.checkstyle.api.BeforeExecutionFileFilter;
 44  
 import com.puppycrawl.tools.checkstyle.api.BeforeExecutionFileFilterSet;
 45  
 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
 46  
 import com.puppycrawl.tools.checkstyle.api.Configuration;
 47  
 import com.puppycrawl.tools.checkstyle.api.Context;
 48  
 import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder;
 49  
 import com.puppycrawl.tools.checkstyle.api.FileSetCheck;
 50  
 import com.puppycrawl.tools.checkstyle.api.FileText;
 51  
 import com.puppycrawl.tools.checkstyle.api.Filter;
 52  
 import com.puppycrawl.tools.checkstyle.api.FilterSet;
 53  
 import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
 54  
 import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
 55  
 import com.puppycrawl.tools.checkstyle.api.RootModule;
 56  
 import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
 57  
 import com.puppycrawl.tools.checkstyle.api.SeverityLevelCounter;
 58  
 import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
 59  
 
 60  
 /**
 61  
  * This class provides the functionality to check a set of files.
 62  
  * @author Oliver Burn
 63  
  * @author <a href="mailto:stephane.bailliez@wanadoo.fr">Stephane Bailliez</a>
 64  
  * @author lkuehne
 65  
  * @author Andrei Selkin
 66  
  */
 67  
 public class Checker extends AutomaticBean implements MessageDispatcher, RootModule {
 68  
     /** Message to use when an exception occurs and should be printed as a violation. */
 69  
     public static final String EXCEPTION_MSG = "general.exception";
 70  
 
 71  
     /** Logger for Checker. */
 72  
     private final Log log;
 73  
 
 74  
     /** Maintains error count. */
 75  2022
     private final SeverityLevelCounter counter = new SeverityLevelCounter(
 76  
             SeverityLevel.ERROR);
 77  
 
 78  
     /** Vector of listeners. */
 79  2022
     private final List<AuditListener> listeners = new ArrayList<>();
 80  
 
 81  
     /** Vector of fileset checks. */
 82  2022
     private final List<FileSetCheck> fileSetChecks = new ArrayList<>();
 83  
 
 84  
     /** The audit event before execution file filters. */
 85  2022
     private final BeforeExecutionFileFilterSet beforeExecutionFileFilters =
 86  
             new BeforeExecutionFileFilterSet();
 87  
 
 88  
     /** The audit event filters. */
 89  2022
     private final FilterSet filters = new FilterSet();
 90  
 
 91  
     /** Class loader to resolve classes with. **/
 92  2022
     private ClassLoader classLoader = Thread.currentThread()
 93  2022
             .getContextClassLoader();
 94  
 
 95  
     /** The basedir to strip off in file names. */
 96  
     private String basedir;
 97  
 
 98  
     /** Locale country to report messages . **/
 99  2022
     private String localeCountry = Locale.getDefault().getCountry();
 100  
     /** Locale language to report messages . **/
 101  2022
     private String localeLanguage = Locale.getDefault().getLanguage();
 102  
 
 103  
     /** The factory for instantiating submodules. */
 104  
     private ModuleFactory moduleFactory;
 105  
 
 106  
     /** The classloader used for loading Checkstyle module classes. */
 107  
     private ClassLoader moduleClassLoader;
 108  
 
 109  
     /** The context of all child components. */
 110  
     private Context childContext;
 111  
 
 112  
     /** The file extensions that are accepted. */
 113  2022
     private String[] fileExtensions = CommonUtils.EMPTY_STRING_ARRAY;
 114  
 
 115  
     /**
 116  
      * The severity level of any violations found by submodules.
 117  
      * The value of this property is passed to submodules via
 118  
      * contextualize().
 119  
      *
 120  
      * <p>Note: Since the Checker is merely a container for modules
 121  
      * it does not make sense to implement logging functionality
 122  
      * here. Consequently Checker does not extend AbstractViolationReporter,
 123  
      * leading to a bit of duplicated code for severity level setting.
 124  
      */
 125  2022
     private SeverityLevel severityLevel = SeverityLevel.ERROR;
 126  
 
 127  
     /** Name of a charset. */
 128  2022
     private String charset = System.getProperty("file.encoding", StandardCharsets.UTF_8.name());
 129  
 
 130  
     /** Cache file. **/
 131  
     private PropertyCacheFile cache;
 132  
 
 133  
     /** Controls whether exceptions should halt execution or not. */
 134  2022
     private boolean haltOnException = true;
 135  
 
 136  
     /**
 137  
      * Creates a new {@code Checker} instance.
 138  
      * The instance needs to be contextualized and configured.
 139  
      */
 140  2022
     public Checker() {
 141  2022
         addListener(counter);
 142  2022
         log = LogFactory.getLog(Checker.class);
 143  2022
     }
 144  
 
 145  
     /**
 146  
      * Sets cache file.
 147  
      * @param fileName the cache file.
 148  
      * @throws IOException if there are some problems with file loading.
 149  
      */
 150  
     public void setCacheFile(String fileName) throws IOException {
 151  27
         final Configuration configuration = getConfiguration();
 152  27
         cache = new PropertyCacheFile(configuration, fileName);
 153  27
         cache.load();
 154  27
     }
 155  
 
 156  
     /**
 157  
      * Removes before execution file filter.
 158  
      * @param filter before execution file filter to remove.
 159  
      */
 160  
     public void removeBeforeExecutionFileFilter(BeforeExecutionFileFilter filter) {
 161  1
         beforeExecutionFileFilters.removeBeforeExecutionFileFilter(filter);
 162  1
     }
 163  
 
 164  
     /**
 165  
      * Removes filter.
 166  
      * @param filter filter to remove.
 167  
      */
 168  
     public void removeFilter(Filter filter) {
 169  1
         filters.removeFilter(filter);
 170  1
     }
 171  
 
 172  
     @Override
 173  
     public void destroy() {
 174  1927
         listeners.clear();
 175  1927
         fileSetChecks.clear();
 176  1927
         beforeExecutionFileFilters.clear();
 177  1927
         filters.clear();
 178  1927
         if (cache != null) {
 179  
             try {
 180  23
                 cache.persist();
 181  
             }
 182  1
             catch (IOException ex) {
 183  1
                 throw new IllegalStateException("Unable to persist cache file.", ex);
 184  22
             }
 185  
         }
 186  1926
     }
 187  
 
 188  
     /**
 189  
      * Removes a given listener.
 190  
      * @param listener a listener to remove
 191  
      */
 192  
     public void removeListener(AuditListener listener) {
 193  1
         listeners.remove(listener);
 194  1
     }
 195  
 
 196  
     /**
 197  
      * Sets base directory.
 198  
      * @param basedir the base directory to strip off in file names
 199  
      */
 200  
     public void setBasedir(String basedir) {
 201  3
         this.basedir = basedir;
 202  3
     }
 203  
 
 204  
     @Override
 205  
     public int process(List<File> files) throws CheckstyleException {
 206  1525
         if (cache != null) {
 207  23
             cache.putExternalResources(getExternalResourceLocations());
 208  
         }
 209  
 
 210  
         // Prepare to start
 211  1525
         fireAuditStarted();
 212  1525
         for (final FileSetCheck fsc : fileSetChecks) {
 213  1505
             fsc.beginProcessing(charset);
 214  1505
         }
 215  
 
 216  1525
         processFiles(files);
 217  
 
 218  
         // Finish up
 219  
         // It may also log!!!
 220  1517
         fileSetChecks.forEach(FileSetCheck::finishProcessing);
 221  
 
 222  
         // It may also log!!!
 223  1517
         fileSetChecks.forEach(FileSetCheck::destroy);
 224  
 
 225  1517
         final int errorCount = counter.getCount();
 226  1517
         fireAuditFinished();
 227  1517
         return errorCount;
 228  
     }
 229  
 
 230  
     /**
 231  
      * Returns a set of external configuration resource locations which are used by all file set
 232  
      * checks and filters.
 233  
      * @return a set of external configuration resource locations which are used by all file set
 234  
      *         checks and filters.
 235  
      */
 236  
     private Set<String> getExternalResourceLocations() {
 237  23
         final Set<String> externalResources = new HashSet<>();
 238  37
         fileSetChecks.stream().filter(check -> check instanceof ExternalResourceHolder)
 239  23
             .forEach(check -> {
 240  13
                 final Set<String> locations =
 241  13
                     ((ExternalResourceHolder) check).getExternalResourceLocations();
 242  13
                 externalResources.addAll(locations);
 243  13
             });
 244  31
         filters.getFilters().stream().filter(filter -> filter instanceof ExternalResourceHolder)
 245  23
             .forEach(filter -> {
 246  6
                 final Set<String> locations =
 247  6
                     ((ExternalResourceHolder) filter).getExternalResourceLocations();
 248  6
                 externalResources.addAll(locations);
 249  6
             });
 250  23
         return externalResources;
 251  
     }
 252  
 
 253  
     /** Notify all listeners about the audit start. */
 254  
     private void fireAuditStarted() {
 255  1527
         final AuditEvent event = new AuditEvent(this);
 256  1527
         for (final AuditListener listener : listeners) {
 257  3125
             listener.auditStarted(event);
 258  3125
         }
 259  1527
     }
 260  
 
 261  
     /** Notify all listeners about the audit end. */
 262  
     private void fireAuditFinished() {
 263  1519
         final AuditEvent event = new AuditEvent(this);
 264  1519
         for (final AuditListener listener : listeners) {
 265  3109
             listener.auditFinished(event);
 266  3109
         }
 267  1519
     }
 268  
 
 269  
     /**
 270  
      * Processes a list of files with all FileSetChecks.
 271  
      * @param files a list of files to process.
 272  
      * @throws CheckstyleException if error condition within Checkstyle occurs.
 273  
      * @noinspection ProhibitedExceptionThrown
 274  
      */
 275  
     private void processFiles(List<File> files) throws CheckstyleException {
 276  1525
         for (final File file : files) {
 277  
             try {
 278  1596
                 final String fileName = file.getAbsolutePath();
 279  1596
                 final long timestamp = file.lastModified();
 280  1594
                 if (cache != null && cache.isInCache(fileName, timestamp)
 281  1588
                         || !CommonUtils.matchesFileExtension(file, fileExtensions)
 282  1586
                         || !acceptFileStarted(fileName)) {
 283  9
                     continue;
 284  
                 }
 285  1585
                 if (cache != null) {
 286  16
                     cache.put(fileName, timestamp);
 287  
                 }
 288  1585
                 fireFileStarted(fileName);
 289  1585
                 final SortedSet<LocalizedMessage> fileMessages = processFile(file);
 290  1579
                 fireErrors(fileName, fileMessages);
 291  1579
                 fireFileFinished(fileName);
 292  
             }
 293  
             // -@cs[IllegalCatch] There is no other way to deliver filename that was under
 294  
             // processing. See https://github.com/checkstyle/checkstyle/issues/2285
 295  7
             catch (Exception ex) {
 296  
                 // We need to catch all exceptions to put a reason failure (file name) in exception
 297  7
                 throw new CheckstyleException("Exception was thrown while processing "
 298  7
                         + file.getPath(), ex);
 299  
             }
 300  1
             catch (Error error) {
 301  
                 // We need to catch all errors to put a reason failure (file name) in error
 302  1
                 throw new Error("Error was thrown while processing " + file.getPath(), error);
 303  1579
             }
 304  1579
         }
 305  1517
     }
 306  
 
 307  
     /**
 308  
      * Processes a file with all FileSetChecks.
 309  
      * @param file a file to process.
 310  
      * @return a sorted set of messages to be logged.
 311  
      * @throws CheckstyleException if error condition within Checkstyle occurs.
 312  
      * @noinspection ProhibitedExceptionThrown
 313  
      */
 314  
     private SortedSet<LocalizedMessage> processFile(File file) throws CheckstyleException {
 315  1585
         final SortedSet<LocalizedMessage> fileMessages = new TreeSet<>();
 316  
         try {
 317  1585
             final FileText theText = new FileText(file.getAbsoluteFile(), charset);
 318  1576
             for (final FileSetCheck fsc : fileSetChecks) {
 319  1566
                 fileMessages.addAll(fsc.process(file, theText));
 320  1559
             }
 321  
         }
 322  9
         catch (final IOException ioe) {
 323  9
             log.debug("IOException occurred.", ioe);
 324  18
             fileMessages.add(new LocalizedMessage(0,
 325  
                     Definitions.CHECKSTYLE_BUNDLE, EXCEPTION_MSG,
 326  9
                     new String[] {ioe.getMessage()}, null, getClass(), null));
 327  
         }
 328  
         // -@cs[IllegalCatch] There is no other way to obey haltOnException field
 329  7
         catch (Exception ex) {
 330  7
             if (haltOnException) {
 331  6
                 throw ex;
 332  
             }
 333  
 
 334  1
             log.debug("Exception occurred.", ex);
 335  
 
 336  1
             final StringWriter sw = new StringWriter();
 337  1
             final PrintWriter pw = new PrintWriter(sw, true);
 338  
 
 339  1
             ex.printStackTrace(pw);
 340  
 
 341  2
             fileMessages.add(new LocalizedMessage(0,
 342  
                     Definitions.CHECKSTYLE_BUNDLE, EXCEPTION_MSG,
 343  1
                     new String[] {sw.getBuffer().toString()},
 344  1
                     null, getClass(), null));
 345  1578
         }
 346  1579
         return fileMessages;
 347  
     }
 348  
 
 349  
     /**
 350  
      * Check if all before execution file filters accept starting the file.
 351  
      *
 352  
      * @param fileName
 353  
      *            the file to be audited
 354  
      * @return {@code true} if the file is accepted.
 355  
      */
 356  
     private boolean acceptFileStarted(String fileName) {
 357  1586
         final String stripped = CommonUtils.relativizeAndNormalizePath(basedir, fileName);
 358  1586
         return beforeExecutionFileFilters.accept(stripped);
 359  
     }
 360  
 
 361  
     /**
 362  
      * Notify all listeners about the beginning of a file audit.
 363  
      *
 364  
      * @param fileName
 365  
      *            the file to be audited
 366  
      */
 367  
     @Override
 368  
     public void fireFileStarted(String fileName) {
 369  1587
         final String stripped = CommonUtils.relativizeAndNormalizePath(basedir, fileName);
 370  1587
         final AuditEvent event = new AuditEvent(this, stripped);
 371  1587
         for (final AuditListener listener : listeners) {
 372  3247
             listener.fileStarted(event);
 373  3247
         }
 374  1587
     }
 375  
 
 376  
     /**
 377  
      * Notify all listeners about the errors in a file.
 378  
      *
 379  
      * @param fileName the audited file
 380  
      * @param errors the audit errors from the file
 381  
      */
 382  
     @Override
 383  
     public void fireErrors(String fileName, SortedSet<LocalizedMessage> errors) {
 384  1606
         final String stripped = CommonUtils.relativizeAndNormalizePath(basedir, fileName);
 385  1606
         boolean hasNonFilteredViolations = false;
 386  1606
         for (final LocalizedMessage element : errors) {
 387  72070
             final AuditEvent event = new AuditEvent(this, stripped, element);
 388  72070
             if (filters.accept(event)) {
 389  72057
                 hasNonFilteredViolations = true;
 390  72057
                 for (final AuditListener listener : listeners) {
 391  144567
                     listener.addError(event);
 392  144567
                 }
 393  
             }
 394  72070
         }
 395  1606
         if (hasNonFilteredViolations && cache != null) {
 396  5
             cache.remove(fileName);
 397  
         }
 398  1606
     }
 399  
 
 400  
     /**
 401  
      * Notify all listeners about the end of a file audit.
 402  
      *
 403  
      * @param fileName
 404  
      *            the audited file
 405  
      */
 406  
     @Override
 407  
     public void fireFileFinished(String fileName) {
 408  1602
         final String stripped = CommonUtils.relativizeAndNormalizePath(basedir, fileName);
 409  1602
         final AuditEvent event = new AuditEvent(this, stripped);
 410  1602
         for (final AuditListener listener : listeners) {
 411  3280
             listener.fileFinished(event);
 412  3280
         }
 413  1602
     }
 414  
 
 415  
     @Override
 416  
     public void finishLocalSetup() throws CheckstyleException {
 417  1994
         final Locale locale = new Locale(localeLanguage, localeCountry);
 418  1994
         LocalizedMessage.setLocale(locale);
 419  
 
 420  1994
         if (moduleFactory == null) {
 421  
 
 422  1989
             if (moduleClassLoader == null) {
 423  1
                 throw new CheckstyleException(
 424  
                         "if no custom moduleFactory is set, "
 425  
                                 + "moduleClassLoader must be specified");
 426  
             }
 427  
 
 428  1988
             final Set<String> packageNames = PackageNamesLoader
 429  1988
                     .getPackageNames(moduleClassLoader);
 430  1988
             moduleFactory = new PackageObjectFactory(packageNames,
 431  
                     moduleClassLoader);
 432  
         }
 433  
 
 434  1993
         final DefaultContext context = new DefaultContext();
 435  1993
         context.add("charset", charset);
 436  1993
         context.add("classLoader", classLoader);
 437  1993
         context.add("moduleFactory", moduleFactory);
 438  1993
         context.add("severity", severityLevel.getName());
 439  1993
         context.add("basedir", basedir);
 440  1993
         childContext = context;
 441  1993
     }
 442  
 
 443  
     /**
 444  
      * {@inheritDoc} Creates child module.
 445  
      * @noinspection ChainOfInstanceofChecks
 446  
      */
 447  
     @Override
 448  
     protected void setupChild(Configuration childConf)
 449  
             throws CheckstyleException {
 450  1992
         final String name = childConf.getName();
 451  
         final Object child;
 452  
 
 453  
         try {
 454  1992
             child = moduleFactory.createModule(name);
 455  
 
 456  1992
             if (child instanceof AutomaticBean) {
 457  1986
                 final AutomaticBean bean = (AutomaticBean) child;
 458  1986
                 bean.contextualize(childContext);
 459  1986
                 bean.configure(childConf);
 460  
             }
 461  
         }
 462  38
         catch (final CheckstyleException ex) {
 463  38
             throw new CheckstyleException("cannot initialize module " + name
 464  38
                     + " - " + ex.getMessage(), ex);
 465  1951
         }
 466  1951
         if (child instanceof FileSetCheck) {
 467  1928
             final FileSetCheck fsc = (FileSetCheck) child;
 468  1928
             fsc.init();
 469  1928
             addFileSetCheck(fsc);
 470  1928
         }
 471  23
         else if (child instanceof BeforeExecutionFileFilter) {
 472  4
             final BeforeExecutionFileFilter filter = (BeforeExecutionFileFilter) child;
 473  4
             addBeforeExecutionFileFilter(filter);
 474  4
         }
 475  19
         else if (child instanceof Filter) {
 476  16
             final Filter filter = (Filter) child;
 477  16
             addFilter(filter);
 478  16
         }
 479  3
         else if (child instanceof AuditListener) {
 480  2
             final AuditListener listener = (AuditListener) child;
 481  2
             addListener(listener);
 482  2
         }
 483  
         else {
 484  1
             throw new CheckstyleException(name
 485  
                     + " is not allowed as a child in Checker");
 486  
         }
 487  1950
     }
 488  
 
 489  
     /**
 490  
      * Adds a FileSetCheck to the list of FileSetChecks
 491  
      * that is executed in process().
 492  
      * @param fileSetCheck the additional FileSetCheck
 493  
      */
 494  
     public void addFileSetCheck(FileSetCheck fileSetCheck) {
 495  1933
         fileSetCheck.setMessageDispatcher(this);
 496  1933
         fileSetChecks.add(fileSetCheck);
 497  1933
     }
 498  
 
 499  
     /**
 500  
      * Adds a before execution file filter to the end of the event chain.
 501  
      * @param filter the additional filter
 502  
      */
 503  
     public void addBeforeExecutionFileFilter(BeforeExecutionFileFilter filter) {
 504  8
         beforeExecutionFileFilters.addBeforeExecutionFileFilter(filter);
 505  8
     }
 506  
 
 507  
     /**
 508  
      * Adds a filter to the end of the audit event filter chain.
 509  
      * @param filter the additional filter
 510  
      */
 511  
     public void addFilter(Filter filter) {
 512  21
         filters.addFilter(filter);
 513  21
     }
 514  
 
 515  
     @Override
 516  
     public final void addListener(AuditListener listener) {
 517  3649
         listeners.add(listener);
 518  3649
     }
 519  
 
 520  
     /**
 521  
      * Sets the file extensions that identify the files that pass the
 522  
      * filter of this FileSetCheck.
 523  
      * @param extensions the set of file extensions. A missing
 524  
      *     initial '.' character of an extension is automatically added.
 525  
      */
 526  
     public final void setFileExtensions(String... extensions) {
 527  9
         if (extensions == null) {
 528  1
             fileExtensions = null;
 529  
         }
 530  
         else {
 531  8
             fileExtensions = new String[extensions.length];
 532  25
             for (int i = 0; i < extensions.length; i++) {
 533  17
                 final String extension = extensions[i];
 534  17
                 if (CommonUtils.startsWithChar(extension, '.')) {
 535  2
                     fileExtensions[i] = extension;
 536  
                 }
 537  
                 else {
 538  15
                     fileExtensions[i] = "." + extension;
 539  
                 }
 540  
             }
 541  
         }
 542  9
     }
 543  
 
 544  
     /**
 545  
      * Sets the factory for creating submodules.
 546  
      *
 547  
      * @param moduleFactory the factory for creating FileSetChecks
 548  
      */
 549  
     public void setModuleFactory(ModuleFactory moduleFactory) {
 550  10
         this.moduleFactory = moduleFactory;
 551  10
     }
 552  
 
 553  
     /**
 554  
      * Sets locale country.
 555  
      * @param localeCountry the country to report messages
 556  
      */
 557  
     public void setLocaleCountry(String localeCountry) {
 558  2
         this.localeCountry = localeCountry;
 559  2
     }
 560  
 
 561  
     /**
 562  
      * Sets locale language.
 563  
      * @param localeLanguage the language to report messages
 564  
      */
 565  
     public void setLocaleLanguage(String localeLanguage) {
 566  2
         this.localeLanguage = localeLanguage;
 567  2
     }
 568  
 
 569  
     /**
 570  
      * Sets the severity level.  The string should be one of the names
 571  
      * defined in the {@code SeverityLevel} class.
 572  
      *
 573  
      * @param severity  The new severity level
 574  
      * @see SeverityLevel
 575  
      */
 576  
     public final void setSeverity(String severity) {
 577  2
         severityLevel = SeverityLevel.getInstance(severity);
 578  2
     }
 579  
 
 580  
     /**
 581  
      * Sets the classloader that is used to contextualize fileset checks.
 582  
      * Some Check implementations will use that classloader to improve the
 583  
      * quality of their reports, e.g. to load a class and then analyze it via
 584  
      * reflection.
 585  
      * @param classLoader the new classloader
 586  
      */
 587  
     public final void setClassLoader(ClassLoader classLoader) {
 588  12
         this.classLoader = classLoader;
 589  12
     }
 590  
 
 591  
     @Override
 592  
     public final void setModuleClassLoader(ClassLoader moduleClassLoader) {
 593  1991
         this.moduleClassLoader = moduleClassLoader;
 594  1991
     }
 595  
 
 596  
     /**
 597  
      * Sets a named charset.
 598  
      * @param charset the name of a charset
 599  
      * @throws UnsupportedEncodingException if charset is unsupported.
 600  
      */
 601  
     public void setCharset(String charset)
 602  
             throws UnsupportedEncodingException {
 603  1360
         if (!Charset.isSupported(charset)) {
 604  1
             final String message = "unsupported charset: '" + charset + "'";
 605  1
             throw new UnsupportedEncodingException(message);
 606  
         }
 607  1359
         this.charset = charset;
 608  1359
     }
 609  
 
 610  
     /**
 611  
      * Sets the field haltOnException.
 612  
      * @param haltOnException the new value.
 613  
      */
 614  
     public void setHaltOnException(boolean haltOnException) {
 615  2
         this.haltOnException = haltOnException;
 616  2
     }
 617  
 
 618  
     /**
 619  
      * Clears the cache.
 620  
      */
 621  
     public void clearCache() {
 622  3
         if (cache != null) {
 623  2
             cache.reset();
 624  
         }
 625  3
     }
 626  
 }