From cbef5639ea26e43cf94cb93e73741e881c6657f0 Mon Sep 17 00:00:00 2001 From: Graeme Rocher Date: Tue, 9 Dec 2014 09:59:35 +0100 Subject: [PATCH] Changes to support the cache plugin --- ...alGrailsClassInjectorTransformation.groovy | 90 ++++++++++++++++--- .../compiler/injection/PluginAstReader.java | 2 +- .../core/GrailsPluginGradlePlugin.groovy | 3 +- .../mvc/UrlMappingsHandlerMapping.groovy | 5 ++ 4 files changed, 87 insertions(+), 13 deletions(-) diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy b/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy index 57cb033e55..5e66cbb60a 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy @@ -11,6 +11,7 @@ import grails.util.GrailsNameUtils import groovy.transform.CompilationUnitAware import groovy.transform.CompileDynamic import groovy.transform.CompileStatic +import groovy.util.slurpersupport.GPathResult import groovy.xml.MarkupBuilder import groovy.xml.StreamingMarkupBuilder import org.codehaus.groovy.ast.ASTNode @@ -26,6 +27,7 @@ import org.codehaus.groovy.control.SourceUnit import org.codehaus.groovy.transform.ASTTransformation import org.codehaus.groovy.transform.GroovyASTTransformation import org.grails.core.io.support.GrailsFactoriesLoader +import org.grails.io.support.AntPathMatcher import org.grails.io.support.FileSystemResource import org.grails.io.support.GrailsResourceUtils import org.grails.io.support.Resource @@ -43,6 +45,9 @@ import java.lang.reflect.Modifier @CompileStatic class GlobalGrailsClassInjectorTransformation implements ASTTransformation, CompilationUnitAware { + + public static final String ARTEFACT_HANDLER_CLASS = "grails.core.ArtefactHandler" + @Override void visit(ASTNode[] nodes, SourceUnit source) { @@ -64,9 +69,11 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp } } + if(url == null || !GrailsResourceUtils.isGrailsResource(new UrlResource(url))) return + List artefactHandlers = GrailsFactoriesLoader.loadFactories(ArtefactHandler) ClassInjector[] classInjectors = GrailsAwareInjectionOperation.getClassInjectors() @@ -91,13 +98,18 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp Set transformedClasses = [] String pluginVersion = null ClassNode pluginClassNode = null + def compilationTargetDirectory = source.configuration.targetDirectory + def pluginXmlFile = new File(compilationTargetDirectory, "META-INF/grails-plugin.xml") for (ClassNode classNode : classes) { def projectName = classNode.getNodeMetaData("projectName") def projectVersion = classNode.getNodeMetaData("projectVersion") pluginVersion = projectVersion - if(classNode.name.endsWith("GrailsPlugin")) { + + def classNodeName = classNode.name + + if(classNodeName.endsWith("GrailsPlugin")) { pluginClassNode = classNode if(projectVersion && !classNode.getProperty('version')) { classNode.addProperty(new PropertyNode('version', Modifier.PUBLIC, ClassHelper.make(Object), classNode, new ConstantExpression(projectVersion.toString()) , null, null)) @@ -106,6 +118,30 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp continue } + if(GrailsASTUtils.isSubclassOf(classNode, ARTEFACT_HANDLER_CLASS)) { + // generate META-INF/grails.factories + def factoriesFile = new File(compilationTargetDirectory, "META-INF/grails.factories") + factoriesFile.parentFile.mkdirs() + def props = new Properties() + if(factoriesFile.exists()) { + // update + factoriesFile.withInputStream { InputStream input -> + props.load(input) + } + def existing = props.getProperty(ARTEFACT_HANDLER_CLASS) + if(existing != classNodeName) { + props.put(ARTEFACT_HANDLER_CLASS, [existing, classNodeName].join(',')) + } + } + else { + props.put(ARTEFACT_HANDLER_CLASS, classNodeName) + } + factoriesFile.withObjectOutputStream { OutputStream out -> + props.store(out, "Grails Factories File") + } + continue + } + if(projectName && projectVersion) { GrailsASTUtils.addAnnotationOrGetExisting(classNode, GrailsPlugin, [name: GrailsNameUtils.getPropertyNameForLowerCaseHyphenSeparatedName(projectName.toString()), version:projectVersion]) @@ -114,7 +150,7 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp for(ArtefactHandler handler in artefactHandlers) { if(handler.isArtefact(classNode)) { if(!classNode.getAnnotations(ARTEFACT_CLASS_NODE)) { - transformedClasses << classNode.name + transformedClasses << classNodeName def annotationNode = new AnnotationNode(new ClassNode(Artefact.class)) annotationNode.addMember("value", new ConstantExpression(handler.getType())) classNode.addAnnotation(annotationNode) @@ -131,7 +167,7 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp } - if(!transformedClasses.contains(classNode.name)) { + if(!transformedClasses.contains(classNodeName)) { def globalClassInjectors = GrailsAwareInjectionOperation.globalClassInjectors for(ClassInjector injector in globalClassInjectors) { @@ -143,14 +179,13 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp // now create or update grails-plugin.xml // first check if plugin.xml exists - def compilationTargetDirectory = source.configuration.targetDirectory - def pluginXmlFile = new File(compilationTargetDirectory, "META-INF/grails-plugin.xml") pluginXmlFile.parentFile.mkdirs() generatePluginXml(pluginClassNode, pluginVersion, transformedClasses, pluginXmlFile) } static Set pendingPluginClasses = [] + static Collection pluginExcludes = [] protected static void generatePluginXml(ClassNode pluginClassNode, String pluginVersion, Set transformedClasses, File pluginXmlFile) { def pluginXmlExists = pluginXmlFile.exists() @@ -184,21 +219,33 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp pluginXml.withWriter( "UTF-8") { Writer writer -> def mkp = new MarkupBuilder(writer) def pluginName = GrailsNameUtils.getLogicalPropertyName(pluginClassNode.name, "GrailsPlugin") - def grailsVersion = info.getProperties()['grailsVersion'] ?: getClass().getPackage().getImplementationVersion() + " > *" + + def pluginProperties = info.getProperties() + def excludes = pluginProperties.get('pluginExcludes') + if(excludes instanceof List) { + pluginExcludes.clear() + pluginExcludes.addAll(excludes) + } + + def grailsVersion = pluginProperties['grailsVersion'] ?: getClass().getPackage().getImplementationVersion() + " > *" mkp.plugin(name:pluginName, version: pluginVersion, grailsVersion: grailsVersion) { type(pluginClassNode.name) - for(entry in info.getProperties()) { + for(entry in pluginProperties) { delegate."$entry.key"(entry.value) } // if there are pending classes to add to the plugin.xml add those if(artefactClasses) { + def antPathMatcher = new AntPathMatcher() resources { for(String cn in artefactClasses) { - resource cn + if (!pluginExcludes.any() { String exc -> antPathMatcher.match(exc, cn.replace('.','/')) }) { + resource cn + } } } } + } } @@ -222,11 +269,19 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp PluginAstReader pluginAstReader = new PluginAstReader() def info = pluginAstReader.readPluginInfo(pluginClassNode) - def grailsVersion = info.getProperties()['grailsVersion'] ?: getClass().getPackage().getImplementationVersion() + " > *" + + def pluginProperties = info.getProperties() + def grailsVersion = pluginProperties['grailsVersion'] ?: getClass().getPackage().getImplementationVersion() + " > *" pluginXml.@grailsVersion = grailsVersion - for(entry in info.getProperties()) { + for(entry in pluginProperties) { pluginXml."$entry.key" = entry.value } + + def excludes = pluginProperties.get('pluginExcludes') + if(excludes instanceof List) { + pluginExcludes.clear() + pluginExcludes.addAll(excludes) + } } def resources = pluginXml.resources @@ -239,6 +294,8 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp } } + handleExcludes(pluginXml) + Writable writable = new StreamingMarkupBuilder().bind { mkp.yield pluginXml } @@ -256,6 +313,19 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp } } + @CompileDynamic + protected static void handleExcludes(GPathResult pluginXml) { + if (pluginExcludes) { + + def antPathMatcher = new AntPathMatcher() + pluginXml.resources.resource.each { res -> + if (pluginExcludes.any() { String exc -> antPathMatcher.match(exc, res.text().replace('.','/')) }) { + res.replaceNdoe {} + } + } + } + } + public static final ClassNode ARTEFACT_CLASS_NODE = new ClassNode(Artefact.class) CompilationUnit compilationUnit diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/PluginAstReader.java b/grails-core/src/main/groovy/org/grails/compiler/injection/PluginAstReader.java index fe0f8f97a7..3c17a897d4 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/PluginAstReader.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/PluginAstReader.java @@ -73,7 +73,7 @@ public void visitProperty(PropertyNode node) { for (Expression i : ((ListExpression)expr).getExpressions()) { list.add(i.getText()); } - value = DefaultGroovyMethods.join(((Iterable)list), ","); + value = list; } else if (expr instanceof MapExpression) { final Map map = new LinkedHashMap(); diff --git a/grails-gradle-plugin/src/main/groovy/org/grails/gradle/plugin/core/GrailsPluginGradlePlugin.groovy b/grails-gradle-plugin/src/main/groovy/org/grails/gradle/plugin/core/GrailsPluginGradlePlugin.groovy index 15939c8dfd..67b3101b3b 100644 --- a/grails-gradle-plugin/src/main/groovy/org/grails/gradle/plugin/core/GrailsPluginGradlePlugin.groovy +++ b/grails-gradle-plugin/src/main/groovy/org/grails/gradle/plugin/core/GrailsPluginGradlePlugin.groovy @@ -42,7 +42,6 @@ class GrailsPluginGradlePlugin extends GrailsGradlePlugin { def providedFiles = project.files(providedConfig) ast { groovy { - srcDirs = ["${project.projectDir}/src/main/ast"] compileClasspath += project.configurations.compile + providedFiles } } @@ -50,7 +49,7 @@ class GrailsPluginGradlePlugin extends GrailsGradlePlugin { compileClasspath += providedFiles + sourceSets.ast.output } test { - compileClasspath += providedFiles + compileClasspath += providedFiles + sourceSets.ast.output runtimeClasspath += providedFiles } } diff --git a/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/mvc/UrlMappingsHandlerMapping.groovy b/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/mvc/UrlMappingsHandlerMapping.groovy index 1f83f7a30f..3e4f19591a 100644 --- a/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/mvc/UrlMappingsHandlerMapping.groovy +++ b/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/mvc/UrlMappingsHandlerMapping.groovy @@ -40,6 +40,7 @@ import javax.servlet.http.HttpServletRequest @CompileStatic class UrlMappingsHandlerMapping extends AbstractHandlerMapping{ + static final String MATCHED_REQUEST = "org.grails.url.match.info" protected UrlMappingsHolder urlMappingsHolder protected UrlPathHelper urlHelper = new UrlPathHelper(); @@ -60,6 +61,9 @@ class UrlMappingsHandlerMapping extends AbstractHandlerMapping{ @Override protected Object getHandlerInternal(HttpServletRequest request) throws Exception { + def matchedInfo = request.getAttribute(MATCHED_REQUEST) + if(matchedInfo != null) return matchedInfo + String uri = urlHelper.getPathWithinApplication(request); def webRequest = GrailsWebRequest.lookup(request) @@ -88,6 +92,7 @@ class UrlMappingsHandlerMapping extends AbstractHandlerMapping{ webRequest.resetParams() info.configure(webRequest) if(info instanceof GrailsControllerUrlMappingInfo) { + request.setAttribute(MATCHED_REQUEST, info) return info } else if(info.viewName || info.URI) return info