From bf5e7695e0a92d2bdf46aa8186755cd335c41ea4 Mon Sep 17 00:00:00 2001 From: Graeme Rocher Date: Thu, 18 Dec 2014 17:43:35 +0100 Subject: [PATCH] Get rid of TagLibraryApi, ControllersApi and CommonWebApi in favour of traits --- .../plugins/web/api/CommonWebApi.groovy | 17 -- .../plugins/web/api/ControllersApi.groovy | 20 -- .../grails/plugins/BinaryGrailsPlugin.java | 5 +- ...ailsConventionGroovyPageLocatorSpec.groovy | 3 +- .../groovy/grails/artefact/Controller.groovy | 11 +- .../web/controllers/api/ControllersApi.java | 161 ----------- .../web/GroovyPagesGrailsPlugin.groovy | 5 - .../web/taglib/ApplicationTagLib.groovy | 7 +- .../plugins/web/taglib/CountryTagLib.groovy | 8 +- .../plugins/web/taglib/FormTagLib.groovy | 7 +- .../plugins/web/taglib/FormatTagLib.groovy | 7 +- .../web/taglib/JavascriptTagLib.groovy | 7 +- .../plugins/web/taglib/PluginTagLib.groovy | 9 +- .../web/taglib/UrlMappingTagLib.groovy | 11 +- .../web/taglib/ValidationTagLib.groovy | 7 +- ...JavascriptLibraryHandlerInterceptor.groovy | 58 ++++ .../JavascriptLibraryHandlerInterceptor.java | 63 ----- .../mixin/web/GroovyPageUnitTestMixin.groovy | 24 +- .../test/mixin/AnotherController.groovy | 129 +++++++++ ...nhancedControllerUnitTestMixinTests.groovy | 101 +------ .../mixin/ControllerUnitTestMixinTests.groovy | 4 +- .../mixin/TagLibraryInvokeBodySpec.groovy | 6 +- .../taglib/TagLibraryTransformerSpec.groovy | 2 +- .../grails/web/api}/ServletAttributes.groovy | 9 +- .../grails/web/api/WebAttributes.groovy | 10 +- .../org/grails/web/api/CommonWebApi.java | 263 ------------------ .../plugins/web/taglib/RenderTagLib.groovy | 6 +- .../plugins/web/taglib/SitemeshTagLib.groovy | 9 +- .../web/pages/StandaloneTagLibraryLookup.java | 8 +- .../groovy/grails/artefact/TagLibrary.groovy | 72 +++-- .../artefact/gsp/TagLibraryInvoker.groovy | 43 ++- .../web/taglib/TagLibraryTransformer.java | 45 +-- .../grails/plugins/web/api/TagLibraryApi.java | 112 -------- .../taglib/util/TagLibraryMetaUtils.groovy | 5 + .../web/taglib/TagLibraryLookupSpec.groovy | 8 +- 35 files changed, 377 insertions(+), 885 deletions(-) delete mode 100644 grails-compat/src/main/groovy/org/codehaus/groovy/grails/plugins/web/api/CommonWebApi.groovy delete mode 100644 grails-compat/src/main/groovy/org/codehaus/groovy/grails/plugins/web/api/ControllersApi.groovy delete mode 100644 grails-plugin-controllers/src/main/groovy/org/grails/plugins/web/controllers/api/ControllersApi.java create mode 100644 grails-plugin-gsp/src/main/groovy/org/grails/web/filters/JavascriptLibraryHandlerInterceptor.groovy delete mode 100644 grails-plugin-gsp/src/main/groovy/org/grails/web/filters/JavascriptLibraryHandlerInterceptor.java create mode 100644 grails-test-suite-uber/src/test/groovy/grails/test/mixin/AnotherController.groovy rename {grails-plugin-controllers/src/main/groovy/grails/artefact/controller => grails-web-common/src/main/groovy/grails/web/api}/ServletAttributes.groovy (90%) delete mode 100644 grails-web-common/src/main/groovy/org/grails/web/api/CommonWebApi.java rename {grails-plugin-gsp/src/ast => grails-web-taglib/src/main}/groovy/grails/artefact/gsp/TagLibraryInvoker.groovy (73%) delete mode 100644 grails-web-taglib/src/main/groovy/org/grails/plugins/web/api/TagLibraryApi.java diff --git a/grails-compat/src/main/groovy/org/codehaus/groovy/grails/plugins/web/api/CommonWebApi.groovy b/grails-compat/src/main/groovy/org/codehaus/groovy/grails/plugins/web/api/CommonWebApi.groovy deleted file mode 100644 index 39914a70867..00000000000 --- a/grails-compat/src/main/groovy/org/codehaus/groovy/grails/plugins/web/api/CommonWebApi.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package org.codehaus.groovy.grails.plugins.web.api - -import grails.plugins.GrailsPluginManager - -/** - * @deprecated Use {@link org.grails.web.api.CommonWebApi} instead - */ -@Deprecated -class CommonWebApi extends org.grails.web.api.CommonWebApi { - - CommonWebApi(GrailsPluginManager pluginManager) { - super(pluginManager) - } - - CommonWebApi() { - } -} diff --git a/grails-compat/src/main/groovy/org/codehaus/groovy/grails/plugins/web/api/ControllersApi.groovy b/grails-compat/src/main/groovy/org/codehaus/groovy/grails/plugins/web/api/ControllersApi.groovy deleted file mode 100644 index 7ffa932df1a..00000000000 --- a/grails-compat/src/main/groovy/org/codehaus/groovy/grails/plugins/web/api/ControllersApi.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package org.codehaus.groovy.grails.plugins.web.api - -import grails.plugins.GrailsPluginManager -import groovy.transform.CompileStatic - -/** - * @author Graeme Rocher - * @deprecated Use {@link grails.artefact.Controller} instead - */ -@Deprecated -@CompileStatic -class ControllersApi extends org.grails.plugins.web.controllers.api.ControllersApi { - - ControllersApi() { - } - - ControllersApi(GrailsPluginManager pluginManager) { - super(pluginManager) - } -} diff --git a/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPlugin.java b/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPlugin.java index 5b5d5ade8a6..a8a88b7fd1b 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPlugin.java +++ b/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPlugin.java @@ -15,6 +15,7 @@ */ package org.grails.plugins; +import grails.plugins.exceptions.PluginException; import groovy.util.slurpersupport.GPathResult; import groovy.util.slurpersupport.Node; @@ -128,8 +129,8 @@ protected void initializeProvidedArtefacts(GPathResult descriptor) { final String className = ((Node)i.next()).text(); try { artefacts.add(classLoader.loadClass(className)); - } catch (ClassNotFoundException e) { - LOG.error("Class not found loading plugin resource [" + className + "]. Resource skipped.", e); + } catch (Throwable e) { + throw new PluginException("Failed to initialize class ["+className+"] from plugin ["+ getName()+ "] : " + e.getMessage(), e); } } } diff --git a/grails-gsp/src/test/groovy/org/grails/gsp/io/GrailsConventionGroovyPageLocatorSpec.groovy b/grails-gsp/src/test/groovy/org/grails/gsp/io/GrailsConventionGroovyPageLocatorSpec.groovy index f37bc284ad7..d36a1a4c6c9 100644 --- a/grails-gsp/src/test/groovy/org/grails/gsp/io/GrailsConventionGroovyPageLocatorSpec.groovy +++ b/grails-gsp/src/test/groovy/org/grails/gsp/io/GrailsConventionGroovyPageLocatorSpec.groovy @@ -203,7 +203,7 @@ class GrailsConventionGroovyPageLocatorSpec extends Specification { TestBinaryGrailsPlugin - org.codehaus.groovy.grails.plugins.TestBinaryResource + org.grails.gsp.io.TestBinaryResource ''' @@ -236,6 +236,7 @@ class GrailsConventionGroovyPageLocatorSpec extends Specification { class TestBinaryGrailsPlugin { def version = 1.0 } +class TestBinaryResource {} class TestController {} diff --git a/grails-plugin-controllers/src/main/groovy/grails/artefact/Controller.groovy b/grails-plugin-controllers/src/main/groovy/grails/artefact/Controller.groovy index 5ede44c219d..463a400e03f 100644 --- a/grails-plugin-controllers/src/main/groovy/grails/artefact/Controller.groovy +++ b/grails-plugin-controllers/src/main/groovy/grails/artefact/Controller.groovy @@ -46,7 +46,7 @@ import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.DEFAULT_ENCODING -import grails.artefact.controller.ServletAttributes +import grails.web.api.ServletAttributes import grails.artefact.controller.support.ResponseRenderer import grails.core.GrailsControllerClass import grails.core.GrailsDomainClassProperty @@ -253,15 +253,6 @@ trait Controller implements ResponseRenderer, DataBinder, WebAttributes, Servlet (Map)getFlash().get("chainModel") } - /** - * Obtains the Grails parameter map - * - * @return The GrailsParameterMap instance - */ - GrailsParameterMap getParams() { - currentRequestAttributes().getParams() - } - /** * Chains from one action to another via an HTTP redirect. The model is retained in the following request in the 'chainModel' property within flash scope. diff --git a/grails-plugin-controllers/src/main/groovy/org/grails/plugins/web/controllers/api/ControllersApi.java b/grails-plugin-controllers/src/main/groovy/org/grails/plugins/web/controllers/api/ControllersApi.java deleted file mode 100644 index 8371daa2839..00000000000 --- a/grails-plugin-controllers/src/main/groovy/org/grails/plugins/web/controllers/api/ControllersApi.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2011 SpringSource - * - * 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 org.grails.plugins.web.controllers.api; - -import grails.core.GrailsControllerClass; -import grails.plugins.GrailsPluginManager; -import grails.util.GrailsClassUtils; -import grails.util.GrailsUtil; -import grails.web.mapping.LinkGenerator; -import grails.web.mapping.ResponseRedirector; -import grails.web.mapping.mvc.RedirectEventListener; -import groovy.lang.Closure; -import groovy.lang.GroovyObject; -import groovy.lang.MissingMethodException; - -import java.util.Collection; -import java.util.Map; - -import org.codehaus.groovy.grails.web.metaclass.ControllerDynamicMethods; -import org.grails.web.api.CommonWebApi; -import org.grails.web.servlet.mvc.GrailsWebRequest; -import org.springframework.context.ApplicationContext; -import org.springframework.validation.Errors; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.servlet.support.RequestDataValueProcessor; -/** - * API for each controller in a Grails application. - * - * @author Graeme Rocher - * @since 2.0 - */ -@SuppressWarnings("rawtypes") -public class ControllersApi extends CommonWebApi { - - private static final long serialVersionUID = 1; - - private Collection redirectListeners; - private LinkGenerator linkGenerator; - private RequestDataValueProcessor requestDataValueProcessor; - private boolean useJessionId = false; - - public ControllersApi() { - this(null); - } - - public ControllersApi(GrailsPluginManager pluginManager) { - super(pluginManager); - } - - public void setRedirectListeners(Collection redirectListeners) { - this.redirectListeners = redirectListeners; - } - - public void setUseJessionId(boolean useJessionId) { - this.useJessionId = useJessionId; - } - - public void setLinkGenerator(LinkGenerator linkGenerator) { - this.linkGenerator = linkGenerator; - } - - /** - * Redirects for the given arguments. - * - * @param argMap The arguments - * @return null - */ - public Object redirect(Object target, Map argMap) { - - if (argMap.isEmpty()) { - throw new MissingMethodException("redirect",target.getClass(),new Object[]{ argMap }); - } - - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes(); - - if(target instanceof GroovyObject) { - GroovyObject controller = (GroovyObject)target; - - // if there are errors add it to the list of errors - Errors controllerErrors = (Errors)controller.getProperty(ControllerDynamicMethods.ERRORS_PROPERTY); - Errors errors = (Errors)argMap.get(ControllerDynamicMethods.ERRORS_PROPERTY); - if (controllerErrors != null && errors != null) { - controllerErrors.addAllErrors(errors); - } - else { - controller.setProperty(ControllerDynamicMethods.ERRORS_PROPERTY, errors); - } - Object action = argMap.get(GrailsControllerClass.ACTION); - if (action != null) { - argMap.put(GrailsControllerClass.ACTION, establishActionName(action,controller)); - } - if (!argMap.containsKey(GrailsControllerClass.NAMESPACE_PROPERTY)) { - // this could be made more efficient if we had a reference to the GrailsControllerClass object, which - // has the namespace property accessible without needing reflection - argMap.put(GrailsControllerClass.NAMESPACE_PROPERTY, GrailsClassUtils.getStaticFieldValue(controller.getClass(), GrailsControllerClass.NAMESPACE_PROPERTY)); - } - } - - ResponseRedirector redirector = new ResponseRedirector(getLinkGenerator(webRequest)); - redirector.setRedirectListeners(redirectListeners); - redirector.setRequestDataValueProcessor(initRequestDataValueProcessor()); - redirector.setUseJessionId(useJessionId); - redirector.redirect(webRequest.getRequest(), webRequest.getResponse(), argMap); - return null; - } - - private LinkGenerator getLinkGenerator(GrailsWebRequest webRequest) { - if (linkGenerator == null) { - ApplicationContext applicationContext = webRequest.getApplicationContext(); - if (applicationContext != null) { - linkGenerator = applicationContext.getBean("grailsLinkGenerator", LinkGenerator.class); - } - } - - return linkGenerator; - } - - /* - * Figures out the action name from the specified action reference (either a string or closure) - */ - private String establishActionName(Object actionRef, Object target) { - String actionName = null; - if (actionRef instanceof String) { - actionName = (String)actionRef; - } - else if (actionRef instanceof CharSequence) { - actionName = actionRef.toString(); - } - else if (actionRef instanceof Closure) { - GrailsUtil.deprecated("Using a closure reference in the 'action' argument of the 'redirect' method is deprecated. Please change to use a String."); - actionName = GrailsClassUtils.findPropertyNameForValue(target, actionRef); - } - return actionName; - } - - /** - * getter to obtain RequestDataValueProcessor from - */ - private RequestDataValueProcessor initRequestDataValueProcessor() { - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes(); - ApplicationContext applicationContext = webRequest.getApplicationContext(); - if (requestDataValueProcessor == null && applicationContext.containsBean("requestDataValueProcessor")) { - requestDataValueProcessor = applicationContext.getBean("requestDataValueProcessor", RequestDataValueProcessor.class); - } - return requestDataValueProcessor; - } - -} diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy index 5d4c2d5ef24..0d0ee770e50 100644 --- a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy +++ b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy @@ -34,7 +34,6 @@ import org.grails.gsp.GroovyPagesTemplateRenderer import org.grails.gsp.io.CachingGrailsConventionGroovyPageLocator import org.grails.gsp.io.CachingGroovyPageStaticResourceLocator import org.grails.gsp.jsp.TagLibraryResolverImpl -import org.grails.plugins.web.api.TagLibraryApi import org.grails.plugins.web.taglib.* import org.grails.spring.RuntimeSpringConfiguration import org.grails.web.errors.ErrorsViewStackTracePrinter @@ -249,7 +248,6 @@ class GroovyPagesGrailsPlugin extends Plugin { } final pluginManager = manager - instanceTagLibraryApi(TagLibraryApi, pluginManager) // Now go through tag libraries and configure them in Spring too. With AOP proxies and so on for (taglib in application.tagLibClasses) { @@ -265,9 +263,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } errorsViewStackTracePrinter(ErrorsViewStackTracePrinter, ref('grailsResourceLocator')) - javascriptLibraryHandlerInterceptor(JavascriptLibraryHandlerInterceptor, application) - filteringCodecsByContentTypeSettings(FilteringCodecsByContentTypeSettings, application) groovyPagesServlet(ServletRegistrationBean, new GroovyPagesServlet(), "*.gsp") { @@ -291,7 +287,6 @@ class GroovyPagesGrailsPlugin extends Plugin { @Override void doWithDynamicMethods() { StreamCharBufferMetaUtils.registerStreamCharBufferMetaClass() - TagLibraryLookup gspTagLibraryLookup = applicationContext.getBean('gspTagLibraryLookup',TagLibraryLookup) for(GrailsClass cls in grailsApplication.getArtefacts(TagLibArtefactHandler.TYPE)) { diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/ApplicationTagLib.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/ApplicationTagLib.groovy index 6577f79652d..b3f19f54e75 100644 --- a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/ApplicationTagLib.groovy +++ b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/ApplicationTagLib.groovy @@ -15,7 +15,8 @@ */ package org.grails.plugins.web.taglib -import grails.artefact.Artefact +import grails.artefact.TagLibrary +import grails.gsp.TagLib import grails.util.GrailsUtil import grails.util.Metadata import groovy.transform.CompileStatic @@ -44,8 +45,8 @@ import javax.servlet.http.HttpServletResponse * * @author Graeme Rocher */ -@Artefact("TagLibrary") -class ApplicationTagLib implements ApplicationContextAware, InitializingBean, GrailsApplicationAware { +@TagLib +class ApplicationTagLib implements ApplicationContextAware, InitializingBean, GrailsApplicationAware, TagLibrary { static returnObjectForTags = ['createLink', 'resource', 'createLinkTo', 'cookie', 'header', 'img', 'join', 'meta', 'set', 'applyCodec'] ApplicationContext applicationContext diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/CountryTagLib.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/CountryTagLib.groovy index 6bcaf496e7d..32bec39a659 100644 --- a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/CountryTagLib.groovy +++ b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/CountryTagLib.groovy @@ -15,7 +15,9 @@ */ package org.grails.plugins.web.taglib -import grails.artefact.Artefact +import grails.artefact.TagLibrary +import grails.gsp.TagLib + /** * Tags for rendering country selection / display of country names. @@ -24,8 +26,8 @@ import grails.artefact.Artefact * * @author Marc Palmer (marc@anyware.co.uk) */ -@Artefact("TagLibrary") -class CountryTagLib { +@TagLib +class CountryTagLib implements TagLibrary { static final ISO3166_3 = [ "afg":"Afghanistan", "alb":"Albania", diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormTagLib.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormTagLib.groovy index 4969d9e0607..77472ae3032 100644 --- a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormTagLib.groovy +++ b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormTagLib.groovy @@ -15,7 +15,8 @@ */ package org.grails.plugins.web.taglib -import grails.artefact.Artefact +import grails.artefact.TagLibrary +import grails.gsp.TagLib import groovy.transform.CompileStatic import java.text.DateFormat @@ -42,8 +43,8 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor * * @author Graeme Rocher */ -@Artefact("TagLibrary") -class FormTagLib implements ApplicationContextAware, InitializingBean { +@TagLib +class FormTagLib implements ApplicationContextAware, InitializingBean, TagLibrary { private static final DEFAULT_CURRENCY_CODES = ['EUR', 'XCD', 'USD', 'XOF', 'NOK', 'AUD', 'XAF', 'NZD', 'MAD', 'DKK', 'GBP', 'CHF', diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormatTagLib.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormatTagLib.groovy index 31f04f90253..7ae3ef8bb21 100644 --- a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormatTagLib.groovy +++ b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormatTagLib.groovy @@ -15,7 +15,8 @@ */ package org.grails.plugins.web.taglib -import grails.artefact.Artefact +import grails.artefact.TagLibrary +import grails.gsp.TagLib import groovy.transform.CompileStatic import java.math.RoundingMode @@ -41,8 +42,8 @@ import org.springframework.util.StringUtils * * @since 0.6 */ -@Artefact("TagLibrary") -class FormatTagLib { +@TagLib +class FormatTagLib implements TagLibrary { static returnObjectForTags = ['formatBoolean','formatDate','formatNumber','encodeAs'] diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/JavascriptTagLib.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/JavascriptTagLib.groovy index 23875885dc5..5a542262c02 100644 --- a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/JavascriptTagLib.groovy +++ b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/JavascriptTagLib.groovy @@ -15,7 +15,8 @@ */ package org.grails.plugins.web.taglib -import grails.artefact.Artefact +import grails.artefact.TagLibrary +import grails.gsp.TagLib import javax.annotation.PostConstruct @@ -32,8 +33,8 @@ import org.springframework.util.ClassUtils * * @author Graeme Rocher */ -@Artefact("TagLibrary") -class JavascriptTagLib implements ApplicationContextAware { +@TagLib +class JavascriptTagLib implements ApplicationContextAware, TagLibrary { ApplicationContext applicationContext /** * Mappings to the relevant files to be included for each library. diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/PluginTagLib.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/PluginTagLib.groovy index 2c34fe1a1c2..a265281dbd6 100644 --- a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/PluginTagLib.groovy +++ b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/PluginTagLib.groovy @@ -15,7 +15,8 @@ */ package org.grails.plugins.web.taglib -import grails.artefact.Artefact +import grails.artefact.TagLibrary +import grails.gsp.TagLib import grails.plugins.GrailsPluginManager /** @@ -24,10 +25,10 @@ import grails.plugins.GrailsPluginManager * @author Graeme Rocher * @since 1.1 */ -@Artefact("TagLibrary") -class PluginTagLib { +@TagLib +class PluginTagLib implements TagLibrary { - static namespace = "plugin" + static String namespace = "plugin" GrailsPluginManager pluginManager diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/UrlMappingTagLib.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/UrlMappingTagLib.groovy index e235c5f54aa..bcf042a0241 100644 --- a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/UrlMappingTagLib.groovy +++ b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/UrlMappingTagLib.groovy @@ -1,8 +1,7 @@ package org.grails.plugins.web.taglib - +import grails.artefact.TagLibrary import grails.gsp.TagLib import grails.web.mapping.UrlMapping -import org.grails.web.util.GrailsApplicationAttributes import grails.web.util.TypeConvertingMap import groovy.transform.CompileStatic import org.codehaus.groovy.grails.web.metaclass.ControllerDynamicMethods @@ -10,10 +9,9 @@ import org.grails.encoder.CodecLookup import org.grails.encoder.Encoder import org.grails.web.mapping.ForwardUrlMappingInfo import org.grails.web.mapping.UrlMappingUtils -import org.grails.web.taglib.TagLibraryLookup import org.grails.web.taglib.TagOutput +import org.grails.web.util.GrailsApplicationAttributes import org.springframework.web.servlet.support.RequestContextUtils - /** * Tag library with tags that integration with the URL mappings API (paginate, include etc.) * @@ -22,9 +20,8 @@ import org.springframework.web.servlet.support.RequestContextUtils */ @CompileStatic @TagLib -class UrlMappingTagLib { +class UrlMappingTagLib implements TagLibrary{ - TagLibraryLookup gspTagLibraryLookup CodecLookup codecLookup /** @@ -327,6 +324,6 @@ class UrlMappingTagLib { } private callLink(Map attrs, Object body) { - TagOutput.captureTagOutput(gspTagLibraryLookup, 'g', 'link', attrs, body, webRequest) + TagOutput.captureTagOutput(tagLibraryLookup, 'g', 'link', attrs, body, webRequest) } } diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/ValidationTagLib.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/ValidationTagLib.groovy index 3c75e328d73..582f2d8bb8a 100644 --- a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/ValidationTagLib.groovy +++ b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/ValidationTagLib.groovy @@ -15,7 +15,8 @@ */ package org.grails.plugins.web.taglib -import grails.artefact.Artefact +import grails.artefact.TagLibrary +import grails.gsp.TagLib import groovy.transform.CompileStatic import groovy.xml.MarkupBuilder @@ -40,8 +41,8 @@ import org.springframework.validation.Errors * * @author Graeme Rocher */ -@Artefact("TagLibrary") -class ValidationTagLib { +@TagLib +class ValidationTagLib implements TagLibrary { static returnObjectForTags = ['message', 'fieldError', 'formatValue'] diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/web/filters/JavascriptLibraryHandlerInterceptor.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/web/filters/JavascriptLibraryHandlerInterceptor.groovy new file mode 100644 index 00000000000..d7535b0bcd0 --- /dev/null +++ b/grails-plugin-gsp/src/main/groovy/org/grails/web/filters/JavascriptLibraryHandlerInterceptor.groovy @@ -0,0 +1,58 @@ +/* + * Copyright 2014 original 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. + */ +package org.grails.web.filters + +import grails.core.GrailsApplication +import groovy.transform.CompileStatic +import groovy.util.logging.Commons +import org.grails.plugins.web.taglib.JavascriptTagLib +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter + +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + + + +/** + * @author Graeme Rocher + * @since 3.0 + */ +@Commons +@CompileStatic +class JavascriptLibraryHandlerInterceptor extends HandlerInterceptorAdapter { + + public static final String JAVA_SCRIPT_LIBRARY = "grails.views.javascript.library" + + protected String library + + public JavascriptLibraryHandlerInterceptor(GrailsApplication application) { + library = application.config.getProperty(JAVA_SCRIPT_LIBRARY) + log.debug "Using [$library] as the default Ajax provider." + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if (library) { + List libraries = (List)request.getAttribute(JavascriptTagLib.INCLUDED_LIBRARIES) + if (libraries == null) { + libraries = new ArrayList(1) + request.setAttribute(JavascriptTagLib.INCLUDED_LIBRARIES, libraries) + } + libraries<< library + } + return true + } +} diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/web/filters/JavascriptLibraryHandlerInterceptor.java b/grails-plugin-gsp/src/main/groovy/org/grails/web/filters/JavascriptLibraryHandlerInterceptor.java deleted file mode 100644 index 91c31b0158c..00000000000 --- a/grails-plugin-gsp/src/main/groovy/org/grails/web/filters/JavascriptLibraryHandlerInterceptor.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2013 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. - */ -package org.grails.web.filters; - -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import grails.core.GrailsApplication; -import org.grails.plugins.web.taglib.JavascriptTagLib; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; - -/** - * Sets up the Javascript library to use based on configuration. - * - * @author Burt Beckwith - * @since 2.3 - */ -public class JavascriptLibraryHandlerInterceptor extends HandlerInterceptorAdapter { - - protected Logger log = LoggerFactory.getLogger(getClass()); - - protected String library; - - public JavascriptLibraryHandlerInterceptor(GrailsApplication application) { - Object lib = application.getFlatConfig().get("grails.views.javascript.library"); - if (lib instanceof CharSequence) { - library = lib.toString(); - log.debug("Using [{}] as the default Ajax provider.", library); - } - } - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - if (library != null) { - @SuppressWarnings("unchecked") - List libraries = (List) request.getAttribute(JavascriptTagLib.INCLUDED_LIBRARIES); - if (libraries == null) { - libraries = new ArrayList(1); - request.setAttribute(JavascriptTagLib.INCLUDED_LIBRARIES, libraries); - } - libraries.add(library); - } - return true; - } -} diff --git a/grails-plugin-testing/src/main/groovy/grails/test/mixin/web/GroovyPageUnitTestMixin.groovy b/grails-plugin-testing/src/main/groovy/grails/test/mixin/web/GroovyPageUnitTestMixin.groovy index 609640cfca2..e7a7ca8bf8d 100644 --- a/grails-plugin-testing/src/main/groovy/grails/test/mixin/web/GroovyPageUnitTestMixin.groovy +++ b/grails-plugin-testing/src/main/groovy/grails/test/mixin/web/GroovyPageUnitTestMixin.groovy @@ -17,13 +17,13 @@ package grails.test.mixin.web import grails.artefact.Enhanced +import grails.artefact.TagLibrary import groovy.text.Template import grails.util.GrailsMetaClassUtils import grails.core.GrailsTagLibClass import org.grails.core.artefact.TagLibArtefactHandler import org.grails.core.metaclass.MetaClassEnhancer -import org.grails.plugins.web.api.TagLibraryApi import org.grails.gsp.GroovyPagesTemplateEngine import org.grails.web.taglib.TagLibraryLookup import org.grails.buffer.GrailsPrintWriter @@ -72,21 +72,6 @@ class GroovyPageUnitTestMixin extends ControllerUnitTestMixin { GrailsTagLibClass tagLib = grailsApplication.addArtefact(TagLibArtefactHandler.TYPE, tagLibClass) final tagLookup = applicationContext.getBean(TagLibraryLookup) - if (!applicationContext.containsBean('instanceTagLibraryApi')) { - defineBeans(true) { - instanceTagLibraryApi(TagLibraryApi) { bean -> - bean.autowire = true - } - } - } - - if (!tagLibClass.getAnnotation(Enhanced)) { - MetaClassEnhancer enhancer = new MetaClassEnhancer() - enhancer.addApi(applicationContext.getBean('instanceTagLibraryApi')) - MetaClass mc = GrailsMetaClassUtils.getMetaClass(tagLib) - enhancer.enhance(mc) - TagLibraryMetaUtils.enhanceTagLibMetaClass(tagLib, tagLookup) - } defineBeans(true) { "${tagLib.fullName}"(tagLibClass) { bean -> @@ -96,7 +81,12 @@ class GroovyPageUnitTestMixin extends ControllerUnitTestMixin { tagLookup.registerTagLib(tagLib) - return applicationContext.getBean(tagLib.fullName) + def taglibObject = applicationContext.getBean(tagLib.fullName) + if(taglibObject instanceof TagLibrary) { + ((TagLibrary)taglibObject).setTagLibraryLookup(tagLookup) + } + + return taglibObject } /** diff --git a/grails-test-suite-uber/src/test/groovy/grails/test/mixin/AnotherController.groovy b/grails-test-suite-uber/src/test/groovy/grails/test/mixin/AnotherController.groovy new file mode 100644 index 00000000000..19282d2f354 --- /dev/null +++ b/grails-test-suite-uber/src/test/groovy/grails/test/mixin/AnotherController.groovy @@ -0,0 +1,129 @@ +package grails.test.mixin + +import grails.artefact.Controller +import grails.converters.JSON +import grails.converters.XML +import grails.web.mime.MimeUtility +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.MessageSource +import org.springframework.web.multipart.MultipartFile + +/* + * Copyright 2014 original 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. + */ + +/** + * @author graemerocher + */ +class AnotherController { + + def handleCommand = { TestCommand test -> + + if (test.hasErrors()) { + render "Bad" + } + else { + render "Good" + } + } + def uploadFile = { + assert request.method == 'POST' + assert request.contentType == "multipart/form-data" + MultipartFile file = request.getFile("myFile") + file.transferTo(new File("/local/disk/myFile")) + } + + def renderTemplateContents = { + def contents = createLink(controller:"foo") + render contents + } + def renderTemplateContentsViaNamespace = { + def contents = g.render(template:"bar") + + render contents + } + def renderText = { + render "good" + } + + def redirectToController = { + redirect(controller:"bar") + } + + def renderView = { + render(view:"foo") + } + + def renderTemplate = { + render(template:"bar") + } + + def renderXml = { + render(contentType:"text/xml") { + book(title:"Great") + } + } + + def renderJson = { + render(contentType:"text/json") { + book = "Great" + } + } + + def renderAsJson = { + render([foo:"bar"] as JSON) + } + + def renderWithFormat = { + def data = [foo:"bar"] + withFormat { + xml { render data as XML } + html data + } + } + + def renderState = { + render(contentType:"text/xml") { + println params.foo + println request.bar + requestInfo { + for (p in params) { + parameter(name:p.key, value:p.value) + } + request.each { + attribute(name:it.key, value:it.value) + } + } + } + } + + MessageSource messageSource + @Autowired + MimeUtility mimeUtility + + def renderMessage() { + assert mimeUtility !=null + assert grailsLinkGenerator != null + render messageSource.getMessage("foo.bar", null, request.locale) + } + + def renderWithForm() { + withForm { + render "Good" + }.invalidToken { + render "Bad" + } + } +} \ No newline at end of file diff --git a/grails-test-suite-uber/src/test/groovy/grails/test/mixin/AstEnhancedControllerUnitTestMixinTests.groovy b/grails-test-suite-uber/src/test/groovy/grails/test/mixin/AstEnhancedControllerUnitTestMixinTests.groovy index 6e5fcfd8e3e..bd37b274b77 100644 --- a/grails-test-suite-uber/src/test/groovy/grails/test/mixin/AstEnhancedControllerUnitTestMixinTests.groovy +++ b/grails-test-suite-uber/src/test/groovy/grails/test/mixin/AstEnhancedControllerUnitTestMixinTests.groovy @@ -1,6 +1,7 @@ package grails.test.mixin import grails.artefact.Artefact +import grails.artefact.Controller import grails.converters.JSON import grails.converters.XML import grails.test.mixin.web.ControllerUnitTestMixin @@ -203,104 +204,4 @@ class AstEnhancedControllerUnitTestMixinTests extends GroovyTestCase{ } } -@Artefact("Controller") -class AnotherController { - def handleCommand = { TestCommand test -> - - if (test.hasErrors()) { - render "Bad" - } - else { - render "Good" - } - } - def uploadFile = { - assert request.method == 'POST' - assert request.contentType == "multipart/form-data" - MultipartFile file = request.getFile("myFile") - file.transferTo(new File("/local/disk/myFile")) - } - - def renderTemplateContents = { - def contents = createLink(controller:"foo") - render contents - } - def renderTemplateContentsViaNamespace = { - def contents = g.render(template:"bar") - - render contents - } - def renderText = { - render "good" - } - - def redirectToController = { - redirect(controller:"bar") - } - - def renderView = { - render(view:"foo") - } - - def renderTemplate = { - render(template:"bar") - } - - def renderXml = { - render(contentType:"text/xml") { - book(title:"Great") - } - } - - def renderJson = { - render(contentType:"text/json") { - book = "Great" - } - } - - def renderAsJson = { - render([foo:"bar"] as JSON) - } - - def renderWithFormat = { - def data = [foo:"bar"] - withFormat { - xml { render data as XML } - html data - } - } - - def renderState = { - render(contentType:"text/xml") { - println params.foo - println request.bar - requestInfo { - for (p in params) { - parameter(name:p.key, value:p.value) - } - request.each { - attribute(name:it.key, value:it.value) - } - } - } - } - - MessageSource messageSource - @Autowired - MimeUtility mimeUtility - - def renderMessage() { - assert mimeUtility !=null - assert grailsLinkGenerator != null - render messageSource.getMessage("foo.bar", null, request.locale) - } - - def renderWithForm() { - withForm { - render "Good" - }.invalidToken { - render "Bad" - } - } -} diff --git a/grails-test-suite-uber/src/test/groovy/grails/test/mixin/ControllerUnitTestMixinTests.groovy b/grails-test-suite-uber/src/test/groovy/grails/test/mixin/ControllerUnitTestMixinTests.groovy index ed839e5f494..35e0957d5ce 100644 --- a/grails-test-suite-uber/src/test/groovy/grails/test/mixin/ControllerUnitTestMixinTests.groovy +++ b/grails-test-suite-uber/src/test/groovy/grails/test/mixin/ControllerUnitTestMixinTests.groovy @@ -1,6 +1,7 @@ package grails.test.mixin import grails.artefact.Artefact +import grails.artefact.Controller import grails.converters.JSON import grails.converters.XML import grails.test.mixin.web.ControllerUnitTestMixin @@ -453,8 +454,7 @@ class ControllerUnitTestMixinTests extends GroovyTestCase { } } -@Artefact("Controller") -class TestController { +class TestController { static allowedMethods = [action2: 'POST', action3: ['POST', 'PUT', 'PATCH'], method2: 'POST', method3: ['POST', 'PUT', 'PATCH']] diff --git a/grails-test-suite-uber/src/test/groovy/grails/test/mixin/TagLibraryInvokeBodySpec.groovy b/grails-test-suite-uber/src/test/groovy/grails/test/mixin/TagLibraryInvokeBodySpec.groovy index 5fb46d15dbd..4911f60fc45 100644 --- a/grails-test-suite-uber/src/test/groovy/grails/test/mixin/TagLibraryInvokeBodySpec.groovy +++ b/grails-test-suite-uber/src/test/groovy/grails/test/mixin/TagLibraryInvokeBodySpec.groovy @@ -1,6 +1,8 @@ package grails.test.mixin import grails.artefact.Artefact +import grails.artefact.TagLibrary +import grails.gsp.TagLib import spock.lang.Specification @TestFor(SimpleTagLib) @@ -20,8 +22,8 @@ class TagLibraryInvokeBodySpec extends Specification { } } -@Artefact("TagLibrary") -class SimpleTagLib { +@TagLib +class SimpleTagLib implements TagLibrary { def output = { attrs, body -> def param = attrs.param out << body(param: param) diff --git a/grails-test-suite-web/src/test/groovy/org/grails/compiler/web/taglib/TagLibraryTransformerSpec.groovy b/grails-test-suite-web/src/test/groovy/org/grails/compiler/web/taglib/TagLibraryTransformerSpec.groovy index 5a3e3835f72..f359ac7c044 100644 --- a/grails-test-suite-web/src/test/groovy/org/grails/compiler/web/taglib/TagLibraryTransformerSpec.groovy +++ b/grails-test-suite-web/src/test/groovy/org/grails/compiler/web/taglib/TagLibraryTransformerSpec.groovy @@ -49,7 +49,7 @@ class TagLibraryTransformerSpec extends Specification { expect: gcl.parseClass(''' @groovy.transform.CompileStatic - class StaticallyCompiledTagLib { + class StaticallyCompiledTagLib implements grails.artefact.TagLibrary{ def closureTagWithNoExplicitArgs = { } def closureTagWithOneArg = { attrs -> } def closureTagWithTwoArgs = { attrs, body -> } diff --git a/grails-plugin-controllers/src/main/groovy/grails/artefact/controller/ServletAttributes.groovy b/grails-web-common/src/main/groovy/grails/web/api/ServletAttributes.groovy similarity index 90% rename from grails-plugin-controllers/src/main/groovy/grails/artefact/controller/ServletAttributes.groovy rename to grails-web-common/src/main/groovy/grails/web/api/ServletAttributes.groovy index dd7638f18d6..1f839a4b0cb 100644 --- a/grails-plugin-controllers/src/main/groovy/grails/artefact/controller/ServletAttributes.groovy +++ b/grails-web-common/src/main/groovy/grails/web/api/ServletAttributes.groovy @@ -14,9 +14,8 @@ * limitations under the License. */ -package grails.artefact.controller +package grails.web.api -import grails.web.api.WebAttributes import groovy.transform.CompileStatic import org.springframework.context.ApplicationContext import org.springframework.web.context.support.WebApplicationContextUtils @@ -27,8 +26,10 @@ import javax.servlet.http.HttpServletResponse import javax.servlet.http.HttpSession /** - * This class is a temporary placeholder for Controller methods which in their current - * implementation there are direct references to the servlet api. This is temporary. + * A trait that adds attributes specific to the Servlet API + * + * @author Graeme Rocher + * @author Jeff Brown * */ @CompileStatic diff --git a/grails-web-common/src/main/groovy/grails/web/api/WebAttributes.groovy b/grails-web-common/src/main/groovy/grails/web/api/WebAttributes.groovy index c23ec9f33f8..358bbd72196 100644 --- a/grails-web-common/src/main/groovy/grails/web/api/WebAttributes.groovy +++ b/grails-web-common/src/main/groovy/grails/web/api/WebAttributes.groovy @@ -19,6 +19,7 @@ import grails.core.GrailsApplication import grails.core.GrailsControllerClass import grails.plugins.GrailsPluginManager import grails.web.mvc.FlashScope +import grails.web.servlet.mvc.GrailsParameterMap import org.grails.web.util.GrailsApplicationAttributes import groovy.transform.CompileStatic @@ -107,7 +108,14 @@ trait WebAttributes { currentRequestAttributes().getFlashScope() } - + /** + * Obtains the Grails parameter map + * + * @return The GrailsParameterMap instance + */ + GrailsParameterMap getParams() { + currentRequestAttributes().getParams() + } /** * Obtains the currently executing web request * diff --git a/grails-web-common/src/main/groovy/org/grails/web/api/CommonWebApi.java b/grails-web-common/src/main/groovy/org/grails/web/api/CommonWebApi.java deleted file mode 100644 index 945922713dc..00000000000 --- a/grails-web-common/src/main/groovy/org/grails/web/api/CommonWebApi.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright 2010 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. - */ -package org.grails.web.api; - -import java.io.Serializable; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import grails.core.GrailsApplication; -import grails.core.GrailsControllerClass; -import grails.plugins.GrailsPluginManager; -import grails.core.support.GrailsApplicationAware; -import org.grails.encoder.CodecLookupHelper; -import org.grails.encoder.Encoder; -import grails.web.mvc.FlashScope; -import org.grails.web.util.GrailsApplicationAttributes; -import grails.web.servlet.mvc.GrailsParameterMap; -import org.grails.web.servlet.mvc.GrailsWebRequest; -import org.codehaus.groovy.runtime.InvokerHelper; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.web.context.ServletContextAware; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.support.WebApplicationContextUtils; - -/** - * API shared by controllers, tag libraries and any other web artifact. - * - * @author Graeme Rocher - * @since 2.0 - */ -public class CommonWebApi implements GrailsApplicationAware, ServletContextAware, ApplicationContextAware, Serializable{ - private static final long serialVersionUID = 1; - public static final String RAW_CODEC_NAME = "org.grails.encoder.impl.RawCodec"; - - private transient GrailsPluginManager pluginManager; - private transient GrailsApplication grailsApplication; - private transient ServletContext servletContext; - private transient ApplicationContext applicationContext; - private transient Encoder rawEncoder; - - public CommonWebApi(GrailsPluginManager pluginManager) { - this.pluginManager = pluginManager; - } - - public CommonWebApi() { - } - - /** - * Marks the given value to be output in raw form without encoding - * - * @param instance The instance - * @param value The value - * @return The raw unencoded value - * @since 2.3 - */ - public Object raw(Object instance, Object value) { - Encoder encoder = getRawEncoder(instance); - if(encoder != null) { - return encoder.encode(value); - } - else { - return InvokerHelper.invokeMethod(value, "encodeAsRaw", null); - } - } - - private Encoder getRawEncoder(GrailsApplication application) { - if(application != null) { - return CodecLookupHelper.lookupEncoder(application, "Raw"); - } - return null; - } - private Encoder getRawEncoder(Object instance) { - if(rawEncoder == null) { - GrailsApplication application = getGrailsApplication(instance); - rawEncoder = getRawEncoder(application); - } - return rawEncoder; - } - - /** - * Obtains the Grails parameter map - * - * @return The GrailsParameterMap instance - */ - public GrailsParameterMap getParams(Object instance) { - return currentRequestAttributes().getParams(); - } - - /** - * Obtains the Grails FlashScope instance - * - * @return The FlashScope instance - */ - public FlashScope getFlash(Object instance) { - return currentRequestAttributes().getFlashScope(); - } - - /** - * Obtains the HttpSession instance - * - * @return The HttpSession instance - */ - public HttpSession getSession(Object instance) { - return currentRequestAttributes().getSession(); - } - - /** - * Obtains the HttpServletRequest instance - * - * @return The HttpServletRequest instance - */ - public HttpServletRequest getRequest(Object instance) { - return currentRequestAttributes().getCurrentRequest(); - } - - /** - * Obtains the ServletContext instance - * - * @return The ServletContext instance - */ - public ServletContext getServletContext(Object instance) { - if (servletContext == null) { - servletContext = currentRequestAttributes().getServletContext(); - } - return servletContext; - } - - /** - * Obtains the HttpServletResponse instance - * - * @return The HttpServletResponse instance - */ - public HttpServletResponse getResponse(Object instance) { - return currentRequestAttributes().getCurrentResponse(); - } - - /** - * Obtains the GrailsApplicationAttributes instance - * - * @return The GrailsApplicationAttributes instance - */ - public GrailsApplicationAttributes getGrailsAttributes(Object instance) { - return currentRequestAttributes().getAttributes(); - } - - /** - * Obtains the GrailsApplication instance - * @return The GrailsApplication instance - */ - public GrailsApplication getGrailsApplication(Object instance) { - if (grailsApplication == null) { - grailsApplication = getGrailsAttributes(instance).getGrailsApplication(); - } - return grailsApplication; - } - - /** - * Obtains the ApplicationContext instance - * @return The ApplicationContext instance - */ - public ApplicationContext getApplicationContext(Object instance) { - if (applicationContext == null) { - applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext(instance)); - } - return applicationContext; - } - - /** - * Obtains the currently executing action name - * @return The action name - */ - public String getActionName(Object instance) { - return currentRequestAttributes().getActionName(); - } - - /** - * Obtains the currently executing controller name - * @return The controller name - */ - public String getControllerName(Object instance) { - return currentRequestAttributes().getControllerName(); - } - - /** - * Obtains the currently executing controller namespace - * @return The controller name - */ - public String getControllerNamespace(Object instance) { - return currentRequestAttributes().getControllerNamespace(); - } - - /** - * Obtains the currently executing controllerClass - * @return The controller class - */ - public GrailsControllerClass getControllerClass(Object instance) { - return currentRequestAttributes().getControllerClass(); - } - - /** - * Obtains the pluginContextPath - * - * @param delegate The object the method is being invoked on - * @return The plugin context path - */ - public String getPluginContextPath(Object delegate) { - GrailsPluginManager manager = getPluginManagerInternal(delegate); - final String pluginPath = manager != null ? manager.getPluginPathForInstance(delegate) : null; - return pluginPath !=null ? pluginPath : ""; - } - - /** - * Obtains the currently executing web request - * - * @return The GrailsWebRequest instance - */ - public GrailsWebRequest getWebRequest(Object instance) { - return currentRequestAttributes(); - } - - private GrailsPluginManager getPluginManagerInternal(Object delegate) { - if (pluginManager == null) { - ApplicationContext ctx = getApplicationContext(delegate); - pluginManager = ctx != null ? ctx.getBean(GrailsPluginManager.BEAN_NAME, GrailsPluginManager.class) : null; - } - return pluginManager; - } - - public void setGrailsApplication(GrailsApplication grailsApplication) { - this.grailsApplication = grailsApplication; - this.rawEncoder = getRawEncoder(grailsApplication); - } - - public void setServletContext(ServletContext servletContext) { - this.servletContext = servletContext; - } - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - protected GrailsWebRequest currentRequestAttributes() { - return (GrailsWebRequest)RequestContextHolder.currentRequestAttributes(); - } -} diff --git a/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/RenderTagLib.groovy b/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/RenderTagLib.groovy index dd6e8ff935e..6d691273d70 100644 --- a/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/RenderTagLib.groovy +++ b/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/RenderTagLib.groovy @@ -18,6 +18,8 @@ package org.grails.plugins.web.taglib import com.opensymphony.module.sitemesh.* import com.opensymphony.module.sitemesh.parser.AbstractHTMLPage import grails.artefact.Artefact +import grails.artefact.TagLibrary +import grails.gsp.TagLib import grails.web.util.TypeConvertingMap import groovy.text.Template import groovy.transform.CompileStatic @@ -46,8 +48,8 @@ import javax.servlet.http.HttpServletRequest * @author Graeme Rocher */ @CompileStatic -@Artefact("TagLibrary") -class RenderTagLib implements RequestConstants { +@TagLib +class RenderTagLib implements RequestConstants, TagLibrary { GroovyPagesTemplateRenderer groovyPagesTemplateRenderer ErrorsViewStackTracePrinter errorsViewStackTracePrinter GroovyPagesTemplateEngine groovyPagesTemplateEngine diff --git a/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/SitemeshTagLib.groovy b/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/SitemeshTagLib.groovy index e042724f45f..9c3ef6c433d 100644 --- a/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/SitemeshTagLib.groovy +++ b/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/SitemeshTagLib.groovy @@ -15,7 +15,8 @@ */ package org.grails.plugins.web.taglib -import grails.artefact.Artefact +import grails.artefact.TagLibrary +import grails.gsp.TagLib import groovy.transform.CompileStatic import org.grails.encoder.CodecLookup @@ -35,12 +36,12 @@ import com.opensymphony.module.sitemesh.RequestConstants * @author Graeme Rocher * @since 1.2 */ -@Artefact("TagLibrary") @CompileStatic -class SitemeshTagLib implements RequestConstants { +@TagLib +class SitemeshTagLib implements RequestConstants, TagLibrary { protected static final String GSP_SITEMESH_PAGE = 'org.grails.web.sitemesh.GrailsLayoutView.GSP_SITEMESH_PAGE' - static namespace = 'sitemesh' + static String namespace = 'sitemesh' CodecLookup codecLookup def captureTagContent(GrailsPrintWriter writer, String tagname, Map attrs, Object body, boolean noEndTagForEmpty=false) { diff --git a/grails-web-gsp-taglib/src/main/groovy/org/grails/web/pages/StandaloneTagLibraryLookup.java b/grails-web-gsp-taglib/src/main/groovy/org/grails/web/pages/StandaloneTagLibraryLookup.java index 6de3d7eafa4..5af4c7f6448 100644 --- a/grails-web-gsp-taglib/src/main/groovy/org/grails/web/pages/StandaloneTagLibraryLookup.java +++ b/grails-web-gsp-taglib/src/main/groovy/org/grails/web/pages/StandaloneTagLibraryLookup.java @@ -3,10 +3,7 @@ import grails.core.GrailsTagLibClass; import grails.gsp.TagLib; import org.grails.core.DefaultGrailsTagLibClass; -import org.grails.plugins.web.taglib.RenderTagLib; -import org.grails.plugins.web.taglib.SitemeshTagLib; import org.grails.web.taglib.TagLibraryLookup; -import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; @@ -19,8 +16,7 @@ * @since 2.4.0 */ public class StandaloneTagLibraryLookup extends TagLibraryLookup implements ApplicationListener { - public static final Class[] DEFAULT_TAGLIB_CLASSES=new Class[] { SitemeshTagLib.class, RenderTagLib.class }; - Set tagLibInstancesSet; + Set tagLibInstancesSet; private StandaloneTagLibraryLookup() { @@ -63,7 +59,7 @@ public void detectAndRegisterTabLibBeans() { if(tagLibInstancesSet==null) { tagLibInstancesSet = new LinkedHashSet(); } - Collection detectedInstances = ((ListableBeanFactory)applicationContext).getBeansWithAnnotation(TagLib.class).values(); + Collection detectedInstances = applicationContext.getBeansWithAnnotation(TagLib.class).values(); for(Object instance : detectedInstances) { if(!tagLibInstancesSet.contains(instance)) { tagLibInstancesSet.add(instance); diff --git a/grails-web-taglib/src/main/groovy/grails/artefact/TagLibrary.groovy b/grails-web-taglib/src/main/groovy/grails/artefact/TagLibrary.groovy index 52c990c14e0..e448291639c 100644 --- a/grails-web-taglib/src/main/groovy/grails/artefact/TagLibrary.groovy +++ b/grails-web-taglib/src/main/groovy/grails/artefact/TagLibrary.groovy @@ -15,14 +15,19 @@ */ package grails.artefact +import grails.artefact.gsp.TagLibraryInvoker +import grails.core.GrailsApplication +import grails.core.GrailsTagLibClass import grails.util.Environment +import grails.util.GrailsMetaClassUtils +import grails.web.api.ServletAttributes import grails.web.api.WebAttributes -import org.grails.web.util.GrailsApplicationAttributes +import groovy.transform.CompileDynamic import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode - import org.codehaus.groovy.runtime.InvokerHelper import org.grails.buffer.GrailsPrintWriter +import org.grails.core.artefact.TagLibArtefactHandler +import org.grails.encoder.Encoder import org.grails.web.encoder.OutputEncodingStack import org.grails.web.encoder.WithCodecHelper import org.grails.web.servlet.mvc.GrailsWebRequest @@ -32,19 +37,38 @@ import org.grails.web.taglib.TemplateVariableBinding import org.grails.web.taglib.WebRequestTemplateVariableBinding import org.grails.web.taglib.exceptions.GrailsTagException import org.grails.web.taglib.util.TagLibraryMetaUtils -import org.springframework.beans.factory.annotation.Autowired +import org.grails.web.util.GrailsApplicationAttributes import org.springframework.web.context.request.RequestAttributes +import javax.annotation.PostConstruct + /** + * A trait that makes a class into a GSP tag library + * * @since 3.0 * @author Jeff Brown - * + * @author Graeme Rocher */ @CompileStatic -trait TagLibrary implements WebAttributes { - - TagLibraryLookup tagLibraryLookup - +trait TagLibrary implements WebAttributes, ServletAttributes, TagLibraryInvoker { + + private Encoder rawEncoder + + @PostConstruct + void initializeTagLibrary() { + TagLibraryMetaUtils.enhanceTagLibMetaClass(GrailsMetaClassUtils.getExpandoMetaClass(getClass()), tagLibraryLookup, getTaglibNamespace()) + } + + @CompileDynamic + def raw(Object value) { + if (rawEncoder == null) { + rawEncoder = WithCodecHelper.lookupEncoder(grailsApplication, "Raw") + if(rawEncoder == null) + return InvokerHelper.invokeMethod(value, "encodeAsRaw", null) + } + return rawEncoder.encode(value) + } + /** * Throws a GrailsTagException * @@ -54,6 +78,13 @@ trait TagLibrary implements WebAttributes { throw new GrailsTagException(message) } + String getTaglibNamespace() { + if(hasProperty('namespace')) { + return ((GroovyObject)this).getProperty('namespace') + } + return TagOutput.DEFAULT_NAMESPACE + } + /** * Obtains the page scope instance * @@ -87,14 +118,7 @@ trait TagLibrary implements WebAttributes { OutputEncodingStack.currentStack().push(newOut,true) } - def withCodec(Object codecInfo, Closure body) { - WithCodecHelper.withCodec(getGrailsApplication(), codecInfo, body) - } - - @CompileStatic(TypeCheckingMode.SKIP) - String getTaglibNamespace() { - getNamespace() - } + /** * Property missing implementation that looks up tag library namespaces or tags in the default namespace * @@ -103,13 +127,13 @@ trait TagLibrary implements WebAttributes { * * @throws MissingPropertyException When no tag namespace or tag is found */ - public Object propertyMissing(String name) { + Object propertyMissing(String name) { TagLibraryLookup gspTagLibraryLookup = getTagLibraryLookup(); if (gspTagLibraryLookup != null) { Object result = gspTagLibraryLookup.lookupNamespaceDispatcher(name); if (result == null) { - String namespace = getTaglibNamespace(); + String namespace = getTaglibNamespace() GroovyObject tagLibrary = gspTagLibraryLookup.lookupTagLibrary(namespace, name); if (tagLibrary == null) { tagLibrary = gspTagLibraryLookup.lookupTagLibrary(TagOutput.DEFAULT_NAMESPACE, name); @@ -124,7 +148,7 @@ trait TagLibrary implements WebAttributes { } if (result != null && !Environment.isDevelopmentMode()) { - MetaClass mc = InvokerHelper.getMetaClass(this); + MetaClass mc = GrailsMetaClassUtils.getExpandoMetaClass(getClass()) TagLibraryMetaUtils.registerPropertyMissingForTag(mc, name, result); } @@ -135,13 +159,5 @@ trait TagLibrary implements WebAttributes { throw new MissingPropertyException(name, this.getClass()); } - - @Autowired - void setGspTagLibraryLookup(TagLibraryLookup lookup) { - tagLibraryLookup = lookup; - } - void setTagLibraryLookup(TagLibraryLookup lookup) { - tagLibraryLookup = lookup; - } } diff --git a/grails-plugin-gsp/src/ast/groovy/grails/artefact/gsp/TagLibraryInvoker.groovy b/grails-web-taglib/src/main/groovy/grails/artefact/gsp/TagLibraryInvoker.groovy similarity index 73% rename from grails-plugin-gsp/src/ast/groovy/grails/artefact/gsp/TagLibraryInvoker.groovy rename to grails-web-taglib/src/main/groovy/grails/artefact/gsp/TagLibraryInvoker.groovy index 8142d39b885..0a12c4621ba 100644 --- a/grails-plugin-gsp/src/ast/groovy/grails/artefact/gsp/TagLibraryInvoker.groovy +++ b/grails-web-taglib/src/main/groovy/grails/artefact/gsp/TagLibraryInvoker.groovy @@ -19,10 +19,10 @@ import grails.util.Environment import grails.util.GrailsMetaClassUtils import grails.web.api.WebAttributes import groovy.transform.CompileStatic -import org.grails.gsp.GroovyPage import org.grails.web.encoder.WithCodecHelper import org.grails.web.taglib.NamespacedTagDispatcher import org.grails.web.taglib.TagLibraryLookup +import org.grails.web.taglib.TagOutput import org.grails.web.taglib.util.TagLibraryMetaUtils import org.springframework.beans.factory.annotation.Autowired @@ -35,11 +35,28 @@ import org.springframework.beans.factory.annotation.Autowired @CompileStatic trait TagLibraryInvoker extends WebAttributes{ - @Autowired - TagLibraryLookup tagLibraryLookup + private TagLibraryLookup tagLibraryLookup private boolean developmentMode = Environment.isDevelopmentMode(); + @Autowired + void setTagLibraryLookup(TagLibraryLookup tagLibraryLookup) { + this.tagLibraryLookup = tagLibraryLookup + } + + TagLibraryLookup getTagLibraryLookup() { + def lookup = this.tagLibraryLookup + if(lookup == null) { + lookup = getGrailsApplication()?.mainContext?.getBean(TagLibraryLookup) + setTagLibraryLookup(lookup) + } + return lookup + } + + String getTaglibNamespace() { + TagOutput.DEFAULT_NAMESPACE + } + /** * Method missing implementation that handles tag invocation by method name @@ -51,14 +68,20 @@ trait TagLibraryInvoker extends WebAttributes{ */ Object methodMissing(String methodName, Object argsObject) { Object[] args = argsObject instanceof Object[] ? (Object[])argsObject : [argsObject] as Object[] - if (shouldHandleMethodMissing(methodName, args)) { + if (!"render".equals(methodName)) { TagLibraryLookup lookup = tagLibraryLookup if (lookup) { - GroovyObject tagLibrary = lookup.lookupTagLibrary(GroovyPage.DEFAULT_NAMESPACE, methodName) + def usedNamespace = getTaglibNamespace() + GroovyObject tagLibrary = lookup.lookupTagLibrary(usedNamespace, methodName) + if (tagLibrary == null) { + tagLibrary = lookup.lookupTagLibrary(TagOutput.DEFAULT_NAMESPACE, methodName); + usedNamespace = TagOutput.DEFAULT_NAMESPACE; + } + if (tagLibrary) { if (!developmentMode) { MetaClass controllerMc = GrailsMetaClassUtils.getMetaClass(this) - TagLibraryMetaUtils.registerMethodMissingForTags(controllerMc, lookup, GroovyPage.DEFAULT_NAMESPACE, methodName) + TagLibraryMetaUtils.registerMethodMissingForTags(controllerMc, lookup, usedNamespace, methodName) } return tagLibrary.invokeMethod(methodName, args) } @@ -87,12 +110,12 @@ trait TagLibraryInvoker extends WebAttributes{ throw new MissingPropertyException(propertyName, this.getClass()) } - def T withCodec(Object instance, Object codecInfo, Closure body) { + /** + * @see {@link WithCodecHelper#withCodec(grails.core.GrailsApplication, java.lang.Object, groovy.lang.Closure)} + */ + def T withCodec(Object codecInfo, Closure body) { return WithCodecHelper.withCodec(getGrailsApplication(), codecInfo, body) } - private boolean shouldHandleMethodMissing(String methodName, Object[] args) { - return !"render".equals(methodName); - } } \ No newline at end of file diff --git a/grails-web-taglib/src/main/groovy/org/grails/compiler/web/taglib/TagLibraryTransformer.java b/grails-web-taglib/src/main/groovy/org/grails/compiler/web/taglib/TagLibraryTransformer.java index d15022e0230..67466919f8b 100644 --- a/grails-web-taglib/src/main/groovy/org/grails/compiler/web/taglib/TagLibraryTransformer.java +++ b/grails-web-taglib/src/main/groovy/org/grails/compiler/web/taglib/TagLibraryTransformer.java @@ -15,7 +15,10 @@ */ package org.grails.compiler.web.taglib; +import grails.artefact.TagLibrary; +import grails.compiler.ast.AnnotatedClassInjector; import grails.compiler.ast.AstTransformer; +import grails.compiler.ast.GrailsArtefactClassInjector; import groovy.lang.Closure; import org.codehaus.groovy.ast.*; import org.codehaus.groovy.ast.expr.*; @@ -23,11 +26,11 @@ import org.codehaus.groovy.ast.stmt.ExpressionStatement; import org.codehaus.groovy.ast.stmt.ReturnStatement; import org.codehaus.groovy.ast.stmt.Statement; +import org.codehaus.groovy.classgen.GeneratorContext; import org.codehaus.groovy.control.SourceUnit; -import org.grails.compiler.injection.AbstractGrailsArtefactTransformer; +import org.grails.compiler.injection.GrailsASTUtils; import org.grails.core.artefact.TagLibArtefactHandler; import org.grails.io.support.GrailsResourceUtils; -import org.grails.plugins.web.api.TagLibraryApi; import org.grails.web.servlet.mvc.GrailsWebRequest; import org.grails.web.taglib.TagOutput; import org.springframework.web.context.request.RequestContextHolder; @@ -46,7 +49,7 @@ * @since 2.0 */ @AstTransformer -public class TagLibraryTransformer extends AbstractGrailsArtefactTransformer { +public class TagLibraryTransformer implements GrailsArtefactClassInjector, AnnotatedClassInjector { protected static final String GET_TAG_LIB_NAMESPACE_METHOD_NAME = "$getTagLibNamespace"; @@ -75,29 +78,33 @@ public class TagLibraryTransformer extends AbstractGrailsArtefactTransformer { private static final String NAMESPACE_PROPERTY = "namespace"; private static final ClassNode CLOSURE_CLASS_NODE = new ClassNode(Closure.class); + @Override - public Class getInstanceImplementation() { - return TagLibraryApi.class; + public String[] getArtefactTypes() { + return new String[] { getArtefactType(), "TagLibrary" }; } - @Override - public Class getStaticImplementation() { - return null; // no static methods + protected String getArtefactType() { + return TagLibArtefactHandler.TYPE; } + @Override + public void performInjectionOnAnnotatedClass(SourceUnit source, GeneratorContext context, ClassNode classNode) { + performInjectionOnAnnotatedClass(source, classNode); + } @Override - public String[] getArtefactTypes() { - return new String[] { getArtefactType(), "TagLibrary" }; + public void performInjection(SourceUnit source, GeneratorContext context, ClassNode classNode) { + performInjectionOnAnnotatedClass(source, classNode); } @Override - protected String getArtefactType() { - return TagLibArtefactHandler.TYPE; + public void performInjection(SourceUnit source, ClassNode classNode) { + performInjectionOnAnnotatedClass(source, classNode); } @Override - protected void performInjectionInternal(String apiInstanceProperty, SourceUnit source, ClassNode classNode) { + public void performInjectionOnAnnotatedClass(SourceUnit source, ClassNode classNode) { List tags = findTags(classNode); PropertyNode namespaceProperty = classNode.getProperty(NAMESPACE_PROPERTY); @@ -112,7 +119,7 @@ protected void performInjectionInternal(String apiInstanceProperty, SourceUnit s addGetTagLibNamespaceMethod(classNode, namespace); - MethodCallExpression tagLibraryLookupMethodCall = new MethodCallExpression(new VariableExpression(apiInstanceProperty, ClassHelper.make(TagLibraryApi.class)), "getTagLibraryLookup", ZERO_ARGS); + MethodCallExpression tagLibraryLookupMethodCall = new MethodCallExpression(new VariableExpression("this", ClassHelper.make(TagLibrary.class)), "getTagLibraryLookup", ZERO_ARGS); for (PropertyNode tag : tags) { String tagName = tag.getName(); addAttributesAndBodyMethod(classNode, tagLibraryLookupMethodCall, tagName); @@ -138,7 +145,7 @@ private void addAttributesAndStringBodyMethod(ClassNode classNode, String tagNam arguments.addExpression(new CastExpression(ClassHelper.make(Map.class), ATTRS_EXPRESSION)) .addExpression(new ConstructorCallExpression(new ClassNode(TagOutput.ConstantClosure.class), constructorArgs)); methodBody.addStatement(new ExpressionStatement(new MethodCallExpression(new VariableExpression("this"), tagName, arguments))); - classNode.addMethod(new MethodNode(tagName, Modifier.PUBLIC,OBJECT_CLASS, MAP_CHARSEQUENCE_PARAMETERS, null, methodBody)); + classNode.addMethod(new MethodNode(tagName, Modifier.PUBLIC, GrailsASTUtils.OBJECT_CLASS_NODE, MAP_CHARSEQUENCE_PARAMETERS, null, methodBody)); } private void addAttributesAndBodyMethod(ClassNode classNode, MethodCallExpression tagLibraryLookupMethodCall, String tagName) { @@ -163,22 +170,22 @@ private void addAttributesAndBodyMethod(ClassNode classNode, MethodCallExpressio if (includeBody && includeAttrs) { if (!methodExists(classNode, tagName, MAP_CLOSURE_PARAMETERS)) { - classNode.addMethod(new MethodNode(tagName, Modifier.PUBLIC,OBJECT_CLASS, MAP_CLOSURE_PARAMETERS, null, methodBody)); + classNode.addMethod(new MethodNode(tagName, Modifier.PUBLIC,GrailsASTUtils.OBJECT_CLASS_NODE, MAP_CLOSURE_PARAMETERS, null, methodBody)); } } else if (includeAttrs && !includeBody) { if (!methodExists(classNode, tagName, MAP_PARAMETERS)) { - classNode.addMethod(new MethodNode(tagName, Modifier.PUBLIC,OBJECT_CLASS, MAP_PARAMETERS, null, methodBody)); + classNode.addMethod(new MethodNode(tagName, Modifier.PUBLIC,GrailsASTUtils.OBJECT_CLASS_NODE, MAP_PARAMETERS, null, methodBody)); } } else if (includeBody) { if (!methodExists(classNode, tagName, CLOSURE_PARAMETERS)) { - classNode.addMethod(new MethodNode(tagName, Modifier.PUBLIC,OBJECT_CLASS, CLOSURE_PARAMETERS, null, methodBody)); + classNode.addMethod(new MethodNode(tagName, Modifier.PUBLIC,GrailsASTUtils.OBJECT_CLASS_NODE, CLOSURE_PARAMETERS, null, methodBody)); } } else { if (!methodExists(classNode, tagName, Parameter.EMPTY_ARRAY)) { - classNode.addMethod(new MethodNode(tagName, Modifier.PUBLIC,OBJECT_CLASS, Parameter.EMPTY_ARRAY, null, methodBody)); + classNode.addMethod(new MethodNode(tagName, Modifier.PUBLIC,GrailsASTUtils.OBJECT_CLASS_NODE, Parameter.EMPTY_ARRAY, null, methodBody)); } } } diff --git a/grails-web-taglib/src/main/groovy/org/grails/plugins/web/api/TagLibraryApi.java b/grails-web-taglib/src/main/groovy/org/grails/plugins/web/api/TagLibraryApi.java deleted file mode 100644 index 123c4f8d75c..00000000000 --- a/grails-web-taglib/src/main/groovy/org/grails/plugins/web/api/TagLibraryApi.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2010 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. - */ -package org.grails.plugins.web.api; - -import grails.core.GrailsApplication; -import grails.core.GrailsTagLibClass; -import grails.plugins.GrailsPluginManager; -import grails.util.Environment; -import groovy.lang.GroovyObject; -import groovy.lang.MetaClass; -import groovy.lang.MetaMethod; -import groovy.lang.MissingMethodException; -import org.codehaus.groovy.runtime.InvokerHelper; -import org.grails.core.artefact.TagLibArtefactHandler; -import org.grails.web.api.CommonWebApi; -import org.grails.web.taglib.TagLibraryLookup; -import org.grails.web.taglib.TagOutput; -import org.grails.web.taglib.util.TagLibraryMetaUtils; -import org.springframework.context.ApplicationContext; - -import java.util.List; - -/** - * API for Tag libraries in a Grails application. - * - * @author Graeme Rocher - * @since 2.0 - */ -public class TagLibraryApi extends CommonWebApi { - - private static final long serialVersionUID = 1; - - private transient TagLibraryLookup tagLibraryLookup; - private boolean developmentMode = Environment.isDevelopmentMode(); - - public TagLibraryApi() { - super(null); - } - - public TagLibraryApi(GrailsPluginManager pluginManager) { - super(pluginManager); - } - - /** - * Method missing implementation that handles tag invocation by method name - * - * @param instance The instance - * @param methodName The method name - * @param argsObject The arguments - * @return The result - */ - public Object methodMissing(Object instance, String methodName, Object argsObject) { - Object[] args = argsObject instanceof Object[] ? (Object[])argsObject : new Object[]{argsObject}; - MetaClass mc = InvokerHelper.getMetaClass(instance); - String usednamespace = getNamespace(instance); - TagLibraryLookup lookup = getTagLibraryLookup(); - if (lookup != null) { - - GroovyObject tagLibrary = lookup.lookupTagLibrary(usednamespace, methodName); - if (tagLibrary == null) { - tagLibrary = lookup.lookupTagLibrary(TagOutput.DEFAULT_NAMESPACE, methodName); - usednamespace = TagOutput.DEFAULT_NAMESPACE; - } - - if (tagLibrary != null && !developmentMode) { - TagLibraryMetaUtils.registerMethodMissingForTags(mc, lookup, usednamespace, methodName); - } - - if (tagLibrary != null) { - List respondsTo = tagLibrary.getMetaClass().respondsTo(tagLibrary, methodName, args); - if (respondsTo.size()>0) { - return respondsTo.get(0).invoke(tagLibrary, args); - } - } - } - - throw new MissingMethodException(methodName, instance.getClass(), args); - } - - private String getNamespace(Object instance) { - GrailsApplication grailsApplication = getGrailsApplication(null); - if (grailsApplication != null) { - GrailsTagLibClass taglibrary = (GrailsTagLibClass) grailsApplication.getArtefact(TagLibArtefactHandler.TYPE, instance.getClass().getName()); - if (taglibrary != null) { - return taglibrary.getNamespace(); - } - } - return TagOutput.DEFAULT_NAMESPACE; - } - public TagLibraryLookup getTagLibraryLookup() { - if (tagLibraryLookup == null) { - ApplicationContext applicationContext = getApplicationContext(null); - if (applicationContext != null && applicationContext.containsBean("gspTagLibraryLookup")) { - tagLibraryLookup = applicationContext.getBean("gspTagLibraryLookup", TagLibraryLookup.class); - } - } - return tagLibraryLookup; - } -} diff --git a/grails-web-taglib/src/main/groovy/org/grails/web/taglib/util/TagLibraryMetaUtils.groovy b/grails-web-taglib/src/main/groovy/org/grails/web/taglib/util/TagLibraryMetaUtils.groovy index 6ef2504b7dd..9da59b43d58 100644 --- a/grails-web-taglib/src/main/groovy/org/grails/web/taglib/util/TagLibraryMetaUtils.groovy +++ b/grails-web-taglib/src/main/groovy/org/grails/web/taglib/util/TagLibraryMetaUtils.groovy @@ -19,6 +19,11 @@ class TagLibraryMetaUtils { static void enhanceTagLibMetaClass(final GrailsTagLibClass taglib, TagLibraryLookup gspTagLibraryLookup) { final MetaClass mc = taglib.getMetaClass() final String namespace = taglib.namespace ?: TagOutput.DEFAULT_NAMESPACE + enhanceTagLibMetaClass(mc, gspTagLibraryLookup, namespace) + } + + @CompileStatic + public static void enhanceTagLibMetaClass(MetaClass mc, TagLibraryLookup gspTagLibraryLookup, String namespace) { registerTagMetaMethods(mc, gspTagLibraryLookup, namespace) registerNamespaceMetaProperties(mc, gspTagLibraryLookup) } diff --git a/grails-web-taglib/src/test/groovy/org/grails/web/taglib/TagLibraryLookupSpec.groovy b/grails-web-taglib/src/test/groovy/org/grails/web/taglib/TagLibraryLookupSpec.groovy index 97d82982d8d..b6ff8354a85 100644 --- a/grails-web-taglib/src/test/groovy/org/grails/web/taglib/TagLibraryLookupSpec.groovy +++ b/grails-web-taglib/src/test/groovy/org/grails/web/taglib/TagLibraryLookupSpec.groovy @@ -2,7 +2,6 @@ package org.grails.web.taglib import grails.core.DefaultGrailsApplication import grails.gsp.TagLib -import org.grails.plugins.web.api.TagLibraryApi import org.grails.web.servlet.mvc.GrailsWebRequest import org.springframework.mock.web.MockHttpServletRequest import org.springframework.mock.web.MockHttpServletResponse @@ -30,11 +29,8 @@ class TagLibraryLookupSpec extends Specification { application.initialise() def applicationContext = new GenericWebApplicationContext() - def tagLibApi = new TagLibraryApi() - tagLibApi.applicationContext = applicationContext - - applicationContext.defaultListableBeanFactory.registerSingleton(OneTagLib.name, new OneTagLib(instanceTagLibraryApi: tagLibApi, tagLibraryLookup: lookup)) - applicationContext.defaultListableBeanFactory.registerSingleton(TwoTagLib.name, new TwoTagLib(instanceTagLibraryApi: tagLibApi, tagLibraryLookup: lookup)) + applicationContext.defaultListableBeanFactory.registerSingleton(OneTagLib.name, new OneTagLib(tagLibraryLookup: lookup)) + applicationContext.defaultListableBeanFactory.registerSingleton(TwoTagLib.name, new TwoTagLib(tagLibraryLookup: lookup)) applicationContext.defaultListableBeanFactory.registerSingleton("gspTagLibraryLookup", lookup) // instanceTagLibraryApi(TagLibraryApi, pluginManager) applicationContext.refresh()