forked from grails-plugins/grails-resources
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ResourcesGrailsPlugin.groovy
175 lines (153 loc) · 6.32 KB
/
ResourcesGrailsPlugin.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import org.codehaus.groovy.grails.commons.ConfigurationHolder
import org.springframework.beans.factory.config.MethodInvokingFactoryBean
import org.springframework.core.io.FileSystemResource
import org.grails.plugin.resource.util.HalfBakedLegacyLinkGenerator
/**
* @author Marc Palmer ([email protected])
* @author Luke Daley ([email protected])
*/
class ResourcesGrailsPlugin {
def version = "1.0"
def grailsVersion = "1.2 > *"
def dependsOn = [logging:'1.0 > *']
def loadAfter = ['logging']
def pluginExcludes = [
"grails-app/views/error.gsp",
"grails-app/views/index.gsp",
"grails-app/controllers/**/*.groovy",
"web-app/css/**/*.*",
"web-app/js/**/*.*",
"web-app/images/**/*.*",
"grails-app/resourceMappers/**/test/*",
"grails-app/conf/*Resources.groovy"
]
def artefacts = [getResourceMapperArtefactHandler(), getResourcesArtefactHandler()]
def watchedResources = [
"file:./grails-app/resourceMappers/**/*.groovy",
"file:./plugins/*/grails-app/resourceMappers/**/*.groovy",
"file:./grails-app/conf/*Resources.groovy",
"file:./plugins/*/grails-app/conf/*Resources.groovy",
"file:./web-app/**/*.*" // Watch for resource changes, we need excludes here for WEB-INF+META-INF when grails impls this
]
def author = "Marc Palmer, Luke Daley"
def authorEmail = "[email protected], [email protected]"
def title = "Resources"
def description = 'HTML resource management enhancements to replace g.resource etc.'
def documentation = "http://grails.org/plugin/resources"
static DEFAULT_URI_PREFIX = 'static'
static DEFAULT_ADHOC_PATTERNS = ["/images/*", "*.css", "*.js"].asImmutable()
def getResourcesConfig() {
ConfigurationHolder.config.grails.resources
}
def getUriPrefix() {
def prf = resourcesConfig.uri.prefix
prf instanceof String ? prf : DEFAULT_URI_PREFIX
}
def getAdHocPatterns() {
def patterns = resourcesConfig.adhoc.patterns
patterns instanceof List ? patterns : DEFAULT_ADHOC_PATTERNS
}
def doWithSpring = { ->
if (!springConfig.containsBean('grailsLinkGenerator')) {
grailsLinkGenerator(HalfBakedLegacyLinkGenerator) {
pluginManager = ref('pluginManager')
}
}
}
def doWithWebDescriptor = { webXml ->
def adHocPatterns = getAdHocPatterns()
log.info("Adding servlet filter")
def filters = webXml.filter[0]
filters + {
'filter' {
'filter-name'("DeclaredResourcesPluginFilter")
'filter-class'("org.grails.plugin.resource.ProcessingFilter")
}
if (adHocPatterns) {
'filter' {
'filter-name'("AdHocResourcesPluginFilter")
'filter-class'("org.grails.plugin.resource.ProcessingFilter")
'init-param' {
'param-name'("adhoc")
'param-value'("true")
}
}
}
}
def mappings = webXml.'filter-mapping' // this does only yield 2 filter mappings
mappings + {
'filter-mapping' {
'filter-name'("DeclaredResourcesPluginFilter")
'url-pattern'("/${uriPrefix}/*")
}
// To be pre-Servlets 2.5 safe, we have 1 extension mapping per filter-mapping entry
// Lame, but Tomcat 5.5 is not SSDK 2.5
adHocPatterns.each { pattern ->
'filter-mapping' {
'filter-name'("AdHocResourcesPluginFilter")
'url-pattern'(pattern.toString())
}
}
}
}
def doWithDynamicMethods = { applicationContext ->
applicationContext.resourceService.staticUrlPrefix = "/${uriPrefix}"
applicationContext.resourceService.reload()
}
boolean isResourceWeShouldProcess(File file) {
// @todo Improve this, but for now tracing the ancestry of every file is seriously zzzz and overkill
// when STS creats 100s of .class changes
boolean shouldProcess = (file.parent.indexOf('WEB-INF') < 0) && (file.parent.indexOf('META-INF') < 0)
return shouldProcess
}
def onChange = { event ->
if (event.source instanceof FileSystemResource) {
if (isResourceWeShouldProcess(event.source.file)) {
event.application.mainContext.resourceService.reload()
}
} else {
[getResourceMapperArtefactHandler().TYPE, getResourcesArtefactHandler().TYPE].each {
if (handleChange(application, event, it, log)) {
log.info("reloading resources due to change of $event.source.name")
event.application.mainContext.resourceService.reload()
}
}
}
}
protected handleChange(application, event, type, log) {
if (application.isArtefactOfType(type, event.source)) {
log.debug("reloading $event.source.name ($type)")
def oldClass = application.getArtefact(type, event.source.name)
application.addArtefact(type, event.source)
// Reload subclasses
application.getArtefacts(type).each {
if (it.clazz != event.source && oldClass.clazz.isAssignableFrom(it.clazz)) {
def newClass = application.classLoader.reloadClass(it.clazz.name)
application.addArtefact(type, newClass)
}
}
true
} else {
false
}
}
def onConfigChange = { event ->
event.application.mainContext.resourceService.reload()
}
/**
* We have to soft load this class so this file can be compiled on it's own.
*/
static getResourceMapperArtefactHandler() {
softLoadClass('org.grails.plugin.resources.artefacts.ResourceMapperArtefactHandler')
}
static getResourcesArtefactHandler() {
softLoadClass('org.grails.plugin.resources.artefacts.ResourcesArtefactHandler')
}
static softLoadClass(String className) {
try {
getClassLoader().loadClass(className)
} catch (ClassNotFoundException e) {
null
}
}
}