Skip to content

Commit

Permalink
grails#11494 Implemented MicronautGroovyPropertySourceLoader
Browse files Browse the repository at this point in the history
to read application.groovy configurations from Micronaut application context.
  • Loading branch information
puneetbehl committed Feb 28, 2020
1 parent 0421e15 commit 3ad099a
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.grails.core.cfg

import grails.util.BuildSettings
import grails.util.Environment
import grails.util.Metadata
import groovy.transform.CompileStatic
import io.micronaut.context.env.AbstractPropertySourceLoader
import io.micronaut.context.exceptions.ConfigurationException
import io.micronaut.core.io.ResourceLoader
import org.grails.config.NavigableMap

import java.util.concurrent.atomic.AtomicBoolean
import java.util.stream.Stream

/**
* Loads properties from a Groovy script.
*
* @author Puneet Behl
* @since 4.0.3
*/
@CompileStatic
class MicronautGroovyPropertySourceLoader extends AbstractPropertySourceLoader {

AtomicBoolean loaded = new AtomicBoolean(false)

@Override
int getOrder() {
return DEFAULT_POSITION
}

@Override
protected void processInput(String name, InputStream input, Map<String, Object> finalMap) throws IOException {
if (loaded.compareAndSet(false, true)) {
def env = Environment.current.name
if (input.available()) {
ConfigSlurper configSlurper = env ? new ConfigSlurper(env) : new ConfigSlurper()
configSlurper.setBinding(
userHome: System.getProperty('user.home'),
grailsHome: BuildSettings.GRAILS_HOME?.absolutePath,
appName: Metadata.getCurrent().getApplicationName(),
appVersion: Metadata.getCurrent().getApplicationVersion())
try {
def configObject = configSlurper.parse(input.getText("UTF-8"))
def propertySource = new NavigableMap()
propertySource.merge(configObject, false)
finalMap.putAll(propertySource)
} catch (Throwable e) {
throw new ConfigurationException("Exception occurred reading configuration [" + name + "]: " + e.getMessage(), e)
}
}

}
}

@Override
protected Optional<InputStream> readInput(ResourceLoader resourceLoader, String fileName) {
Stream<URL> urls = resourceLoader.getResources(fileName)
Stream<URL> urlStream = urls.filter({url -> !url.getPath().contains("src/main/groovy")})
Optional<URL> config = urlStream.findFirst()
if (config.isPresent()) {
return config.flatMap( {url ->
try {
return Optional.of(url.openStream())
} catch (IOException e) {
throw new ConfigurationException("Exception occurred reading configuration [" + fileName + "]: " + e.getMessage(), e)
}
})
}
return Optional.empty()
}

@Override
Set<String> getExtensions() {
return Collections.singleton("groovy")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.grails.core.cfg.MicronautGroovyPropertySourceLoader
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package org.grails.core.cfg

import grails.util.Metadata
import org.grails.config.NavigableMap
import spock.lang.Specification

@SuppressWarnings("GrMethodMayBeStatic")
class MicronautGroovyPropertySourceLoaderSpec extends Specification {

void "test parsing configuration file with DSL"() {

setup:
InputStream inputStream = new ByteArrayInputStream(applicationGroovyWithDsl)
MicronautGroovyPropertySourceLoader groovyPropertySourceLoader = new MicronautGroovyPropertySourceLoader()
Map<String, Object> finalMap = [:]

when:
groovyPropertySourceLoader.processInput("test-application.groovy", inputStream, finalMap)

then:
noExceptionThrown()
finalMap.get("grails") instanceof NavigableMap
finalMap.get("grails.gorm.default.constraints")
finalMap.get("grails.gorm.default.constraints") instanceof Closure
}

void "test parsing configuration file unknown variables as assignment"() {
setup:
InputStream inputStream = new ByteArrayInputStream(applicationGroovyWithUnknownVars)
MicronautGroovyPropertySourceLoader groovyPropertySourceLoader = new MicronautGroovyPropertySourceLoader()
Map<String, Object> finalMap = [:]

when:
groovyPropertySourceLoader.processInput("test-application.groovy", inputStream, finalMap)

then:
noExceptionThrown()
finalMap.containsKey("undefinedVar")
!finalMap.get("undefinedVar")
finalMap.containsKey("my.local.var")
!finalMap.get("my.local.var")
finalMap.get("my") instanceof NavigableMap
}

void "test parsing configuration for built-in variables"() {
setup:
Metadata.getInstance(new ByteArrayInputStream('''
info:
app:
name: test
version: 0.0
'''.bytes))
InputStream inputStream = new ByteArrayInputStream(applicationGroovyBuiltInVars)
MicronautGroovyPropertySourceLoader groovyPropertySourceLoader = new MicronautGroovyPropertySourceLoader()
Map<String, Object> finalMap = [:]

when:
groovyPropertySourceLoader.processInput("test-application.groovy", inputStream, finalMap)

then:
noExceptionThrown()
finalMap.get("userHomeVar")
finalMap.get("appNameVar")
finalMap.get("appVersionVar")

cleanup:
Metadata.reset()
}


private byte[] getApplicationGroovyWithDsl() {
'''
grails.gorm.default.constraints = {
'*'(nullable: true, size: 1..20)
}
'''.bytes
}

private byte[] getApplicationGroovyWithUnknownVars() {
'''
my.local.var = undefinedVar
'''.bytes
}

private byte[] getApplicationGroovyBuiltInVars() {
'''
userHomeVar=userHome
grailsHomeVar=grailsHome
appNameVar=appName
appVersionVar=appVersion
'''.bytes
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.grails.plugins.databinding


import org.grails.testing.GrailsUnitTest
import org.springframework.context.ConfigurableApplicationContext
import spock.lang.Specification

class GroovyConfigPropertySourceLoaderSpec extends Specification implements GrailsUnitTest {

void "test read config from application.groovy from parent Micronaut context"() {

expect:
((ConfigurableApplicationContext) applicationContext.parent).getEnvironment().getProperty("foo", String) == "bar"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo="bar"

0 comments on commit 3ad099a

Please sign in to comment.