You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by pa...@apache.org on 2016/12/24 10:29:27 UTC

[15/19] zest-java git commit: build: detangle buildSrc

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/publish/PublishingPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/publish/PublishingPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/publish/PublishingPlugin.groovy
deleted file mode 100644
index 843f519..0000000
--- a/buildSrc/src/main/groovy/org/apache/polygene/gradle/publish/PublishingPlugin.groovy
+++ /dev/null
@@ -1,183 +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.
- */
-package org.apache.polygene.gradle.publish
-
-import groovy.transform.CompileStatic
-import org.apache.polygene.gradle.PolygeneExtension
-import org.apache.polygene.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.polygene.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 polygene = project.extensions.getByType( PolygeneExtension )
-    def config = new Config()
-    config.snapshots = polygene.developmentVersion
-    config.releases = polygene.releaseVersion
-    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.rootProject.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/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/CheckReleaseSpecTask.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/CheckReleaseSpecTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/CheckReleaseSpecTask.groovy
deleted file mode 100644
index d1fe082..0000000
--- a/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/CheckReleaseSpecTask.groovy
+++ /dev/null
@@ -1,75 +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.
- */
-package org.apache.polygene.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/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ModuleReleaseSpec.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ModuleReleaseSpec.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ModuleReleaseSpec.groovy
deleted file mode 100644
index c80c6bd..0000000
--- a/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ModuleReleaseSpec.groovy
+++ /dev/null
@@ -1,53 +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.
- */
-package org.apache.polygene.gradle.release;
-
-import org.gradle.api.Project
-
-class ModuleReleaseSpec
-{
-  boolean satisfiedBy( Project project )
-  {
-    def devStatusFile = new File( project.projectDir, "dev-status.xml" )
-    if( !devStatusFile.exists() )
-    {
-      return false
-    }
-    def module = new XmlSlurper().parse( devStatusFile )
-    def codebase = module.status.codebase.text() as String
-    def docs = module.status.documentation.text() as String
-    def tests = module.status.unittests.text() as String
-    return satisfiedBy( codebase, docs, tests )
-  }
-
-  boolean satisfiedBy( String codebase, String docs, String tests )
-  {
-    def satisfied = ( codebase == 'none' && docs == 'complete' )
-    satisfied |= ( codebase == 'early'
-            && ( docs == 'complete' || docs == 'good' )
-            && ( tests == 'complete' || tests == 'good' ) )
-    satisfied |= ( codebase == 'beta'
-            && ( docs == 'complete' || docs == 'good' || docs == 'brief' )
-            && ( tests == 'complete' || tests == 'good' || tests == 'some' ) )
-    satisfied |= ( codebase == 'stable' )
-    satisfied |= ( codebase == 'mature' )
-    // TODO Add a task to report this easily
-    // println "$project.name($satisfied) -> $codebase, $docs, $tests"
-    return satisfied
-  }
-}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseApprovedProjectsTask.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseApprovedProjectsTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseApprovedProjectsTask.groovy
deleted file mode 100644
index 9a93925..0000000
--- a/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseApprovedProjectsTask.groovy
+++ /dev/null
@@ -1,57 +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.
- */
-package org.apache.polygene.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/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseSpecExtension.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseSpecExtension.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseSpecExtension.groovy
deleted file mode 100644
index c5b0887..0000000
--- a/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseSpecExtension.groovy
+++ /dev/null
@@ -1,40 +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.
- */
-package org.apache.polygene.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/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseSpecPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseSpecPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseSpecPlugin.groovy
deleted file mode 100644
index 34422a9..0000000
--- a/buildSrc/src/main/groovy/org/apache/polygene/gradle/release/ReleaseSpecPlugin.groovy
+++ /dev/null
@@ -1,56 +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.
- */
-package org.apache.polygene.gradle.release
-
-import groovy.transform.CompileStatic
-import org.apache.polygene.gradle.TaskGroups
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.Task
-
-@CompileStatic
-class ReleaseSpecPlugin implements Plugin<Project>
-{
-  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
-      task.description = 'Apply release specification to projects in the build'
-    }
-    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/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/RootPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/RootPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/RootPlugin.groovy
new file mode 100644
index 0000000..5b0c497
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/RootPlugin.groovy
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.gradle.structure
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.BasePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+@CompileStatic
+class RootPlugin implements Plugin<Project>
+{
+  static final String PROJECT_TITLE = 'Apache Polygene\u2122 (Java Edition) SDK'
+  static final String PROJECT_DESCRIPTION = 'Apache Polygene\u2122 (Java Edition) is a framework for domain centric ' +
+                                            'application development, including evolved concepts from AOP, DI and DDD.'
+
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply BasePlugin
+    applyProjectMetadata( project )
+  }
+
+  private static void applyProjectMetadata( Project project )
+  {
+    def extraProperties = project.extensions.extraProperties
+    extraProperties.set 'title', PROJECT_TITLE
+    extraProperties.set 'description', PROJECT_DESCRIPTION
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/SettingsPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/SettingsPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/SettingsPlugin.groovy
new file mode 100644
index 0000000..f252055
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/SettingsPlugin.groovy
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.gradle.structure
+
+import org.gradle.api.Plugin
+import org.gradle.api.initialization.Settings
+import org.gradle.api.JavaVersion
+
+class SettingsPlugin implements Plugin<Settings>
+{
+  @Override
+  void apply( Settings settings )
+  {
+    checkPreconditions settings
+  }
+
+  static void checkPreconditions( Settings setting )
+  {
+    def java = JavaVersion.current()
+    def mini = JavaVersion.VERSION_1_8
+    if( java < mini )
+    {
+      throw new Exception( "Cannot build using Java ${ java }, please use ${ JavaVersion.VERSION_1_8 } or greater." )
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/core/CorePlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/core/CorePlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/core/CorePlugin.groovy
new file mode 100644
index 0000000..a07d88f
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/core/CorePlugin.groovy
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.gradle.structure.core
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.code.PublishedCodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.tasks.compile.JavaCompile
+
+@CompileStatic
+class CorePlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply PublishedCodePlugin
+    configureJava( project )
+  }
+
+  private static void configureJava( Project project )
+  {
+    project.tasks.withType( JavaCompile ) { JavaCompile task ->
+      // Unchecked warnings for non-test compilations
+      if( !task.name.toLowerCase( Locale.US ).contains( 'test' ) )
+      {
+        task.options.compilerArgs << '-Xlint:unchecked'
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/distributions/DistributionsPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/distributions/DistributionsPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/distributions/DistributionsPlugin.groovy
new file mode 100644
index 0000000..0deb84d
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/distributions/DistributionsPlugin.groovy
@@ -0,0 +1,523 @@
+/*
+ *  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.polygene.gradle.structure.distributions
+
+import groovy.transform.CompileStatic
+import groovy.transform.TypeCheckingMode
+import java.nio.file.Files
+import java.nio.file.Path
+import org.apache.commons.io.FileUtils
+import org.apache.polygene.gradle.BasePlugin
+import org.apache.polygene.gradle.TaskGroups
+import org.apache.polygene.gradle.code.PublishedCodePlugin
+import org.apache.polygene.gradle.dependencies.DependenciesDeclarationExtension
+import org.apache.polygene.gradle.dependencies.DependenciesPlugin
+import org.apache.polygene.gradle.structure.release.ReleaseSpecExtension
+import org.apache.polygene.gradle.tasks.ExecLogged
+import org.apache.rat.gradle.RatTask
+import org.apache.tools.ant.filters.ReplaceTokens
+import org.gradle.api.Action
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.artifacts.Dependency
+import org.gradle.api.artifacts.component.ModuleComponentIdentifier
+import org.gradle.api.artifacts.result.ComponentArtifactsResult
+import org.gradle.api.artifacts.result.ResolvedArtifactResult
+import org.gradle.api.artifacts.result.ResolvedDependencyResult
+import org.gradle.api.file.CopySpec
+import org.gradle.api.file.FileCopyDetails
+import org.gradle.api.tasks.Copy
+import org.gradle.api.tasks.Sync
+import org.gradle.api.tasks.bundling.Compression
+import org.gradle.api.tasks.bundling.Tar
+import org.gradle.api.tasks.bundling.Zip
+import org.gradle.language.base.plugins.LifecycleBasePlugin
+import org.gradle.maven.MavenModule
+import org.gradle.maven.MavenPomArtifact
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor
+import org.gradle.plugins.ide.internal.resolver.model.IdeExtendedRepoFileDependency
+
+// TODO Expose all project outputs into configurations
+@CompileStatic
+class DistributionsPlugin implements Plugin<Project>
+{
+  static class TaskNames
+  {
+    static final String STAGE_SOURCE_DIST = 'stageSourceDistribution'
+    static final String ZIP_SOURCE_DIST = 'zipSourceDistribution'
+    static final String TAR_SOURCE_DIST = 'tarSourceDistribution'
+
+    static final String STAGE_MAVEN_BINARIES = 'stageBinariesMavenRepository'
+    static final String STAGE_BINARY_DIST = 'stageBinaryDistribution'
+    static final String ZIP_BINARY_DIST = 'zipBinaryDistribution'
+    static final String TAR_BINARY_DIST = 'tarBinaryDistribution'
+
+    private static final String STAGE_MAVEN_DEPENDENCIES = 'stageDependenciesMavenRepository'
+    static final String ZIP_DEPENDENCIES_DIST = 'zipDependenciesDistribution'
+
+    static final String CHECK_DISTRIBUTIONS = 'checkDistributions'
+    static final String CHECK_SOURCE_DIST = 'checkSourceDistribution'
+    static final String CHECK_BINARY_DIST = 'checkBinaryDistribution'
+    private static final String RAT_SOURCE_DIST = 'ratSourceDistribution'
+    private static final String BUILD_SOURCE_DIST = 'buildSourceDistribution'
+    private static final String RAT_BINARY_DIST = 'ratBinaryDistribution'
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    project.plugins.apply BasePlugin
+    project.plugins.apply org.gradle.api.plugins.BasePlugin
+    project.plugins.apply DependenciesPlugin
+    applyStageBinariesMavenRepository project
+    applyStageLibrariesMavenRepository project
+    applyAssembleDistributions project
+    applyCheckDistributions project
+    configureDistributionChecksums project
+  }
+
+  private static void applyAssembleDistributions( Project project )
+  {
+    applySourceDistribution project
+    applyBinaryDistribution project
+  }
+
+  private static void applyCheckDistributions( Project project )
+  {
+    def distChecks = [ applySourceDistributionCheck( project ),
+                       applyBinaryDistributionCheck( project ) ]
+    project.tasks.create( TaskNames.CHECK_DISTRIBUTIONS ) { Task task ->
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.description = 'Run all distribution checks.'
+      task.dependsOn distChecks
+    }
+  }
+
+  private static void applySourceDistribution( Project project )
+  {
+    def releaseSpec = project.extensions.getByType( ReleaseSpecExtension )
+    def srcDistFilesCopySpec = project.copySpec { CopySpec spec ->
+      spec.from project.rootProject.projectDir
+      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.publishedProjects.each { p ->
+        def relPath = new File( project.rootProject.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 caches
+      spec.exclude '**/.gradletasknamecache' // Gradle shell completion cache
+      spec.into '.'
+    }
+    def srcDistSupplementaryFilesCopySpec = project.copySpec { CopySpec spec ->
+      spec.from project.file( 'src/src-dist' )
+      spec.into '.'
+    }
+    def srcDistFilteredFilesTask = project.tasks.create 'srcDistFilteredFiles'
+    srcDistFilteredFilesTask.description = 'Apply release specification to source distribution build scripts'
+    // 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()
+      if( releaseSpec.releaseVersion )
+      {
+        def filteredSettings = ''
+        def unapprovedProjectPaths = releaseSpec.unapprovedProjects.collect { p -> p.path.substring( 1 ) }
+        project.rootProject.file( 'settings.gradle' ).readLines().each { line ->
+          if( !unapprovedProjectPaths.find { p -> line.contains p } )
+          {
+            filteredSettings += "$line\n"
+          }
+        }
+        settingsFile.text = filteredSettings
+      }
+      else
+      {
+        settingsFile.text = project.rootProject.file( 'settings.gradle' ).text
+      }
+      // gradle.properties
+      def gradlePropsFile = new File( filteredDir, 'gradle.properties' )
+      gradlePropsFile.parentFile.mkdirs()
+      gradlePropsFile.text = project.rootProject.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-polygene-java-$project.version-src"
+      spec.with srcDistFilesCopySpec
+      spec.with srcDistSupplementaryFilesCopySpec
+      spec.with srcDistFilteredFilesCopySpec
+    }
+
+    def zipSources = project.tasks.create( TaskNames.ZIP_SOURCE_DIST, Zip ) { Zip task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Assembles .zip source distribution.'
+      task.baseName = 'apache-polygene-java'
+      task.with srcDistCopySpec
+      task.classifier = 'src'
+    }
+    def tarSources = project.tasks.create( TaskNames.TAR_SOURCE_DIST, Tar ) { Tar task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Assembles .tar.gz source distribution.'
+      task.baseName = 'apache-polygene-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.STAGE_SOURCE_DIST, Copy ) { Copy task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = "Stages the source distribution in the build directory."
+      task.with srcDistCopySpec
+      task.into 'build/stage/source-distribution'
+    }
+  }
+
+  private static Task applySourceDistributionCheck( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    project.plugins.apply 'org.nosphere.apache.rat-base'
+    def unpackedSrcDistDir = project.file( "build/stage/source-distribution/apache-polygene-java-$project.version-src" )
+    project.tasks.create( TaskNames.RAT_SOURCE_DIST, RatTask, { RatTask task ->
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.description = 'Checks the source distribution using Apache RAT.'
+      task.dependsOn TaskNames.STAGE_SOURCE_DIST
+      task.setInputDir unpackedSrcDistDir.absolutePath
+      task.onlyIf { !releaseSpec.developmentVersion }
+      task.excludes = [
+        '**/.DS_Store/**', '**/._*',
+        // Git Files
+        '**/.git/**', '**/.gitignore',
+        // Gradle Files
+        'gradle/wrapper/**', '**/gradlew', '**/gradlew.bat', '**/.gradle/**',
+        // Build Output
+        '**/build/**', '**/derby.log', 'out/**',
+        // IDE Files
+        '**/.idea/**', '**/*.iml', '**/*.ipr', '**/*.iws',
+        '**/.settings/**', '**/.classpath', '**/.project',
+        '**/.gradletasknamecache', '**/private/cache/**',
+        '**/.nb-gradle-properties', '**/.nb-gradle/**',
+        // JSON files are not allowed to have comments, according to http://www.json.org/ and http://www.ietf.org/rfc/rfc4627.txt
+        '**/*.json',
+        // Various Text Resources
+        '**/README.*', '**/README*.*', '**/TODO',
+        '**/src/main/resources/**/*.txt',
+        '**/src/test/resources/**/*.txt',
+        'libraries/rest-server/src/main/resources/**/*.htm',
+        'libraries/rest-server/src/main/resources/**/*.atom',
+        'tools/qidea/src/main/resources/**/*.ft',
+        'tools/qidea/src/main/resources/**/*.template',
+        // Graphic Resources
+        '**/*.svg', '**/*.gif', '**/*.png', '**/*.jpg', '**/*.psd',
+        // Keystores
+        '**/*.jceks',
+        // Syntax Highlighter - MIT
+        'manual/**/sh*.css', 'manual/**/sh*.js',
+        // jQuery & plugins - MIT
+        'manual/**/jquery*.js',
+        // W3C XML Schemas - W3C Software License
+        'samples/rental/src/main/resources/*.xsd',
+        // Polygene Generator Heroes Templates - MIT
+        'tools/generator-polygene/app/templates/Heroes/**',
+        // templates that will become the user's source files, should not have license headers
+        'tools/shell/src/dist/etc/templates/**',
+      ]
+    } as Action<RatTask> )
+    project.tasks.create( TaskNames.BUILD_SOURCE_DIST, ExecLogged, { ExecLogged task ->
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.description = 'Checks the source distribution by running `gradle build` inside.'
+      task.dependsOn TaskNames.STAGE_SOURCE_DIST
+      task.mustRunAfter TaskNames.RAT_SOURCE_DIST
+      def workDir = project.file( "$project.buildDir/tmp/${ TaskNames.BUILD_SOURCE_DIST }" )
+      task.inputs.dir unpackedSrcDistDir
+      task.workingDir = workDir
+      task.commandLine = [ './gradlew', 'build', '-u', '-s', /* '-g', workDir */ ]
+      task.doFirst {
+        project.copy { CopySpec spec ->
+          spec.from unpackedSrcDistDir
+          spec.into workDir
+        }
+      }
+      task.doLast {
+        if( workDir.exists() )
+        {
+          FileUtils.deleteDirectory( workDir )
+        }
+      }
+    } as Action<ExecLogged> )
+    project.tasks.create( TaskNames.CHECK_SOURCE_DIST ) { Task task ->
+      task.description = "Checks the source distribution."
+      task.dependsOn TaskNames.RAT_SOURCE_DIST, TaskNames.BUILD_SOURCE_DIST
+    }
+  }
+
+  private static void applyBinaryDistribution( Project project )
+  {
+    def releaseSpec = project.extensions.getByType( ReleaseSpecExtension )
+    def reportsDistCopySpec = project.copySpec { CopySpec spec ->
+      spec.from "$project.rootProject.projectDir/reports/build/reports"
+      spec.into 'docs/reports'
+    }
+    def docsCopySpec = project.copySpec { CopySpec spec ->
+      spec.from "$project.rootProject.projectDir/reports/build/docs"
+      spec.from "$project.rootProject.projectDir/manual/build/docs/website"
+      spec.into 'docs'
+    }
+    def libsCopySpec = project.copySpec { CopySpec spec ->
+      spec.from project.tasks.getByName( TaskNames.STAGE_MAVEN_BINARIES )
+      spec.into 'libs/'
+      spec.exclude '**-testsources.jar'
+      spec.exclude '**/*.asc'
+    }
+    def extraDistTextCopySpec = project.copySpec { CopySpec spec ->
+      releaseSpec.publishedProjects.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.publishedProjects.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-polygene-java-$project.version-bin"
+      spec.with binDistNoticesCopySpec
+      spec.with docsCopySpec
+      spec.with reportsDistCopySpec
+      spec.with extraDistTextCopySpec
+      spec.with extraDistBinCopySpec
+      spec.with libsCopySpec
+    }
+
+    def binariesBuildDependencies = {
+      project.rootProject.allprojects
+             .findAll { p -> p.plugins.hasPlugin( PublishedCodePlugin ) || p.path == ':manual' || p.path == ':reports' }
+             .collect { p -> "${ p.path }:${ LifecycleBasePlugin.BUILD_TASK_NAME }" }
+    }
+
+    def zipBinaries = project.tasks.create( TaskNames.ZIP_BINARY_DIST, Zip ) { Zip task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Assembles .zip binary distribution.'
+      task.dependsOn binariesBuildDependencies
+      task.baseName = 'apache-polygene-java'
+      task.classifier = 'bin'
+      task.with binDistImage
+    }
+    def tarBinaries = project.tasks.create( TaskNames.TAR_BINARY_DIST, Tar ) { Tar task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Assembles .tar.gz binary distribution.'
+      task.dependsOn binariesBuildDependencies
+      task.baseName = 'apache-polygene-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.STAGE_BINARY_DIST, Copy ) { Copy task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = "Stages the binary distribution in the build directory."
+      task.with binDistImage
+      task.into 'build/stage/binary-distribution'
+    }
+  }
+
+  private static Task applyBinaryDistributionCheck( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    project.plugins.apply 'org.nosphere.apache.rat-base'
+    def unpackedBinDistDir = project.file( "build/stage/binary-distribution/apache-polygene-java-$project.version-bin" )
+    project.tasks.create( TaskNames.RAT_BINARY_DIST, RatTask, { RatTask task ->
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.description = "Checks the binary distribution using Apache RAT."
+      task.onlyIf { !releaseSpec.developmentVersion }
+      task.dependsOn TaskNames.STAGE_BINARY_DIST
+      task.inputDir = unpackedBinDistDir.absolutePath
+      task.reportDir = project.file( 'build/reports/rat-bin-dist' )
+      task.excludes = [
+        '.gradle/**',
+        'docs/**',
+        'etc/templates/**',
+        'libs/**'
+      ]
+    } as Action<RatTask> )
+    project.tasks.create( TaskNames.CHECK_BINARY_DIST ) { Task task ->
+      task.description = 'Checks the binary distribution.'
+      task.dependsOn TaskNames.RAT_BINARY_DIST
+    }
+  }
+
+  @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 applyStageBinariesMavenRepository( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    project.tasks.create( TaskNames.STAGE_MAVEN_BINARIES, Sync, { Sync task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Stages published binaries as a maven repository in the build directory.'
+      releaseSpec.publishedProjects.each { p ->
+        task.dependsOn "${ p.path }:uploadStageArchives"
+        task.from "${ p.buildDir }/stage/archives"
+      }
+      task.into project.file( "$project.buildDir/stage/maven-binaries" )
+    } as Action<Sync> )
+  }
+
+  private static void applyStageLibrariesMavenRepository( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    def dependenciesDeclaration = project.rootProject.extensions.getByType DependenciesDeclarationExtension
+    def stageTask = project.tasks.create( TaskNames.STAGE_MAVEN_DEPENDENCIES ) { Task task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Stages dependencies of published binaries as a maven repository in the build directory. (BIG)'
+      def output = project.file "$project.buildDir/stage/dependencies"
+      task.inputs.property 'libraries', dependenciesDeclaration.libraries
+      task.outputs.dir output
+      task.doLast {
+        // Resolve runtime dependencies across all staged projects
+        def libraries = [ ] as Set<Dependency>
+        releaseSpec.publishedProjects.each { p ->
+          libraries += p.configurations.getByName( 'runtime' ).allDependencies
+        }
+        def configuration = project.configurations.detachedConfiguration( libraries as Dependency[] )
+        DependenciesPlugin.applyDependencyResolutionRules configuration, dependenciesDeclaration
+        // Copy Maven POMs
+        def allDependencies = configuration.incoming.resolutionResult.allDependencies as Set<ResolvedDependencyResult>
+        def componentIds = allDependencies.collect { it.selected.id }
+        def result = project.dependencies.createArtifactResolutionQuery()
+                            .forComponents( componentIds )
+                            .withArtifacts( MavenModule, MavenPomArtifact )
+                            .execute()
+        result.resolvedComponents.each { ComponentArtifactsResult component ->
+          def id = component.id
+          if( id instanceof ModuleComponentIdentifier )
+          {
+            def artifact = component.getArtifacts( MavenPomArtifact )[ 0 ]
+            if( artifact instanceof ResolvedArtifactResult )
+            {
+              def groupDir = new File( output, id.getGroup().split( "\\." ).join( '/' ) )
+              File moduleDir = new File( groupDir, "${ id.getModule() }/${ id.getVersion() }" )
+              Files.createDirectories moduleDir.toPath()
+              def destination = new File( moduleDir, artifact.getFile().getName() ).toPath()
+              Files.exists( destination ) ?: Files.copy( artifact.getFile().toPath(), destination )
+            }
+          }
+        }
+        // Copy Maven artifacts using the Gradle IDE Model
+        // Include sources if available, otherwise include javadoc if available
+        IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
+        def ideDependencies = dependenciesExtractor.extractRepoFileDependencies project.dependencies,
+                                                                                [ configuration ], [ ],
+                                                                                true, true
+        ideDependencies.each { IdeExtendedRepoFileDependency ideDependency ->
+          def id = ideDependency.id
+          def groupDir = new File( output, id.group.split( "\\." ).join( '/' ) )
+          File moduleDir = new File( groupDir, "${ id.name }/${ id.version }" )
+          Files.createDirectories moduleDir.toPath()
+          Path destination = new File( moduleDir, ideDependency.file.name ).toPath()
+          Files.exists( destination ) ?: Files.copy( ideDependency.file.toPath(), destination )
+          if( ideDependency.sourceFile )
+          {
+            def sourceDestination = new File( moduleDir, ideDependency.sourceFile.name ).toPath()
+            Files.exists( sourceDestination ) ?: Files.copy( ideDependency.sourceFile.toPath(), sourceDestination )
+          }
+          else if( ideDependency.javadocFile )
+          {
+            def javadocDestination = new File( moduleDir, ideDependency.javadocFile.name ).toPath()
+            Files.exists( javadocDestination ) ?: Files.copy( ideDependency.javadocFile.toPath(), javadocDestination )
+          }
+        }
+      }
+    }
+    project.tasks.create( TaskNames.ZIP_DEPENDENCIES_DIST, Zip ) { Zip task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Assemble .zip dependencies distribution (BIG)'
+      task.baseName = 'apache-polygene-java'
+      task.classifier = 'dependencies'
+      task.from stageTask
+      task.into "apache-polygene-java-$project.version-dependencies"
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/extensions/ExtensionPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/extensions/ExtensionPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/extensions/ExtensionPlugin.groovy
new file mode 100644
index 0000000..735952c
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/extensions/ExtensionPlugin.groovy
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.gradle.structure.extensions
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.code.PublishedCodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+@CompileStatic
+class ExtensionPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply PublishedCodePlugin
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalPlugin.groovy
new file mode 100644
index 0000000..baa8842
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalPlugin.groovy
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.gradle.structure.internals
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.code.CodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+@CompileStatic
+class InternalPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply CodePlugin
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/libraries/LibraryPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/libraries/LibraryPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/libraries/LibraryPlugin.groovy
new file mode 100644
index 0000000..7603e8b
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/libraries/LibraryPlugin.groovy
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.gradle.structure.libraries
+
+import org.apache.polygene.gradle.code.PublishedCodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+class LibraryPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply PublishedCodePlugin
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/AsciidocBuildInfoPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/AsciidocBuildInfoPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/AsciidocBuildInfoPlugin.groovy
new file mode 100644
index 0000000..220bc38
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/AsciidocBuildInfoPlugin.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.polygene.gradle.structure.manual
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.TaskGroups
+import org.gradle.api.Project
+import org.gradle.api.Plugin
+
+@CompileStatic
+class AsciidocBuildInfoPlugin implements Plugin<Project>
+{
+  final static String TASK_NAME = 'makeAsciidocBuildInfo'
+
+  void apply( Project project )
+  {
+    def buildInfoDir = new File( project.buildDir, "docs/buildinfo" );
+
+    def makeAsciidocBuildInfoTask = project.tasks.create( TASK_NAME )
+    makeAsciidocBuildInfoTask.group = TaskGroups.DOCUMENTATION
+    makeAsciidocBuildInfoTask.description = 'Generates asciidoc artifact snippet'
+    makeAsciidocBuildInfoTask.doLast {
+      buildInfoDir.mkdirs()
+
+      // GroupID, ArtifactID, Version table in artifact.txt
+      def artifactTableFile = new File( buildInfoDir, "artifact.txt" )
+      def artifactTable = """
+        |.Artifact
+        |[role="artifact", options="header,autowidth"]
+        ||===================================================
+        ||Group ID|Artifact ID|Version
+        ||${ project.group }|${ project.name }|${ project.version }
+        ||===================================================
+        """.stripMargin()
+      artifactTableFile.withWriter { out -> out.println( artifactTable ) }
+    }
+
+    // Declare inputs/outputs
+    if( project.getBuildFile() != null && project.getBuildFile().exists() )
+    {
+      makeAsciidocBuildInfoTask.getInputs().file( project.getBuildFile() )
+    }
+    makeAsciidocBuildInfoTask.getOutputs().file( buildInfoDir )
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/DocumentationTask.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/DocumentationTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/DocumentationTask.groovy
new file mode 100644
index 0000000..d32320d
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/DocumentationTask.groovy
@@ -0,0 +1,320 @@
+/*
+ *  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.polygene.gradle.structure.manual
+
+import groovy.io.FileType
+import groovy.transform.CompileStatic
+import groovy.transform.TypeCheckingMode
+import java.security.MessageDigest
+import org.apache.polygene.gradle.structure.release.ReleaseSpecExtension
+import org.apache.polygene.gradle.tasks.ExecLogged
+import org.gradle.api.Action
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.CopySpec
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputDirectory
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.TaskAction
+import org.gradle.process.ExecSpec
+
+// TODO: try to use dependencies for FOP and execute within the same JVM.
+// TODO: move the bulk of resources into this plugin, instead of sitting in the project.
+@CompileStatic
+class DocumentationTask extends DefaultTask
+{
+  @Input
+  String docName
+  @Input
+  String docType
+
+  @InputDirectory
+  File getCommonResourcesDir()
+  { project.file( 'src/resources' ) }
+
+  @InputDirectory
+  File getConfigDir()
+  { project.file( 'src/conf' ) }
+
+  @InputDirectory
+  File getDocsDir()
+  { project.file( 'src/docs' ) }
+
+  @InputDirectory
+  File getSrcMainDir()
+  { project.file( 'src/main' ) }
+
+  @InputDirectory
+  File getXslDir()
+  { project.file( 'src/xsl' ) }
+
+  @InputDirectory
+  File getBuildSrcDir()
+  { project.rootProject.file( 'buildSrc/src' ) }
+
+  @InputFiles
+  getSubProjectsDocsDirs()
+  { project.rootProject.subprojects.collect { p -> p.file( 'src/docs' ) } }
+
+  @InputFiles
+  def getSubProjectsTestDirs()
+  { project.rootProject.subprojects.collect { p -> p.file( 'src/test' ) } }
+
+  @OutputDirectory
+  File getOutputDir()
+  { project.file( "${ project.buildDir }/docs/${ docName }/" ) }
+
+  @Internal
+  File getTempAsciidocDir()
+  { project.file( "${ project.buildDir }/tmp-asciidoc" ) }
+
+  @Internal
+  File getTempDir()
+  { project.file( "${ project.buildDir }/tmp/docs/${ docName }" ) }
+
+  @TaskAction
+  void generate()
+  {
+    installAsciidocFilters()
+
+    [ outputDir, tempAsciidocDir, tempDir ].each { it.deleteDir() }
+    [ outputDir, tempAsciidocDir, tempDir ].each { it.mkdirs() }
+
+    copySubProjectsDocsResources()
+    generateAsciidocAccordingToReleaseSpecification()
+    generateXDoc()
+    generateChunkedHtml()
+    // generateSingleHtml()
+    // generatePdf()
+  }
+
+  void installAsciidocFilters()
+  {
+    def digester = MessageDigest.getInstance( 'SHA' )
+    def filtersDir = project.rootProject.file( 'buildSrc/src/asciidoc/filters' )
+    def userHome = new File( System.getProperty( 'user.home' ) )
+    def dotAsciidocFiltersDir = new File( userHome, '.asciidoc/filters' )
+    def installSnippets = false
+    filtersDir.eachFileRecurse( FileType.FILES ) { originalFile ->
+      def targetFile = new File( dotAsciidocFiltersDir,
+                                 ( originalFile.toURI() as String ) - ( filtersDir.toURI() as String ) )
+      if( !targetFile.exists() )
+      {
+        installSnippets = true
+      }
+      else
+      {
+        def originalDigest = digester.digest( originalFile.bytes )
+        def targetDigest = digester.digest( targetFile.bytes )
+        if( originalDigest != targetDigest )
+        {
+          installSnippets = true
+        }
+      }
+    }
+    if( installSnippets )
+    {
+      dotAsciidocFiltersDir.mkdirs()
+      project.rootProject.copy { CopySpec spec ->
+        spec.from filtersDir
+        spec.into dotAsciidocFiltersDir
+      }
+      dotAsciidocFiltersDir.eachFileRecurse( FileType.FILES ) { file ->
+        if( file.name.endsWith( '.py' ) )
+        {
+          chmod( file, '755' )
+        }
+      }
+      println "Polygene Asciidoc Filters Installed!"
+    }
+  }
+
+  @CompileStatic( TypeCheckingMode.SKIP )
+  void chmod( File file, String permissions )
+  {
+    ant.chmod( file: file.absolutePath, perm: permissions )
+  }
+
+  def void copySubProjectsDocsResources()
+  {
+    project.rootProject.subprojects.each { p ->
+      p.copy { CopySpec spec ->
+        spec.from p.file( 'src/docs/resources' )
+        spec.into outputDir
+        spec.include '**'
+      }
+    }
+  }
+
+  void generateAsciidocAccordingToReleaseSpecification()
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    project.copy { CopySpec spec ->
+      spec.from docsDir
+      spec.into tempAsciidocDir
+      spec.include '**'
+    }
+    if( releaseSpec.releaseVersion )
+    {
+      def licenseFile = new File( tempAsciidocDir, 'userguide/libraries.txt' )
+      def extensionsFile = new File( tempAsciidocDir, 'userguide/extensions.txt' )
+      def toolsFile = new File( tempAsciidocDir, 'userguide/tools.txt' )
+      [ licenseFile, extensionsFile, toolsFile ].each { asciidocFile ->
+        def filteredFileContent = ''
+        asciidocFile.readLines().each { line ->
+          if( line.startsWith( 'include::' ) )
+          {
+            def approved = false
+            releaseSpec.approvedProjects.collect { it.projectDir }.each { approvedProjectDir ->
+              if( line.contains( "${ approvedProjectDir.parentFile.name }/${ approvedProjectDir.name }" ) )
+              {
+                approved = true
+              }
+            }
+            if( approved )
+            {
+              filteredFileContent += "$line\n"
+            }
+          }
+          else
+          {
+            filteredFileContent += "$line\n"
+          }
+        }
+        asciidocFile.text = filteredFileContent
+      }
+    }
+  }
+
+  void generateXDoc()
+  {
+    def outLog = getLogFile( 'adoc-2-docbook', 'stdout' )
+    def errLog = getLogFile( 'adoc-2-docbook', 'stderr' )
+    ExecLogged.execLogged( project, outLog, errLog, { ExecSpec spec ->
+      spec.executable = 'asciidoc'
+      spec.workingDir = '..'
+      def commonResourcesPath = relativePath( project.rootDir, commonResourcesDir )
+      def asciidocConfigPath = relativePath( project.rootDir, new File( configDir, 'asciidoc.conf' ) )
+      def docbookConfigPath = relativePath( project.rootDir, new File( configDir, 'docbook45.conf' ) )
+      def linkimagesConfigPath = relativePath( project.rootDir, new File( configDir, 'linkedimages.conf' ) )
+      def xdocOutputPath = relativePath( project.rootDir, new File( tempDir, 'xdoc-temp.xml' ) )
+      def asciidocIndexPath = relativePath( project.rootDir, new File( tempAsciidocDir, "$docName/index.txt" ) )
+      spec.args = [
+        '--attribute', 'revnumber=' + project.version,
+        '--attribute', 'level1=' + ( docType == 'article' ? 1 : 0 ),
+        '--attribute', 'level2=' + ( docType == 'article' ? 2 : 1 ),
+        '--attribute', 'level3=' + ( docType == 'article' ? 3 : 2 ),
+        '--attribute', 'level4=' + ( docType == 'article' ? 4 : 3 ),
+        '--attribute', 'importdir=' + commonResourcesPath,
+        '--backend', 'docbook',
+        '--attribute', 'docinfo1',
+        '--doctype', docType,
+        '--conf-file=' + asciidocConfigPath,
+        '--conf-file=' + docbookConfigPath,
+        '--conf-file=' + linkimagesConfigPath,
+        '--out-file', xdocOutputPath,
+        asciidocIndexPath
+      ]
+    } as Action<? super ExecSpec> )
+  }
+
+  void generateChunkedHtml()
+  {
+    project.copy { CopySpec spec ->
+      spec.from commonResourcesDir
+      spec.into outputDir
+      spec.include '**'
+    }
+    project.copy { CopySpec spec ->
+      spec.from "$docsDir/$docName/resources"
+      spec.into outputDir
+      spec.include '**'
+    }
+    def outLog = getLogFile( 'docbook-2-chunked-html', 'stdout' )
+    def errLog = getLogFile( 'docbook-2-chunked-html', 'stderr' )
+    ExecLogged.execLogged( project, outLog, errLog, { ExecSpec spec ->
+      def xsltFile = "$docsDir/$docName/xsl/chunked.xsl"
+      def outputPath = relativePath( project.projectDir, outputDir ) + '/'
+      spec.executable = 'xsltproc'
+      spec.args = [
+        '--nonet',
+        '--noout',
+        '--output', outputPath,
+        xsltFile,
+        "$tempDir/xdoc-temp.xml"
+      ]
+    } as Action<? super ExecSpec> )
+  }
+
+  void generateSingleHtml()
+  {
+    def outLog = getLogFile( 'docbook-2-html', 'stdout' )
+    def errLog = getLogFile( 'docbook-2-html', 'stderr' )
+    ExecLogged.execLogged( project, outLog, errLog, { ExecSpec spec ->
+      // XML_CATALOG_FILES=
+      String xsltFile = "$xslDir/xhtml.xsl"
+      spec.executable = 'xsltproc'
+      spec.args = [
+        '--nonet',
+        '--noout',
+        '--output', "$outputDir/${ docName }.html",
+        xsltFile,
+        "$tempDir/xdoc-temp.xml"
+      ]
+    } as Action<? super ExecSpec> )
+  }
+
+  void generatePdf()
+  {
+    // $ xsltproc --nonet ../docbook-xsl/fo.xsl article.xml > article.fo
+    def outLog = getLogFile( 'docbook-2-fo', 'stdout' )
+    def errLog = getLogFile( 'docbook-2-fo', 'stderr' )
+    ExecLogged.execLogged( project, outLog, errLog, { ExecSpec spec ->
+      String xsltFile = "$xslDir/fo.xsl"
+      spec.executable = 'xsltproc'
+      spec.args = [
+        '--nonet',
+        '--output', "$tempDir/${ docName }.fo",
+        xsltFile,
+        "$tempDir/xdoc-temp.xml"
+      ]
+    } as Action<? super ExecSpec> )
+
+    // $ fop article.fo article.pdf
+    outLog = getLogFile( 'fo-2-pdf', 'stdout' )
+    errLog = getLogFile( 'fo-2-pdf', 'stderr' )
+    ExecLogged.execLogged( project, outLog, errLog, { ExecSpec spec ->
+      spec.executable = 'fop'
+      spec.args = [
+        "$tempDir/${ docName }.fo",
+        "$outputDir/${ docName }.pdf"
+      ]
+    } as Action<? super ExecSpec> )
+  }
+
+  private File getLogFile( String step, String stream )
+  {
+    return project.file( "${ project.buildDir }/tmp/${ name }/${ step }-${ stream }.log" )
+  }
+
+  private static String relativePath( File root, File target )
+  {
+    new File( root.toURI().relativize( target.toURI() ).toString() ).path
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/ManualPlugin.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/ManualPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/ManualPlugin.groovy
new file mode 100644
index 0000000..94d0743
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/ManualPlugin.groovy
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.gradle.structure.manual
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.TaskGroups
+import org.apache.polygene.gradle.code.CodePlugin
+import org.apache.polygene.gradle.structure.release.ReleaseSpecExtension
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.language.base.plugins.LifecycleBasePlugin
+
+// TODO Expose project output into configurations
+@CompileStatic
+class ManualPlugin implements Plugin<Project>
+{
+  static class TaskNames
+  {
+    static final String WEBSITE = "website"
+    static final String MANUALS = "manuals"
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    project.plugins.apply CodePlugin
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    def websiteTask = project.tasks.create( TaskNames.WEBSITE, DocumentationTask ) { DocumentationTask task ->
+      task.group = TaskGroups.DOCUMENTATION
+      task.description = 'Generates documentation website'
+      task.dependsOn project.rootProject.allprojects.findResults { Project p ->
+        p.tasks.findByName AsciidocBuildInfoPlugin.TASK_NAME
+      }
+      task.onlyIf { isAsciidocInstalled( project, releaseSpec ) }
+      task.docName = 'website'
+      task.docType = 'article'
+    }
+    def manualsTask = project.tasks.create( TaskNames.MANUALS ) { Task task ->
+      task.group = TaskGroups.DOCUMENTATION
+      task.description = 'Generates all documentation'
+      task.dependsOn websiteTask
+    }
+    project.tasks.getByName( LifecycleBasePlugin.BUILD_TASK_NAME ).dependsOn manualsTask
+  }
+
+  private static Boolean asciidocInstalled = null
+
+  // Force when building a release version
+  // Skip if skipAsciidocIfAbsent property is set
+  // Skip if asciidoc is not found in PATH when building a development version
+  private static boolean isAsciidocInstalled( Project project, ReleaseSpecExtension releaseSpec )
+  {
+    if( asciidocInstalled == null )
+    {
+      def skipAsciidocIfAbsent = project.findProperty 'skipAsciidocIfAbsent'
+      if( !skipAsciidocIfAbsent && releaseSpec.releaseVersion )
+      {
+        project.logger.info 'Asciidoc tasks forced for building a release version, hope you have Asciidoc installed'
+        asciidocInstalled = true
+      }
+      else
+      {
+        def pathDirs = System.getenv( 'PATH' ).split( File.pathSeparator )
+        def asciidocCandidates = pathDirs.collect( { String path ->
+          new File( path, 'asciidoc' )
+        } ).flatten() as List<File>
+        asciidocInstalled = asciidocCandidates.findAll( { it.isFile() } )
+        if( !asciidocInstalled )
+        {
+          project.logger.lifecycle 'WARNING Asciidoc not found in PATH, manual tasks will skip\n' +
+                                   '        Please install http://www.methods.co.nz/asciidoc/'
+        }
+      }
+    }
+    return asciidocInstalled
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/XsltTask.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/XsltTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/XsltTask.groovy
new file mode 100644
index 0000000..18af2bd
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/XsltTask.groovy
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.gradle.structure.manual
+
+import groovy.transform.CompileStatic
+import org.gradle.api.file.EmptyFileVisitor
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.SourceTask
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.file.FileVisitDetails
+import javax.xml.transform.TransformerFactory
+import javax.xml.transform.stream.StreamResult
+import javax.xml.transform.stream.StreamSource
+
+/**
+ *  Gradle task for running a set of one or more
+ *  files through an XSLT transform.  A styleSheet
+ *  file must be specified.  The source file(s) are
+ *  configured just like any other source task:
+ *     source <file>
+ *       ...or...
+ *     source <directory>
+ *       ...and then optionally...
+ *     include '*.xml'
+ *     exclude, etc.
+ *
+ *  One of destDir or destFile must be specified, though if
+ *  there are multiple source files then destFile will just
+ *  keep getting rewritten.
+ *
+ *  The extension is stripped from the source files and the
+ *  specified extension is appended (whether it is set or not)
+ *  it defaults to no extension.
+ *
+ *  Example task formatting a check style report:
+ *
+ *  task checkstyleReport(type: XsltTask, dependsOn: check) {
+ *      source project.checkstyleResultsDir
+ *      include '*.xml'
+ *
+ *      destDir = project.checkstyleResultsDir
+ *      extension = 'html'
+ *
+ *      stylesheetFile = file( 'config/checkstyle/checkstyle-noframes.xsl' )
+ * }
+ *
+ *  The above definition requires that the specified XSL file be
+ *  copied in with the other checkstyle configuration files.  (The
+ *  file in the example is part of the checkstyle distribution.)
+ *
+ */
+@CompileStatic
+class XsltTask extends SourceTask
+{
+
+  @OutputDirectory
+  File destDir
+
+  @Input
+  String extension = 'html'
+
+  @InputFile
+  File stylesheetFile
+
+  @TaskAction
+  def transform()
+  {
+    def factory = TransformerFactory.newInstance()
+    def transformer = factory.newTransformer( new StreamSource( stylesheetFile ) );
+
+    getSource().visit( new EmptyFileVisitor() {
+      @Override
+      void visitFile( FileVisitDetails fvd )
+      {
+        // Remove the extension from the file name
+        def name = fvd.file.name.replaceAll( '[.][^\\.]*$', '' )
+        name += '.' + extension
+        def destFile = new File( destDir, name )
+        transformer.transform( new StreamSource( fvd.file ), new StreamResult( destFile ) )
+      }
+    } )
+  }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/CheckReleaseSpecTask.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/CheckReleaseSpecTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/CheckReleaseSpecTask.groovy
new file mode 100644
index 0000000..a0e0d6e
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/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.polygene.gradle.structure.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.'
+    dependsOn {
+      project.extensions.getByType( ReleaseSpecExtension ).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/de73010f/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ModuleReleaseSpec.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ModuleReleaseSpec.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ModuleReleaseSpec.groovy
new file mode 100644
index 0000000..fb1665c
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ModuleReleaseSpec.groovy
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.gradle.structure.release;
+
+import org.gradle.api.Project
+
+class ModuleReleaseSpec
+{
+  boolean satisfiedBy( Project project )
+  {
+    def devStatusFile = new File( project.projectDir, "dev-status.xml" )
+    if( !devStatusFile.exists() )
+    {
+      return false
+    }
+    def module = new XmlSlurper().parse( devStatusFile )
+    def codebase = module.status.codebase.text() as String
+    def docs = module.status.documentation.text() as String
+    def tests = module.status.unittests.text() as String
+    return satisfiedBy( codebase, docs, tests )
+  }
+
+  boolean satisfiedBy( String codebase, String docs, String tests )
+  {
+    def satisfied = ( codebase == 'none' && docs == 'complete' )
+    satisfied |= ( codebase == 'early'
+            && ( docs == 'complete' || docs == 'good' )
+            && ( tests == 'complete' || tests == 'good' ) )
+    satisfied |= ( codebase == 'beta'
+            && ( docs == 'complete' || docs == 'good' || docs == 'brief' )
+            && ( tests == 'complete' || tests == 'good' || tests == 'some' ) )
+    satisfied |= ( codebase == 'stable' )
+    satisfied |= ( codebase == 'mature' )
+    return satisfied
+  }
+}