![JAR search and dependency download from the Maven repository](/logo.png)
org.akhikhl.gretty.ProductConfigurer.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gretty Show documentation
Show all versions of gretty Show documentation
Advanced gradle plugin for running web-apps on jetty and tomcat
/*
/*
* Gretty
*
* Copyright (C) 2013-2015 Andrey Hihlovskiy and contributors.
*
* See the file "LICENSE" for copying and usage permission.
* See the file "CONTRIBUTORS" for complete list of contributors.
*/
package org.akhikhl.gretty
import groovy.json.JsonBuilder
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.bundling.Zip
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
*
* @author akhikhl
*/
class ProductConfigurer {
protected static final Logger log = LoggerFactory.getLogger(ProductConfigurer)
protected static final String mainClass = 'org.akhikhl.gretty.GrettyStarter'
protected final Project project
protected final File baseOutputDir
protected final String productName
protected final ProductExtension product
protected final File outputDir
protected ServerConfig sconfig
protected List wconfigs
protected jsonConfig
protected String logbackConfig
protected Map launchScripts = [:]
ProductConfigurer(Project project, File baseOutputDir, String productName, ProductExtension product) {
this.project = project
this.baseOutputDir = baseOutputDir
this.productName = productName
this.product = product
outputDir = new File(baseOutputDir, productName ?: project.name)
}
void configureProduct() {
def buildProductTask = project.task("buildProduct${productName}", group: 'gretty') { task ->
description = "Builds gretty product${ productName ? ' ' + productName : '' }."
dependsOn {
resolveConfig()
wconfigs.collectMany { wconfig ->
def result = []
if(wconfig.projectPath) {
def proj = project.project(wconfig.projectPath)
result.add(proj.tasks.build)
if(ProjectUtils.isSpringBootApp(proj, wconfig))
result.add(proj.tasks.jar)
}
result
}
}
inputs.property 'config', {
resolveConfig()
jsonConfig.toString()
}
inputs.property 'logbackConfig', {
resolveConfig()
logbackConfig
}
inputs.property 'launchScripts', {
resolveConfig()
launchScripts
}
inputs.property 'textFiles', {
createTextFiles(false)
}
inputs.property 'realms', {
resolveConfig()
[ '#server': sconfig.realm ] + wconfigs.collectEntries({ [ it.contextPath, it.realm ] })
}
inputs.files {
resolveConfig()
def result = []
for(WebAppConfig wconfig in wconfigs) {
// projects are already set as input in dependsOn
if(wconfig.projectPath)
result.addAll project.project(wconfig.projectPath).configurations.runtime.files
else
result.add wconfig.resourceBase
if(wconfig.realmConfigFile)
result.add wconfig.realmConfigFile
if(wconfig.contextConfigFile)
result.add wconfig.contextConfigFile
if(wconfig.extraResourceBases) {
def proj = wconfig.projectPath ? project.project(wconfig.projectPath) : project
for(def resBase in wconfig.extraResourceBases)
result.addAll proj.fileTree(resBase).files
}
result
}
result
}
inputs.files {
resolveConfig()
def result = []
if(sconfig.realmConfigFile)
result.add sconfig.realmConfigFile
if(sconfig.serverConfigFile)
result.add sconfig.serverConfigFile
if(sconfig.logbackConfigFile)
result.add sconfig.logbackConfigFile
result
}
inputs.files project.configurations.grettyStarter
inputs.files {
resolveConfig()
getRunnerFileCollection()
}
inputs.property 'logback-config-template', { getLogbackConfigTemplate() }
outputs.dir outputDir
ext.outputDir = outputDir
ext.baseOutputDir = baseOutputDir
doLast {
resolveConfig()
writeConfigFiles()
writeLaunchScripts()
writeTextFiles(createTextFiles(true))
copyWebappFiles()
copyStarter()
copyRunner()
}
}
project.tasks.buildAllProducts.dependsOn buildProductTask
def archiveProductTask = project.task("archiveProduct${productName}", group: 'gretty', type: Zip) {
description = "Archives gretty product${ productName ? ' ' + productName : '' }."
dependsOn buildProductTask
baseName = productName ?: project.name
version = project.version
destinationDir = baseOutputDir
from outputDir, { into project.name }
doLast {
ant.checksum file: it.archivePath
}
}
project.tasks.archiveAllProducts.dependsOn archiveProductTask
}
void copyRunner() {
ManagedDirectory dir = new ManagedDirectory(new File(outputDir, 'runner'))
for(File file in getRunnerFileCollection().files)
dir.add(file)
File logbackConfigFile = new File(project.buildDir, 'runner/logback.' + getLogbackConfigExtension())
logbackConfigFile.parentFile.mkdirs()
logbackConfigFile.text = getRunnerLogbackConfig()
dir.add(logbackConfigFile, 'logback-config')
dir.cleanup()
}
void copyStarter() {
ManagedDirectory dir = new ManagedDirectory(new File(outputDir, 'starter'))
for(File file in project.configurations.grettyStarter.files)
dir.add(file)
File logbackConfigFile = new File(project.buildDir, 'starter/logback.groovy')
logbackConfigFile.parentFile.mkdirs()
logbackConfigFile.text = getStarterLogbackConfig()
dir.add(logbackConfigFile, 'logback-config')
dir.cleanup()
}
void copyWebappFiles() {
ManagedDirectory webappsDir = new ManagedDirectory(new File(outputDir, 'webapps'))
for(WebAppConfig wconfig in wconfigs) {
String appDir = ProjectUtils.getWebAppDestinationDirName(project, wconfig)
if(ProjectUtils.isSpringBootApp(project, wconfig)) {
def files
if(wconfig.projectPath) {
def proj = project.project(wconfig.projectPath)
for(File webappDir in ProjectUtils.getWebAppDirs(proj))
for(File f in (webappDir.listFiles() ?: []))
webappsDir.add(f, appDir)
def resolvedClassPath = new LinkedHashSet()
resolvedClassPath.addAll(ProjectUtils.getClassPathJars(proj, 'productRuntime'))
resolvedClassPath.addAll(ProjectUtils.resolveClassPath(proj, wconfig.classPath))
files = resolvedClassPath.collect { new File(it.path) }
files -= getVisibleRunnerFileCollection().files
} else {
def file = wconfig.resourceBase
if(!(file instanceof File))
file = new File(file.toString())
files = [ file ]
}
for(File file in files) {
if(file.isDirectory())
for(File f in (file.listFiles() ?: []))
webappsDir.add(f, appDir + '/WEB-INF/classes')
else
webappsDir.add(file, appDir + '/WEB-INF/lib')
}
} else {
def file = wconfig.resourceBase
if(!(file instanceof File))
file = new File(file.toString())
webappsDir.add(file)
}
}
webappsDir.cleanup()
if(wconfigs.find { it.extraResourceBases }) {
ManagedDirectory extraResourcesDir = new ManagedDirectory(new File(outputDir, 'extraResources'))
for(WebAppConfig wconfig in wconfigs) {
String appDir = ProjectUtils.getWebAppDestinationDirName(project, wconfig)
for(def resBase in wconfig.extraResourceBases)
extraResourcesDir.add(resBase, appDir)
}
extraResourcesDir.cleanup()
}
}
protected void createLaunchScripts() {
String shellResolveDir = '#!/bin/bash\n' +
'SOURCE="${BASH_SOURCE[0]}"\n' +
'while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink\n' +
'DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"\n' +
'SOURCE="$(readlink "$SOURCE")"\n' +
'[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"\n' +
'done\n' +
'DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"\n'
for(String cmd in ['run', 'start', 'stop', 'restart']) {
launchScripts[cmd + '.sh'] = shellResolveDir + 'java -Dfile.encoding=UTF8 -cp \"${DIR}/starter/*:${DIR}/starter/logback-config\" ' + mainClass + ' $@ ' + cmd
launchScripts[cmd + '.bat'] = '@java.exe -Dfile.encoding=UTF8 -cp \"%~dp0\\starter\\*;%~dp0\\starter\\logback-config\" ' + mainClass + ' %* ' + cmd
}
}
protected Map createTextFiles(boolean addTimeStamp) {
String text = """Product: ${productName ?: project.name}
Version: ${project.version}"""
if(addTimeStamp)
text += "\nCreated: ${new Date()}"
['VERSION.txt': text]
}
private String getLogbackConfigExtension() {
if(sconfig.logbackConfigFile) {
def logbackConfigFile = sconfig.logbackConfigFile
if(!(logbackConfigFile instanceof File))
logbackConfigFile = new File(logbackConfigFile.toString())
int extPos = logbackConfigFile.name.lastIndexOf('.')
return logbackConfigFile.name.substring(extPos + 1)
}
'groovy'
}
private String getLogbackConfigTemplate() {
ProductConfigurer.class.classLoader.getResourceAsStream('logback-config-template/logback.groovy').withStream {
it.text
}
}
protected FileCollection getRunnerFileCollection() {
def servletContainerConfig = ServletContainerConfig.getConfig(sconfig.servletContainer)
def files = project.configurations.grettyNoSpringBoot
if(ProjectUtils.anyWebAppUsesSpringBoot(project, wconfigs)) {
files += project.configurations[servletContainerConfig.servletContainerRunnerConfig]
if(servletContainerConfig.servletContainerType == 'jetty')
files += project.configurations.grettyRunnerSpringBootJetty
else if(servletContainerConfig.servletContainerType == 'tomcat')
files += project.configurations.grettyRunnerSpringBootTomcat
} else
files += project.configurations[servletContainerConfig.servletContainerRunnerConfig]
files
}
private String getRunnerLogbackConfig() {
if(sconfig.logbackConfigFile) {
def logbackConfigFile = sconfig.logbackConfigFile
if(!(logbackConfigFile instanceof File))
logbackConfigFile = new File(logbackConfigFile.toString())
return logbackConfigFile.text
}
String logDir = sconfig.logDir
if(!logDir || logDir == "${System.getProperty('user.home')}/logs")
logDir = '${System.getProperty(\'user.home\')}/logs'
def logFileName = (sconfig.logFileName ?: productName ?: project.name)
def loggingLevel = sconfig.loggingLevel ?: 'INFO'
new groovy.text.SimpleTemplateEngine().createTemplate(getLogbackConfigTemplate()).make([
logDir: logDir,
logFileName: logFileName,
loggingLevel: loggingLevel,
consoleLogEnabled: sconfig.consoleLogEnabled,
fileLogEnabled: sconfig.fileLogEnabled
]).toString()
}
protected String getSpringBootMainClass() {
sconfig.springBootMainClass ?:
SpringBootMainClassFinder.findMainClass(project) ?:
wconfigs.findResult { it.projectPath ? SpringBootMainClassFinder.findMainClass(project.project(it.projectPath)) : null }
}
private String getStarterLogbackConfig() {
String logDir = sconfig.logDir
if(!logDir || logDir == "${System.getProperty('user.home')}/logs")
logDir = '${System.getProperty(\'user.home\')}/logs'
def logFileName = (sconfig.logFileName ?: productName ?: project.name) + '-starter'
def loggingLevel = sconfig.loggingLevel ?: 'INFO'
new groovy.text.SimpleTemplateEngine().createTemplate(getLogbackConfigTemplate()).make([
logDir: logDir,
logFileName: logFileName,
loggingLevel: loggingLevel,
consoleLogEnabled: sconfig.consoleLogEnabled,
fileLogEnabled: sconfig.fileLogEnabled
]).toString()
}
protected FileCollection getVisibleRunnerFileCollection() {
def files = getRunnerFileCollection()
files = files.filter { f ->
!f.name.startsWith('slf4j') && !f.name.startsWith('logback') && !f.name.startsWith('groovy')
}
}
protected resolveConfig() {
if(sconfig != null)
return
FarmConfigurer configurer = new FarmConfigurer(project)
FarmExtension productFarm = new FarmExtension(project)
configurer.configureFarm(productFarm,
new FarmExtension(project, serverConfig: product.serverConfig, webAppRefs: product.webAppRefs),
configurer.findProjectFarm(productName)
)
sconfig = productFarm.serverConfig
wconfigs = []
// we don't need to pass inplaceMode here cuz inplace=false anyway
configurer.resolveWebAppRefs(productFarm.webAppRefs, wconfigs, false)
for(WebAppConfig wconfig in wconfigs)
ProjectUtils.prepareToRun(project, wconfig)
CertificateGenerator.maybeGenerate(project, sconfig)
jsonConfig = writeConfigToJson()
createLaunchScripts()
}
protected void writeConfigFiles() {
// certificate files might be deleted by clean task
if(sconfig.sslKeyStorePath instanceof File &&
sconfig.sslKeyStorePath.absolutePath.startsWith(new File(project.buildDir, 'ssl').absolutePath) &&
!sconfig.sslKeyStorePath.exists()) {
sconfig.sslKeyStorePath = null
CertificateGenerator.maybeGenerate(project, sconfig)
jsonConfig = writeConfigToJson()
}
// there are cases when springBootMainClass was accessed too early (in configuration phase),
// so we neeed to recalculate it.
if(wconfigs.find { ProjectUtils.isSpringBootApp(project, it) } && jsonConfig.content.springBootMainClass == null) {
for(WebAppConfig wconfig in wconfigs)
ProjectUtils.prepareToRun(project, wconfig)
jsonConfig = writeConfigToJson()
}
ManagedDirectory dir = new ManagedDirectory(new File(outputDir, 'conf'))
File configFile = new File(dir.baseDir, 'server.json')
configFile.parentFile.mkdirs()
configFile.text = jsonConfig.toPrettyString()
dir.registerAdded(configFile)
if(sconfig.sslKeyStorePath && (!(sconfig.sslKeyStorePath instanceof String) || !sconfig.sslKeyStorePath.startsWith('classpath:')))
dir.add(sconfig.sslKeyStorePath)
if(sconfig.sslTrustStorePath && (!(sconfig.sslTrustStorePath instanceof String) || !sconfig.sslTrustStorePath.startsWith('classpath:')))
dir.add(sconfig.sslTrustStorePath)
if(sconfig.realmConfigFile)
dir.add(sconfig.realmConfigFile)
if(sconfig.serverConfigFile)
dir.add(sconfig.serverConfigFile)
for(WebAppConfig wconfig in wconfigs) {
String appDir = ProjectUtils.getWebAppDestinationDirName(project, wconfig)
if(wconfig.realmConfigFile)
dir.add(wconfig.realmConfigFile, appDir)
if(wconfig.contextConfigFile)
dir.add(wconfig.contextConfigFile, appDir)
}
dir.cleanup()
}
protected writeConfigToJson() {
def json = new JsonBuilder()
json {
writeConfigToJson(delegate)
}
json
}
protected void writeConfigToJson(json) {
def self = this
def getFileName = { file ->
if(file == null)
return null
if(!(file instanceof File))
file = new File(file.toString())
file.name
}
def servletContainerConfig = ServletContainerConfig.getConfig(sconfig.servletContainer)
json.with {
productName self.productName ?: project.name
servletContainer {
id sconfig.servletContainer
version servletContainerConfig.servletContainerVersion
description servletContainerConfig.servletContainerDescription
}
serverConfig {
if(sconfig.servicePort != ServerConfig.defaultServicePort)
servicePort sconfig.servicePort
if(sconfig.statusPort != ServerConfig.defaultStatusPort)
statusPort sconfig.statusPort
if(sconfig.host)
host sconfig.host
if(sconfig.httpEnabled) {
if(sconfig.httpPort)
httpPort sconfig.httpPort
if(sconfig.httpIdleTimeout)
httpIdleTimeout sconfig.httpIdleTimeout
} else
httpEnabled false
if(sconfig.httpsEnabled) {
httpsEnabled true
if(sconfig.httpsPort)
httpsPort sconfig.httpsPort
if(sconfig.httpsIdleTimeout)
httpsIdleTimeout sconfig.httpsIdleTimeout
// Note that sslHost is not written to config. sslHost must be only used by CertificateGenerator, which is not available in gretty products.
if(sconfig.sslKeyStorePath) {
if(sconfig.sslKeyStorePath instanceof File)
sslKeyStorePath 'conf/' + sconfig.sslKeyStorePath.name
else if(sconfig.sslKeyStorePath instanceof String)
sslKeyStorePath sconfig.sslKeyStorePath
}
if(sconfig.sslKeyStorePassword)
sslKeyStorePassword sconfig.sslKeyStorePassword
if(sconfig.sslKeyManagerPassword)
sslKeyManagerPassword sconfig.sslKeyManagerPassword
if(sconfig.sslTrustStorePath) {
if(sconfig.sslTrustStorePath instanceof File)
sslTrustStorePath 'conf/' + sconfig.sslTrustStorePath.name
else if(sconfig.sslTrustStorePath instanceof String)
sslTrustStorePath sconfig.sslTrustStorePath
}
if(sconfig.sslTrustStorePassword)
sslTrustStorePassword sconfig.sslTrustStorePassword
}
if(sconfig.realm)
realm sconfig.realm
if(sconfig.realmConfigFile)
realmConfigFile 'conf/' + getFileName(sconfig.realmConfigFile)
if(sconfig.serverConfigFile)
serverConfigFile 'conf/' + getFileName(sconfig.serverConfigFile)
if(sconfig.secureRandom != null)
secureRandom sconfig.secureRandom
if(wconfigs.find { ProjectUtils.isSpringBootApp(project, it) })
springBootMainClass self.getSpringBootMainClass()
if(sconfig.singleSignOn != null)
singleSignOn sconfig.singleSignOn
if(sconfig.enableNaming != null)
enableNaming sconfig.enableNaming
if(sconfig.jvmArgs)
jvmArgs sconfig.jvmArgs
}
webApps wconfigs.collect { WebAppConfig wconfig ->
{ ->
String webappDestName = ProjectUtils.getWebAppDestinationDirName(project, wconfig)
String appConfigDir = 'conf/' + webappDestName
contextPath wconfig.contextPath
if(ProjectUtils.isSpringBootApp(project, wconfig))
resourceBase 'webapps/' + ProjectUtils.getWebAppDestinationDirName(project, wconfig)
else
resourceBase 'webapps/' + getFileName(wconfig.resourceBase)
if(wconfig.extraResourceBases)
extraResourceBases wconfig.extraResourceBases.collect { 'extraResources/' + webappDestName + '/' + getFileName(it) }
if(wconfig.initParameters)
initParams wconfig.initParameters
if(wconfig.realm)
realm wconfig.realm
if(wconfig.realmConfigFile)
realmConfigFile appConfigDir + '/' + getFileName(wconfig.realmConfigFile)
if(wconfig.contextConfigFile)
contextConfigFile appConfigDir + '/' + getFileName(wconfig.contextConfigFile)
if(ProjectUtils.isSpringBootApp(project, wconfig))
springBoot true
if(wconfig.springBootSources)
springBootSources wconfig.springBootSources
}
}
} // json
}
protected void writeLaunchScripts() {
launchScripts.each { fileName, fileText ->
File file = new File(outputDir, fileName)
file.text = fileText
if(fileName.endsWith('.sh'))
file.setExecutable(true)
}
}
protected void writeTextFiles(Map textFiles) {
textFiles.each { fileName, fileText ->
File file = new File(outputDir, fileName)
file.text = fileText
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy