| /* |
| * 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. |
| */ |
| import org.apache.tools.ant.filters.ReplaceTokens |
| import org.asciidoctor.gradle.jvm.AsciidoctorTask |
| |
| /* ======================================================== |
| * Project setup |
| * ======================================================== */ |
| plugins { |
| id 'application' |
| id 'groovy' |
| id 'eclipse' |
| id 'checkstyle' |
| id 'codenarc' |
| id 'maven-publish' |
| id 'org.asciidoctor.jvm.convert' version '3.3.2' // 4.0.2 does not compile |
| id 'org.asciidoctor.jvm.pdf' version '3.3.2' // 4.0.2 does not compile |
| id 'org.owasp.dependencycheck' version '9.0.9' apply false //Not tested after 7.4.4 |
| id 'se.patrikerdes.use-latest-versions' version '0.2.18' apply false |
| id 'com.github.ben-manes.versions' version '0.51.0' apply false |
| id "com.github.ManifestClasspath" version "0.1.0-RELEASE" |
| id "com.github.jakemarsden.git-hooks" version "0.0.2" |
| id "com.github.node-gradle.node" version '7.0.2' apply false |
| } |
| |
| /* OWASP plugin |
| * |
| * If project property "enableOwasp" is flagged then |
| * gradle will download required dependencies and |
| * activate Gradle's OWASP plugin and its related tasks. |
| * |
| * Syntax: gradlew -PenableOwasp dependencyCheckAnalyze |
| */ |
| if (project.hasProperty('enableOwasp')) { |
| apply plugin: 'org.owasp.dependencycheck' |
| } |
| |
| /* DependencyUpdates plugin |
| * |
| * If project property "enableDependencyUpdates" is flagged then |
| * gradle will download required dependencies and |
| * activate Gradle's DependencyUpdates plugin and its related tasks. |
| * |
| * Syntax: gradlew -PenableDependencyUpdates dependencyUpdates -Drevision=release |
| * |
| * You may want to use the use-latest-versions plugin to help you in your work |
| * Syntax: |
| * Check only: gradlew -PenableDependencyUpdates useLatestVersions && gradlew -PenableDependencyUpdates useLatestVersionsCheck |
| * Automated update: gradlew -PenableDependencyUpdates useLatestVersions |
| * Beware that this is only a help. |
| * If you use it without check you will need to check things by yourself (can be as tedious as not using this plugin) |
| */ |
| if (project.hasProperty('enableDependencyUpdates')) { |
| apply plugin: 'com.github.ben-manes.versions' |
| apply plugin: 'se.patrikerdes.use-latest-versions' |
| } |
| |
| apply from: 'common.gradle' |
| apply from: 'dependencies.gradle' |
| |
| // global properties |
| ext.os = System.getProperty('os.name').toLowerCase() |
| ext.gradlew = os.contains('windows') ? 'gradlew.bat' : './gradlew' |
| ext.pluginsDir = "${rootDir}/plugins" |
| |
| application { |
| mainClass = 'org.apache.ofbiz.base.start.Start' |
| applicationDefaultJvmArgs = project.hasProperty('jvmArgs') |
| ? jvmArgs.tokenize() |
| : ['-Xms128M','-Xmx1024M', |
| '-Djdk.serialFilter=maxarray=100000;maxdepth=20;maxrefs=1000;maxbytes=500000', // OFBIZ-12592 and OFBIZ-12716 |
| // '--add-exports=java.base/sun.util.calendar=ALL-UNNAMED', // OFBIZ-12721 |
| '--add-opens=java.base/java.util=ALL-UNNAMED' // OFBIZ-12726 |
| ] |
| } |
| |
| distributions.main.contents.from(rootDir) { |
| include 'framework/**', 'applications/**', 'themes/**', 'plugins/**' |
| } |
| |
| javadoc { |
| title="OFBiz " + getCurrentGitBranch() + " API" |
| failOnError = true |
| options { |
| source '17' |
| encoding 'UTF-8' |
| charSet 'UTF-8' |
| // Those external Javadoc links should correspond to the actual |
| // versions declared in the 'dependencies' block. |
| links( |
| 'https://docs.oracle.com/javase/17/docs/api', |
| 'https://tomcat.apache.org/tomcat-9.0-doc/servletapi/', |
| 'http://docs.groovy-lang.org/docs/groovy-3.0.20/html/api', |
| 'https://commons.apache.org/proper/commons-cli/apidocs' |
| ) |
| } |
| } |
| |
| java { |
| sourceCompatibility(JavaVersion.VERSION_17) |
| targetCompatibility(JavaVersion.VERSION_17) |
| } |
| |
| // Java compile options, syntax gradlew -PXlint:none build |
| tasks.withType(JavaCompile) { |
| options.encoding = 'UTF-8' |
| if (!project.hasProperty('Xlint:none')) { |
| options.compilerArgs << '-Xlint:all' |
| // Exclude varargs warnings which are not silenced by @SafeVarargs. |
| options.compilerArgs << '-Xlint:-varargs' |
| } |
| } |
| |
| // Only used for release branches |
| def getCurrentGitBranch() { |
| return "git branch --show-current".execute().text.trim() |
| } |
| |
| // defines the footer files for git info |
| def File gitFooterFile = file("${rootDir}/runtime/GitInfo.ftl") |
| |
| // root and subproject settings |
| defaultTasks 'jar', 'test' |
| |
| allprojects { |
| repositories { |
| mavenCentral() |
| // the switch from jCenter to mavenCentral needs some additional repositories to be configured here |
| // this should be checked frequently to remove obsolete configurations if the artifacts are available |
| // on mavenCentral directly |
| maven { |
| // org.restlet and org.restlet.ext.servlet |
| url 'https://maven.restlet.talend.com' |
| } |
| maven { |
| // net.fortuna.ical4j:ical4j:1.0-rc3-atlassian-11 |
| url 'https://packages.atlassian.com/maven-3rdparty/' |
| } |
| maven { |
| // org/milyn/flute/1.3/flute-1.3.jar |
| // need artifact only because of wrong pom metadata in maven central |
| // Required by: plugins:birt > org.eclipse.birt.runtime:viewservlets:4.5.0 > org.eclipse.birt.runtime:org.eclipse.birt.runtime:4.4.1 |
| // TODO Maybe this will no longer needed wheh upgrading viewservlets to 4.9.0 |
| url "https://repo1.maven.org/maven2" |
| metadataSources { |
| artifact() |
| } |
| } |
| maven { |
| url 'https://clojars.org/repo' |
| } |
| maven { |
| // org.cyberneko.html.parsers (used by UELFunctions, was in esapi before 2.3) |
| url "https://repository.ow2.org/nexus/content/repositories/public/" |
| } |
| maven { |
| // To test not released FreeMarker versions |
| url "https://repository.apache.org/content/repositories/snapshots/" |
| } |
| |
| } |
| } |
| |
| subprojects { |
| configurations { |
| // compile-time plugin libraries |
| pluginLibsCompile |
| // runtime plugin libraries |
| pluginLibsRuntime |
| //compile-only libraries |
| pluginLibsCompileOnly |
| } |
| } |
| |
| configurations { |
| junitReport { |
| description = 'libraries needed to run junitreport for OFBiz unit tests' |
| } |
| ofbizPlugins { |
| description = 'ofbiz plugin dependencies configuration' |
| transitive = true |
| } |
| } |
| |
| configurations.all { |
| exclude group: 'log4j', module: 'log4j' |
| exclude group: 'org.slf4j', module: 'slf4j-log4j12' |
| exclude group: 'xml-apis', module: 'xml-apis' |
| exclude group: 'jaxen', module: 'jaxen' |
| exclude group: 'javax.xml.stream', module: 'stax-api' |
| exclude group: 'org.apache.geronimo.specs', module: 'geronimo-stax-api_1.0_spec' |
| exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jta_1.1_spec' |
| exclude group: 'javax.transaction', module: 'jta' |
| } |
| |
| dependencies { |
| // Dependencies defined by the plugins |
| subprojects.each { subProject -> |
| implementation project(path: subProject.path, configuration: 'pluginLibsCompile') |
| runtimeOnly project(path: subProject.path, configuration: 'pluginLibsRuntime') |
| compileOnly project(path: subProject.path, configuration: 'pluginLibsCompileOnly') |
| } |
| |
| junitReport 'junit:junit:4.13.2' |
| junitReport 'org.apache.ant:ant-junit:1.10.14' |
| |
| // Libraries downloaded manually |
| implementation fileTree(dir: file("${rootDir}/lib"), include: '**/*.jar') |
| getDirectoryInActiveComponentsIfExists('lib').each { libDir -> |
| implementation fileTree(dir: libDir, include: '**/*.jar') |
| } |
| } |
| |
| def excludedJavaSources = [ |
| 'org/apache/ofbiz/accounting/thirdparty/cybersource/IcsPaymentServices.java', |
| 'org/apache/ofbiz/accounting/thirdparty/orbital/OrbitalPaymentServices.java', |
| 'org/apache/ofbiz/accounting/thirdparty/paypal/PayPalServices.java', |
| 'org/apache/ofbiz/accounting/thirdparty/securepay/SecurePayPaymentServices.java', |
| 'org/apache/ofbiz/accounting/thirdparty/securepay/SecurePayServiceTest.java', |
| 'org/apache/ofbiz/accounting/thirdparty/verisign/PayflowPro.java', |
| 'org/apache/ofbiz/order/thirdparty/taxware/TaxwareException.java', |
| 'org/apache/ofbiz/order/thirdparty/taxware/TaxwareServices.java', |
| 'org/apache/ofbiz/order/thirdparty/taxware/TaxwareUTL.java' |
| ] |
| |
| sourceSets { |
| // This is for integration tests (DB access) |
| main { |
| java { |
| srcDirs = getDirectoryInActiveComponentsIfExists('src/main/java') |
| exclude excludedJavaSources |
| } |
| groovy { |
| srcDirs = getDirectoryInActiveComponentsIfExists('src/main/groovy') |
| } |
| resources { |
| srcDirs = getDirectoryInActiveComponentsIfExists('src/main/resources') |
| srcDirs += getDirectoryInActiveComponentsIfExists('config') |
| srcDirs += getDirectoryInActiveComponentsIfExists('dtd') |
| } |
| } |
| // This is for unit tests (no DB access) |
| test { |
| java { |
| srcDirs = getDirectoryInActiveComponentsIfExists('src/test/java') |
| } |
| // Groovy tests often fail, because JUNIT does not have access to the ofbiz enviroment. |
| // If a groovy test is supposed to be tested this way, it can be added here. |
| groovy { |
| srcDirs = getDirectoryInActiveComponentsIfExists('src/test/groovy') |
| include 'org/apache/ofbiz/service/ModelServiceTest.groovy' |
| include 'org/apache/ofbiz/test/TestServices.groovy' |
| include 'org/apache/ofbiz/base/util/FileUtilTests.groovy' |
| } |
| resources { |
| srcDirs = getDirectoryInActiveComponentsIfExists('src/test/resources') |
| } |
| } |
| } |
| |
| jar.manifest.attributes( |
| 'Implementation-Title': project.name, |
| 'Main-Class': application.mainClass, |
| 'Class-Path': getJarClasspath() |
| ) |
| |
| // Checks OFBiz Java coding conventions. |
| checkstyle { |
| // Defining a maximum number of "tolerated" errors ensures that |
| // this number cannot increase in the future. It corresponds to |
| // the sum of errors found last time it was changed after using the |
| // 'checkstyle' tool present in the framework and in the official |
| // plugins. |
| tasks.checkstyleMain.maxErrors = 0 |
| // Currently there are no errors so we can show new one when they appear |
| showViolations = true |
| } |
| gitHooks { |
| hooks = ['pre-push': 'checkstyleMain codenarcMain codenarcTest'] |
| } |
| |
| // Checks OFBiz Groovy coding conventions. |
| codenarc { |
| setConfigFile(new File('config/codenarc/codenarc.groovy')) |
| setMaxPriority1Violations(0) |
| setMaxPriority2Violations(410) |
| setMaxPriority3Violations(3974) |
| } |
| |
| // Eclipse plugin settings |
| eclipse.classpath.file.whenMerged { classpath -> |
| /* The code inside this block removes unnecessary entries |
| * in the .classpath file which are generated automatically |
| * due to the settings in the sourceSets block |
| */ |
| def fileSep = System.getProperty('file.separator') |
| |
| activeComponents().each { component -> |
| def componentName = component.toString() - rootDir.toString() - fileSep |
| def eclipseEntry = os.contains('windows') ? componentName.replaceAll("\\\\", '/') : componentName |
| |
| classpath.entries.removeAll { entry -> |
| // remove any "src" entries in .classpath of the form /componentName |
| entry.kind == 'src' && ( |
| entry.path ==~ '.*/+(' + componentName.tokenize(fileSep).last() + ')$' || |
| entry.path ==~ /(\/+framework)$/ || |
| entry.path ==~ /(\/+applications)$/ || |
| entry.path ==~ /(\/+plugins)$/ || |
| entry.path ==~ /(\/+themes)$/ ) |
| } |
| } |
| } |
| tasks.eclipse.dependsOn(cleanEclipse) |
| |
| test { |
| jvmArgs "-javaagent:${classpath.find { it.name.contains('jmockit') }.absolutePath}" |
| } |
| |
| /* ======================================================== |
| * Tasks |
| * ======================================================== */ |
| |
| // ========== Task group labels ========== |
| def cleanupGroup = 'Cleaning' |
| def docsGroup = 'Documentation' |
| def ofbizServer = 'OFBiz Server' |
| def ofbizPlugin = 'OFBiz Plugin' |
| def sysadminGroup = 'System Administration' |
| |
| // ========== OFBiz Server tasks ========== |
| |
| task loadAll(group: ofbizServer) { |
| dependsOn 'ofbiz --load-data' |
| description 'Load default data; meant for OFBiz development, testing, and demo purposes' |
| } |
| |
| task testIntegration(group: ofbizServer) { |
| dependsOn 'ofbiz --test' |
| description 'Run OFBiz integration tests; You must run loadAll before running this task' |
| } |
| |
| task terminateOfbiz(group: ofbizServer, |
| description: 'Force termination of any running OFBiz servers, only use if \"--shutdown\" command fails') { |
| doLast { |
| if (os.contains('windows')) { |
| Runtime.getRuntime().exec("wmic process where \"CommandLine Like \'%org.apache.ofbiz.base.start.Start%\'\" Call Terminate") |
| } else { |
| def processOutput = new ByteArrayOutputStream() |
| exec { |
| commandLine 'ps', 'ax' |
| standardOutput = processOutput |
| } |
| processOutput.toString().split(System.lineSeparator()).each { line -> |
| if (line ==~ /.*org\.apache\.ofbiz\.base\.start\.Start.*/) { |
| exec { commandLine 'kill', '-9', line.tokenize().first() } |
| } |
| } |
| } |
| } |
| } |
| |
| task loadAdminUserLogin(group: ofbizServer) { |
| description 'Create admin user with temporary password equal to ofbiz. You must provide userLoginId' |
| createOfbizCommandTask('executeLoadAdminUser', |
| ['--load-data', 'file=/runtime/tmp/AdminUserLoginData.xml']) |
| executeLoadAdminUser.doFirst { |
| copy { |
| from ("${rootDir}/framework/resources/templates/AdminUserLoginData.xml") { |
| filter(ReplaceTokens, tokens: [userLoginId: userLoginId]) |
| } |
| into "${rootDir}/runtime/tmp/" |
| } |
| } |
| dependsOn executeLoadAdminUser |
| doLast { |
| delete("${rootDir}/runtime/tmp/AdminUserLoginData.xml") |
| } |
| } |
| |
| task loadTenant(group: ofbizServer, description: 'Load data using tenantId') { |
| |
| createOfbizCommandTask('executeLoadTenant', []) |
| |
| if (project.hasProperty('tenantId')) { |
| executeLoadTenant.args '--load-data', "delegator=default#${tenantId}" |
| } |
| if (project.hasProperty('tenantReaders')) { |
| executeLoadTenant.args '--load-data', "readers=${tenantReaders}" |
| } |
| if (project.hasProperty('tenantComponent')) { |
| executeLoadTenant.args '--load-data', "component=${tenantComponent}" |
| } |
| |
| executeLoadTenant.doFirst { |
| if (!project.hasProperty('tenantId')) { |
| throw new GradleException('Missing project property tenantId') |
| } |
| } |
| dependsOn executeLoadTenant |
| } |
| |
| task createTenant(group: ofbizServer, description: 'Create a new tenant in your environment') { |
| |
| def databaseTemplateFile = "${rootDir}/framework/resources/templates/AdminNewTenantData-Derby.xml" |
| |
| task prepareAndValidateTenantArguments { |
| doLast { |
| if (!project.hasProperty('tenantId')) { |
| throw new GradleException('Project property tenantId is missing') |
| } |
| // dbPlatform values: D(Derby), M(MySQL), O(Oracle), P(PostgreSQL) (default D) |
| if (project.hasProperty('dbPlatform')) { |
| if (dbPlatform == 'D') { |
| databaseTemplateFile = "${rootDir}/framework/resources/templates/AdminNewTenantData-Derby.xml" |
| } else if (dbPlatform == 'M') { |
| databaseTemplateFile = "${rootDir}/framework/resources/templates/AdminNewTenantData-MySQL.xml" |
| } else if (dbPlatform == 'O') { |
| databaseTemplateFile = "${rootDir}/framework/resources/templates/AdminNewTenantData-Oracle.xml" |
| } else if (dbPlatform == 'P') { |
| databaseTemplateFile = "${rootDir}/framework/resources/templates/AdminNewTenantData-PostgreSQL.xml" |
| } else { |
| throw new GradleException('Invalid value for property dbPlatform: ' + "${dbPlatform}") |
| } |
| } |
| } |
| } |
| |
| task generateDatabaseTemplateFile(dependsOn: prepareAndValidateTenantArguments) { |
| doLast { |
| def filterTokens = ['tenantId': tenantId, |
| 'tenantName': project.hasProperty('tenantName') ? tenantName : tenantId, |
| 'domainName': project.hasProperty('domainName') ? domainName : 'org.apache.ofbiz', |
| 'db-IP': project.hasProperty('dbIp') ? dbIp : '', |
| 'db-User': project.hasProperty('dbUser') ? dbUser : '', |
| 'db-Password': project.hasProperty('dbPassword') ? dbPassword : ''] |
| |
| generateFileFromTemplate(databaseTemplateFile, 'runtime/tmp', |
| filterTokens, 'tmpFilteredTenantData.xml') |
| } |
| } |
| |
| task generateAdminUserTemplateFile(dependsOn: prepareAndValidateTenantArguments) { |
| doLast { |
| generateFileFromTemplate( |
| "${rootDir}/framework/resources/templates/AdminUserLoginData.xml", |
| 'runtime/tmp', |
| ['userLoginId': "${tenantId}-admin".toString()], |
| 'tmpFilteredUserLogin.xml') |
| } |
| } |
| |
| // Load the tenants master database |
| createOfbizCommandTask('loadTenantOnMasterTenantDb', |
| ['--load-data', 'file=/runtime/tmp/tmpFilteredTenantData.xml', |
| '--load-data', 'readers=tenant']) |
| loadTenantOnMasterTenantDb.dependsOn(generateDatabaseTemplateFile, generateAdminUserTemplateFile) |
| |
| // Load the actual tenant data |
| createOfbizCommandTask('loadTenantData', []) |
| loadTenantData.dependsOn(loadTenantOnMasterTenantDb) |
| |
| // Load the tenant admin user account |
| createOfbizCommandTask('loadTenantAdminUserLogin', []) |
| loadTenantAdminUserLogin.dependsOn(loadTenantData) |
| |
| /* pass arguments to tasks, must be done this way |
| * because we are in the configuration phase. We cannot |
| * set the parameters at the execution phase. */ |
| if (project.hasProperty('tenantId')) { |
| loadTenantData.args '--load-data', "delegator=default#${tenantId}" |
| loadTenantAdminUserLogin.args( |
| '--load-data', "delegator=default#${tenantId}", |
| '--load-data', "file=${rootDir}/runtime/tmp/tmpFilteredUserLogin.xml" |
| ) |
| } |
| if (project.hasProperty('tenantReaders')) { |
| loadTenantData.args '--load-data', "readers=${tenantReaders}" |
| } |
| |
| dependsOn(loadTenantAdminUserLogin) |
| |
| // cleanup |
| doLast { |
| delete("${rootDir}/runtime/tmp/tmpFilteredTenantData.xml") |
| delete("${rootDir}/runtime/tmp/tmpFilteredUserLogin.xml") |
| } |
| } |
| |
| // ========== Documentation tasks ========== |
| tasks.withType(AsciidoctorTask) { task -> |
| inProcess = JAVA_EXEC |
| forkOptions { |
| jvmArgs("--add-opens","java.base/sun.nio.ch=ALL-UNNAMED","--add-opens","java.base/java.io=ALL-UNNAMED") |
| } |
| outputOptions { |
| // I hate we have to do this - but JRuby (asciidoctorj-pdf) and Windows don't mix well |
| if (System.properties['os.name'].toLowerCase().contains('windows')) { |
| backends = ['html5'] |
| } else { |
| backends = ['html5', 'pdf'] |
| } |
| } |
| attributes \ |
| 'doctype': 'book', |
| 'revnumber': getCurrentGitBranch(), |
| 'experimental': '', |
| 'allow-uri-read': true, |
| 'icons': 'font', |
| 'sectnums': '', |
| 'chapter-label': '', |
| 'toc': 'left@', |
| 'toclevels': '3' |
| } |
| |
| task deleteOfbizDocumentation { |
| doFirst { delete "${buildDir}/asciidoc/ofbiz" } |
| } |
| |
| task deletePluginDocumentation { |
| doFirst { |
| if (!project.hasProperty('pluginId')) { |
| throw new GradleException('Missing property \"pluginId\"') |
| } |
| if(!(activeComponents().stream().anyMatch { it.name == pluginId })) { |
| throw new GradleException("Could not find plugin with id ${pluginId}") |
| } |
| delete "${buildDir}/asciidoc/plugins/${pluginId}" |
| } |
| } |
| |
| task deleteAllPluginsDocumentation { |
| doFirst { delete "${buildDir}/asciidoc/plugins" } |
| } |
| |
| |
| task generateReadmeFiles(group: docsGroup, type: AsciidoctorTask) { |
| doFirst { delete "${buildDir}/asciidoc/readme" } |
| description 'Generate OFBiz README files' |
| sourceDir "${rootDir}" |
| // CHANGELOG.adoc should be only present in the current stable version |
| sources { |
| include 'README.adoc', 'CHANGELOG.adoc', 'CONTRIBUTING.adoc', 'DOCKER.adoc' |
| } |
| outputDir file("${buildDir}/asciidoc/readme/") |
| } |
| |
| task generateOfbizDocumentation(group: docsGroup, type: AsciidoctorTask) { |
| dependsOn deleteOfbizDocumentation |
| description 'Generate OFBiz documentation manuals' |
| activeComponents().each { component -> |
| copy { |
| from "${component}/src/docs/asciidoc/images/${component.name}" |
| include '**/*.*' |
| into "${rootDir}/docs/asciidoc/images/${component.name}" |
| } |
| } |
| sourceDir "${rootDir}/docs/asciidoc" |
| outputDir file("${buildDir}/asciidoc/ofbiz") |
| doLast { |
| activeComponents().each { component -> |
| delete "${rootDir}/docs/asciidoc/images/${component.name}" |
| } |
| } |
| } |
| |
| task generatePluginDocumentation(group: docsGroup) { |
| dependsOn deletePluginDocumentation |
| description 'Generate plugin documentation. Expects pluginId flag' |
| activeComponents() |
| .findAll { project.hasProperty('pluginId') && it.name == pluginId } |
| .each { component -> |
| def pluginAsciidoc = task "${component.name}Documentation" (type: AsciidoctorTask) { |
| def asciidocFolder = new File("${component}/src/docs/asciidoc") |
| if (asciidocFolder.exists()) { |
| copy { |
| from "${rootDir}/docs/asciidoc/images/OFBiz-Logo.svg" |
| into "${component}/src/docs/asciidoc/images" |
| } |
| sourceDir file("${component}/src/docs/asciidoc") |
| outputDir file("${buildDir}/asciidoc/plugins/${component.name}") |
| doLast { println "Documentation generated for plugin ${component.name}" } |
| } else { |
| println "No documentation found for plugin ${component.name}" |
| } |
| doLast { delete "${component}/src/docs/asciidoc/images/OFBiz-Logo.svg" } |
| mustRunAfter deletePluginDocumentation |
| } |
| dependsOn pluginAsciidoc |
| doLast { delete "${component}/src/docs/asciidoc/images/OFBiz-Logo.svg" } |
| } |
| } |
| |
| task generateAllPluginsDocumentation(group: docsGroup, |
| description: 'Generate all plugins documentation.') { |
| |
| dependsOn deleteAllPluginsDocumentation |
| file("${pluginsDir}").eachDir { plugin -> |
| activeComponents().each { component -> |
| if (component.name == plugin.name) { |
| if (subprojectExists(":plugins:${plugin.name}")) { |
| // Note: the "-" between "component.name" and "Documentation" allows to differentiate from |
| // the other inner task temporary created by the generatePluginDocumentation task |
| def pluginAsciidoc = task "${component.name}-Documentation" (type: AsciidoctorTask) { |
| def asciidocFolder = new File("${component}/src/docs/asciidoc") |
| doFirst { |
| if (asciidocFolder.exists()) { |
| copy { |
| from "${rootDir}/docs/asciidoc/images/OFBiz-Logo.svg" |
| into "${component}/src/docs/asciidoc/images" |
| } |
| } |
| } |
| if (asciidocFolder.exists()) { |
| sourceDir file("${component}/src/docs/asciidoc") |
| outputDir file("${buildDir}/asciidoc/plugins/${component.name}") |
| doLast { println "Documentation generated for plugin ${component.name}" } |
| } |
| mustRunAfter deleteAllPluginsDocumentation |
| doLast { delete "${component}/src/docs/asciidoc/images/OFBiz-Logo.svg" } |
| } |
| dependsOn pluginAsciidoc |
| } |
| } |
| } |
| } |
| } |
| |
| |
| // ========== System Administration tasks ========== |
| task createTestReports(group: sysadminGroup, description: 'Generate HTML reports from junit XML output') { |
| doLast { |
| ant.taskdef(name: 'junitreport', |
| classname: 'org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator', |
| classpath: configurations.junitReport.asPath) |
| ant.junitreport(todir: './runtime/logs/test-results') { |
| fileset(dir: './runtime/logs/test-results') { |
| include(name: '*.xml') |
| } |
| report(format:'frames', todir:'./runtime/logs/test-results/html') |
| } |
| } |
| } |
| |
| task gitInfoFooter(group: sysadminGroup, description: 'Update the Git Branch-revision info in the footer if Git is used') { |
| doLast { |
| def branch |
| def revision |
| def timestamp = new Date().format 'yyyy-MM-dd HH:mm:ss' |
| def gitFolder = rootProject.file('.git') |
| |
| if (!gitFolder.exists()) { |
| println ('Git is not used') |
| return |
| } |
| |
| def branchOutput = new ByteArrayOutputStream() |
| exec { |
| commandLine 'git', 'rev-parse', '--abbrev-ref', 'HEAD' |
| standardOutput = branchOutput |
| } |
| branch = branchOutput.toString() |
| def revisionOutput = new ByteArrayOutputStream() |
| exec { |
| commandLine 'git', 'rev-parse', 'HEAD' |
| standardOutput = revisionOutput |
| } |
| revision = revisionOutput.toString() |
| gitFooterFile.delete() |
| gitFooterFile.createNewFile() |
| gitFooterFile << System.lineSeparator() |
| gitFooterFile << '${uiLabelMap.CommonBranch} : ' + "${branch}" + System.lineSeparator() |
| gitFooterFile << '${uiLabelMap.CommonRevision} : ' + "${revision}" + System.lineSeparator() |
| gitFooterFile << '${uiLabelMap.CommonBuiltOn} : ' + "${timestamp}" + System.lineSeparator() |
| gitFooterFile << '${uiLabelMap.CommonJavaVersion} : ' + "${org.gradle.internal.jvm.Jvm.current()}" |
| } |
| } |
| |
| // ========== OFBiz Plugin Management ========== |
| task createPlugin(group: ofbizPlugin, description: 'create a new plugin component based on specified templates') { |
| doLast { |
| if (!project.hasProperty('pluginResourceName')) { |
| ext.pluginResourceName = pluginId.capitalize() |
| } |
| if (!project.hasProperty('webappName')) { |
| ext.webappName = pluginId |
| } |
| if (!project.hasProperty('basePermission')) { |
| ext.basePermission = pluginId.toUpperCase() |
| } |
| |
| def filterTokens = ['component-name': pluginId, |
| 'component-resource-name': pluginResourceName, |
| 'webapp-name': webappName, |
| 'base-permission': basePermission] |
| def templateDir = "${rootDir}/framework/resources/templates" |
| def pluginDir = "${pluginsDir}/${pluginId}" |
| |
| ['config', 'dtd', 'entitydef', 'lib', 'patches/test', 'patches/qa', |
| 'patches/production', 'src/main/groovy', 'minilang', 'servicedef', 'src/main/java', 'src/test/java', 'testdef', |
| 'widget', "webapp/${webappName}/error", "webapp/${webappName}/WEB-INF"].each { |
| mkdir pluginDir + '/' + it |
| } |
| |
| [ [tempName:'ofbiz-component.xml', newName:'ofbiz-component.xml', location:''], |
| [tempName:'build.gradle', newName:'build.gradle', location:''], |
| [tempName:'TypeData.xml', newName:"${pluginResourceName}TypeData.xml", location:'data'], |
| [tempName:'SecurityPermissionSeedData.xml', newName:"${pluginResourceName}SecurityPermissionSeedData.xml", location:'data'], |
| [tempName:'SecurityGroupDemoData.xml', newName:"${pluginResourceName}SecurityGroupDemoData.xml", location:'data'], |
| [tempName:'DemoData.xml', newName:"${pluginResourceName}DemoData.xml", location:'data'], |
| [tempName:'HELP.adoc', newName:'HELP.adoc', location:''], |
| [tempName:'README.adoc', newName:'README.adoc', location:''], |
| [tempName:'entitymodel.xml', newName:'entitymodel.xml', location:'entitydef'], |
| [tempName:'services.xml', newName:'services.xml', location:'servicedef'], |
| [tempName:'Tests.xml', newName:"${pluginResourceName}Tests.xml", location:'testdef'], |
| [tempName:'UiLabels.xml', newName:"${pluginResourceName}UiLabels.xml", location:'config'], |
| [tempName:'index.jsp', newName:'index.jsp', location:"webapp/${webappName}"], |
| [tempName:'controller.xml', newName:'controller.xml', location:"webapp/${webappName}/WEB-INF"], |
| [tempName:'web.xml', newName:'web.xml', location:"webapp/${webappName}/WEB-INF"], |
| [tempName:'CommonScreens.xml', newName:'CommonScreens.xml', location:'widget'], |
| [tempName:'Screens.xml', newName:"${pluginResourceName}Screens.xml", location:'widget'], |
| [tempName:'Menus.xml', newName:"${pluginResourceName}Menus.xml", location:'widget'], |
| [tempName:'Forms.xml', newName:"${pluginResourceName}Forms.xml", location:'widget'] |
| ].each { tmpl -> |
| generateFileFromTemplate(templateDir + '/' + tmpl.tempName, |
| pluginDir + '/' + tmpl.location, filterTokens, tmpl.newName) |
| } |
| |
| println "plugin successfully created in directory ${pluginsDir}/${pluginId}." |
| } |
| } |
| |
| task installPlugin(group: ofbizPlugin, description: 'executes plugin install task if it exists') { |
| |
| doFirst { |
| if (!project.hasProperty('pluginId')) { |
| throw new GradleException('Missing property \"pluginId\"') |
| } |
| } |
| |
| if (project.hasProperty('pluginId')) { |
| activeComponents() |
| .findAll { it.name == pluginId } |
| .each { component -> |
| if (taskExistsInproject(":plugins:${pluginId}", 'install')) { |
| dependsOn ":plugins:${pluginId}:install" |
| doLast { println "installed plugin ${pluginId}" } |
| } else { |
| doLast { println "No install task defined for plugin ${pluginId}, nothing to do" } |
| } |
| } |
| } |
| } |
| |
| task uninstallPlugin(group: ofbizPlugin, description: 'executes plugin uninstall task if it exists') { |
| |
| doFirst { |
| if (!project.hasProperty('pluginId')) { |
| throw new GradleException('Missing property \"pluginId\"') |
| } |
| if (!subprojectExists(":plugins:${pluginId}")) { |
| throw new GradleException("Plugin \"${pluginId}\" does not exist") |
| } |
| } |
| |
| if (project.hasProperty('pluginId') && taskExistsInproject(":plugins:${pluginId}", 'uninstall')) { |
| dependsOn ":plugins:${pluginId}:uninstall" |
| doLast { println "uninstalled plugin ${pluginId}" } |
| } else { |
| doLast { println "No uninstall task defined for plugin ${pluginId}" } |
| } |
| } |
| |
| task removePlugin(group: ofbizPlugin, description: 'Uninstall a plugin and delete its files') { |
| if (project.hasProperty('pluginId') && subprojectExists(":plugins:${pluginId}")) { |
| dependsOn uninstallPlugin |
| } |
| |
| doLast { |
| if (file("${pluginsDir}/${pluginId}").exists()) { |
| delete "${pluginsDir}/${pluginId}" |
| } else { |
| throw new GradleException("Directory not found: ${pluginsDir}/${pluginId}") |
| } |
| } |
| } |
| |
| task pushPlugin(group: ofbizPlugin, description: 'push an existing plugin to local maven repository') { |
| |
| if (project.hasProperty('pluginId')) { |
| doFirst { |
| if (!subprojectExists(":plugins:${pluginId}")) { |
| throw new GradleException("Plugin ${pluginId} does not exist, cannot publish") |
| } |
| } |
| task createPluginArchive(type: Zip) { |
| from "${pluginsDir}/${pluginId}" |
| } |
| |
| publishing { |
| publications { |
| ofbizPluginPublication(MavenPublication) { |
| artifactId pluginId |
| groupId project.hasProperty('pluginGroup') ? pluginGroup : 'org.apache.ofbiz.plugin' |
| version project.hasProperty('pluginVersion') ? pluginVersion : '0.1.0-SNAPSHOT' |
| |
| artifact createPluginArchive |
| |
| pom.withXml { |
| if (project.hasProperty('pluginDescription')) { |
| asNode().appendNode('description', pluginDescription) |
| } else { |
| asNode().appendNode('description', "Publication of OFBiz plugin ${pluginId}") |
| } |
| } |
| } |
| } |
| } |
| |
| if (subprojectExists(":plugins:${pluginId}")) { |
| dependsOn publishToMavenLocal |
| } |
| |
| } else { |
| doFirst { throw new GradleException('Missing property \"pluginId\"') } |
| } |
| } |
| |
| task pullPlugin(group: ofbizPlugin, description: 'Download and install a plugin with all dependencies') { |
| doLast { |
| if (!project.hasProperty('dependencyId')) { |
| throw new GradleException('You must pass the dependencyId of the plugin') |
| } |
| |
| // Connect to a remote maven repository if defined |
| if (project.hasProperty('repoUrl')) { |
| repositories { |
| maven { |
| url repoUrl |
| if (project.hasProperty('repoUser') && project.hasProperty('repoPassword')) { |
| credentials { |
| username repoUser |
| password repoPassword |
| } |
| } |
| } |
| } |
| } |
| |
| // download plugin and dependencies |
| dependencies { |
| ofbizPlugins dependencyId |
| } |
| |
| // reverse the order of dependencies to install them before the plugin |
| def ofbizPluginArchives = new ArrayList(configurations.ofbizPlugins.files) |
| Collections.reverse(ofbizPluginArchives) |
| |
| // Extract and install plugin and dependencies |
| ofbizPluginArchives.each { pluginArchive -> |
| ext.pluginId = dependencyId.tokenize(':').get(1) |
| println "installing plugin: ${pluginId}" |
| copy { |
| from zipTree(pluginArchive) |
| into "${pluginsDir}/${pluginId}" |
| } |
| gradlewSubprocess(['installPlugin', "-PpluginId=${pluginId}"]) |
| } |
| } |
| } |
| |
| // ========== Clean up tasks ========== |
| task cleanCatalina(group: cleanupGroup, description: 'Clean Catalina data in runtime/catalina/work') { |
| doLast { delete "${rootDir}/runtime/catalina/work" } |
| } |
| task cleanData(group: cleanupGroup, description: 'Clean all DB data (Derby) under runtime/data') { |
| doLast { deleteAllInDirWithExclusions("${rootDir}/runtime/data/", ['README', 'derby.properties']) } |
| } |
| task cleanDownloads(group: cleanupGroup, description: 'Clean all downloaded files') { |
| doLast { |
| delete fileTree(dir: "${rootDir}/framework/base/lib", includes: ['activemq-*.jar']) |
| delete fileTree(dir: "${rootDir}/framework/entity/lib/jdbc", includes: ['postgresql-*.jar']) |
| delete fileTree(dir: "${rootDir}/framework/entity/lib/jdbc", includes: ['mysql-*.jar']) |
| } |
| } |
| task cleanLogs(group: cleanupGroup, description: 'Clean all logs in runtime/logs') { |
| doLast { deleteAllInDirWithExclusions("${rootDir}/runtime/logs/", ['README']) } |
| } |
| task cleanOutput(group: cleanupGroup, description: 'Clean runtime/output directory') { |
| doLast { deleteAllInDirWithExclusions("${rootDir}/runtime/output/", ['README']) } |
| } |
| task cleanIndexes(group: cleanupGroup, description: 'Remove search indexes (e.g. Lucene) from runtime/indexes') { |
| doLast { deleteAllInDirWithExclusions("${rootDir}/runtime/indexes/", ['README', 'index.properties']) } |
| } |
| task cleanTempfiles(group: cleanupGroup, description: 'Remove file in runtime/tempfiles') { |
| doLast { |
| deleteAllInDirWithExclusions("${rootDir}/runtime/tempfiles/", ['README']) |
| deleteAllInDirWithExclusions("${rootDir}/runtime/tmp/", ['README']) |
| } |
| } |
| task cleanUploads(group: cleanupGroup, description: 'Remove uploaded files.') { |
| doLast { deleteAllInDirWithExclusions("${rootDir}/runtime/uploads/", []) } |
| } |
| task cleanXtra(group: cleanupGroup, description: 'Clean extra generated files like .rej, .DS_Store, etc.') { |
| doLast { |
| delete fileTree(dir: "${rootDir}", |
| includes: ['**/.nbattrs', '**/*~','**/.#*', '**/.DS_Store', '**/*.rej', '**/*.orig']) |
| } |
| } |
| task cleanFooterFiles(group: cleanupGroup, description: 'clean generated footer files') { |
| doLast { |
| delete gitFooterFile |
| } |
| } |
| /* |
| * Keep this task below all other clean tasks The location of |
| * declaration is important because it means that it will automatically |
| * run whenever the task cleanAll executes (dependency matched by regex) |
| */ |
| def cleanTasks = tasks.findAll { it.name ==~ /^clean.+/ } |
| task cleanAll(group: cleanupGroup, dependsOn: [cleanTasks, clean]) { |
| description 'Execute all cleaning tasks.' |
| } |
| |
| /* ======================================================== |
| * Rules-based OFBiz server commands |
| * ======================================================== */ |
| |
| tasks.addRule('Pattern: ofbiz <Commands>: Execute OFBiz startup commands') { String taskName -> |
| if (taskName ==~ /^ofbiz\s.*/ || taskName == 'ofbiz') { |
| def arguments = (taskName - 'ofbiz').tokenize(' ') |
| createOfbizCommandTask(taskName, arguments) |
| } |
| } |
| |
| tasks.addRule('Pattern: ofbizBackground <Commands>: Execute OFBiz startup commands in background and output to console.log') { String taskName -> |
| if (taskName ==~ /^ofbizBackground\s.*/ || taskName == 'ofbizBackground') { |
| createOfbizBackgroundCommandTask(taskName) |
| } |
| } |
| |
| /* ======================================================== |
| * Helper Functions |
| * ======================================================== */ |
| |
| def createOfbizCommandTask(taskName, arguments) { |
| task(type: JavaExec, dependsOn: classes, taskName) { |
| jvmArgs(application.applicationDefaultJvmArgs) |
| classpath = sourceSets.main.runtimeClasspath |
| mainClass = application.mainClass |
| args arguments |
| if (taskName ==~ /^ofbiz.*(--test|-t).*/) { |
| finalizedBy(createTestReports) |
| } |
| } |
| } |
| |
| def createOfbizBackgroundCommandTask(taskName) { |
| def sourceTask = taskName.tokenize().first() |
| def arguments = (taskName - sourceTask) |
| def serverCommand = "ofbiz ${arguments}".toString() |
| |
| task (taskName) { |
| doLast { |
| spawnProcess([gradlew, '--no-daemon', serverCommand]) |
| } |
| } |
| } |
| |
| def spawnProcess(command) { |
| ProcessBuilder pb = new ProcessBuilder(command) |
| File consoleLog = file("${rootDir}/runtime/logs/console.log") |
| |
| pb.directory(file("${rootDir}")) |
| pb.redirectErrorStream(true) |
| pb.redirectOutput(ProcessBuilder.Redirect.appendTo(consoleLog)) |
| pb.start() |
| } |
| |
| def getDirectoryInActiveComponentsIfExists(String dirName) { |
| activeComponents() |
| .collect { file(it.toString() + '/' + dirName) } |
| .findAll { it.exists() } |
| } |
| |
| def deleteAllInDirWithExclusions(dirName, exclusions) { |
| ant.delete (includeEmptyDirs: 'true', verbose: 'on') { |
| fileset(dir: dirName, includes: '**/*', erroronmissingdir: 'false') { |
| exclusions.each { exclusion -> |
| exclude name: exclusion |
| } |
| } |
| } |
| } |
| |
| def generateFileFromTemplate(templateFileInFullPath, targetDirectory, filterTokens, newFileName) { |
| copy { |
| from (templateFileInFullPath) { |
| filter ReplaceTokens, tokens: filterTokens |
| rename templateFileInFullPath.tokenize('/').last(), newFileName |
| } |
| into targetDirectory |
| } |
| } |
| |
| def getJarClasspath() { |
| def mapper = os.contains('windows') ? { '\\' + "$it" } : { "$it" } |
| configurations.runtimeClasspath.collect(mapper).join(' ') |
| } |
| |
| def subprojectExists(fullyQualifiedProject) { |
| subprojects.stream() |
| .anyMatch { it.path == fullyQualifiedProject.toString() } |
| } |
| |
| def taskExistsInproject(fullyQualifiedProject, taskName) { |
| subprojects.stream() |
| .filter { it.path == fullyQualifiedProject.toString() } |
| .flatMap { it.tasks.stream() } |
| .anyMatch { it.name == taskName } |
| } |
| |
| def gradlewSubprocess(commandList) { |
| exec { commandLine(gradlew, '--no-daemon', *commandList) } |
| } |
| |
| |
| def gradle = project.getGradle() |
| new File("${gradle.getGradleUserHomeDir().getAbsolutePath()}/daemon/${gradle.getGradleVersion()}").listFiles().each { |
| if (it.getName().endsWith('.out.log')) { |
| logger.debug("Cleaning up daemon log file $it") |
| it.delete() |
| } |
| } |
| |
| tasks.startScripts { |
| doLast { |
| // Alter the start script for Unix systems. |
| unixScript.text = |
| unixScript.text.replace('CLASSPATH=$APP_HOME/lib','CLASSPATH=$APP_HOME/config/:$APP_HOME/lib-extra/*:$APP_HOME/lib') |
| // Alter the start script for Windows systems. |
| windowsScript.text = |
| windowsScript.text.replace('CLASSPATH=%APP_HOME%\\lib','CLASSPATH=%APP_HOME%\\conf\\;%APP_HOME%\\lib-extra\\*;%APP_HOME%\\lib') |
| } |
| } |