/* * Copyright 2004-2005 the original author or authors. * * 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. */ import org.apache.log4j.LogManager import org.codehaus.groovy.grails.commons.ConfigurationHolder import org.codehaus.groovy.grails.commons.cfg.ConfigurationHelper import org.codehaus.groovy.grails.plugins.logging.Log4jConfig import org.springframework.core.io.FileSystemResource /** * Gant script that packages a Grails application (note: does not create WAR) * * @author Graeme Rocher * * @since 0.4 */ includeTargets << grailsScript("_GrailsCompile") includeTargets << grailsScript("_PackagePlugins") target( createConfig: "Creates the configuration object") { if(configFile.exists()) { def configClass try { configClass = classLoader.loadClass("Config") } catch (ClassNotFoundException cnfe) { println "WARNING: No config found for the application." } if(configClass) { try { config = configSlurper.parse(configClass) config.setConfigFile(configFile.toURI().toURL()) ConfigurationHolder.setConfig(config) } catch(Exception e) { logError("Failed to compile configuration file",e) exit(1) } } } def dataSourceFile = new File("${basedir}/grails-app/conf/DataSource.groovy") if(dataSourceFile.exists()) { try { def dataSourceConfig = configSlurper.parse(classLoader.loadClass("DataSource")) config.merge(dataSourceConfig) ConfigurationHolder.setConfig(config) } catch(ClassNotFoundException e) { println "WARNING: DataSource.groovy not found, assuming dataSource bean is configured by Spring..." } catch(Exception e) { logError("Error loading DataSource.groovy",e) exit(1) } } ConfigurationHelper.initConfig(config, null, classLoader) } target( packageApp : "Implementation of package target") { depends(createStructure, packagePlugins, packageTlds) try { profile("compile") { compile() } } catch(Exception e) { logError("Compilation error",e) exit(1) } profile("creating config") { createConfig() } configureServerContextPath() String i18nDir = "${resourcesDirPath}/grails-app/i18n" ant.mkdir(dir:i18nDir) def files = ant.fileScanner { fileset(dir:"${basedir}/grails-app/views", includes:"**/*.jsp") } if(files.iterator().hasNext()) { ant.mkdir(dir:"${basedir}/web-app/WEB-INF/grails-app/views") ant.copy(todir:"${basedir}/web-app/WEB-INF/grails-app/views") { fileset(dir:"${basedir}/grails-app/views", includes:"**/*.jsp") } } if(config.grails.enable.native2ascii) { profile("converting native message bundles to ascii") { ant.native2ascii(src:"${basedir}/grails-app/i18n", dest:i18nDir, includes:"*.properties", encoding:"UTF-8") } } else { ant.copy(todir:i18nDir) { fileset(dir:"${basedir}/grails-app/i18n", includes:"*.properties") } } ant.copy(todir:classesDirPath) { fileset(dir:"${basedir}", includes:metadataFile.name) } // Copy resources from various directories to the target "resources" dir. packageFiles(basedir) startLogging() loadPlugins() generateWebXml() event("PackagingEnd",[]) } target(configureServerContextPath: "Configuring server context path") { // Get the application context path by looking for a property named 'app.context' in the following order of precedence: // System properties // application.properties // config // default to grailsAppName if not specified serverContextPath = System.getProperty("app.context") serverContextPath = serverContextPath ?: metadata.'app.context' serverContextPath = serverContextPath ?: config.grails.app.context serverContextPath = serverContextPath ?: grailsAppName if(!serverContextPath.startsWith('/')) { serverContextPath = "/${serverContextPath}" } } target(startLogging:"Bootstraps logging") { LogManager.resetConfiguration() if(config.log4j instanceof Closure) { profile("configuring log4j") { new Log4jConfig().configure(config.log4j) } } else { // setup default logging new Log4jConfig().configure() } } target( generateWebXml : "Generates the web.xml file") { depends(classpath) if(buildConfig.grails.config.base.webXml) { def customWebXml = resolveResources(buildConfig.grails.config.base.webXml) if(customWebXml) webXml = customWebXml[0] else { event("StatusError", [ "Custom web.xml defined in config [${buildConfig.grails.config.base.webXml}] could not be found." ]) exit(1) } } else { webXml = new FileSystemResource("${basedir}/src/templates/war/web.xml") def tmpWebXml = "${projectWorkDir}/web.xml.tmp" if(!webXml.exists()) { copyGrailsResource(tmpWebXml, grailsResource("src/war/WEB-INF/web${servletVersion}.template.xml")) } else { ant.copy(file:webXml.file, tofile:tmpWebXml, overwrite:true) } webXml = new FileSystemResource(tmpWebXml) ant.replace(file:tmpWebXml, token:"@grails.project.key@", value:"${grailsAppName}-${grailsEnv}-${grailsAppVersion}") } def sw = new StringWriter() try { profile("generating web.xml from $webXml") { event("WebXmlStart", [webXml.filename]) pluginManager.doWebDescriptor(webXml, sw) webXmlFile.withWriter { it << sw.toString() } event("WebXmlEnd", [webXml.filename]) } } catch(Exception e) { logError("Error generating web.xml file",e) exit(1) } } target(packageTemplates: "Packages templates into the app") { ant.mkdir(dir:scaffoldDir) if(new File("${basedir}/src/templates/scaffolding").exists()) { ant.copy(todir:scaffoldDir, overwrite:true) { fileset(dir:"${basedir}/src/templates/scaffolding", includes:"**") } } else { copyGrailsResources(scaffoldDir, "src/grails/templates/scaffolding/*") } } target(packageTlds:"packages tld definitions for the correct servlet version") { // We don't know until runtime what servlet version to use, so // install the relevant TLDs now. copyGrailsResources("${basedir}/web-app/WEB-INF/tld", "src/war/WEB-INF/tld/${servletVersion}/*") } // Checks whether the project's sources have changed since the last // compilation, and then performs a recompilation if this is the case. // Returns the updated 'lastModified' value. recompileCheck = { lastModified, callback -> try { def ant = new AntBuilder() def classpathId = "grails.compile.classpath" ant.taskdef (name: 'groovyc', classname : 'org.codehaus.groovy.grails.compiler.GrailsCompiler') ant.path(id:classpathId,compileClasspath) ant.groovyc(destdir:classesDirPath, classpathref:classpathId, encoding:"UTF-8", projectName:baseName) { src(path:"${basedir}/src/groovy") src(path:"${basedir}/grails-app/domain") src(path:"${basedir}/grails-app/utils") src(path:"${basedir}/src/java") javac(classpathref:classpathId, debug:"yes") } ant = null } catch(Exception e) { compilationError = true logError("Error automatically restarting container",e) } def tmp = classesDir.lastModified() if(lastModified < tmp) { // run another compile JIT try { callback() } catch(Exception e) { logError("Error automatically restarting container",e) } finally { lastModified = classesDir.lastModified() } } return lastModified }