All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencms.OpenCmsModulesPlugin.groovy Maven / Gradle / Ivy

The newest version!

package org.opencms

import org.apache.tools.ant.filters.ReplaceTokens

import org.gradle.api.JavaVersion
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.UnknownDomainObjectException
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.bundling.Zip
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.wrapper.Wrapper
import org.gradle.api.publish.tasks.GenerateModuleMetadata
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.artifacts.ExternalModuleDependency
/**
 * This Gradle plugin should be used to build modules for OpenCms.

* * It assumes each module is placed in a folder named as the module within the project folder.

* This module folder should contain a 'resources' folder containing all module VFS resource * including the module manifest.xml file.

* Optionally the module folder may contain a 'src' folder containing the java source file * required by the module.

* Optionally it may contain a 'static' folder containing static resources that will be placed * into the module JAR file and will be accessible through static resource URLs within OpenCms.

* * All module names of the project must be listed in the build property 'modules_list' as comma * separated values.

* Also the artifact name needs be provided with the build property 'project_name' as well as the * project nice name with 'project_nice_name' and the build version with 'build_version'.

* * Use the task 'bindist' to build all project modules and 'install' to make project artifacts * available within your local maven cache.

**/ class OpenCmsModulesPlugin implements Plugin { private static final String GRADLE_VERSION='6.1.1' private static final String DEFAULT_JAVA_COMPATIBILITY='1.8' private static final String PROJECT_EXTENSION = "ocDependencies" private static final String DEFAULT_BUILD_DIR = "build/modules" private static final String DEFAULT_MAX_HEAPSIZE = "1024m" private static final String DEFAULT_TEST_MODULE_FOLDER = "test/data/WEB-INF/packages" private static final String HORIZONTAL_LINE='===============================================================================' /** * Called when applying to the build p.

* * @param project the project that is being build **/ @Override void apply(Project p) { def OpenCmsModulesExtension ocDependencies = null; try { ocDependencies = p.getExtensions().getByName('ocDependencies'); } catch (UnknownDomainObjectException ex) { // this is ok. } if (p.hasProperty('build_directory')) { p.buildDir = p.build_directory } else { p.buildDir = DEFAULT_BUILD_DIR; } if (p.hasProperty('java_target_version')) { p.java.targetCompatibility = p.java_target_version } else { println "Using plugins default Java target compatibility (${DEFAULT_JAVA_COMPATIBILITY}). To overwrite use property 'java_target_version'." p.java.targetCompatibility = DEFAULT_JAVA_COMPATIBILITY } if (p.hasProperty('java_source_version')) { p.java.sourceCompatibility = p.java_source_version } else { println "Java source compatibility not explicitly specified. Using target compatiblity (${p.java.targetCompatibility}). To overwrite use property 'java_source_version'." p.java.sourceCompatibility = p.java.targetCompatibility } p.ext.gwtStyle='obfuscated' if (p.hasProperty('gwt_style')) { p.gwtStyle=p.gwt_style } p.ext.gwtMode='strict' if (p.hasProperty('gwt_mode')) { p.gwtMode=p.gwt_mode } p.repositories { mavenLocal() if (p.hasProperty('additional_repositories')){ p.additional_repositories.split(';').each{ repo -> maven { url repo } } } mavenCentral() maven { url "https://maven.restlet.talend.com" } maven { url "https://maven.vaadin.com/vaadin-addons" } } p.configurations { moduleDeps { description = 'additional dependencies required by modules, need to be added into the webapp lib folder' } compile { description = 'used to compile the modules jars' extendsFrom moduleDeps } implementation { extendsFrom compile } testCompile { description = 'used to compile and execute test cases' extendsFrom compile } testImplementation { extendsFrom testCompile } } if (null != ocDependencies) { println "You are using default OpenCms dependencies with the following configuration:" println "" ocDependencies.printState() if (ocDependencies.inModuleDeps) { println "Adding jars placed in some lib* folder to the moduleDeps:" println " - moduleDeps p.fileTree(dir: '.').matching {" println " include '**/lib*/*.jar'" println " exclude 'build/*" println " }" p.dependencies { moduleDeps p.fileTree(dir: '.').matching { include '**/lib*/*.jar' exclude 'build/*' } } } def List compileDependencies = ocDependencies.compile.getDependenies(p.opencms_version) if (compileDependencies.isEmpty()) { printn "No default compile dependencies are added." } else { println "Adding default compile dependencies:" for(String dependency : compileDependencies) { println " - compile ${dependency}" p.dependencies.add("compile", dependency) } } def List testCompileDependencies = ocDependencies.testCompile.getDependenies(p.opencms_version) if (testCompileDependencies.isEmpty()) { printn "No default testCompile dependencies are added." } else { println "Adding default testCompile dependencies:" for(String dependency : testCompileDependencies) { println " - testCompile ${dependency}" p.dependencies.add("testCompile", dependency) } } } if (p.file("dependencies.gradle").exists()) { println "Adding custom dependencies from 'dependencies.gradle'" p.apply([from: 'dependencies.gradle']) } else { println "No custom dependencies loaded. Add file 'dependencies.gradle' with to dependencies to add some." } if (p.ext.has('coreproject')) { def coreproject = p.ext.coreproject println "The Modules are compiled with the core directly." println "Replacing dependencies to the following core artifacts with the core project \"${coreproject}\":" println " - org.opencms:opencms-core" println " - org.opencms:opencms-gwt" println " - org.opencms:opencms-modules" println " - org.opencms:opencms-test" println " - org.opencms:opencms-setup" p.configurations.all { resolutionStrategy.dependencySubstitution { substitute module("org.opencms:opencms-core") using project(coreproject) substitute module("org.opencms:opencms-gwt") using project(coreproject) substitute module("org.opencms:opencms-modules") using project(coreproject) substitute module("org.opencms:opencms-test") using project(coreproject) substitute module("org.opencms:opencms-setup") using project(coreproject) } } } p.sourceSets { test { java { srcDir "test/src" } compileClasspath=p.configurations.testCompile resources.srcDir "test/src" } } p.task('opencmsPluginDescription'){ doFirst{ println HORIZONTAL_LINE println 'OpenCms modules plugin description' println '' println 'Use this plugin to build modules for OpenCms.' println '' println 'Required build properties:' println ' build_version: the artifact version' println ' project_name: the project name used to name artifacts' println ' project_nice_name: the nice name of the project used in artifact description' println ' modules_list: the comma separated list of module names' println '' println 'Optional build properties:' println " build_directory: the build directory (default: ${DEFAULT_BUILD_DIR})" println " java_target_version: the java source and compatibility version (default: ${DEFAULT_JAVA_COMPATIBILITY})" println " max_heap_size: the heap size to use during GWT build (default: ${DEFAULT_MAX_HEAPSIZE})" println ' gwt_style: the GWT output style, use pretty for debug build (default: obfuscated)' println ' gwt_mode: the GWT compile mode, use draftCompile to speed up build times (default: strict)' println ' copy_module_test: the folder to copy modules for test case import to (default: test/data/WEB-INF/packages)' println HORIZONTAL_LINE } } try { p.ext.modulesDistsDir = p.file("${p.buildDir}/modulesZip") p.ext.moduleLibs='' p.ext.dependencyLibs='' p.ext.modulesAll='' if (!p.hasProperty('max_heap_size')){ p.ext.max_heap_size=DEFAULT_MAX_HEAPSIZE } if (!p.hasProperty('copy_module_test')) { p.ext.copy_module_test=DEFAULT_TEST_MODULE_FOLDER } def folder = p.file(p.copy_module_test) if (!folder.exists() && folder.getParentFile().exists()) { folder.mkdirs() } p.ext.copyModuleTestExists=p.file(p.copy_module_test).isDirectory() p.ext.allModuleNames = p.modules_list.split(',') p.ext.modulesDistsDir = p.file("${p.buildDir}/modulesZip") // iterate all configured modules p.allModuleNames.each{ moduleName -> p.sourceSets.create(moduleName,{ java { srcDir "${moduleName}/src" exclude '**/test/**' } resources.srcDir "${moduleName}/src" }); p.sourceSets[moduleName].compileClasspath=p.configurations.compile def moduleFolder = p.file("${moduleName}") def srcModule = p.file("${moduleFolder}/src") def srcGwtDir = p.file("${moduleFolder}/src-gwt") def staticFolder=p.file("${moduleFolder}/static") def requiresJar = srcModule.exists() || srcGwtDir.exists() || staticFolder.exists() def manifestFile = p.file("${moduleFolder}/resources/manifest.xml") def gwtModule = null def gwtSourceSetName = null def propertyFile = p.file("${moduleFolder}/module.properties") def gwtRename = null def installForTests = false if (propertyFile.exists()){ p.logger.lifecycle("checking properties for module $moduleName") Properties moduleProperties= new Properties() moduleProperties.load(new FileInputStream(propertyFile)) if (moduleProperties['module.gwt']!=null){ gwtModule = moduleProperties['module.gwt'] gwtSourceSetName = moduleName.replace(".", "_")+'_gwt' p.logger.lifecycle("found GWT module $gwtModule") def moduleXml = (new XmlParser()).parse(srcGwtDir.toString()+"/" +gwtModule.replaceAll('\\.','/')+'.gwt.xml') gwtRename = moduleXml['@rename-to'] if (gwtRename==null){ gwtRename=gwtModule } } installForTests = 'true'.equals(moduleProperties['testinstall']) } def testDir = p.file("${moduleFolder}/test") def requiresTest = testDir.exists() if (requiresTest){ p.sourceSets.test.compileClasspath += p.files(p.sourceSets[moduleName].java.classesDirectory) { builtBy p.sourceSets[moduleName].compileJavaTaskName } p.sourceSets.test.runtimeClasspath += p.files(p.sourceSets[moduleName].java.classesDirectory) { builtBy p.sourceSets[moduleName].compileJavaTaskName } p.sourceSets.test.java.srcDir "${moduleName}/test" p.sourceSets.test.resources.srcDir "${moduleName}/test" } def moduleDependencies=[] def moduleVersion = p.version if (manifestFile.exists()){ def parsedManifest= (new XmlParser()).parse("${moduleFolder}/resources/manifest.xml") parsedManifest.module[0].dependencies[0].dependency.each{ dep -> moduleDependencies.add(dep.@name) } moduleVersion = parsedManifest.module[0].version[0].text() } if (requiresJar.toBoolean()) { p.task([type: Jar],"jar_$moduleName") { ext.moduleName = moduleName ext.moduleVersion= moduleVersion manifest { attributes 'Implementation-Title': p.project_nice_name, 'Implementation-Version': moduleVersion } from p.sourceSets[moduleName].output from ("$moduleFolder") { include "META-INF/**" } from ("$staticFolder") { into "OPENCMS" } if (gwtModule != null){ from( "${p.buildDir}/gwt/${moduleName}") { exclude '**/WEB-INF/**' into "OPENCMS/gwt" } } archiveFileName = moduleName+'.jar' archiveBaseName = moduleName exclude '**/.gitignore' exclude '**/test/**' doFirst { println HORIZONTAL_LINE println "Building JAR for $moduleName version $moduleVersion" println HORIZONTAL_LINE } } } if (requiresTest.toBoolean()) { p.task([type: Test, dependsOn: p.sourceSets.test.compileJavaTaskName], "test_$moduleName") { useJUnit() def dc = p.sourceSets.test.compileClasspath classpath = dc + p.files(p.sourceSets.test.java.classesDirectory) include "**/Test*" // important: exclude all anonymous classes exclude '**/*$*.class' scanForTestClasses false testClassesDirs = p.files(p.sourceSets.test.java.classesDirectory) systemProperties['db.product'] = "hsqldb" systemProperties['test.data.path'] = "${p.projectDir}/test/data" systemProperties['test.webapp.path'] = "${p.projectDir}/test/webapp" systemProperties['test.build.folder'] =p.sourceSets.test.output.resourcesDir maxHeapSize = p.max_heap_size jvmArgs '-XX:MaxPermSize=256m' testLogging.showStandardStreams = true ignoreFailures true } } if (installForTests) { if (p.copyModuleTestExists) { if (p.hasProperty('noVersion')) { p.task([type: Copy], "installForTest_$moduleName") { from "${p.modulesDistsDir}/${moduleName}.zip" into p.copy_module_test doFirst { println "copying ${p.modulesDistsDir}/${moduleName}.zip to ${p.copy_module_test}" } ext.moduleName="${moduleName}" } } else { p.task([type: Copy], "installForTest_$moduleName") { from "${p.modulesDistsDir}/${moduleName}-${moduleVersion}.zip" into p.copy_module_test rename("${moduleName}-${moduleVersion}.zip","${moduleName}.zip") doFirst { println "copying ${p.modulesDistsDir}/${moduleName}-${moduleVersion}.zip to ${p.copy_module_test}/${moduleName}.zip" } ext.moduleName="${moduleName}" } } p.tasks["installForTest_$moduleName"].dependsOn("dist_$moduleName") p.tasks["test"].dependsOn("installForTest_$moduleName") if (requiresTest.toBoolean()) { p.tasks["test_$moduleName"].dependsOn("installForTest_$moduleName") } } else { println "WARN: Installing module $moduleName for testcases will not work. The property 'copy_module_test' is not set correctly." } } p.task([type: Zip], "dist_$moduleName"){ ext.moduleName = moduleName ext.moduleFolder = moduleFolder ext.dependencies = moduleDependencies ext.gwtSourceSetName = gwtSourceSetName ext.gwtRenameTo = gwtRename ext.requiresJar = requiresJar ext.requiresTest = requiresTest if (p.hasProperty('noVersion')) { archiveVersion = null p.modulesAll +="${moduleName}.zip," } else { archiveVersion = moduleVersion p.modulesAll +="${moduleName}-${moduleVersion}.zip," } destinationDirectory = p.modulesDistsDir archiveBaseName = moduleName doFirst { println HORIZONTAL_LINE println "Building ZIP for $moduleName version $moduleVersion" println HORIZONTAL_LINE } // excluding jars from modules, jars will be placed in the WEB-INF lib folder through the deployment process from("${moduleFolder}/resources"){ exclude '**/lib*/*.jar' exclude 'manifest.xml' } // the following allows to rename the .categories to _categories for instances still using the legacy folder name from("${moduleFolder}/resources"){ include 'manifest.xml' if (p.hasProperty('replaceCategoryFolder')){ filter { line -> line.replaceAll('/.categories', '/_categories') } } } } if (requiresJar.toBoolean()) { p.tasks["dist_$moduleName"].dependsOn("jar_$moduleName") p.moduleLibs+="${moduleName}.jar," } if (gwtModule != null){ p.logger.lifecycle("creating sourceset for $gwtModule") p.sourceSets.create(gwtSourceSetName,{ java { srcDirs srcGwtDir srcDir srcModule exclude '**/test/**' } resources { srcDirs srcGwtDir } }) p.sourceSets[gwtSourceSetName].compileClasspath=p.configurations.compile p.task([dependsOn: p.tasks["${gwtSourceSetName}Classes"], type: JavaExec], "gwt_$moduleName") { ext.buildDir = p.buildDir.toString() +"/gwt/$moduleName" ext.extraDir = p.buildDir.toString() + "/extra/$moduleName" ext.moduleName = moduleName inputs.files p.sourceSets[gwtSourceSetName].java.srcDirs inputs.dir p.sourceSets[gwtSourceSetName].output.resourcesDir outputs.dir buildDir // Workaround for incremental build (GRADLE-1483) outputs.upToDateSpec = new org.gradle.api.specs.AndSpec() doFirst { println HORIZONTAL_LINE println "Building GWT resources for $gwtModule" println HORIZONTAL_LINE // to clean the output directory, delete it first def dir = p.file(buildDir) if (dir.exists()){ p.delete(dir) } dir.mkdirs() } mainClass = 'com.google.gwt.dev.Compiler' classpath { [ p.sourceSets[moduleName].java.srcDirs, p.sourceSets[moduleName].compileClasspath, p.sourceSets[gwtSourceSetName].java.srcDirs, p.sourceSets[gwtSourceSetName].output.resourcesDir, p.sourceSets[gwtSourceSetName].java.classesDirectory ] } args = [ gwtModule, // Your GWT module '-war', buildDir, '-logLevel', 'ERROR', '-localWorkers', '2', '-style', p.gwtStyle, '-extra', extraDir, "-${p.gwtMode}" ] maxHeapSize = p.max_heap_size } p.tasks["jar_$moduleName"].dependsOn p.tasks["gwt_$moduleName"] } } p.task([type: Copy], 'copyDeps'){ from p.configurations.moduleDeps into "${p.buildDir}/deps" } p.task([type: Copy], 'copyProjectProps'){ p.configurations.moduleDeps.each {d -> p.dependencyLibs="${p.dependencyLibs}${d.name}," } from(p.projectDir) { include 'project.properties' filter(ReplaceTokens, tokens: [ MODULES_ALL: ''+p.modulesAll, MODULE_LIBS: ''+p.moduleLibs, DEPENDENCY_LIBS: ''+p.dependencyLibs ]) } into p.modulesDistsDir } p.task([dependsOn: [ p.copyDeps, p.copyProjectProps ]], 'bindist') { doFirst{ println 'Done' } } p.task([type: Jar], 'projectAllJar'){ p.allModuleNames.each{ moduleName -> from p.sourceSets[moduleName].output } archiveBaseName = "${p.project_name}" exclude '**/.gitignore' exclude '**/test/**' doFirst { println HORIZONTAL_LINE println "Building JAR for ${p.project_nice_name} ALL" println HORIZONTAL_LINE } duplicatesStrategy 'exclude' } p.task([type: Javadoc], 'projectAllJavadoc'){ p.allModuleNames.each{ moduleName -> source += p.sourceSets[moduleName].allJava classpath += p.sourceSets[moduleName].compileClasspath } destinationDir = p.file("${p.buildDir}/docs/projectAllJavadoc") options.addStringOption("sourcepath", "") } p.task([dependsOn: p.projectAllJavadoc, type: Jar], 'projectAllJavadocJar') { archiveClassifier = 'javadoc' from "${p.buildDir}/docs/projectAllJavadoc" archiveBaseName = "${p.project_name}" } p.task([type: Jar], 'projectAllSourcesJar') { p.allModuleNames.each{ moduleName -> from p.sourceSets[moduleName].allSource } archiveClassifier = 'sources' archiveBaseName = "${p.project_name}" duplicatesStrategy 'exclude' } p.task([dependsOn: p.publishToMavenLocal], "install") { doFirst { println("Installing artifacts for version ${p.build_version}") } } p.tasks.findAll{ task -> task.name.startsWith('dist_')}.each{ dist_task -> dist_task.dependencies.each{ dep -> def depCompileName = 'compile'+dep.replaceAll('\\.','')+'java' p.tasks.findAll{ comp_task -> comp_task.name.toLowerCase().equals(depCompileName)}.each {comp_task -> p.sourceSets[dist_task.moduleName].compileClasspath += p.files(p.sourceSets[dep].java.classesDirectory) { builtBy comp_task.name } if (dist_task.gwtSourceSetName!=null){ p.sourceSets["${dist_task.gwtSourceSetName}"].compileClasspath += p.files(p.sourceSets[dep].java.classesDirectory) { builtBy comp_task.name } } if (dist_task.requiresTest.toBoolean()){ p.sourceSets.test.compileClasspath += p.files(p.sourceSets[dep].java.classesDirectory) { builtBy comp_task.name } p.sourceSets.test.runtimeClasspath += p.files(p.sourceSets[dep].java.classesDirectory) { builtBy comp_task.name } if (p.tasks.findByName("installForTest_${dep}")) { tasks["test_${dist_task.moduleName}"].dependsOn("installForTest_${dep}") } } } } if (dist_task.requiresJar.toBoolean()){ p.tasks['jar_'+dist_task.moduleName].dependsOn{ p.tasks.findAll{ comp_task -> comp_task.name.toLowerCase().equals('compile'+dist_task.moduleName.replaceAll('\\.','')+'java')} } } p.bindist.dependsOn dist_task p.projectAllJar.dependsOn{ p.tasks.findAll{ comp_task -> comp_task.name.toLowerCase().equals('compile'+dist_task.moduleName.replaceAll('\\.','')+'java')} } } // fixed issue with libraries containing both .java and .class files p.tasks.withType(JavaCompile) { options.sourcepath=p.files() options.encoding='UTF-8' } p.tasks.withType(Javadoc) { options.addStringOption("sourcepath", "") if (JavaVersion.current().isJava8Compatible()) { options.addStringOption("Xdoclint:none", "-quiet") options.addBooleanOption("-allow-script-in-comments",true); } } p.artifacts { archives p.projectAllJar archives p.projectAllSourcesJar archives p.projectAllJavadocJar } p.publishing { publications { modules(MavenPublication) { artifactId = "${p.project_name}" artifact p.projectAllJar artifact p.projectAllSourcesJar { archiveClassifier = 'sources' } artifact p.projectAllJavadocJar { archiveClassifier = 'javadoc' } pom { name = "${p.project_nice_name} all" description = "${p.project_nice_name} all modules" packaging 'jar' groupId = 'com.alkacon' url = 'http://www.alkacon.com' version = p.build_version licenses { license { name = 'GNU General Public License' url = 'http://www.gnu.org/licenses/gpl.html' distribution = 'repo' } } organization { name = 'Alkacon Software' url = 'http://www.alkacon.com' } developers { developer { name = 'Alkacon Software' url = 'http://www.alkacon.com' } } withXml { xml -> def depsNode = xml.asNode().appendNode("dependencies") def depsWithScopes = [ [p.configurations.compile.dependencies, "compile"], [p.configurations.moduleDeps.dependencies, "compile"], [p.configurations.testCompile.dependencies, "test"] ] depsWithScopes.each { depsAndScope -> def deps = depsAndScope[0] def scope = depsAndScope[1] deps.each { dep -> if (dep instanceof ExternalModuleDependency) { def depNode = depsNode.appendNode("dependency") depNode.appendNode('groupId', dep.group) depNode.appendNode('artifactId', dep.name) depNode.appendNode('version', dep.version) depNode.appendNode('scope', scope) if (!dep.isTransitive()) { def exclusionNode = depNode.appendNode("exclusions").appendNode("exclusion") exclusionNode.appendNode('artifactId', '*') exclusionNode.appendNode('groupId', '*') } } } } } } } } } if (p.copyModuleTestExists) { p.task([type: Delete],"deleteInstallForTestCopies") { delete (p.fileTree(dir: p.copy_module_test).matching { p.tasks.findAll{ task -> task.name.startsWith('installForTest_')}.each{ install_task -> include "${install_task.moduleName}.zip" } }) } p.tasks["clean"].dependsOn("deleteInstallForTestCopies") } p.task([type: Wrapper], 'setGradleVersion'){ gradleVersion = GRADLE_VERSION } p.tasks.withType(GenerateModuleMetadata) { enabled = false } } catch(Exception e) { p.logger.error("${HORIZONTAL_LINE}\nFailed to configure OpenCms modules project:\n\n${e.message} \n\nUse the opencmsPluginDescription task to view plugin description.\n${HORIZONTAL_LINE}\n\n",e) } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy