http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/build.gradle ---------------------------------------------------------------------- diff --git a/build.gradle b/build.gradle index ebd7b5d..4147856 100644 --- a/build.gradle +++ b/build.gradle @@ -15,9 +15,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import org.apache.zest.gradle.AllProjectsPlugin -import org.apache.zest.gradle.RootProjectPlugin -import org.apache.zest.gradle.dependencies.DependenciesDeclarationPlugin +import org.apache.polygene.gradle.AllProjectsPlugin +import org.apache.polygene.gradle.RootProjectPlugin +import org.apache.polygene.gradle.dependencies.DependenciesDeclarationPlugin apply plugin: DependenciesDeclarationPlugin apply from: 'dependencies.gradle'
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/AllProjectsPlugin.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/AllProjectsPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/AllProjectsPlugin.groovy new file mode 100644 index 0000000..6c9a2c0 --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/AllProjectsPlugin.groovy @@ -0,0 +1,208 @@ +/* + * 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 + +import groovy.transform.CompileStatic +import org.apache.polygene.gradle.dependencies.DependenciesPlugin +import org.apache.polygene.gradle.publish.PublishingPlugin +import org.gradle.api.JavaVersion +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.plugins.JavaPluginConvention +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.api.tasks.javadoc.Javadoc +import org.gradle.api.tasks.testing.Test +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.gradle.external.javadoc.StandardJavadocDocletOptions +import org.nosphere.honker.gradle.HonkerExtension +import org.nosphere.honker.gradle.HonkerGenDependenciesTask +import org.nosphere.honker.gradle.HonkerGenLicenseTask +import org.nosphere.honker.gradle.HonkerGenNoticeTask +import org.nosphere.honker.gradle.HonkerLicenseOverrideCandidate + +@CompileStatic +class AllProjectsPlugin implements Plugin<Project> +{ + @Override + void apply( final Project project ) + { + project.defaultTasks = [ 'classes', 'test' ] + project.group = project.name == 'org.apache.polygene' ? + 'org.apache.polygene' : + project.name.substring( 0, project.name.lastIndexOf( '.' ) ) + + applyDefaultVersion( project ) + applyPolygeneExtension( project ) + + configureJava( project ) + project.plugins.apply DependenciesPlugin + configureJavadoc( project ) + configureTest( project ) + if( CodeProjectsPlugin.isCodeProject( project ) ) + { + project.plugins.apply CodeProjectsPlugin + } + configureDependencyReport( project ) + configureHonker( project ) + project.plugins.apply PublishingPlugin + } + + private static void applyDefaultVersion( Project project ) + { + if( project.version == 'unspecified' ) + { + project.version = System.properties.version ?: '0' + } + } + + private static void applyPolygeneExtension( Project project ) + { + project.extensions.create( "polygene", PolygeneExtension, project ) + } + + private static void configureJava( Project project ) + { + project.plugins.apply 'java' + def javaConvention = project.convention.getPlugin( JavaPluginConvention ) + javaConvention.targetCompatibility = JavaVersion.VERSION_1_8 + javaConvention.sourceCompatibility = JavaVersion.VERSION_1_8 + project.tasks.withType( JavaCompile ) { JavaCompile task -> + task.options.encoding = 'UTF-8' + // Deprecation warnings for all compilations + task.options.compilerArgs << "-Xlint:deprecation" + // Unchecked warnings for non-test core compilations + if( 'org.apache.polygene.core' == project.group && !task.name.toLowerCase( Locale.US ).contains( 'test' ) ) + { + task.options.compilerArgs << "-Xlint:unchecked" + } + } + } + + private static void configureJavadoc( Project project ) + { + project.tasks.withType( Javadoc ) { Javadoc task -> + def options = task.options as StandardJavadocDocletOptions + options.encoding = 'UTF-8' + options.docEncoding = 'UTF-8' + options.charSet = 'UTF-8' + options.noTimestamp = true + options.links = [ + 'http://docs.oracle.com/javase/8/docs/api/', + 'https://stleary.github.io/JSON-java/', + 'http://junit.org/junit4/javadoc/latest/' + ] + // exclude '**/internal/**' + } + } + + private static void configureTest( Project project ) + { + // Match --max-workers and Test maxParallelForks, use 1 if parallel is disabled + def parallel = project.gradle.startParameter.parallelProjectExecutionEnabled + def maxTestWorkers = ( parallel ? project.gradle.startParameter.maxWorkerCount : 1 ) as int + // The space in the directory name is intentional + def allTestsDir = project.file( "$project.buildDir/tmp/test files" ) + project.tasks.withType( Test ) { Test testTask -> + testTask.onlyIf { !project.hasProperty( 'skipTests' ) } + testTask.testLogging.info.exceptionFormat = TestExceptionFormat.FULL + testTask.maxHeapSize = '1g' + testTask.maxParallelForks = maxTestWorkers + testTask.systemProperties = [ 'proxySet' : System.properties[ 'proxySet' ], + 'proxyHost': System.properties[ 'proxyHost' ], + 'proxyPort': System.properties[ 'proxyPort' ] ] + testTask.reports.html.enabled = true + def testDir = new File( allTestsDir, testTask.name ) + def workDir = new File( testDir, 'work' ) + def tmpDir = new File( testDir, 'tmp' ) + def homeDir = new File( testDir, 'home' ) + testTask.workingDir = workDir + testTask.systemProperties << ( [ + 'user.dir' : workDir.absolutePath, + 'java.io.tmpdir': tmpDir.absolutePath, + 'home.dir' : homeDir.absolutePath + ] as Map<String, Object> ) + testTask.environment << ( [ + 'HOME' : homeDir.absolutePath, + 'USERPROFILE': homeDir.absolutePath + ] as Map<String, Object> ) + testTask.doFirst { Test task -> + [ workDir, tmpDir, homeDir ]*.mkdirs() + } + testTask.doLast { Test task -> + if( !task.state.failure ) + { + project.delete testDir + } + } + } + } + + // Dependency Report generate only the runtime configuration + // The report is packaged in the SDK distributions + private static void configureDependencyReport( Project project ) + { + project.plugins.apply 'project-report' + // TODO Fails with no task found + // def dependencyReport = project.tasks.getByName( 'dependencyReport' ) as DependencyReportTask + // dependencyReport.configurations = [ project.configurations.getByName( 'runtime' ) ] as Set + } + + private static void configureHonker( Project project ) + { + project.plugins.apply 'org.nosphere.honker' + def honkerGenDependencies = project.tasks.getByName( 'honkerGenDependencies' ) as HonkerGenDependenciesTask + def honkerGenLicense = project.tasks.getByName( 'honkerGenLicense' ) as HonkerGenLicenseTask + def honkerGenNotice = project.tasks.getByName( 'honkerGenNotice' ) as HonkerGenNoticeTask + def javaConvention = project.convention.getPlugin( JavaPluginConvention ) + def mainSourceSet = javaConvention.sourceSets.getByName( 'main' ) + mainSourceSet.output.dir( [ builtBy: honkerGenDependencies ] as Map<String, Object>, + honkerGenDependencies.outputDir ) + mainSourceSet.output.dir( [ builtBy: honkerGenLicense ] as Map<String, Object>, + honkerGenLicense.outputDir ) + mainSourceSet.output.dir( [ builtBy: honkerGenNotice ] as Map<String, Object>, + honkerGenNotice.outputDir ) + def honker = project.extensions.getByType( HonkerExtension ) + // Project License, applied to all submodules + honker.license 'Apache 2' + // Dependencies (transitive or not) with no license information, overriding them + honker.licenseOverride { HonkerLicenseOverrideCandidate candidate -> + if( candidate.group == 'asm' || candidate.module == 'prefuse-core' ) + { + candidate.license = 'BSD 3-Clause' + } + if( candidate.group == 'javax.websocket' + || candidate.group == 'javax.xml.bind' ) + { + candidate.license = 'CDDL' + } + if( candidate.group == 'org.apache.httpcomponents' + || candidate.group == 'net.java.dev.jna' + || candidate.group == 'lucene' + || candidate.group == 'jdbm' + || candidate.group == 'org.osgi' + || candidate.group.startsWith( 'org.restlet' ) ) + { + candidate.license = 'Apache 2' + } + } + honkerGenNotice.header = 'Apache Polygene' + honkerGenNotice.footer = 'This product includes software developed at\n' + + 'The Apache Software Foundation (http://www.apache.org/).\n' + project.tasks.getByName( 'check' ).dependsOn project.tasks.getByName( 'honkerCheck' ) + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/CodeProjectsPlugin.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/CodeProjectsPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/CodeProjectsPlugin.groovy new file mode 100644 index 0000000..6aa345b --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/CodeProjectsPlugin.groovy @@ -0,0 +1,146 @@ +/* + * 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 + +import groovy.transform.CompileStatic +import org.apache.polygene.gradle.dependencies.DependenciesDeclarationExtension +import org.apache.polygene.gradle.doc.AsciidocBuildInfoPlugin +import org.apache.polygene.gradle.version.VersionClassPlugin +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.plugins.JavaPluginConvention +import org.gradle.api.plugins.osgi.OsgiManifest +import org.gradle.api.tasks.javadoc.Javadoc +import org.gradle.jvm.tasks.Jar +import org.gradle.testing.jacoco.plugins.JacocoPluginExtension +import org.gradle.testing.jacoco.tasks.JacocoReport + +@CompileStatic +class CodeProjectsPlugin implements Plugin<Project> +{ + static boolean isCodeProject( Project project ) + { + [ 'src/main/java', 'src/test/java', + 'src/main/groovy', 'src/test/groovy' ].collect { path -> + new File( "$project.projectDir/$path" ) + }.any { dir -> dir.isDirectory() } + } + + @Override + void apply( final Project project ) + { + project.plugins.apply VersionClassPlugin + project.plugins.apply AsciidocBuildInfoPlugin + + configureJar( project ) + configureSupplementaryArchives( project ) + + configureJacoco( project ) + configureCheckstyle( project ) + } + + private static void configureJar( Project project ) + { + project.plugins.apply 'osgi' + def jar = project.tasks.getByName( 'jar' ) as Jar + def manifest = jar.manifest as OsgiManifest + manifest.attributes( [ + license : 'http://www.apache.org/licenses/LICENSE-2.0.txt', + docURL : 'https://polygene.apache.org/', + description: project.description ?: + 'Apache Polygene⢠(Java Edition) is a platform for Composite Oriented Programming', + vendor : 'The Apache Software Foundation, https://www.apache.org', + ] ) + manifest.instruction '-debug', 'true' + } + + private static void configureSupplementaryArchives( Project project ) + { + def javaConvention = project.convention.getPlugin( JavaPluginConvention ) + def sourceJar = project.tasks.create( 'sourceJar', Jar ) { Jar task -> + task.description = 'Builds -sources.jar' + task.classifier = 'sources' + task.from javaConvention.sourceSets.getByName( 'main' ).allSource + } + def testSourceJar = project.tasks.create( 'testSourceJar', Jar ) { Jar task -> + task.description = 'Builds -testsources.jar' + task.classifier = 'testsources' + task.from javaConvention.sourceSets.getByName( 'test' ).allSource + } + def javadoc = project.tasks.getByName( 'javadoc' ) as Javadoc + def javadocJar = project.tasks.create( 'javadocJar', Jar ) { Jar task -> + task.description = 'Builds -javadoc.jar' + task.classifier = 'javadoc' + task.from javadoc.destinationDir + task.dependsOn javadoc + } + project.artifacts.add( 'archives', sourceJar ) + project.artifacts.add( 'archives', testSourceJar ) + project.artifacts.add( 'archives', javadocJar ) + } + + private static void configureJacoco( Project project ) + { + def dependencies = project.rootProject.extensions.getByType( DependenciesDeclarationExtension ) + project.plugins.apply 'jacoco' + def jacoco = project.extensions.getByType( JacocoPluginExtension ) + jacoco.toolVersion = dependencies.buildToolsVersions.jacoco + project.tasks.withType( JacocoReport ) { JacocoReport task -> + task.group = TaskGroups.VERIFICATION + task.description = 'Generates test coverage report.' + } + } + + private static void configureCheckstyle( Project project ) + { + // project.plugins.apply 'checkstyle' + // if( name == "org.apache.polygene.core.runtime" ) + // { + // checkstyleMain { + // configFile = new File( "$rootProject.projectDir.absolutePath/etc/polygene-runtime-checkstyle.xml" ) + // ignoreFailures = true + // } + // } + // else + // { + // checkstyleMain { + // configFile = new File( rootProject.projectDir.absolutePath.toString() + '/etc/polygene-api-checkstyle.xml' ) + // ignoreFailures = true + // reporting.baseDir = "$rootProject.reporting.baseDir/checkstyle" + // } + // } + // checkstyleTest { + // configFile = new File( "$rootProject.projectDir.absolutePath/etc/polygene-tests-checkstyle.xml" ) + // ignoreFailures = true + // } + // + // checkstyleVersion { + // configFile = new File( "$rootProject.projectDir.absolutePath/etc/polygene-tests-checkstyle.xml" ) + // ignoreFailures = true + // } + // // Create checkstyle report + // task checkstyleReport( type: XsltTask, dependsOn: check ) { + // source project.checkstyle.reportsDir + // include '*.xml' + // destDir = file( "build/reports/checkstyle/" ) + // extension = 'html' + // stylesheetFile = file( "$rootProject.projectDir/etc/checkstyle-noframes.xsl" ) + // } + // + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/RootProjectPlugin.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/RootProjectPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/RootProjectPlugin.groovy new file mode 100644 index 0000000..c05a584 --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/RootProjectPlugin.groovy @@ -0,0 +1,262 @@ +/* + * 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 + +import groovy.transform.CompileStatic +import org.apache.rat.gradle.RatTask +import org.apache.polygene.gradle.dependencies.DependenciesDeclarationExtension +import org.apache.polygene.gradle.dist.DistributionPlugin +import org.apache.polygene.gradle.release.ReleaseSpecExtension +import org.apache.polygene.gradle.release.ReleaseSpecPlugin +import org.apache.polygene.gradle.test.AggregatedJacocoReportTask +import org.gradle.api.GradleException +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.Configuration +import org.gradle.api.plugins.JavaPluginConvention +import org.gradle.api.tasks.Copy +import org.gradle.api.tasks.javadoc.Javadoc +import org.gradle.api.tasks.testing.Test +import org.gradle.api.tasks.testing.TestReport +import org.gradle.external.javadoc.StandardJavadocDocletOptions + +@CompileStatic +class RootProjectPlugin implements Plugin<Project> +{ + static final String PROJECT_TITLE = 'Apache Polygene⢠(Java Edition) SDK' + static final String PROJECT_DESCRIPTION = 'Apache Polygene⢠(Java Edition) is a framework for domain centric ' + + 'application development, including evolved concepts from AOP, DI and DDD.' + + static class TaskNames + { + static final String GO_OFFLINE = 'goOffline' + static final String GLOBAL_TEST_REPORT = 'globalTestReport' + static final String JAVADOCS = 'javadocs' + static final String ARCHIVE_JAVADOCS = 'archiveJavadocs' + static final String BUILD_ALL = 'buildAll' + } + + @Override + void apply( Project project ) + { + project.plugins.apply ReleaseSpecPlugin + + applyProjectMetadata( project ) + applyHelperTasks( project ) + applyPlugins( project ) + + configureJacoco( project ) + configureTestReport( project ) + configureJavadocs( project ) + configureRat( project ) + + project.plugins.apply DistributionPlugin + configureReleaseTask( project ) + } + + private static void applyProjectMetadata( Project project ) + { + def extraProperties = project.extensions.extraProperties + extraProperties.set 'title', PROJECT_TITLE + extraProperties.set 'description', PROJECT_DESCRIPTION + } + + private static void applyHelperTasks( Project project ) + { + project.tasks.create( TaskNames.GO_OFFLINE ) { Task task -> + task.group = TaskGroups.HELP + task.description = 'Resolves all dependencies configuration' + task.doLast { + def allConfigurations = project.allprojects.collect { Project each -> + each.configurations + }.flatten() as Set<Configuration> + allConfigurations*.resolvedConfiguration + } + } + def buildAll = project.tasks.create( TaskNames.BUILD_ALL ) + buildAll.group = TaskGroups.BUILD + buildAll.description = 'Builds all' + buildAll.dependsOn 'javadocs', 'check', 'jar', + project.subprojects.collect { p -> p.tasks.getByName( 'dependencyReport' ) }, + project.subprojects.collect { p -> p.tasks.getByName( 'assemble' ) }, + ':org.apache.polygene.manual:website' + } + + private static void applyPlugins( Project project ) + { + project.plugins.apply 'org.nosphere.apache.rat' + } + + private static void configureJacoco( Project project ) + { + def dependencies = project.rootProject.extensions.getByType( DependenciesDeclarationExtension ) + project.configurations.create( 'jacoco' ) + project.dependencies.add( 'jacoco', "org.jacoco:org.jacoco.ant:${ dependencies.buildToolsVersions.jacoco }" ) + def task = project.tasks.create( 'coverageReport', AggregatedJacocoReportTask ) { AggregatedJacocoReportTask task -> + task.group = TaskGroups.VERIFICATION + task.description = 'Generates global coverage report' + task.dependsOn project.subprojects.collect( { Project p -> p.tasks.getByName( 'test' ) } ) + } + project.tasks.getByName( 'check' ).dependsOn task + } + + private static void configureTestReport( Project project ) + { + project.tasks.create( TaskNames.GLOBAL_TEST_REPORT, TestReport ) { TestReport task -> + task.group = TaskGroups.VERIFICATION + task.description = 'Generates global test report' + task.destinationDir = project.file( "$project.buildDir/reports/tests" ) + task.reportOn project.subprojects.collect { it.tasks.getByName( 'test' ) } + } + def test = project.tasks.getByName( 'test' ) as Test + test.dependsOn project.subprojects.collect { it.tasks.getByName( 'test' ) } + test.dependsOn project.tasks.getByName( TaskNames.GLOBAL_TEST_REPORT ) + test.reports.html.enabled = false + } + + private static void configureJavadocs( Project project ) + { + def zest = project.extensions.getByType( PolygeneExtension ) + def releaseSpec = project.extensions.getByType( ReleaseSpecExtension ) + project.tasks.create( TaskNames.JAVADOCS, Javadoc ) { Javadoc task -> + task.group = TaskGroups.DOCUMENTATION + task.description = 'Builds the whole SDK public Javadoc' + task.dependsOn ReleaseSpecPlugin.TaskNames.RELEASE_APPROVED_PROJECTS + def options = task.options as StandardJavadocDocletOptions + options.docFilesSubDirs = true + options.encoding = "UTF-8" + options.overview = "${ project.projectDir }/src/javadoc/overview.html" + task.title = "${ PROJECT_TITLE } ${ project.version }" + def apiSources = releaseSpec.approvedProjects.findAll { approved -> + ( approved.name.startsWith( 'org.apache.polygene.core' ) && + !approved.name.startsWith( 'org.apache.polygene.core.runtime' ) ) || + approved.name.startsWith( 'org.apache.polygene.library' ) || + approved.name.startsWith( 'org.apache.polygene.extension' ) || + approved.name.startsWith( 'org.apache.polygene.tool' ) + } + task.source apiSources.collect { each -> + each.convention.getPlugin( JavaPluginConvention ).sourceSets.getByName( 'main' ).allJava + } + task.destinationDir = project.file( "${ project.convention.getPlugin( JavaPluginConvention ).docsDir }/javadocs" ) + task.classpath = project.files( apiSources.collect { apiProject -> + apiProject.convention.getPlugin( JavaPluginConvention ).sourceSets.getByName( 'main' ).compileClasspath + } ) + options.group( [ + "Core API" : [ "org.apache.polygene.api", + "org.apache.polygene.api.*" ], + "Core Bootstrap": [ "org.apache.polygene.bootstrap", + "org.apache.polygene.bootstrap.*" ], + "Core SPI" : [ "org.apache.polygene.spi", + "org.apache.polygene.spi.*" ], + "Libraries" : [ "org.apache.polygene.library.*" ], + "Extensions" : [ "org.apache.polygene.valueserialization.*", + "org.apache.polygene.entitystore.*", + "org.apache.polygene.index.*", + "org.apache.polygene.metrics.*", + "org.apache.polygene.cache.*", + "org.apache.polygene.migration", + "org.apache.polygene.migration.*" ], + "Tools" : [ "org.apache.polygene.tools.*", + "org.apache.polygene.envisage", + "org.apache.polygene.envisage.*" ], + "Test Support" : [ "org.apache.polygene.test", + "org.apache.polygene.test.*" ] + ] ) + } + project.tasks.create( TaskNames.ARCHIVE_JAVADOCS, Copy ) { Copy task -> + task.group = TaskGroups.DOCUMENTATION + task.description = 'Copy SDK public Javadoc to ../polygene-web' + task.dependsOn TaskNames.JAVADOCS + task.from 'build/docs/javadoc/' + if( zest.developmentVersion ) + { + task.into( "$project.projectDir/../polygene-web/site/content/java/develop/javadocs/" ) + } + else + { + task.into( "$project.projectDir/../polygene-web/site/content/java/$project.version/javadocs/" ) + } + } + } + + private static void configureRat( Project project ) + { + def rat = project.tasks.getByName( 'rat' ) as RatTask + rat.group = TaskGroups.VERIFICATION + rat.onlyIf { project.version != '0' } + rat.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/**', + ] + } + + private static void configureReleaseTask( Project project ) + { + def zest = project.extensions.getByType( PolygeneExtension ) + def release = project.tasks.create( 'release' ) + release.description = 'Builds, tests and uploads the release artifacts' + release.group = TaskGroups.RELEASE + release.doFirst { + if( zest.developmentVersion ) + { + throw new GradleException( "Cannot release development version $project.version, use '-Dversion=X.Y.Z'" ) + } + } + release.dependsOn 'checkReleaseSpec', + 'rat', + 'archiveJavadocs', + ':org.apache.polygene.manual:copyWebsite', + project.allprojects.collect { it.tasks.getByName( 'uploadArchives' ) }, + 'dist' + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/TaskGroups.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/TaskGroups.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/TaskGroups.groovy new file mode 100644 index 0000000..61d3d0d --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/TaskGroups.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.polygene.gradle + +import org.gradle.api.plugins.ApplicationPlugin +import org.gradle.api.plugins.BasePlugin +import org.gradle.api.plugins.HelpTasksPlugin +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.language.base.plugins.LifecycleBasePlugin + +class TaskGroups +{ + static final String HELP = HelpTasksPlugin.HELP_GROUP + static final String BUILD = LifecycleBasePlugin.BUILD_GROUP + static final String VERIFICATION = LifecycleBasePlugin.VERIFICATION_GROUP + static final String DOCUMENTATION = JavaBasePlugin.DOCUMENTATION_GROUP + static final String DISTRIBUTION = ApplicationPlugin.APPLICATION_GROUP + static final String DISTRIBUTION_VERIFICATION = 'distribution verification' + static final String PERFORMANCE = 'performance' + static final String PERFORMANCE_VERIFICATION = 'performance verification' + static final String RELEASE = 'release' + static final String RELEASE_VERIFICATION = 'release verification' + static final String UPLOAD = BasePlugin.UPLOAD_GROUP + static final String SAMPLES = 'samples' +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/ZestExtension.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/ZestExtension.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/ZestExtension.groovy new file mode 100644 index 0000000..41e472a --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/ZestExtension.groovy @@ -0,0 +1,79 @@ +/* + * 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 + +import groovy.transform.CompileStatic +import org.gradle.api.Project +import org.gradle.api.artifacts.Dependency + +@CompileStatic +class PolygeneExtension +{ + private final Project project + final Core core + + PolygeneExtension( Project project ) + { + this.project = project + this.core = new Core() + } + + boolean isDevelopmentVersion() + { + return project.version == '0' || project.version.toString().contains( 'SNAPSHOT' ) + } + + boolean isReleaseVersion() + { + return !isDevelopmentVersion() + } + + class Core + { + Dependency api = core( 'api' ) + Dependency spi = core( 'spi' ) + Dependency runtime = core( 'runtime' ) + Dependency bootstrap = core( 'bootstrap' ) + Dependency testsupport = core( 'testsupport' ) + } + + private Dependency core( String name ) + { + return dependency( 'org.apache.polygene.core', "org.apache.polygene.core.$name" ) + } + + Dependency library( String name ) + { + return dependency( 'org.apache.polygene.libraries', "org.apache.polygene.library.$name" ) + } + + Dependency extension( String name ) + { + return dependency( 'org.apache.polygene.extensions', "org.apache.polygene.extension.$name" ) + } + + Dependency tool( String name ) + { + return dependency( 'org.apache.polygene.tools', "org.apache.polygene.tool.$name" ) + } + + private Dependency dependency( String group, String name ) + { + project.dependencies.project( path: ":$group:$name" ) + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationExtension.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationExtension.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationExtension.groovy new file mode 100644 index 0000000..c91f0b2 --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationExtension.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.dependencies + +import groovy.transform.CompileStatic +import org.gradle.api.artifacts.DependencySubstitution +import org.gradle.api.artifacts.component.ModuleComponentSelector +import org.gradle.internal.BiAction + +@CompileStatic +class DependenciesDeclarationExtension +{ + final Map<String, String> repositoriesUrls = [ : ] + final Map<String, Object> libraries = [ : ] + final Map<String, List<Object>> defaultDependencies = [ : ] + BiAction<DependencySubstitution, ModuleComponentSelector> dependencySubstitutionSpec + final Map<String, String> buildToolsVersions = [ : ] +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationPlugin.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationPlugin.groovy new file mode 100644 index 0000000..cb90182 --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationPlugin.groovy @@ -0,0 +1,30 @@ +/* + * 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.dependencies + +import org.gradle.api.Plugin +import org.gradle.api.Project + +class DependenciesDeclarationPlugin implements Plugin<Project> +{ + @Override + void apply( Project project ) + { + project.extensions.create( 'dependenciesDeclaration', DependenciesDeclarationExtension ) + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesPlugin.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesPlugin.groovy new file mode 100644 index 0000000..660406d --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesPlugin.groovy @@ -0,0 +1,89 @@ +/* + * 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.dependencies + +import groovy.transform.CompileStatic +import org.gradle.api.Action +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.DependencySubstitution +import org.gradle.api.artifacts.component.ModuleComponentSelector +import org.gradle.api.artifacts.repositories.MavenArtifactRepository + +@CompileStatic +class DependenciesPlugin implements Plugin<Project> +{ + @Override + void apply( final Project project ) + { + def dependenciesDeclaration = project.rootProject.extensions.getByType( DependenciesDeclarationExtension ) + applyRepositories( project, dependenciesDeclaration ) + applyLibraries( project, dependenciesDeclaration ) + applyDependencyResolutionRules( project, dependenciesDeclaration ) + applyDefaultDependencies( project, dependenciesDeclaration ) + } + + private static void applyRepositories( Project project, DependenciesDeclarationExtension declaration ) + { + declaration.repositoriesUrls.each { name, url -> + project.repositories.maven { MavenArtifactRepository repo -> + repo.name = name + repo.url = url + } + } + } + + private static void applyLibraries( Project project, DependenciesDeclarationExtension declaration ) + { + project.extensions.extraProperties.set 'libraries', declaration.libraries + } + + private static void applyDependencyResolutionRules( Project project, DependenciesDeclarationExtension declaration ) + { + project.configurations.all( + { Configuration configuration -> + configuration.resolutionStrategy.dependencySubstitution.all( + { DependencySubstitution dep -> + if( dep.requested instanceof ModuleComponentSelector ) + { + def selector = dep.requested as ModuleComponentSelector + declaration.dependencySubstitutionSpec.execute dep, selector + } + } as Action<DependencySubstitution> ) + } as Action<Configuration> ) + } + + private static void applyDefaultDependencies( Project project, DependenciesDeclarationExtension declaration ) + { + declaration.defaultDependencies.each { String configuration, List<Object> dependencies -> + dependencies.each { dependency -> + if( dependency instanceof Collection ) + { + dependency.each { subdep -> + project.dependencies.add( configuration, subdep ) + } + } + else + { + project.dependencies.add( configuration, dependency ) + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/dist/DistributionPlugin.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/dist/DistributionPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dist/DistributionPlugin.groovy new file mode 100644 index 0000000..0a4a49b --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dist/DistributionPlugin.groovy @@ -0,0 +1,387 @@ +/* + * 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.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.polygene.gradle.RootProjectPlugin +import org.apache.polygene.gradle.TaskGroups +import org.apache.polygene.gradle.dependencies.DependenciesDeclarationExtension +import org.apache.polygene.gradle.release.ReleaseSpecExtension +import org.apache.polygene.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 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' ) + 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() + 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-polygene-java-$project.version-src" + spec.with srcDistFilesCopySpec + spec.with srcDistFilteredFilesCopySpec + } + + def zipSources = project.tasks.create( 'zipSources', Zip ) { Zip task -> + task.group = TaskGroups.DISTRIBUTION + task.description = 'Assemble .zip source distribution' + task.baseName = 'apache-polygene-java' + task.with srcDistCopySpec + task.classifier = 'src' + } + def tarSources = project.tasks.create( 'tarSources', Tar ) { Tar task -> + task.group = TaskGroups.DISTRIBUTION + task.description = 'Assemble .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.UNPACK_SOURCE_DIST, Copy ) { Copy task -> + task.group = TaskGroups.DISTRIBUTION + task.description = "Unpack source distribution" + task.with srcDistCopySpec + task.into 'build/unpacked-distributions/src' + } + + def unpackedSrcDistDir = project.file( "build/unpacked-distributions/src/apache-polygene-java-$project.version-src" ) + project.tasks.create( TaskNames.CHECK_SOURCE_DIST, GradleBuild.class, { GradleBuild task -> + task.group = TaskGroups.DISTRIBUTION_VERIFICATION + task.description = "Check the source distribution by running the 'check' and 'assemble' tasks inside" + 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-polygene-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.group = TaskGroups.DISTRIBUTION + task.description = 'Assemble .zip binary distribution' + task.dependsOn project.tasks.getByName( RootProjectPlugin.TaskNames.BUILD_ALL ) + task.baseName = 'apache-polygene-java' + task.classifier = 'bin' + task.with binDistImage + } + def tarBinaries = project.tasks.create( 'tarBinaries', Tar ) { Tar task -> + task.group = TaskGroups.DISTRIBUTION + task.description = 'Assemble .tar.gz binary distribution' + task.dependsOn project.tasks.getByName( RootProjectPlugin.TaskNames.BUILD_ALL ) + 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.UNPACK_BINARY_DIST, Copy ) { Copy task -> + task.group = TaskGroups.DISTRIBUTION + task.description = "Unpack binary distribution" + task.with binDistImage + task.into 'build/unpacked-distributions/bin' + } + + configureBinaryDistributionCheck( project ) + } + + private static void configureGoOfflineHelpers( Project project ) + { + def externalRepos = project.rootProject.extensions.getByType( DependenciesDeclarationExtension ).repositoriesUrls + 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 = externalRepos + genOfflineGradle.repositories = externalRepos + [ genOfflineMaven, genOfflineGradle ].each { task -> + task.group = TaskGroups.DISTRIBUTION + task.dependsOn approvedProjectsTask + } + def checkOfflineMaven = project.tasks.create( TaskNames.CHECK_MAVEN_OFFLINE_HELPERS, + GoOfflineHelpersTasks.CheckMaven ) + checkOfflineMaven.group = TaskGroups.DISTRIBUTION_VERIFICATION + checkOfflineMaven.description = 'Check binary distribution Maven dependencies download helper' + checkOfflineMaven.dependsOn genOfflineMaven + def checkOfflineGradle = project.tasks.create( TaskNames.CHECK_GRADLE_OFFLINE_HELPERS, + GoOfflineHelpersTasks.CheckGradle ) + checkOfflineGradle.group = TaskGroups.DISTRIBUTION_VERIFICATION + checkOfflineGradle.description = 'Check binary distribution Gradle dependencies download helper' + 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-polygene-java-$project.version-bin" ) + project.tasks.create( TaskNames.CHECK_BINARY_DIST_RAT, RatTask, { RatTask task -> + task.group = TaskGroups.DISTRIBUTION_VERIFICATION + task.description = "Checks binary distribution using Apache RAT" + task.dependsOn TaskNames.UNPACK_BINARY_DIST + task.inputDir = unpackedBinDistDir.absolutePath + task.reportDir = project.file( 'build/reports/rat-bin-dist' ) + task.excludes = [ + '.gradle/**', + 'docs/reports/**', + 'docs/javadocs/**', + '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.group = TaskGroups.DISTRIBUTION_VERIFICATION + task.description = 'Checks binary distribution' + 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.group = TaskGroups.DISTRIBUTION + task.description = "Assembles source and binary distributions" + task.dependsOn 'install' + task.from project.tasks.getByName( 'unpackBinDist' ) + task.into "$project.buildDir/dist" + } + project.tasks.create( 'checkDists' ) { Task task -> + task.group = TaskGroups.DISTRIBUTION_VERIFICATION + task.description = "Checks source and binary distributions" + task.dependsOn TaskNames.CHECK_SOURCE_DIST, TaskNames.CHECK_BINARY_DIST + } + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/dist/GoOfflineHelpersTasks.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/dist/GoOfflineHelpersTasks.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dist/GoOfflineHelpersTasks.groovy new file mode 100644 index 0000000..415a0bb --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/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.polygene.gradle.dist + +import groovy.transform.CompileStatic +import org.apache.polygene.gradle.release.ReleaseSpecExtension +import org.apache.polygene.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.polygene</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.polygene' ) + } 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.polygene' ) + } + } + + 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 '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/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/doc/AsciidocBuildInfoPlugin.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/doc/AsciidocBuildInfoPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/doc/AsciidocBuildInfoPlugin.groovy new file mode 100644 index 0000000..f8edcfb --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/doc/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.doc + +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' + + def 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/1c722f44/buildSrc/src/main/groovy/org/apache/polygene/gradle/doc/DocumentationTask.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/doc/DocumentationTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/doc/DocumentationTask.groovy new file mode 100644 index 0000000..a043aa0 --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/doc/DocumentationTask.groovy @@ -0,0 +1,292 @@ +/* + * 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.doc + +import groovy.io.FileType +import groovy.transform.CompileStatic +import groovy.transform.TypeCheckingMode +import java.security.MessageDigest +import org.apache.polygene.gradle.PolygeneExtension +import org.apache.polygene.gradle.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.Internal +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.OutputDirectory +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 def String docName + @Input def String docType + + @InputDirectory def File getCommonResourcesDir() { project.file( 'src/resources' ) } + @InputDirectory def File getConfigDir() { project.file( 'src/conf' ) } + @InputDirectory def File getDocsDir() { project.file( 'src/docs' ) } + @InputDirectory def File getSrcMainDir() { project.file( 'src/main' ) } + @InputDirectory def File getXslDir() { project.file( 'src/xsl' ) } + @InputDirectory def File getBuildSrcDir() { project.rootProject.file( 'buildSrc/src' ) } + + @InputFiles def getSubProjectsDocsDirs() { project.rootProject.subprojects.collect { p -> p.file( 'src/docs' ) } } + @InputFiles def getSubProjectsTestDirs() { project.rootProject.subprojects.collect { p -> p.file( 'src/test' ) } } + + @OutputDirectory def File getOutputDir() { project.file( "${ project.buildDir }/docs/${ docName }/" ) } + + @Internal def File getTempAsciidocDir() { project.file( "${ project.buildDir }/tmp-asciidoc" ) } + @Internal def File getTempDir() { project.file( "${ project.buildDir }/tmp/docs/${ docName }" ) } + + @TaskAction + def void generate() + { + installAsciidocFilters() + + [ outputDir, tempAsciidocDir, tempDir ].each { it.deleteDir() } + [ outputDir, tempAsciidocDir, tempDir ].each { it.mkdirs() } + + copySubProjectsDocsResources() + generateAsciidocAccordingToReleaseSpecification() + generateXDoc() + generateChunkedHtml() + // generateSingleHtml() + // generatePdf() + } + + def 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 ) + def 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 '**' + } + } + } + + def void generateAsciidocAccordingToReleaseSpecification() + { + def zest = project.extensions.getByType( PolygeneExtension ) + project.copy { CopySpec spec -> + spec.from docsDir + spec.into tempAsciidocDir + spec.include '**' + } + if( zest.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 + def releaseApprovedProjects = project.rootProject.extensions. + getByType( ReleaseSpecExtension ).approvedProjects + releaseApprovedProjects.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 + } + } + } + + def 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> ) + } + + def 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> ) + } + + def 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> ) + } + + def 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 + } +}
