[Solved] Including shared checkstyle.xml from jar dependency

While trying to use a shared (i.e. from a jar dependency) checkstyle.xml, I seem to be hitting a road block where I can’t cast the data correctly.

My layout is this:

  1. I have a jar with a checkstyle.xml at the root of the jar.
  2. I have the aforementioned jar as a compileOnly dependency.
dependencies {
  compileOnly group: 'com.companyname', name: 'checkstyle', version: '1.0-SNAPSHOT'
  ...
}
  1. I have a checkstyle config where I try to set the value for config (the value of rules is not null, it does contain the text from the checkstyle.xml file)
checkstyle {
  toolVersion = '8.6'
  def classLoader = new URLClassLoader(sourceSets.main.compileClasspath.collect { it.toURI().toURL() } as URL[])
  def rules = classLoader.getResource('checkstyle.xml').getText()
  config = rules
}
  1. Here is the console output:
./gradlew clean build --info
Initialized native services in: /Users/mdelaney/.gradle/native
The client will now receive all logging from the daemon (pid: 2076). The daemon log file: /Users/mdelaney/.gradle/daemon/5.2/daemon-2076.out.log
Starting 163rd build in daemon [uptime: 2 hrs 51 mins 17.032 secs, performance: 99%, GC rate: 0.13/s, tenured heap usage: 17% of 358.1 MB]
Using 8 worker leases.
Starting Build
Settings evaluated using settings file '<working directory>/settings.gradle'.
Projects loaded. Root project using build file '<working directory>/build.gradle'.
Included projects: [root project 'xwt']

> Configure project :
Evaluating root project 'xwt' using build file '<working directory>/build.gradle'.
Compiling build file '<working directory>/build.gradle' using SubsetScriptTransformer.
Compiling build file '<working directory>/build.gradle' using BuildScriptTransformer.
java.net.URL

FAILURE: Build failed with an exception.

* Where:
Build file '<working directory>/build.gradle' line: 80

* What went wrong:
A problem occurred evaluating root project 'xwt'.
> Cannot cast object '<?xml version="1.0"?>
  <!DOCTYPE module PUBLIC
      "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
      "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
  
  <!--
  
    Checkstyle configuration that checks the sun coding conventions from:
  
      - the Java Language Specification at
        http://java.sun.com/docs/books/jls/second_edition/html/index.html
  
      - the Sun Code Conventions at http://java.sun.com/docs/codeconv/
  
      - the Javadoc guidelines at
        http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
  
      - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html
  
      - some best practices
  
    Checkstyle is very configurable. Be sure to read the documentation at
    http://checkstyle.sf.net (or in your downloaded distribution).
  
    Most Checks are configurable, be sure to consult the documentation.
  
    To completely disable a check, just comment it out or delete it from the file.
  
    Finally, it is worth reading the documentation.
  
  -->
  
  <module name="Checker">
      <!--
          If you set the basedir property below, then all reported file
          names will be relative to the specified directory. See
          http://checkstyle.sourceforge.net/5.x/config.html#Checker
  
          <property name="basedir" value="${basedir}"/>
      -->
  
      <!-- Checks that a package-info.java file exists for each package.     -->
      <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage -->
      <module name="JavadocPackage"/>
  
      <!-- Checks whether files end with a new line.                        -->
      <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
      <module name="NewlineAtEndOfFile"/>
  
      <!-- Checks that property files contain the same keys.         -->
      <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
      <module name="Translation"/>
  
      <!-- Checks for Size Violations.                    -->
      <!-- See http://checkstyle.sf.net/config_sizes.html -->
      <module name="FileLength"/>
  
      <!-- Checks for whitespace                               -->
      <!-- See http://checkstyle.sf.net/config_whitespace.html -->
      <module name="FileTabCharacter"/>
  
      <!-- Miscellaneous other checks.                   -->
      <!-- See http://checkstyle.sf.net/config_misc.html -->
      <module name="RegexpSingleline">
         <property name="format" value="\s+$"/>
         <property name="minimum" value="0"/>
         <property name="maximum" value="0"/>
         <property name="message" value="Line has trailing spaces."/>
      </module>
  
      <module name="TreeWalker">
  
          <!-- Checks for Javadoc comments.                     -->
          <!-- See http://checkstyle.sf.net/config_javadoc.html -->
          <module name="JavadocMethod"/>
          <module name="JavadocType"/>
          <module name="JavadocVariable"/>
          <module name="JavadocStyle"/>
  
  
          <!-- Checks for Naming Conventions.                  -->
          <!-- See http://checkstyle.sf.net/config_naming.html -->
          <module name="ConstantName"/>
          <module name="LocalFinalVariableName"/>
          <module name="LocalVariableName"/>
          <module name="MemberName"/>
          <module name="MethodName"/>
          <module name="PackageName"/>
          <module name="ParameterName"/>
          <module name="StaticVariableName"/>
          <module name="TypeName"/>
  
  
          <!-- Checks for Headers                                -->
          <!-- See http://checkstyle.sf.net/config_header.html   -->
          <!-- <module name="Header">                            -->
              <!-- The follow property value demonstrates the ability     -->
              <!-- to have access to ANT properties. In this case it uses -->
              <!-- the ${basedir} property to allow Checkstyle to be run  -->
              <!-- from any directory within a project. See property      -->
              <!-- expansion,                                             -->
              <!-- http://checkstyle.sf.net/config.html#properties        -->
              <!-- <property                                              -->
              <!--     name="headerFile"                                  -->
              <!--     value="${basedir}/java.header"/>                   -->
          <!-- </module> -->
  
          <!-- Following interprets the header file as regular expressions. -->
          <!-- <module name="RegexpHeader"/>                                -->
  
  
          <!-- Checks for imports                              -->
          <!-- See http://checkstyle.sf.net/config_import.html -->
          <module name="AvoidStarImport"/>
          <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
          <module name="RedundantImport"/>
          <module name="UnusedImports"/>
  
  
          <!-- Checks for Size Violations.                    -->
          <!-- See http://checkstyle.sf.net/config_sizes.html -->
          <module name="LineLength"/>
          <module name="MethodLength"/>
          <module name="ParameterNumber"/>
  
  
          <!-- Checks for whitespace                               -->
          <!-- See http://checkstyle.sf.net/config_whitespace.html -->
          <module name="EmptyForIteratorPad"/>
          <module name="GenericWhitespace"/>
          <module name="MethodParamPad"/>
          <module name="NoWhitespaceAfter"/>
          <module name="NoWhitespaceBefore"/>
          <module name="OperatorWrap"/>
          <module name="ParenPad"/>
          <module name="TypecastParenPad"/>
          <module name="WhitespaceAfter"/>
          <module name="WhitespaceAround"/>
  
  
          <!-- Modifier Checks                                    -->
          <!-- See http://checkstyle.sf.net/config_modifiers.html -->
          <module name="ModifierOrder"/>
          <module name="RedundantModifier"/>
  
  
          <!-- Checks for blocks. You know, those {}'s         -->
          <!-- See http://checkstyle.sf.net/config_blocks.html -->
          <module name="AvoidNestedBlocks"/>
          <module name="EmptyBlock"/>
          <module name="LeftCurly"/>
          <module name="NeedBraces"/>
          <module name="RightCurly"/>
  
  
          <!-- Checks for common coding problems               -->
          <!-- See http://checkstyle.sf.net/config_coding.html -->
          <module name="AvoidInlineConditionals"/>
          <module name="DoubleCheckedLocking"/>    <!-- MY FAVOURITE -->
          <module name="EmptyStatement"/>
          <module name="EqualsHashCode"/>
          <module name="HiddenField"/>
          <module name="IllegalInstantiation"/>
          <module name="InnerAssignment"/>
          <module name="MagicNumber"/>
          <module name="MissingSwitchDefault"/>
          <module name="RedundantThrows"/>
          <module name="SimplifyBooleanExpression"/>
          <module name="SimplifyBooleanReturn"/>
  
          <!-- Checks for class design                         -->
          <!-- See http://checkstyle.sf.net/config_design.html -->
          <module name="DesignForExtension"/>
          <module name="FinalClass"/>
          <module name="HideUtilityClassConstructor"/>
          <module name="InterfaceIsType"/>
          <module name="VisibilityModifier"/>
  
  
          <!-- Miscellaneous other checks.                   -->
          <!-- See http://checkstyle.sf.net/config_misc.html -->
          <module name="ArrayTypeStyle"/>
          <module name="FinalParameters"/>
          <module name="TodoComment"/>
          <module name="UpperEll"/>
  
      </module>
  
  </module>
  ' with class 'java.lang.String' to class 'org.gradle.api.resources.TextResource'

* Try:
Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 0s
Exit 1

What am I doing wrong here?

Your types are wrong. Effectively, you’re doing this:

String rules = classLoader.getResource("checkstyle.xml").getText();
TextResource config = rules;

A String can’t be assigned to a TextResource, but you can easily get a TextResource with the String as the value by using the TextResourceFactory (resources.text):

checkstyle {
    toolVersion = '8.6'
    def classLoader = new URLClassLoader(sourceSets.main.compileClasspath.collect { it.toURI().toURL() } as URL[])
    def rules = classLoader.getResource('checkstyle.xml').getText()
    config = resources.text.fromString(rules)
}

Awesome. Thanks for the info. I’ll give that a shot.