diff --git a/conf/build.gradle b/conf/build.gradle new file mode 100644 index 0000000..57f9b25 --- /dev/null +++ b/conf/build.gradle @@ -0,0 +1,1200 @@ + +/* + * 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 at.bxm.gradleplugins.svntools.tasks.SvnCheckout +import org.apache.tools.ant.filters.ReplaceTokens +import org.asciidoctor.gradle.AsciidoctorTask + +/* ======================================================== + * Project setup + * ======================================================== */ +buildscript { + repositories { + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath 'at.bxm.gradleplugins:gradle-svntools-plugin:2.2.1' + classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.8.1' // Rather than using 1.5.9.2 see OFBIZ-10693 + classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.16' + } +} +apply plugin: 'java' +apply plugin: 'groovy' +apply plugin: 'eclipse' +apply plugin: 'maven-publish' +apply plugin: "at.bxm.svntools" +apply plugin: 'org.asciidoctor.convert' +apply plugin: 'checkstyle' + +apply from: 'common.gradle' + +// global properties +ext.os = System.getProperty('os.name').toLowerCase() +ext.pluginsDir = "${rootDir}/plugins" + +// java settings +List jvmArguments = ['-Xms128M', '-Xmx1024M'] +if (project.hasProperty('jvmArgs')) { + jvmArguments = jvmArgs.tokenize() +} +ext.ofbizMainClass = 'org.apache.ofbiz.base.start.Start' + +javadoc { + title='OFBiz R18.12 API' + failOnError = true + options { + source '8' + 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/8/docs/api", + "https://docs.oracle.com/javaee/7/api", + "http://docs.groovy-lang.org/docs/groovy-2.4.13/html/api", + "https://commons.apache.org/proper/commons-cli/apidocs" + ) + } +} +// 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 that were present before introducing the + // ‘checkstyle’ tool present in the framework and in the official + // plugins. + // Because of Windows EOL difference with *nix, despite the number + // for maxErrors being more around 39600+ we temporarily put 50000 + // here to avoid issue when releasing. + // Just increasing the number of lines is the problem. + maxErrors = 50000 + // Currently there are a lot of errors so we need to temporarily + // hide them to avoid polluting the terminal output. + showViolations = false +} + +sourceCompatibility = '1.8' +targetCompatibility = '1.8' + +// 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" + } +} + +// defines the footer files for svn and git info +def File gitFooterFile = file("${rootDir}/runtime/GitInfo.ftl") +def File svnFooterFile = file("${rootDir}/runtime/SvnInfo.ftl") + +// root and subproject settings +defaultTasks 'build' + +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 { + // apache-xerces:xercesImpl:2.9.1 + url "https://maven.repository.redhat.com/ga/" + } + maven { + // net.fortuna.ical4j:ical4j:1.0-rc4-atlassian-12 + 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 + url "https://repo1.maven.org/maven2" + metadataSources { + artifact() + } + } + } +} + +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 + } +} + +dependencies { + // ofbiz compile libs + compile 'apache-xerces:xercesImpl:2.9.1' + compile 'com.google.zxing:core:3.3.3' + compile 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2' + compile 'com.googlecode.ez-vcard:ez-vcard:0.9.10' + compile 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20180219.1' + compile 'com.googlecode.libphonenumber:libphonenumber:8.9.16' + compile 'com.ibm.icu:icu4j:63.1' + compile 'com.lowagie:itext:2.1.7' // Don't update due to license change in newer versions, see OFBIZ-10455 + compile 'com.sun.mail:javax.mail:1.6.2' + compile 'com.rometools:rome:1.16.0' + compile 'com.thoughtworks.xstream:xstream:1.4.11.1' + compile 'commons-cli:commons-cli:1.4' + compile 'commons-net:commons-net:3.6' + compile 'commons-validator:commons-validator:1.6' + compile 'commons-fileupload:commons-fileupload:1.3.3' + compile 'de.odysseus.juel:juel-impl:2.2.7' + compile 'javax.el:javax.el-api:3.0.1-b06' + compile 'javax.servlet:javax.servlet-api:4.0.1' + compile 'javax.servlet.jsp:javax.servlet.jsp-api:2.3.3' + compile 'junit:junit-dep:4.11' + compile 'net.fortuna.ical4j:ical4j:1.0-rc4-atlassian-12' + compile 'org.apache.ant:ant-junit:1.10.5' + compile 'org.apache.axis2:axis2-kernel:1.7.8' + compile 'org.apache.commons:commons-collections4:4.2' + compile 'org.apache.commons:commons-csv:1.6' + compile 'org.apache.commons:commons-dbcp2:2.5.0' + compile 'org.apache.commons:commons-text:1.6' + compile 'org.apache.geronimo.components:geronimo-transaction:3.1.4' + compile 'org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1.1' + compile 'org.apache.httpcomponents:httpclient-cache:4.5.6' + compile 'org.apache.logging.log4j:log4j-api:2.17.1' // the API of log4j 2 + compile 'org.apache.logging.log4j:log4j-web:2.17.1' //??? + compile 'org.apache.poi:poi:3.17' + compile 'org.apache.pdfbox:pdfbox:2.0.24' + compile 'org.apache.shiro:shiro-core:1.4.0' + compile 'org.apache.sshd:sshd-core:1.7.0' + compile 'org.apache.tika:tika-core:1.28' + compile 'org.apache.tika:tika-parsers:1.28' + compile 'org.apache.tomcat:tomcat-catalina-ha:9.0.54' + compile 'org.apache.tomcat:tomcat-catalina:9.0.54' + compile 'org.apache.tomcat:tomcat-jasper:9.0.54' + compile 'org.apache.tomcat:tomcat-tribes:9.0.54' + compile 'org.apache.xmlgraphics:fop:2.3' + compile 'org.apache.xmlrpc:xmlrpc-client:3.1.3' + compile 'org.apache.xmlrpc:xmlrpc-server:3.1.3' + compile 'org.codehaus.groovy:groovy-all:2.4.13' // Remember to change the version number in javadoc.options block + compile 'org.freemarker:freemarker:2.3.31' // Remember to change the version number in FreeMarkerWorker class when upgrading + compile 'org.hamcrest:hamcrest-all:1.3' + compile 'org.owasp.esapi:esapi:2.1.0.1' + compile 'org.springframework:spring-test:5.1.2.RELEASE' + compile 'org.zapodot:jackson-databind-java-optional:2.6.1' + compile 'oro:oro:2.0.8' + compile 'wsdl4j:wsdl4j:1.6.3' + compile 'org.jsoup:jsoup:1.11.3' + compile 'com.auth0:java-jwt:3.8.2' + compile 'org.jdom:jdom:1.1.3' // don't upgrade above 1.1.3, makes a lot of not obvious and useless complications, see last commits of OFBIZ-12092 for more + compile 'net.lingala.zip4j:zip4j:2.6.4' + compile 'org.apache.commons:commons-imaging:1.0-alpha2' // Alpha but OK, "Imaging was working and was used by a number of projects in production even before reaching its initial release as an Apache Commons component." + compile 'batik:batik-svg-dom:1.6-1' + compile 'org.postgresql:postgresql:42.3.3' + + + // ofbiz unit-test compile libs + testCompile 'org.mockito:mockito-core:2.23.0' + + // ofbiz runtime libs + runtime 'javax.xml.soap:javax.xml.soap-api:1.4.0' + runtime 'de.odysseus.juel:juel-spi:2.2.7' + runtime 'net.sf.barcode4j:barcode4j-fop-ext:2.1' + runtime 'net.sf.barcode4j:barcode4j:2.1' + runtime 'org.apache.axis2:axis2-transport-http:1.7.8' + runtime 'org.apache.axis2:axis2-transport-local:1.7.8' + runtime 'org.apache.derby:derby:10.14.2.0' + runtime 'org.apache.geronimo.specs:geronimo-jaxrpc_1.1_spec:1.1' + runtime 'org.apache.logging.log4j:log4j-1.2-api:2.17.1' // for external jars using the old log4j1.2: routes logging to log4j 2 + runtime 'org.apache.logging.log4j:log4j-core:2.17.1' // the implementation of the log4j 2 API + runtime 'org.apache.logging.log4j:log4j-jul:2.17.1' // for external jars using the java.util.logging: routes logging to log4j 2 + runtime 'org.apache.logging.log4j:log4j-slf4j-impl:2.17.1' // for external jars using slf4j: routes logging to log4j 2 + runtime 'org.apache.logging.log4j:log4j-jcl:2.17.1' // need to constrain to version to avoid classpath conflict (ReflectionUtil) + runtime 'org.codeartisans.thirdparties.swing:batik-all:1.8pre-r1084380' + + // plugin libs + subprojects.each { subProject -> + compile project(path: subProject.path, configuration: 'pluginLibsCompile') + runtime project(path: subProject.path, configuration: 'pluginLibsRuntime') + compileOnly project(path: subProject.path, configuration: 'pluginLibsCompileOnly') + } + + // libs needed for junitreport + junitReport 'junit:junit:4.12' + junitReport 'org.apache.ant:ant-junit:1.10.5' + + // bug workaround - see OFBIZ-9873 + asciidoctor 'org.jruby:jruby-complete:9.2.4.0' + + // local libs + getDirectoryInActiveComponentsIfExists('lib').each { libDir -> + compile fileTree(dir: libDir, include: '**/*.jar') + } + compile fileTree(dir: file("${rootDir}/lib"), 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' +] + +// Files and directories present in config directories that should not be included in ofbiz.jar (see OFBIZ-8321). +def excludedConfigFiles = [ + 'README', + 'APACHE2_HEADER_FOR_XML', + '*.txt', + '*.jks', + 'fop.xconf', + 'MiniLang.xslt', + 'AutoImportTemplate.ftl', + 'axis2', + 'barcode' +] + +sourceSets { + main { + java { + srcDirs = getDirectoryInActiveComponentsIfExists('src/main/java') + exclude excludedJavaSources + } + groovy { + srcDirs = getDirectoryInActiveComponentsIfExists('src/main/groovy') + } + resources { + srcDirs = getDirectoryInActiveComponentsIfExists('src/main/java') + srcDirs += getDirectoryInActiveComponentsIfExists('config') + srcDirs += getDirectoryInActiveComponentsIfExists('dtd') + exclude excludedJavaSources + exclude excludedConfigFiles + // Below are necessary for unit tests run by Gradle and integration tests + exclude { FileTreeElement elem -> elem.getName().contains('Labels.xml') } + exclude { FileTreeElement elem -> elem.getName().contains('.properties') && + !elem.getName().contains('start.properties') && + !elem.getName().contains('load-data.properties') && + !elem.getName().contains('debug.properties') && + !elem.getName().contains('cache.properties') && + !elem.getName().contains('test.properties') && + !elem.getName().contains('rmi.properties') + } + } + } + + test { + java { + srcDirs = getDirectoryInActiveComponentsIfExists('src/test/java') + } + groovy { + srcDirs = getDirectoryInActiveComponentsIfExists('src/test/groovy') + } + resources { + srcDirs = getDirectoryInActiveComponentsIfExists('src/test/java') + } + } +} + +jar { + manifest { + attributes( + "Implementation-Title": project.name, + "Main-Class": ofbizMainClass, + "Class-Path": getJarManifestClasspathForCurrentOs() + ) + } +} + +// 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") + + iterateOverActiveComponents { 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 ==~ 'framework/base/config' || entry.path ==~ 'framework/base/dtd') && ( + entry.path ==~ '.*/+(' + componentName.tokenize(fileSep).last() + ')$' || + entry.path ==~ /(\/+framework)$/ || + entry.path ==~ /(\/+applications)$/ || + entry.path ==~ /(\/+plugins)$/ || + entry.path ==~ /(\/+themes)$/ || + entry.path ==~ eclipseEntry + '/config' || + entry.path ==~ eclipseEntry + '/dtd') + } + } +} +tasks.eclipse.dependsOn(cleanEclipse) + +/* 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 + */ +buildscript { + if (project.hasProperty('enableOwasp')) { + dependencies { + classpath 'org.owasp:dependency-check-gradle:3.0.2' + } + } +} +if (project.hasProperty('enableOwasp')) { + apply plugin: 'org.owasp.dependencycheck' +} + +/* ======================================================== + * 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'], + jvmArguments, false) + 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', [], jvmArguments, false) + + if (project.hasProperty('tenantId')) { + executeLoadTenant.args '--load-data' + executeLoadTenant.args "delegator=default#${tenantId}" + } + if (project.hasProperty('tenantReaders')) { + executeLoadTenant.args '--load-data' + executeLoadTenant.args "readers=${tenantReaders}" + } + if (project.hasProperty('tenantComponent')) { + executeLoadTenant.args '--load-data' + executeLoadTenant.args "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'], + jvmArguments, false) + loadTenantOnMasterTenantDb.dependsOn(generateDatabaseTemplateFile, generateAdminUserTemplateFile) + + // Load the actual tenant data + createOfbizCommandTask('loadTenantData', [], jvmArguments, false) + loadTenantData.dependsOn(loadTenantOnMasterTenantDb) + + // Load the tenant admin user account + createOfbizCommandTask('loadTenantAdminUserLogin', [], jvmArguments, false) + 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' + loadTenantData.args "delegator=default#${tenantId}" + + loadTenantAdminUserLogin.args '--load-data' + loadTenantAdminUserLogin.args "delegator=default#${tenantId}" + loadTenantAdminUserLogin.args '--load-data' + loadTenantAdminUserLogin.args "file=${rootDir}/runtime/tmp/tmpFilteredUserLogin.xml" + } + if (project.hasProperty('tenantReaders')) { + loadTenantData.args '--load-data' + loadTenantData.args "readers=${tenantReaders}" + } + + dependsOn(loadTenantAdminUserLogin) + + // cleanup + doLast { + delete("${rootDir}/runtime/tmp/tmpFilteredTenantData.xml") + delete("${rootDir}/runtime/tmp/tmpFilteredUserLogin.xml") + } +} + +// ========== Documentation tasks ========== +tasks.withType(AsciidoctorTask) { task -> + backends 'html5', 'pdf' + attributes \ + 'doctype': 'book', + 'experimental': '', + 'icons': 'font', + 'sectnums': '', + 'chapter-label': '', + 'toc': 'left@', + 'toclevels': '3' +} + +task deleteOfbizDocumentation { + doFirst { delete "${buildDir}/asciidoc/ofbiz" } +} + +task deletePluginDocumentation { + def activeComponents = [] + iterateOverActiveComponents { component -> + activeComponents.add(component.name) + } + doFirst { + if (!project.hasProperty('pluginId')) { + throw new GradleException('Missing property \"pluginId\"') + } + if(!activeComponents.contains(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}" + sources { + include 'README.adoc', 'CHANGELOG.adoc', 'CONTRIBUTING.adoc' + } + outputDir file("${buildDir}/asciidoc/readme/") +} + +task generateOfbizDocumentation(group: docsGroup, type: AsciidoctorTask) { + dependsOn deleteOfbizDocumentation + description 'Generate OFBiz documentation manuals' + sourceDir "${rootDir}/docs/asciidoc" + outputDir file("${buildDir}/asciidoc/ofbiz") +} + +task generatePluginDocumentation(group: docsGroup) { + dependsOn deletePluginDocumentation + description 'Generate plugin documentation. Expects pluginId flag' + iterateOverActiveComponents { component -> + if (project.hasProperty('pluginId') && component.name == pluginId) { + 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 -> + iterateOverActiveComponents { 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 = new 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()}" + } +} + +task svnInfoFooter(group: sysadminGroup, description: 'Update the Subversion revision info in the footer if Subversion is used') { + doLast { + def timestamp = new Date().format 'yyyy-MM-dd HH:mm:ss' + def svnOutput = new ByteArrayOutputStream() + def svnFolder = new File('.svn') + + if (!svnFolder.exists()) { + println ("Subversion is not used") + return + } + + exec{ + commandLine 'svn', 'info', '--xml' + standardOutput = svnOutput + } + def info = new XmlParser().parseText(svnOutput.toString()) + svnFooterFile.delete() + svnFooterFile.createNewFile() + svnFooterFile << System.lineSeparator() + svnFooterFile << '${uiLabelMap.CommonBranch} : ' + "${info.entry.url.text()}" + System.lineSeparator() + svnFooterFile << '${uiLabelMap.CommonRevision} : ' + "${info.entry.commit.@revision}" + System.lineSeparator() + svnFooterFile << '${uiLabelMap.CommonBuiltOn} : ' + "${timestamp}" + System.lineSeparator() + svnFooterFile << '${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', 'data/helpdata', 'dtd', 'documents', 'entitydef', 'lib', 'patches/test', 'patches/qa', + 'patches/production', 'groovyScripts', '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.xml', newName:"HELP_${pluginResourceName}.xml", location:'data/helpdata'], + [tempName:'document.xml', newName:"${pluginResourceName}.xml", location:'documents'], + [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:'error.jsp', newName:'error.jsp', location:"webapp/${webappName}/error"], + [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')) { + iterateOverActiveComponents { component -> + if (component.name == pluginId) { + if (subprojectExists(":plugins:${pluginId}")) { + 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}"]) + } + } +} + +task pullPluginSource(group: ofbizPlugin, description: 'Download and install a plugin from source control') { + + if (project.hasProperty('pluginId')) { + task pullPluginFromSvn(type: SvnCheckout) { + svnUrl = "https://github.com/apache/ofbiz-plugins/branches/release18.12/${pluginId}" + workspaceDir = "${pluginsDir}/${pluginId}" + } + dependsOn pullPluginFromSvn + } + doLast { + gradlewSubprocess(['installPlugin', "-PpluginId=${pluginId}"]) + } +} + +task pullAllPluginsSource(group: ofbizPlugin, + description: 'Download and install all plugins from source control. Warning! deletes existing plugins') { + + task deleteBeforePulling { + doLast { delete "${pluginsDir}" } + } + task pullPluginsFromSvn(type: SvnCheckout, dependsOn: deleteBeforePulling) { + svnUrl = "https://github.com/apache/ofbiz-plugins/branches/release18.12" + workspaceDir = "${pluginsDir}" + } + dependsOn pullPluginsFromSvn + + task installAllPlugins { + file("${pluginsDir}").eachDir { plugin -> + iterateOverActiveComponents { component -> + if (component.name == plugin.name) { + if (subprojectExists(":plugins:${plugin.name}")) { + if (taskExistsInproject(":plugins:${plugin.name}", 'install')) { + dependsOn ":plugins:${plugin.name}:install" + doLast { println "installed plugin ${plugin.name}" } + } + } + } + } + } + } + doLast { + gradlewSubprocess(['installAllPlugins']) + } +} + +// ========== 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 + delete svnFooterFile + } +} +/* + * 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 : Execute OFBiz startup commands') { String taskName -> + if (taskName ==~ /^ofbiz\s.*/ || taskName == 'ofbiz') { + def arguments = (taskName - 'ofbiz').tokenize(' ') + createOfbizCommandTask(taskName, arguments, jvmArguments, false) + } +} + +tasks.addRule('Pattern: ofbizDebug : Execute OFBiz startup commands in remote debug mode') { String taskName -> + if (taskName ==~ /^ofbizDebug\s.*/ || taskName == 'ofbizDebug') { + def arguments = (taskName - 'ofbizDebug').tokenize(' ') + createOfbizCommandTask(taskName, arguments, jvmArguments, true) + } +} + +tasks.addRule('Pattern: ofbizBackground : 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, jvmArguments, isDebugMode) { + + def ofbizJarName = buildDir.toString()+'/libs/'+project.name+'.jar' + + task(type: JavaExec, dependsOn: build, taskName) { + jvmArgs(jvmArguments) + debug = isDebugMode + classpath = files(ofbizJarName) + main = ofbizMainClass + arguments.each { argument -> + args argument + } + + if (taskName ==~ /^ofbiz.*--test.*/ + || taskName ==~ /^ofbiz.*-t.*/) { + finalizedBy(createTestReports) + } + } +} + +def createOfbizBackgroundCommandTask(taskName) { + def sourceTask = taskName.tokenize().first() + def arguments = (taskName - sourceTask) + def serverCommand = "ofbiz ${arguments}".toString() + def gradleRunner = os.contains('windows') ? 'gradlew.bat' : './gradlew' + + task (taskName) { + doLast { + spawnProcess([gradleRunner, "--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) { + def dirInComponents = [] + iterateOverActiveComponents { component -> + def subDir = file(component.toString() + '/' + dirName) + if (subDir.exists()) { + dirInComponents.add subDir + } + } + return dirInComponents +} + +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 getJarManifestClasspathForCurrentOs() { + def osClassPath = '' + if (os.contains('windows')) { + configurations.runtime.files.each { cpEntry -> + osClassPath += '\\' + cpEntry.toString() + ' ' + } + } else { + osClassPath = configurations.runtime.files.collect { "$it" }.join(' ') + } + return osClassPath +} + + +def subprojectExists(fullyQualifiedProject) { + subprojects.stream() + .filter { it.path == fullyQualifiedProject.toString() } + .findAny() + .isPresent() +} + +def taskExistsInproject(fullyQualifiedProject, taskName) { + subprojects.stream() + .filter { it.path == fullyQualifiedProject.toString() } + .flatMap { it.tasks.stream() } + .anyMatch { it.name == taskName } +} + +def gradlewSubprocess(commandList) { + def gradlew = os.contains('windows') ? 'gradlew.bat' : './gradlew' + 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() + } +} diff --git a/conf/nginx.conf b/conf/nginx.conf index 692a7f4..97b740c 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,13 +1,20 @@ -#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; -location __PATH__/ { - proxy_pass http://127.0.0.1:8444; +location @ofbiz { + proxy_pass https://127.0.0.1:__PORT__; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for; - #proxy_redirect off; - #client_max_body_size 100M; - #proxy_set_header X-Real-IP $remote_addr; - #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - #proxy_set_header Host $http_host; - #proxy_set_header X-NginX-Proxy true; } + +location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { + root /opt/ofbiz/framework/images/webapp/images; + try_files $uri $uri/ @ofbiz; + expires 3d; +} + +location / { + root /opt/ofbiz/framework/images/webapp/images; + try_files $uri $uri/ @ofbiz; + + # Include SSOWAT user panel. + include conf.d/yunohost_panel.conf.inc; +} \ No newline at end of file diff --git a/conf/systemd.service b/conf/systemd.service index 412bbfd..9195630 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -1,5 +1,5 @@ [Unit] -Description=Small description of the service +Description=OFBiz Service After=network.target [Service] diff --git a/doc/DESCRIPTION.md b/doc/DESCRIPTION.md index 0685205..e69de29 100644 --- a/doc/DESCRIPTION.md +++ b/doc/DESCRIPTION.md @@ -1,9 +0,0 @@ -Some long and extensive description of what the app is and does, lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. - -### Features - -- Ut enim ad minim veniam, quis nostrud exercitation ullamco ; -- Laboris nisi ut aliquip ex ea commodo consequat ; -- Duis aute irure dolor in reprehenderit in voluptate ; -- Velit esse cillum dolore eu fugiat nulla pariatur ; -- Excepteur sint occaecat cupidatat non proident, sunt in culpa." diff --git a/doc/DISCLAIMER.md b/doc/DISCLAIMER.md index aded581..a613c85 100644 --- a/doc/DISCLAIMER.md +++ b/doc/DISCLAIMER.md @@ -1,12 +1 @@ -* Any known limitations, constrains or stuff not working, such as (but not limited to): - * requiring a full dedicated domain ? - * architectures not supported ? - * not-working single-sign on or LDAP integration ? - * the app requires an important amount of RAM / disk / .. to install or to work properly - * etc... - -* Other infos that people should be aware of, such as: - * any specific step to perform after installing (such as manually finishing the install, specific admin credentials, ...) - * how to configure / administrate the application if it ain't obvious - * upgrade process / specificities / things to be aware of ? - * security considerations ? +The default administrative account is username: "admin", password: "ofbiz". \ No newline at end of file diff --git a/scripts/_common.sh b/scripts/_common.sh index e786c25..8fc2053 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -5,7 +5,7 @@ #================================================= # dependencies used by the app -pkg_dependencies="openjdk-11-jdk" +pkg_dependencies="openjdk-11-jdk postgresql" #================================================= # PERSONAL HELPERS diff --git a/scripts/backup b/scripts/backup index 45e12cc..95dbd9b 100755 --- a/scripts/backup +++ b/scripts/backup @@ -1,15 +1,70 @@ #!/bin/bash -app=ynhexample -# The parameter $1 is the backup directory location -# which will be compressed afterward -backup_dir=$1/apps/$app -mkdir -p $backup_dir +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Backup sources & data -sudo cp -a /var/www/$app/. $backup_dir/sources +# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers -# Copy Nginx and YunoHost parameters to make the script "standalone" -sudo cp -a /etc/yunohost/apps/$app/. $backup_dir/yunohost -domain=$(sudo yunohost app setting $app domain) -sudo cp -a /etc/nginx/conf.d/$domain.d/$app.conf $backup_dir/nginx.conf \ No newline at end of file +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + true +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info --message="Loading installation settings..." + +app=$YNH_APP_INSTANCE_NAME + +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) + +#================================================= +# DECLARE DATA AND CONF FILES TO BACKUP +#================================================= +ynh_print_info --message="Declaring files to be backed up..." + +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= + +ynh_backup --src_path="$final_path" + +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= + +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# SPECIFIC BACKUP +#================================================= +# BACKUP SYSTEMD +#================================================= + +ynh_backup --src_path="/etc/systemd/system/$app.service" + +#================================================= +# BACKUP THE POSTGRESQL DATABASE +#================================================= +ynh_print_info --message="Backing up the PostgreSQL database..." + +ynh_psql_dump_db --database="$db_name" > db.sql + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." diff --git a/scripts/change_url b/scripts/change_url index 495b7eb..00848ce 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -24,11 +24,12 @@ app=$YNH_APP_INSTANCE_NAME #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --time --weight=1 +ynh_script_progression --message="Loading installation settings..." # Needed for helper "ynh_add_nginx_config" final_path=$(ynh_app_setting_get --app=$app --key=final_path) +port=$(ynh_app_setting_get --app=$app --key=port) # Add settings here as needed by your application #db_name=$(ynh_app_setting_get --app=$app --key=db_name) #db_user=$db_name @@ -37,11 +38,12 @@ final_path=$(ynh_app_setting_get --app=$app --key=final_path) #================================================= # BACKUP BEFORE CHANGE URL THEN ACTIVE TRAP #================================================= -ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." --time --weight=1 +ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." # Backup the current version of the app ynh_backup_before_upgrade ynh_clean_setup () { + ynh_clean_check_starting # Remove the new domain config file, the remove script won't do it as it doesn't know yet its location. ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" @@ -72,14 +74,14 @@ fi #================================================= # STOP SYSTEMD SERVICE #================================================= -ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 +ynh_script_progression --message="Stopping a systemd service..." ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" #================================================= # MODIFY URL IN NGINX CONF #================================================= -ynh_script_progression --message="Updating NGINX web server configuration..." --time --weight=1 +ynh_script_progression --message="Updating NGINX web server configuration..." nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf @@ -116,14 +118,15 @@ fi #================================================= # START SYSTEMD SERVICE #================================================= -ynh_script_progression --message="Starting a systemd service..." --time --weight=1 +ynh_script_progression --message="Starting a systemd service..." +# Start a systemd service ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" #================================================= # RELOAD NGINX #================================================= -ynh_script_progression --message="Reloading NGINX web server..." --time --weight=1 +ynh_script_progression --message="Reloading NGINX web server..." ynh_systemd_action --service_name=nginx --action=reload @@ -131,4 +134,4 @@ ynh_systemd_action --service_name=nginx --action=reload # END OF SCRIPT #================================================= -ynh_script_progression --message="Change of URL completed for $app" --time --last +ynh_script_progression --message="Change of URL completed for $app" diff --git a/scripts/install b/scripts/install index e96a8e0..f0cfb01 100755 --- a/scripts/install +++ b/scripts/install @@ -49,6 +49,17 @@ ynh_app_setting_set --app=$app --key=domain --value=$domain ynh_app_setting_set --app=$app --key=path --value=$path_url ynh_app_setting_set --app=$app --key=admin --value=$admin +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# FIND AND OPEN A PORT +#================================================= +ynh_script_progression --message="Finding an available port..." + +# Find an available port +port=$(ynh_find_port --port=8095) +ynh_app_setting_set --app=$app --key=port --value=$port + #================================================= # INSTALL DEPENDENCIES #================================================= @@ -64,6 +75,22 @@ ynh_script_progression --message="Configuring system user..." # Create a system user ynh_system_user_create --username=$app --home_dir="$final_path" +#================================================= +# CREATE A POSTGRESQL DATABASE +#================================================= +ynh_script_progression --message="Creating a PostgreSQL database..." + +db_name=$(ynh_sanitize_dbid --db_name=$app) +db_user=$db_name +db_pwd=$(ynh_string_random --length=30) +ynh_app_setting_set --app=$app --key=db_name --value=$db_name +ynh_app_setting_set --app=$app --key=db_pwd --value=$db_pwd +ynh_psql_test_if_first_run +ynh_psql_create_user "$db_user" "$db_pwd" +ynh_psql_execute_as_root --sql="CREATE DATABASE ${db_name} WITH OWNER ${db_user} TEMPLATE template0 ENCODING 'UTF8';" +ynh_psql_execute_as_root --sql="CREATE DATABASE ${db_name}olap WITH OWNER ${db_user} TEMPLATE template0 ENCODING 'UTF8';" +ynh_psql_execute_as_root --sql="CREATE DATABASE ${db_name}tenant WITH OWNER ${db_user} TEMPLATE template0 ENCODING 'UTF8';" + #================================================= # DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= @@ -92,22 +119,34 @@ ynh_add_nginx_config #================================================= ynh_script_progression --message="Building app..." +ynh_replace_string --match_string="port.https=" --replace_string="port.https=443" --target_file="$final_path/framework/webapp/config/url.properties" +ynh_replace_string --match_string="force.https.host=" --replace_string="force.https.host=$domain" --target_file="$final_path/framework/webapp/config/url.properties" +ynh_replace_string --match_string="port.http=8080" --replace_string="port.http=80" --target_file="$final_path/framework/webapp/config/url.properties" +ynh_replace_string --match_string="force.http.host=" --replace_string="force.http.host=$domain" --target_file="$final_path/framework/webapp/config/url.properties" + +ynh_replace_string --match_string="host-headers-allowed=.*" --replace_string="host-headers-allowed=$domain" --target_file="$final_path/framework/security/config/security.properties" + +ynh_replace_string --match_string="8443" --replace_string="$port" --target_file="$final_path/framework/catalina/ofbiz-component.xml" + +ynh_replace_string --match_string="jdbc:postgresql://127.0.0.1/ofbiz" --replace_string="jdbc:postgresql://127.0.0.1:5432/${db_name}" --target_file="$final_path/framework/entity/config/entityengine.xml" +ynh_replace_string --match_string="jdbc:postgresql://127.0.0.1/ofbizolap" --replace_string="jdbc:postgresql://127.0.0.1:5432/${db_name}olap" --target_file="$final_path/framework/entity/config/entityengine.xml" +ynh_replace_string --match_string="jdbc:postgresql://127.0.0.1/ofbiztenant" --replace_string="jdbc:postgresql://127.0.0.1:5432/${db_name}tenant" --target_file="$final_path/framework/entity/config/entityengine.xml" +ynh_replace_string --match_string="jdbc-username=\"ofbiz\"" --replace_string="jdbc-username=\"$db_user\"" --target_file="$final_path/framework/entity/config/entityengine.xml" +ynh_replace_string --match_string="jdbc-password=\"ofbiz\"" --replace_string="jdbc-password=\"$db_pwd\"" --target_file="$final_path/framework/entity/config/entityengine.xml" +ynh_replace_string --match_string="group-map group-name=\"org.apache.ofbiz\" datasource-name=\"localderby\"" --replace_string="group-map group-name=\"org.apache.ofbiz\" datasource-name=\"localpostgres\"" --target_file="$final_path/framework/entity/config/entityengine.xml" +ynh_replace_string --match_string="group-map group-name=\"org.apache.ofbiz.olap\" datasource-name=\"localderbyolap\"" --replace_string="group-map group-name=\"org.apache.ofbiz.olap\" datasource-name=\"localpostgresolap\"" --target_file="$final_path/framework/entity/config/entityengine.xml" +ynh_replace_string --match_string="group-map group-name=\"org.apache.ofbiz.tenant\" datasource-name=\"localderbytenant\"" --replace_string="group-map group-name=\"org.apache.ofbiz.tenant\" datasource-name=\"localpostgrestenant\"" --target_file="$final_path/framework/entity/config/entityengine.xml" + +ynh_replace_string --match_string="security.ldap.enable=false" --replace_string="security.ldap.enable=true" --target_file="$final_path/framework/security/config/security.properties" +ynh_replace_string --match_string="ldap.dn.template=cn=%u,ou=system" --replace_string="ldap.dn.template=uid=%u,ou=users,dc=yunohost,dc=org" --target_file="$final_path/framework/security/config/jndiLdap.properties" + +cp -f ../conf/build.gradle "$final_path/build.gradle" + pushd "$final_path" - ./gradle/init-gradle-wrapper.sh - ./gradlew cleanAll "ofbiz --load-data readers=seed,seed-initial" loadAdminUserLogin -PuserLoginId=admin 2>&1 + ynh_exec_as $app ./gradle/init-gradle-wrapper.sh + ynh_exec_as $app ./gradlew cleanAll "ofbiz --load-data readers=seed,seed-initial" loadAdminUserLogin -PuserLoginId=admin 2>&1 popd - -port.https= port.https=443 -force.https.host= force.https.host=test31.yh.yalh.net -port.http=8080 port.http=80 -force.http.host= force.http.host=test31.yh.yalh.net - -$final_path/framework/webapp/config/url.properties - -host-headers-allowed=.* host-headers-allowed=test31.yh.yalh.net -framework/security/config/security.properties - #================================================= # SETUP SYSTEMD #================================================= @@ -130,8 +169,11 @@ yunohost service add $app --log="/var/log/$app/$app.log" #================================================= ynh_script_progression --message="Starting a systemd service..." +mkdir -p /var/log/$app +chown -R $app:$app "/var/log/$app" + # Start a systemd service -ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" --line_match="is started and ready" #================================================= # SETUP SSOWAT diff --git a/scripts/remove b/scripts/remove index 2389d44..186c404 100755 --- a/scripts/remove +++ b/scripts/remove @@ -17,6 +17,8 @@ ynh_script_progression --message="Loading installation settings..." app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get --app=$app --key=domain) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name final_path=$(ynh_app_setting_get --app=$app --key=final_path) #================================================= @@ -32,6 +34,13 @@ then yunohost service remove $app fi +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." + +ynh_systemd_action --service_name=$app --action="stop" --log_path="systemd" --line_match="Stopped OFBiz Service" + #================================================= # STOP AND REMOVE SERVICE #================================================= @@ -40,6 +49,16 @@ ynh_script_progression --message="Stopping and removing the systemd service..." # Remove the dedicated systemd config ynh_remove_systemd_config +#================================================= +# REMOVE THE POSTGRESQL DATABASE +#================================================= +ynh_script_progression --message="Removing the PostgreSQL database..." + +# Remove a database if it exists, along with the associated user +ynh_psql_drop_db ${db_name}tenant +ynh_psql_drop_db ${db_name}olap +ynh_psql_remove_db --db_user=$db_user --db_name=$db_name + #================================================= # REMOVE APP MAIN DIR #================================================= @@ -64,6 +83,16 @@ ynh_script_progression --message="Removing dependencies..." # Remove metapackage and its dependencies ynh_remove_app_dependencies +#================================================= +# SPECIFIC REMOVE +#================================================= +# REMOVE VARIOUS FILES +#================================================= +ynh_script_progression --message="Removing various files..." + +# Remove the log files +ynh_secure_remove --file="/var/log/$app" + #================================================= # GENERIC FINALIZATION #================================================= diff --git a/scripts/restore b/scripts/restore index 917b5e5..4cecddc 100755 --- a/scripts/restore +++ b/scripts/restore @@ -1,16 +1,135 @@ #!/bin/bash -app=ynhexample -# The parameter $1 is the uncompressed restore directory location -backup_dir=$1/apps/$app +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Restore sources & data -sudo cp -a $backup_dir/sources/. /var/www/$app +# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers -# Restore Nginx and YunoHost parameters -sudo cp -a $backup_dir/yunohost/. /etc/yunohost/apps/$app -domain=$(sudo yunohost app setting $app domain) -sudo cp -a $backup_dir/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= -# Restart webserver -sudo service nginx reload \ No newline at end of file +ynh_clean_setup () { + ynh_clean_check_starting +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." + +app=$YNH_APP_INSTANCE_NAME + +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) +port=$(ynh_app_setting_get --app=$app --key=port) + +#================================================= +# CHECK IF THE APP CAN BE RESTORED +#================================================= +ynh_script_progression --message="Validating restoration parameters..." + +test ! -d $final_path \ + || ynh_die --message="There is already a directory: $final_path " + +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Restoring the NGINX web server configuration..." + +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# RECREATE THE DEDICATED USER +#================================================= +ynh_script_progression --message="Recreating the dedicated system user..." + +# Create the dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir=$final_path + +yunohost user create ${app}_notifs --firstname "Mobilizon" --lastname "Notifications" --domain "$domain" --password "$ynh_user_password" -q 0 +yunohost user update ${app}_notifs --add-mailalias $app@$domain --add-mailforward $admin_email + +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= +ynh_script_progression --message="Restoring the app main directory..." + +ynh_restore_file --origin_path="$final_path" + +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" + +#================================================= +# SPECIFIC RESTORATION +#================================================= +# REINSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Reinstalling dependencies..." + +# Define and install dependencies +ynh_exec_warn_less ynh_install_app_dependencies $pkg_dependencies + +#================================================= +# RESTORE THE POSTGRESQL DATABASE +#================================================= +ynh_script_progression --message="Restoring the PostgreSQL database..." + +ynh_psql_test_if_first_run +ynh_psql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd +ynh_psql_execute_file_as_root --file="./db.sql" --database=$db_name + +#================================================= +# RESTORE SYSTEMD +#================================================= +ynh_script_progression --message="Restoring the systemd configuration..." + +ynh_restore_file --origin_path="/etc/systemd/system/$app.service" +systemctl enable $app.service --quiet + +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." + +yunohost service add $app --log="/var/log/$app/$app.log" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." + +mkdir -p /var/log/$app +chown -R $app:$app "/var/log/$app" + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" --line_match="is started and ready" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Restoration completed for $app" diff --git a/scripts/upgrade b/scripts/upgrade index f3a5ac5..13c40b2 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,32 +1,174 @@ #!/bin/bash -app=ynhexample -# Retrieve arguments -domain=$(sudo yunohost app setting $app domain) -path=$(sudo yunohost app setting $app path) -admin=$(sudo yunohost app setting $app admin) -is_public=$(sudo yunohost app setting $app is_public) +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Remove trailing "/" for next commands -path=${path%/} +source _common.sh +source ynh_package_version +source /usr/share/yunohost/helpers -# Copy source files -final_path=/var/www/$app -sudo mkdir -p $final_path -sudo cp -a ../sources/* $final_path +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." -# Modify Nginx configuration file and copy it to Nginx conf directory -sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf -sed -i "s@YNH_WWW_ALIAS@$final_path/@g" ../conf/nginx.conf -sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf +app=$YNH_APP_INSTANCE_NAME -# If app is public, add url to SSOWat conf as skipped_uris -if [ "$is_public" = "Yes" ]; +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +admin=$(ynh_app_setting_get --app=$app --key=admin) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) +port=$(ynh_app_setting_get --app=$app --key=port) + +#================================================= +# CHECK VERSION +#================================================= +ynh_script_progression --message="Checking version..." + +upgrade_type=$(ynh_check_app_version_changed) + +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." + +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + ynh_clean_check_starting + # Restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# STANDARD UPGRADE STEPS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." + +ynh_systemd_action --service_name=$app --action="stop" --log_path="systemd" --line_match="Stopped OFBiz Service" + +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= +ynh_script_progression --message="Ensuring downward compatibility..." + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Making sure dedicated system user exists..." + +# Create a dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir=$final_path + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +if [ "$upgrade_type" == "UPGRADE_APP" ] then - sudo yunohost app setting $app skipped_uris -v "/" + ynh_script_progression --message="Upgrading source files..." + + # Download, check integrity, uncompress and patch the source from app.src + ynh_setup_source --dest_dir="$final_path" fi -# Restart services -sudo service nginx reload -sudo yunohost app ssowatconf +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Upgrading NGINX web server configuration..." + +# Create a dedicated NGINX config +ynh_add_nginx_config + +#================================================= +# UPGRADE DEPENDENCIES +#================================================= +ynh_script_progression --message="Upgrading dependencies..." + +ynh_exec_warn_less ynh_install_app_dependencies $pkg_dependencies + +#================================================= +# SPECIFIC UPGRADE +#================================================= +# BUILD APP +#================================================= + +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Building app..." + + ynh_replace_string --match_string="port.https=" --replace_string="port.https=443" --target_file="$final_path/framework/webapp/config/url.properties" + ynh_replace_string --match_string="force.https.host=" --replace_string="force.https.host=$domain" --target_file="$final_path/framework/webapp/config/url.properties" + ynh_replace_string --match_string="port.http=8080" --replace_string="port.http=80" --target_file="$final_path/framework/webapp/config/url.properties" + ynh_replace_string --match_string="force.http.host=" --replace_string="force.http.host=$domain" --target_file="$final_path/framework/webapp/config/url.properties" + + ynh_replace_string --match_string="host-headers-allowed=.*" --replace_string="host-headers-allowed=$domain" --target_file="$final_path/framework/security/config/security.properties" + + ynh_replace_string --match_string="8443" --replace_string="$port" --target_file="$final_path/framework/catalina/ofbiz-component.xml" + + ynh_replace_string --match_string="jdbc:postgresql://127.0.0.1/ofbiz" --replace_string="jdbc:postgresql://127.0.0.1:5432/${db_name}" --target_file="$final_path/framework/entity/config/entityengine.xml" + ynh_replace_string --match_string="jdbc:postgresql://127.0.0.1/ofbizolap" --replace_string="jdbc:postgresql://127.0.0.1:5432/${db_name}olap" --target_file="$final_path/framework/entity/config/entityengine.xml" + ynh_replace_string --match_string="jdbc:postgresql://127.0.0.1/ofbiztenant" --replace_string="jdbc:postgresql://127.0.0.1:5432/${db_name}tenant" --target_file="$final_path/framework/entity/config/entityengine.xml" + ynh_replace_string --match_string="jdbc-username=\"ofbiz\"" --replace_string="jdbc-username=\"$db_user\"" --target_file="$final_path/framework/entity/config/entityengine.xml" + ynh_replace_string --match_string="jdbc-password=\"ofbiz\"" --replace_string="jdbc-password=\"$db_pwd\"" --target_file="$final_path/framework/entity/config/entityengine.xml" + ynh_replace_string --match_string="group-map group-name=\"org.apache.ofbiz\" datasource-name=\"localderby\"" --replace_string="group-map group-name=\"org.apache.ofbiz\" datasource-name=\"localpostgres\"" --target_file="$final_path/framework/entity/config/entityengine.xml" + ynh_replace_string --match_string="group-map group-name=\"org.apache.ofbiz.olap\" datasource-name=\"localderbyolap\"" --replace_string="group-map group-name=\"org.apache.ofbiz.olap\" datasource-name=\"localpostgresolap\"" --target_file="$final_path/framework/entity/config/entityengine.xml" + ynh_replace_string --match_string="group-map group-name=\"org.apache.ofbiz.tenant\" datasource-name=\"localderbytenant\"" --replace_string="group-map group-name=\"org.apache.ofbiz.tenant\" datasource-name=\"localpostgrestenant\"" --target_file="$final_path/framework/entity/config/entityengine.xml" + + cp -f ../conf/build.gradle "$final_path/build.gradle" +fi + +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_script_progression --message="Upgrading systemd configuration..." + +# Create a dedicated systemd config +ynh_add_systemd_config + +#================================================= +# GENERIC FINALIZATION +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." + +yunohost service add $app --log="/var/log/$app/$app.log" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." + +mkdir -p /var/log/$app +chown -R $app:$app "/var/log/$app" + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" --line_match="is started and ready" + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Upgrade of $app completed"