Accessing configuration files from a custom gradle plugin


(Rory Gallagher) #1

Hello

I have a suite of microservices that are stored in individual Bitbucket projects

In order to avoid duplication in each of these projects, I’ve created a suite of custom gradle plugins so I can have the default build logic in one location and easily apply this logic to each project.

The plugins are divided into modular components:
root-plugin to set up the default library definitions (extensions)
publishing-plugin to set up the default publishing behavour and handle transitive dependencies through pom definitions
coding standards plugin to set up the coding standards process
etc, etc

In my coding standards plugin I have the following code:

apply plugin: 'java’
apply plugin: ‘checkstyle’

checkstyle {
toolVersion = "6.12.1"
configFile = file(’/config/checkstyle/checkstyle.xml’)
}

The checkstyle.xml file is contained in the src/main/resources/config/checkstyle file within the coding standards plugin project.

When I apply this plugin in another project it looks for the file within that project.

Is there any way that I can make this look for the config file within the plugin?

Or do I need to add the config file as a dependency in the pom definition when publishing the plugin?

Many Thanks


(Rory Gallagher) #2

Since there’s been no reply I thought I’d show the workaround that I implemented last week just in case it helps someone else out

I couldn’t find a way to have the project calling the plugin to access the file in the plugin and I didn’t want to have to define this configuration file in every project calling the plugin. I want the configuration to be stored in one place - the plugin

So the workaround was to add a task to my plugin to build the config file for every project calling the plugin

package com.aerlingus.plugin.coding.standards.tasks

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction

/**

  • A custom task to build the checkstyle configuration file for each project.
    */
    class BuildCheckstyleConfigFile extends DefaultTask {

    @TaskAction
    def buildCheckstyleConfigFile() {

     // Checkstyle expects the file to be in this location by convention
     def file = project.file('/config/checkstyle/checkstyle.xml')
    
     // Create the file if it does not exist
     if (!file.exists()) {
    
         file.parentFile.mkdirs()
         file.write "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                 "<!DOCTYPE module PUBLIC \"-//Puppy Crawl//DTD Check Configuration 1.3//EN\" \"http://www.puppycrawl.com/dtds/configuration_1_3.dtd\">\n" +
    
                 "<!--\n" +
                 "    Checkstyle configuration that checks the Google coding conventions from:\n" +
                 "\n" +
                 "    -  Google Java Style\n" +
                 "       https://google-styleguide.googlecode.com/svn-history/r130/trunk/javaguide.html\n" +
                 "\n" +
                 "    Checkstyle is very configurable. Be sure to read the documentation at\n" +
                 "    http://checkstyle.sf.net (or in your downloaded distribution).\n" +
                 "\n" +
                 "    Most Checks are configurable, be sure to consult the documentation.\n" +
                 "\n" +
                 "    To completely disable a check, just comment it out or delete it from the file.\n" +
                 "\n" +
                 "    Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.\n" +
                 " -->\n" +
    
                 "<module name=\"Checker\">\n" +
                 "    <property name=\"charset\" value=\"UTF-8\" />\n" +
                 "    <property name=\"severity\" value=\"warning\" />\n" +
                 "    <property name=\"fileExtensions\" value=\"java, properties, xml\" />\n" +
                 "    <!-- Checks for whitespace                               -->\n" +
                 "    <!-- See http://checkstyle.sf.net/config_whitespace.html -->\n" +
                 "    <module name=\"FileTabCharacter\">\n" +
                 "        <property name=\"eachLine\" value=\"true\" />\n" +
                 "    </module>\n" +
                 "    <module name=\"TreeWalker\">\n" +
                 "        <module name=\"OuterTypeFilename\" />\n" +
                 "        <module name=\"IllegalTokenText\">\n" +
                 "            <property name=\"tokens\" value=\"STRING_LITERAL, CHAR_LITERAL\" />\n" +
                 "            <property name=\"format\" value=\"\\\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\\\(0(10|11|12|14|15|42|47)|134)\" />\n" +
                 "            <property name=\"message\" value=\"Avoid using corresponding octal or Unicode escape.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"AvoidEscapedUnicodeCharacters\">\n" +
                 "            <property name=\"allowEscapesForControlCharacters\" value=\"true\" />\n" +
                 "            <property name=\"allowByTailComment\" value=\"true\" />\n" +
                 "            <property name=\"allowNonPrintableEscapes\" value=\"true\" />\n" +
                 "            <property name=\"allowIfAllCharactersEscaped\" value=\"true\"/>\n" +
                 "        </module>\n" +
                 "        <module name=\"LineLength\">\n" +
                 "            <property name=\"max\" value=\"130\" />\n" +
                 "            <property name=\"ignorePattern\" value=\"^package.*|^import.*\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"AvoidStarImport\" />\n" +
                 "        <module name=\"OneTopLevelClass\" />\n" +
                 "        <module name=\"NoLineWrap\" />\n" +
                 "        <module name=\"NeedBraces\" />\n" +
                 "        <module name=\"LeftCurly\">\n" +
                 "            <property name=\"maxLineLength\" value=\"130\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"WhitespaceAround\">\n" +
                 "            <property name=\"allowEmptyConstructors\" value=\"true\" />\n" +
                 "            <property name=\"allowEmptyMethods\" value=\"true\" />\n" +
                 "            <property name=\"allowEmptyTypes\" value=\"true\" />\n" +
                 "            <property name=\"allowEmptyLoops\" value=\"true\" />\n" +
                 "            <message key=\"ws.notFollowed\" value=\"WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)\" />\n" +
                 "            <message key=\"ws.notPreceded\" value=\"WhitespaceAround: ''{0}'' is not preceded with whitespace.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"OneStatementPerLine\" />\n" +
                 "        <module name=\"MultipleVariableDeclarations\" />\n" +
                 "        <module name=\"ArrayTypeStyle\" />\n" +
                 "        <module name=\"MissingSwitchDefault\" />\n" +
                 "        <module name=\"FallThrough\" />\n" +
                 "        <module name=\"UpperEll\" />\n" +
                 "        <module name=\"ModifierOrder\" />\n" +
                 "        <module name=\"EmptyLineSeparator\">\n" +
                 "            <property name=\"allowNoEmptyLineBetweenFields\" value=\"true\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"SeparatorWrap\">\n" +
                 "            <property name=\"tokens\" value=\"DOT\" />\n" +
                 "            <property name=\"option\" value=\"nl\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"SeparatorWrap\">\n" +
                 "            <property name=\"tokens\" value=\"COMMA\" />\n" +
                 "            <property name=\"option\" value=\"EOL\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"PackageName\">\n" +
                 "            <property name=\"format\" value=\"^[a-z]+(\\.[a-z][a-z0-9]*)*\$\" />\n" +
                 "            <message key=\"name.invalidPattern\" value=\"Package name ''{0}'' must match pattern ''{1}''.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"TypeName\">\n" +
                 "            <message key=\"name.invalidPattern\" value=\"Type name ''{0}'' must match pattern ''{1}''.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"MemberName\">\n" +
                 "            <property name=\"format\" value=\"^[a-z][a-z0-9][a-zA-Z0-9]*\$\" />\n" +
                 "            <message key=\"name.invalidPattern\" value=\"Member name ''{0}'' must match pattern ''{1}''.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"ParameterName\">\n" +
                 "            <property name=\"format\" value=\"^[a-z][a-z0-9][a-zA-Z0-9]*\$\" />\n" +
                 "            <message key=\"name.invalidPattern\" value=\"Parameter name ''{0}'' must match pattern ''{1}''.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"LocalVariableName\">\n" +
                 "            <property name=\"tokens\" value=\"VARIABLE_DEF\" />\n" +
                 "            <property name=\"format\" value=\"^[a-z][a-z0-9][a-zA-Z0-9]*\$\" />\n" +
                 "            <property name=\"allowOneCharVarInForLoop\" value=\"true\" />\n" +
                 "            <message key=\"name.invalidPattern\" value=\"Local variable name ''{0}'' must match pattern ''{1}''.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"ClassTypeParameterName\">\n" +
                 "            <property name=\"format\" value=\"(^[A-Z][0-9]?)\$|([A-Z][a-zA-Z0-9]*[T]\$)\" />\n" +
                 "            <message key=\"name.invalidPattern\" value=\"Class type name ''{0}'' must match pattern ''{1}''.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"MethodTypeParameterName\">\n" +
                 "            <property name=\"format\" value=\"(^[A-Z][0-9]?)\$|([A-Z][a-zA-Z0-9]*[T]\$)\" />\n" +
                 "            <message key=\"name.invalidPattern\" value=\"Method type name ''{0}'' must match pattern ''{1}''.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"NoFinalizer\" />\n" +
                 "        <module name=\"GenericWhitespace\">\n" +
                 "            <message key=\"ws.followed\" value=\"GenericWhitespace ''{0}'' is followed by whitespace.\" />\n" +
                 "            <message key=\"ws.preceded\" value=\"GenericWhitespace ''{0}'' is preceded with whitespace.\" />\n" +
                 "            <message key=\"ws.illegalFollow\" value=\"GenericWhitespace ''{0}'' should followed by whitespace.\" />\n" +
                 "            <message key=\"ws.notPreceded\" value=\"GenericWhitespace ''{0}'' is not preceded with whitespace.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"Indentation\">\n" +
                 "            <property name=\"basicOffset\" value=\"2\" />\n" +
                 "            <property name=\"braceAdjustment\" value=\"0\" />\n" +
                 "            <property name=\"caseIndent\" value=\"2\" />\n" +
                 "            <property name=\"throwsIndent\" value=\"4\" />\n" +
                 "            <property name=\"lineWrappingIndentation\" value=\"4\" />\n" +
                 "            <property name=\"arrayInitIndent\" value=\"2\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"AbbreviationAsWordInName\">\n" +
                 "            <property name=\"ignoreFinal\" value=\"false\" />\n" +
                 "            <property name=\"allowedAbbreviationLength\" value=\"4\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"OverloadMethodsDeclarationOrder\" />\n" +
                 "        <module name=\"VariableDeclarationUsageDistance\" />\n" +
                 "        <module name=\"CustomImportOrder\">\n" +
                 "            <property name=\"specialImportsRegExp\" value=\"com.google\" />\n" +
                 "            <property name=\"sortImportsInGroupAlphabetically\" value=\"true\" />\n" +
                 "            <property name=\"customImportOrderRules\" value=\"STATIC###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"OperatorWrap\">\n" +
                 "            <property name=\"option\" value=\"NL\" />\n" +
                 "            <property name=\"tokens\" value=\"BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR \" />\n" +
                 "        </module>\n" +
                 "        <module name=\"AnnotationLocation\">\n" +
                 "            <property name=\"tokens\" value=\"CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"AnnotationLocation\">\n" +
                 "            <property name=\"tokens\" value=\"VARIABLE_DEF\" />\n" +
                 "            <property name=\"allowSamelineMultipleAnnotations\" value=\"true\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"JavadocTagContinuationIndentation\" />\n" +
                 "        <module name=\"SummaryJavadocCheck\">\n" +
                 "            <property name=\"forbiddenSummaryFragments\" value=\"^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"JavadocParagraph\" />\n" +
                 "        <module name=\"AtclauseOrder\">\n" +
                 "            <property name=\"tagOrder\" value=\"@param, @return, @throws, @deprecated\" />\n" +
                 "            <property name=\"target\" value=\"CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"MethodName\">\n" +
                 "            <property name=\"format\" value=\"^[a-z][a-z0-9][a-zA-Z0-9_]*\$\" />\n" +
                 "            <message key=\"name.invalidPattern\" value=\"Method name ''{0}'' must match pattern ''{1}''.\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"SingleLineJavadoc\" />\n" +
                 "        <module name=\"EmptyCatchBlock\">\n" +
                 "            <property name=\"exceptionVariableName\" value=\"expected\" />\n" +
                 "        </module>\n" +
                 "        <!-- ##### Sun checks ##### -->\n" +
                 "        <!-- Checks for Javadoc comments.                     -->\n" +
                 "        <!-- See http://checkstyle.sf.net/config_javadoc.html -->\n" +
                 "        <module name=\"JavadocMethod\">\n" +
                 "            <property name=\"allowMissingPropertyJavadoc\" value=\"true\" />\n" +
                 "            <property name=\"minLineCount\" value=\"2\" />\n" +
                 "            <property name=\"allowedAnnotations\" value=\"Override, Test\" />\n" +
                 "            <property name=\"allowThrowsTagsForSubclasses\" value=\"true\" />\n" +
                 "            <property name=\"allowMissingParamTags\" value=\"true\" />\n" +
                 "            <property name=\"scope\" value=\"nothing\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"JavadocType\" />\n" +
                 "        <module name=\"JavadocVariable\">\n" +
                 "            <property name=\"ignoreNamePattern\" value=\".*\" />\n" +
                 "        </module>\n" +
                 "        <module name=\"JavadocStyle\" >\n" +
                 "            <property name=\"checkFirstSentence\" value=\"true\" />\n" +
                 "        </module>\n" +
                 "        <!-- Checks for Naming Conventions.                  -->\n" +
                 "        <!-- See http://checkstyle.sf.net/config_naming.html -->\n" +
                 "        <module name=\"ConstantName\" />\n" +
                 "        <module name=\"LocalFinalVariableName\" />\n" +
                 "        <module name=\"StaticVariableName\" />\n" +
                 "        <!-- Checks for imports                              -->\n" +
                 "        <!-- See http://checkstyle.sf.net/config_import.html -->\n" +
                 "        <module name=\"IllegalImport\" />\n" +
                 "        <!-- defaults to sun.* packages -->\n" +
                 "        <module name=\"RedundantImport\" />\n" +
                 "        <module name=\"UnusedImports\" />\n" +
                 "        <!-- Checks for Size Violations.                    -->\n" +
                 "        <!-- See http://checkstyle.sf.net/config_sizes.html -->\n" +
                 "        <module name=\"MethodLength\" />\n" +
                 "        <module name=\"ParameterNumber\" />\n" +
                 "        <!-- Checks for whitespace                               -->\n" +
                 "        <!-- See http://checkstyle.sf.net/config_whitespace.html -->\n" +
                 "        <module name=\"EmptyForIteratorPad\" />\n" +
                 "        <module name=\"GenericWhitespace\" />\n" +
                 "        <module name=\"NoWhitespaceAfter\" />\n" +
                 "        <module name=\"NoWhitespaceBefore\" />\n" +
                 "        <module name=\"ParenPad\" />\n" +
                 "        <module name=\"TypecastParenPad\" />\n" +
                 "        <module name=\"WhitespaceAfter\" />\n" +
                 "        <!-- Modifier Checks                                    -->\n" +
                 "        <!-- See http://checkstyle.sf.net/config_modifiers.html -->\n" +
                 "        <module name=\"RedundantModifier\" />\n" +
                 "        <!-- Checks for blocks. You know, those {}'s         -->\n" +
                 "        <!-- See http://checkstyle.sf.net/config_blocks.html -->\n" +
                 "        <module name=\"AvoidNestedBlocks\" />\n" +
                 "        <module name=\"EmptyBlock\" />\n" +
                 "        <module name=\"LeftCurly\" />\n" +
                 "        <module name=\"NeedBraces\" />\n" +
                 "        <module name=\"RightCurly\" />\n" +
                 "        <!-- Checks for common coding problems               -->\n" +
                 "        <!-- See http://checkstyle.sf.net/config_coding.html -->\n" +
                 "        <module name=\"AvoidInlineConditionals\" />\n" +
                 "        <module name=\"EmptyStatement\" />\n" +
                 "        <module name=\"EqualsHashCode\" />\n" +
                 "        <module name=\"IllegalInstantiation\" />\n" +
                 "        <module name=\"InnerAssignment\" />\n" +
                 "        <module name=\"MagicNumber\" />\n" +
                 "        <module name=\"SimplifyBooleanExpression\" />\n" +
                 "        <module name=\"SimplifyBooleanReturn\" />\n" +
                 "        <!-- Checks for class design                         -->\n" +
                 "        <!-- See http://checkstyle.sf.net/config_design.html -->\n" +
                 "        <module name=\"FinalClass\" />\n" +
                 "        <module name=\"HideUtilityClassConstructor\" />\n" +
                 "        <module name=\"InterfaceIsType\" />\n" +
                 "        <module name=\"VisibilityModifier\" />\n" +
                 "        <!-- Miscellaneous other checks.                   -->\n" +
                 "        <!-- See http://checkstyle.sf.net/config_misc.html -->\n" +
                 "        <module name=\"FinalParameters\" />\n" +
                 "        <module name=\"TodoComment\" />\n" +
                 "        <!-- Ignoring possible hidden fields for constructors and setters.                   -->\n" +
                 "        <module name=\"HiddenField\" >\n" +
                 "            <property name=\"ignoreSetter\" value=\"true\" />\n" +
                 "            <property name=\"ignoreConstructorParameter\" value=\"true\" />\n" +
                 "            <property name=\"setterCanReturnItsClass\" value=\"true\"/>\n" +
                 "        </module>\n" +
                 "    </module>\n" +
                 "</module>"
     }
    

    }
    }

package com.aerlingus.plugin.coding.standards

import com.aerlingus.plugin.coding.standards.tasks.BuildCheckstyleConfigFile
import com.aerlingus.plugin.coding.standards.tasks.VerifyNoCheckstyleViolations
import org.gradle.api.Plugin
import org.gradle.api.Project

/**

  • This is our coding standards plugin.

  • It can be injected into other obe builds as a plugin.
    */
    public class CodingStandardsPlugin implements Plugin {

    @Override
    public void apply(Project project) {

     // Configure the coding standards
     configureCodingStandards(project)
    

    }

    // Configure the coding standards
    private void configureCodingStandards(Project project) {

     // Add a custom tasks for checkstyle.
     project.task('buildCheckstyleConfigFile', type: BuildCheckstyleConfigFile)
     project.task('verifyNoCheckstyleViolations', type: VerifyNoCheckstyleViolations)
    
     project.configure(project) {
         apply plugin: 'java'
         apply plugin: 'checkstyle'
         apply plugin: 'findbugs'
         apply plugin: 'pmd'
         apply plugin: 'jacoco'
         apply plugin: 'jdepend'
    
         /**
          * FindBugs Section.
          * FindBugs uses static analysis to look for bugs in Java code.
          */
         findbugs {
             ignoreFailures = false
         }
    
         /**
          * PMD Section.
          * PMD is a source code analyzer that finds common programming flaws
          * like unused variables, empty catch blocks, and unnecessary object creation.
          */
         pmd {
             toolVersion = "5.3.5"
             ignoreFailures = false
         }
    
         /**
          * Checkstyle Section.
          * Checkstyle can check many aspects of your source code.
          * It can find class design problems, method design problems.
          * It also has the ability to check code layout and formatting issues.
          */
         checkstyle {
             toolVersion = "6.12.1"
         }
    
         // Build the checkstyle config file if it doesn't exist.
         checkstyleMain.dependsOn buildCheckstyleConfigFile
         checkstyleTest.dependsOn buildCheckstyleConfigFile
    
         // Fail the build on any checkstyle violations.
         check.finalizedBy verifyNoCheckstyleViolations
     }
    

    }
    }

It’s ugly but it works

I’d prefer a cleaner solution if anyone has any suggestions

Cheers


(Negi) #3

I am also trying to achieve similar thing(having multiple micro-service) which have common gradle task and dependency used. I want to write a custom gradle plugin which will hold all common task and dependency and then I can apply that custom plugin to each micro-services.
But don’t know how to get started.Can you help in achieving the same.
Thanks in advance.


(Rory Gallagher) #4

I have several plugins in a gradle plugin project

  • A root plugin which gives access to all library dfinitions and nexus credentials etc
  • A versioning plugin that handles all version control logic
  • A coding standards plugin that enforces findbugs, checkstyle etc in a build
  • A test plugin that contains all standard logic for unit tests, library definitions etc
  • A publishing plugin to publish artefacts to Nexus
  • A swagger plugin that provides logic to generate code from swagger definitions (top down approach)
  • A sonar plugin that provides a task to run sonarqube against the current gradle project/module
  • A Java plugin that applies all of the plugins above as well as the gradle Java plugin (specifying src and targets)
  • A war plugin that applies the Java plugin and the gradle war plugin as well as some custom scripts

The way this is set up, a non-Java project can still avail of any of the custom plugins without applying the Java plugin. While a Java or war plugin only needs to apply one plugin and they are up and running with all of the bells and whistles.

As a basic step I will give the details for the ei-root-plugin

Create a root-plugin gradle module with the following structure:
src/main/groovy
src/main/resources

In the resources folder create the following folder:
META-INF.gradle-plugins

In this folder create the following file
com.whatever.root-plugin.properties

This is what defines your module as a gradle plugin
In this file specify the implementation class for the plugin

implementation-class=com.whatever.plugin.root.RootPlugin

Now create this (groovy) class in the groovy folder
com.whatever.plugin.root.RootPlugin

package com.whatever.plugin.root

import com.whatever.plugin.root.extensions.LibrariesExtension
import com.whatever.plugin.root.extensions.NexusExtension
import org.gradle.api.Plugin
import org.gradle.api.Project

/**

  • This is the root gradle build for all projects.

  • It can be injected into other builds as a plugin.
    */
    public class RootPlugin implements Plugin {

    @Override
    public void apply(final Project project) {
    if (null == project.extensions.findByName(“nexus”)) {
    addExtensions(project)
    addRepositories(project)
    }
    }

    // Add the root propject extensions
    private void addExtensions(final Project project) {
    project.extensions.create(“nexus”, NexusExtension)
    project.extensions.create(“libraries”, LibrariesExtension)
    }

    // Add the root project repositories
    private void addRepositories(final Project project) {
    project.repositories {
    maven { url “$project.nexus.nexusServer/nexus/content/repositories/releases/” }
    maven { url “$project.nexus.nexusServer/nexus/content/repositories/snapshots/” }
    maven { url “$project.nexus.nexusServer/nexus/content/repositories/public/” }
    }
    }
    }

You can see here that I’ve added extension folders to contain the library and nexus definitions
Create the package in com.whatever.plugin.root.extensions
Create the groovy class LibrariesExtension

package com.whatever.plugin.root.extensions

/**

  • Libraries Extension.

  • Needed for access to root plugin variables.
    */
    public class LibrariesExtension {

    // Spring
    def spring_version = '4.3.3.RELEASE’
    def spring_core = "org.springframework:spring-core:${spring_version}"
    def spring_web = "org.springframework:spring-web:${spring_version}"
    def spring_test = "org.springframework:spring-test:${spring_version}"
    def spring_jdbc = "org.springframework:spring-jdbc:${spring_version}"
    def spring_context = "org.springframework:spring-context:${spring_version}"
    def spring_support = "org.springframework:spring-context-support:${spring_version}"
    def spring_webmvc = "org.springframework:spring-webmvc:${spring_version}"
    def spring_tx = "org.springframework:spring-tx:${spring_version}"
    def spring_aop = "org.springframework:spring-aop:${spring_version}"
    def spring_beans = "org.springframework:spring-beans:${spring_version}"
    def spring_expression = "org.springframework:spring-expression:${spring_version}"
    def spring_oxm = “org.springframework:spring-oxm:${spring_version}”

    // Spring Security
    def spring_security_version = "3.2.9.RELEASE"
    def spring_security_web = "org.springframework.security:spring-security-web:${spring_security_version}"
    def spring_security_config = “org.springframework.security:spring-security-config:${spring_security_version}”

You can add whatever library definitions you need in here

Next create the NexusExtension groovy class

package com.whatever.plugin.root.extensions

/**

  • Nexus Extension.

  • Needed for access to root plugin variables.
    */
    public class NexusExtension {

    def nexusUser = "username"
    def nexusPassword = "password"
    def nexusServer = “nexus url”
    }

That’s it at it’s most basic. Just publish this to Nexus or whatever you use and you can pull the root plugin down in other modules

To do this open the project that you want to use the gradle plugin and create a gradle.properties folder
Add the following to do to specify the version of the plugin and the nexus server to find this plugin

Nexus host

nexusServer=http://whateveryour server is

Plugin versions

rootPluginVersion=1.0.0-SNAPSHOT

In the build.gradle you need to add a buildscript dependency so your gradle buildscript has access to your plugin. Buildscripts need to be at the top of your build.gradle file

buildscript {
repositories {
maven { url “$nexusServer/nexus/content/repositories/releases/” }
maven { url “$nexusServer/nexus/content/repositories/snapshots/” }
maven { url “$nexusServer/nexus/content/repositories/public/” }
}

dependencies {
    classpath "com.whatever:root-plugin:$rootPluginVersion"
}

}

Next apply the plugin:

apply plugin: ‘com.whatever.root-plugin’

Now you can access anything from the root plugin:

dependencies {

// common libraries
compile project.libraries.spring_context
compile project.libraries.findbugs_annotations
compile project.libraries.javax_servlet
compile project.libraries.castor_dlex
compile project.libraries.mscf
compile project.libraries.jini_ext_dlex
compile project.libraries.jini_core_dlex
compile project.libraries.ojdbc
compile project.libraries.reggie_dlex
compile project.libraries.commons_collections

}

project is the key word here
libraries is defined in your root plugin

// Add the root propject extensions
private void addExtensions(final Project project) {
    project.extensions.create("nexus", NexusExtension)
    project.extensions.create("libraries", LibrariesExtension)
}

To access nexus you would use
project.nexus.nexusPassword

If your library definitions were

// Add the root propject extensions
private void addExtensions(final Project project) {
    project.extensions.create("nnnnn", NexusExtension)
    project.extensions.create("libs", LibrariesExtension)
}

To access libraries you would use
project.libs.spring_context

To access nexus you would use
project.nnnnn.nexusPassword

Hope that helps


(Negi) #5

Appreciate your quick response.Will try implementing the same.


(uklance) #6

Any files in src/main/resources of the plugin will be available via the plugin classloader at runtime. If you require it as a file you could copy it locally to the project (eg under $buildDir)

Eg:

task copyCheckstyle {
    doLast {
        mkdir "$buildDir/checkstyleConfig"
        file("$buildDir/checkstyleConfig/checkstyle.xml").text = MyPlugin.getResource('/config/checkstyle/checkstyle.xml').text
   }
} 
task checkstyle(type: Checkstyle) {
    dependsOn copyCheckstyle
    configFile "$buildDir/checkstyleConfig/checkstyle.xml"
   ...
} 

(Rory Gallagher) #7

Thanks for the info. That looks cleaner than what I have. I’ll give it a go