Skip to content

Commit

Permalink
Changes to support the cache plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
graemerocher committed Dec 9, 2014
1 parent 15395e6 commit cbef563
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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) {

Expand All @@ -64,9 +69,11 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp
}
}


if(url == null || !GrailsResourceUtils.isGrailsResource(new UrlResource(url))) return



List<ArtefactHandler> artefactHandlers = GrailsFactoriesLoader.loadFactories(ArtefactHandler)
ClassInjector[] classInjectors = GrailsAwareInjectionOperation.getClassInjectors()

Expand All @@ -91,13 +98,18 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp
Set<String> 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))
Expand All @@ -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])
Expand All @@ -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)
Expand All @@ -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) {
Expand All @@ -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<String> pendingPluginClasses = []
static Collection<String> pluginExcludes = []

protected static void generatePluginXml(ClassNode pluginClassNode, String pluginVersion, Set<String> transformedClasses, File pluginXmlFile) {
def pluginXmlExists = pluginXmlFile.exists()
Expand Down Expand Up @@ -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
}
}
}
}

}
}

Expand All @@ -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
Expand All @@ -239,6 +294,8 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp
}
}

handleExcludes(pluginXml)

Writable writable = new StreamingMarkupBuilder().bind {
mkp.yield pluginXml
}
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String> map = new LinkedHashMap<String, String>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,14 @@ class GrailsPluginGradlePlugin extends GrailsGradlePlugin {
def providedFiles = project.files(providedConfig)
ast {
groovy {
srcDirs = ["${project.projectDir}/src/main/ast"]
compileClasspath += project.configurations.compile + providedFiles
}
}
main {
compileClasspath += providedFiles + sourceSets.ast.output
}
test {
compileClasspath += providedFiles
compileClasspath += providedFiles + sourceSets.ast.output
runtimeClasspath += providedFiles
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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)

Expand Down Expand Up @@ -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
Expand Down

0 comments on commit cbef563

Please sign in to comment.