Removed extra process alive check.
Removed extra process alive check.

/*
* Copyright 2014 John Ahlroos
*
* Licensed 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.
*/
package fi.jasoft.plugin

import fi.jasoft.plugin.tasks.CompileThemeTask
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.plugins.WarPluginConvention

import java.nio.file.WatchEvent

class ApplicationServer {

    def Process process;

    def final Project project;

    def List browserParameters

    def ApplicationServer(project, browserParameters = []) {
        this.project = project
        this.browserParameters = browserParameters
    }

    def boolean start(restarting=false) {

        if (process != null) {
            project.logger.error('Server is already running.')
            return false
        }

        File webAppDir = project.convention.getPlugin(WarPluginConvention).webAppDir
        FileCollection cp = project.configurations[DependencyListener.Configuration.JETTY9.caption] + Util.getClassPath(project)

        def appServerProcess = ['java']

        // Debug
        if (project.vaadin.debug) {
            appServerProcess.add('-Xdebug')
            appServerProcess.add("-Xrunjdwp:transport=dt_socket,address=${project.vaadin.debugPort},server=y,suspend=n")
        }

        // Jrebel
        if (project.vaadin.jrebel.enabled && project.vaadin.debug) {
            if (project.vaadin.jrebel.location != null && new File(project.vaadin.jrebel.location).exists()) {
                appServerProcess.add('-noverify')
                appServerProcess.add("-javaagent:${project.vaadin.jrebel.location}")
            } else {
                project.logger.warn('jrebel.jar not found, running without jrebel')
            }
        }

        // JVM options
        if (project.vaadin.debug) {
            appServerProcess.add('-ea')
        }

        appServerProcess.add('-cp')
        appServerProcess.add(cp.getAsPath())

        if (project.vaadin.jvmArgs != null) {
            appServerProcess.addAll(project.vaadin.jvmArgs)
        }

        // Program args
        appServerProcess.add('fi.jasoft.plugin.ApplicationServerRunner')

        appServerProcess.add(project.vaadin.serverPort)

        appServerProcess.add(webAppDir.canonicalPath + '/')

        File classesDir = project.file("build/classes")
        appServerProcess.add(classesDir.canonicalPath + '/')

        // Execute server
        process = appServerProcess.execute()

        // Watch for changes in classes
        if(project.vaadin.plugin.jettyAutoRefresh) {
            def self = this
            Thread.start 'Class Directory Watcher', {
                watchClassDirectoryForChanges(self)
            }
        }

        // Watch for changes in theme
        if(project.vaadin.plugin.themeAutoRecompile){
            Thread.start 'Theme Directory Watcher', {
                watchThemeDirectoryForChanges()
            }
        }

        // Build browser GET parameters
        def paramString = ''
        if (project.vaadin.debug) {
            paramString += '?debug'
            paramString += '&' + browserParameters.join('&')
        } else if(!browserParameters.isEmpty()){
            paramString += '?' + browserParameters.join('&')
        }
        paramString = paramString.replaceAll('\\?$|&$', '')

        // Capture log output
        Util.logProcess(project, process, 'jetty.log', { line ->
            if(line.contains('Server:main: Started')) {
                def resultStr = "Application running on http://localhost:${project.vaadin.serverPort} "
                if (project.vaadin.jrebel.enabled) {
                    resultStr += "(debugger on ${project.vaadin.debugPort}, JRebel active)"
                } else if (project.vaadin.debug) {
                    resultStr += "(debugger on ${project.vaadin.debugPort})"
                }
                project.logger.lifecycle(resultStr)
                project.logger.lifecycle('Press [Ctrl+C] to terminate server...')

                // Open browser
                if(!restarting) {
                    Util.openBrowser((Project)project, "http://localhost:${(Integer)project.vaadin.serverPort}/${paramString}")
                }
            }
        })

        project.logger.info 'Server running'
    }

    def restart = false

    def startAndBlock() {
        while(true){
            // Keep main loop running so task does not end

            // Reset values
            def restarting = restart
            restart = false
            process = null

            // Start server
            start(restarting)

            // Wait until server process calls destroy()
            process.waitFor()

            // In no restart is requested, terminate task
            if(!restart) {
                break;
            }
        }
    }

    def terminate() {
        if(process){
            process.destroy()
            project.logger.lifecycle("Application server terminated.")
        }
    }

    def restart() {
        restart = true
        terminate()
    }

    def watchClassDirectoryForChanges(final ApplicationServer server) {
        def classesDir
        if (project.vaadin.plugin.eclipseOutputDir == null) {
            classesDir = project.sourceSets.main.output.classesDir
        } else {
            classesDir = project.file(project.vaadin.plugin.eclipseOutputDir)
        }

        Util.watchDirectoryForChanges(project, classesDir as File, { event ->
            server.restart()
            true // Terminate watching
        })
    }

    def watchThemeDirectoryForChanges() {
        File webAppDir = project.convention.getPlugin(WarPluginConvention).webAppDir
        File themesDir = new File(webAppDir.canonicalPath + '/VAADIN/themes')
        if(themesDir.exists()) {
            Util.watchDirectoryForChanges(project, themesDir, { WatchEvent event ->
                if(event.context().toString().toLowerCase().endsWith(".scss")){
                    CompileThemeTask.compile(project)
                }
                false // Do not terminate on completion
            })
        }
    }
}

/*
* Copyright 2014 John Ahlroos
*
* Licensed 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.
*/
package fi.jasoft.plugin

import fi.jasoft.plugin.tasks.CompileThemeTask
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.plugins.WarPluginConvention

import java.nio.file.WatchEvent

class ApplicationServer {

    def Process process;

    def final Project project;

    def List browserParameters

    def ApplicationServer(project, browserParameters = []) {
        this.project = project
        this.browserParameters = browserParameters
    }

    def boolean start(restarting=false) {

        if (process != null) {
            project.logger.error('Server is already running.')
            return false
        }

        File webAppDir = project.convention.getPlugin(WarPluginConvention).webAppDir
        FileCollection cp = project.configurations[DependencyListener.Configuration.JETTY9.caption] + Util.getClassPath(project)

        def appServerProcess = ['java']

        // Debug
        if (project.vaadin.debug) {
            appServerProcess.add('-Xdebug')
            appServerProcess.add("-Xrunjdwp:transport=dt_socket,address=${project.vaadin.debugPort},server=y,suspend=n")
        }

        // Jrebel
        if (project.vaadin.jrebel.enabled && project.vaadin.debug) {
            if (project.vaadin.jrebel.location != null && new File(project.vaadin.jrebel.location).exists()) {
                appServerProcess.add('-noverify')
                appServerProcess.add("-javaagent:${project.vaadin.jrebel.location}")
            } else {
                project.logger.warn('jrebel.jar not found, running without jrebel')
            }
        }

        // JVM options
        if (project.vaadin.debug) {
            appServerProcess.add('-ea')
        }

        appServerProcess.add('-cp')
        appServerProcess.add(cp.getAsPath())

        if (project.vaadin.jvmArgs != null) {
            appServerProcess.addAll(project.vaadin.jvmArgs)
        }

        // Program args
        appServerProcess.add('fi.jasoft.plugin.ApplicationServerRunner')

        appServerProcess.add(project.vaadin.serverPort)

        appServerProcess.add(webAppDir.canonicalPath + '/')

        File classesDir = project.file("build/classes")
        appServerProcess.add(classesDir.canonicalPath + '/')

        // Execute server
        process = appServerProcess.execute()

        if(!process.alive) {
            project.logger.error("Could not start server,  server terminated with error code ${process.exitValue()}. Please look at jetty.log for reason.")
            return
        }

        // Watch for changes in classes
        if(project.vaadin.plugin.jettyAutoRefresh) {
            def self = this
            Thread.start 'Class Directory Watcher', {
                watchClassDirectoryForChanges(self)
            }
        }

        // Watch for changes in theme
        if(project.vaadin.plugin.themeAutoRecompile){
            Thread.start 'Theme Directory Watcher', {
                watchThemeDirectoryForChanges()
            }
        }

        // Build browser GET parameters
        def paramString = ''
        if (project.vaadin.debug) {
            paramString += '?debug'
            paramString += '&' + browserParameters.join('&')
        } else if(!browserParameters.isEmpty()){
            paramString += '?' + browserParameters.join('&')
        }
        paramString = paramString.replaceAll('\\?$|&$', '')

        // Capture log output
        Util.logProcess(project, process, 'jetty.log', { line ->
            if(line.contains('Server:main: Started')) {
                def resultStr = "Application running on http://localhost:${project.vaadin.serverPort} "
                if (project.vaadin.jrebel.enabled) {
                    resultStr += "(debugger on ${project.vaadin.debugPort}, JRebel active)"
                } else if (project.vaadin.debug) {
                    resultStr += "(debugger on ${project.vaadin.debugPort})"
                }
                project.logger.lifecycle(resultStr)
                project.logger.lifecycle('Press [Ctrl+C] to terminate server...')

                // Open browser
                if(!restarting) {
                    Util.openBrowser((Project)project, "http://localhost:${(Integer)project.vaadin.serverPort}/${paramString}")
                }
            }
        })

        project.logger.info 'Server running'
    }

    def restart = false

    def startAndBlock() {
        while(true){
            // Keep main loop running so task does not end

            // Reset values
            def restarting = restart
            restart = false
            process = null

            // Start server
            start(restarting)

            // Wait until server process calls destroy()
            process.waitFor()

            // In no restart is requested, terminate task
            if(!restart) {
                break;
            }
        }
    }

    def terminate() {
        if(process){
            process.destroy()
            project.logger.lifecycle("Application server terminated.")
        }
    }

    def restart() {
        restart = true
        terminate()
    }

    def watchClassDirectoryForChanges(final ApplicationServer server) {
        def classesDir
        if (project.vaadin.plugin.eclipseOutputDir == null) {
            classesDir = project.sourceSets.main.output.classesDir
        } else {
            classesDir = project.file(project.vaadin.plugin.eclipseOutputDir)
        }

        Util.watchDirectoryForChanges(project, classesDir as File, { event ->
            server.restart()
            true // Terminate watching
        })
    }

    def watchThemeDirectoryForChanges() {
        File webAppDir = project.convention.getPlugin(WarPluginConvention).webAppDir
        File themesDir = new File(webAppDir.canonicalPath + '/VAADIN/themes')
        if(themesDir.exists()) {
            Util.watchDirectoryForChanges(project, themesDir, { WatchEvent event ->
                if(event.context().toString().toLowerCase().endsWith(".scss")){
                    CompileThemeTask.compile(project)
                }
                false // Do not terminate on completion
            })
        }
    }
}
