Checkstyle config file from dependency jar - gradle

I am trying to apply the checkstyle plugin to my gradle project. The configuration of which is in a seperate, shared jar dependency:
project.apply plugin: StaticAnalysisPlugin
class StaticAnalysisPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.apply plugin: 'checkstyle'
project.configurations {
codingStandardsConfig
}
project.dependencies {
codingStandardsConfig 'com.sample.tools:coding-standards:1.+:#jar'
}
def checkstyleConfigFileLocation = "classpath:sample-checkstyle-config.xml"
project.checkstyle {
toolVersion = '6.3'
project.logger.debug "$project Using checkstyle version $toolVersion."
project.logger.debug "$project Using checkstyle config from: ${checkstyleConfigFileLocation}"
config = project.resources.text.fromFile(checkstyleConfigFileLocation)
}
project.checkstyleMain.source = "src/main/java"
project.checkstyleTest.exclude "**/*"
}
}
the config file is located in the coding-standards jar, but I am unsure how to wire this in to the checkstyle config.

I think you should use the configFile option (which expects a File object) rather than the config option (which expects a text resource with your actual configuration).
Then the problem comes down to determining the correct File object. From this answer, it seems you can do
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("file/test.xml").getFile());
Alternative solutions can be found on StackOverflow. Make sure that the class loader's class path includes your coding-standards.jar. You may have to put that dependency in a buildscript block to make it available, well, to the build script.

Related

Gradle get dependency programatically without configuration

Is there an option to get Maven dependency in Gradle without using custom configuration for it? For example in custom plugin to just obtain dependency provided from extension? Something like
class DependencyPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create("deps", DepsExtension)
project.task('useDependency') {
doLast {
//use Gradle api to resolve dependency without custom configuration
project.resolve(project.deps.dependency)
}
}
}
}
class DepsExtension {
def dependency = 'custom:maven:1.0'
}
Something like this:
Configuration config = project.configurations.create('myPrivateConfig')
Dependency dep = project.dependencies.create('custom:maven:1.0') {
exclude group: 'foo', module: 'bar'
}
config.dependencies.add(dep)
Set<File> files = config.files
I do a similar thing in a gradle plugin here
References
https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/Configuration.html
https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/DependencySet.html
https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/dsl/DependencyHandler.html

How do I set task properties in a Gradle Plugin

I am creating a gradle plugin to apply the sonar-runner plugin and default many of the values such as the sonar host URL and the sonar JDBC URL. I cannot figure out how to set the properties though.
When I set this up in build.gradle I use:
apply plugin: 'sonar-runner'
sonarRunner {
sonarProperties {
property 'sonar.host.url', 'http://mySonar.company.com'
property 'sonar.jdbc.url', 'jdbc:mysql://127.0.0.1:1234/sonar'
}
}
My gradle plugin looks like:
class MySonarPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.apply plugin: 'sonar-runner'
project.configurations {
sonarRunner {
sonarProperties {
property 'sonar.host.url', 'http://mySonar.company.com'
property 'sonar.jdbc.url', 'jdbc:mysql://127.0.0.1:1234/sonar'
}
}
}
}
}
With this setup I get a No signature of method exception. How should I be setting these properties?
I discovered that I could use project.getExtensions().sonarRunner.sonarProperties{ ... } to set the sonar properties. See example below.
class MySonarPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.apply plugin:'sonar-runner'
project.getExtensions().sonarRunner.sonarProperties {
property 'sonar.host.url', 'http://mySonar.company.com'
property 'sonar.jdbc.url', 'jdbc:mysql://127.0.0.1:1234/sonar'
}
}
}
Thank you #mikerylander and #ravikanth! I also had tried the setProperty and .properties solutions but they didn't work for me.
The really tricky thing was that autocomplete did not find the "sonarqube" portion of project.getExtensions().sonarqube.properties for me so I never got to this solution without your post.
I wrote a custom Gradle plugin to run sonarqube for a multi-module Android project and your post helped me. Below is my full custom plugin. Since the plugin is designed to be included in the build.gradle of any submodule of my Android project I prepended "my_product" ${project.path} but of course you can use any values here.
Here is my complete plugin code in case its helpful:
package com.example.gradle.plugins
import org.gradle.api.Plugin
import org.gradle.api.Project
class MySonarCodeCoveragePlugin implements Plugin<Project> {
private Project project
void apply(Project project) {
this.project = project
project.apply plugin: 'org.sonarqube'
project.getExtensions().sonarqube.properties
{
property "sonar.sources", "${project.projectDir}/src/main"
property "sonar.organization", "my_org"
property "sonar.projectKey", "my_product${project.path}"
property "sonar.projectName", "my_product${project.path}"
property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/jacocoTestReport/jacocoTestReport.xml"
property "sonar.scanner.metadataFilePath", "${project.buildDir}/sonar/report-task.txt"
}
}
}

Do gradle configurations merge or override?

Say I define a plugin, like so:
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.Project
import org.gradle.api.Plugin
class MyRepos implements Plugin<Project> {
static final String NEXUS_URL = 'http://nexus.mine.com/nexus/content/repositories/'
static final List<String> NEXUS_REPOS = [
'central',
'build',
'snapshots',
'release-candidates',
'releases',
]
void apply(Project project) {
project.repositories {
NEXUS_REPOS.each {
maven {
url (NEXUS_URL + it)
}
}
mavenLocal()
}
project.buildscript {
repositories {
maven {
url (NEXUS_URL + 'central')
}
mavenLocal()
}
}
}
}
and in a local build.gradle, I write
apply plugin: MyRepos
buildscript {
dependencies {
...
}
}
My desire is for the two buildscript sections to be merged such that the repositories are defined in the plugin and the dependencies in build.gradle, but it appears that the local declaration overrides the plugin and I end up with an error indicating "no repositories defined".
If I do this via configuration injection from the top level build.gradle, is the result the same?
Maybe the right solution is for the plugin to provide an ext closure to define useMyRepos() similar to the way mavenCentral() is used...
Generally configuration items in gradle are merged so you can apply configurations in different locations. You can, for example, configure some of the dependencies in one build script that will be applied to another build script that will add additional dependencies.
However, your case is a bit different since you're using buildScript configuration which is can be used to define the dependencies for the build script itself rather than the root repositories node which is intended for defining the dependencies of the project you build.
In this case, according to Purpose of buildScript in Gradle as these are different configurations you'll have to define your dependency twice.

How to apply a Gradle plugin from another plugin?

I'm trying to encapsulate android plugin in my own plugin, but when I'm trying to apply my plugin build fails with an exception:
A problem occurred evaluating root project 'myproj'.
> Failed to apply plugin [id 'com.mycomp.build']
> Failed to apply plugin [id 'android-library']
> Plugin with id 'android-library' not found.
Here is how I'm applying android plugin inside my own plugin's implementation:
// build.gradle
apply plugin: 'groovy'
version = '1.0'
group = 'com.mycomp'
dependencies {
compile gradleApi()
compile localGroovy()
}
// Build.groovy
package com.mycomp
import org.gradle.api.Plugin
import org.gradle.api.Project
class Build implements Plugin<Project> {
void apply(Project project) {
println 'Hello from com.mycomp.Build'
project.beforeEvaluate {
buildscript.configurations.classpath +=
'com.android.tools.build:gradle:1.0.0-rc1'
}
project.configure(project) {
buildscript.repositories.mavenCentral()
apply plugin: 'android-library'
}
}
}
For some reason a classpath is not being properly loaded, what am I doing wrong?
I guess that at the time you'd like to add the plugin dependencies for the build script have been already resolved, thus it won't work that way. You need to specify the plugin You'd like to apply as a script dependency itself.
It will work that way:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0-rc1'
}
}
apply plugin: 'groovy'
apply plugin: Build
version = '1.0'
group = 'com.mycomp'
dependencies {
compile gradleApi()
compile localGroovy()
}
import org.gradle.api.Plugin
import org.gradle.api.Project
class Build implements Plugin<Project> {
void apply(Project project) {
project.configure(project) {
apply plugin: 'android-library'
}
}
}
Now, android-plugin is found but it fails because of the fact that groovy plugin had been applied earlier and there's a conflict.
Use the project's PluginManager. For example, the war plugin pulls in the java plugin like this:
public class WarPlugin implements Plugin<Project> {
// ...
public void apply(final Project project) {
project.getPluginManager().apply(org.gradle.api.plugins.JavaPlugin.class);
// ...
}
// ...
}

Why Does gradle eclipseClasspath task does not include transitive project dependencies?

I created a simple example(the names don't really mean anything):
folder structure:
gradleMultiProject
build.gradle
core
build.gradle
src
main
java
Core.java
database
build.gradle
src
main
java
Database.java
settings.gradle
webapp
build.gradle
src
main
java
Webapp.java
Below are the files mentioned above:
build.gradle (root gradle build file under gradleMultiProject folder)
subprojects {
apply plugin: 'java'
apply plugin: 'eclipse'
}
settings.gradle
include 'core', 'database', 'webapp'
gradleMultiProject\core\src\main\java\Core.java
package main.java;
public class Core
{
public static String HELLO_MESSAGE = "hello world!";
}
Core's build.gradle
task hello {
println "hello from core!"
}
gradleMultiProject\database\src\main\java\Database.java
package main.java;
public class Database
{
public void saveMessage()
{
System.out.println(Core.HELLO_MESSAGE);
}
}
Database's build.gradle
dependencies {
compile project(':core')
}
gradleMultiProject\webapp\src\main\java
package main.java;
public class Webapp
{
public static void main(String[] args)
{
Database database = new Database();
database.saveMessage();
System.out.println(Core.HELLO_MESSAGE);
}
}
Webapp's build.gradle
dependencies {
compile project(':database')
}
Gradle compiles everything just fine(gradle build). It even lists the transitive dependencies just fine(gradle dependencies). But when I try to generate a .classpath file(gradle eclipseClasspath) for the webapp project it doesn't include core. WHY?!?!?!?!?!
Actually this isn't a problem because eclipse "exports" core in database. What that means is that it will show up in any project that require the database project.
I just created this exact project and ran "gradle eclipse" and there are no build errors because the webapp project requires the database project and the database project requires and exports the core project. To see more look at the build path in eclipse.

Resources