diff --git a/scripts/War.groovy b/scripts/War.groovy index 6c53bfa53c8..df37c383c64 100755 --- a/scripts/War.groovy +++ b/scripts/War.groovy @@ -105,6 +105,7 @@ target (war: "The implementation target") { Ant.propertyfile(file:"${basedir}/staging/WEB-INF/classes/application.properties") { entry(key:"grails.env", value:grailsEnv) + entry(key:"grails.war.deployed", value:"true") } Ant.replace(file:"${basedir}/staging/WEB-INF/applicationContext.xml", diff --git a/src/commons/org/codehaus/groovy/grails/commons/DefaultGrailsApplication.java b/src/commons/org/codehaus/groovy/grails/commons/DefaultGrailsApplication.java index 51340770f63..8b7e74c5f99 100644 --- a/src/commons/org/codehaus/groovy/grails/commons/DefaultGrailsApplication.java +++ b/src/commons/org/codehaus/groovy/grails/commons/DefaultGrailsApplication.java @@ -99,6 +99,7 @@ public class DefaultGrailsApplication extends GroovyObjectSupport implements Gra private static final String CONFIG_BINDING_GRAILS_HOME = "grailsHome"; private static final String CONFIG_BINDING_APP_NAME = "appName"; private static final String CONFIG_BINDING_APP_VERSION = "appVersion"; + private static final String META_GRAILS_WAR_DEPLOYED = "grails.war.deployed"; /** * Creates a new empty Grails application @@ -124,7 +125,7 @@ public DefaultGrailsApplication(final Class[] classes, GroovyClassLoader classLo } this.allClasses = classes; this.cl = classLoader; - loadMetadata(); + this.applicationMeta = loadMetadata(); } @@ -143,7 +144,7 @@ public DefaultGrailsApplication(GrailsResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; try { - loadMetadata(); + this.applicationMeta = loadMetadata(); loadGrailsApplicationFromResources(resourceLoader.getResources()); } catch (IOException e) { throw new GrailsConfigurationException("I/O exception loading Grails: " + e.getMessage(), e); @@ -206,7 +207,7 @@ private void loadGrailsApplicationFromResources(Resource[] resources) throws IOE } } - private void loadMetadata() { + protected Map loadMetadata() { final Properties meta = new Properties(); Resource r = new ClassPathResource(PROJECT_META_FILE); try { @@ -218,7 +219,7 @@ private void loadMetadata() { if (System.getProperty(GrailsApplication.ENVIRONMENT) != null) { meta.setProperty(GrailsApplication.ENVIRONMENT, System.getProperty(GrailsApplication.ENVIRONMENT)); } - applicationMeta = Collections.unmodifiableMap(meta); + return Collections.unmodifiableMap(meta); } /** @@ -872,6 +873,17 @@ public void addArtefact(Class artefact) { } } + public boolean isWarDeployed() { + Map metadata = getMetadata(); + if(metadata != null) { + Object val = metadata.get(META_GRAILS_WAR_DEPLOYED); + if(val != null && val.equals("true")) { + return true; + } + } + return false; + } + public void setBeanClassLoader(ClassLoader classLoader) { this.beanClassLoader = classLoader; } diff --git a/src/commons/org/codehaus/groovy/grails/commons/GrailsApplication.java b/src/commons/org/codehaus/groovy/grails/commons/GrailsApplication.java index 3cc0f5517fd..ac565953799 100644 --- a/src/commons/org/codehaus/groovy/grails/commons/GrailsApplication.java +++ b/src/commons/org/codehaus/groovy/grails/commons/GrailsApplication.java @@ -268,4 +268,11 @@ public interface GrailsApplication extends ApplicationContextAware { * @param artefact The artefact to add */ void addArtefact(Class artefact); + + /** + * Returns true if this application has been deployed as a WAR file + * + * @return True if the application is WAR deployed + */ + boolean isWarDeployed(); } diff --git a/src/groovy/org/codehaus/groovy/grails/plugins/web/ControllersGrailsPlugin.groovy b/src/groovy/org/codehaus/groovy/grails/plugins/web/ControllersGrailsPlugin.groovy index 71139548f63..f8f24306cab 100644 --- a/src/groovy/org/codehaus/groovy/grails/plugins/web/ControllersGrailsPlugin.groovy +++ b/src/groovy/org/codehaus/groovy/grails/plugins/web/ControllersGrailsPlugin.groovy @@ -12,9 +12,9 @@ * 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 org.codehaus.groovy.grails.plugins.web; - + import org.codehaus.groovy.grails.commons.GrailsClassUtils as GCU import org.springframework.web.context.request.RequestContextHolder as RCH @@ -53,288 +53,291 @@ import org.springframework.web.servlet.ModelAndView */ class ControllersGrailsPlugin { - def watchedResources = ["file:./grails-app/controllers/**/*Controller.groovy", - "file:./plugins/*/grails-app/controllers/**/*Controller.groovy", - "file:./plugins/*/grails-app/taglib/**/*TagLib.groovy", - "file:./grails-app/taglib/**/*TagLib.groovy"] - - def version = grails.util.GrailsUtil.getGrailsVersion() - def dependsOn = [core:version,i18n:version] - def providedArtefacts = [ ApplicationTagLib, - FormatTagLib, - FormTagLib, - JavascriptTagLib, - RenderTagLib, - ValidationTagLib - ] - - def doWithSpring = { - exceptionHandler(GrailsExceptionResolver) { - exceptionMappings = ['java.lang.Exception':'/error'] - } - multipartResolver(CommonsMultipartResolver) - def urlMappings = [:] - grailsUrlMappings(UrlMappingFactoryBean) { - mappings = urlMappings - } - simpleGrailsController(SimpleGrailsController.class) { - grailsApplication = ref("grailsApplication", true) - } - - - - def viewsDir = application.config.grails.gsp.view.dir - if(viewsDir) { - log.info "Configuring GSP views directory as '${viewsDir}'" - groovyPageResourceLoader(org.codehaus.groovy.grails.web.pages.GroovyPageResourceLoader) { - baseResource = "file:${viewsDir}" - } - } - else if(grails.util.GrailsUtil.isDevelopmentEnv()) { - groovyPageResourceLoader(org.codehaus.groovy.grails.web.pages.GroovyPageResourceLoader) { - baseResource = new FileSystemResource(".") - } - } - - - groovyPagesTemplateEngine(org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateEngine) { - classLoader = ref("classLoader") - if(grails.util.GrailsUtil.isDevelopmentEnv()) { - resourceLoader = groovyPageResourceLoader - } - if(grails.util.GrailsUtil.isDevelopmentEnv() || application.config.grails.gsp.enable.reload == true) { + def watchedResources = ["file:./grails-app/controllers/**/*Controller.groovy", + "file:./plugins/*/grails-app/controllers/**/*Controller.groovy", + "file:./plugins/*/grails-app/taglib/**/*TagLib.groovy", + "file:./grails-app/taglib/**/*TagLib.groovy"] + + def version = grails.util.GrailsUtil.getGrailsVersion() + def dependsOn = [core: version, i18n: version] + def providedArtefacts = [ApplicationTagLib, + FormatTagLib, + FormTagLib, + JavascriptTagLib, + RenderTagLib, + ValidationTagLib + ] + + def doWithSpring = { + exceptionHandler(GrailsExceptionResolver) { + exceptionMappings = ['java.lang.Exception': '/error'] + } + multipartResolver(CommonsMultipartResolver) + def urlMappings = [:] + grailsUrlMappings(UrlMappingFactoryBean) { + mappings = urlMappings + } + simpleGrailsController(SimpleGrailsController.class) { + grailsApplication = ref("grailsApplication", true) + } + + boolean developmentMode = grails.util.GrailsUtil.isDevelopmentEnv() && !application.warDeployed + + + def viewsDir = application.config.grails.gsp.view.dir + if (viewsDir) { + log.info "Configuring GSP views directory as '${viewsDir}'" + groovyPageResourceLoader(org.codehaus.groovy.grails.web.pages.GroovyPageResourceLoader) { + baseResource = "file:${viewsDir}" + } + } + else { + if (developmentMode) { + groovyPageResourceLoader(org.codehaus.groovy.grails.web.pages.GroovyPageResourceLoader) { + baseResource = new FileSystemResource(".") + } + } + } + + + groovyPagesTemplateEngine(org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateEngine) { + classLoader = ref("classLoader") + if (developmentMode) { + resourceLoader = groovyPageResourceLoader + } + if (grails.util.GrailsUtil.isDevelopmentEnv() || application.config.grails.gsp.enable.reload == true) { reloadEnabled = true } - } - - jspViewResolver(GrailsViewResolver) { - viewClass = org.springframework.web.servlet.view.JstlView.class - prefix = GrailsApplicationAttributes.PATH_TO_VIEWS - suffix = ".jsp" - templateEngine = groovyPagesTemplateEngine - pluginMetaManager = ref("pluginMetaManager", true) - if(grails.util.GrailsUtil.isDevelopmentEnv()) { - resourceLoader = groovyPageResourceLoader - } - } - - - def handlerInterceptors = [ref("localeChangeInterceptor")] - grailsUrlHandlerMapping(GrailsUrlHandlerMapping) { - interceptors = handlerInterceptors - mappings = grailsUrlMappings - } - handlerMappingTargetSource(HotSwappableTargetSource, grailsUrlHandlerMapping) - handlerMapping(ProxyFactoryBean) { - targetSource = handlerMappingTargetSource - proxyInterfaces = [org.springframework.web.servlet.HandlerMapping] - } - - application.controllerClasses.each { controller -> - log.debug "Configuring controller $controller.fullName" - if(controller.available) { - // configure the controller with AOP proxies for auto-updates and - // mappings in the urlMappings bean - configureAOPProxyBean.delegate = delegate + } + + jspViewResolver(GrailsViewResolver) { + viewClass = org.springframework.web.servlet.view.JstlView.class + prefix = GrailsApplicationAttributes.PATH_TO_VIEWS + suffix = ".jsp" + templateEngine = groovyPagesTemplateEngine + pluginMetaManager = ref("pluginMetaManager", true) + if (developmentMode) { + resourceLoader = groovyPageResourceLoader + } + } + + + def handlerInterceptors = [ref("localeChangeInterceptor")] + grailsUrlHandlerMapping(GrailsUrlHandlerMapping) { + interceptors = handlerInterceptors + mappings = grailsUrlMappings + } + handlerMappingTargetSource(HotSwappableTargetSource, grailsUrlHandlerMapping) + handlerMapping(ProxyFactoryBean) { + targetSource = handlerMappingTargetSource + proxyInterfaces = [org.springframework.web.servlet.HandlerMapping] + } + + application.controllerClasses.each {controller -> + log.debug "Configuring controller $controller.fullName" + if (controller.available) { + // configure the controller with AOP proxies for auto-updates and + // mappings in the urlMappings bean + configureAOPProxyBean.delegate = delegate configureAOPProxyBean(controller, ControllerArtefactHandler.TYPE, org.codehaus.groovy.grails.commons.GrailsControllerClass.class, false) - } - - } - - // Now go through tag libraries and configure them in spring too. With AOP proxies and so on - application.tagLibClasses.each { taglib -> - configureAOPProxyBean.delegate = delegate - configureAOPProxyBean(taglib, TagLibArtefactHandler.TYPE, org.codehaus.groovy.grails.commons.GrailsTagLibClass.class, true) - } - } - - def configureAOPProxyBean = { grailsClass, artefactType, proxyClass, singleton -> - "${grailsClass.fullName}Class"(MethodInvokingFactoryBean) { - targetObject = ref("grailsApplication", true) - targetMethod = "getArtefact" - arguments = [artefactType, grailsClass.fullName] - } - "${grailsClass.fullName}TargetSource"(HotSwappableTargetSource, ref("${grailsClass.fullName}Class")) - - "${grailsClass.fullName}Proxy"(ProxyFactoryBean) { - targetSource = ref("${grailsClass.fullName}TargetSource") - proxyInterfaces = [proxyClass] - } - "${grailsClass.fullName}"("${grailsClass.fullName}Proxy":"newInstance") { bean -> - bean.singleton = singleton - bean.autowire = "byName" - } - - } - - def doWithWebDescriptor = { webXml -> - - def basedir = System.getProperty("base.dir") - def grailsEnv = GrailsUtil.getEnvironment() - - def mappingElement = webXml.'servlet-mapping' - mappingElement + { - 'servlet-mapping' { - 'servlet-name'("grails") - 'url-pattern'("*.dispatch") - } - } - - def filters = webXml.filter - def filterMappings = webXml.'filter-mapping' - - def lastFilter = filters[filters.size()-1] - def lastFilterMapping = filterMappings[filterMappings.size()-1] - def charEncodingFilter = filterMappings.find { it.'filter-name'.text() == 'charEncodingFilter'} - - // add the Grails web request filter - lastFilter + { - filter { - 'filter-name'('grailsWebRequest') - 'filter-class'(org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter.getName()) - } - filter { - 'filter-name'('urlMapping') - 'filter-class'(org.codehaus.groovy.grails.web.mapping.filter.UrlMappingsFilter.getName()) - } - if(grailsEnv == "development") { - filter { - 'filter-name'('reloadFilter') - 'filter-class'(org.codehaus.groovy.grails.web.servlet.filter.GrailsReloadServletFilter.getName()) - } - } - } - def grailsWebRequestFilter = { - 'filter-mapping' { - 'filter-name'('grailsWebRequest') - 'url-pattern'("/*") - } - if(grailsEnv == "development") { + } + + } + + // Now go through tag libraries and configure them in spring too. With AOP proxies and so on + application.tagLibClasses.each {taglib -> + configureAOPProxyBean.delegate = delegate + configureAOPProxyBean(taglib, TagLibArtefactHandler.TYPE, org.codehaus.groovy.grails.commons.GrailsTagLibClass.class, true) + } + } + + def configureAOPProxyBean = {grailsClass, artefactType, proxyClass, singleton -> + "${grailsClass.fullName}Class"(MethodInvokingFactoryBean) { + targetObject = ref("grailsApplication", true) + targetMethod = "getArtefact" + arguments = [artefactType, grailsClass.fullName] + } + "${grailsClass.fullName}TargetSource"(HotSwappableTargetSource, ref("${grailsClass.fullName}Class")) + + "${grailsClass.fullName}Proxy"(ProxyFactoryBean) { + targetSource = ref("${grailsClass.fullName}TargetSource") + proxyInterfaces = [proxyClass] + } + "${grailsClass.fullName}"("${grailsClass.fullName}Proxy": "newInstance") {bean -> + bean.singleton = singleton + bean.autowire = "byName" + } + + } + + def doWithWebDescriptor = {webXml -> + + def basedir = System.getProperty("base.dir") + def grailsEnv = GrailsUtil.getEnvironment() + + def mappingElement = webXml.'servlet-mapping' + mappingElement + { + 'servlet-mapping' { + 'servlet-name'("grails") + 'url-pattern'("*.dispatch") + } + } + + def filters = webXml.filter + def filterMappings = webXml.'filter-mapping' + + def lastFilter = filters[filters.size() - 1] + def lastFilterMapping = filterMappings[filterMappings.size() - 1] + def charEncodingFilter = filterMappings.find {it.'filter-name'.text() == 'charEncodingFilter'} + + // add the Grails web request filter + lastFilter + { + filter { + 'filter-name'('grailsWebRequest') + 'filter-class'(org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter.getName()) + } + filter { + 'filter-name'('urlMapping') + 'filter-class'(org.codehaus.groovy.grails.web.mapping.filter.UrlMappingsFilter.getName()) + } + if (grailsEnv == "development") { + filter { + 'filter-name'('reloadFilter') + 'filter-class'(org.codehaus.groovy.grails.web.servlet.filter.GrailsReloadServletFilter.getName()) + } + } + } + def grailsWebRequestFilter = { + 'filter-mapping' { + 'filter-name'('grailsWebRequest') + 'url-pattern'("/*") + } + if (grailsEnv == "development") { 'filter-mapping' { 'filter-name'('reloadFilter') 'url-pattern'("/*") - } - } - } - if(charEncodingFilter) { - charEncodingFilter + grailsWebRequestFilter - } - else { - lastFilterMapping + grailsWebRequestFilter - } - filterMappings = webXml.'filter-mapping' - lastFilterMapping = filterMappings[filterMappings.size()-1] - - lastFilterMapping + { - 'filter-mapping' { - 'filter-name'('urlMapping') - 'url-pattern'("/*") - } - } - // if we're in development environment first add a the reload filter - // to the web.xml by finding the last filter and appending it after - if(grailsEnv == "development") { - // now find the GSP servlet and allow viewing generated source in - // development mode - def gspServlet = webXml.servlet.find { it.'servlet-name'?.text() == 'gsp' } - gspServlet.'servlet-class' + { - 'init-param' { - description """ + } + } + } + if (charEncodingFilter) { + charEncodingFilter + grailsWebRequestFilter + } + else { + lastFilterMapping + grailsWebRequestFilter + } + filterMappings = webXml.'filter-mapping' + lastFilterMapping = filterMappings[filterMappings.size() - 1] + + lastFilterMapping + { + 'filter-mapping' { + 'filter-name'('urlMapping') + 'url-pattern'("/*") + } + } + // if we're in development environment first add a the reload filter + // to the web.xml by finding the last filter and appending it after + if (grailsEnv == "development") { + // now find the GSP servlet and allow viewing generated source in + // development mode + def gspServlet = webXml.servlet.find {it.'servlet-name'?.text() == 'gsp'} + gspServlet.'servlet-class' + { + 'init-param' { + description """ Allows developers to view the intermediade source code, when they pass a spillGroovy argument in the URL. """ - 'param-name'('showSource') - 'param-value'(1) - } - } - } + 'param-name'('showSource') + 'param-value'(1) + } + } + } - } + } - def doWithDynamicMethods = { ApplicationContext ctx -> + def doWithDynamicMethods = {ApplicationContext ctx -> - // add common objects and out variable for tag libraries - def registry = GroovySystem.getMetaClassRegistry() + // add common objects and out variable for tag libraries + def registry = GroovySystem.getMetaClassRegistry() def constructor = new DataBindingDynamicConstructor(ctx) def Closure constructorMapArg = {domainClass, Map params -> - constructor.invoke(domainClass.clazz, [params] as Object[]) + constructor.invoke(domainClass.clazz, [params] as Object[]) } def consructorNoArgs = {domainClass -> constructor.invoke(domainClass.clazz, [] as Object[]) - } - for(domainClass in application.domainClasses) { + } + for (domainClass in application.domainClasses) { def mc = domainClass.metaClass mc.constructor = consructorNoArgs.curry(domainClass) mc.constructor = constructorMapArg.curry(domainClass) def setProps = new SetPropertiesDynamicProperty() - mc.setProperties = { Object o -> + mc.setProperties = {Object o -> setProps.set(delegate, o) } - //mc.getProperties = {-> org.codehaus.groovy.runtime.DefaultGroovyMethods.getProperties(delegate) } + //mc.getProperties = {-> org.codehaus.groovy.runtime.DefaultGroovyMethods.getProperties(delegate) } } def namespaces = [] as HashSet - for(taglib in application.tagLibClasses) { - MetaClass mc = taglib.metaClass - String namespace = taglib.namespace + for (taglib in application.tagLibClasses) { + MetaClass mc = taglib.metaClass + String namespace = taglib.namespace namespaces << namespace - WebMetaUtils.registerCommonWebProperties(mc, application) - - mc.throwTagError = { String message -> - throw new org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException(message) - } - mc.getPluginContextPath = {-> - PluginMetaManager metaManager = ctx.pluginMetaManager - String path = metaManager.getPluginPathForResource(delegate.class.name) - path ? path : "" - } - - mc.getPageScope = {-> - def request = RCH.currentRequestAttributes().currentRequest - def binding = request[GrailsApplicationAttributes.PAGE_SCOPE] - if(!binding) { - binding = new Binding() - request[GrailsApplicationAttributes.PAGE_SCOPE] = binding - } - binding - } - - mc.getOut = {-> - RCH.currentRequestAttributes().out - } - mc.setOut = { Writer newOut -> - RCH.currentRequestAttributes().out = newOut - } - mc.getProperty = { String name -> + WebMetaUtils.registerCommonWebProperties(mc, application) + + mc.throwTagError = {String message -> + throw new org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException(message) + } + mc.getPluginContextPath = {-> + PluginMetaManager metaManager = ctx.pluginMetaManager + String path = metaManager.getPluginPathForResource(delegate.class.name) + path ? path : "" + } + + mc.getPageScope = {-> + def request = RCH.currentRequestAttributes().currentRequest + def binding = request[GrailsApplicationAttributes.PAGE_SCOPE] + if (!binding) { + binding = new Binding() + request[GrailsApplicationAttributes.PAGE_SCOPE] = binding + } + binding + } + + mc.getOut = {-> + RCH.currentRequestAttributes().out + } + mc.setOut = {Writer newOut -> + RCH.currentRequestAttributes().out = newOut + } + mc.getProperty = {String name -> MetaProperty metaProperty = mc.getMetaProperty(name) def result - if(metaProperty) result = metaProperty.getProperty(delegate) + if (metaProperty) result = metaProperty.getProperty(delegate) else { def ns = namespace ? namespace : GroovyPage.DEFAULT_NAMESPACE def tagName = "${ns}:$name" GrailsClass tagLibraryClass = application.getArtefactForFeature( - TagLibArtefactHandler.TYPE, tagName.toString()) + TagLibArtefactHandler.TYPE, tagName.toString()) - if(tagLibraryClass) { + if (tagLibraryClass) { def tagLibrary = ctx.getBean(tagLibraryClass.fullName) result = tagLibrary."$name".clone() - mc."${GCU.getGetterName(name)}" = {-> result } + mc."${GCU.getGetterName(name)}" = {-> result} } else { // try obtaining reference to tag lib via namespacing tagLibraryClass = application.getArtefactForFeature(TagLibArtefactHandler.TYPE, name) - if(tagLibraryClass) { - result = new NamespacedTagDispatcher(tagLibraryClass.namespace,delegate.class, application, ctx) - mc."${GCU.getGetterName(name)}" = {-> result } + if (tagLibraryClass) { + result = new NamespacedTagDispatcher(tagLibraryClass.namespace, delegate.class, application, ctx) + mc."${GCU.getGetterName(name)}" = {-> result} } else { throw new MissingPropertyException(name, delegate.class) @@ -344,43 +347,43 @@ class ControllersGrailsPlugin { } result } - mc.invokeMethod = { String name, args -> + mc.invokeMethod = {String name, args -> args = args == null ? [] as Object[] : args def metaMethod - synchronized(mc) { + synchronized (mc) { metaMethod = mc.getMetaMethod(name, args) } def result - if(metaMethod) result = metaMethod.invoke(delegate, args) - else { + if (metaMethod) result = metaMethod.invoke(delegate, args) + else { def ns = namespace ? namespace : GroovyPage.DEFAULT_NAMESPACE def tagName = "${ns}:$name" GrailsClass tagLibraryClass = application.getArtefactForFeature( - TagLibArtefactHandler.TYPE, tagName.toString()) + TagLibArtefactHandler.TYPE, tagName.toString()) - if(!tagLibraryClass) { + if (!tagLibraryClass) { tagName = "${GroovyPage.DEFAULT_NAMESPACE}:$name" tagLibraryClass = application.getArtefactForFeature(TagLibArtefactHandler.TYPE, tagName.toString()) } - if(tagLibraryClass) { - synchronized(mc) { - WebMetaUtils.registerMethodMissingForTags(mc, ctx, tagLibraryClass, name) - } + if (tagLibraryClass) { + synchronized (mc) { + WebMetaUtils.registerMethodMissingForTags(mc, ctx, tagLibraryClass, name) + } } - if(mc.respondsTo(delegate,name, args)) { + if (mc.respondsTo(delegate, name, args)) { result = mc.invokeMethod(delegate, name, args) } else { // deal with the case where there is a closure property that could be invoked MetaProperty metaProperty = mc.getMetaProperty(name) def callable = metaProperty?.getProperty(delegate) - if(callable instanceof Closure) { - mc."$name" = { Object[] varArgs -> - varArgs ? callable.call(*varArgs) : callable.call() + if (callable instanceof Closure) { + mc."$name" = {Object[] varArgs -> + varArgs ? callable.call(* varArgs) : callable.call() } - result = args ? callable.call(*args) : callable.call() + result = args ? callable.call(* args) : callable.call() } else { throw new MissingMethodException(name, delegate.class, args) @@ -390,79 +393,79 @@ class ControllersGrailsPlugin { result } ctx.getBean(taglib.fullName).metaClass = mc - } - def bind = new BindDynamicMethod() - // add commons objects and dynamic methods like render and redirect to controllers - for(GrailsClass controller in application.controllerClasses ) { - MetaClass mc = controller.metaClass - - Class controllerClass = controller.clazz - WebMetaUtils.registerCommonWebProperties(mc, application) - registerControllerMethods(mc, ctx) - registerMethodMissing(mc, application, ctx) + } + def bind = new BindDynamicMethod() + // add commons objects and dynamic methods like render and redirect to controllers + for (GrailsClass controller in application.controllerClasses) { + MetaClass mc = controller.metaClass + + Class controllerClass = controller.clazz + WebMetaUtils.registerCommonWebProperties(mc, application) + registerControllerMethods(mc, ctx) + registerMethodMissing(mc, application, ctx) Class superClass = controller.clazz.superclass - for(ns in namespaces) { + for (ns in namespaces) { def propName = GCU.getGetterName(ns) - if(!controller.hasProperty(propName)) { + if (!controller.hasProperty(propName)) { def namespaceDispatcher = new NamespacedTagDispatcher(ns, controllerClass, application, ctx) - mc."$propName" = {-> namespaceDispatcher } + mc."$propName" = {-> namespaceDispatcher} } } - + mc.getPluginContextPath = {-> - PluginMetaManager metaManager = ctx.pluginMetaManager - String path = metaManager.getPluginPathForResource(delegate.class.name) - path ? path : "" + PluginMetaManager metaManager = ctx.pluginMetaManager + String path = metaManager.getPluginPathForResource(delegate.class.name) + path ? path : "" } // deal with abstract super classes - while(superClass != Object.class) { - if(Modifier.isAbstract(superClass.getModifiers())) { + while (superClass != Object.class) { + if (Modifier.isAbstract(superClass.getModifiers())) { WebMetaUtils.registerCommonWebProperties(superClass.metaClass, application) registerControllerMethods(superClass.metaClass, ctx) - registerMethodMissing(superClass.metaClass, application, ctx) + registerMethodMissing(superClass.metaClass, application, ctx) } superClass = superClass.superclass - } + } // look for actions that accept command objects and override // each of the actions to make command objects binding before executing - for(actionName in controller.commandObjectActions) { + for (actionName in controller.commandObjectActions) { def originalAction = controller.getPropertyValue(actionName) def paramTypes = originalAction.getParameterTypes() def closureName = actionName - def commandObjectBindingAction = { Object[] varArgs -> + def commandObjectBindingAction = {Object[] varArgs -> def commandObjects = [] - for( v in varArgs) { + for (v in varArgs) { commandObjects << v } def counter = 0 - for( paramType in paramTypes ) { + for (paramType in paramTypes) { - if(GroovyObject.class.isAssignableFrom(paramType)) { + if (GroovyObject.class.isAssignableFrom(paramType)) { try { def commandObject; - if(counter < commandObjects.size()) { - if(paramType.isInstance(commandObjects[counter])) { + if (counter < commandObjects.size()) { + if (paramType.isInstance(commandObjects[counter])) { commandObject = commandObjects[counter] } } - if(!commandObject) { + if (!commandObject) { commandObject = paramType.newInstance() commandObjects << commandObject } def params = RCH.currentRequestAttributes().params - bind.invoke(commandObject,"bindData",[commandObject, params] as Object[]) + bind.invoke(commandObject, "bindData", [commandObject, params] as Object[]) def errors = new BindException(commandObject, paramType.name) def constrainedProperties = commandObject.constraints?.values() - constrainedProperties.each { constrainedProperty -> + constrainedProperties.each {constrainedProperty -> constrainedProperty.messageSource = ctx.getBean("messageSource") - constrainedProperty.validate(commandObject, commandObject.getProperty( constrainedProperty.getPropertyName() ),errors); + constrainedProperty.validate(commandObject, commandObject.getProperty(constrainedProperty.getPropertyName()), errors); } commandObject.errors = errors } catch (Exception e) { @@ -471,91 +474,90 @@ class ControllersGrailsPlugin { } counter++ } - GCU.getPropertyOrStaticPropertyOrFieldValue(delegate, closureName).call(*commandObjects) + GCU.getPropertyOrStaticPropertyOrFieldValue(delegate, closureName).call(* commandObjects) } - mc."${GrailsClassUtils.getGetterName(actionName)}" = { -> - commandObjectBindingAction.delegate = delegate - commandObjectBindingAction + mc."${GrailsClassUtils.getGetterName(actionName)}" = {-> + commandObjectBindingAction.delegate = delegate + commandObjectBindingAction } } - // look for actions that accept command objects and configure - // each of the command object types - def commandObjectClasses = controller.commandObjectClasses - commandObjectClasses.each { commandObjectClass -> - def commandObject = commandObjectClass.newInstance() - def commandObjectMetaClass = commandObject.metaClass - commandObjectMetaClass.setErrors = { Errors errors -> - RCH.currentRequestAttributes().setAttribute( "${commandObjectClass.name}_errors", errors, 0) - } - commandObjectMetaClass.getErrors = {-> - RCH.currentRequestAttributes().getAttribute( "${commandObjectClass.name}_errors", 0) - } - - commandObjectMetaClass.hasErrors = {-> - errors?.hasErrors() ? true : false - } - def validationClosure = GCU.getStaticPropertyValue(commandObjectClass, 'constraints') - if(validationClosure) { - def constrainedPropertyBuilder = new ConstrainedPropertyBuilder(commandObject) - validationClosure.setDelegate(constrainedPropertyBuilder) - validationClosure() - commandObjectMetaClass.constraints = constrainedPropertyBuilder.constrainedProperties - } else { - commandObjectMetaClass.constraints = [:] - } - } - } - - } + // look for actions that accept command objects and configure + // each of the command object types + def commandObjectClasses = controller.commandObjectClasses + commandObjectClasses.each {commandObjectClass -> + def commandObject = commandObjectClass.newInstance() + def commandObjectMetaClass = commandObject.metaClass + commandObjectMetaClass.setErrors = {Errors errors -> + RCH.currentRequestAttributes().setAttribute("${commandObjectClass.name}_errors", errors, 0) + } + commandObjectMetaClass.getErrors = {-> + RCH.currentRequestAttributes().getAttribute("${commandObjectClass.name}_errors", 0) + } + + commandObjectMetaClass.hasErrors = {-> + errors?.hasErrors() ? true : false + } + def validationClosure = GCU.getStaticPropertyValue(commandObjectClass, 'constraints') + if (validationClosure) { + def constrainedPropertyBuilder = new ConstrainedPropertyBuilder(commandObject) + validationClosure.setDelegate(constrainedPropertyBuilder) + validationClosure() + commandObjectMetaClass.constraints = constrainedPropertyBuilder.constrainedProperties + } else { + commandObjectMetaClass.constraints = [:] + } + } + } + + } def registerMethodMissing(MetaClass mc, GrailsApplication application, ApplicationContext ctx) { // allow controllers to call tag library methods - mc.methodMissing = { String name, args -> - args = args == null ? [] as Object[] : args + mc.methodMissing = {String name, args -> + args = args == null ? [] as Object[] : args def tagName = "${GroovyPage.DEFAULT_NAMESPACE}:$name" GrailsClass tagLibraryClass = application.getArtefactForFeature( - TagLibArtefactHandler.TYPE, tagName.toString()) + TagLibArtefactHandler.TYPE, tagName.toString()) def result - if(tagLibraryClass) { - synchronized(mc) { + if (tagLibraryClass) { + synchronized (mc) { WebMetaUtils.registerMethodMissingForTags(mc, ctx, tagLibraryClass, name) } result = mc.invokeMethod(delegate, name, args) } else { - throw new MissingMethodException(name, delegate.class, args) + throw new MissingMethodException(name, delegate.class, args) } result } - } def registerControllerMethods(MetaClass mc, ApplicationContext ctx) { - mc.getActionUri = {-> "/$controllerName/$actionName".toString() } - mc.getControllerUri = {-> "/$controllerName".toString() } - mc.getTemplateUri = { String name -> + mc.getActionUri = {-> "/$controllerName/$actionName".toString()} + mc.getControllerUri = {-> "/$controllerName".toString()} + mc.getTemplateUri = {String name -> def webRequest = RCH.currentRequestAttributes() webRequest.attributes.getTemplateUri(name, webRequest.currentRequest) } - mc.getViewUri = { String name -> + mc.getViewUri = {String name -> def webRequest = RCH.currentRequestAttributes() webRequest.attributes.getViewUri(name, webRequest.currentRequest) } - mc.setErrors = { Errors errors -> - RCH.currentRequestAttributes().setAttribute( GrailsApplicationAttributes.ERRORS, errors, 0) + mc.setErrors = {Errors errors -> + RCH.currentRequestAttributes().setAttribute(GrailsApplicationAttributes.ERRORS, errors, 0) } mc.getErrors = {-> - RCH.currentRequestAttributes().getAttribute(GrailsApplicationAttributes.ERRORS, 0) + RCH.currentRequestAttributes().getAttribute(GrailsApplicationAttributes.ERRORS, 0) } - mc.setModelAndView = { ModelAndView mav -> - RCH.currentRequestAttributes().setAttribute( GrailsApplicationAttributes.MODEL_AND_VIEW, mav, 0) + mc.setModelAndView = {ModelAndView mav -> + RCH.currentRequestAttributes().setAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW, mav, 0) } mc.getModelAndView = {-> - RCH.currentRequestAttributes().getAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW, 0) + RCH.currentRequestAttributes().getAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW, 0) } mc.getChainModel = {-> RCH.currentRequestAttributes().flashScope["chainModel"] @@ -569,104 +571,104 @@ class ControllersGrailsPlugin { def render = new RenderDynamicMethod() def bind = new BindDynamicMethod() // the redirect dynamic method - mc.redirect = { Map args -> - redirect.invoke(delegate,"redirect",args) + mc.redirect = {Map args -> + redirect.invoke(delegate, "redirect", args) } - mc.chain = { Map args -> - chain.invoke(delegate, "chain",args) + mc.chain = {Map args -> + chain.invoke(delegate, "chain", args) } // the render method - mc.render = { Object o -> - render.invoke(delegate, "render",[o?.inspect()] as Object[]) + mc.render = {Object o -> + render.invoke(delegate, "render", [o?.inspect()] as Object[]) } - mc.render = { String txt -> - render.invoke(delegate, "render",[txt] as Object[]) + mc.render = {String txt -> + render.invoke(delegate, "render", [txt] as Object[]) } - mc.render = { Map args -> - render.invoke(delegate, "render",[args] as Object[]) + mc.render = {Map args -> + render.invoke(delegate, "render", [args] as Object[]) } - mc.render = { Closure c -> - render.invoke(delegate,"render", [c] as Object[]) + mc.render = {Closure c -> + render.invoke(delegate, "render", [c] as Object[]) } - mc.render = { Map args, Closure c -> - render.invoke(delegate,"render", [args, c] as Object[]) + mc.render = {Map args, Closure c -> + render.invoke(delegate, "render", [args, c] as Object[]) } // the bindData method - mc.bindData = { Object target, Object args -> + mc.bindData = {Object target, Object args -> bind.invoke(delegate, "bindData", [target, args] as Object[]) } - mc.bindData = { Object target, Object args, List disallowed -> - bind.invoke(delegate, "bindData", [target, args, [exclude:disallowed]] as Object[]) + mc.bindData = {Object target, Object args, List disallowed -> + bind.invoke(delegate, "bindData", [target, args, [exclude: disallowed]] as Object[]) } - mc.bindData = { Object target, Object args, List disallowed, String filter -> - bind.invoke(delegate, "bindData", [target, args, [exclude:disallowed] , filter] as Object[]) + mc.bindData = {Object target, Object args, List disallowed, String filter -> + bind.invoke(delegate, "bindData", [target, args, [exclude: disallowed], filter] as Object[]) } - mc.bindData = { Object target, Object args, Map includeExclude -> + mc.bindData = {Object target, Object args, Map includeExclude -> bind.invoke(delegate, "bindData", [target, args, includeExclude] as Object[]) } - mc.bindData = { Object target, Object args, Map includeExclude, String filter -> - bind.invoke(delegate, "bindData", [target, args, includeExclude , filter] as Object[]) + mc.bindData = {Object target, Object args, Map includeExclude, String filter -> + bind.invoke(delegate, "bindData", [target, args, includeExclude, filter] as Object[]) } - mc.bindData = { Object target, Object args, String filter -> + mc.bindData = {Object target, Object args, String filter -> bind.invoke(delegate, "bindData", [target, args, filter] as Object[]) } } - def onChange = { event -> - if(application.isArtefactOfType(ControllerArtefactHandler.TYPE, event.source)) { - def context = event.ctx - if(!context) { - if(log.isDebugEnabled()) - log.debug("Application context not found. Can't reload") - return - } - boolean isNew = application.getControllerClass(event.source?.name) ? false : true - def controllerClass = application.addArtefact(ControllerArtefactHandler.TYPE, event.source) - - - - if(isNew) { - log.info "Controller ${event.source} added. Configuring.." - // we can create the bean definitions from the oroginal configureAOPProxyBean closure - // by currying it, which populates the values within the curried closure - // once that is done we pass it to the "beans" method which will return a BeanBuilder - def beanConfigs = configureAOPProxyBean.curry(controllerClass, - ControllerArtefactHandler.TYPE, - org.codehaus.groovy.grails.commons.GrailsControllerClass.class, - false) - def beanDefinitions = beans(beanConfigs) - // now that we have a BeanBuilder calling registerBeans and passing the app ctx will - // register the necessary beans with the given app ctx - beanDefinitions.registerBeans(event.ctx) - - } - else { - if(log.isDebugEnabled()) - log.debug("Controller ${event.source} changed. Reloading...") - - def controllerTargetSource = context.getBean("${controllerClass.fullName}TargetSource") - controllerTargetSource.swap(controllerClass) - } - - } - else if(application.isArtefactOfType(TagLibArtefactHandler.TYPE, event.source)) { - boolean isNew = application.getTagLibClass(event.source?.name) ? false : true - def taglibClass = application.addArtefact(TagLibArtefactHandler.TYPE, event.source) - if(taglibClass) { - // replace tag library bean - def beanName = taglibClass.fullName - def beans = beans { - "$beanName"(taglibClass.getClazz()) { bean -> - bean.autowire = true - } - } - beans.registerBeans(event.ctx) - } - } - - event.manager?.getGrailsPlugin("controllers")?.doWithDynamicMethods(event.ctx) - } + def onChange = {event -> + if (application.isArtefactOfType(ControllerArtefactHandler.TYPE, event.source)) { + def context = event.ctx + if (!context) { + if (log.isDebugEnabled()) + log.debug("Application context not found. Can't reload") + return + } + boolean isNew = application.getControllerClass(event.source?.name) ? false : true + def controllerClass = application.addArtefact(ControllerArtefactHandler.TYPE, event.source) + + + + if (isNew) { + log.info "Controller ${event.source} added. Configuring.." + // we can create the bean definitions from the oroginal configureAOPProxyBean closure + // by currying it, which populates the values within the curried closure + // once that is done we pass it to the "beans" method which will return a BeanBuilder + def beanConfigs = configureAOPProxyBean.curry(controllerClass, + ControllerArtefactHandler.TYPE, + org.codehaus.groovy.grails.commons.GrailsControllerClass.class, + false) + def beanDefinitions = beans(beanConfigs) + // now that we have a BeanBuilder calling registerBeans and passing the app ctx will + // register the necessary beans with the given app ctx + beanDefinitions.registerBeans(event.ctx) + + } + else { + if (log.isDebugEnabled()) + log.debug("Controller ${event.source} changed. Reloading...") + + def controllerTargetSource = context.getBean("${controllerClass.fullName}TargetSource") + controllerTargetSource.swap(controllerClass) + } + + } + else if (application.isArtefactOfType(TagLibArtefactHandler.TYPE, event.source)) { + boolean isNew = application.getTagLibClass(event.source?.name) ? false : true + def taglibClass = application.addArtefact(TagLibArtefactHandler.TYPE, event.source) + if (taglibClass) { + // replace tag library bean + def beanName = taglibClass.fullName + def beans = beans { + "$beanName"(taglibClass.getClazz()) {bean -> + bean.autowire = true + } + } + beans.registerBeans(event.ctx) + } + } + + event.manager?.getGrailsPlugin("controllers")?.doWithDynamicMethods(event.ctx) + } } \ No newline at end of file diff --git a/test/groovy/org/codehaus/groovy/grails/plugins/web/ControllersGrailsPluginTests.groovy b/test/groovy/org/codehaus/groovy/grails/plugins/web/ControllersGrailsPluginTests.groovy index 9aa160d4718..fc6b6c56c22 100644 --- a/test/groovy/org/codehaus/groovy/grails/plugins/web/ControllersGrailsPluginTests.groovy +++ b/test/groovy/org/codehaus/groovy/grails/plugins/web/ControllersGrailsPluginTests.groovy @@ -5,6 +5,8 @@ import org.codehaus.groovy.grails.commons.* import org.codehaus.groovy.grails.commons.spring.* import org.codehaus.groovy.grails.plugins.* import org.codehaus.groovy.grails.web.plugins.* +import grails.spring.BeanBuilder +import org.springframework.core.io.FileSystemResource class ControllersGrailsPluginTests extends AbstractGrailsPluginTests { @@ -59,6 +61,47 @@ class TestController { assertNull(bean.address) } + void testBeansWhenNotWarDeployedAndDevelopmentEnv() { + try { + System.setProperty("grails.env", "development") + def mock = [application: [config: new ConfigObject(), warDeployed: false]] + def plugin = new ControllersGrailsPlugin() + def beans = plugin.doWithSpring + def bb = new BeanBuilder() + bb.setBinding(new Binding(mock)) + bb.beans(beans) + def beanDef = bb.getBeanDefinition('groovyPageResourceLoader') + assertEquals "org.codehaus.groovy.grails.web.pages.GroovyPageResourceLoader", beanDef.beanClassName + assertNotNull beanDef.getPropertyValues().getPropertyValue('baseResource') + + assertEquals new FileSystemResource("."), beanDef.getPropertyValues().getPropertyValue('baseResource').getValue() + + beanDef = bb.getBeanDefinition("groovyPagesTemplateEngine") + assertEquals "groovyPageResourceLoader", beanDef.getPropertyValues().getPropertyValue("resourceLoader").getValue()?.beanName + + beanDef = bb.getBeanDefinition("jspViewResolver") + assertEquals "groovyPageResourceLoader", beanDef.getPropertyValues().getPropertyValue("resourceLoader").getValue()?.beanName + + } finally { + System.setProperty("grails.env", "") + } + } + + void testBeansWhenWarDeployedAndDevelopmentEnv() { + try { + System.setProperty("grails.env", "development") + def mock = [application: [config: new ConfigObject(), warDeployed: true]] + def plugin = new ControllersGrailsPlugin() + def beans = plugin.doWithSpring + def bb = new BeanBuilder() + bb.setBinding(new Binding(mock)) + bb.beans(beans) + assertNull bb.getBeanDefinition('groovyPageResourceLoader') + } finally { + System.setProperty("grails.env", "") + } + } + Class parseTestBean(){ return gcl.parseClass( """ @@ -70,4 +113,4 @@ class TestController { """) } -} \ No newline at end of file +}