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

org.akhikhl.gretty.GrettyPlugin.groovy Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * 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 org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import groovy.util.XmlSlurper
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ResolvedArtifact
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
 *
 * @author akhikhl
 */
class GrettyPlugin implements Plugin {

  protected static final Logger log = LoggerFactory.getLogger(GrettyPlugin)

  private void addConfigurations(Project project) {
    project.configurations {
      compile {
        exclude module: 'spring-boot-starter-tomcat'
        exclude module: 'spring-boot-starter-jetty'
      }
      gretty
      grettyStarter
      springBoot {
        exclude module: 'spring-boot-starter-tomcat'
        exclude module: 'spring-boot-starter-jetty'
        exclude group: 'org.eclipse.jetty'
        exclude group: 'org.eclipse.jetty.websocket'
      }
      grettyNoSpringBoot {
        extendsFrom project.configurations.gretty
        exclude group: 'org.springframework.boot'
      }
      grettySpringLoaded {
        transitive = false
      }
      grettyProductRuntime
      grettyProvidedCompile
      project.configurations.findByName('compile')?.extendsFrom grettyProvidedCompile
    }

    ServletContainerConfig.getConfigs().each { configName, config ->
      project.configurations.create config.servletContainerRunnerConfig
    }
  }

  private void addConfigurationsAfterEvaluate(Project project) {
    def runtimeConfig = project.configurations.findByName('runtime')
    project.configurations {
      springBoot {
        if (runtimeConfig)
          extendsFrom runtimeConfig
      }
      grettyProductRuntime {
        if (runtimeConfig)
          extendsFrom runtimeConfig
      }
    }
    // need to configure providedCompile, so that war excludes grettyProvidedCompile artifacts
    def providedCompile = project.configurations.findByName('providedCompile')
    if(providedCompile)
      providedCompile.extendsFrom project.configurations.grettyProvidedCompile
    SpringBootResolutionStrategy.apply(project)
  }

  private void addDependencies(Project project) {

    String grettyVersion = Externalized.getString('grettyVersion')
    String springBootVersion = project.gretty.springBootVersion ?: (project.hasProperty('springBootVersion') ? project.springBootVersion : Externalized.getString('springBootVersion'))
    String springLoadedVersion = project.gretty.springLoadedVersion ?: (project.hasProperty('springLoadedVersion') ? project.springLoadedVersion : Externalized.getString('springLoadedVersion'))
    String springVersion = project.gretty.springVersion ?: (project.hasProperty('springVersion') ? project.springVersion : Externalized.getString('springVersion'))
    String slf4jVersion = Externalized.getString('slf4jVersion')
    String logbackVersion = Externalized.getString('logbackVersion')

    project.dependencies {
      grettyStarter "org.akhikhl.gretty:gretty-starter:$grettyVersion"
      grettySpringLoaded "org.springframework:springloaded:$springLoadedVersion"
    }

    ServletContainerConfig.getConfig(project.gretty.servletContainer).with { config ->
      def closure = config.servletApiDependencies
      closure = closure.rehydrate(config, closure.owner, closure.thisObject)
      closure.resolveStrategy = Closure.DELEGATE_FIRST
      closure(project)
    }

    ServletContainerConfig.getConfigs().each { configName, config ->
      def closure = config.servletContainerRunnerDependencies
      closure = closure.rehydrate(config, closure.owner, closure.thisObject)
      closure.resolveStrategy = Closure.DELEGATE_FIRST
      closure(project)
    }

    if(project.gretty.springBoot) {
      String configName = project.configurations.findByName('compile') ? 'compile' : 'springBoot'
      project.dependencies.add configName, "org.springframework.boot:spring-boot-starter-web:$springBootVersion", {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
      }
      project.dependencies.add configName, "org.springframework.boot:spring-boot-starter-websocket:${springBootVersion}", {
        exclude group: 'org.apache.tomcat.embed'
      }
      project.dependencies.add configName, "org.springframework:spring-messaging:$springVersion"
      project.dependencies.add configName, "org.springframework:spring-websocket:$springVersion"
      project.dependencies.add configName, "ch.qos.logback:logback-classic:$logbackVersion"
      configName = project.configurations.findByName('runtime') ? 'runtime' : 'springBoot'
      project.dependencies.add configName, "org.akhikhl.gretty:gretty-springboot:$grettyVersion"
    }

    for(String overlay in project.gretty.overlays)
      project.dependencies.add 'grettyProvidedCompile', project.project(overlay)

    ProjectUtils.withOverlays(project).find { proj ->
      boolean alteredDependencies = false
      File webXmlFile = new File(ProjectUtils.getWebAppDir(proj), 'WEB-INF/web.xml')
      if(webXmlFile.exists()) {
        def webXml = new XmlSlurper().parse(webXmlFile)
        if(webXml.filter.find { it.'filter-class'.text() == 'org.akhikhl.gretty.RedirectFilter' }) {
          project.dependencies {
            compile "org.akhikhl.gretty:gretty-filter:${project.ext.grettyVersion}", {
              exclude group: 'javax.servlet', module: 'servlet-api'
            }
          }
          alteredDependencies = true
        }
      }
      alteredDependencies
    }

    def runtimeConfig = project.configurations.findByName('runtime')
    if(runtimeConfig) {
      def artifacts = runtimeConfig.copyRecursive().resolvedConfiguration.resolvedArtifacts
      if(artifacts.find { it.name == 'slf4j-api' } && !artifacts.find { it.name in ['slf4j-nop', 'slf4j-simple', 'slf4j-log4j12', 'slf4j-jdk14', 'logback-classic'] }) {
        project.dependencies {
          compile "org.slf4j:slf4j-nop:$slf4jVersion"
        }
      }
    }
  }

  private void addExtensions(Project project) {

    project.extensions.create('gretty', GrettyExtension)

    project.extensions.create('farm', FarmExtension, project)

    project.extensions.create('farms', FarmsExtension, project)
    project.farms.farmsMap_[''] = project.farm

    project.extensions.create('product', ProductExtension)

    project.extensions.create('products', ProductsExtension)
    project.products.productsMap[''] = project.product
  }

  private void addRepositories(Project project) {
    project.repositories {
      mavenLocal()
      jcenter()
      mavenCentral()
      maven { url 'http://repo.spring.io/release' }
      maven { url 'http://repo.spring.io/milestone' }
      maven { url 'http://repo.spring.io/snapshot' }
    }
  }

  private void addTaskDependencies(Project project) {

    project.tasks.whenObjectAdded { task ->
      if(GradleUtils.instanceOf(task, 'org.akhikhl.gretty.AppStartTask'))
        task.dependsOn {
          // We don't need any task for hard inplace mode.
          task.effectiveInplace ? project.tasks.prepareInplaceWebApp : project.tasks.prepareArchiveWebApp
        }
      else if(GradleUtils.instanceOf(task, 'org.akhikhl.gretty.FarmStartTask'))
        task.dependsOn {
          task.getWebAppConfigsForProjects().findResults {
            def proj = project.project(it.projectPath)
            boolean inplace = it.inplace == null ? task.inplace : it.inplace
            String prepareTaskName = inplace ? 'prepareInplaceWebApp' : 'prepareArchiveWebApp'
            def projTask = proj.tasks.findByName(prepareTaskName)
            if(!projTask)
              proj.tasks.whenObjectAdded { t ->
                if(t.name == prepareTaskName)
                  task.dependsOn t
              }
            projTask
          }
        }
    }
  }

  private void addTasks(Project project) {

    if(project.tasks.findByName('classes')) { // JVM project?

      project.task('prepareInplaceWebAppFolder', group: 'gretty') {
        description = 'Copies webAppDir of this web-app and all overlays (if any) to ${buildDir}/inplaceWebapp'
        def getInplaceMode = {
            project.tasks.findByName('appRun').effectiveInplaceMode
        }
        inputs.dir ProjectUtils.getWebAppDir(project)
        // We should track changes in inplaceMode value or plugin would show UP-TO-DATE for this task
        // even if inplaceMode was changed
        inputs.property('inplaceMode', getInplaceMode)
        outputs.dir "${project.buildDir}/inplaceWebapp"
        doLast {
            if(getInplaceMode() != 'hard') {
                // Skipping this task for hard inplaceMode.
                ProjectUtils.prepareInplaceWebAppFolder(project)
            }
        }

      }

      project.task('prepareInplaceWebAppClasses', group: 'gretty') {
        description = 'Compiles classes of this web-app and all overlays (if any)'
        dependsOn project.tasks.classes
        for(String overlay in project.gretty.overlays)
          dependsOn "$overlay:prepareInplaceWebAppClasses"
      }

      project.task('prepareInplaceWebApp', group: 'gretty') {
        description = 'Prepares inplace web-app'
        dependsOn project.tasks.prepareInplaceWebAppFolder
        dependsOn project.tasks.prepareInplaceWebAppClasses
      }

      def archiveTask = project.tasks.findByName('war') ?: project.tasks.jar

      archiveTask.configure project.gretty.webappCopy

      if(project.gretty.overlays) {

        project.ext.finalArchivePath = archiveTask.archivePath

        archiveTask.archiveName = 'partial.' + (project.tasks.findByName('war') ? 'war' : 'jar')

        // 'explodeWebApps' task is only activated by 'overlayArchive' task
        project.task('explodeWebApps', group: 'gretty') {
          description = 'Explodes this web-app and all overlays (if any) to ${buildDir}/explodedWebapp'
          for(String overlay in project.gretty.overlays)
            dependsOn "$overlay:assemble" as String
          dependsOn archiveTask
          for(String overlay in project.gretty.overlays)
            inputs.file { ProjectUtils.getFinalArchivePath(project.project(overlay)) }
          inputs.file archiveTask.archivePath
          outputs.dir "${project.buildDir}/explodedWebapp"
          doLast {
            ProjectUtils.prepareExplodedWebAppFolder(project)
          }
        }

        project.task('overlayArchive', group: 'gretty') {
          description = 'Creates archive from exploded web-app in ${buildDir}/explodedWebapp'
          dependsOn project.tasks.explodeWebApps
          inputs.dir "${project.buildDir}/explodedWebapp"
          outputs.file project.ext.finalArchivePath
          doLast {
            ant.zip destfile: project.ext.finalArchivePath, basedir: "${project.buildDir}/explodedWebapp"
          }
        }

        project.tasks.assemble.dependsOn project.tasks.overlayArchive
      } // overlays

      project.task('prepareArchiveWebApp', group: 'gretty') {
        description = 'Prepares war web-app'
        if(project.gretty.overlays)
          dependsOn project.tasks.overlayArchive
        else
          dependsOn archiveTask
      }

      project.task('appRun', type: AppStartTask, group: 'gretty') {
        description = 'Starts web-app inplace, in interactive mode.'
      }

      project.tasks.run.dependsOn 'appRun'

      project.task('appRunDebug', type: AppStartTask, group: 'gretty') {
        description = 'Starts web-app inplace, in debug and interactive mode.'
        debug = true
      }

      project.tasks.debug.dependsOn 'appRunDebug'

      project.task('appStart', type: AppStartTask, group: 'gretty') {
        description = 'Starts web-app inplace (stopped by \'appStop\').'
        interactive = false
      }

      project.task('appStartDebug', type: AppStartTask, group: 'gretty') {
        description = 'Starts web-app inplace, in debug mode (stopped by \'appStop\').'
        interactive = false
        debug = true
      }

      if(project.plugins.findPlugin(org.gradle.api.plugins.WarPlugin)) {

        project.task('appRunWar', type: AppStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file, in interactive mode.'
          inplace = false
        }

        project.task('appRunWarDebug', type: AppStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file, in debug and interactive mode.'
          inplace = false
          debug = true
        }

        project.task('appStartWar', type: AppStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file (stopped by \'appStop\').'
          inplace = false
          interactive = false
        }

        project.task('appStartWarDebug', type: AppStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file, in debug mode (stopped by \'appStop\').'
          inplace = false
          interactive = false
          debug = true
        }
      }

      project.task('appStop', type: AppStopTask, group: 'gretty') {
        description = 'Sends \'stop\' command to a running server.'
      }

      project.task('appRestart', type: AppRestartTask, group: 'gretty') {
        description = 'Sends \'restart\' command to a running server.'
      }

      project.task('appBeforeIntegrationTest', type: AppBeforeIntegrationTestTask, group: 'gretty') {
        description = 'Starts server before integration test.'
      }

      project.task('appAfterIntegrationTest', type: AppAfterIntegrationTestTask, group: 'gretty') {
        description = 'Stops server after integration test.'
      }

      project.task('jettyRun', type: JettyStartTask, group: 'gretty') {
        description = 'Starts web-app inplace, in interactive mode.'
      }

      project.task('jettyRunDebug', type: JettyStartTask, group: 'gretty') {
        description = 'Starts web-app inplace, in debug and interactive mode.'
        debug = true
      }

      project.task('jettyStart', type: JettyStartTask, group: 'gretty') {
        description = 'Starts web-app inplace (stopped by \'jettyStop\').'
        interactive = false
      }

      project.task('jettyStartDebug', type: JettyStartTask, group: 'gretty') {
        description = 'Starts web-app inplace, in debug mode (stopped by \'jettyStop\').'
        interactive = false
        debug = true
      }

      if(project.plugins.findPlugin(org.gradle.api.plugins.WarPlugin)) {

        project.task('jettyRunWar', type: JettyStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file, in interactive mode.'
          inplace = false
        }

        project.task('jettyRunWarDebug', type: JettyStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file, in debug and interactive mode.'
          inplace = false
          debug = true
        }

        project.task('jettyStartWar', type: JettyStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file (stopped by \'jettyStop\').'
          inplace = false
          interactive = false
        }

        project.task('jettyStartWarDebug', type: JettyStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file, in debug mode (stopped by \'jettyStop\').'
          inplace = false
          interactive = false
          debug = true
        }
      }

      project.task('jettyStop', type: AppStopTask, group: 'gretty') {
        description = 'Sends \'stop\' command to a running server.'
      }

      project.task('jettyRestart', type: AppRestartTask, group: 'gretty') {
        description = 'Sends \'restart\' command to a running server.'
      }

      project.task('tomcatRun', type: TomcatStartTask, group: 'gretty') {
        description = 'Starts web-app inplace, in interactive mode.'
      }

      project.task('tomcatRunDebug', type: TomcatStartTask, group: 'gretty') {
        description = 'Starts web-app inplace, in debug and interactive mode.'
        debug = true
      }

      project.task('tomcatStart', type: TomcatStartTask, group: 'gretty') {
        description = 'Starts web-app inplace (stopped by \'tomcatStop\').'
        interactive = false
      }

      project.task('tomcatStartDebug', type: TomcatStartTask, group: 'gretty') {
        description = 'Starts web-app inplace, in debug mode (stopped by \'tomcatStop\').'
        interactive = false
        debug = true
      }

      if(project.plugins.findPlugin(org.gradle.api.plugins.WarPlugin)) {

        project.task('tomcatRunWar', type: TomcatStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file, in interactive mode.'
          inplace = false
        }

        project.task('tomcatRunWarDebug', type: TomcatStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file, in debug and interactive mode.'
          inplace = false
          debug = true
        }

        project.task('tomcatStartWar', type: TomcatStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file (stopped by \'tomcatStop\').'
          inplace = false
          interactive = false
        }

        project.task('tomcatStartWarDebug', type: TomcatStartTask, group: 'gretty') {
          description = 'Starts web-app on WAR-file, in debug mode (stopped by \'tomcatStop\').'
          inplace = false
          interactive = false
          debug = true
        }
      }

      project.task('tomcatStop', type: AppStopTask, group: 'gretty') {
        description = 'Sends \'stop\' command to a running server.'
      }

      project.task('tomcatRestart', type: AppRestartTask, group: 'gretty') {
        description = 'Sends \'restart\' command to a running server.'
      }

      project.ext.jettyBeforeIntegrationTest = project.tasks.ext.jettyBeforeIntegrationTest = project.tasks.appBeforeIntegrationTest

      project.ext.jettyAfterIntegrationTest = project.tasks.ext.jettyAfterIntegrationTest = project.tasks.appAfterIntegrationTest

      project.task('showClassPath', group: 'gretty') {
        description = 'Shows classpath information'
        doLast {
          println "Runner classpath:"
          project.tasks.appRun.runnerClassPath.each { URL url ->
            println " $url"
          }
          project.tasks.appRun.getWebappClassPaths().each { contextPath, cp ->
            println "$contextPath classpath:"
            cp.each { URL url ->
              println " $url"
            }
          }
        }
      }

    } // JVM project

    project.farms.farmsMap.each { fname, farm ->

      String farmDescr = fname ? "farm '${fname}'" : 'default farm'

      project.task('farmRun' + fname, type: FarmStartTask, group: 'gretty') {
        description = "Starts ${farmDescr} inplace, in interactive mode."
        farmName = fname
        if(!fname)
          doFirst {
            GradleUtils.disableTaskOnOtherProjects(project, 'run')
            GradleUtils.disableTaskOnOtherProjects(project, 'jettyRun')
            GradleUtils.disableTaskOnOtherProjects(project, 'farmRun')
          }
      }

      project.task('farmRunDebug' + fname, type: FarmStartTask, group: 'gretty') {
        description = "Starts ${farmDescr} inplace, in debug and in interactive mode."
        farmName = fname
        debug = true
        if(!fname)
          doFirst {
            GradleUtils.disableTaskOnOtherProjects(project, 'debug')
            GradleUtils.disableTaskOnOtherProjects(project, 'jettyRunDebug')
            GradleUtils.disableTaskOnOtherProjects(project, 'farmRunDebug')
          }
      }

      project.task('farmStart' + fname, type: FarmStartTask, group: 'gretty') {
        description = "Starts ${farmDescr} inplace (stopped by 'farmStop${fname}')."
        farmName = fname
        interactive = false
      }

      project.task('farmStartDebug' + fname, type: FarmStartTask, group: 'gretty') {
        description = "Starts ${farmDescr} inplace, in debug mode (stopped by 'farmStop${fname}')."
        farmName = fname
        interactive = false
        debug = true
      }

      project.task('farmRunWar' + fname, type: FarmStartTask, group: 'gretty') {
        description = "Starts ${farmDescr} on WAR-files, in interactive mode."
        farmName = fname
        inplace = false
      }

      project.task('farmRunWarDebug' + fname, type: FarmStartTask, group: 'gretty') {
        description = "Starts ${farmDescr} on WAR-files, in debug and in interactive mode."
        farmName = fname
        debug = true
        inplace = false
      }

      project.task('farmStartWar' + fname, type: FarmStartTask, group: 'gretty') {
        description = "Starts ${farmDescr} on WAR-files (stopped by 'farmStop${fname}')."
        farmName = fname
        interactive = false
        inplace = false
      }

      project.task('farmStartWarDebug' + fname, type: FarmStartTask, group: 'gretty') {
        description = "Starts ${farmDescr} on WAR-files, in debug (stopped by 'farmStop${fname}')."
        farmName = fname
        interactive = false
        debug = true
        inplace = false
      }

      project.task('farmStop' + fname, type: FarmStopTask, group: 'gretty') {
        description = "Sends \'stop\' command to a running ${farmDescr}."
        farmName = fname
      }

      project.task('farmRestart' + fname, type: FarmRestartTask, group: 'gretty') {
        description = "Sends \'restart\' command to a running ${farmDescr}."
        farmName = fname
      }

      project.task('farmBeforeIntegrationTest' + fname, type: FarmBeforeIntegrationTestTask, group: 'gretty') {
        description = "Starts ${farmDescr} before integration test."
        farmName = fname
      }

      project.task('farmIntegrationTest' + fname, type: FarmIntegrationTestTask, group: 'gretty') {
        description = "Runs integration tests on ${farmDescr} web-apps."
        farmName = fname
        dependsOn 'farmBeforeIntegrationTest' + fname
        finalizedBy 'farmAfterIntegrationTest' + fname
      }

      project.task('farmAfterIntegrationTest' + fname, type: FarmAfterIntegrationTestTask, group: 'gretty') {
        description = "Stops ${farmDescr} after integration test."
        farmName = fname
      }
    } // farmsMap
  } // addTasks

  private void afterProjectEvaluate(Project project) {

    if(project.extensions.findByName('gretty')) {

      addConfigurationsAfterEvaluate(project)
      addTaskDependencies(project)
      new ProductsConfigurer(project).configureProducts()

      if(project.gretty.autoConfigureRepositories)
        addRepositories(project)

      addDependencies(project)
      addTasks(project)

      for(Closure afterEvaluateClosure in project.gretty.afterEvaluate) {
        afterEvaluateClosure.delegate = project.gretty
        afterEvaluateClosure.resolveStrategy = Closure.DELEGATE_FIRST
        afterEvaluateClosure()
      }

      project.tasks.findByName('appBeforeIntegrationTest')?.with {
        if(!integrationTestTaskAssigned)
          integrationTestTask null // default binding
      }

      project.tasks.findByName('appAfterIntegrationTest')?.with {
        if(!integrationTestTaskAssigned)
          integrationTestTask null // default binding
      }
    }
  }

  private void afterAllProjectsEvaluate(Project rootProject) {

    rootProject.allprojects { project ->

      if(project.extensions.findByName('farms'))
        project.farms.farmsMap.each { fname, farm ->

          for(Closure afterEvaluateClosure in farm.afterEvaluate) {
            afterEvaluateClosure.delegate = farm
            afterEvaluateClosure.resolveStrategy = Closure.DELEGATE_FIRST
            afterEvaluateClosure()
          }

          if(!project.tasks."farmBeforeIntegrationTest$fname".integrationTestTaskAssigned)
            project.tasks."farmBeforeIntegrationTest$fname".integrationTestTask null // default binding

          if(!project.tasks."farmIntegrationTest$fname".integrationTestTaskAssigned)
            project.tasks."farmIntegrationTest$fname".integrationTestTask null // default binding

          if(!project.tasks."farmAfterIntegrationTest$fname".integrationTestTaskAssigned)
            project.tasks."farmAfterIntegrationTest$fname".integrationTestTask null // default binding
        }
    }
  }

  void apply(final Project project) {

    if(project.gradle.gradleVersion.startsWith('1.')) {
      String releaseNumberStr = project.gradle.gradleVersion.split('\\.')[1]
      if(releaseNumberStr.contains('-'))
        releaseNumberStr = releaseNumberStr.split('-')[0]
      int releaseNumber = releaseNumberStr as int
      if(releaseNumber < 10)
        throw new GradleException("Gretty supports only Gradle 1.10 or newer. You have Gradle ${project.gradle.gradleVersion}.")
    }

    project.ext {
      grettyVersion = Externalized.getString('grettyVersion')
      jetty7Version = Externalized.getString('jetty7Version')
      jetty7ServletApi = Externalized.getString('jetty7ServletApi')
      jetty7ServletApiVersion = Externalized.getString('jetty7ServletApiVersion')
      jetty8Version = Externalized.getString('jetty8Version')
      jetty8ServletApi = Externalized.getString('jetty8ServletApi')
      jetty8ServletApiVersion = Externalized.getString('jetty8ServletApiVersion')
      jetty9Version = Externalized.getString('jetty9Version')
      jetty9ServletApi = Externalized.getString('jetty9ServletApi')
      jetty9ServletApiVersion = Externalized.getString('jetty9ServletApiVersion')
      tomcat7Version = Externalized.getString('tomcat7Version')
      tomcat7ServletApi = Externalized.getString('tomcat7ServletApi')
      tomcat7ServletApiVersion = Externalized.getString('tomcat7ServletApiVersion')
      tomcat8Version = Externalized.getString('tomcat8Version')
      tomcat8ServletApi = Externalized.getString('tomcat8ServletApi')
      tomcat8ServletApiVersion = Externalized.getString('tomcat8ServletApiVersion')
    }

    if(!project.tasks.findByName('run'))
      project.task('run', group: 'gretty') {
        description = 'Starts web-app inplace, in interactive mode. Same as appRun task.'
      }

    if(!project.tasks.findByName('debug'))
      project.task('debug', group: 'gretty') {
        description = 'Starts web-app inplace, in debug and interactive mode. Same as appRunDebug task.'
      }

    addExtensions(project)
    addConfigurations(project)

    if(!project.rootProject.hasProperty('gretty_')) {
      Project rootProject = project.rootProject
      rootProject.ext.gretty_ = [:]
      rootProject.ext.gretty_.projects = []
      rootProject.allprojects { proj ->
        afterEvaluate {
          afterProjectEvaluate(proj)
          rootProject.ext.gretty_.projects.add proj
          if(rootProject.ext.gretty_.projects.size() == rootProject.allprojects.size())
            afterAllProjectsEvaluate(rootProject)
        }
      }
    }
  } // apply
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy