Skip to content

Commit 35dd00e

Browse files
committed
Merge branch '3.2.x' into GRAILS-10141
2 parents 211a907 + bc0d233 commit 35dd00e

File tree

38 files changed

+3142
-212
lines changed

38 files changed

+3142
-212
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ apply plugin: 'idea'
2222
ext {
2323
bintrayPublish = false
2424
// Sets release version
25-
grailsVersion = '3.2.0.BUILD-SNAPSHOT'
25+
grailsVersion = '3.2.1.BUILD-SNAPSHOT'
2626
isBuildSnapshot = grailsVersion.endsWith(".BUILD-SNAPSHOT")
2727
isTravisBuild = System.getenv().get("TRAVIS") == 'true'
2828

grails-bom/build.gradle

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,23 @@ publishing {
165165
mkp.dependency {
166166
mkp.groupId 'org.grails.plugins'
167167
mkp.artifactId plugin.key
168-
mkp.version( plugin.value )
168+
def version = plugin.value
169+
if(!isBuildSnapshot && version.toString().endsWith("-SNAPSHOT")) {
170+
throw new RuntimeException("Cannot have a snapshot dependency on a plugin [$plugin.key] for a release!")
171+
}
172+
mkp.version(version)
169173
}
170174
}
171175

172176
for(profile in profiles) {
173177
mkp.dependency {
174178
mkp.groupId 'org.grails.profiles'
175179
mkp.artifactId profile.key
176-
mkp.version( profile.value )
180+
def version = profile.value
181+
if(!isBuildSnapshot && version.toString().endsWith("-SNAPSHOT")) {
182+
throw new RuntimeException("Cannot have a snapshot dependency on a profile [$profile.key] for a release!")
183+
}
184+
mkp.version(version)
177185
}
178186
}
179187
}

grails-bom/profiles.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ rest-api-plugin=3.2.0
44
base=3.2.0
55
plugin=3.2.0
66
web-plugin=3.2.0
7-
web=3.2.0
7+
web=3.2.1.BUILD-SNAPSHOT
88
profile=3.2.0

grails-bootstrap/src/main/groovy/grails/io/ResourceUtils.groovy

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,46 @@ class ResourceUtils extends GrailsResourceUtils {
4444
File rootDir = baseDir ? new File(baseDir, "grails-app") : null
4545
Set<String> packageNames = []
4646
if (rootDir?.exists()) {
47+
File[] allFiles = rootDir.listFiles()
4748
rootDir.eachDir { File dir ->
4849
def dirName = dir.name
4950
if (!dir.hidden && !dirName.startsWith('.') && !['conf', 'i18n', 'assets', 'views'].contains(dirName)) {
50-
populatePackages(dir, packageNames, "")
51+
File[] files = dir.listFiles()
52+
populatePackages(dir,files, packageNames, "")
5153
}
5254
}
5355
}
5456

5557
return packageNames
5658
}
5759

58-
protected static populatePackages(File rootDir, Collection<String> packageNames, String prefix) {
59-
rootDir.eachDir { File dir ->
60-
def dirName = dir.name
61-
if (!dir.hidden && !dirName.startsWith('.')) {
62-
packageNames << "${prefix}${dirName}".toString()
60+
protected static populatePackages(File rootDir, File[] files, Collection<String> packageNames, String prefix) {
6361

64-
populatePackages(dir, packageNames, "${prefix}${dirName}.")
62+
if(files != null) {
63+
for(dir in files ) {
64+
if(dir.isDirectory()) {
65+
String dirName = dir.name
66+
if (!dir.hidden && !dirName.startsWith('.')) {
67+
def dirFiles = dir.listFiles()
68+
if(dirFiles != null) {
69+
boolean hasGroovySources = dirFiles?.find() { File f -> f.name.endsWith('.groovy') }
70+
if(hasGroovySources) {
71+
// if there are Groovy sources stop here, no need to add child packages
72+
packageNames.add "${prefix}${dirName}".toString()
73+
}
74+
else {
75+
// otherwise recurse into a child package
76+
populatePackages(dir, dirFiles, packageNames, "${prefix}${dirName}.")
77+
}
78+
}
79+
80+
}
81+
}
82+
else {
83+
if(dir.name.endsWith('.groovy') && prefix == "") {
84+
packageNames.add("")
85+
}
86+
}
6587
}
6688
}
6789
}

grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import org.grails.config.PrefixedMapPropertySource
1919
import org.grails.config.PropertySourcesConfig
2020
import org.grails.core.exceptions.GrailsConfigurationException
2121
import org.grails.core.lifecycle.ShutdownOperations
22+
import org.grails.core.util.ClassPropertyFetcher
2223
import org.grails.dev.support.GrailsSpringLoadedPlugin
2324
import org.grails.spring.DefaultRuntimeSpringConfiguration
2425
import org.grails.spring.RuntimeSpringConfigUtilities
@@ -70,7 +71,7 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces
7071
this.applicationClass = null
7172
}
7273
this.classes = classes != null ? classes : [] as Class[]
73-
grailsApplication = new DefaultGrailsApplication()
74+
grailsApplication = applicationClass != null ? new DefaultGrailsApplication(applicationClass) : new DefaultGrailsApplication()
7475
pluginManager = new DefaultGrailsPluginManager(grailsApplication)
7576
if(applicationContext != null) {
7677
setApplicationContext(applicationContext)
@@ -89,6 +90,7 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces
8990
loadApplicationConfig()
9091
customizeGrailsApplication(grailsApplication)
9192
performGrailsInitializationSequence()
93+
ClassPropertyFetcher.clearClassPropertyFetcherCache()
9294
}
9395

9496
protected void customizePluginManager(GrailsPluginManager grailsApplication) {

grails-core/src/main/groovy/grails/boot/config/GrailsAutoConfiguration.groovy

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import groovy.transform.CompileStatic
99
import groovy.transform.InheritConstructors
1010
import groovy.transform.Memoized
1111
import groovy.util.logging.Slf4j
12+
import org.grails.asm.AnnotationMetadataReader
1213
import org.grails.compiler.injection.AbstractGrailsArtefactTransformer
1314
import org.grails.spring.aop.autoproxy.GroovyAwareAspectJAwareAdvisorAutoProxyCreator
1415
import org.springframework.aop.config.AopConfigUtils
@@ -33,6 +34,7 @@ import java.lang.reflect.Field
3334
*
3435
*/
3536
@CompileStatic
37+
@Slf4j
3638
class GrailsAutoConfiguration implements GrailsApplicationClass, ApplicationContextAware {
3739

3840
private static final String APC_PRIORITY_LIST_FIELD = "APC_PRIORITY_LIST";
@@ -77,15 +79,24 @@ class GrailsAutoConfiguration implements GrailsApplicationClass, ApplicationCont
7779
if(ignoredRootPackages().contains(pkg)) {
7880
continue
7981
}
80-
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
81-
ClassUtils.convertClassNameToResourcePath(pkg) + Settings.CLASS_RESOURCE_PATTERN;
82+
// if it is the default package
83+
if(pkg == "") {
84+
// try the default package in case of a script without recursing into subpackages
85+
log.error("The application defines a Groovy source using the default package. Please move all Groovy sources into a package.")
86+
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "*.class"
87+
classes.addAll scanUsingPattern(pattern, readerFactory)
88+
}
89+
else {
90+
91+
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
92+
ClassUtils.convertClassNameToResourcePath(pkg) + Settings.CLASS_RESOURCE_PATTERN;
93+
94+
95+
classes.addAll scanUsingPattern(pattern, readerFactory)
96+
}
8297

83-
classes.addAll scanUsingPattern(pattern, readerFactory)
8498
}
8599

86-
// try the default package in case of a script without recursing into subpackages
87-
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "*.class"
88-
classes.addAll scanUsingPattern(pattern, readerFactory)
89100

90101
def classLoader = Thread.currentThread().contextClassLoader
91102
for(cls in AbstractGrailsArtefactTransformer.transformedClassNames) {
@@ -139,7 +150,7 @@ class GrailsAutoConfiguration implements GrailsApplicationClass, ApplicationCont
139150
for (Resource res in resources) {
140151
// ignore closures / inner classes
141152
if(!res.filename.contains('$') && !res.filename.startsWith("gsp_")) {
142-
def reader = readerFactory.getMetadataReader(res)
153+
def reader = new AnnotationMetadataReader(res, classLoader)
143154
def metadata = reader.annotationMetadata
144155
if (metadata.annotationTypes.any() { String annotation -> annotation.startsWith('grails.') }) {
145156
classes << classLoader.loadClass(reader.classMetadata.className)
@@ -234,10 +245,10 @@ class GrailsAutoConfiguration implements GrailsApplicationClass, ApplicationCont
234245

235246
this.rootResource = getURLs()[0]
236247
this.applicationClass = applicationClass
237-
def urlStr = rootResource.toString()
248+
String urlStr = rootResource.toString()
238249
jarDeployed = urlStr.startsWith("jar:")
239250
try {
240-
def withoutBang = new URL("${urlStr.substring(0, urlStr.length() - 2)}/")
251+
URL withoutBang = new URL("${urlStr.substring(0, urlStr.length() - 2)}/")
241252
addURL(withoutBang)
242253

243254
} catch (MalformedURLException e) {

grails-core/src/main/groovy/grails/core/DefaultGrailsApplication.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,22 @@ public class DefaultGrailsApplication extends AbstractGrailsApplication implemen
9191
protected Class<?>[] allArtefactClassesArray;
9292
protected Resource[] resources;
9393
protected boolean initialised = false;
94+
protected GrailsApplicationClass applicationClass;
9495

9596
/**
9697
* Creates a new empty Grails application.
9798
*/
9899
public DefaultGrailsApplication() {
99100
this(new GroovyClassLoader());
100101
}
102+
103+
/**
104+
* Creates a new empty Grails application.
105+
*/
106+
public DefaultGrailsApplication(GrailsApplicationClass applicationClass) {
107+
this(new GroovyClassLoader());
108+
this.applicationClass = applicationClass;
109+
}
101110

102111
public DefaultGrailsApplication(ClassLoader classLoader) {
103112
super();
@@ -168,6 +177,13 @@ public DefaultGrailsApplication(org.grails.io.support.Resource[] resources) {
168177
}
169178
}
170179

180+
/**
181+
* @return The application class
182+
*/
183+
public GrailsApplicationClass getApplicationClass() {
184+
return applicationClass;
185+
}
186+
171187
/**
172188
* Initialises the default set of ArtefactHandler instances.
173189
*
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package org.grails.asm;
2+
3+
import org.springframework.asm.AnnotationVisitor;
4+
import org.springframework.asm.SpringAsmInfo;
5+
import org.springframework.asm.Type;
6+
import org.springframework.core.NestedIOException;
7+
import org.springframework.core.io.Resource;
8+
import org.springframework.core.type.AnnotationMetadata;
9+
import org.springframework.core.type.ClassMetadata;
10+
import org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor;
11+
import org.springframework.core.type.classreading.MetadataReader;
12+
13+
import java.io.BufferedInputStream;
14+
import java.io.IOException;
15+
import java.io.InputStream;
16+
17+
/**
18+
* A more limited version of Spring's annotation reader that only reads annotations on classes
19+
*
20+
* @author Graeme Rocher
21+
* @since 3.1.13
22+
*/
23+
public class AnnotationMetadataReader implements MetadataReader {
24+
private final Resource resource;
25+
26+
private final ClassMetadata classMetadata;
27+
28+
private final AnnotationMetadata annotationMetadata;
29+
30+
/**
31+
* Reads only the annotation names from a class resource
32+
* @param resource The resource
33+
* @param classLoader The classloader
34+
* @throws IOException
35+
*/
36+
public AnnotationMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
37+
this(resource, classLoader, false);
38+
}
39+
/**
40+
* Constructs a new annotation metadata reader
41+
*
42+
* @param resource The resource
43+
* @param classLoader The classloader
44+
* @param readAttributeValues Whether to read the attributes in addition or just the annotation class names
45+
* @throws IOException
46+
*/
47+
public AnnotationMetadataReader(Resource resource, ClassLoader classLoader, boolean readAttributeValues) throws IOException {
48+
InputStream is = new BufferedInputStream(resource.getInputStream());
49+
ClassReader classReader;
50+
try {
51+
classReader = new ClassReader(is);
52+
}
53+
catch (IllegalArgumentException ex) {
54+
throw new NestedIOException("ASM ClassReader failed to parse class file - " +
55+
"probably due to a new Java class file version that isn't supported yet: " + resource, ex);
56+
}
57+
finally {
58+
is.close();
59+
}
60+
61+
62+
AnnotationMetadataReadingVisitor visitor;
63+
64+
if(readAttributeValues) {
65+
visitor = new AnnotationMetadataReadingVisitor(classLoader);
66+
}
67+
else {
68+
visitor = new AnnotationMetadataReadingVisitor(classLoader) {
69+
@Override
70+
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
71+
String className = Type.getType(desc).getClassName();
72+
this.annotationSet.add(className);
73+
return new EmptyAnnotationVisitor();
74+
}
75+
};
76+
}
77+
classReader.accept(visitor, ClassReader.SKIP_DEBUG);
78+
79+
this.annotationMetadata = visitor;
80+
// (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor)
81+
this.classMetadata = visitor;
82+
this.resource = resource;
83+
}
84+
85+
86+
@Override
87+
public Resource getResource() {
88+
return this.resource;
89+
}
90+
91+
@Override
92+
public ClassMetadata getClassMetadata() {
93+
return this.classMetadata;
94+
}
95+
96+
@Override
97+
public AnnotationMetadata getAnnotationMetadata() {
98+
return this.annotationMetadata;
99+
}
100+
101+
private static class EmptyAnnotationVisitor extends AnnotationVisitor {
102+
103+
public EmptyAnnotationVisitor() {
104+
super(SpringAsmInfo.ASM_VERSION);
105+
}
106+
107+
@Override
108+
public AnnotationVisitor visitAnnotation(String name, String desc) {
109+
return this;
110+
}
111+
112+
@Override
113+
public AnnotationVisitor visitArray(String name) {
114+
return this;
115+
}
116+
}
117+
}

0 commit comments

Comments
 (0)