-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
54aca7a
commit dd7e4f7
Showing
16 changed files
with
435 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
.idea | ||
*.iml | ||
*.ipr | ||
*.iws | ||
.classpath | ||
target | ||
out | ||
plugin.xml | ||
*.zip | ||
*.log | ||
.project | ||
.settings |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
class FeatureSwitchGrailsPlugin { | ||
// the plugin version | ||
def version = "0.1" | ||
// the version or versions of Grails the plugin is designed for | ||
def grailsVersion = "2.0 > *" | ||
// the other plugins this plugin depends on | ||
def dependsOn = [:] | ||
// resources that are excluded from plugin packaging | ||
def pluginExcludes = [ | ||
"grails-app/views/error.gsp" | ||
] | ||
|
||
// TODO Fill in these fields | ||
def title = "Feature Switch Plugin" | ||
def author = "Antony Jones and Matt Tortolani" | ||
def authorEmail = "" | ||
def description = 'Allows turning on and off of features' | ||
|
||
// URL to the plugin's documentation | ||
def documentation = "http://grails.org/plugin/feature-switch" | ||
|
||
// Extra (optional) plugin metadata | ||
|
||
// License: one of 'APACHE', 'GPL2', 'GPL3' | ||
def license = "APACHE" | ||
|
||
// Details of company behind the plugin (if there is one) | ||
// def organization = [ name: "My Company", url: "http://www.my-company.com/" ] | ||
|
||
// Any additional developers beyond the author specified above. | ||
def developers = [ | ||
[ name: "Antony Jones", email: "aj/desirableobjects.co.uk" ], | ||
[ name: "Matt Tortolani", email: "hello/doodlemoonch.com", ] | ||
] | ||
|
||
// Location of the plugin's issue tracker. | ||
// def issueManagement = [ system: "JIRA", url: "http://jira.grails.org/browse/GPMYPLUGIN" ] | ||
|
||
// Online location of the plugin's browseable source code. | ||
// def scm = [ url: "http://svn.grails-plugins.codehaus.org/browse/grails-plugins/" ] | ||
|
||
def doWithWebDescriptor = { xml -> | ||
// TODO Implement additions to web.xml (optional), this event occurs before | ||
} | ||
|
||
def doWithSpring = { | ||
// TODO Implement runtime spring config (optional) | ||
} | ||
|
||
def doWithDynamicMethods = { ctx -> | ||
// TODO Implement registering dynamic methods to classes (optional) | ||
} | ||
|
||
def doWithApplicationContext = { applicationContext -> | ||
// TODO Implement post initialization spring config (optional) | ||
} | ||
|
||
def onChange = { event -> | ||
// TODO Implement code that is executed when any artefact that this plugin is | ||
// watching is modified and reloaded. The event contains: event.source, | ||
// event.application, event.manager, event.ctx, and event.plugin. | ||
} | ||
|
||
def onConfigChange = { event -> | ||
// TODO Implement code that is executed when the project configuration changes. | ||
// The event is the same as for 'onChange'. | ||
} | ||
|
||
def onShutdown = { event -> | ||
// TODO Implement code that is executed when the application shuts down (optional) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#Grails Metadata file | ||
#Mon Aug 20 15:21:45 BST 2012 | ||
app.grails.version=2.0.3 | ||
app.name=feature-switch | ||
plugins.svn=1.0.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
grails.project.class.dir = "target/classes" | ||
grails.project.test.class.dir = "target/test-classes" | ||
grails.project.test.reports.dir = "target/test-reports" | ||
grails.project.target.level = 1.6 | ||
//grails.project.war.file = "target/${appName}-${appVersion}.war" | ||
|
||
grails.project.dependency.resolution = { | ||
// inherit Grails' default dependencies | ||
inherits("global") { | ||
// uncomment to disable ehcache | ||
// excludes 'ehcache' | ||
} | ||
log "warn" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose' | ||
repositories { | ||
grailsCentral() | ||
// uncomment the below to enable remote dependency resolution | ||
// from public Maven repositories | ||
mavenLocal | ||
mavenCentral() | ||
//mavenRepo "http://snapshots.repository.codehaus.org" | ||
//mavenRepo "http://repository.codehaus.org" | ||
//mavenRepo "http://download.java.net/maven/2/" | ||
//mavenRepo "http://repository.jboss.com/maven2/" | ||
} | ||
dependencies { | ||
|
||
} | ||
|
||
plugins { | ||
|
||
test ':spock:0.6' | ||
|
||
build(":tomcat:$grailsVersion", | ||
":release:1.0.0") { | ||
export = false | ||
} | ||
|
||
|
||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// configuration for plugin testing - will not be included in the plugin zip | ||
|
||
log4j = { | ||
// Example of changing the log pattern for the default console | ||
// appender: | ||
// | ||
//appenders { | ||
// console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n') | ||
//} | ||
|
||
error 'org.codehaus.groovy.grails.web.servlet', // controllers | ||
'org.codehaus.groovy.grails.web.pages', // GSP | ||
'org.codehaus.groovy.grails.web.sitemesh', // layouts | ||
'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping | ||
'org.codehaus.groovy.grails.web.mapping', // URL mapping | ||
'org.codehaus.groovy.grails.commons', // core / classloading | ||
'org.codehaus.groovy.grails.plugins', // plugins | ||
'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration | ||
'org.springframework', | ||
'org.hibernate', | ||
'net.sf.ehcache.hibernate' | ||
|
||
warn 'org.mortbay.log' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
dataSource { | ||
pooled = true | ||
driverClassName = "org.h2.Driver" | ||
username = "sa" | ||
password = "" | ||
} | ||
hibernate { | ||
cache.use_second_level_cache = true | ||
cache.use_query_cache = false | ||
cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' | ||
} | ||
// environment specific settings | ||
environments { | ||
development { | ||
dataSource { | ||
dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', '' | ||
url = "jdbc:h2:mem:devDb;MVCC=TRUE" | ||
} | ||
} | ||
test { | ||
dataSource { | ||
dbCreate = "update" | ||
url = "jdbc:h2:mem:testDb;MVCC=TRUE" | ||
} | ||
} | ||
production { | ||
dataSource { | ||
dbCreate = "update" | ||
url = "jdbc:h2:prodDb;MVCC=TRUE" | ||
pooled = true | ||
properties { | ||
maxActive = -1 | ||
minEvictableIdleTimeMillis=1800000 | ||
timeBetweenEvictionRunsMillis=1800000 | ||
numTestsPerEvictionRun=3 | ||
testOnBorrow=true | ||
testWhileIdle=true | ||
testOnReturn=true | ||
validationQuery="SELECT 1" | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
class UrlMappings { | ||
|
||
static mappings = { | ||
"/$controller/$action?/$id?"{ | ||
constraints { | ||
// apply constraints here | ||
} | ||
} | ||
|
||
"/"(view:"/index") | ||
"500"(view:'/error') | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
grails-app/services/uk/co/desirableobjects/featureswitch/FeatureSwitchService.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package uk.co.desirableobjects.featureswitch | ||
|
||
import org.codehaus.groovy.grails.commons.GrailsApplication | ||
|
||
class FeatureSwitchService { | ||
|
||
GrailsApplication grailsApplication | ||
|
||
boolean hasFeature(String feature) { | ||
|
||
return grailsApplication.config.features[feature].enabled | ||
|
||
} | ||
|
||
def withFeature(String feature, Closure closure) { | ||
|
||
if (hasFeature(feature)) { | ||
closure() | ||
} | ||
|
||
} | ||
|
||
} |
30 changes: 30 additions & 0 deletions
30
grails-app/taglib/uk/co/desirableobjects/featureswitch/FeatureSwitchTagLib.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package uk.co.desirableobjects.featureswitch | ||
|
||
class FeatureSwitchTagLib { | ||
|
||
static namespace = 'feature' | ||
|
||
FeatureSwitchService featureSwitchService | ||
|
||
def enabled = { attrs, body -> | ||
|
||
renderByFeature(attrs, true, body) | ||
|
||
} | ||
|
||
private renderByFeature(Map attrs, boolean condition, Closure body) { | ||
|
||
String feature = attrs.feature | ||
|
||
if (featureSwitchService.hasFeature(feature) == condition) { | ||
out << body() | ||
} | ||
} | ||
|
||
def disabled = { attrs, body -> | ||
|
||
renderByFeature(attrs, false, body) | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<title>Grails Runtime Exception</title> | ||
<meta name="layout" content="main"> | ||
<link rel="stylesheet" href="${resource(dir: 'css', file: 'errors.css')}" type="text/css"> | ||
</head> | ||
<body> | ||
<g:renderException exception="${exception}" /> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// | ||
// This script is executed by Grails after plugin was installed to project. | ||
// This script is a Gant script so you can use all special variables provided | ||
// by Gant (such as 'baseDir' which points on project base dir). You can | ||
// use 'ant' to access a global instance of AntBuilder | ||
// | ||
// For example you can create directory under project tree: | ||
// | ||
// ant.mkdir(dir:"${basedir}/grails-app/jobs") | ||
// |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// | ||
// This script is executed by Grails when the plugin is uninstalled from project. | ||
// Use this script if you intend to do any additional clean-up on uninstall, but | ||
// beware of messing up SVN directories! | ||
// |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// | ||
// This script is executed by Grails during application upgrade ('grails upgrade' | ||
// command). This script is a Gant script so you can use all special variables | ||
// provided by Gant (such as 'baseDir' which points on project base dir). You can | ||
// use 'ant' to access a global instance of AntBuilder | ||
// | ||
// For example you can create directory under project tree: | ||
// | ||
// ant.mkdir(dir:"${basedir}/grails-app/jobs") | ||
// |
13 changes: 13 additions & 0 deletions
13
src/groovy/uk/co/desirableobjects/featureswitch/InnocentClass.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package uk.co.desirableobjects.featureswitch | ||
|
||
class InnocentClass { | ||
|
||
def testWith() { | ||
boolean result = false | ||
withFeature('eggs') { | ||
result = true | ||
} | ||
return result | ||
} | ||
|
||
} |
67 changes: 67 additions & 0 deletions
67
test/unit/uk/co/desirableobjects/featureswitch/SwitchFeatureSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package uk.co.desirableobjects.featureswitch | ||
|
||
import spock.lang.Specification | ||
|
||
import grails.test.mixin.support.GrailsUnitTestMixin | ||
import spock.lang.Unroll | ||
import grails.test.mixin.TestFor | ||
|
||
@Mixin(GrailsUnitTestMixin) | ||
@TestFor(FeatureSwitchService) | ||
class SwitchFeatureSpec extends Specification { | ||
|
||
void setup() { | ||
|
||
InnocentClass.metaClass.withFeature = { String feature, Closure closure -> service.withFeature(feature, closure) } | ||
|
||
} | ||
|
||
@Unroll | ||
def 'A feature can be set to enabled = #enabled'() { | ||
|
||
given: | ||
service.grailsApplication.config.features.eggs.enabled = enabled | ||
|
||
expect: | ||
service.hasFeature('eggs') == enabled | ||
|
||
where: | ||
enabled << [true, false] | ||
|
||
} | ||
|
||
def 'When there is no configuration'() { | ||
|
||
given: | ||
service.grailsApplication.config = [:] | ||
|
||
expect: | ||
!service.hasFeature('peas') | ||
|
||
} | ||
|
||
def 'When a requested feature does not exist'() { | ||
|
||
given: | ||
service.grailsApplication.config.features.eggs.enabled = true | ||
|
||
expect: | ||
!service.hasFeature('dogs') | ||
|
||
} | ||
|
||
@Unroll | ||
def 'User can use withFeature in a class which is decorated with it, where feature = #enabled'() { | ||
|
||
given: | ||
service.grailsApplication.config.features.eggs.enabled = enabled | ||
|
||
expect: | ||
new InnocentClass().testWith() == enabled | ||
|
||
where: | ||
enabled << [true, false] | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.