polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From paulmer...@apache.org
Subject [10/35] zest-java git commit: build: move build logic from build scripts to plugins in buildSrc
Date Sat, 19 Nov 2016 22:50:11 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/dist/DistributionPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/dist/DistributionPlugin.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/dist/DistributionPlugin.groovy
new file mode 100644
index 0000000..fc4e23d
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/dist/DistributionPlugin.groovy
@@ -0,0 +1,375 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.zest.gradle.dist
+
+import groovy.transform.CompileStatic
+import groovy.transform.TypeCheckingMode
+import org.apache.rat.gradle.RatTask
+import org.apache.tools.ant.filters.ReplaceTokens
+import org.apache.zest.gradle.RootProjectPlugin
+import org.apache.zest.gradle.dependencies.DependenciesPlugin
+import org.apache.zest.gradle.release.ReleaseSpecExtension
+import org.apache.zest.gradle.release.ReleaseSpecPlugin
+import org.gradle.api.Action
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.file.CopySpec
+import org.gradle.api.file.FileCopyDetails
+import org.gradle.api.tasks.Copy
+import org.gradle.api.tasks.GradleBuild
+import org.gradle.api.tasks.bundling.Compression
+import org.gradle.api.tasks.bundling.Tar
+import org.gradle.api.tasks.bundling.Zip
+
+@CompileStatic
+class DistributionPlugin implements Plugin<Project>
+{
+  static class TaskGroups
+  {
+    static final String DISTRIBUTION = 'Distribution'
+    static final String DISTRIBUTION_VERIFICATION = 'Distribution verification'
+  }
+
+  static class TaskNames
+  {
+    static final String UNPACK_SOURCE_DIST = 'unpackSrcDist'
+    static final String UNPACK_BINARY_DIST = 'unpackBinDist'
+    static final String CHECK_SOURCE_DIST = 'checkSrcDist'
+    static final String CHECK_BINARY_DIST = 'checkBinDist'
+    static final String CHECK_BINARY_DIST_RAT = 'checkBinDist_rat'
+    static final String GENERATE_MAVEN_OFFLINE_HELPERS = 'generateMavenGoOfflineHelpers'
+    static final String GENERATE_GRADLE_OFFLINE_HELPERS = 'generateGradleGoOfflineHelpers'
+    static final String CHECK_MAVEN_OFFLINE_HELPERS = 'checkMavenGoOfflineHelpers'
+    static final String CHECK_GRADLE_OFFLINE_HELPERS = 'checkGradleGoOfflineHelpers'
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    configureSourceDistribution( project )
+    configureBinaryDistribution( project )
+    configureDistributionChecksums( project )
+    configureHelperTasks( project )
+  }
+
+  private static void configureSourceDistribution( Project project )
+  {
+    def releaseSpec = project.extensions.getByType( ReleaseSpecExtension )
+    def srcDistFilesCopySpec = project.copySpec { CopySpec spec ->
+      spec.from '.'
+      spec.include '*.txt'
+      spec.include 'doap.rdf'
+      spec.include '*.gradle'
+      spec.include 'gradlew*'
+      spec.include 'gradle/**'
+      spec.include 'etc/**'
+      spec.include 'buildSrc/**'
+      spec.include 'src/**'
+      releaseSpec.approvedProjects.each { p ->
+        def relPath = new File( project.projectDir.toURI().relativize( p.projectDir.toURI() ).toString() )
+        spec.include "$relPath/**"
+      }
+      spec.include 'manual/**'
+      spec.include 'samples/**'
+      spec.include 'tests/**'
+      spec.include 'tutorials/**'
+      spec.include 'tools/shell/**'
+      // Filtered, see below
+      spec.exclude 'settings.gradle'
+      spec.exclude 'gradle.properties'
+      // Excludes
+      spec.exclude '**/build/**'             // Build output
+      spec.exclude 'derby.log'               // Derby test garbage
+      spec.exclude '**/*.iml'                // IDEA files
+      spec.exclude '**/*.ipr'                // IDEA files
+      spec.exclude '**/*.iws'                // IDEA files
+      spec.exclude '**/.idea'                // IDEA files
+      spec.exclude '**/out/**'               // IDEA build output
+      spec.exclude '**/.classpath'           // Eclipse files
+      spec.exclude '**/.project'             // Eclipse files
+      spec.exclude '**/.settings'            // Eclipse files
+      spec.exclude '**/.nb-gradle/**'        // Netbeans files
+      spec.exclude '**/.nb-gradle*'          // Netbeans files
+      spec.exclude '**/.git/**'              // Git directories
+      spec.exclude '**/.git*'                // Git files
+      spec.exclude '**/.gradle/**'           // Gradle management files
+      spec.exclude '**/.gradletasknamecache' // Gradle cache
+      spec.into '.'
+    }
+    def srcDistFilteredFilesTask = project.tasks.create( 'srcDistFilteredFiles' )
+    // Generates various files for the source distribution
+    // - settings.gradle
+    // - gradle.properties to set version !
+    def filteredDir = new File( "$project.buildDir/tmp/srcDistFilteredFiles" )
+    srcDistFilteredFilesTask.outputs.file filteredDir
+    srcDistFilteredFilesTask.doLast {
+      // Settings
+      def settingsFile = new File( filteredDir, 'settings.gradle' )
+      settingsFile.parentFile.mkdirs()
+      def filteredSettings = ''
+      project.file( 'settings.gradle' ).readLines().each { line ->
+        if( line.contains( '\'libraries:' ) || line.contains( '\'extensions:' ) || line.contains( '\'tools:' ) )
+        {
+          def accepted = false
+          releaseSpec.approvedProjects.collect { it.projectDir }.each { acceptedProjectDir ->
+            if( line.contains( "'${ acceptedProjectDir.parentFile.name }:${ acceptedProjectDir.name }'" ) )
+            {
+              accepted = true
+            }
+          }
+          if( accepted )
+          {
+            filteredSettings += "$line\n"
+          }
+        }
+        else
+        {
+          filteredSettings += "$line\n"
+        }
+      }
+      settingsFile.text = filteredSettings
+      // gradle.properties
+      def gradlePropsFile = new File( filteredDir, 'gradle.properties' )
+      gradlePropsFile.parentFile.mkdirs()
+      gradlePropsFile.text = project.file( 'gradle.properties' ).text +
+                             "\nskipSigning=true\nskipAsciidocIfAbsent=true\n\nversion=$project.version\n"
+    }
+    def srcDistFilteredFilesCopySpec = project.copySpec { CopySpec spec ->
+      spec.from srcDistFilteredFilesTask
+      spec.into '.'
+    }
+    def srcDistCopySpec = project.copySpec { CopySpec spec ->
+      spec.into "apache-zest-java-$project.version-src"
+      spec.with srcDistFilesCopySpec
+      spec.with srcDistFilteredFilesCopySpec
+    }
+
+    def zipSources = project.tasks.create( 'zipSources', Zip ) { Zip task ->
+      task.baseName = 'apache-zest-java'
+      task.with srcDistCopySpec
+      task.classifier = 'src'
+    }
+    def tarSources = project.tasks.create( 'tarSources', Tar ) { Tar task ->
+      task.baseName = 'apache-zest-java'
+      task.with srcDistCopySpec
+      task.compression = Compression.GZIP
+      task.classifier = 'src'
+    }
+    project.artifacts.add( 'archives', zipSources )
+    project.artifacts.add( 'archives', tarSources )
+
+    project.tasks.create( TaskNames.UNPACK_SOURCE_DIST, Copy ) { Copy task ->
+      task.description = "Unpack the source distribution"
+      task.group = TaskGroups.DISTRIBUTION
+      task.with srcDistCopySpec
+      task.into 'build/unpacked-distributions/src'
+    }
+
+    def unpackedSrcDistDir = project.file( "build/unpacked-distributions/src/apache-zest-java-$project.version-src" )
+    project.tasks.create( TaskNames.CHECK_SOURCE_DIST, GradleBuild.class, { GradleBuild task ->
+      task.description = "Check the source distribution by running the 'check' and 'assemble' tasks inside"
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.dependsOn TaskNames.UNPACK_SOURCE_DIST
+      task.buildFile = "$unpackedSrcDistDir/build.gradle"
+      task.tasks = [ 'check', 'assemble' ]
+    } as Action<GradleBuild> )
+  }
+
+  private static void configureBinaryDistribution( Project project )
+  {
+    configureGoOfflineHelpers( project )
+
+    def releaseSpec = project.extensions.getByType( ReleaseSpecExtension )
+    def reportsDistCopySpec = project.copySpec { CopySpec spec ->
+      spec.from "$project.buildDir/reports"
+      spec.into 'docs/reports'
+    }
+    def docsCopySpec = project.copySpec { CopySpec spec ->
+      spec.from 'build/docs'
+      spec.from 'manual/build/docs/website'
+      spec.into 'docs'
+    }
+    def runtimeDependenciesListCopySpec = project.copySpec { CopySpec spec ->
+      releaseSpec.approvedProjects.collect { p ->
+        spec.into( 'libs/' ) { CopySpec sub ->
+          sub.from "$p.buildDir/reports/project/dependencies.txt"
+          sub.rename 'dependencies.txt', "${ p.name }-${ p.version }-runtime-deps.txt"
+        }
+      }
+      spec.into( '.' ) { CopySpec sub ->
+        sub.from project.tasks.getByName( TaskNames.GENERATE_MAVEN_OFFLINE_HELPERS ).outputs
+        sub.from project.tasks.getByName( TaskNames.GENERATE_GRADLE_OFFLINE_HELPERS ).outputs
+      }
+    }
+    def libsCopySpec = project.copySpec { CopySpec spec ->
+      releaseSpec.approvedProjects.collect { proj ->
+        spec.into( 'libs/' ) { CopySpec sub ->
+          sub.from proj.configurations.getByName( 'archives' ).artifacts.files
+          sub.exclude '**-testsources.jar'
+          sub.exclude '**/*.asc'
+        }
+      }
+    }
+    def extraDistTextCopySpec = project.copySpec { CopySpec spec ->
+      releaseSpec.approvedProjects.collect { p ->
+        spec.from project.fileTree( dir: "$p.projectDir/src/dist/", include: '**', exclude: "**/*.jar*" )
+        spec.eachFile { FileCopyDetails fcd ->
+          fcd.filter( ReplaceTokens, tokens: [ version: project.version ] )
+        }
+      }
+      spec.into '.'
+    }
+    def extraDistBinCopySpec = project.copySpec { CopySpec spec ->
+      releaseSpec.approvedProjects.collect { p ->
+        spec.from "$p.projectDir/src/dist/"
+        spec.include '**/*.jar'
+        spec.include '**/*.jar_'
+      }
+      spec.into '.'
+    }
+    def binDistNoticesCopySpec = project.copySpec { CopySpec spec ->
+      spec.from "$project.projectDir/LICENSE.txt"
+      spec.from "$project.projectDir/src/bin-dist"
+      spec.into '.'
+    }
+    def binDistImage = project.copySpec { CopySpec spec ->
+      spec.into "apache-zest-java-$project.version-bin"
+      spec.with binDistNoticesCopySpec
+      spec.with docsCopySpec
+      spec.with reportsDistCopySpec
+      spec.with runtimeDependenciesListCopySpec
+      spec.with extraDistTextCopySpec
+      spec.with extraDistBinCopySpec
+      spec.with libsCopySpec
+    }
+
+    def zipBinaries = project.tasks.create( 'zipBinaries', Zip ) { Zip task ->
+      task.dependsOn project.tasks.getByName( RootProjectPlugin.TaskNames.BUILD_ALL )
+      task.baseName = 'apache-zest-java'
+      task.classifier = 'bin'
+      task.with binDistImage
+    }
+    def tarBinaries = project.tasks.create( 'tarBinaries', Tar ) { Tar task ->
+      task.dependsOn project.tasks.getByName( RootProjectPlugin.TaskNames.BUILD_ALL )
+      task.baseName = 'apache-zest-java'
+      task.classifier = 'bin'
+      task.compression = Compression.GZIP
+      task.with binDistImage
+    }
+    project.artifacts.add( 'archives', zipBinaries )
+    project.artifacts.add( 'archives', tarBinaries )
+
+    project.tasks.create( TaskNames.UNPACK_BINARY_DIST, Copy ) { Copy task ->
+      task.description = "Unpack the binary distribution"
+      task.group = TaskGroups.DISTRIBUTION
+      task.with binDistImage
+      task.into 'build/unpacked-distributions/bin'
+    }
+
+    configureBinaryDistributionCheck( project )
+  }
+
+  private static void configureGoOfflineHelpers( Project project )
+  {
+    def approvedProjectsTask = project.tasks.getByName( ReleaseSpecPlugin.TaskNames.RELEASE_APPROVED_PROJECTS )
+    def genOfflineMaven = project.tasks.create( TaskNames.GENERATE_MAVEN_OFFLINE_HELPERS,
+                                                GoOfflineHelpersTasks.GenerateMaven )
+    def genOfflineGradle = project.tasks.create( TaskNames.GENERATE_GRADLE_OFFLINE_HELPERS,
+                                                 GoOfflineHelpersTasks.GenerateGradle )
+    genOfflineMaven.repositories = DependenciesPlugin.REPOSITORIES_URLS
+    genOfflineGradle.repositories = DependenciesPlugin.REPOSITORIES_URLS
+    [ genOfflineMaven, genOfflineGradle ].each { task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.dependsOn approvedProjectsTask
+    }
+    def checkOfflineMaven = project.tasks.create( TaskNames.CHECK_MAVEN_OFFLINE_HELPERS,
+                                                  GoOfflineHelpersTasks.CheckMaven )
+    def checkOfflineGradle = project.tasks.create( TaskNames.CHECK_GRADLE_OFFLINE_HELPERS,
+                                                   GoOfflineHelpersTasks.CheckGradle )
+    checkOfflineMaven.dependsOn genOfflineMaven
+    checkOfflineGradle.dependsOn genOfflineGradle
+    [ checkOfflineMaven, checkOfflineGradle ].each { task ->
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.dependsOn TaskNames.UNPACK_BINARY_DIST
+    }
+  }
+
+  private static void configureBinaryDistributionCheck( Project project )
+  {
+    def unpackedBinDistDir = project.file( "build/unpacked-distributions/bin/apache-zest-java-$project.version-bin" )
+    project.tasks.create( TaskNames.CHECK_BINARY_DIST_RAT, RatTask, { RatTask task ->
+      task.dependsOn TaskNames.UNPACK_BINARY_DIST
+      task.description = "Check the binary distribution using Apache RAT"
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.inputDir = unpackedBinDistDir.absolutePath
+      task.reportDir = project.file( 'build/reports/rat-bin-dist' )
+      task.excludes = [
+        '.gradle/**',
+        'docs/reports/**',
+        'etc/templates/**',
+        'libs/**'
+      ]
+    } as Action<RatTask> )
+    project.tasks.getByName( TaskNames.CHECK_MAVEN_OFFLINE_HELPERS ) { GoOfflineHelpersTasks.CheckMaven task ->
+      task.directory = unpackedBinDistDir
+    }
+    project.tasks.getByName( TaskNames.CHECK_GRADLE_OFFLINE_HELPERS ) { GoOfflineHelpersTasks.CheckGradle task ->
+      task.directory = unpackedBinDistDir
+      task.mustRunAfter TaskNames.CHECK_MAVEN_OFFLINE_HELPERS
+    }
+    project.tasks.create( TaskNames.CHECK_BINARY_DIST ) { Task task ->
+      task.dependsOn TaskNames.CHECK_BINARY_DIST_RAT
+      task.dependsOn TaskNames.CHECK_MAVEN_OFFLINE_HELPERS
+      task.dependsOn TaskNames.CHECK_GRADLE_OFFLINE_HELPERS
+    }
+  }
+
+  @CompileStatic( TypeCheckingMode.SKIP )
+  private static void configureDistributionChecksums( Project project )
+  {
+    project.tasks.withType( Zip ) { Zip task ->
+      task.doLast {
+        project.ant.checksum file: task.archivePath, algorithm: 'MD5'
+        project.ant.checksum file: task.archivePath, algorithm: 'SHA-512'
+      }
+    }
+    project.tasks.withType( Tar ) { Tar task ->
+      task.doLast {
+        project.ant.checksum file: task.archivePath, algorithm: 'MD5'
+        project.ant.checksum file: task.archivePath, algorithm: 'SHA-512'
+      }
+    }
+  }
+
+  private static void configureHelperTasks( Project project )
+  {
+    project.tasks.create( 'dist', Copy ) { Copy task ->
+      task.dependsOn 'install'
+      task.description = "Unpack the binary distribution"
+      task.group = TaskGroups.DISTRIBUTION
+      task.from project.tasks.getByName( 'unpackBinDist' )
+      task.into "$project.buildDir/dist"
+    }
+    project.tasks.create( 'checkDists' ) { Task task ->
+      task.description = "Check the source and binary distributions"
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.dependsOn TaskNames.CHECK_SOURCE_DIST, TaskNames.CHECK_BINARY_DIST
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/dist/GoOfflineHelpersTasks.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/dist/GoOfflineHelpersTasks.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/dist/GoOfflineHelpersTasks.groovy
new file mode 100644
index 0000000..459eaaf
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/dist/GoOfflineHelpersTasks.groovy
@@ -0,0 +1,345 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.zest.gradle.dist
+
+import groovy.transform.CompileStatic
+import org.apache.zest.gradle.release.ReleaseSpecExtension
+import org.apache.zest.gradle.tasks.ExecLogged
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Dependency
+import org.gradle.api.artifacts.ProjectDependency
+import org.gradle.api.artifacts.result.ResolvedComponentResult
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.TaskAction
+import org.gradle.process.ExecSpec
+
+/**
+ * Tasks to generate and check go-offline maven and gradle helpers bundled with the binary distribution.
+ */
+@CompileStatic
+interface GoOfflineHelpersTasks
+{
+  class GenerateMaven extends DefaultTask
+  {
+    static final String POM_FILENAME = 'go-offline.pom'
+
+    @Input
+    Map<String, String> repositories = [ : ]
+
+    @Internal
+    File outputDir = new File( project.buildDir, 'go-offline-helpers' )
+
+    @OutputFile
+    File getMavenGoOfflineHelper()
+    {
+      return new File( outputDir, POM_FILENAME )
+    }
+
+    GenerateMaven()
+    {
+      super();
+      outputs.upToDateWhen { false }
+    }
+
+    @TaskAction
+    void generate()
+    {
+      outputDir.mkdirs()
+      def components = Utils.resolveAllRuntimeComponents( project )
+      def maven = generateMaven( components )
+      mavenGoOfflineHelper.text = maven
+    }
+
+    private String generateMaven( Set<ResolvedComponentResult> components )
+    {
+      def pom = Utils.licenseHeader( project.file( 'etc/header.txt' ).text, 'xml' )
+      pom += '<project>\n  <modelVersion>4.0.0</modelVersion>\n'
+      pom +=
+        "  <groupId>org.apache.zest</groupId>\n  <artifactId>go-offline-helper</artifactId>\n  <version>$project.version</version>\n"
+      pom += '  <packaging>pom</packaging>\n'
+      pom +=
+        '  <!--\n  This pom has the sole purpose of downloading all dependencies in a directory relative to this file named \'dependencies\'.\n'
+      pom += "  Use the following command:\n\n  mvn -f $POM_FILENAME validate\n  -->\n  <repositories>\n"
+      repositories.entrySet().each { repo ->
+        pom += "    <repository><id>go-offline-repo-$repo.key</id><url>${ repo.value }</url></repository>\n"
+      }
+      pom += '  </repositories>\n  <dependencies>\n'
+      components.each { comp ->
+        pom += '    <dependency>\n'
+        pom += "      <groupId>$comp.moduleVersion.group</groupId>\n"
+        pom += "      <artifactId>$comp.moduleVersion.name</artifactId>\n"
+        pom += "      <version>$comp.moduleVersion.version</version>\n"
+        pom += '    </dependency>\n'
+      }
+      pom += """  </dependencies>\n  <build><plugins><plugin>
+    <groupId>org.apache.maven.plugins</groupId>
+    <artifactId>maven-dependency-plugin</artifactId>
+    <version>2.10</version>
+    <executions>
+      <execution>
+        <id>go-offline-jars</id><phase>validate</phase>
+        <goals><goal>copy-dependencies</goal></goals>
+        <configuration>
+          <outputDirectory>\${project.basedir}/dependencies</outputDirectory>
+          <excludeTransitive>true</excludeTransitive>
+        </configuration>
+      </execution>
+      <execution>
+        <id>go-offline-sources</id><phase>validate</phase>
+        <goals><goal>copy-dependencies</goal></goals>
+        <configuration>
+          <classifier>sources</classifier><failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
+          <outputDirectory>\${project.basedir}/dependencies</outputDirectory>
+          <excludeTransitive>true</excludeTransitive>
+        </configuration>
+      </execution>
+      <execution>
+        <id>go-offline-javadocs</id><phase>validate</phase>
+        <goals><goal>copy-dependencies</goal></goals>
+        <configuration>
+          <classifier>javadoc</classifier><failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
+          <outputDirectory>\${project.basedir}/dependencies</outputDirectory>
+          <excludeTransitive>true</excludeTransitive>
+        </configuration>
+      </execution>
+    </executions>
+  </plugin></plugins></build>
+</project>
+"""
+      return pom
+    }
+  }
+
+  class GenerateGradle extends DefaultTask
+  {
+    static final String BUILD_SCRIPT_FILENAME = 'go-offline.gradle'
+
+    @Input
+    Map<String, String> repositories = [ : ]
+
+    @Internal
+    File outputDir = new File( project.buildDir, 'go-offline-helpers' )
+
+    @OutputFile
+    File getGradleGoOfflineHelper()
+    {
+      return new File( outputDir, BUILD_SCRIPT_FILENAME )
+    }
+
+    GenerateGradle()
+    {
+      super();
+      outputs.upToDateWhen { false }
+    }
+
+    @TaskAction
+    void generate()
+    {
+      outputDir.mkdirs()
+      def components = Utils.resolveAllRuntimeComponents( project )
+      def gradle = generateGradle( components )
+      gradleGoOfflineHelper.text = gradle
+    }
+
+    private String generateGradle( Set<ResolvedComponentResult> components )
+    {
+      def build = Utils.licenseHeader( project.file( 'etc/header.txt' ).text, 'java' )
+      build += '// This gradle build file has the sole purpose of downloading all dependencies in a directory\n'
+      build += '// relative to this file named \'dependencies\'.\n'
+      build += "// Use the following command: gradle -b $BUILD_SCRIPT_FILENAME download\n"
+      build += 'apply plugin: \'java\'\nconfigurations { download }\nrepositories {\n'
+      repositories.entrySet().each { repo ->
+        build += "  maven { url '${ repo.value }' }\n"
+      }
+      build += '}\ndependencies {\n'
+      components.each { comp ->
+        def depCoords = "${ comp.moduleVersion.group }:${ comp.moduleVersion.name }:${ comp.moduleVersion.version }"
+        build += "  download( '$depCoords' ) { transitive = false }\n"
+      }
+      build += """}
+task download( type: Copy ) {
+  outputs.upToDateWhen { false }
+  def sources = configurations.download.resolvedConfiguration.resolvedArtifacts.collect { artifact ->
+    project.dependencies.create( [ group: artifact.moduleVersion.id.group, name: artifact.moduleVersion.id.name, version: artifact.moduleVersion.id.version, classifier: 'sources' ] )
+  }
+  def javadocs = configurations.download.resolvedConfiguration.resolvedArtifacts.collect { artifact ->
+    project.dependencies.create( [ group: artifact.moduleVersion.id.group, name: artifact.moduleVersion.id.name, version: artifact.moduleVersion.id.version, classifier: 'javadoc' ] )
+  }
+  from configurations.download
+  from configurations.detachedConfiguration( sources as Dependency[] ).resolvedConfiguration.lenientConfiguration.getFiles( Specs.SATISFIES_ALL )
+  from configurations.detachedConfiguration( javadocs as Dependency[] ).resolvedConfiguration.lenientConfiguration.getFiles( Specs.SATISFIES_ALL )
+  into file( 'dependencies/' )
+}
+"""
+      return build
+    }
+  }
+
+  class CheckMaven extends DefaultTask
+  {
+    @Internal
+    File directory
+
+    @InputFile
+    File getMavenGoOfflineHelper()
+    {
+      return new File( directory, GenerateMaven.POM_FILENAME )
+    }
+
+    CheckMaven()
+    {
+      super();
+      description = 'Check the binary distribution Maven go-offline helper'
+      outputs.upToDateWhen { false }
+      onlyIf { Utils.isMvnInstalled() }
+    }
+
+    @TaskAction
+    void check()
+    {
+      def dependenciesDir = new File( directory, 'dependencies' )
+      project.delete dependenciesDir
+      def outLog = project.file( "$project.buildDir/tmp/$name/stdout.log" )
+      def errLog = project.file( "$project.buildDir/tmp/$name/stderr.log" )
+      def command = [ 'mvn', '-e', '-f', GenerateMaven.POM_FILENAME, 'validate' ] as Object[]
+      ExecLogged.execLogged( project, outLog, errLog ) { ExecSpec spec ->
+        spec.workingDir directory
+        spec.commandLine command
+      }
+      Utils.checkAllJarsArePresent( project, dependenciesDir, GenerateMaven.POM_FILENAME )
+    }
+  }
+
+  class CheckGradle extends DefaultTask
+  {
+    @Internal
+    File directory
+
+    @InputFile
+    File getGradleGoOfflineHelper()
+    {
+      return new File( directory, GenerateGradle.BUILD_SCRIPT_FILENAME )
+    }
+
+    CheckGradle()
+    {
+      super();
+      description = 'Check the binary distribution Gradle go-offline helper'
+      outputs.upToDateWhen { false }
+    }
+
+    @TaskAction
+    void check()
+    {
+      def buildScript = new File( directory, GenerateGradle.BUILD_SCRIPT_FILENAME )
+      def dependenciesDir = new File( directory, 'dependencies' )
+      project.delete dependenciesDir
+      def outLog = project.file( "$project.buildDir/tmp/$name/stdout.log" )
+      def errLog = project.file( "$project.buildDir/tmp/$name/stderr.log" )
+      ExecLogged.execLogged( project, outLog, errLog ) { ExecSpec spec ->
+        spec.workingDir project.projectDir
+        spec.commandLine './gradlew', '-u', '-s', '-b', buildScript.absolutePath, 'download'
+      }
+      Utils.checkAllJarsArePresent( project, dependenciesDir, GenerateGradle.BUILD_SCRIPT_FILENAME )
+    }
+  }
+
+  static class Utils
+  {
+    // Do the global dependency resolution here so there won't be any surprise when using the helpers
+    // This also allow to apply the resolution strategy defined in libraries.gradle
+    // WARN some of our modules depends on != versions of some artifacts, this resolution flatten this using the most up to date
+    private static Set<ResolvedComponentResult> resolveAllRuntimeComponents( Project rootProject )
+    {
+      def allRuntimeDeps = getAllRuntimeDependencies( rootProject )
+      def configuration = rootProject.configurations.findByName( 'goOfflineHelpers' )
+      if( !configuration )
+      {
+        configuration = rootProject.configurations.create( 'goOfflineHelpers' )
+        allRuntimeDeps.each { set -> rootProject.dependencies.add( configuration.name, set ) }
+      }
+      return configuration.incoming.resolutionResult.allComponents.findAll { ResolvedComponentResult comp ->
+        !comp.moduleVersion.group.startsWith( 'org.apache.zest' )
+      } as Set<ResolvedComponentResult>
+    }
+
+    private static List<Dependency> getAllRuntimeDependencies( Project rootProject )
+    {
+      def releaseSpec = rootProject.extensions.getByType( ReleaseSpecExtension )
+      def allDependencies = releaseSpec.approvedProjects.collect { project ->
+        project.configurations.getByName( 'runtime' ).allDependencies
+      }.flatten() as List<Dependency>
+      return allDependencies.findAll { Dependency dep ->
+        !( dep instanceof ProjectDependency ) && dep.name != null && !dep.group.startsWith( 'org.apache.zest' )
+      }
+    }
+
+    private static void checkAllJarsArePresent( Project rootProject, File dependenciesDir, String helper )
+    {
+      def allDependencies = getAllRuntimeDependencies( rootProject )
+      allDependencies.each { Dependency dep ->
+        def jarName = "${ dep.name }-${ dep.version }.jar"
+        def jarFile = new File( dependenciesDir, jarName )
+        if( !jarFile.exists() )
+        {
+          throw new GradleException( "Binary distribution $helper failed!\n" +
+                                     "\tMissing: $dep\n" +
+                                     "\tin $jarFile" );
+        }
+      }
+    }
+
+    private static boolean isMvnInstalled()
+    {
+      def pathDirs = System.getenv( 'PATH' ).split( File.pathSeparator )
+      def flattened = pathDirs.collect( { String pathDir -> new File( pathDir, 'mvn' ) } ).flatten() as List<File>
+      return flattened.find( { File pathDir -> pathDir.isFile() } ) != null
+    }
+
+    // Generate license headers with comment styles
+    private static String licenseHeader( String base, String flavour )
+    {
+      def header
+      switch( flavour )
+      {
+        case 'java': case 'groovy': case 'scala': case 'js':
+          header = licenseHeader_wrap( base, '/*', ' * ', ' */' ); break
+        case 'xml': case 'html':
+          header = licenseHeader_wrap( base, '<!--', '  ', '-->' ); break
+        case 'txt': case 'shell': case 'python': case 'ruby':
+          header = licenseHeader_wrap( base, null, '# ', null ); break
+        case 'adoc': case 'asciidoc':
+          header = licenseHeader_wrap( base, null, '// ', null ); break
+        default:
+          header = base
+      }
+      header
+    }
+
+    private static String licenseHeader_wrap( String base, String top, String left, String bottom )
+    {
+      ( top ? "$top\n" : '' ) + base.readLines().collect { "${ left }${ it }" }.join( '\n' ) + '\n' +
+      ( bottom ? "$bottom\n" : '' )
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/doc/AsciidocBuildInfoPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/doc/AsciidocBuildInfoPlugin.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/doc/AsciidocBuildInfoPlugin.groovy
index efb9654..dad0f6d 100644
--- a/buildSrc/src/main/groovy/org/apache/zest/gradle/doc/AsciidocBuildInfoPlugin.groovy
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/doc/AsciidocBuildInfoPlugin.groovy
@@ -30,7 +30,8 @@ class AsciidocBuildInfoPlugin implements Plugin<Project>
   {
     def buildInfoDir = new File( project.buildDir, "docs/buildinfo" );
 
-    def makeAsciidocBuildInfoTask = project.task( TASK_NAME ) << {
+    def makeAsciidocBuildInfoTask = project.task( TASK_NAME )
+    makeAsciidocBuildInfoTask.doLast {
       buildInfoDir.mkdirs()
 
       // GroupID, ArtifactID, Version table in artifact.txt

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/doc/DocumentationTask.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/doc/DocumentationTask.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/doc/DocumentationTask.groovy
index af1efa5..3c37465 100644
--- a/buildSrc/src/main/groovy/org/apache/zest/gradle/doc/DocumentationTask.groovy
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/doc/DocumentationTask.groovy
@@ -19,9 +19,9 @@ package org.apache.zest.gradle.doc
 
 import groovy.io.FileType
 import groovy.transform.CompileStatic
-import groovy.transform.TypeCheckingMode;
+import groovy.transform.TypeCheckingMode
+import org.apache.zest.gradle.release.ReleaseSpecExtension;
 import org.gradle.api.DefaultTask
-import org.gradle.api.Project
 import org.gradle.api.file.CopySpec
 import org.gradle.api.tasks.TaskAction
 import org.gradle.api.tasks.Input
@@ -142,7 +142,7 @@ class DocumentationTask extends DefaultTask
         asciidocFile.readLines().each { line ->
           if( line.startsWith( 'include::' ) ) {
             def approved = false
-            Set<Project> releaseApprovedProjects = project.rootProject.extensions.extraProperties.get('releaseApprovedProjects') as Set<Project>
+            def releaseApprovedProjects = project.rootProject.extensions.getByType( ReleaseSpecExtension ).approvedProjects
             releaseApprovedProjects.collect{it.projectDir}.each { approvedProjectDir ->
               if( line.contains( "${approvedProjectDir.parentFile.name}/${approvedProjectDir.name}" ) ) {
                 approved = true

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/publish/MavenMetadata.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/publish/MavenMetadata.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/publish/MavenMetadata.groovy
new file mode 100644
index 0000000..7f368e6
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/publish/MavenMetadata.groovy
@@ -0,0 +1,281 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.zest.gradle.publish
+
+import org.gradle.api.artifacts.maven.MavenDeployer
+
+class MavenMetadata
+{
+  static void applyTo( MavenDeployer mavenDeployer )
+  {
+    mavenDeployer.pom {
+      project {
+        url 'https://zest.apache.org/'
+        organization {
+          name 'The Apache Software Foundation'
+          url 'https://apache.org/'
+        }
+        inceptionYear '2007'
+        issueManagement {
+          system 'jira'
+          url 'https://issues.apache.org/jira/browse/ZEST'
+        }
+        scm {
+          url "https://github.com/apache/zest-java"
+          connection "scm:git:https://git-wip-us.apache.org/repos/asf/zest-java.git"
+          developerConnection "scm:git:https://git-wip-us.apache.org/repos/asf/zest-java.git"
+        }
+        licenses {
+          license {
+            name 'Apache License, version 2.0.'
+            url 'http://www.apache.org/licenses/LICENSE-2.0'
+          }
+        }
+        mailingLists {
+          mailingList {
+            name 'Users List'
+            subscribe 'users-subscribe@zest.apache.org'
+            unsubscribe 'users-unsubscribe@zest.apache.org'
+            post 'users@zest.apache.org'
+            archive 'https://mail-archives.apache.org/mod_mbox/zest-users/'
+            otherArchives {
+              otherArchive 'https://www.apache.org/foundation/mailinglists.html#archives'
+            }
+          }
+          mailingList {
+            name 'Development List'
+            subscribe 'dev-subscribe@zest.apache.org'
+            unsubscribe 'dev-unsubscribe@zest.apache.org'
+            post 'dev@zest.apache.org'
+            archive 'https://mail-archives.apache.org/mod_mbox/zest-dev/'
+            otherArchives {
+              otherArchive 'https://www.apache.org/foundation/mailinglists.html#archives'
+            }
+          }
+          mailingList {
+            name 'Commits List'
+            subscribe 'commits-subscribe@zest.apache.org'
+            unsubscribe 'commits-unsubscribe@zest.apache.org'
+            post 'commits@zest.apache.org'
+            archive 'https://mail-archives.apache.org/mod_mbox/zest-commits/'
+            otherArchives {
+              otherArchive 'https://www.apache.org/foundation/mailinglists.html#archives'
+            }
+          }
+        }
+        developers {
+          developer {
+            id 'niclas@hedhman.org'
+            name 'Niclas Hedhman'
+            email 'niclas@hedhman.org'
+            roles {
+              role 'Core Team'
+            }
+            organizationUrl 'http://zest.apache.org'
+            timezone 'UTC+8'
+          }
+          developer {
+            id 'rickardoberg'
+            name 'Rickard \u00F6berg'
+            email 'rickard.oberg@jayway.se'
+            roles {
+              role 'Core Team'
+            }
+            url 'http://www.neotechnology.com'
+            organization 'Neo Technology AB'
+            organizationUrl 'http://www.neotechnology.com'
+            timezone 'UTC+8'
+          }
+          developer {
+            id 'edward.yakop@gmail.com'
+            name 'Edward Yakop'
+            email 'efy@codedragons.com'
+            roles {
+              role 'Core Team'
+            }
+            organizationUrl 'http://zest.apache.org'
+            timezone 'UTC+8'
+          }
+          developer {
+            id 'adreghiciu@gmail.com'
+            name 'Alin Dreghiciu'
+            email 'adreghiciu@codedragons.com'
+            roles {
+              role 'Core Team'
+            }
+            organizationUrl 'http://zest.apache.org'
+            timezone 'UTC+2'
+          }
+          developer {
+            id 'mesirii'
+            name 'Michael Hunger'
+            email 'qi4j@jexp.de'
+            roles {
+              role 'Core Team'
+            }
+            timezone 'CET'
+          }
+
+          developer {
+            id "muhdkamil"
+            name "Muhd Kamil bin Mohd Baki"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC+8"
+          }
+
+          developer {
+            id "ops4j@leangen.net"
+            name "David Leangen"
+            organization "Bioscene"
+            email "ops4j@leangen.net"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC+9"
+          }
+
+          developer {
+            id "sonny.gill@jayway.net"
+            name "Sonny Gill"
+            email "sonny.public@gmail.com"
+            roles {
+              role 'Community Team'
+            }
+            timezone "UTC+8"
+          }
+
+          developer {
+            id "taowen"
+            name "Tao Wen"
+            organization ""
+            email "taowen@gmail.com"
+            roles {
+              role 'Community Team'
+            }
+            timezone "UTC+8"
+          }
+
+          developer {
+            id "thobe"
+            name "Tobias Ivarsson"
+            email "tobias@neotechnology.com"
+            url "http://www.neotechnology.com"
+            organization "NeoTechnology"
+            organizationUrl "http://www.neotechnology.com"
+            roles {
+              role "Platform Team"
+            }
+            timezone "CET"
+          }
+
+          developer {
+            id "boon"
+            name "Lan Boon Ping"
+            email "boonping81@gmail.com"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC+8"
+          }
+
+          developer {
+            id "jan.kronquist@gmail.com"
+            name "Jan Kronquist"
+            email "jan.kronquist@gmail.com"
+            organization "Jayway"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "CET"
+          }
+
+          developer {
+            id "nmwael"
+            name "Nino Saturnino Martinez Vazquez Wael"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "CET"
+          }
+
+          developer {
+            id "peter@neubauer.se"
+            name "Peter Neubauer"
+            email "peter@neubauer.se"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "CET"
+          }
+
+          developer {
+            id "rwallace"
+            name "Richard Wallace"
+            email "rwallace@thewallacepack.net"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC-7"
+          }
+
+          developer {
+            id "siannyhalim@gmail.com"
+            name "Sianny Halim"
+            email "siannyhalim@gmail.com"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC+8"
+          }
+
+          developer {
+            id "paul@nosphere.org"
+            name "Paul Merlin"
+            email "paul@nosphere.org"
+            roles {
+              role 'Core Team'
+            }
+            timezone "CET"
+          }
+
+          developer {
+            id "stas.dev+qi4j@gmail.com"
+            name "Stanislav Muhametsin"
+            email "stas.dev+qi4j@gmail.com"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC+2"
+          }
+
+          developer {
+            id "tonny"
+            name "Tonny Kohar"
+            roles {
+              role "Community Team"
+            }
+            email "tonny.kohar@gmail.com"
+            timezone "UTC+7"
+          }
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/publish/PublishingPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/publish/PublishingPlugin.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/publish/PublishingPlugin.groovy
new file mode 100644
index 0000000..34b1f95
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/publish/PublishingPlugin.groovy
@@ -0,0 +1,181 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.zest.gradle.publish
+
+import groovy.transform.CompileStatic
+import org.apache.zest.gradle.release.ReleaseSpecExtension
+import org.gradle.api.GradleException
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.artifacts.maven.MavenDeployer
+import org.gradle.api.artifacts.maven.MavenDeployment
+import org.gradle.api.internal.plugins.DslObject
+import org.gradle.api.plugins.MavenRepositoryHandlerConvention
+import org.gradle.api.publication.maven.internal.deployer.DefaultGroovyMavenDeployer
+import org.gradle.api.publication.maven.internal.deployer.MavenRemoteRepository
+import org.gradle.api.tasks.Upload
+import org.gradle.plugins.signing.Sign
+import org.gradle.plugins.signing.SigningExtension
+
+/**
+ * Publishing.
+ *
+ * <strong>Configuration</strong>
+ *
+ * By default RELEASES are signed, SNAPSHOTS are not.
+ * Signing can be turned on or off by setting the {@literal uploadSigned} property.
+ *
+ * By default RELEASES must satisfy {@link org.apache.zest.gradle.release.ModuleReleaseSpec}, SNAPSHOT don't.
+ * This can be turned on or off by setting the {@literal uploadReleaseSpec} property.
+ *
+ * By default RELEASES and SNAPSHOTS are uploaded using HTTP.
+ * Used Wagon can be overridden by setting the {@literal uploadWagon} property.
+ *
+ * By default RELEASES and SNAPSHOTS are uploaded to Apache Nexus.
+ * Target repository can be overridden by setting the {@literal uploadRepository} property.
+ *
+ * No username/password is provided by default.
+ * If needed set them using the uploadUsername and {@literal uploadPassword} properties.
+ */
+@CompileStatic
+class PublishingPlugin implements Plugin<Project>
+{
+  static final String WAGON_HTTP = 'org.apache.maven.wagon:wagon-http:2.2'
+  static final String WAGON_SSH = 'org.apache.maven.wagon:wagon-ssh:2.2'
+  static final String WAGON_WEBDAV = 'org.apache.maven.wagon:wagon-webdav:1.0-beta-2'
+
+  static final String RELEASES_REPOSITORY_NAME = 'apache.releases.https'
+  static final String RELEASES_REPOSITORY_URL = 'https://repository.apache.org/service/local/staging/deploy/maven2'
+  static final String SNAPSHOTS_REPOSITORY_NAME = 'apache.snapshots.https'
+  static final String SNAPSHOTS_REPOSITORY_URL = 'https://repository.apache.org/content/repositories/snapshots'
+
+  static class Config
+  {
+    boolean snapshots
+    boolean releases
+    boolean signed
+    boolean releaseSpec
+    String wagon
+    String repositoryName
+    String repositoryUrl
+    String username
+    String password
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    Config config = configFor( project )
+    applyWagonConfiguration( project, config )
+    configureSigning( project, config )
+    configureUploadArchives( project, config )
+    configureMavenMetadata( project )
+    applyMavenPublishAuth( project )
+  }
+
+  private static Config configFor( Project project )
+  {
+    def config = new Config()
+    config.snapshots = project.version == '0' || project.version.toString().contains( 'SNAPSHOT' )
+    config.releases = !config.snapshots
+    config.signed = project.findProperty( 'uploadSigned' ) ?: config.releases
+    config.releaseSpec = project.findProperty( 'uploadReleaseSpec' ) ?: config.releases
+    config.wagon = project.findProperty( 'uploadWagon' ) ?: WAGON_HTTP
+    config.repositoryName = project.findProperty( 'uploadRepositoryName' ) ?:
+                            config.releases ? RELEASES_REPOSITORY_NAME : SNAPSHOTS_REPOSITORY_NAME
+    config.repositoryUrl = project.findProperty( 'uploadRepository' ) ?:
+                           config.releases ? RELEASES_REPOSITORY_URL : SNAPSHOTS_REPOSITORY_URL
+    config.username = project.findProperty( 'uploadUsername' )
+    config.password = project.findProperty( 'uploadPassword' )
+    return config
+  }
+
+  private static void applyWagonConfiguration( Project project, Config config )
+  {
+    project.configurations.create( 'deployersJars' )
+    project.dependencies.add( 'deployersJars', config.wagon )
+  }
+
+  private static void configureSigning( Project project, Config config )
+  {
+    project.plugins.apply 'signing'
+    def signing = project.extensions.getByType( SigningExtension )
+    signing.required = config.signed
+    signing.sign project.configurations.getByName( 'archives' )
+    def signArchives = project.tasks.getByName( 'signArchives' ) as Sign
+    signArchives.onlyIf { !project.findProperty( 'skipSigning' ) }
+  }
+
+  private static void configureUploadArchives( Project project, Config config )
+  {
+    project.plugins.apply 'maven'
+    def uploadArchives = project.tasks.getByName( 'uploadArchives' ) as Upload
+    uploadArchives.doFirst {
+      if( project.version == "0" )
+      {
+        throw new GradleException( "'version' must be given as a system property to perform a release." )
+      }
+    }
+    uploadArchives.onlyIf {
+      def notSkipped = !project.hasProperty( 'skipUpload' )
+      def approvedProject = project.extensions.getByType( ReleaseSpecExtension ).approvedProjects.contains( project )
+      return notSkipped && ( !config.releaseSpec || ( approvedProject || project == project.rootProject ) )
+    }
+    uploadArchives.dependsOn project.tasks.getByName( 'check' )
+    def repositoriesConvention = new DslObject( uploadArchives.repositories )
+      .getConvention()
+      .getPlugin( MavenRepositoryHandlerConvention )
+    def mavenDeployer = repositoriesConvention.mavenDeployer() as DefaultGroovyMavenDeployer
+    if( config.signed )
+    {
+      mavenDeployer.beforeDeployment { MavenDeployment deployment ->
+        project.extensions.getByType( SigningExtension ).signPom( deployment )
+      }
+    }
+    mavenDeployer.configuration = project.configurations.getByName( 'deployersJars' )
+    def repository = new MavenRemoteRepository()
+    repository.id = config.repositoryName
+    repository.url = config.repositoryUrl
+    if( config.username )
+    {
+      repository.authentication.userName = config.username
+      repository.authentication.password = config.password
+    }
+    if( config.releases )
+    {
+      mavenDeployer.repository = repository
+    }
+    else
+    {
+      mavenDeployer.snapshotRepository = repository
+    }
+  }
+
+  private static void configureMavenMetadata( Project project )
+  {
+    def uploadArchives = project.tasks.getByName( 'uploadArchives' ) as Upload
+    def mavenDeployer = uploadArchives.repositories.getByName( 'mavenDeployer' ) as MavenDeployer
+    MavenMetadata.applyTo( mavenDeployer )
+  }
+
+  private static void applyMavenPublishAuth( final Project project )
+  {
+    // Bug in maven-publish-auth require apply after uploadArchives setup
+    project.plugins.apply 'maven-publish-auth'
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/release/CheckReleaseSpecTask.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/release/CheckReleaseSpecTask.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/release/CheckReleaseSpecTask.groovy
new file mode 100644
index 0000000..72eb41d
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/release/CheckReleaseSpecTask.groovy
@@ -0,0 +1,75 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.zest.gradle.release
+
+import groovy.transform.CompileStatic
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.Project
+import org.gradle.api.artifacts.ProjectDependency
+import org.gradle.api.tasks.TaskAction
+
+@CompileStatic
+class CheckReleaseSpecTask extends DefaultTask
+{
+  CheckReleaseSpecTask()
+  {
+    description = 'Ensure that no releasable module depend on module(s) that don\'t fit the release criteria.'
+    doFirst {
+      def approvedProjects = project.extensions.getByType( ReleaseSpecExtension ).approvedProjects
+      dependsOn approvedProjects.collect { each -> each.configurations.getByName( 'runtime' ) }
+    }
+  }
+
+  @TaskAction
+  void check()
+  {
+    Map<Project, Set<ProjectDependency>> notReleasable = [ : ]
+    def approvedProjects = project.extensions.getByType( ReleaseSpecExtension ).approvedProjects
+    approvedProjects.each { approvedProject ->
+      def projectDependencies = approvedProject.configurations.getByName( 'runtime' ).allDependencies.findAll {
+        it instanceof ProjectDependency
+      } as Set<ProjectDependency>
+      projectDependencies.each { dep ->
+        def depNotReleaseApproved = approvedProjects.findAll { rp ->
+          rp.group == dep.dependencyProject.group && rp.name == dep.dependencyProject.name
+        }.isEmpty()
+        if( depNotReleaseApproved )
+        {
+          if( !notReleasable[ approvedProject ] )
+          {
+            notReleasable[ approvedProject ] = [ ] as Set
+          }
+          notReleasable[ approvedProject ] << dep
+        }
+      }
+    }
+    if( !notReleasable.isEmpty() )
+    {
+      def errorMessage = new StringBuilder()
+      errorMessage << "At least one releasable module depends on module(s) that don't fit the release criteria!\n"
+      errorMessage << "\tOffending module -> Non releasable dependencies\n"
+      notReleasable.each { k, v ->
+        def noRlsDeps = v.collect { d -> ':' + d.dependencyProject.group + ':' + d.dependencyProject.name }
+        errorMessage << "\t$k -> ${ noRlsDeps })\n"
+      }
+      errorMessage << "Check the dev-status.xml file content in each modules directory."
+      throw new GradleException( errorMessage.toString() )
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseApprovedProjectsTask.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseApprovedProjectsTask.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseApprovedProjectsTask.groovy
new file mode 100644
index 0000000..3fe168e
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseApprovedProjectsTask.groovy
@@ -0,0 +1,57 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.zest.gradle.release
+
+import groovy.json.JsonBuilder
+import groovy.transform.CompileStatic
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.TaskAction
+
+/**
+ * Write paths of release approved projects to a JSON file.
+ *
+ * This task sole purpose is proper up-do-date behaviour when changing {@literal dev-status.xml} files.
+ */
+@CompileStatic
+class ReleaseApprovedProjectsTask extends DefaultTask
+{
+  @InputFiles
+  FileCollection getDevStatusFiles()
+  {
+    return project.files( project.allprojects
+                                 .collect( { project -> project.file( 'dev-status.xml' ) } )
+                                 .findAll( { it.exists() } ) )
+  }
+
+  @OutputFile
+  File getJsonApprovedProjects()
+  {
+    return new File( new File( project.buildDir, 'release' ), 'approved-projects.json' )
+  }
+
+  @TaskAction
+  void approveProjects()
+  {
+    def releaseSpec = project.extensions.getByType( ReleaseSpecExtension )
+    jsonApprovedProjects.parentFile.mkdirs()
+    jsonApprovedProjects.text = new JsonBuilder( releaseSpec.approvedProjects.collect( { it.path } ) ).toPrettyString()
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseSpecExtension.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseSpecExtension.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseSpecExtension.groovy
new file mode 100644
index 0000000..4ca5813
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseSpecExtension.groovy
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.zest.gradle.release
+
+import groovy.transform.CompileStatic
+import org.gradle.api.Project
+
+/**
+ * Provide release approved projects.
+ *
+ * There's no up-to-date checking on Gradle extensions.
+ * Depend on {@link ReleaseApprovedProjectsTask} to get a good up-to-date behavior.
+ */
+@CompileStatic
+class ReleaseSpecExtension
+{
+  static final String NAME = 'releaseSpec'
+  Set<Project> approvedProjects
+
+  ReleaseSpecExtension( Project rootProject )
+  {
+    def spec = new ModuleReleaseSpec()
+    approvedProjects = rootProject.allprojects.findAll( { p -> spec.satisfiedBy( p ) } )
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseSpecPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseSpecPlugin.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseSpecPlugin.groovy
new file mode 100644
index 0000000..ac46eed
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/release/ReleaseSpecPlugin.groovy
@@ -0,0 +1,60 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.zest.gradle.release
+
+import groovy.transform.CompileStatic
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+
+@CompileStatic
+class ReleaseSpecPlugin implements Plugin<Project>
+{
+  static class TaskGroups
+  {
+    static final String RELEASE = 'Release'
+    static final String RELEASE_VERIFICATION = 'Release verification'
+  }
+
+  static class TaskNames
+  {
+    static final String RELEASE_APPROVED_PROJECTS = 'releaseSpecApprovedProjects'
+    static final String CHECK_RELEASE_SPEC = 'checkReleaseSpec'
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    if( project != project.rootProject )
+    {
+      throw new IllegalStateException( "This plugin is only applicable to the root project" )
+    }
+    applyReleaseSpec( project )
+  }
+
+  private static void applyReleaseSpec( Project project )
+  {
+    project.extensions.create( ReleaseSpecExtension.NAME, ReleaseSpecExtension, project.rootProject )
+    project.tasks.create( TaskNames.RELEASE_APPROVED_PROJECTS, ReleaseApprovedProjectsTask ) { Task task ->
+      task.group = TaskGroups.RELEASE
+    }
+    project.tasks.create( TaskNames.CHECK_RELEASE_SPEC, CheckReleaseSpecTask ) { Task task ->
+      task.group = TaskGroups.RELEASE_VERIFICATION
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/tasks/ExecLogged.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/tasks/ExecLogged.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/tasks/ExecLogged.groovy
new file mode 100644
index 0000000..3c1a0d5
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/tasks/ExecLogged.groovy
@@ -0,0 +1,94 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.zest.gradle.tasks
+
+import groovy.transform.CompileStatic
+import org.gradle.api.Action
+import org.gradle.api.GradleException
+import org.gradle.api.Project
+import org.gradle.api.tasks.AbstractExecTask
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.TaskAction
+import org.gradle.internal.logging.ConsoleRenderer
+import org.gradle.process.ExecSpec
+
+@CompileStatic
+class ExecLogged extends AbstractExecTask<ExecLogged>
+{
+  @OutputFile
+  File stdoutFile = project.file( "$project.buildDir/tmp/${ getName() }/stdout.log" )
+
+  @OutputFile
+  File stderrFile = project.file( "$project.buildDir/tmp/${ getName() }/stderr.log" )
+
+  ExecLogged()
+  {
+    super( ExecLogged.class )
+  }
+
+  @TaskAction
+  protected void exec()
+  {
+    [ stdoutFile, stderrFile ].each { it.parentFile.mkdirs() }
+    def outStream = stdoutFile.newOutputStream()
+    def errStream = stderrFile.newOutputStream()
+    try
+    {
+      super.exec()
+    }
+    catch( Exception ex )
+    {
+      throw new GradleException( errorMessage( ex, stdoutFile, stderrFile ), ex )
+    }
+    finally
+    {
+      [ outStream, errStream ].each { it.close() }
+    }
+  }
+
+  static void execLogged( Project project, File stdoutFile, File stderrFile, Action<? super ExecSpec> specAction )
+  {
+    [ stdoutFile, stderrFile ].each { it.parentFile.mkdirs() }
+    def outStream = stdoutFile.newOutputStream()
+    def errStream = stderrFile.newOutputStream()
+    try
+    {
+      project.exec { ExecSpec spec ->
+        specAction.execute( spec )
+        spec.standardOutput = outStream
+        spec.errorOutput = errStream
+      }
+    }
+    catch( Exception ex )
+    {
+      throw new GradleException( errorMessage( ex, stdoutFile, stderrFile ), ex )
+    }
+    finally
+    {
+      [ outStream, errStream ].each { it.close() }
+    }
+  }
+
+  private static String errorMessage( Exception ex, File stdoutFile, File stderrFile )
+  {
+    def consoleRenderer = new ConsoleRenderer()
+    return "${ ex.message }\n" +
+           "\tSTDOUT ${ consoleRenderer.asClickableFileUrl( stdoutFile ) }\n" +
+           "\tSTDERR ${ consoleRenderer.asClickableFileUrl( stderrFile ) }"
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/test/AggregatedJacocoReportTask.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/test/AggregatedJacocoReportTask.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/test/AggregatedJacocoReportTask.groovy
new file mode 100644
index 0000000..724706d
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/test/AggregatedJacocoReportTask.groovy
@@ -0,0 +1,91 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.zest.gradle.test
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.Project
+import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.TaskAction
+
+class AggregatedJacocoReportTask extends DefaultTask
+{
+  @InputFiles
+  FileCollection getJacocoExecDataDirectories()
+  {
+    return project.files( project.subprojects.collect( { Project p -> "${ p.buildDir.path }/jacoco" } ) )
+  }
+
+  @OutputDirectory
+  File getOutputDirectory()
+  {
+    return project.file( "$project.buildDir/reports/coverage" )
+  }
+
+  @TaskAction
+  void report()
+  {
+    def coveredProjects = project.subprojects.findAll { p -> new File( "${ p.buildDir.path }/jacoco" ).exists() }
+    def coreProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.apache.zest.core' ) }
+    def libProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.apache.zest.lib' ) }
+    def extProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.apache.zest.ext' ) }
+    def toolsProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.apache.zest.tool' ) }
+    def tutoProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.apache.zest.tuto' ) }
+    def samplesProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.apache.zest.sample' ) }
+    def classpath = project.configurations.getByName( 'jacoco' ).asPath
+    project.ant {
+      taskdef name: 'jacocoreport', classname: 'org.jacoco.ant.ReportTask', classpath: classpath
+      mkdir dir: outputDirectory
+      jacocoreport {
+        executiondata {
+          coveredProjects.collect { p -> fileset( dir: "${ p.buildDir.path }/jacoco" ) { include( name: '*.exec' ) } }
+        }
+        structure( name: "Apache Zestâ„¢ (Java Edition) SDK" ) {
+          group( name: "Core" ) {
+            classfiles { coreProjects.collect { p -> fileset dir: "${ p.buildDir.path }/classes/main" } }
+            sourcefiles { coreProjects.collect { p -> fileset dir: "${ p.projectDir.path }/src/main/java" } }
+          }
+          group( name: "Libraries" ) {
+            classfiles { libProjects.collect { p -> fileset dir: "${ p.buildDir.path }/classes/main" } }
+            sourcefiles { libProjects.collect { p -> fileset dir: "${ p.projectDir.path }/src/main/java" } }
+          }
+          group( name: "Extensions" ) {
+            classfiles { extProjects.collect { p -> fileset dir: "${ p.buildDir.path }/classes/main" } }
+            sourcefiles { extProjects.collect { p -> fileset dir: "${ p.projectDir.path }/src/main/java" } }
+          }
+          group( name: "Tools" ) {
+            classfiles { toolsProjects.collect { p -> fileset dir: "${ p.buildDir.path }/classes/main" } }
+            sourcefiles { toolsProjects.collect { p -> fileset dir: "${ p.projectDir.path }/src/main/java" } }
+          }
+          group( name: "Tutorials" ) {
+            classfiles { tutoProjects.collect { p -> fileset dir: "${ p.buildDir.path }/classes/main" } }
+            sourcefiles { tutoProjects.collect { p -> fileset dir: "${ p.projectDir.path }/src/main/java" } }
+          }
+          group( name: "Samples" ) {
+            classfiles { samplesProjects.collect { p -> fileset dir: "${ p.buildDir.path }/classes/main" } }
+            sourcefiles { samplesProjects.collect { p -> fileset dir: "${ p.projectDir.path }/src/main/java" } }
+          }
+        }
+        csv destfile: "${ outputDirectory }/jacoco.csv", encoding: "UTF-8"
+        xml destfile: "${ outputDirectory }/jacoco.xml", encoding: "UTF-8"
+        html destdir: outputDirectory, encoding: "UTF-8", locale: "en", footer: "Apache Zestâ„¢ (Java Edition) SDK"
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/buildSrc/src/main/groovy/org/apache/zest/gradle/version/VersionClassPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/version/VersionClassPlugin.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/version/VersionClassPlugin.groovy
index b32e843..a78f588 100644
--- a/buildSrc/src/main/groovy/org/apache/zest/gradle/version/VersionClassPlugin.groovy
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/version/VersionClassPlugin.groovy
@@ -27,9 +27,8 @@ import org.gradle.api.plugins.JavaPluginConvention
 import org.gradle.api.tasks.SourceSet
 import org.gradle.api.tasks.bundling.Jar
 
-// TODO:perf Build only one for the whole project
-// TODO:perf Remove the build date, maybe not for release versions
-// TODO:release Put git data in with placeholders for dev versions
+// TODO:release:perf Placeholder for date for dev versions
+// TODO:release:perf Add git data, placeholders for dev versions
 @CompileStatic
 class VersionClassPlugin implements Plugin<Project>
 {
@@ -39,7 +38,8 @@ class VersionClassPlugin implements Plugin<Project>
     def genSrc = 'generated-src/version'
     def generatedSrcDir = new File( project.buildDir, genSrc )
 
-    Task makeVersionClassTask = project.task( 'makeVersionClass' ) << {
+    Task makeVersionClassTask = project.task( 'makeVersionClass' )
+    makeVersionClassTask.doLast {
       def now = new Date()
       def tmpGroup = project.name
       if( tmpGroup.startsWith( "org.apache.zest.core" ) )
@@ -96,5 +96,3 @@ public interface BuildVersion
     }
   }
 }
-
-

http://git-wip-us.apache.org/repos/asf/zest-java/blob/56793996/libraries.gradle
----------------------------------------------------------------------
diff --git a/libraries.gradle b/libraries.gradle
deleted file mode 100644
index 7952f73..0000000
--- a/libraries.gradle
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *
- */
-
-// Versions of Dependencies;
-def asmVersion = '5.1'
-def bonecpVersion = '0.8.0.RELEASE'
-def bouncyVersion = '1.55'
-def codahaleMetricsVersion = '3.1.2'
-def commonsDbcpVersion = '2.1.1'
-def commonsLangVersion = '3.5'
-def derbyVersion = '10.13.1.1'
-def dnsJavaVersion = '2.1.7'
-def ehcacheVersion = '3.1.3'
-def elasticsearchVersion = '5.0.0'
-def freemarkerVersion = '2.3.25-incubating'
-def geodeVersion = '1.0.0-incubating'
-def groovyVersion = '2.4.7'
-def h2Version = '1.4.193'
-def hazelcastVersion = '3.7.2'
-def hamcrestVersion = '1.3'
-def httpClientVersion = '4.5.2'
-def jacksonVersion = '2.8.4'
-def javascriptVersion = '1.7.7.1'
-def javasqlgeneratorVersion = '0.3.2'
-def jcloudsVersion = '1.9.2'
-def jdbmVersion = '2.4'
-def jedisVersion = '2.9.0'
-def jettyVersion = '9.2.17.v20160517' // 9.3.x Tests fail!
-def jgoodiesLooksVersion = '2.7.0'
-def jtaVersion = '1.1'
-def leveldbVersion = '0.9'
-def leveldbJniVersion = '1.8'
-def liquibaseVersion = '3.5.3'
-def logbackVersion = '1.1.7'
-def mongodbVersion = '3.3.0'
-def mysqlVersion = '6.0.4'
-def orgJsonVersion = '20130213'
-def osgiVersion = '4.2.0' // 4.3.0 Fails to compile! - 5.0.0 exists
-def pdfboxVersion = '2.0.3'
-def postgresqlVersion = '9.4.1211'
-def prefuseVersion = '1.0.1'
-def restletVersion = '2.3.7'
-def rdfVersion = '2.7.16' // 2.8.x change query results!! 4.x exists
-def riakVersion = '2.0.8'
-def scalaVersion = '2.11.8'
-def servletVersion = '3.1.0'
-def shiroVersion = '1.3.2'
-def skedVersion = '2.1'
-def slf4jVersion = '1.7.21'
-def solrVersion = "1.4.1" // 4.x Fails to compile!
-def springVersion = '4.3.3.RELEASE'
-def spymemcachedVersion = '2.12.1'
-def sqliteVersion = '3.14.2.1'
-def velocityVersion = '1.7'
-def woodstoxVersion = '4.4.1'
-
-def antVersion = '1.9.7'
-def awaitilityVersion = '2.0.0'
-def easyMockVersion = '3.4'
-def junitVersion = '4.12'
-def mockitoVersion = '2.2.9'
-
-// build a map of the dependency artifacts to use.  Allows centralized definition of the version of artifacts to
-// use.  In that respect it serves a role similar to <dependencyManagement> in Maven
-
-rootProject.ext {
-  libraries = [
-          // Ant
-          ant: "org.apache.ant:ant:$antVersion",
-          ant_junit: "org.apache.ant:ant-junit:$antVersion",
-
-          // ASM
-          asm: "org.ow2.asm:asm:$asmVersion",
-          asm_util: "org.ow2.asm:asm-util:$asmVersion",
-          asm_commons: "org.ow2.asm:asm-commons:$asmVersion",
-
-          // OSGi
-          osgi_core: "org.osgi:org.osgi.core:$osgiVersion",
-          osgi_compendium: "org.osgi:org.osgi.compendium:$osgiVersion",
-          osgi_enterprise: "org.osgi:org.osgi.enterprise:$osgiVersion",
-
-          // logging
-          slf4j_api: "org.slf4j:slf4j-api:$slf4jVersion",
-          slf4j_simple: "org.slf4j:slf4j-simple:$slf4jVersion",
-          logback: 'ch.qos.logback:logback-classic:' + logbackVersion,
-          jcl_slf4j: "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-          jcl_api: 'commons-logging:commons-logging-api:99.0-does-not-exist',  //ensure it is never used.
-          jcl: 'commons-logging:commons-logging:99.0-does-not-exist',  // ensure it is never used.
-
-          // org.json
-          org_json: "org.codeartisans:org.json:$orgJsonVersion",
-
-          // Restlet
-          restlet: [
-                  "org.restlet.jee:org.restlet:$restletVersion",
-//                  "org.restlet.jee:org.restlet.ext.ssl:$restletVersion",
-                  "org.restlet.jee:org.restlet.ext.atom:$restletVersion",
-                  "org.restlet.jee:org.restlet.ext.servlet:$restletVersion",
-                  "org.restlet.jee:org.restlet.ext.slf4j:$restletVersion"
-          ],
-
-          // Scala
-          scala:  "org.scala-lang:scala-library:$scalaVersion",
-
-          // Spring
-          spring_core: [
-                  "org.springframework:spring-beans:$springVersion",
-                  "org.springframework:spring-context:$springVersion"
-          ],
-
-          spring_testsupport: [
-                  "org.springframework:spring-test:$springVersion"
-          ],
-
-          // RDF
-          sesame: [ "org.openrdf.sesame:sesame-model:$rdfVersion",
-                  "org.openrdf.sesame:sesame-queryparser-sparql:$rdfVersion",
-                  "org.openrdf.sesame:sesame-repository-dataset:$rdfVersion",
-                  "org.openrdf.sesame:sesame-repository-http:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-api:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-n3:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-ntriples:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-rdfxml:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-trig:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-trix:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-turtle:$rdfVersion",
-                  "org.openrdf.sesame:sesame-sail-api:$rdfVersion",
-                  "org.openrdf.sesame:sesame-sail-memory:$rdfVersion",
-                  "org.openrdf.sesame:sesame-sail-nativerdf:$rdfVersion",
-                  "org.openrdf.sesame:sesame-sail-rdbms:$rdfVersion"
-          ],
-          sparql: [
-                  "org.openrdf.sesame:sesame-queryresultio-sparqlxml:$rdfVersion",
-                  "org.openrdf.sesame:sesame-queryresultio-sparqljson:$rdfVersion"
-          ],
-
-          // SOLR
-          solr: [ "org.apache.solr:solr-core:$solrVersion",
-                  "org.apache.solr:solr-solrj:$solrVersion"
-          ],
-
-          // Jetty
-          jetty_server: "org.eclipse.jetty:jetty-server:$jettyVersion",
-          jetty_webapp: "org.eclipse.jetty:jetty-webapp:$jettyVersion",
-          jetty_servlet: "org.eclipse.jetty:jetty-servlet:$jettyVersion",
-          jetty_http: "org.eclipse.jetty:jetty-http:$jettyVersion",
-          jetty_io: "org.eclipse.jetty:jetty-io:$jettyVersion",
-          jetty_jmx: "org.eclipse.jetty:jetty-jmx:$jettyVersion",
-          jetty_security: "org.eclipse.jetty:jetty-security:$jettyVersion",
-          jetty_jsp: "org.eclipse.jetty:jetty-jsp:$jettyVersion",
-          jetty_util: "org.eclipse.jetty:jetty-util:$jettyVersion",
-          jetty_continuation: "org.eclipse.jetty:jetty-continuation:$jettyVersion",
-          jetty_client: "org.eclipse.jetty:jetty-client:$jettyVersion",
-          jetty_xml: "org.eclipse.jetty:jetty-xml:$jettyVersion",
-
-          // Scripting
-          groovy: "org.codehaus.groovy:groovy-all:$groovyVersion",
-
-          javascript: "org.mozilla:rhino:$javascriptVersion",
-
-          // Library & Extension dependencies
-          jackson_mapper: "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion",
-          ehcache: "org.ehcache:ehcache:$ehcacheVersion",
-          elasticsearch: [
-              "org.elasticsearch:elasticsearch:$elasticsearchVersion",
-              "org.elasticsearch.client:transport:$elasticsearchVersion",
-              // Elasticsearch 5.0 do not work with log4j 2.7
-              "org.apache.logging.log4j:log4j-api:2.6.2",
-              "org.apache.logging.log4j:log4j-core:2.6.2"
-          ],
-          geode: "org.apache.geode:geode-core:$geodeVersion",
-          h2: "com.h2database:h2:$h2Version",
-          hazelcast: "com.hazelcast:hazelcast:$hazelcastVersion",
-          jclouds_core: "org.apache.jclouds:jclouds-core:$jcloudsVersion",
-          jclouds_blobstore: "org.apache.jclouds:jclouds-allblobstore:$jcloudsVersion",
-          jclouds_filesystem: "org.apache.jclouds.api:filesystem:$jcloudsVersion",
-          jdbm: "jdbm:jdbm:$jdbmVersion",
-          jedis: "redis.clients:jedis:$jedisVersion",
-          jgoodies_looks: "com.jgoodies:jgoodies-looks:$jgoodiesLooksVersion",
-          leveldb_api: "org.iq80.leveldb:leveldb-api:$leveldbVersion",
-          leveldb_java: "org.iq80.leveldb:leveldb:$leveldbVersion",
-          leveldb_jni_all: "org.fusesource.leveldbjni:leveldbjni-all:$leveldbJniVersion",
-          mongodb: "org.mongodb:mongo-java-driver:$mongodbVersion",
-          riak: "com.basho.riak:riak-client:$riakVersion",
-          jta: "javax.transaction:jta:$jtaVersion",
-          javaSqlGenerator: "org.java-sql-generator:org.java-sql-generator.api:$javasqlgeneratorVersion",
-          javaSqlGeneratorImpl: "org.java-sql-generator:org.java-sql-generator.implementation:$javasqlgeneratorVersion",
-          velocity: "org.apache.velocity:velocity:$velocityVersion",
-          commons_dbcp: "org.apache.commons:commons-dbcp2:$commonsDbcpVersion",
-          commons_lang: "org.apache.commons:commons-lang3:$commonsLangVersion",
-          servlet_api: "javax.servlet:javax.servlet-api:$servletVersion",
-          http_client: "org.apache.httpcomponents:httpclient:$httpClientVersion",
-          woodstox: "org.codehaus.woodstox:woodstox-core-asl:$woodstoxVersion",
-          restlet_xml: "org.restlet.jee:org.restlet.ext.xml:$restletVersion",
-          bouncy_castle: "org.bouncycastle:bcprov-jdk15on:$bouncyVersion",
-          dnsjava: "dnsjava:dnsjava:$dnsJavaVersion",
-          freemarker: "org.freemarker:freemarker:$freemarkerVersion",
-          shiro: "org.apache.shiro:shiro-core:$shiroVersion",
-          shiro_web: "org.apache.shiro:shiro-web:$shiroVersion",
-          bonecp: "com.jolbox:bonecp:$bonecpVersion",
-          liquibase: "org.liquibase:liquibase-core:$liquibaseVersion",
-          sked: "org.codeartisans:sked:$skedVersion",
-          pdfbox: "org.apache.pdfbox:pdfbox:$pdfboxVersion",
-          prefuse: "de.sciss:prefuse-core:$prefuseVersion",
-          spymemcached: "net.spy:spymemcached:$spymemcachedVersion",
-          codahale_metrics: [
-              "io.dropwizard.metrics:metrics-core:$codahaleMetricsVersion",
-              "io.dropwizard.metrics:metrics-healthchecks:$codahaleMetricsVersion"
-          ],
-
-          // Testing
-          junit: "junit:junit:$junitVersion",
-          hamcrest: [
-                  "org.hamcrest:hamcrest-core:$hamcrestVersion",
-                  "org.hamcrest:hamcrest-library:$hamcrestVersion"
-          ],
-          awaitility: "org.awaitility:awaitility:$awaitilityVersion",
-          easymock: "org.easymock:easymock:$easyMockVersion",
-          mockito: "org.mockito:mockito-core:$mockitoVersion",
-
-          // Tests dependencies
-          derby: "org.apache.derby:derby:$derbyVersion",
-          derbyclient: "org.apache.derby:derbyclient:$derbyVersion",
-          derbynet: "org.apache.derby:derbynet:$derbyVersion",
-          postgres: "org.postgresql:postgresql:$postgresqlVersion",
-          mysql_connector: "mysql:mysql-connector-java:$mysqlVersion",
-          sqlite: "org.xerial:sqlite-jdbc:$sqliteVersion",
-  ]
-}
-
-// Global transitive dependencies substitution rules
-// See https://docs.gradle.org/current/userguide/dependency_management.html#dependency_substitution_rules
-// See https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.DependencySubstitutions.html
-allprojects {
-  configurations.all {
-    resolutionStrategy.dependencySubstitution.all { DependencySubstitution dep ->
-      if( dep.requested instanceof ModuleComponentSelector ) {
-        // Always resolve SLF4J to the same version
-        if( dep.requested.group == 'org.slf4j' ) {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: slf4jVersion
-        }
-        // Always resolve ASM to the same version
-        if( dep.requested.group == 'org.ow2.asm' ) {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: asmVersion
-        }
-        // Always resolve OSGi to the same version
-        if( dep.requested.group == 'org.osgi' ) {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: osgiVersion
-        }
-        // Always resolve Jackson to the same version
-        if( dep.requested.group.startsWith( 'com.fasterxml.jackson' ) && dep.requested.module != 'jackson-parent' ) {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: jacksonVersion
-        }
-        // woodstox:wstx-asl is broken (no pom), use org.codehaus.woodstox:wstx-asl instead
-        if( dep.requested.group == 'woodstox' && dep.requested.module == 'wstx-asl' ) {
-          dep.useTarget group: 'org.codehaus.woodstox', name: 'wstx-asl', version: dep.requested.version
-        }
-        // some bad citizens have SNAPSHOT parents ...
-        if( dep.requested.module == 'commons-sandbox-parent' && dep.requested.version == '3-SNAPSHOT') {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: '3'
-        }
-        // GSON 2.3 POM is invalid, use 2.3.1 instead .. see https://github.com/google/gson/issues/588
-        if( dep.requested.group == 'com.google.code.gson' && dep.requested.module == 'gson' && dep.requested.version == '2.3' ) {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: '2.3.1'
-        }
-        // Findbugs Annotation is LGPL, use https://github.com/stephenc/findbugs-annotations which is
-        // Apache 2 licensed instead
-        if( dep.requested.group == 'net.sourceforge.findbugs' && dep.requested.module == 'annotations' ) {
-          dep.useTarget group: 'com.github.stephenc.findbugs', name: 'findbugs-annotations', version: '1.3.9-1'
-        }
-      }
-    }
-  }
-}


Mime
View raw message