Browse Source

SEC-2915: groovy/gradle spaces->tabs

Rob Winch 10 years ago
parent
commit
0a2e496a84
100 changed files with 6024 additions and 6024 deletions
  1. 12 12
      acl/acl.gradle
  2. 6 6
      aspects/aspects.gradle
  3. 1 1
      bom/build.gradle
  4. 109 109
      build.gradle
  5. 16 16
      buildSrc/build.gradle
  6. 46 46
      buildSrc/src/main/groovy/MavenBomTask.groovy
  7. 93 93
      buildSrc/src/main/groovy/aspectj/AspectJPlugin.groovy
  8. 84 84
      buildSrc/src/main/groovy/emma/EmmaPlugin.groovy
  9. 15 15
      buildSrc/src/main/groovy/gae/GaePlugin.groovy
  10. 34 34
      buildSrc/src/main/groovy/trang/TrangPlugin.groovy
  11. 9 9
      cas/cas.gradle
  12. 54 54
      config/config.gradle
  13. 52 52
      config/src/test/groovy/org/springframework/security/config/AbstractXmlConfigTests.groovy
  14. 116 116
      config/src/test/groovy/org/springframework/security/config/annotation/BaseSpringSpec.groovy
  15. 15 15
      config/src/test/groovy/org/springframework/security/config/annotation/SecurityConfigurerAdapterTests.groovy
  16. 52 52
      config/src/test/groovy/org/springframework/security/config/annotation/issue50/Issue50Tests.groovy
  17. 96 96
      config/src/test/groovy/org/springframework/security/config/annotation/sec2758/Sec2758Tests.groovy
  18. 28 28
      config/src/test/groovy/org/springframework/security/config/annotation/web/RequestMatchersTests.groovy
  19. 437 437
      config/src/test/groovy/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.groovy
  20. 12 12
      config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/BaseWebConfig.groovy
  21. 72 72
      config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.groovy
  22. 75 75
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/Issue55Tests.groovy
  23. 1 1
      config/src/test/groovy/org/springframework/security/config/debug/AuthProviderDependency.groovy
  24. 10 10
      config/src/test/groovy/org/springframework/security/config/debug/TestAuthenticationProvider.groovy
  25. 6 6
      config/src/test/groovy/org/springframework/security/config/doc/Attribute.groovy
  26. 60 60
      config/src/test/groovy/org/springframework/security/config/doc/Element.groovy
  27. 139 139
      config/src/test/groovy/org/springframework/security/config/doc/SpringSecurityXsdParser.groovy
  28. 163 163
      config/src/test/groovy/org/springframework/security/config/doc/XsdDocumentedTests.groovy
  29. 39 39
      config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy
  30. 30 30
      config/src/test/groovy/org/springframework/security/config/http/AccessDeniedConfigTests.groovy
  31. 282 282
      config/src/test/groovy/org/springframework/security/config/http/CsrfConfigTests.groovy
  32. 75 75
      config/src/test/groovy/org/springframework/security/config/http/FormLoginBeanDefinitionParserTests.groovy
  33. 89 89
      config/src/test/groovy/org/springframework/security/config/http/FormLoginConfigTests.groovy
  34. 15 15
      config/src/test/groovy/org/springframework/security/config/http/HttpConfigTests.groovy
  35. 616 616
      config/src/test/groovy/org/springframework/security/config/http/HttpHeadersConfigTests.groovy
  36. 128 128
      config/src/test/groovy/org/springframework/security/config/http/HttpOpenIDConfigTests.groovy
  37. 68 68
      config/src/test/groovy/org/springframework/security/config/http/InterceptUrlConfigTests.groovy
  38. 698 698
      config/src/test/groovy/org/springframework/security/config/http/MiscHttpConfigTests.groovy
  39. 94 94
      config/src/test/groovy/org/springframework/security/config/http/MultiHttpBlockConfigTests.groovy
  40. 136 136
      config/src/test/groovy/org/springframework/security/config/http/PlaceHolderAndELConfigTests.groovy
  41. 265 265
      config/src/test/groovy/org/springframework/security/config/http/RememberMeConfigTests.groovy
  42. 371 371
      config/src/test/groovy/org/springframework/security/config/http/SessionManagementConfigTests.groovy
  43. 30 30
      core/core.gradle
  44. 4 4
      crypto/crypto.gradle
  45. 3 3
      data/data.gradle
  46. 115 115
      docs/docs.gradle
  47. 32 32
      docs/guides/build.gradle
  48. 124 124
      gradle/javaprojects.gradle
  49. 101 101
      gradle/maven-deployment.gradle
  50. 14 14
      gradle/release-checks.gradle
  51. 49 49
      gradle/tomcat.gradle
  52. 2 2
      gradle/war-sample.gradle
  53. 12 12
      itest/context/itest-context.gradle
  54. 29 29
      itest/web/itest-web.gradle
  55. 26 26
      ldap/ldap.gradle
  56. 17 17
      messaging/messaging.gradle
  57. 17 17
      openid/openid.gradle
  58. 7 7
      remoting/remoting.gradle
  59. 4 4
      samples/aspectj-jc/build.gradle
  60. 4 4
      samples/aspectj-xml/aspectj.gradle
  61. 88 88
      samples/cas/sample-xml/cassample.gradle
  62. 43 43
      samples/cas/server/casserver.gradle
  63. 30 30
      samples/chat-jc/build.gradle
  64. 18 18
      samples/concurrency-jc/build.gradle
  65. 20 20
      samples/contacts-xml/contacts.gradle
  66. 53 53
      samples/contacts-xml/src/integration-test/groovy/org/springframework/security/samples/ContactsTests.groovy
  67. 12 12
      samples/contacts-xml/src/integration-test/groovy/org/springframework/security/samples/pages/AddPage.groovy
  68. 8 8
      samples/contacts-xml/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy
  69. 12 12
      samples/contacts-xml/src/integration-test/groovy/org/springframework/security/samples/pages/LoginPage.groovy
  70. 8 8
      samples/data-jc/build.gradle
  71. 10 10
      samples/dms-xml/dms.gradle
  72. 19 19
      samples/form-jc/build.gradle
  73. 25 25
      samples/form-jc/src/integration-test/groovy/org/springframework/security/samples/FormJcTests.groovy
  74. 7 7
      samples/form-jc/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy
  75. 12 12
      samples/form-jc/src/integration-test/groovy/org/springframework/security/samples/pages/LoginPage.groovy
  76. 32 32
      samples/gae-xml/gae.gradle
  77. 19 19
      samples/hellojs-jc/build.gradle
  78. 19 19
      samples/hellomvc-jc/build.gradle
  79. 8 8
      samples/helloworld-jc/build.gradle
  80. 7 7
      samples/helloworld-jc/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy
  81. 8 8
      samples/helloworld-xml/build.gradle
  82. 19 19
      samples/inmemory-jc/build.gradle
  83. 6 6
      samples/insecure/build.gradle
  84. 9 9
      samples/insecure/src/integration-test/groovy/org/springframework/security/samples/HelloInsecureTests.groovy
  85. 6 6
      samples/insecure/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy
  86. 15 15
      samples/insecuremvc/build.gradle
  87. 17 17
      samples/jaas-xml/jaas.gradle
  88. 29 29
      samples/jaas-xml/src/integration-test/groovy/org/springframework/security/samples/JaasXmlTests.groovy
  89. 6 6
      samples/jaas-xml/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy
  90. 12 12
      samples/jaas-xml/src/integration-test/groovy/org/springframework/security/samples/pages/LoginPage.groovy
  91. 3 3
      samples/jaas-xml/src/integration-test/groovy/org/springframework/security/samples/pages/LogoutPage.groovy
  92. 7 7
      samples/jaas-xml/src/integration-test/groovy/org/springframework/security/samples/pages/SecurePage.groovy
  93. 19 19
      samples/jdbc-jc/build.gradle
  94. 25 25
      samples/jdbc-jc/src/integration-test/groovy/org/springframework/security/samples/JdbcJcTests.groovy
  95. 7 7
      samples/jdbc-jc/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy
  96. 12 12
      samples/jdbc-jc/src/integration-test/groovy/org/springframework/security/samples/pages/LoginPage.groovy
  97. 21 21
      samples/ldap-jc/build.gradle
  98. 25 25
      samples/ldap-jc/src/integration-test/groovy/org/springframework/security/samples/LdapJcTests.groovy
  99. 7 7
      samples/ldap-jc/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy
  100. 12 12
      samples/ldap-jc/src/integration-test/groovy/org/springframework/security/samples/pages/LoginPage.groovy

+ 12 - 12
acl/acl.gradle

@@ -1,19 +1,19 @@
 // Acl Module build file
 
 dependencies {
-    compile project(':spring-security-core'),
-            springCoreDependency,
-            'aopalliance:aopalliance:1.0',
-            "org.springframework:spring-aop:$springVersion",
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-tx:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion"
+	compile project(':spring-security-core'),
+			springCoreDependency,
+			'aopalliance:aopalliance:1.0',
+			"org.springframework:spring-aop:$springVersion",
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-tx:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion"
 
-    optional "net.sf.ehcache:ehcache:$ehcacheVersion"
+	optional "net.sf.ehcache:ehcache:$ehcacheVersion"
 
-    testCompile "org.springframework:spring-beans:$springVersion",
-                "org.springframework:spring-context-support:$springVersion",
-                "org.springframework:spring-test:$springVersion"
+	testCompile "org.springframework:spring-beans:$springVersion",
+				"org.springframework:spring-context-support:$springVersion",
+				"org.springframework:spring-test:$springVersion"
 
-    testRuntime "org.hsqldb:hsqldb:$hsqlVersion"
+	testRuntime "org.hsqldb:hsqldb:$hsqlVersion"
 }

+ 6 - 6
aspects/aspects.gradle

@@ -1,10 +1,10 @@
 
 dependencies {
-    compile project(':spring-security-core'),
-            springCoreDependency,
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-context:$springVersion"
+	compile project(':spring-security-core'),
+			springCoreDependency,
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-context:$springVersion"
 
-    testCompile 'aopalliance:aopalliance:1.0',
-                "org.springframework:spring-aop:$springVersion"
+	testCompile 'aopalliance:aopalliance:1.0',
+				"org.springframework:spring-aop:$springVersion"
 }

+ 1 - 1
bom/build.gradle

@@ -5,5 +5,5 @@ generatePom.enabled = false
 sonarRunner.skipProject = true
 
 mavenBom {
-    projects = coreModuleProjects
+	projects = coreModuleProjects
 }

+ 109 - 109
build.gradle

@@ -1,17 +1,17 @@
 import groovy.text.SimpleTemplateEngine
 
 buildscript {
-    repositories {
-        maven { url "https://repo.spring.io/plugins-release" }
-    }
-    dependencies {
-        classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
-        classpath("org.springframework.build.gradle:spring-io-plugin:0.0.3.RELEASE")
-        classpath("org.gradle.api.plugins:gradle-tomcat-plugin:1.2.5")
-        classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
-        classpath('org.asciidoctor:asciidoctor-gradle-plugin:1.5.1')
-        classpath("io.spring.gradle:docbook-reference-plugin:0.3.0")
-    }
+	repositories {
+		maven { url "https://repo.spring.io/plugins-release" }
+	}
+	dependencies {
+		classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
+		classpath("org.springframework.build.gradle:spring-io-plugin:0.0.3.RELEASE")
+		classpath("org.gradle.api.plugins:gradle-tomcat-plugin:1.2.5")
+		classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
+		classpath('org.asciidoctor:asciidoctor-gradle-plugin:1.5.1')
+		classpath("io.spring.gradle:docbook-reference-plugin:0.3.0")
+	}
 }
 
 apply plugin: 'sonar-runner'
@@ -20,38 +20,38 @@ apply plugin: 'base'
 description = 'Spring Security'
 
 allprojects {
-    apply plugin: 'idea'
-    apply plugin: 'eclipse'
+	apply plugin: 'idea'
+	apply plugin: 'eclipse'
 
-    ext.releaseBuild = version.endsWith('RELEASE')
-    ext.snapshotBuild = version.endsWith('SNAPSHOT')
-    ext.springVersion = '4.1.5.RELEASE'
-    ext.springLdapVersion = '2.0.2.RELEASE'
+	ext.releaseBuild = version.endsWith('RELEASE')
+	ext.snapshotBuild = version.endsWith('SNAPSHOT')
+	ext.springVersion = '4.1.5.RELEASE'
+	ext.springLdapVersion = '2.0.2.RELEASE'
 
-    group = 'org.springframework.security'
+	group = 'org.springframework.security'
 
-    repositories {
-       mavenCentral()
-       maven { url "https://repo.spring.io/libs-snapshot" }
-       maven { url "https://repo.spring.io/plugins-release" }
-       maven { url "http://repo.terracotta.org/maven2/" }
-    }
+	repositories {
+	   mavenCentral()
+	   maven { url "https://repo.spring.io/libs-snapshot" }
+	   maven { url "https://repo.spring.io/plugins-release" }
+	   maven { url "http://repo.terracotta.org/maven2/" }
+	}
 
-    eclipse.project.name = "${project.name}-4.0.x"
+	eclipse.project.name = "${project.name}-4.0.x"
 }
 
 sonarRunner {
-    sonarProperties {
-        property "sonar.java.coveragePlugin", "jacoco"
-        property "sonar.projectName", "Spring Security"
-        property "sonar.jacoco.reportPath", "${buildDir.name}/jacoco.exec"
-        property "sonar.links.homepage", 'https://www.springsource.org/spring-security'
-        property "sonar.links.ci", 'https://build.springsource.org/browse/SEC-B32X'
-        property "sonar.links.issue", 'https://jira.springsource.org/browse/SEC'
-        property "sonar.links.scm", 'https://github.com/SpringSource/spring-security'
-        property "sonar.links.scm_dev", 'https://github.com/SpringSource/spring-security.git'
-        property "sonar.java.coveragePlugin", "jacoco"
-    }
+	sonarProperties {
+		property "sonar.java.coveragePlugin", "jacoco"
+		property "sonar.projectName", "Spring Security"
+		property "sonar.jacoco.reportPath", "${buildDir.name}/jacoco.exec"
+		property "sonar.links.homepage", 'https://www.springsource.org/spring-security'
+		property "sonar.links.ci", 'https://build.springsource.org/browse/SEC-B32X'
+		property "sonar.links.issue", 'https://jira.springsource.org/browse/SEC'
+		property "sonar.links.scm", 'https://github.com/SpringSource/spring-security'
+		property "sonar.links.scm_dev", 'https://github.com/SpringSource/spring-security.git'
+		property "sonar.java.coveragePlugin", "jacoco"
+	}
 }
 
 // Set up different subproject lists for individual configuration
@@ -62,105 +62,105 @@ ext.coreModuleProjects = javaProjects - sampleProjects - itestProjects
 ext.aspectjProjects = [project(':spring-security-aspects'), project(':spring-security-samples-aspectj-xml'), project(':spring-security-samples-aspectj-jc')]
 
 configure(allprojects - javaProjects) {
-    task afterEclipseImport {
-        ext.srcFile = file('.classpath')
-        inputs.file srcFile
-        outputs.dir srcFile
+	task afterEclipseImport {
+		ext.srcFile = file('.classpath')
+		inputs.file srcFile
+		outputs.dir srcFile
 
-        onlyIf { !srcFile.exists() }
+		onlyIf { !srcFile.exists() }
 
-        doLast {
-            srcFile << """<?xml version="1.0" encoding="UTF-8"?>
+		doLast {
+			srcFile << """<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-    <classpathentry kind="output" path="bin"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
 </classpath>
 """
-        }
-    }
+		}
+	}
 }
 
 configure(subprojects - coreModuleProjects - project(':spring-security-samples-messages-jc') - project(':spring-security-bom')) {
-    tasks.findByPath("artifactoryPublish")?.enabled = false
-    sonarRunner {
-        skipProject = true
-    }
+	tasks.findByPath("artifactoryPublish")?.enabled = false
+	sonarRunner {
+		skipProject = true
+	}
 }
 
 configure(javaProjects) {
-    ext.TOMCAT_GRADLE = "$rootDir/gradle/tomcat.gradle"
-    ext.WAR_SAMPLE_GRADLE = "$rootDir/gradle/war-sample.gradle"
-    apply from: "$rootDir/gradle/javaprojects.gradle"
-    apply from: "$rootDir/gradle/release-checks.gradle"
-    apply from: "$rootDir/gradle/maven-deployment.gradle"
+	ext.TOMCAT_GRADLE = "$rootDir/gradle/tomcat.gradle"
+	ext.WAR_SAMPLE_GRADLE = "$rootDir/gradle/war-sample.gradle"
+	apply from: "$rootDir/gradle/javaprojects.gradle"
+	apply from: "$rootDir/gradle/release-checks.gradle"
+	apply from: "$rootDir/gradle/maven-deployment.gradle"
 }
 
 configure(coreModuleProjects) {
-    apply plugin: 'emma'
-    apply plugin: 'spring-io'
-
-    ext.springIoVersion = project.hasProperty('platformVersion') ? platformVersion : '1.1.0.BUILD-SNAPSHOT'
-
-    configurations {
-        jacoco //Configuration Group used by Sonar to provide Code Coverage using JaCoCo
-    }
-
-    dependencies {
-        springIoVersions "io.spring.platform:platform-versions:${springIoVersion}@properties"
-        jacoco "org.jacoco:org.jacoco.agent:0.6.2.201302030002:runtime"
-    }
-    test {
-        jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=${project.group}.*"
-    }
-    integrationTest {
-        jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=${project.group}.*"
-    }
+	apply plugin: 'emma'
+	apply plugin: 'spring-io'
+
+	ext.springIoVersion = project.hasProperty('platformVersion') ? platformVersion : '1.1.0.BUILD-SNAPSHOT'
+
+	configurations {
+		jacoco //Configuration Group used by Sonar to provide Code Coverage using JaCoCo
+	}
+
+	dependencies {
+		springIoVersions "io.spring.platform:platform-versions:${springIoVersion}@properties"
+		jacoco "org.jacoco:org.jacoco.agent:0.6.2.201302030002:runtime"
+	}
+	test {
+		jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=${project.group}.*"
+	}
+	integrationTest {
+		jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=${project.group}.*"
+	}
 }
 
 configure (aspectjProjects) {
-    apply plugin: 'java'
-    apply plugin: 'aspectj'
+	apply plugin: 'java'
+	apply plugin: 'aspectj'
 }
 
 task coreBuild {
-    dependsOn coreModuleProjects*.tasks*.matching { task -> task.name == 'build' }
+	dependsOn coreModuleProjects*.tasks*.matching { task -> task.name == 'build' }
 }
 
 // Task for creating the distro zip
 
 task dist(type: Zip) {
-    dependsOn subprojects*.tasks*.matching { task -> task.name == 'assemble' || task.name.endsWith('Zip') || task.name.endsWith('generatePom') }
-    classifier = 'dist'
-
-    evaluationDependsOn(':docs')
-    evaluationDependsOn(':docs:manual')
-
-    def zipRootDir = "${project.name}-$version"
-    into(zipRootDir) {
-        from(rootDir) {
-            include '*.adoc'
-        }
-        into('docs') {
-            with(project(':docs').apiSpec)
-            with(project(':docs:manual').spec)
-            with(project(':docs:guides').spec)
-        }
-        into('dist') {
-            from coreModuleProjects.collect {project -> project.libsDir }
-        }
-        sampleProjects.each { project->
-            into("$zipRootDir/samples/$project.name") {
-                from(project.projectDir) {
-                    include "src/main/**"
-                    include "pom.xml"
-                }
-            }
-        }
-    }
+	dependsOn subprojects*.tasks*.matching { task -> task.name == 'assemble' || task.name.endsWith('Zip') || task.name.endsWith('generatePom') }
+	classifier = 'dist'
+
+	evaluationDependsOn(':docs')
+	evaluationDependsOn(':docs:manual')
+
+	def zipRootDir = "${project.name}-$version"
+	into(zipRootDir) {
+		from(rootDir) {
+			include '*.adoc'
+		}
+		into('docs') {
+			with(project(':docs').apiSpec)
+			with(project(':docs:manual').spec)
+			with(project(':docs:guides').spec)
+		}
+		into('dist') {
+			from coreModuleProjects.collect {project -> project.libsDir }
+		}
+		sampleProjects.each { project->
+			into("$zipRootDir/samples/$project.name") {
+				from(project.projectDir) {
+					include "src/main/**"
+					include "pom.xml"
+				}
+			}
+		}
+	}
 }
 
 artifacts {
-    archives dist
-    archives project(':docs').docsZip
-    archives project(':docs').schemaZip
+	archives dist
+	archives project(':docs').docsZip
+	archives project(':docs').schemaZip
 }

+ 16 - 16
buildSrc/build.gradle

@@ -1,37 +1,37 @@
 apply plugin: 'groovy'
 
 repositories {
-    mavenCentral()
-    maven {
-        name = 'SpringSource Enterprise Release'
-        url = 'http://repository.springsource.com/maven/bundles/release'
-    }
-    maven {
-        name = 'SpringSource Enterprise External'
-        url = 'http://repository.springsource.com/maven/bundles/external'
-    }
+	mavenCentral()
+	maven {
+		name = 'SpringSource Enterprise Release'
+		url = 'http://repository.springsource.com/maven/bundles/release'
+	}
+	maven {
+		name = 'SpringSource Enterprise External'
+		url = 'http://repository.springsource.com/maven/bundles/external'
+	}
 }
 
 dependencies {
-    compile gradleApi()
+	compile gradleApi()
 }
 
 // GAE
 dependencies {
-    compile 'com.google.appengine:appengine-tools-sdk:1.4.2'
+	compile 'com.google.appengine:appengine-tools-sdk:1.4.2'
 }
 
 dependencies{
-    compile "emma:emma:2.0.5312"
+	compile "emma:emma:2.0.5312"
 }
 
 // Trang
 dependencies {
-    compile 'com.thaiopensource:trang:20091111',
-            'net.sourceforge.saxon:saxon:9.1.0.8'
+	compile 'com.thaiopensource:trang:20091111',
+			'net.sourceforge.saxon:saxon:9.1.0.8'
 }
 
 task ide(type: Copy)  {
-    from configurations.runtime
-    into 'ide'
+	from configurations.runtime
+	into 'ide'
 }

+ 46 - 46
buildSrc/src/main/groovy/MavenBomTask.groovy

@@ -6,50 +6,50 @@ import org.gradle.api.tasks.*
 
 public class MavenBomTask extends DefaultTask {
 
-    Set<Project> projects
-
-    File bomFile
-
-
-    public MavenBomTask() {
-        this.group = "Generate"
-        this.description = "Generates a Maven Build of Materials (BOM). See http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies"
-        this.projects = project.subprojects
-        this.bomFile = project.file("${->project.buildDir}/maven-bom/${->project.name}-${->project.version}.txt")
-    }
-
-    @TaskAction
-    public void configureBom() {
-        project.configurations.archives.artifacts.clear()
-
-        bomFile.parentFile.mkdirs()
-        bomFile.write("Maven Build of Materials (BOM). See http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies")
-        project.artifacts {
-            // work around GRADLE-2406 by attaching text artifact
-            archives(bomFile)
-        }
-        project.install {
-            repositories.mavenInstaller {
-                pom.whenConfigured {
-                    packaging = "pom"
-                    withXml {
-                        asNode().children().last() + {
-                            delegate.dependencyManagement {
-                                delegate.dependencies {
-                                    projects.sort { dep -> "$dep.group:$dep.name" }.each { p ->
-
-                                        delegate.dependency {
-                                            delegate.groupId(p.group)
-                                            delegate.artifactId(p.name)
-                                            delegate.version(p.version)
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
+	Set<Project> projects
+
+	File bomFile
+
+
+	public MavenBomTask() {
+		this.group = "Generate"
+		this.description = "Generates a Maven Build of Materials (BOM). See http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies"
+		this.projects = project.subprojects
+		this.bomFile = project.file("${->project.buildDir}/maven-bom/${->project.name}-${->project.version}.txt")
+	}
+
+	@TaskAction
+	public void configureBom() {
+		project.configurations.archives.artifacts.clear()
+
+		bomFile.parentFile.mkdirs()
+		bomFile.write("Maven Build of Materials (BOM). See http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies")
+		project.artifacts {
+			// work around GRADLE-2406 by attaching text artifact
+			archives(bomFile)
+		}
+		project.install {
+			repositories.mavenInstaller {
+				pom.whenConfigured {
+					packaging = "pom"
+					withXml {
+						asNode().children().last() + {
+							delegate.dependencyManagement {
+								delegate.dependencies {
+									projects.sort { dep -> "$dep.group:$dep.name" }.each { p ->
+
+										delegate.dependency {
+											delegate.groupId(p.group)
+											delegate.artifactId(p.name)
+											delegate.version(p.version)
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
 }

+ 93 - 93
buildSrc/src/main/groovy/aspectj/AspectJPlugin.groovy

@@ -22,100 +22,100 @@ import org.gradle.plugins.ide.eclipse.model.ProjectDependency
  */
 class AspectJPlugin implements Plugin<Project> {
 
-    void apply(Project project) {
-        project.plugins.apply(JavaPlugin)
-
-        if (!project.hasProperty('aspectjVersion')) {
-            throw new GradleException("You must set the property 'aspectjVersion' before applying the aspectj plugin")
-        }
-
-        if (project.configurations.findByName('ajtools') == null) {
-            project.configurations.create('ajtools')
-            project.dependencies {
-                ajtools "org.aspectj:aspectjtools:${project.aspectjVersion}"
-                optional "org.aspectj:aspectjrt:${project.aspectjVersion}"
-            }
-        }
-
-        if (project.configurations.findByName('aspectpath') == null) {
-            project.configurations.create('aspectpath')
-        }
-
-        project.tasks.create(name: 'compileAspect', overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) {
-            dependsOn project.configurations*.getTaskDependencyFromProjectDependency(true, "compileJava")
-
-            dependsOn project.processResources
-            sourceSet = project.sourceSets.main
-            inputs.files(sourceSet.allSource)
-            outputs.dir(sourceSet.output.classesDir)
-            aspectPath = project.configurations.aspectpath
-        }
-        project.tasks.compileJava.deleteAllActions()
-        project.tasks.compileJava.dependsOn project.tasks.compileAspect
-
-
-        project.tasks.create(name: 'compileTestAspect', overwrite: true, description: 'Compiles AspectJ Test Source', type: Ajc) {
-            dependsOn project.processTestResources, project.compileJava, project.jar
-            sourceSet = project.sourceSets.test
-            inputs.files(sourceSet.allSource)
-            outputs.dir(sourceSet.output.classesDir)
-            aspectPath = project.files(project.configurations.aspectpath, project.jar.archivePath)
-        }
-        project.tasks.compileTestJava.deleteAllActions()
-        project.tasks.compileTestJava.dependsOn project.tasks.compileTestAspect
-
-        project.tasks.withType(GenerateEclipseProject) {
-            project.eclipse.project.file.whenMerged { p ->
-                p.natures.add(0, 'org.eclipse.ajdt.ui.ajnature')
-                p.buildCommands = [new BuildCommand('org.eclipse.ajdt.core.ajbuilder')]
-            }
-        }
-
-        project.tasks.withType(GenerateEclipseClasspath) {
-            project.eclipse.classpath.file.whenMerged { classpath ->
-                def entries = classpath.entries.findAll { it instanceof ProjectDependency}.findAll { entry ->
-                    def projectPath = entry.path.replaceAll('/','')
-                    project.rootProject.allprojects.find{ p->
-                        if(p.plugins.findPlugin(EclipsePlugin)) {
-                            return p.eclipse.project.name == projectPath && p.plugins.findPlugin(AspectJPlugin)
-                        }
-                        false
-                    }
-                }
-                entries.each { entry->
-                    entry.entryAttributes.put('org.eclipse.ajdt.aspectpath','org.eclipse.ajdt.aspectpath')
-                }
-            }
-        }
-    }
+	void apply(Project project) {
+		project.plugins.apply(JavaPlugin)
+
+		if (!project.hasProperty('aspectjVersion')) {
+			throw new GradleException("You must set the property 'aspectjVersion' before applying the aspectj plugin")
+		}
+
+		if (project.configurations.findByName('ajtools') == null) {
+			project.configurations.create('ajtools')
+			project.dependencies {
+				ajtools "org.aspectj:aspectjtools:${project.aspectjVersion}"
+				optional "org.aspectj:aspectjrt:${project.aspectjVersion}"
+			}
+		}
+
+		if (project.configurations.findByName('aspectpath') == null) {
+			project.configurations.create('aspectpath')
+		}
+
+		project.tasks.create(name: 'compileAspect', overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) {
+			dependsOn project.configurations*.getTaskDependencyFromProjectDependency(true, "compileJava")
+
+			dependsOn project.processResources
+			sourceSet = project.sourceSets.main
+			inputs.files(sourceSet.allSource)
+			outputs.dir(sourceSet.output.classesDir)
+			aspectPath = project.configurations.aspectpath
+		}
+		project.tasks.compileJava.deleteAllActions()
+		project.tasks.compileJava.dependsOn project.tasks.compileAspect
+
+
+		project.tasks.create(name: 'compileTestAspect', overwrite: true, description: 'Compiles AspectJ Test Source', type: Ajc) {
+			dependsOn project.processTestResources, project.compileJava, project.jar
+			sourceSet = project.sourceSets.test
+			inputs.files(sourceSet.allSource)
+			outputs.dir(sourceSet.output.classesDir)
+			aspectPath = project.files(project.configurations.aspectpath, project.jar.archivePath)
+		}
+		project.tasks.compileTestJava.deleteAllActions()
+		project.tasks.compileTestJava.dependsOn project.tasks.compileTestAspect
+
+		project.tasks.withType(GenerateEclipseProject) {
+			project.eclipse.project.file.whenMerged { p ->
+				p.natures.add(0, 'org.eclipse.ajdt.ui.ajnature')
+				p.buildCommands = [new BuildCommand('org.eclipse.ajdt.core.ajbuilder')]
+			}
+		}
+
+		project.tasks.withType(GenerateEclipseClasspath) {
+			project.eclipse.classpath.file.whenMerged { classpath ->
+				def entries = classpath.entries.findAll { it instanceof ProjectDependency}.findAll { entry ->
+					def projectPath = entry.path.replaceAll('/','')
+					project.rootProject.allprojects.find{ p->
+						if(p.plugins.findPlugin(EclipsePlugin)) {
+							return p.eclipse.project.name == projectPath && p.plugins.findPlugin(AspectJPlugin)
+						}
+						false
+					}
+				}
+				entries.each { entry->
+					entry.entryAttributes.put('org.eclipse.ajdt.aspectpath','org.eclipse.ajdt.aspectpath')
+				}
+			}
+		}
+	}
 }
 
 class Ajc extends DefaultTask {
-    SourceSet sourceSet
-    FileCollection aspectPath
-
-    Ajc() {
-        logging.captureStandardOutput(LogLevel.INFO)
-    }
-
-    @TaskAction
-    def compile() {
-        logger.info("="*30)
-        logger.info("="*30)
-        logger.info("Running ajc ...")
-        logger.info("classpath: ${sourceSet.compileClasspath.asPath}")
-        logger.info("srcDirs $sourceSet.java.srcDirs")
-        ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: project.configurations.ajtools.asPath)
-        ant.iajc(classpath: sourceSet.compileClasspath.asPath, fork: 'true', destDir: sourceSet.output.classesDir.absolutePath,
-                source: project.convention.plugins.java.sourceCompatibility,
-                target: project.convention.plugins.java.targetCompatibility,
-                aspectPath: aspectPath.asPath, sourceRootCopyFilter: '**/*.java', showWeaveInfo: 'true') {
-            sourceroots {
-                sourceSet.java.srcDirs.each {
-                    logger.info("   sourceRoot $it")
-                    pathelement(location: it.absolutePath)
-                }
-            }
-        }
-    }
+	SourceSet sourceSet
+	FileCollection aspectPath
+
+	Ajc() {
+		logging.captureStandardOutput(LogLevel.INFO)
+	}
+
+	@TaskAction
+	def compile() {
+		logger.info("="*30)
+		logger.info("="*30)
+		logger.info("Running ajc ...")
+		logger.info("classpath: ${sourceSet.compileClasspath.asPath}")
+		logger.info("srcDirs $sourceSet.java.srcDirs")
+		ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: project.configurations.ajtools.asPath)
+		ant.iajc(classpath: sourceSet.compileClasspath.asPath, fork: 'true', destDir: sourceSet.output.classesDir.absolutePath,
+				source: project.convention.plugins.java.sourceCompatibility,
+				target: project.convention.plugins.java.targetCompatibility,
+				aspectPath: aspectPath.asPath, sourceRootCopyFilter: '**/*.java', showWeaveInfo: 'true') {
+			sourceroots {
+				sourceSet.java.srcDirs.each {
+					logger.info("	sourceRoot $it")
+					pathelement(location: it.absolutePath)
+				}
+			}
+		}
+	}
 }

+ 84 - 84
buildSrc/src/main/groovy/emma/EmmaPlugin.groovy

@@ -15,100 +15,100 @@ import com.vladium.util.XProperties;
  */
 class EmmaPlugin implements Plugin<Project> {
 
-    void apply(Project project) {
-        Project rootProject = project.rootProject
-        def emmaMetaDataFile = "${rootProject.buildDir}/emma/emma.em"
-        def emmaCoverageFile = "${rootProject.buildDir}/emma/emma.ec"
-
-        if (project.configurations.findByName('emma_rt') == null) {
-            project.configurations.create('emma_rt')
-            project.dependencies {
-                emma_rt 'emma:emma:2.0.5312'
-            }
-        }
-
-        project.task('emmaInstrument') {
-            dependsOn project.classes
-
-            doFirst {
-                InstrProcessor processor = InstrProcessor.create ();
-                String[] classesDirPath = [project.sourceSets.main.output.classesDir.absolutePath]
-
-                processor.setInstrPath(classesDirPath, false);
-                processor.setOutMode(InstrProcessor.OutMode.OUT_MODE_COPY);
-                processor.setInstrOutDir("${project.buildDir}/emma/classes");
-                processor.setMetaOutFile(emmaMetaDataFile);
-                processor.setMetaOutMerge(true);
-                //processor.setInclExclFilter (null);
-                processor.run();
-            }
-        }
-
-        // Modify test tasks in the project to generate coverage data
-        project.afterEvaluate {
-            if (project.hasProperty('coverage') && ['on','true'].contains(project.properties.coverage)) {
-                project.tasks.withType(Test.class).each { task ->
-                    task.dependsOn project.emmaInstrument
-                    task.configure() {
-                        jvmArgs '-Dsec.log.level=DEBUG', "-Demma.coverage.out.file=$emmaCoverageFile"
-                        jvmArgs '-Demma.verbosity.level=quiet'
-                    }
-                    task.doFirst {
-                        classpath = project.files("${project.buildDir}/emma/classes") + project.configurations.emma_rt + classpath
-                    }
-                }
-            }
-        }
-
-        List<Task> reportTasks = rootProject.getTasksByName('coverageReport', false) as List;
-        CoverageReport task;
-
-        if (reportTasks.isEmpty()) {
-            task = rootProject.tasks.create('coverageReport', CoverageReport.class);
-            task.dataPath = [emmaMetaDataFile, emmaCoverageFile];
-        } else {
-            task = reportTasks[0];
-        }
-
-        task.modules.add(project);
-    }
+	void apply(Project project) {
+		Project rootProject = project.rootProject
+		def emmaMetaDataFile = "${rootProject.buildDir}/emma/emma.em"
+		def emmaCoverageFile = "${rootProject.buildDir}/emma/emma.ec"
+
+		if (project.configurations.findByName('emma_rt') == null) {
+			project.configurations.create('emma_rt')
+			project.dependencies {
+				emma_rt 'emma:emma:2.0.5312'
+			}
+		}
+
+		project.task('emmaInstrument') {
+			dependsOn project.classes
+
+			doFirst {
+				InstrProcessor processor = InstrProcessor.create ();
+				String[] classesDirPath = [project.sourceSets.main.output.classesDir.absolutePath]
+
+				processor.setInstrPath(classesDirPath, false);
+				processor.setOutMode(InstrProcessor.OutMode.OUT_MODE_COPY);
+				processor.setInstrOutDir("${project.buildDir}/emma/classes");
+				processor.setMetaOutFile(emmaMetaDataFile);
+				processor.setMetaOutMerge(true);
+				//processor.setInclExclFilter (null);
+				processor.run();
+			}
+		}
+
+		// Modify test tasks in the project to generate coverage data
+		project.afterEvaluate {
+			if (project.hasProperty('coverage') && ['on','true'].contains(project.properties.coverage)) {
+				project.tasks.withType(Test.class).each { task ->
+					task.dependsOn project.emmaInstrument
+					task.configure() {
+						jvmArgs '-Dsec.log.level=DEBUG', "-Demma.coverage.out.file=$emmaCoverageFile"
+						jvmArgs '-Demma.verbosity.level=quiet'
+					}
+					task.doFirst {
+						classpath = project.files("${project.buildDir}/emma/classes") + project.configurations.emma_rt + classpath
+					}
+				}
+			}
+		}
+
+		List<Task> reportTasks = rootProject.getTasksByName('coverageReport', false) as List;
+		CoverageReport task;
+
+		if (reportTasks.isEmpty()) {
+			task = rootProject.tasks.create('coverageReport', CoverageReport.class);
+			task.dataPath = [emmaMetaDataFile, emmaCoverageFile];
+		} else {
+			task = reportTasks[0];
+		}
+
+		task.modules.add(project);
+	}
 }
 
 class CoverageReport extends DefaultTask {
-    @Input
-    List<Project> modules = [];
+	@Input
+	List<Project> modules = [];
 
-    @Input
-    String[] dataPath;
+	@Input
+	String[] dataPath;
 
-    @TaskAction
-    void generateReport() {
-        def buildDir = project.rootProject.buildDir
+	@TaskAction
+	void generateReport() {
+		def buildDir = project.rootProject.buildDir
 
-        if (!buildDir.exists()) {
-            throw new GradleException("No coverage data. Run gradle with -Pcoverage=on if using coverageReport");
-        }
+		if (!buildDir.exists()) {
+			throw new GradleException("No coverage data. Run gradle with -Pcoverage=on if using coverageReport");
+		}
 
-        ReportProcessor processor = ReportProcessor.create ();
-        processor.setDataPath(dataPath)
+		ReportProcessor processor = ReportProcessor.create ();
+		processor.setDataPath(dataPath)
 
-        def srcPath = []
-        modules.each {module->
-            module.sourceSets.main.java.srcDirs.each {
-                srcPath.add(it.absolutePath)
-            }
-        }
+		def srcPath = []
+		modules.each {module->
+			module.sourceSets.main.java.srcDirs.each {
+				srcPath.add(it.absolutePath)
+			}
+		}
 
-        processor.setSourcePath(srcPath as String[]);
+		processor.setSourcePath(srcPath as String[]);
 
 
-        def types = ['txt', 'html']
-        processor.setReportTypes(types as String[]);
-        XProperties properties = new XProperties();
-        properties.setProperty('report.html.out.file', "$buildDir/emma/coverage.html");
-        properties.setProperty('report.txt.out.file', "$buildDir/emma/coverage.txt");
-        processor.setPropertyOverrides(properties)
+		def types = ['txt', 'html']
+		processor.setReportTypes(types as String[]);
+		XProperties properties = new XProperties();
+		properties.setProperty('report.html.out.file', "$buildDir/emma/coverage.html");
+		properties.setProperty('report.txt.out.file', "$buildDir/emma/coverage.txt");
+		processor.setPropertyOverrides(properties)
 
-        processor.run()
-    }
+		processor.run()
+	}
 }

+ 15 - 15
buildSrc/src/main/groovy/gae/GaePlugin.groovy

@@ -4,23 +4,23 @@ import com.google.appengine.tools.admin.AppCfg
 import org.gradle.api.*;
 
 class GaePlugin implements Plugin<Project> {
-    public void apply(Project project) {
-        if (!project.hasProperty('appEngineSdkRoot')) {
-            println "'appEngineSdkRoot' must be set in gradle.properties"
-        } else {
-            System.setProperty('appengine.sdk.root', project.property('appEngineSdkRoot'))
-        }
+	public void apply(Project project) {
+		if (!project.hasProperty('appEngineSdkRoot')) {
+			println "'appEngineSdkRoot' must be set in gradle.properties"
+		} else {
+			System.setProperty('appengine.sdk.root', project.property('appEngineSdkRoot'))
+		}
 
-        File explodedWar = new File(project.buildDir, "gae-exploded")
+		File explodedWar = new File(project.buildDir, "gae-exploded")
 
-        project.task('gaeDeploy') << {
-            AppCfg.main("update", explodedWar.toString())
-        }
+		project.task('gaeDeploy') << {
+			AppCfg.main("update", explodedWar.toString())
+		}
 
-        project.gaeDeploy.dependsOn project.war
+		project.gaeDeploy.dependsOn project.war
 
-        project.war.doLast {
-            ant.unzip(src: project.war.archivePath, dest: explodedWar)
-        }
-    }
+		project.war.doLast {
+			ant.unzip(src: project.war.archivePath, dest: explodedWar)
+		}
+	}
 }

+ 34 - 34
buildSrc/src/main/groovy/trang/TrangPlugin.groovy

@@ -16,44 +16,44 @@ import org.gradle.api.file.FileCollection
  * @author Rob Winch
  */
 class TrangPlugin implements Plugin<Project> {
-    public void apply(Project project) {
-        Task rncToXsd = project.tasks.create('rncToXsd', RncToXsd.class)
-        rncToXsd.description = 'Converts .rnc to .xsd'
-        rncToXsd.group = 'Build'
-    }
+	public void apply(Project project) {
+		Task rncToXsd = project.tasks.create('rncToXsd', RncToXsd.class)
+		rncToXsd.description = 'Converts .rnc to .xsd'
+		rncToXsd.group = 'Build'
+	}
 }
 
 /**
  * Converts .rnc files to .xsd files using trang and then applies an xsl file to cleanup the results.
  */
 public class RncToXsd extends DefaultTask {
-    @InputDirectory
-    File rncDir
-
-    @InputFile
-    File xslFile
-
-    @OutputDirectory
-    File xsdDir
-
-    @TaskAction
-    public final void transform() {
-        String xslPath = xslFile.absolutePath
-        rncDir.listFiles( { dir, file -> file.endsWith('.rnc')} as FilenameFilter).each { rncFile ->
-            File xsdFile = new File(xsdDir, rncFile.name.replace('.rnc', '.xsd'))
-            String xsdOutputPath = xsdFile.absolutePath
-            new Driver().run([rncFile.absolutePath, xsdOutputPath] as String[]);
-
-            TransformerFactory tFactory = new net.sf.saxon.TransformerFactoryImpl()
-            Transformer transformer =
-                    tFactory.newTransformer(new StreamSource(xslPath))
-            File temp = File.createTempFile("gradle-trang-" + xsdFile.name, ".xsd")
-            xsdFile.withInputStream { is ->
-                temp << is
-            }
-            StreamSource xmlSource = new StreamSource(temp)
-            transformer.transform(xmlSource, new StreamResult(xsdFile))
-            temp.delete()
-        }
-    }
+	@InputDirectory
+	File rncDir
+
+	@InputFile
+	File xslFile
+
+	@OutputDirectory
+	File xsdDir
+
+	@TaskAction
+	public final void transform() {
+		String xslPath = xslFile.absolutePath
+		rncDir.listFiles( { dir, file -> file.endsWith('.rnc')} as FilenameFilter).each { rncFile ->
+			File xsdFile = new File(xsdDir, rncFile.name.replace('.rnc', '.xsd'))
+			String xsdOutputPath = xsdFile.absolutePath
+			new Driver().run([rncFile.absolutePath, xsdOutputPath] as String[]);
+
+			TransformerFactory tFactory = new net.sf.saxon.TransformerFactoryImpl()
+			Transformer transformer =
+					tFactory.newTransformer(new StreamSource(xslPath))
+			File temp = File.createTempFile("gradle-trang-" + xsdFile.name, ".xsd")
+			xsdFile.withInputStream { is ->
+				temp << is
+			}
+			StreamSource xmlSource = new StreamSource(temp)
+			transformer.transform(xmlSource, new StreamResult(xsdFile))
+			temp.delete()
+		}
+	}
 }

+ 9 - 9
cas/cas.gradle

@@ -1,14 +1,14 @@
 
 dependencies {
-    compile project(':spring-security-core'),
-            project(':spring-security-web'),
-            springCoreDependency,
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-web:$springVersion",
-            "org.jasig.cas.client:cas-client-core:$casClientVersion"
+	compile project(':spring-security-core'),
+			project(':spring-security-web'),
+			springCoreDependency,
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-web:$springVersion",
+			"org.jasig.cas.client:cas-client-core:$casClientVersion"
 
-    optional "net.sf.ehcache:ehcache:$ehcacheVersion"
+	optional "net.sf.ehcache:ehcache:$ehcacheVersion"
 
-    provided "javax.servlet:javax.servlet-api:$servletApiVersion"
+	provided "javax.servlet:javax.servlet-api:$servletApiVersion"
 }

+ 54 - 54
config/config.gradle

@@ -8,71 +8,71 @@ apply plugin: 'trang'
 compileTestJava.dependsOn(':spring-security-core:compileTestJava')
 
 dependencies {
-    // NB: Don't add other compile time dependencies to the config module as this breaks tooling
-    compile project(':spring-security-core'),
-            springCoreDependency,
-            'aopalliance:aopalliance:1.0',
-            "org.springframework:spring-aop:$springVersion",
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-beans:$springVersion"
+	// NB: Don't add other compile time dependencies to the config module as this breaks tooling
+	compile project(':spring-security-core'),
+			springCoreDependency,
+			'aopalliance:aopalliance:1.0',
+			"org.springframework:spring-aop:$springVersion",
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-beans:$springVersion"
 
-    optional project(':spring-security-web'),
-             project(':spring-security-ldap'),
-             project(':spring-security-openid'),
-             project(':spring-security-messaging'),
-            "org.springframework:spring-web:$springVersion",
-            "org.springframework:spring-websocket:$springVersion",
-             "org.springframework:spring-webmvc:$springVersion",
-             "org.aspectj:aspectjweaver:$aspectjVersion",
-             "org.springframework:spring-jdbc:$springVersion",
-             "org.springframework:spring-tx:$springVersion"
+	optional project(':spring-security-web'),
+			 project(':spring-security-ldap'),
+			 project(':spring-security-openid'),
+			 project(':spring-security-messaging'),
+			"org.springframework:spring-web:$springVersion",
+			"org.springframework:spring-websocket:$springVersion",
+			 "org.springframework:spring-webmvc:$springVersion",
+			 "org.aspectj:aspectjweaver:$aspectjVersion",
+			 "org.springframework:spring-jdbc:$springVersion",
+			 "org.springframework:spring-tx:$springVersion"
 
-    provided "javax.servlet:javax.servlet-api:$servletApiVersion"
+	provided "javax.servlet:javax.servlet-api:$servletApiVersion"
 
-    testCompile project(':spring-security-cas'),
-                project(':spring-security-core').sourceSets.test.output,
-                project(':spring-security-aspects'),
-                'javax.annotation:jsr250-api:1.0',
-                "org.springframework.ldap:spring-ldap-core:$springLdapVersion",
-                "org.springframework:spring-expression:$springVersion",
-                "org.springframework:spring-jdbc:$springVersion",
-                "org.springframework:spring-orm:$springVersion",
-                "org.springframework:spring-tx:$springVersion",
-                "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-                "org.eclipse.persistence:javax.persistence:2.0.5",
-                "org.hibernate:hibernate-entitymanager:4.1.0.Final",
-                "org.codehaus.groovy:groovy-all:$groovyVersion",
-                "org.apache.directory.server:apacheds-core:$apacheDsVersion",
-                "org.apache.directory.server:apacheds-core-entry:$apacheDsVersion",
-                "org.apache.directory.server:apacheds-protocol-shared:$apacheDsVersion",
-                "org.apache.directory.server:apacheds-protocol-ldap:$apacheDsVersion",
-                "org.apache.directory.server:apacheds-server-jndi:$apacheDsVersion",
-                'org.apache.directory.shared:shared-ldap:0.9.15',
-                'ldapsdk:ldapsdk:4.1',
-                powerMockDependencies,
-                 "org.hibernate:hibernate-entitymanager:3.6.10.Final",
-                "org.hsqldb:hsqldb:$hsqlVersion",
-                spockDependencies
+	testCompile project(':spring-security-cas'),
+				project(':spring-security-core').sourceSets.test.output,
+				project(':spring-security-aspects'),
+				'javax.annotation:jsr250-api:1.0',
+				"org.springframework.ldap:spring-ldap-core:$springLdapVersion",
+				"org.springframework:spring-expression:$springVersion",
+				"org.springframework:spring-jdbc:$springVersion",
+				"org.springframework:spring-orm:$springVersion",
+				"org.springframework:spring-tx:$springVersion",
+				"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+				"org.eclipse.persistence:javax.persistence:2.0.5",
+				"org.hibernate:hibernate-entitymanager:4.1.0.Final",
+				"org.codehaus.groovy:groovy-all:$groovyVersion",
+				"org.apache.directory.server:apacheds-core:$apacheDsVersion",
+				"org.apache.directory.server:apacheds-core-entry:$apacheDsVersion",
+				"org.apache.directory.server:apacheds-protocol-shared:$apacheDsVersion",
+				"org.apache.directory.server:apacheds-protocol-ldap:$apacheDsVersion",
+				"org.apache.directory.server:apacheds-server-jndi:$apacheDsVersion",
+				'org.apache.directory.shared:shared-ldap:0.9.15',
+				'ldapsdk:ldapsdk:4.1',
+				powerMockDependencies,
+				 "org.hibernate:hibernate-entitymanager:3.6.10.Final",
+				"org.hsqldb:hsqldb:$hsqlVersion",
+				spockDependencies
 
-    testCompile('org.openid4java:openid4java-nodeps:0.9.6') {
-        exclude group: 'com.google.code.guice', module: 'guice'
-    }
-    testCompile("org.springframework.data:spring-data-jpa:$springDataJpaVersion") {
-        exclude group: 'org.aspectj', module: 'aspectjrt'
-    }
+	testCompile('org.openid4java:openid4java-nodeps:0.9.6') {
+		exclude group: 'com.google.code.guice', module: 'guice'
+	}
+	testCompile("org.springframework.data:spring-data-jpa:$springDataJpaVersion") {
+		exclude group: 'org.aspectj', module: 'aspectjrt'
+	}
 
-    testRuntime "org.hsqldb:hsqldb:$hsqlVersion",
-                "cglib:cglib-nodep:$cglibVersion"
+	testRuntime "org.hsqldb:hsqldb:$hsqlVersion",
+				"cglib:cglib-nodep:$cglibVersion"
 }
 
 test {
-    inputs.file file("$rootDir/docs/manual/src/docbook/appendix-namespace.xml")
+	inputs.file file("$rootDir/docs/manual/src/docbook/appendix-namespace.xml")
 }
 
 rncToXsd {
-    rncDir = file('src/main/resources/org/springframework/security/config/')
-    xsdDir = rncDir
-    xslFile = new File(rncDir, 'spring-security.xsl')
+	rncDir = file('src/main/resources/org/springframework/security/config/')
+	xsdDir = rncDir
+	xslFile = new File(rncDir, 'spring-security.xsl')
 }
 
 build.dependsOn rncToXsd

+ 52 - 52
config/src/test/groovy/org/springframework/security/config/AbstractXmlConfigTests.groovy

@@ -20,65 +20,65 @@ import org.springframework.security.CollectingAppListener
  * @author Luke Taylor
  */
 abstract class AbstractXmlConfigTests extends Specification {
-    AbstractXmlApplicationContext appContext;
-    Writer writer;
-    MarkupBuilder xml;
-    ApplicationListener appListener;
+	AbstractXmlApplicationContext appContext;
+	Writer writer;
+	MarkupBuilder xml;
+	ApplicationListener appListener;
 
-    def setup() {
-        writer = new StringWriter()
-        xml = new MarkupBuilder(writer)
-        appListener = new CollectingAppListener()
-    }
+	def setup() {
+		writer = new StringWriter()
+		xml = new MarkupBuilder(writer)
+		appListener = new CollectingAppListener()
+	}
 
-    def cleanup() {
-        if (appContext != null) {
-            appContext.close();
-            appContext = null;
-        }
-        SecurityContextHolder.clearContext();
-    }
+	def cleanup() {
+		if (appContext != null) {
+			appContext.close();
+			appContext = null;
+		}
+		SecurityContextHolder.clearContext();
+	}
 
-    def mockBean(Class clazz, String id = clazz.simpleName) {
-        xml.'b:bean'(id: id, 'class': Mockito.class.name, 'factory-method':'mock') {
-            'b:constructor-arg'(value : clazz.name)
-            'b:constructor-arg'(value : id)
-        }
-    }
+	def mockBean(Class clazz, String id = clazz.simpleName) {
+		xml.'b:bean'(id: id, 'class': Mockito.class.name, 'factory-method':'mock') {
+			'b:constructor-arg'(value : clazz.name)
+			'b:constructor-arg'(value : id)
+		}
+	}
 
-    def bean(String name, Class clazz) {
-        xml.'b:bean'(id: name, 'class': clazz.name)
-    }
+	def bean(String name, Class clazz) {
+		xml.'b:bean'(id: name, 'class': clazz.name)
+	}
 
-    def bean(String name, String clazz) {
-        xml.'b:bean'(id: name, 'class': clazz)
-    }
+	def bean(String name, String clazz) {
+		xml.'b:bean'(id: name, 'class': clazz)
+	}
 
-    def bean(String name, String clazz, List constructorArgs) {
-        xml.'b:bean'(id: name, 'class': clazz) {
-            constructorArgs.each { val ->
-                'b:constructor-arg'(value: val)
-            }
-        }
-    }
+	def bean(String name, String clazz, List constructorArgs) {
+		xml.'b:bean'(id: name, 'class': clazz) {
+			constructorArgs.each { val ->
+				'b:constructor-arg'(value: val)
+			}
+		}
+	}
 
-    def bean(String name, String clazz, Map properties, Map refs) {
-        xml.'b:bean'(id: name, 'class': clazz) {
-            properties.each {key, val ->
-                'b:property'(name: key, value: val)
-            }
-            refs.each {key, val ->
-                'b:property'(name: key, ref: val)
-            }
-        }
-    }
+	def bean(String name, String clazz, Map properties, Map refs) {
+		xml.'b:bean'(id: name, 'class': clazz) {
+			properties.each {key, val ->
+				'b:property'(name: key, value: val)
+			}
+			refs.each {key, val ->
+				'b:property'(name: key, ref: val)
+			}
+		}
+	}
 
-    def createAppContext() {
-        createAppContext(AUTH_PROVIDER_XML)
-    }
+	def createAppContext() {
+		createAppContext(AUTH_PROVIDER_XML)
+	}
 
-    def createAppContext(String extraXml) {
-        appContext = new InMemoryXmlApplicationContext(writer.toString() + extraXml);
-        appContext.addApplicationListener(appListener);
-    }
+	def createAppContext(String extraXml) {
+		appContext = new InMemoryXmlApplicationContext(writer.toString() + extraXml);
+		appContext.addApplicationListener(appListener);
+	}
 }

+ 116 - 116
config/src/test/groovy/org/springframework/security/config/annotation/BaseSpringSpec.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -51,119 +51,119 @@ import spock.lang.Specification
  * @author Rob Winch
  */
 abstract class BaseSpringSpec extends Specification {
-    @AutoCleanup
-    ConfigurableApplicationContext context
-    @AutoCleanup
-    ConfigurableApplicationContext oppContext
-
-    MockHttpServletRequest request
-    MockHttpServletResponse response
-    MockFilterChain chain
-    CsrfToken csrfToken
-    AuthenticationManagerBuilder authenticationBldr
-
-    def setup() {
-        authenticationBldr = createAuthenticationManagerBuilder()
-        setupWeb(null)
-    }
-
-    def setupWeb(httpSession = null) {
-        request = new MockHttpServletRequest(method:"GET")
-        if(httpSession) {
-            request.session = httpSession
-        }
-        response = new MockHttpServletResponse()
-        chain = new MockFilterChain()
-        setupCsrf()
-    }
-
-    def setupCsrf(csrfTokenValue="BaseSpringSpec_CSRFTOKEN",req=request,resp=response) {
-        csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf",csrfTokenValue)
-        new HttpSessionCsrfTokenRepository().saveToken(csrfToken, req, resp)
-        req.setParameter(csrfToken.parameterName, csrfToken.token)
-    }
-
-    def cleanup() {
-        SecurityContextHolder.clearContext()
-    }
-
-    def loadConfig(Class<?>... configs) {
-        context = new AnnotationConfigApplicationContext(configs)
-        context
-    }
-
-    def findFilter(Class<?> filter, int index = 0) {
-        filterChain(index).filters.find { filter.isAssignableFrom(it.class)}
-    }
-
-    def filterChain(int index=0) {
-        filterChains()[index]
-    }
-
-    def filterChains() {
-        context.getBean(FilterChainProxy).filterChains
-    }
-
-    Filter getSpringSecurityFilterChain() {
-        context.getBean("springSecurityFilterChain",Filter.class)
-    }
-
-    def getResponseHeaders() {
-        def headers = [:]
-        response.headerNames.each { name ->
-            headers.put(name, response.getHeaderValues(name).join(','))
-        }
-        return headers
-    }
-
-    AuthenticationManager authenticationManager() {
-        context.getBean(AuthenticationManager)
-    }
-
-    AuthenticationManager getAuthenticationManager() {
-        try {
-            authenticationManager().delegateBuilder.getObject()
-        } catch(NoSuchBeanDefinitionException e) {
-        } catch(MissingPropertyException e) {}
-        findFilter(FilterSecurityInterceptor).authenticationManager
-    }
-
-    List<AuthenticationProvider> authenticationProviders() {
-        List<AuthenticationProvider> providers = new ArrayList<AuthenticationProvider>()
-        AuthenticationManager authenticationManager = getAuthenticationManager()
-        while(authenticationManager?.providers) {
-            providers.addAll(authenticationManager.providers)
-            authenticationManager = authenticationManager.parent
-        }
-        providers
-    }
-
-    AuthenticationProvider findAuthenticationProvider(Class<?> provider) {
-        authenticationProviders().find { provider.isAssignableFrom(it.class) }
-    }
-
-    def getCurrentAuthentication() {
-        new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response)).authentication
-    }
-
-    def login(String username="user", String role="ROLE_USER") {
-        login(new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role)))
-    }
-
-    def login(Authentication auth) {
-        HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
-        HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
-        repo.loadContext(requestResponseHolder)
-        repo.saveContext(new SecurityContextImpl(authentication:auth), requestResponseHolder.request, requestResponseHolder.response)
-    }
-
-    def createAuthenticationManagerBuilder() {
-        oppContext = new AnnotationConfigApplicationContext(ObjectPostProcessorConfiguration, AuthenticationConfiguration)
-        AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(objectPostProcessor)
-        auth.inMemoryAuthentication().and()
-    }
-
-    def getObjectPostProcessor() {
-        oppContext.getBean(ObjectPostProcessor)
-    }
+	@AutoCleanup
+	ConfigurableApplicationContext context
+	@AutoCleanup
+	ConfigurableApplicationContext oppContext
+
+	MockHttpServletRequest request
+	MockHttpServletResponse response
+	MockFilterChain chain
+	CsrfToken csrfToken
+	AuthenticationManagerBuilder authenticationBldr
+
+	def setup() {
+		authenticationBldr = createAuthenticationManagerBuilder()
+		setupWeb(null)
+	}
+
+	def setupWeb(httpSession = null) {
+		request = new MockHttpServletRequest(method:"GET")
+		if(httpSession) {
+			request.session = httpSession
+		}
+		response = new MockHttpServletResponse()
+		chain = new MockFilterChain()
+		setupCsrf()
+	}
+
+	def setupCsrf(csrfTokenValue="BaseSpringSpec_CSRFTOKEN",req=request,resp=response) {
+		csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf",csrfTokenValue)
+		new HttpSessionCsrfTokenRepository().saveToken(csrfToken, req, resp)
+		req.setParameter(csrfToken.parameterName, csrfToken.token)
+	}
+
+	def cleanup() {
+		SecurityContextHolder.clearContext()
+	}
+
+	def loadConfig(Class<?>... configs) {
+		context = new AnnotationConfigApplicationContext(configs)
+		context
+	}
+
+	def findFilter(Class<?> filter, int index = 0) {
+		filterChain(index).filters.find { filter.isAssignableFrom(it.class)}
+	}
+
+	def filterChain(int index=0) {
+		filterChains()[index]
+	}
+
+	def filterChains() {
+		context.getBean(FilterChainProxy).filterChains
+	}
+
+	Filter getSpringSecurityFilterChain() {
+		context.getBean("springSecurityFilterChain",Filter.class)
+	}
+
+	def getResponseHeaders() {
+		def headers = [:]
+		response.headerNames.each { name ->
+			headers.put(name, response.getHeaderValues(name).join(','))
+		}
+		return headers
+	}
+
+	AuthenticationManager authenticationManager() {
+		context.getBean(AuthenticationManager)
+	}
+
+	AuthenticationManager getAuthenticationManager() {
+		try {
+			authenticationManager().delegateBuilder.getObject()
+		} catch(NoSuchBeanDefinitionException e) {
+		} catch(MissingPropertyException e) {}
+		findFilter(FilterSecurityInterceptor).authenticationManager
+	}
+
+	List<AuthenticationProvider> authenticationProviders() {
+		List<AuthenticationProvider> providers = new ArrayList<AuthenticationProvider>()
+		AuthenticationManager authenticationManager = getAuthenticationManager()
+		while(authenticationManager?.providers) {
+			providers.addAll(authenticationManager.providers)
+			authenticationManager = authenticationManager.parent
+		}
+		providers
+	}
+
+	AuthenticationProvider findAuthenticationProvider(Class<?> provider) {
+		authenticationProviders().find { provider.isAssignableFrom(it.class) }
+	}
+
+	def getCurrentAuthentication() {
+		new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response)).authentication
+	}
+
+	def login(String username="user", String role="ROLE_USER") {
+		login(new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role)))
+	}
+
+	def login(Authentication auth) {
+		HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
+		HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
+		repo.loadContext(requestResponseHolder)
+		repo.saveContext(new SecurityContextImpl(authentication:auth), requestResponseHolder.request, requestResponseHolder.response)
+	}
+
+	def createAuthenticationManagerBuilder() {
+		oppContext = new AnnotationConfigApplicationContext(ObjectPostProcessorConfiguration, AuthenticationConfiguration)
+		AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(objectPostProcessor)
+		auth.inMemoryAuthentication().and()
+	}
+
+	def getObjectPostProcessor() {
+		oppContext.getBean(ObjectPostProcessor)
+	}
 }

+ 15 - 15
config/src/test/groovy/org/springframework/security/config/annotation/SecurityConfigurerAdapterTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -22,19 +22,19 @@ import spock.lang.Specification
  *
  */
 class SecurityConfigurerAdapterTests extends Specification {
-    ConcereteSecurityConfigurerAdapter conf = new ConcereteSecurityConfigurerAdapter()
+	ConcereteSecurityConfigurerAdapter conf = new ConcereteSecurityConfigurerAdapter()
 
-    def "addPostProcessor closure"() {
-        setup:
-            SecurityBuilder<Object> builder = Mock()
-            conf.addObjectPostProcessor({ List l ->
-                l.add("a")
-                l
-            } as ObjectPostProcessor<List>)
-        when:
-            conf.init(builder)
-            conf.configure(builder)
-        then:
-            conf.list.contains("a")
-    }
+	def "addPostProcessor closure"() {
+		setup:
+			SecurityBuilder<Object> builder = Mock()
+			conf.addObjectPostProcessor({ List l ->
+				l.add("a")
+				l
+			} as ObjectPostProcessor<List>)
+		when:
+			conf.init(builder)
+			conf.configure(builder)
+		then:
+			conf.list.contains("a")
+	}
 }

+ 52 - 52
config/src/test/groovy/org/springframework/security/config/annotation/issue50/Issue50Tests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -39,62 +39,62 @@ import spock.lang.Specification
 @ContextConfiguration(classes=[ApplicationConfig,SecurityConfig])
 @Transactional
 class Issue50Tests extends Specification {
-    @Autowired
-    private FilterChainProxy springSecurityFilterChain
-    @Autowired
-    private AuthenticationManager authenticationManager
-    @Autowired
-    private UserRepository userRepo
+	@Autowired
+	private FilterChainProxy springSecurityFilterChain
+	@Autowired
+	private AuthenticationManager authenticationManager
+	@Autowired
+	private UserRepository userRepo
 
-    def setup() {
-        SecurityContextHolder.context.authentication = new TestingAuthenticationToken("test",null,"ROLE_ADMIN")
-    }
+	def setup() {
+		SecurityContextHolder.context.authentication = new TestingAuthenticationToken("test",null,"ROLE_ADMIN")
+	}
 
-    def cleanup() {
-        SecurityContextHolder.clearContext()
-    }
+	def cleanup() {
+		SecurityContextHolder.clearContext()
+	}
 
-    // https://github.com/SpringSource/spring-security-javaconfig/issues/50
-    def "#50 - GlobalMethodSecurityConfiguration should load AuthenticationManager lazily"() {
-        when:
-        "Configuration Loads"
-        then: "GlobalMethodSecurityConfiguration loads AuthenticationManager lazily"
-        noExceptionThrown()
-    }
+	// https://github.com/SpringSource/spring-security-javaconfig/issues/50
+	def "#50 - GlobalMethodSecurityConfiguration should load AuthenticationManager lazily"() {
+		when:
+		"Configuration Loads"
+		then: "GlobalMethodSecurityConfiguration loads AuthenticationManager lazily"
+		noExceptionThrown()
+	}
 
-    def "AuthenticationManager will not authenticate missing user"() {
-        when:
-        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("test", "password"))
-        then:
-        thrown(UsernameNotFoundException)
-    }
+	def "AuthenticationManager will not authenticate missing user"() {
+		when:
+		authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("test", "password"))
+		then:
+		thrown(UsernameNotFoundException)
+	}
 
-    def "AuthenticationManager will not authenticate with invalid password"() {
-        when:
-        User user = new User(username:"test",password:"password")
-        userRepo.save(user)
-        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.username , "invalid"))
-        then:
-        thrown(BadCredentialsException)
-    }
+	def "AuthenticationManager will not authenticate with invalid password"() {
+		when:
+		User user = new User(username:"test",password:"password")
+		userRepo.save(user)
+		authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.username , "invalid"))
+		then:
+		thrown(BadCredentialsException)
+	}
 
-    def "AuthenticationManager can be used to authenticate a user"() {
-        when:
-        User user = new User(username:"test",password:"password")
-        userRepo.save(user)
-        Authentication result = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.username , user.password))
-        then:
-        result.principal == user.username
-    }
+	def "AuthenticationManager can be used to authenticate a user"() {
+		when:
+		User user = new User(username:"test",password:"password")
+		userRepo.save(user)
+		Authentication result = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.username , user.password))
+		then:
+		result.principal == user.username
+	}
 
-    def "Global Method Security is enabled and works"() {
-        setup:
-        SecurityContextHolder.context.authentication = new TestingAuthenticationToken("test",null,"ROLE_USER")
-        when:
-        User user = new User(username:"denied",password:"password")
-        userRepo.save(user)
-        Authentication result = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.username , user.password))
-        then:
-        thrown(AccessDeniedException)
-    }
+	def "Global Method Security is enabled and works"() {
+		setup:
+		SecurityContextHolder.context.authentication = new TestingAuthenticationToken("test",null,"ROLE_USER")
+		when:
+		User user = new User(username:"denied",password:"password")
+		userRepo.save(user)
+		Authentication result = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.username , user.password))
+		then:
+		thrown(AccessDeniedException)
+	}
 }

+ 96 - 96
config/src/test/groovy/org/springframework/security/config/annotation/sec2758/Sec2758Tests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -44,100 +44,100 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
 
 public class Sec2758Tests extends BaseSpringSpec {
 
-    def cleanup() {
-        SecurityContextHolder.clearContext()
-    }
-
-    def "SEC-2758: Verify Passivity Restored with Advice from JIRA"() {
-        setup:
-        SecurityContextHolder.context.authentication = new TestingAuthenticationToken("user", "pass", "USER")
-        loadConfig(SecurityConfig)
-        Service service = context.getBean(Service)
-
-        when:
-        findFilter(FilterSecurityInterceptor).doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain())
-        then:
-        noExceptionThrown()
-
-        when:
-        service.doPreAuthorize()
-        then:
-        noExceptionThrown()
-
-        when:
-        service.doJsr250()
-        then:
-        noExceptionThrown()
-    }
-
-    @EnableWebSecurity
-    @EnableGlobalMethodSecurity(prePostEnabled=true)
-    static class SecurityConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasAnyAuthority("USER");
-        }
-
-        @Autowired
-        public void configureGlobal(AuthenticationManagerBuilder auth) {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").authorities("USER")
-        }
-
-        @Bean
-        Service service() {
-            return new ServiceImpl()
-        }
-
-        @Bean
-        static DefaultRolesPrefixPostProcessor defaultRolesPrefixPostProcessor() {
-            new DefaultRolesPrefixPostProcessor()
-        }
-    }
-
-    interface Service {
-        void doPreAuthorize()
-        void doJsr250()
-    }
-
-    static class ServiceImpl implements Service {
-        @PreAuthorize("hasRole('USER')")
-        void doPreAuthorize() {}
-
-        @RolesAllowed("USER")
-        void doJsr250() {}
-    }
-
-    static class DefaultRolesPrefixPostProcessor implements BeanPostProcessor, PriorityOrdered {
-
-    @Override
-    public Object postProcessAfterInitialization(Object bean, String beanName)
-            throws BeansException {
-        if(bean instanceof Jsr250MethodSecurityMetadataSource) {
-            ((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(null);
-        }
-        if(bean instanceof DefaultMethodSecurityExpressionHandler) {
-            ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(null);
-        }
-        if(bean instanceof DefaultWebSecurityExpressionHandler) {
-            ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(null);
-        }
-        return bean;
-    }
-
-    @Override
-    public Object postProcessBeforeInitialization(Object bean, String beanName)
-            throws BeansException {
-        return bean;
-    }
-
-    @Override
-    public int getOrder() {
-        return PriorityOrdered.HIGHEST_PRECEDENCE;
-    }
+	def cleanup() {
+		SecurityContextHolder.clearContext()
+	}
+
+	def "SEC-2758: Verify Passivity Restored with Advice from JIRA"() {
+		setup:
+		SecurityContextHolder.context.authentication = new TestingAuthenticationToken("user", "pass", "USER")
+		loadConfig(SecurityConfig)
+		Service service = context.getBean(Service)
+
+		when:
+		findFilter(FilterSecurityInterceptor).doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain())
+		then:
+		noExceptionThrown()
+
+		when:
+		service.doPreAuthorize()
+		then:
+		noExceptionThrown()
+
+		when:
+		service.doJsr250()
+		then:
+		noExceptionThrown()
+	}
+
+	@EnableWebSecurity
+	@EnableGlobalMethodSecurity(prePostEnabled=true)
+	static class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasAnyAuthority("USER");
+		}
+
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").authorities("USER")
+		}
+
+		@Bean
+		Service service() {
+			return new ServiceImpl()
+		}
+
+		@Bean
+		static DefaultRolesPrefixPostProcessor defaultRolesPrefixPostProcessor() {
+			new DefaultRolesPrefixPostProcessor()
+		}
+	}
+
+	interface Service {
+		void doPreAuthorize()
+		void doJsr250()
+	}
+
+	static class ServiceImpl implements Service {
+		@PreAuthorize("hasRole('USER')")
+		void doPreAuthorize() {}
+
+		@RolesAllowed("USER")
+		void doJsr250() {}
+	}
+
+	static class DefaultRolesPrefixPostProcessor implements BeanPostProcessor, PriorityOrdered {
+
+	@Override
+	public Object postProcessAfterInitialization(Object bean, String beanName)
+			throws BeansException {
+		if(bean instanceof Jsr250MethodSecurityMetadataSource) {
+			((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(null);
+		}
+		if(bean instanceof DefaultMethodSecurityExpressionHandler) {
+			((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(null);
+		}
+		if(bean instanceof DefaultWebSecurityExpressionHandler) {
+			((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(null);
+		}
+		return bean;
+	}
+
+	@Override
+	public Object postProcessBeforeInitialization(Object bean, String beanName)
+			throws BeansException {
+		return bean;
+	}
+
+	@Override
+	public int getOrder() {
+		return PriorityOrdered.HIGHEST_PRECEDENCE;
+	}
 }
 }

+ 28 - 28
config/src/test/groovy/org/springframework/security/config/annotation/web/RequestMatchersTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -29,31 +29,31 @@ import spock.lang.Specification;
  */
 class RequestMatchersTests extends Specification {
 
-    def "regexMatchers(GET,'/a.*') uses RegexRequestMatcher"() {
-        when:
-        def matchers = regexMatchers(HttpMethod.GET, "/a.*")
-        then: 'matcher is a RegexRequestMatcher'
-        matchers.collect {it.class } == [RegexRequestMatcher]
-    }
-
-    def "regexMatchers('/a.*') uses RegexRequestMatcher"() {
-        when:
-        def matchers = regexMatchers("/a.*")
-        then: 'matcher is a RegexRequestMatcher'
-        matchers.collect {it.class } == [RegexRequestMatcher]
-    }
-
-    def "antMatchers(GET,'/a.*') uses AntPathRequestMatcher"() {
-        when:
-        def matchers = antMatchers(HttpMethod.GET, "/a.*")
-        then: 'matcher is a RegexRequestMatcher'
-        matchers.collect {it.class } == [AntPathRequestMatcher]
-    }
-
-    def "antMatchers('/a.*') uses AntPathRequestMatcher"() {
-        when:
-        def matchers = antMatchers("/a.*")
-        then: 'matcher is a AntPathRequestMatcher'
-        matchers.collect {it.class } == [AntPathRequestMatcher]
-    }
+	def "regexMatchers(GET,'/a.*') uses RegexRequestMatcher"() {
+		when:
+		def matchers = regexMatchers(HttpMethod.GET, "/a.*")
+		then: 'matcher is a RegexRequestMatcher'
+		matchers.collect {it.class } == [RegexRequestMatcher]
+	}
+
+	def "regexMatchers('/a.*') uses RegexRequestMatcher"() {
+		when:
+		def matchers = regexMatchers("/a.*")
+		then: 'matcher is a RegexRequestMatcher'
+		matchers.collect {it.class } == [RegexRequestMatcher]
+	}
+
+	def "antMatchers(GET,'/a.*') uses AntPathRequestMatcher"() {
+		when:
+		def matchers = antMatchers(HttpMethod.GET, "/a.*")
+		then: 'matcher is a RegexRequestMatcher'
+		matchers.collect {it.class } == [AntPathRequestMatcher]
+	}
+
+	def "antMatchers('/a.*') uses AntPathRequestMatcher"() {
+		when:
+		def matchers = antMatchers("/a.*")
+		then: 'matcher is a AntPathRequestMatcher'
+		matchers.collect {it.class } == [AntPathRequestMatcher]
+	}
 }

+ 437 - 437
config/src/test/groovy/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -60,440 +60,440 @@ import org.springframework.security.web.util.matcher.RequestMatcher
  *
  */
 public class NamespaceHttpTests extends BaseSpringSpec {
-    def "http@access-decision-manager-ref"() {
-        setup:
-            AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR = Mock(AccessDecisionManager)
-            AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR.supports(FilterInvocation) >> true
-            AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR.supports(_ as ConfigAttribute) >> true
-        when:
-            loadConfig(AccessDecisionManagerRefConfig)
-        then:
-            findFilter(FilterSecurityInterceptor).accessDecisionManager == AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR
-    }
-
-    @Configuration
-    static class AccessDecisionManagerRefConfig extends BaseWebConfig {
-        static AccessDecisionManager ACCESS_DECISION_MGR
-
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().permitAll()
-                    .accessDecisionManager(ACCESS_DECISION_MGR)
-        }
-    }
-
-    def "http@access-denied-page"() {
-        when:
-            loadConfig(AccessDeniedPageConfig)
-        then:
-            findFilter(ExceptionTranslationFilter).accessDeniedHandler.errorPage == "/AccessDeniedPageConfig"
-    }
-
-    @Configuration
-    static class AccessDeniedPageConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .exceptionHandling()
-                    .accessDeniedPage("/AccessDeniedPageConfig")
-        }
-    }
-
-    def "http@authentication-manager-ref"() {
-        when: "Specify AuthenticationManager"
-            loadConfig(AuthenticationManagerRefConfig)
-        then: "Populates the AuthenticationManager"
-            findFilter(FilterSecurityInterceptor).authenticationManager.parent.class == CustomAuthenticationManager
-    }
-
-    @Configuration
-    static class AuthenticationManagerRefConfig extends BaseWebConfig {
-        // demo authentication-manager-ref (could be any value)
-
-        @Override
-        protected AuthenticationManager authenticationManager() throws Exception {
-            return new CustomAuthenticationManager();
-        }
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER");
-        }
-
-        static class CustomAuthenticationManager implements AuthenticationManager {
-            public Authentication authenticate(Authentication authentication)
-                    throws AuthenticationException {
-                throw new BadCredentialsException("This always fails");
-            }
-        }
-    }
-
-    // Note: There is no http@auto-config equivalent in Java Config
-
-    def "http@create-session=always"() {
-        when:
-            loadConfig(IfRequiredConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
-            findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == true
-            findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == true
-            findFilter(ExceptionTranslationFilter).requestCache.class == HttpSessionRequestCache
-    }
-
-    @Configuration
-    static class CreateSessionAlwaysConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .sessionManagement()
-                    .sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
-        }
-    }
-
-    def "http@create-session=stateless"() {
-        when:
-            loadConfig(CreateSessionStatelessConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
-            findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository
-            findFilter(SessionManagementFilter).securityContextRepository.class == NullSecurityContextRepository
-            findFilter(ExceptionTranslationFilter).requestCache.class == NullRequestCache
-            findFilter(RequestCacheAwareFilter).requestCache.class == NullRequestCache
-    }
-
-    @Configuration
-    static class CreateSessionStatelessConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .sessionManagement()
-                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
-        }
-    }
-
-    def "http@create-session=ifRequired"() {
-        when:
-            loadConfig(IfRequiredConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
-            findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == true
-            findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == true
-    }
-
-    @Configuration
-    static class IfRequiredConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .sessionManagement()
-                    .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
-        }
-    }
-
-    def "http@create-session defaults to ifRequired"() {
-        when:
-            loadConfig(IfRequiredConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
-            findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == true
-            findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == true
-    }
-
-    def "http@create-session=never"() {
-        when:
-            loadConfig(CreateSessionNeverConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
-            findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == false
-            findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == false
-    }
-
-    @Configuration
-    static class CreateSessionNeverConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .sessionManagement()
-                    .sessionCreationPolicy(SessionCreationPolicy.NEVER);
-        }
-    }
-
-    @Configuration
-    static class DefaultCreateSessionConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-        }
-    }
-
-    def "http@disable-url-rewriting = true (default for Java Config)"() {
-        when:
-            loadConfig(DefaultUrlRewritingConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).repo.disableUrlRewriting
-    }
-
-    @Configuration
-    static class DefaultUrlRewritingConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-        }
-    }
-
-    // http@disable-url-rewriting is on by default to disable it create a custom HttpSecurityContextRepository and use security-context-repository-ref
-
-    def "http@disable-url-rewriting = false"() {
-        when:
-            loadConfig(EnableUrlRewritingConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).repo.disableUrlRewriting == false
-    }
-
-    @Configuration
-    static class EnableUrlRewritingConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            HttpSessionSecurityContextRepository repository = new HttpSessionSecurityContextRepository()
-            repository.disableUrlRewriting = false // explicitly configured (not necessary due to default values)
-
-            http.
-                securityContext()
-                    .securityContextRepository(repository)
-        }
-    }
-
-    def "http@entry-point-ref"() {
-        when:
-            loadConfig(EntryPointRefConfig)
-        then:
-            findFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl == "/EntryPointRefConfig"
-    }
-
-    @Configuration
-    static class EntryPointRefConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .exceptionHandling()
-                    .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/EntryPointRefConfig"))
-        }
-    }
-
-    def "http@jaas-api-provision"() {
-        when:
-            loadConfig(JaasApiProvisionConfig)
-        then:
-            findFilter(JaasApiIntegrationFilter)
-    }
-
-    @Configuration
-    static class JaasApiProvisionConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .addFilter(new JaasApiIntegrationFilter())
-        }
-    }
-
-    // http@name is not available since it can be done w/ standard bean configuration easily
-
-    def "http@once-per-request=true"() {
-        when:
-            loadConfig(OncePerRequestConfig)
-        then:
-            findFilter(FilterSecurityInterceptor).observeOncePerRequest
-    }
-
-    @Configuration
-    static class OncePerRequestConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER");
-        }
-    }
-
-    def "http@once-per-request=false"() {
-        when:
-            loadConfig(OncePerRequestFalseConfig)
-        then:
-            !findFilter(FilterSecurityInterceptor).observeOncePerRequest
-    }
-
-    @Configuration
-    static class OncePerRequestFalseConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http.
-                authorizeRequests()
-                    .filterSecurityInterceptorOncePerRequest(false)
-                    .antMatchers("/users**","/sessions/**").hasRole("ADMIN")
-                    .antMatchers("/signup").permitAll()
-                    .anyRequest().hasRole("USER");
-        }
-    }
-
-    def "http@realm"() {
-        setup:
-            loadConfig(RealmConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getHeader("WWW-Authenticate") == 'Basic realm="RealmConfig"'
-    }
-
-    @Configuration
-    static class RealmConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-                    .and()
-                .httpBasic().realmName("RealmConfig")
-        }
-    }
-
-    // http@request-matcher is not available (instead request matcher instances are used)
-
-    def "http@request-matcher-ref ant"() {
-        when:
-            loadConfig(RequestMatcherAntConfig)
-        then:
-            filterChain(0).requestMatcher.pattern == "/api/**"
-    }
-
-    @Configuration
-    static class RequestMatcherAntConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .antMatcher("/api/**")
-        }
-    }
-
-    def "http@request-matcher-ref regex"() {
-        when:
-            loadConfig(RequestMatcherRegexConfig)
-        then:
-            filterChain(0).requestMatcher.class == RegexRequestMatcher
-            filterChain(0).requestMatcher.pattern.matcher("/regex/a")
-            filterChain(0).requestMatcher.pattern.matcher("/regex/b")
-            !filterChain(0).requestMatcher.pattern.matcher("/regex1/b")
-    }
-
-    @Configuration
-    static class RequestMatcherRegexConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .regexMatcher("/regex/.*")
-        }
-    }
-
-    def "http@request-matcher-ref"() {
-        when:
-            loadConfig(RequestMatcherRefConfig)
-        then:
-            filterChain(0).requestMatcher.class == MyRequestMatcher
-    }
-
-    @Configuration
-    static class RequestMatcherRefConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .requestMatcher(new MyRequestMatcher());
-        }
-        static class MyRequestMatcher implements RequestMatcher {
-            public boolean matches(HttpServletRequest request) {
-                return true;
-            }
-        }
-    }
-
-    def "http@security=none"() {
-        when:
-            loadConfig(SecurityNoneConfig)
-        then:
-            filterChain(0).requestMatcher.pattern == "/resources/**"
-            filterChain(0).filters.empty
-            filterChain(1).requestMatcher.pattern == "/public/**"
-            filterChain(1).filters.empty
-    }
-
-    @Configuration
-    static class SecurityNoneConfig extends BaseWebConfig {
-
-        @Override
-        public void configure(WebSecurity web)
-                throws Exception {
-            web
-                .ignoring()
-                    .antMatchers("/resources/**","/public/**")
-        }
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {}
-
-    }
-
-    def "http@security-context-repository-ref"() {
-        when:
-            loadConfig(SecurityContextRepoConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository
-    }
-
-    @Configuration
-    static class SecurityContextRepoConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .securityContext()
-                    .securityContextRepository(new NullSecurityContextRepository()) // security-context-repository-ref
-        }
-    }
-
-    def "http@servlet-api-provision=false"() {
-        when:
-            loadConfig(ServletApiProvisionConfig)
-        then:
-            findFilter(SecurityContextHolderAwareRequestFilter) == null
-    }
-
-    @Configuration
-    static class ServletApiProvisionConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http.servletApi().disable()
-        }
-    }
-
-    def "http@servlet-api-provision defaults to true"() {
-        when:
-            loadConfig(ServletApiProvisionDefaultsConfig)
-        then:
-            findFilter(SecurityContextHolderAwareRequestFilter) != null
-    }
-
-    @Configuration
-    static class ServletApiProvisionDefaultsConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-        }
-    }
-
-    def "http@use-expressions=true"() {
-        when:
-            loadConfig(UseExpressionsConfig)
-        then:
-            findFilter(FilterSecurityInterceptor).securityMetadataSource.class == ExpressionBasedFilterInvocationSecurityMetadataSource
-            findFilter(FilterSecurityInterceptor).accessDecisionManager.decisionVoters.collect { it.class } == [WebExpressionVoter]
-    }
-
-    @EnableWebSecurity
-    static class UseExpressionsConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .antMatchers("/users**","/sessions/**").hasRole("USER")
-                    .antMatchers("/signup").permitAll()
-                    .anyRequest().hasRole("USER")
-        }
-    }
-
-    def "http@use-expressions=false"() {
-        when:
-            loadConfig(DisableUseExpressionsConfig)
-        then:
-            findFilter(FilterSecurityInterceptor).securityMetadataSource.class == DefaultFilterInvocationSecurityMetadataSource
-            findFilter(FilterSecurityInterceptor).accessDecisionManager.decisionVoters.collect { it.class } == [RoleVoter, AuthenticatedVoter]
-    }
+	def "http@access-decision-manager-ref"() {
+		setup:
+			AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR = Mock(AccessDecisionManager)
+			AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR.supports(FilterInvocation) >> true
+			AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR.supports(_ as ConfigAttribute) >> true
+		when:
+			loadConfig(AccessDecisionManagerRefConfig)
+		then:
+			findFilter(FilterSecurityInterceptor).accessDecisionManager == AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR
+	}
+
+	@Configuration
+	static class AccessDecisionManagerRefConfig extends BaseWebConfig {
+		static AccessDecisionManager ACCESS_DECISION_MGR
+
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().permitAll()
+					.accessDecisionManager(ACCESS_DECISION_MGR)
+		}
+	}
+
+	def "http@access-denied-page"() {
+		when:
+			loadConfig(AccessDeniedPageConfig)
+		then:
+			findFilter(ExceptionTranslationFilter).accessDeniedHandler.errorPage == "/AccessDeniedPageConfig"
+	}
+
+	@Configuration
+	static class AccessDeniedPageConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.exceptionHandling()
+					.accessDeniedPage("/AccessDeniedPageConfig")
+		}
+	}
+
+	def "http@authentication-manager-ref"() {
+		when: "Specify AuthenticationManager"
+			loadConfig(AuthenticationManagerRefConfig)
+		then: "Populates the AuthenticationManager"
+			findFilter(FilterSecurityInterceptor).authenticationManager.parent.class == CustomAuthenticationManager
+	}
+
+	@Configuration
+	static class AuthenticationManagerRefConfig extends BaseWebConfig {
+		// demo authentication-manager-ref (could be any value)
+
+		@Override
+		protected AuthenticationManager authenticationManager() throws Exception {
+			return new CustomAuthenticationManager();
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER");
+		}
+
+		static class CustomAuthenticationManager implements AuthenticationManager {
+			public Authentication authenticate(Authentication authentication)
+					throws AuthenticationException {
+				throw new BadCredentialsException("This always fails");
+			}
+		}
+	}
+
+	// Note: There is no http@auto-config equivalent in Java Config
+
+	def "http@create-session=always"() {
+		when:
+			loadConfig(IfRequiredConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
+			findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == true
+			findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == true
+			findFilter(ExceptionTranslationFilter).requestCache.class == HttpSessionRequestCache
+	}
+
+	@Configuration
+	static class CreateSessionAlwaysConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
+		}
+	}
+
+	def "http@create-session=stateless"() {
+		when:
+			loadConfig(CreateSessionStatelessConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
+			findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository
+			findFilter(SessionManagementFilter).securityContextRepository.class == NullSecurityContextRepository
+			findFilter(ExceptionTranslationFilter).requestCache.class == NullRequestCache
+			findFilter(RequestCacheAwareFilter).requestCache.class == NullRequestCache
+	}
+
+	@Configuration
+	static class CreateSessionStatelessConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+		}
+	}
+
+	def "http@create-session=ifRequired"() {
+		when:
+			loadConfig(IfRequiredConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
+			findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == true
+			findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == true
+	}
+
+	@Configuration
+	static class IfRequiredConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
+		}
+	}
+
+	def "http@create-session defaults to ifRequired"() {
+		when:
+			loadConfig(IfRequiredConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
+			findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == true
+			findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == true
+	}
+
+	def "http@create-session=never"() {
+		when:
+			loadConfig(CreateSessionNeverConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
+			findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == false
+			findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == false
+	}
+
+	@Configuration
+	static class CreateSessionNeverConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.NEVER);
+		}
+	}
+
+	@Configuration
+	static class DefaultCreateSessionConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+		}
+	}
+
+	def "http@disable-url-rewriting = true (default for Java Config)"() {
+		when:
+			loadConfig(DefaultUrlRewritingConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).repo.disableUrlRewriting
+	}
+
+	@Configuration
+	static class DefaultUrlRewritingConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+		}
+	}
+
+	// http@disable-url-rewriting is on by default to disable it create a custom HttpSecurityContextRepository and use security-context-repository-ref
+
+	def "http@disable-url-rewriting = false"() {
+		when:
+			loadConfig(EnableUrlRewritingConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).repo.disableUrlRewriting == false
+	}
+
+	@Configuration
+	static class EnableUrlRewritingConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			HttpSessionSecurityContextRepository repository = new HttpSessionSecurityContextRepository()
+			repository.disableUrlRewriting = false // explicitly configured (not necessary due to default values)
+
+			http.
+				securityContext()
+					.securityContextRepository(repository)
+		}
+	}
+
+	def "http@entry-point-ref"() {
+		when:
+			loadConfig(EntryPointRefConfig)
+		then:
+			findFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl == "/EntryPointRefConfig"
+	}
+
+	@Configuration
+	static class EntryPointRefConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.exceptionHandling()
+					.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/EntryPointRefConfig"))
+		}
+	}
+
+	def "http@jaas-api-provision"() {
+		when:
+			loadConfig(JaasApiProvisionConfig)
+		then:
+			findFilter(JaasApiIntegrationFilter)
+	}
+
+	@Configuration
+	static class JaasApiProvisionConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.addFilter(new JaasApiIntegrationFilter())
+		}
+	}
+
+	// http@name is not available since it can be done w/ standard bean configuration easily
+
+	def "http@once-per-request=true"() {
+		when:
+			loadConfig(OncePerRequestConfig)
+		then:
+			findFilter(FilterSecurityInterceptor).observeOncePerRequest
+	}
+
+	@Configuration
+	static class OncePerRequestConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER");
+		}
+	}
+
+	def "http@once-per-request=false"() {
+		when:
+			loadConfig(OncePerRequestFalseConfig)
+		then:
+			!findFilter(FilterSecurityInterceptor).observeOncePerRequest
+	}
+
+	@Configuration
+	static class OncePerRequestFalseConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http.
+				authorizeRequests()
+					.filterSecurityInterceptorOncePerRequest(false)
+					.antMatchers("/users**","/sessions/**").hasRole("ADMIN")
+					.antMatchers("/signup").permitAll()
+					.anyRequest().hasRole("USER");
+		}
+	}
+
+	def "http@realm"() {
+		setup:
+			loadConfig(RealmConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getHeader("WWW-Authenticate") == 'Basic realm="RealmConfig"'
+	}
+
+	@Configuration
+	static class RealmConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.httpBasic().realmName("RealmConfig")
+		}
+	}
+
+	// http@request-matcher is not available (instead request matcher instances are used)
+
+	def "http@request-matcher-ref ant"() {
+		when:
+			loadConfig(RequestMatcherAntConfig)
+		then:
+			filterChain(0).requestMatcher.pattern == "/api/**"
+	}
+
+	@Configuration
+	static class RequestMatcherAntConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.antMatcher("/api/**")
+		}
+	}
+
+	def "http@request-matcher-ref regex"() {
+		when:
+			loadConfig(RequestMatcherRegexConfig)
+		then:
+			filterChain(0).requestMatcher.class == RegexRequestMatcher
+			filterChain(0).requestMatcher.pattern.matcher("/regex/a")
+			filterChain(0).requestMatcher.pattern.matcher("/regex/b")
+			!filterChain(0).requestMatcher.pattern.matcher("/regex1/b")
+	}
+
+	@Configuration
+	static class RequestMatcherRegexConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.regexMatcher("/regex/.*")
+		}
+	}
+
+	def "http@request-matcher-ref"() {
+		when:
+			loadConfig(RequestMatcherRefConfig)
+		then:
+			filterChain(0).requestMatcher.class == MyRequestMatcher
+	}
+
+	@Configuration
+	static class RequestMatcherRefConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.requestMatcher(new MyRequestMatcher());
+		}
+		static class MyRequestMatcher implements RequestMatcher {
+			public boolean matches(HttpServletRequest request) {
+				return true;
+			}
+		}
+	}
+
+	def "http@security=none"() {
+		when:
+			loadConfig(SecurityNoneConfig)
+		then:
+			filterChain(0).requestMatcher.pattern == "/resources/**"
+			filterChain(0).filters.empty
+			filterChain(1).requestMatcher.pattern == "/public/**"
+			filterChain(1).filters.empty
+	}
+
+	@Configuration
+	static class SecurityNoneConfig extends BaseWebConfig {
+
+		@Override
+		public void configure(WebSecurity web)
+				throws Exception {
+			web
+				.ignoring()
+					.antMatchers("/resources/**","/public/**")
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {}
+
+	}
+
+	def "http@security-context-repository-ref"() {
+		when:
+			loadConfig(SecurityContextRepoConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository
+	}
+
+	@Configuration
+	static class SecurityContextRepoConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.securityContext()
+					.securityContextRepository(new NullSecurityContextRepository()) // security-context-repository-ref
+		}
+	}
+
+	def "http@servlet-api-provision=false"() {
+		when:
+			loadConfig(ServletApiProvisionConfig)
+		then:
+			findFilter(SecurityContextHolderAwareRequestFilter) == null
+	}
+
+	@Configuration
+	static class ServletApiProvisionConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http.servletApi().disable()
+		}
+	}
+
+	def "http@servlet-api-provision defaults to true"() {
+		when:
+			loadConfig(ServletApiProvisionDefaultsConfig)
+		then:
+			findFilter(SecurityContextHolderAwareRequestFilter) != null
+	}
+
+	@Configuration
+	static class ServletApiProvisionDefaultsConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+		}
+	}
+
+	def "http@use-expressions=true"() {
+		when:
+			loadConfig(UseExpressionsConfig)
+		then:
+			findFilter(FilterSecurityInterceptor).securityMetadataSource.class == ExpressionBasedFilterInvocationSecurityMetadataSource
+			findFilter(FilterSecurityInterceptor).accessDecisionManager.decisionVoters.collect { it.class } == [WebExpressionVoter]
+	}
+
+	@EnableWebSecurity
+	static class UseExpressionsConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.antMatchers("/users**","/sessions/**").hasRole("USER")
+					.antMatchers("/signup").permitAll()
+					.anyRequest().hasRole("USER")
+		}
+	}
+
+	def "http@use-expressions=false"() {
+		when:
+			loadConfig(DisableUseExpressionsConfig)
+		then:
+			findFilter(FilterSecurityInterceptor).securityMetadataSource.class == DefaultFilterInvocationSecurityMetadataSource
+			findFilter(FilterSecurityInterceptor).accessDecisionManager.decisionVoters.collect { it.class } == [RoleVoter, AuthenticatedVoter]
+	}
 }

+ 12 - 12
config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/BaseWebConfig.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,17 +24,17 @@ import org.springframework.security.config.annotation.authentication.builders.Au
  */
 @EnableWebSecurity
 public abstract class BaseWebConfig extends WebSecurityConfigurerAdapter {
-    BaseWebConfig(boolean disableDefaults) {
-        super(disableDefaults)
-    }
+	BaseWebConfig(boolean disableDefaults) {
+		super(disableDefaults)
+	}
 
-    BaseWebConfig() {
-    }
+	BaseWebConfig() {
+	}
 
-    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-        auth
-            .inMemoryAuthentication()
-                .withUser("user").password("password").roles("USER").and()
-                .withUser("admin").password("password").roles("USER", "ADMIN");
-    }
+	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+		auth
+			.inMemoryAuthentication()
+				.withUser("user").password("password").roles("USER").and()
+				.withUser("admin").password("password").roles("USER", "ADMIN");
+	}
 }

+ 72 - 72
config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -28,86 +28,86 @@ import org.springframework.security.config.annotation.authentication.builders.Au
 
 public class Sec2515Tests extends BaseSpringSpec {
 
-    def "SEC-2515: Prevent StackOverflow with bean graph cycle"() {
-        when:
-           loadConfig(StackOverflowSecurityConfig)
-        then:
-            thrown(FatalBeanException)
-    }
+	def "SEC-2515: Prevent StackOverflow with bean graph cycle"() {
+		when:
+		   loadConfig(StackOverflowSecurityConfig)
+		then:
+			thrown(FatalBeanException)
+	}
 
-    @EnableWebSecurity
-    static class StackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class StackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        @Bean
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-    }
+		@Override
+		@Bean
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+	}
 
-    def "Custom Name Prevent StackOverflow with bean graph cycle"() {
-        when:
-           loadConfig(StackOverflowSecurityConfig)
-        then:
-            thrown(FatalBeanException)
-    }
+	def "Custom Name Prevent StackOverflow with bean graph cycle"() {
+		when:
+		   loadConfig(StackOverflowSecurityConfig)
+		then:
+			thrown(FatalBeanException)
+	}
 
-    @EnableWebSecurity
-    static class CustomBeanNameStackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class CustomBeanNameStackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        @Bean(name="custom")
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-    }
+		@Override
+		@Bean(name="custom")
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+	}
 
-    def "SEC-2549: Can load with child classloader"() {
-        setup:
-            CanLoadWithChildConfig.AM = Mock(AuthenticationManager)
-            context = new AnnotationConfigApplicationContext()
-            context.classLoader = new URLClassLoader(new URL[0], context.classLoader)
-            context.register(CanLoadWithChildConfig)
-            context.refresh()
-        when:
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
-        then:
-            noExceptionThrown()
-            1 * CanLoadWithChildConfig.AM.authenticate(_) >> new TestingAuthenticationToken("user","password","ROLE_USER")
-    }
+	def "SEC-2549: Can load with child classloader"() {
+		setup:
+			CanLoadWithChildConfig.AM = Mock(AuthenticationManager)
+			context = new AnnotationConfigApplicationContext()
+			context.classLoader = new URLClassLoader(new URL[0], context.classLoader)
+			context.register(CanLoadWithChildConfig)
+			context.refresh()
+		when:
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
+		then:
+			noExceptionThrown()
+			1 * CanLoadWithChildConfig.AM.authenticate(_) >> new TestingAuthenticationToken("user","password","ROLE_USER")
+	}
 
-    @EnableWebSecurity
-    static class CanLoadWithChildConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationManager AM
-        @Bean
-        public AuthenticationManager am() {
-            AM
-        }
-    }
+	@EnableWebSecurity
+	static class CanLoadWithChildConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationManager AM
+		@Bean
+		public AuthenticationManager am() {
+			AM
+		}
+	}
 
-    def "SEC-2515: @Bean still works when configure(AuthenticationManagerBuilder) used"() {
-        when:
-           loadConfig(SecurityConfig)
-        then:
-            noExceptionThrown();
-    }
+	def "SEC-2515: @Bean still works when configure(AuthenticationManagerBuilder) used"() {
+		when:
+		   loadConfig(SecurityConfig)
+		then:
+			noExceptionThrown();
+	}
 
-    @EnableWebSecurity
-    static class SecurityConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class SecurityConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        @Bean
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
+		@Override
+		@Bean
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
 
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth)
-                throws Exception {
-            auth.inMemoryAuthentication()
-        }
-    }
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth)
+				throws Exception {
+			auth.inMemoryAuthentication()
+		}
+	}
 }

+ 75 - 75
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/Issue55Tests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -36,83 +36,83 @@ import org.springframework.stereotype.Component
  */
 class Issue55Tests extends BaseSpringSpec {
 
-    def "WebSecurityConfigurerAdapter defaults to @Autowired"() {
-        setup:
-            TestingAuthenticationToken token = new TestingAuthenticationToken("test", "this")
-        when:
-            loadConfig(WebSecurityConfigurerAdapterDefaultsAuthManagerConfig)
-        then:
-            context.getBean(FilterChainProxy)
-            findFilter(FilterSecurityInterceptor).authenticationManager.authenticate(token) == CustomAuthenticationManager.RESULT
-     }
+	def "WebSecurityConfigurerAdapter defaults to @Autowired"() {
+		setup:
+			TestingAuthenticationToken token = new TestingAuthenticationToken("test", "this")
+		when:
+			loadConfig(WebSecurityConfigurerAdapterDefaultsAuthManagerConfig)
+		then:
+			context.getBean(FilterChainProxy)
+			findFilter(FilterSecurityInterceptor).authenticationManager.authenticate(token) == CustomAuthenticationManager.RESULT
+	 }
 
-    @EnableWebSecurity
-    static class WebSecurityConfigurerAdapterDefaultsAuthManagerConfig {
-        @Component
-        public static class WebSecurityAdapter extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class WebSecurityConfigurerAdapterDefaultsAuthManagerConfig {
+		@Component
+		public static class WebSecurityAdapter extends WebSecurityConfigurerAdapter {
 
-            @Override
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .authorizeRequests()
-                        .anyRequest().hasRole("USER");
-            }
-        }
-        @Configuration
-        public static class AuthenticationManagerConfiguration {
-            @Bean
-            public AuthenticationManager authenticationManager() throws Exception {
-                return new CustomAuthenticationManager();
-            }
-        }
-    }
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.authorizeRequests()
+						.anyRequest().hasRole("USER");
+			}
+		}
+		@Configuration
+		public static class AuthenticationManagerConfiguration {
+			@Bean
+			public AuthenticationManager authenticationManager() throws Exception {
+				return new CustomAuthenticationManager();
+			}
+		}
+	}
 
-    def "multi http WebSecurityConfigurerAdapter defaults to @Autowired"() {
-        setup:
-            TestingAuthenticationToken token = new TestingAuthenticationToken("test", "this")
-        when:
-            loadConfig(MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig)
-        then:
-            context.getBean(FilterChainProxy)
-            findFilter(FilterSecurityInterceptor).authenticationManager.authenticate(token) == CustomAuthenticationManager.RESULT
-            findFilter(FilterSecurityInterceptor,1).authenticationManager.authenticate(token) == CustomAuthenticationManager.RESULT
-     }
+	def "multi http WebSecurityConfigurerAdapter defaults to @Autowired"() {
+		setup:
+			TestingAuthenticationToken token = new TestingAuthenticationToken("test", "this")
+		when:
+			loadConfig(MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig)
+		then:
+			context.getBean(FilterChainProxy)
+			findFilter(FilterSecurityInterceptor).authenticationManager.authenticate(token) == CustomAuthenticationManager.RESULT
+			findFilter(FilterSecurityInterceptor,1).authenticationManager.authenticate(token) == CustomAuthenticationManager.RESULT
+	 }
 
-    @EnableWebSecurity
-    static class MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig {
-        @Component
-        @Order(1)
-        public static class ApiWebSecurityAdapter extends WebSecurityConfigurerAdapter {
-            @Override
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .antMatcher("/api/**")
-                    .authorizeRequests()
-                        .anyRequest().hasRole("USER");
-            }
-        }
-        @Component
-        public static class WebSecurityAdapter extends WebSecurityConfigurerAdapter {
-            @Override
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .authorizeRequests()
-                        .anyRequest().hasRole("USER");
-            }
-        }
-        @Configuration
-        public static class AuthenticationManagerConfiguration {
-            @Bean
-            public AuthenticationManager authenticationManager() throws Exception {
-                return new CustomAuthenticationManager();
-            }
-        }
-    }
+	@EnableWebSecurity
+	static class MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig {
+		@Component
+		@Order(1)
+		public static class ApiWebSecurityAdapter extends WebSecurityConfigurerAdapter {
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.antMatcher("/api/**")
+					.authorizeRequests()
+						.anyRequest().hasRole("USER");
+			}
+		}
+		@Component
+		public static class WebSecurityAdapter extends WebSecurityConfigurerAdapter {
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.authorizeRequests()
+						.anyRequest().hasRole("USER");
+			}
+		}
+		@Configuration
+		public static class AuthenticationManagerConfiguration {
+			@Bean
+			public AuthenticationManager authenticationManager() throws Exception {
+				return new CustomAuthenticationManager();
+			}
+		}
+	}
 
-    static class CustomAuthenticationManager implements AuthenticationManager {
-        static Authentication RESULT = new TestingAuthenticationToken("test", "this","ROLE_USER")
-        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
-            return RESULT;
-        }
-    }
+	static class CustomAuthenticationManager implements AuthenticationManager {
+		static Authentication RESULT = new TestingAuthenticationToken("test", "this","ROLE_USER")
+		public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+			return RESULT;
+		}
+	}
 }

+ 1 - 1
config/src/test/groovy/org/springframework/security/config/debug/AuthProviderDependency.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,

+ 10 - 10
config/src/test/groovy/org/springframework/security/config/debug/TestAuthenticationProvider.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -29,15 +29,15 @@ import org.springframework.stereotype.Service
 @Service("authProvider")
 public class TestAuthenticationProvider implements AuthenticationProvider {
 
-    @Autowired
-    public TestAuthenticationProvider(AuthProviderDependency authProviderDependency) {
-    }
+	@Autowired
+	public TestAuthenticationProvider(AuthProviderDependency authProviderDependency) {
+	}
 
-    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
-        throw new UnsupportedOperationException();
-    }
+	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+		throw new UnsupportedOperationException();
+	}
 
-    public boolean supports(Class<?> authentication) {
-        throw new UnsupportedOperationException();
-    }
+	public boolean supports(Class<?> authentication) {
+		throw new UnsupportedOperationException();
+	}
 }

+ 6 - 6
config/src/test/groovy/org/springframework/security/config/doc/Attribute.groovy

@@ -23,11 +23,11 @@ package org.springframework.security.config.doc
  * @see XsdDocumentedSpec
  */
 class Attribute {
-    def name
-    def desc
-    def elmt
+	def name
+	def desc
+	def elmt
 
-    def getId() {
-        return "${elmt.id}-${name}".toString()
-    }
+	def getId() {
+		return "${elmt.id}-${name}".toString()
+	}
 }

+ 60 - 60
config/src/test/groovy/org/springframework/security/config/doc/Element.groovy

@@ -23,68 +23,68 @@ package org.springframework.security.config.doc
 * @see XsdDocumentedSpec
 */
 class Element {
-    def name
-    def desc
-    def attrs
-    /**
-     * Contains the elements that extend this element (i.e. any-user-service contains ldap-user-service)
-     */
-    def subGrps = []
-    def childElmts = [:]
-    def parentElmts = [:]
+	def name
+	def desc
+	def attrs
+	/**
+	 * Contains the elements that extend this element (i.e. any-user-service contains ldap-user-service)
+	 */
+	def subGrps = []
+	def childElmts = [:]
+	def parentElmts = [:]
 
-    def getId() {
-        return "nsa-${name}".toString()
-    }
+	def getId() {
+		return "nsa-${name}".toString()
+	}
 
-    /**
-     * Gets all the ids related to this Element including attributes, parent elements, and child elements.
-     *
-     * <p>
-     * The expected ids to be found are documented below.
-     * <ul>
-     * <li>Elements - any xml element will have the nsa-&lt;element&gt;. For example the http element will have the id
-     * nsa-http</li>
-     * <li>Parent Section - Any element with a parent other than beans will have a section named
-     * nsa-&lt;element&gt;-parents. For example, authentication-provider would have a section id of
-     * nsa-authentication-provider-parents. The section would then contain a list of links pointing to the
-     * documentation for each parent element.</li>
-     * <li>Attributes Section - Any element with attributes will have a section with the id
-     * nsa-&lt;element&gt;-attributes. For example the http element would require a section with the id
-     * http-attributes.</li>
-     * <li>Attribute - Each attribute of an element would have an id of nsa-&lt;element&gt;-&lt;attributeName&gt;. For
-     * example the attribute create-session for the http attribute would have the id http-create-session.</li>
-     * <li>Child Section - Any element with a child element will have a section named nsa-&lt;element&gt;-children.
-     * For example, authentication-provider would have a section id of nsa-authentication-provider-children. The
-     * section would then contain a list of links pointing to the documentation for each child element.</li>
-     * </ul>
-     * @return
-     */
-    def getIds() {
-        def ids = [id]
-        childElmts.values()*.ids.each { ids.addAll it }
-        attrs*.id.each { ids.add it }
-        if(childElmts) {
-            ids.add id+'-children'
-        }
-        if(attrs) {
-            ids.add id+'-attributes'
-        }
-        if(parentElmts) {
-            ids.add id+'-parents'
-        }
-        ids
-    }
+	/**
+	 * Gets all the ids related to this Element including attributes, parent elements, and child elements.
+	 *
+	 * <p>
+	 * The expected ids to be found are documented below.
+	 * <ul>
+	 * <li>Elements - any xml element will have the nsa-&lt;element&gt;. For example the http element will have the id
+	 * nsa-http</li>
+	 * <li>Parent Section - Any element with a parent other than beans will have a section named
+	 * nsa-&lt;element&gt;-parents. For example, authentication-provider would have a section id of
+	 * nsa-authentication-provider-parents. The section would then contain a list of links pointing to the
+	 * documentation for each parent element.</li>
+	 * <li>Attributes Section - Any element with attributes will have a section with the id
+	 * nsa-&lt;element&gt;-attributes. For example the http element would require a section with the id
+	 * http-attributes.</li>
+	 * <li>Attribute - Each attribute of an element would have an id of nsa-&lt;element&gt;-&lt;attributeName&gt;. For
+	 * example the attribute create-session for the http attribute would have the id http-create-session.</li>
+	 * <li>Child Section - Any element with a child element will have a section named nsa-&lt;element&gt;-children.
+	 * For example, authentication-provider would have a section id of nsa-authentication-provider-children. The
+	 * section would then contain a list of links pointing to the documentation for each child element.</li>
+	 * </ul>
+	 * @return
+	 */
+	def getIds() {
+		def ids = [id]
+		childElmts.values()*.ids.each { ids.addAll it }
+		attrs*.id.each { ids.add it }
+		if(childElmts) {
+			ids.add id+'-children'
+		}
+		if(attrs) {
+			ids.add id+'-attributes'
+		}
+		if(parentElmts) {
+			ids.add id+'-parents'
+		}
+		ids
+	}
 
-    def getAllChildElmts() {
-        def result = [:]
-        childElmts.values()*.subGrps*.each { elmt -> result.put(elmt.name,elmt) }
-        result + childElmts
-    }
+	def getAllChildElmts() {
+		def result = [:]
+		childElmts.values()*.subGrps*.each { elmt -> result.put(elmt.name,elmt) }
+		result + childElmts
+	}
 
-    def getAllParentElmts() {
-        def result = [:]
-        parentElmts.values()*.subGrps*.each { elmt -> result.put(elmt.name,elmt) }
-        result + parentElmts
-    }
+	def getAllParentElmts() {
+		def result = [:]
+		parentElmts.values()*.subGrps*.each { elmt -> result.put(elmt.name,elmt) }
+		result + parentElmts
+	}
 }

+ 139 - 139
config/src/test/groovy/org/springframework/security/config/doc/SpringSecurityXsdParser.groovy

@@ -23,155 +23,155 @@ import groovy.xml.Namespace
  * @author Rob Winch
  */
 class SpringSecurityXsdParser {
-    private def rootElement
+	private def rootElement
 
-    private def xs = new Namespace("http://www.w3.org/2001/XMLSchema", 'xs')
-    private def attrElmts = [] as Set
-    private def elementNameToElement = [:] as Map
+	private def xs = new Namespace("http://www.w3.org/2001/XMLSchema", 'xs')
+	private def attrElmts = [] as Set
+	private def elementNameToElement = [:] as Map
 
-    /**
-     * Returns a map of the element name to the {@link Element}.
-     * @return
-     */
-    Map<String,Element> parse() {
-        elements(rootElement)
-        elementNameToElement
-    }
+	/**
+	 * Returns a map of the element name to the {@link Element}.
+	 * @return
+	 */
+	Map<String,Element> parse() {
+		elements(rootElement)
+		elementNameToElement
+	}
 
-    /**
-     * Creates a Map of the name to an Element object of all the children of element.
-     *
-     * @param element
-     * @return
-     */
-    private def elements(element) {
-        def elementNameToElement = [:] as Map
-        element.children().each { c->
-            if(c.name() == 'element') {
-              def e = elmt(c)
-              elementNameToElement.put(e.name,e)
-            } else {
-              elementNameToElement.putAll(elements(c))
-            }
-        }
-        elementNameToElement
-    }
+	/**
+	 * Creates a Map of the name to an Element object of all the children of element.
+	 *
+	 * @param element
+	 * @return
+	 */
+	private def elements(element) {
+		def elementNameToElement = [:] as Map
+		element.children().each { c->
+			if(c.name() == 'element') {
+			  def e = elmt(c)
+			  elementNameToElement.put(e.name,e)
+			} else {
+			  elementNameToElement.putAll(elements(c))
+			}
+		}
+		elementNameToElement
+	}
 
-    /**
-     * Any children that are attribute will be returned as an Attribute object.
-     * @param element
-     * @return a collection of Attribute objects that are children of element.
-     */
-    private def attrs(element) {
-        def r = []
-        element.children().each { c->
-            if(c.name() == 'attribute') {
-                r.add(attr(c))
-            }else if(c.name() == 'element') {
-            }else {
-                r.addAll(attrs(c))
-            }
-        }
-        r
-    }
+	/**
+	 * Any children that are attribute will be returned as an Attribute object.
+	 * @param element
+	 * @return a collection of Attribute objects that are children of element.
+	 */
+	private def attrs(element) {
+		def r = []
+		element.children().each { c->
+			if(c.name() == 'attribute') {
+				r.add(attr(c))
+			}else if(c.name() == 'element') {
+			}else {
+				r.addAll(attrs(c))
+			}
+		}
+		r
+	}
 
-    /**
-     * Any children will be searched for an attributeGroup, each of it's children will be returned as an Attribute
-     * @param element
-     * @return
-     */
-    private def attrgrps(element) {
-        def r = []
-        element.children().each { c->
-            if(c.name() == 'element') {
-            }else if (c.name() == 'attributeGroup') {
-               if(c.attributes().get('name')) {
-                   r.addAll(attrgrp(c))
-               } else {
-                   def n = c.attributes().get('ref').split(':')[1]
-                   def attrGrp = findNode(element,n)
-                   r.addAll(attrgrp(attrGrp))
-               }
-            } else {
-               r.addAll(attrgrps(c))
-            }
-        }
-        r
-    }
+	/**
+	 * Any children will be searched for an attributeGroup, each of it's children will be returned as an Attribute
+	 * @param element
+	 * @return
+	 */
+	private def attrgrps(element) {
+		def r = []
+		element.children().each { c->
+			if(c.name() == 'element') {
+			}else if (c.name() == 'attributeGroup') {
+			   if(c.attributes().get('name')) {
+				   r.addAll(attrgrp(c))
+			   } else {
+				   def n = c.attributes().get('ref').split(':')[1]
+				   def attrGrp = findNode(element,n)
+				   r.addAll(attrgrp(attrGrp))
+			   }
+			} else {
+			   r.addAll(attrgrps(c))
+			}
+		}
+		r
+	}
 
-    private def findNode(c,name) {
-        def root = c
-        while(root.name() != 'schema') {
-            root = root.parent()
-        }
-        def result = root.breadthFirst().find { child-> name == child.@name?.text() }
-        assert result?.@name?.text() == name
-        result
-    }
+	private def findNode(c,name) {
+		def root = c
+		while(root.name() != 'schema') {
+			root = root.parent()
+		}
+		def result = root.breadthFirst().find { child-> name == child.@name?.text() }
+		assert result?.@name?.text() == name
+		result
+	}
 
-    /**
-     * Processes an individual attributeGroup by obtaining all the attributes and then looking for more attributeGroup elements and prcessing them.
-     * @param e
-     * @return all the attributes for a specific attributeGroup and any child attributeGroups
-     */
-    private def attrgrp(e) {
-        def attrs = attrs(e)
-        attrs.addAll(attrgrps(e))
-        attrs
-    }
+	/**
+	 * Processes an individual attributeGroup by obtaining all the attributes and then looking for more attributeGroup elements and prcessing them.
+	 * @param e
+	 * @return all the attributes for a specific attributeGroup and any child attributeGroups
+	 */
+	private def attrgrp(e) {
+		def attrs = attrs(e)
+		attrs.addAll(attrgrps(e))
+		attrs
+	}
 
-    /**
-     * Obtains the description for a specific element
-     * @param element
-     * @return
-     */
-    private def desc(element) {
-        return element['annotation']['documentation']
-    }
+	/**
+	 * Obtains the description for a specific element
+	 * @param element
+	 * @return
+	 */
+	private def desc(element) {
+		return element['annotation']['documentation']
+	}
 
-    /**
-     * Given an element creates an attribute from it.
-     * @param n
-     * @return
-     */
-    private def attr(n) {
-        new Attribute(desc: desc(n), name: n.@name.text())
-    }
+	/**
+	 * Given an element creates an attribute from it.
+	 * @param n
+	 * @return
+	 */
+	private def attr(n) {
+		new Attribute(desc: desc(n), name: n.@name.text())
+	}
 
-    /**
-     * Given an element creates an Element out of it by collecting all its attributes and child elements.
-     *
-     * @param n
-     * @return
-     */
-    private def elmt(n) {
-        def name = n.@ref.text()
-        if(name) {
-            name = name.split(':')[1]
-            n = findNode(n,name)
-        } else {
-           name = n.@name.text()
-        }
-        if(elementNameToElement.containsKey(name)) {
-            return elementNameToElement.get(name)
-        }
-        attrElmts.add(name)
-        def e = new Element()
-        e.name = n.@name.text()
-        e.desc = desc(n)
-        e.childElmts = elements(n)
-        e.attrs = attrs(n)
-        e.attrs.addAll(attrgrps(n))
-        e.attrs*.elmt = e
-        e.childElmts.values()*.each { it.parentElmts.put(e.name,e) }
+	/**
+	 * Given an element creates an Element out of it by collecting all its attributes and child elements.
+	 *
+	 * @param n
+	 * @return
+	 */
+	private def elmt(n) {
+		def name = n.@ref.text()
+		if(name) {
+			name = name.split(':')[1]
+			n = findNode(n,name)
+		} else {
+		   name = n.@name.text()
+		}
+		if(elementNameToElement.containsKey(name)) {
+			return elementNameToElement.get(name)
+		}
+		attrElmts.add(name)
+		def e = new Element()
+		e.name = n.@name.text()
+		e.desc = desc(n)
+		e.childElmts = elements(n)
+		e.attrs = attrs(n)
+		e.attrs.addAll(attrgrps(n))
+		e.attrs*.elmt = e
+		e.childElmts.values()*.each { it.parentElmts.put(e.name,e) }
 
-        def subGrpName = n.@substitutionGroup.text()
-        if(subGrpName) {
-            def subGrp = elmt(findNode(n,subGrpName.split(":")[1]))
-            subGrp.subGrps.add(e)
-        }
+		def subGrpName = n.@substitutionGroup.text()
+		if(subGrpName) {
+			def subGrp = elmt(findNode(n,subGrpName.split(":")[1]))
+			subGrp.subGrps.add(e)
+		}
 
-        elementNameToElement.put(name,e)
-        e
-    }
+		elementNameToElement.put(name,e)
+		e
+	}
 }

+ 163 - 163
config/src/test/groovy/org/springframework/security/config/doc/XsdDocumentedTests.groovy

@@ -29,167 +29,167 @@ import spock.lang.*
  */
 class XsdDocumentedTests extends Specification {
 
-    def ignoredIds = ['nsa-any-user-service','nsa-any-user-service-parents','nsa-authentication','nsa-websocket-security','nsa-ldap','nsa-method-security','nsa-web']
-    @Shared def reference = new File('../docs/manual/src/docs/asciidoc/index.adoc')
-
-    @Shared File schema31xDocument = new File('src/main/resources/org/springframework/security/config/spring-security-3.1.xsd')
-    @Shared File schemaDocument = new File('src/main/resources/org/springframework/security/config/spring-security-4.0.xsd')
-    @Shared Map<String,Element> elementNameToElement
-    @Shared GPathResult schemaRootElement
-
-    def setupSpec() {
-        schemaRootElement = new XmlSlurper().parse(schemaDocument)
-        elementNameToElement = new SpringSecurityXsdParser(rootElement: schemaRootElement).parse()
-    }
-
-    def cleanupSpec() {
-        reference = null
-        schema31xDocument = null
-        schemaDocument = null
-        elementNameToElement = null
-        schemaRootElement = null
-    }
-
-    def 'SEC-2139: named-security-filter are all defined and ordered properly'() {
-        setup:
-            def expectedFilters = (EnumSet.allOf(SecurityFilters) as List).sort { it.order }
-        when:
-            def nsf = schemaRootElement.simpleType.find { it.@name == 'named-security-filter' }
-            def nsfValues = nsf.children().children().collect { c ->
-                Enum.valueOf(SecurityFilters, c.@value.toString())
-            }
-        then:
-            expectedFilters == nsfValues
-    }
-
-    def 'SEC-2139: 3.1.x named-security-filter are all defined and ordered properly'() {
-        setup:
-            def expectedFilters = ["FIRST", "CHANNEL_FILTER", "SECURITY_CONTEXT_FILTER", "CONCURRENT_SESSION_FILTER", "LOGOUT_FILTER", "X509_FILTER",
-                "PRE_AUTH_FILTER", "CAS_FILTER", "FORM_LOGIN_FILTER", "OPENID_FILTER", "LOGIN_PAGE_FILTER", "DIGEST_AUTH_FILTER","BASIC_AUTH_FILTER",
-                "REQUEST_CACHE_FILTER", "SERVLET_API_SUPPORT_FILTER", "JAAS_API_SUPPORT_FILTER", "REMEMBER_ME_FILTER", "ANONYMOUS_FILTER",
-                "SESSION_MANAGEMENT_FILTER", "EXCEPTION_TRANSLATION_FILTER", "FILTER_SECURITY_INTERCEPTOR", "SWITCH_USER_FILTER", "LAST"].collect {
-                Enum.valueOf(SecurityFilters, it)
-            }
-            def schema31xRootElement = new XmlSlurper().parse(schema31xDocument)
-        when:
-            def nsf = schema31xRootElement.simpleType.find { it.@name == 'named-security-filter' }
-            def nsfValues = nsf.children().children().collect { c ->
-                Enum.valueOf(SecurityFilters, c.@value.toString())
-            }
-        then:
-            expectedFilters == nsfValues
-    }
-
-    /**
-     * This will check to ensure that the expected number of xsd documents are found to ensure that we are validating
-     * against the current xsd document. If this test fails, all that is needed is to update the schemaDocument
-     * and the expected size for this test.
-     * @return
-     */
-    def 'the latest schema is being validated'() {
-        when: 'all the schemas are found'
-        def schemas = schemaDocument.getParentFile().list().findAll { it.endsWith('.xsd') }
-        then: 'the count is equal to 8, if not then schemaDocument needs updated'
-        schemas.size() == 9
-    }
-
-    /**
-     * This uses a naming convention for the ids of the appendix to ensure that the entire appendix is documented.
-     * The naming convention for the ids is documented in {@link Element#getIds()}.
-     * @return
-     */
-    def 'the entire schema is included in the appendix documentation'() {
-        setup: 'get all the documented ids and the expected ids'
-            def documentedIds = []
-            reference.eachLine { line ->
-                if(line.matches("\\[\\[(nsa-.*)\\]\\]")) {
-                    documentedIds.add(line.substring(2,line.length() - 2))
-                }
-            }
-        when: 'the schema is compared to the appendix documentation'
-            def expectedIds = [] as Set
-            elementNameToElement*.value*.ids*.each { expectedIds.addAll it }
-            documentedIds.removeAll ignoredIds
-            expectedIds.removeAll ignoredIds
-            def undocumentedIds = (expectedIds - documentedIds)
-            def shouldNotBeDocumented = (documentedIds - expectedIds)
-        then: 'all the elements and attributes are documented'
-            shouldNotBeDocumented.empty
-            undocumentedIds.empty
-    }
-
-    /**
-     * This test ensures that any element that has children or parents contains a section that has links pointing to that
-     * documentation.
-     * @return
-     */
-    def 'validate parents and children are linked in the appendix documentation'() {
-        when: "get all the links for each element's children and parents"
-            def docAttrNameToChildren = [:]
-            def docAttrNameToParents = [:]
-
-            def currentDocAttrNameToElmt
-            def docAttrName
-
-            reference.eachLine { line ->
-                if(line.matches('^\\[\\[.*\\]\\]$')) {
-                    def id = line.substring(2,line.length() - 2)
-                    if(id.endsWith("-children")) {
-                        docAttrName = id.substring(0,id.length() - 9)
-                        currentDocAttrNameToElmt = docAttrNameToChildren
-                    } else if(id.endsWith("-parents")) {
-                        docAttrName = id.substring(0,id.length() - 8)
-                        currentDocAttrNameToElmt = docAttrNameToParents
-                    } else if(docAttrName && !id.startsWith(docAttrName)) {
-                        currentDocAttrNameToElmt = null
-                        docAttrName = null
-                    }
-                }
-
-                if(docAttrName) {
-                    def expression = '^\\* <<(nsa-.*),.*>>$'
-                    if(line.matches(expression)) {
-                        String elmtId = line.replaceAll(expression, '$1')
-                        currentDocAttrNameToElmt.get(docAttrName, []).add(elmtId)
-                    }
-                }
-            }
-
-            def schemaAttrNameToParents = [:]
-            def schemaAttrNameToChildren = [:]
-            elementNameToElement.each { entry ->
-                def key = 'nsa-'+entry.key
-                if(ignoredIds.contains(key)) {
-                    return
-                }
-                def parentIds = entry.value.allParentElmts.values()*.id.findAll { !ignoredIds.contains(it) }.sort()
-                if(parentIds) {
-                    schemaAttrNameToParents.put(key,parentIds)
-                }
-                def childIds = entry.value.allChildElmts.values()*.id.findAll { !ignoredIds.contains(it) }.sort()
-                if(childIds) {
-                    schemaAttrNameToChildren.put(key,childIds)
-                }
-            }
-        then: "the expected parents and children are all documented"
-            schemaAttrNameToChildren.sort() == docAttrNameToChildren.sort()
-            schemaAttrNameToParents.sort() == docAttrNameToParents.sort()
-    }
-
-    /**
-     * This test checks each xsd element and ensures there is documentation for it.
-     * @return
-     */
-    def 'entire xsd is documented'() {
-        when: "validate that the entire xsd contains documentation"
-        def notDocElmtIds = elementNameToElement.values().findAll {
-            !it.desc.text() && !ignoredIds.contains(it.id)
-        }*.id.sort().join("\n")
-        def notDocAttrIds = elementNameToElement.values()*.attrs.flatten().findAll {
-            !it.desc.text() && !ignoredIds.contains(it.id)
-        }*.id.sort().join("\n")
-        then: "all the elements and attributes have some documentation"
-        !notDocElmtIds
-        !notDocAttrIds
-    }
+	def ignoredIds = ['nsa-any-user-service','nsa-any-user-service-parents','nsa-authentication','nsa-websocket-security','nsa-ldap','nsa-method-security','nsa-web']
+	@Shared def reference = new File('../docs/manual/src/docs/asciidoc/index.adoc')
+
+	@Shared File schema31xDocument = new File('src/main/resources/org/springframework/security/config/spring-security-3.1.xsd')
+	@Shared File schemaDocument = new File('src/main/resources/org/springframework/security/config/spring-security-4.0.xsd')
+	@Shared Map<String,Element> elementNameToElement
+	@Shared GPathResult schemaRootElement
+
+	def setupSpec() {
+		schemaRootElement = new XmlSlurper().parse(schemaDocument)
+		elementNameToElement = new SpringSecurityXsdParser(rootElement: schemaRootElement).parse()
+	}
+
+	def cleanupSpec() {
+		reference = null
+		schema31xDocument = null
+		schemaDocument = null
+		elementNameToElement = null
+		schemaRootElement = null
+	}
+
+	def 'SEC-2139: named-security-filter are all defined and ordered properly'() {
+		setup:
+			def expectedFilters = (EnumSet.allOf(SecurityFilters) as List).sort { it.order }
+		when:
+			def nsf = schemaRootElement.simpleType.find { it.@name == 'named-security-filter' }
+			def nsfValues = nsf.children().children().collect { c ->
+				Enum.valueOf(SecurityFilters, c.@value.toString())
+			}
+		then:
+			expectedFilters == nsfValues
+	}
+
+	def 'SEC-2139: 3.1.x named-security-filter are all defined and ordered properly'() {
+		setup:
+			def expectedFilters = ["FIRST", "CHANNEL_FILTER", "SECURITY_CONTEXT_FILTER", "CONCURRENT_SESSION_FILTER", "LOGOUT_FILTER", "X509_FILTER",
+				"PRE_AUTH_FILTER", "CAS_FILTER", "FORM_LOGIN_FILTER", "OPENID_FILTER", "LOGIN_PAGE_FILTER", "DIGEST_AUTH_FILTER","BASIC_AUTH_FILTER",
+				"REQUEST_CACHE_FILTER", "SERVLET_API_SUPPORT_FILTER", "JAAS_API_SUPPORT_FILTER", "REMEMBER_ME_FILTER", "ANONYMOUS_FILTER",
+				"SESSION_MANAGEMENT_FILTER", "EXCEPTION_TRANSLATION_FILTER", "FILTER_SECURITY_INTERCEPTOR", "SWITCH_USER_FILTER", "LAST"].collect {
+				Enum.valueOf(SecurityFilters, it)
+			}
+			def schema31xRootElement = new XmlSlurper().parse(schema31xDocument)
+		when:
+			def nsf = schema31xRootElement.simpleType.find { it.@name == 'named-security-filter' }
+			def nsfValues = nsf.children().children().collect { c ->
+				Enum.valueOf(SecurityFilters, c.@value.toString())
+			}
+		then:
+			expectedFilters == nsfValues
+	}
+
+	/**
+	 * This will check to ensure that the expected number of xsd documents are found to ensure that we are validating
+	 * against the current xsd document. If this test fails, all that is needed is to update the schemaDocument
+	 * and the expected size for this test.
+	 * @return
+	 */
+	def 'the latest schema is being validated'() {
+		when: 'all the schemas are found'
+		def schemas = schemaDocument.getParentFile().list().findAll { it.endsWith('.xsd') }
+		then: 'the count is equal to 8, if not then schemaDocument needs updated'
+		schemas.size() == 9
+	}
+
+	/**
+	 * This uses a naming convention for the ids of the appendix to ensure that the entire appendix is documented.
+	 * The naming convention for the ids is documented in {@link Element#getIds()}.
+	 * @return
+	 */
+	def 'the entire schema is included in the appendix documentation'() {
+		setup: 'get all the documented ids and the expected ids'
+			def documentedIds = []
+			reference.eachLine { line ->
+				if(line.matches("\\[\\[(nsa-.*)\\]\\]")) {
+					documentedIds.add(line.substring(2,line.length() - 2))
+				}
+			}
+		when: 'the schema is compared to the appendix documentation'
+			def expectedIds = [] as Set
+			elementNameToElement*.value*.ids*.each { expectedIds.addAll it }
+			documentedIds.removeAll ignoredIds
+			expectedIds.removeAll ignoredIds
+			def undocumentedIds = (expectedIds - documentedIds)
+			def shouldNotBeDocumented = (documentedIds - expectedIds)
+		then: 'all the elements and attributes are documented'
+			shouldNotBeDocumented.empty
+			undocumentedIds.empty
+	}
+
+	/**
+	 * This test ensures that any element that has children or parents contains a section that has links pointing to that
+	 * documentation.
+	 * @return
+	 */
+	def 'validate parents and children are linked in the appendix documentation'() {
+		when: "get all the links for each element's children and parents"
+			def docAttrNameToChildren = [:]
+			def docAttrNameToParents = [:]
+
+			def currentDocAttrNameToElmt
+			def docAttrName
+
+			reference.eachLine { line ->
+				if(line.matches('^\\[\\[.*\\]\\]$')) {
+					def id = line.substring(2,line.length() - 2)
+					if(id.endsWith("-children")) {
+						docAttrName = id.substring(0,id.length() - 9)
+						currentDocAttrNameToElmt = docAttrNameToChildren
+					} else if(id.endsWith("-parents")) {
+						docAttrName = id.substring(0,id.length() - 8)
+						currentDocAttrNameToElmt = docAttrNameToParents
+					} else if(docAttrName && !id.startsWith(docAttrName)) {
+						currentDocAttrNameToElmt = null
+						docAttrName = null
+					}
+				}
+
+				if(docAttrName) {
+					def expression = '^\\* <<(nsa-.*),.*>>$'
+					if(line.matches(expression)) {
+						String elmtId = line.replaceAll(expression, '$1')
+						currentDocAttrNameToElmt.get(docAttrName, []).add(elmtId)
+					}
+				}
+			}
+
+			def schemaAttrNameToParents = [:]
+			def schemaAttrNameToChildren = [:]
+			elementNameToElement.each { entry ->
+				def key = 'nsa-'+entry.key
+				if(ignoredIds.contains(key)) {
+					return
+				}
+				def parentIds = entry.value.allParentElmts.values()*.id.findAll { !ignoredIds.contains(it) }.sort()
+				if(parentIds) {
+					schemaAttrNameToParents.put(key,parentIds)
+				}
+				def childIds = entry.value.allChildElmts.values()*.id.findAll { !ignoredIds.contains(it) }.sort()
+				if(childIds) {
+					schemaAttrNameToChildren.put(key,childIds)
+				}
+			}
+		then: "the expected parents and children are all documented"
+			schemaAttrNameToChildren.sort() == docAttrNameToChildren.sort()
+			schemaAttrNameToParents.sort() == docAttrNameToParents.sort()
+	}
+
+	/**
+	 * This test checks each xsd element and ensures there is documentation for it.
+	 * @return
+	 */
+	def 'entire xsd is documented'() {
+		when: "validate that the entire xsd contains documentation"
+		def notDocElmtIds = elementNameToElement.values().findAll {
+			!it.desc.text() && !ignoredIds.contains(it.id)
+		}*.id.sort().join("\n")
+		def notDocAttrIds = elementNameToElement.values()*.attrs.flatten().findAll {
+			!it.desc.text() && !ignoredIds.contains(it.id)
+		}*.id.sort().join("\n")
+		then: "all the elements and attributes have some documentation"
+		!notDocElmtIds
+		!notDocAttrIds
+	}
 }

+ 39 - 39
config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy

@@ -28,55 +28,55 @@ import javax.servlet.http.HttpServletRequest
  *
  */
 abstract class AbstractHttpConfigTests extends AbstractXmlConfigTests {
-    final int AUTO_CONFIG_FILTERS = 14;
+	final int AUTO_CONFIG_FILTERS = 14;
 
-    def httpAutoConfig(Closure c) {
-        xml.http(['auto-config': 'true', 'use-expressions':false], c)
-    }
+	def httpAutoConfig(Closure c) {
+		xml.http(['auto-config': 'true', 'use-expressions':false], c)
+	}
 
-    def httpAutoConfig(String matcher, Closure c) {
-        xml.http(['auto-config': 'true', 'use-expressions':false, 'request-matcher': matcher], c)
-    }
+	def httpAutoConfig(String matcher, Closure c) {
+		xml.http(['auto-config': 'true', 'use-expressions':false, 'request-matcher': matcher], c)
+	}
 
-    def interceptUrl(String path, String authz) {
-        xml.'intercept-url'(pattern: path, access: authz)
-    }
+	def interceptUrl(String path, String authz) {
+		xml.'intercept-url'(pattern: path, access: authz)
+	}
 
-    def interceptUrl(String path, String httpMethod, String authz) {
-        xml.'intercept-url'(pattern: path, method: httpMethod, access: authz)
-    }
+	def interceptUrl(String path, String httpMethod, String authz) {
+		xml.'intercept-url'(pattern: path, method: httpMethod, access: authz)
+	}
 
-    Filter getFilter(Class type) {
-        List filters = getFilters("/any");
+	Filter getFilter(Class type) {
+		List filters = getFilters("/any");
 
-        for (f in filters) {
-            if (f.class.isAssignableFrom(type)) {
-                return f;
-            }
-        }
+		for (f in filters) {
+			if (f.class.isAssignableFrom(type)) {
+				return f;
+			}
+		}
 
-        return null;
-    }
+		return null;
+	}
 
-    List getFilters(String url) {
-        springSecurityFilterChain.getFilters(url)
-    }
+	List getFilters(String url) {
+		springSecurityFilterChain.getFilters(url)
+	}
 
-    Filter getSpringSecurityFilterChain() {
-        appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
-    }
+	Filter getSpringSecurityFilterChain() {
+		appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
+	}
 
-    FilterInvocation createFilterinvocation(String path, String method) {
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        request.setMethod(method);
-        request.setRequestURI(null);
-        request.setServletPath(path);
+	FilterInvocation createFilterinvocation(String path, String method) {
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		request.setMethod(method);
+		request.setRequestURI(null);
+		request.setServletPath(path);
 
-        return new FilterInvocation(request, new MockHttpServletResponse(), new MockFilterChain());
-    }
+		return new FilterInvocation(request, new MockHttpServletResponse(), new MockFilterChain());
+	}
 
-    def basicLogin(HttpServletRequest request, String username="user",String password="password") {
-        def credentials = username + ":" + password
-        request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
-    }
+	def basicLogin(HttpServletRequest request, String username="user",String password="password") {
+		def credentials = username + ":" + password
+		request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
+	}
 }

+ 30 - 30
config/src/test/groovy/org/springframework/security/config/http/AccessDeniedConfigTests.groovy

@@ -10,38 +10,38 @@ import org.springframework.security.web.access.ExceptionTranslationFilter
  * @author Luke Taylor
  */
 class AccessDeniedConfigTests extends AbstractHttpConfigTests {
-    def invalidAccessDeniedUrlIsDetected() {
-        when:
-        httpAutoConfig() {
-            'access-denied-handler'('error-page':'noLeadingSlash')
-        }
-        createAppContext();
-        then:
-        thrown(BeanCreationException)
-    }
+	def invalidAccessDeniedUrlIsDetected() {
+		when:
+		httpAutoConfig() {
+			'access-denied-handler'('error-page':'noLeadingSlash')
+		}
+		createAppContext();
+		then:
+		thrown(BeanCreationException)
+	}
 
-    def accessDeniedHandlerIsSetCorectly() {
-        httpAutoConfig() {
-            'access-denied-handler'(ref: 'adh')
-        }
-        bean('adh', AccessDeniedHandlerImpl)
-        createAppContext();
+	def accessDeniedHandlerIsSetCorectly() {
+		httpAutoConfig() {
+			'access-denied-handler'(ref: 'adh')
+		}
+		bean('adh', AccessDeniedHandlerImpl)
+		createAppContext();
 
-        def filter = getFilter(ExceptionTranslationFilter.class);
-        def adh = appContext.getBean("adh");
+		def filter = getFilter(ExceptionTranslationFilter.class);
+		def adh = appContext.getBean("adh");
 
-        expect:
-        filter.accessDeniedHandler == adh
-    }
+		expect:
+		filter.accessDeniedHandler == adh
+	}
 
-    def void accessDeniedHandlerPageAndRefAreMutuallyExclusive() {
-        when:
-        httpAutoConfig {
-            'access-denied-handler'('error-page': '/go-away', ref: 'adh')
-        }
-        createAppContext();
-        bean('adh', AccessDeniedHandlerImpl)
-        then:
-        thrown(BeanDefinitionParsingException)
-    }
+	def void accessDeniedHandlerPageAndRefAreMutuallyExclusive() {
+		when:
+		httpAutoConfig {
+			'access-denied-handler'('error-page': '/go-away', ref: 'adh')
+		}
+		createAppContext();
+		bean('adh', AccessDeniedHandlerImpl)
+		then:
+		thrown(BeanDefinitionParsingException)
+	}
 }

+ 282 - 282
config/src/test/groovy/org/springframework/security/config/http/CsrfConfigTests.groovy

@@ -43,303 +43,303 @@ import spock.lang.Unroll
  * @author Rob Winch
  */
 class CsrfConfigTests extends AbstractHttpConfigTests {
-    MockHttpServletRequest request = new MockHttpServletRequest()
-    MockHttpServletResponse response = new MockHttpServletResponse()
-    MockFilterChain chain = new MockFilterChain()
+	MockHttpServletRequest request = new MockHttpServletRequest()
+	MockHttpServletResponse response = new MockHttpServletResponse()
+	MockFilterChain chain = new MockFilterChain()
 
-    @Unroll
-    def 'csrf is enabled by default'() {
-        setup:
-        httpAutoConfig {
-        }
-        createAppContext()
-        when:
-        request.method = httpMethod
-        springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-        response.status == httpStatus
-        where:
-        httpMethod | httpStatus
-        'POST'     | HttpServletResponse.SC_FORBIDDEN
-        'PUT'      | HttpServletResponse.SC_FORBIDDEN
-        'PATCH'    | HttpServletResponse.SC_FORBIDDEN
-        'DELETE'   | HttpServletResponse.SC_FORBIDDEN
-        'INVALID'  | HttpServletResponse.SC_FORBIDDEN
-        'GET'      | HttpServletResponse.SC_OK
-        'HEAD'     | HttpServletResponse.SC_OK
-        'TRACE'    | HttpServletResponse.SC_OK
-        'OPTIONS'  | HttpServletResponse.SC_OK
-    }
+	@Unroll
+	def 'csrf is enabled by default'() {
+		setup:
+		httpAutoConfig {
+		}
+		createAppContext()
+		when:
+		request.method = httpMethod
+		springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+		response.status == httpStatus
+		where:
+		httpMethod | httpStatus
+		'POST'	   | HttpServletResponse.SC_FORBIDDEN
+		'PUT'	   | HttpServletResponse.SC_FORBIDDEN
+		'PATCH'	   | HttpServletResponse.SC_FORBIDDEN
+		'DELETE'   | HttpServletResponse.SC_FORBIDDEN
+		'INVALID'  | HttpServletResponse.SC_FORBIDDEN
+		'GET'	   | HttpServletResponse.SC_OK
+		'HEAD'	   | HttpServletResponse.SC_OK
+		'TRACE'	   | HttpServletResponse.SC_OK
+		'OPTIONS'  | HttpServletResponse.SC_OK
+	}
 
-    def 'csrf disabled'() {
-        when:
-            httpAutoConfig {
-                csrf(disabled:true)
-            }
-            createAppContext()
-        then:
-            !getFilter(CsrfFilter)
-    }
+	def 'csrf disabled'() {
+		when:
+			httpAutoConfig {
+				csrf(disabled:true)
+			}
+			createAppContext()
+		then:
+			!getFilter(CsrfFilter)
+	}
 
-    @Unroll
-    def 'csrf defaults'() {
-        setup:
-            httpAutoConfig {
-                'csrf'()
-            }
-            createAppContext()
-        when:
-            request.method = httpMethod
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == httpStatus
-        where:
-            httpMethod | httpStatus
-            'POST'     | HttpServletResponse.SC_FORBIDDEN
-            'PUT'      | HttpServletResponse.SC_FORBIDDEN
-            'PATCH'    | HttpServletResponse.SC_FORBIDDEN
-            'DELETE'   | HttpServletResponse.SC_FORBIDDEN
-            'INVALID'  | HttpServletResponse.SC_FORBIDDEN
-            'GET'      | HttpServletResponse.SC_OK
-            'HEAD'     | HttpServletResponse.SC_OK
-            'TRACE'    | HttpServletResponse.SC_OK
-            'OPTIONS'  | HttpServletResponse.SC_OK
-    }
+	@Unroll
+	def 'csrf defaults'() {
+		setup:
+			httpAutoConfig {
+				'csrf'()
+			}
+			createAppContext()
+		when:
+			request.method = httpMethod
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == httpStatus
+		where:
+			httpMethod | httpStatus
+			'POST'	   | HttpServletResponse.SC_FORBIDDEN
+			'PUT'	   | HttpServletResponse.SC_FORBIDDEN
+			'PATCH'	   | HttpServletResponse.SC_FORBIDDEN
+			'DELETE'   | HttpServletResponse.SC_FORBIDDEN
+			'INVALID'  | HttpServletResponse.SC_FORBIDDEN
+			'GET'	   | HttpServletResponse.SC_OK
+			'HEAD'	   | HttpServletResponse.SC_OK
+			'TRACE'	   | HttpServletResponse.SC_OK
+			'OPTIONS'  | HttpServletResponse.SC_OK
+	}
 
-    def 'csrf default creates CsrfRequestDataValueProcessor'() {
-        when:
-            httpAutoConfig {
-                'csrf'()
-            }
-            createAppContext()
-        then:
-            appContext.getBean("requestDataValueProcessor",RequestDataValueProcessor)
-    }
+	def 'csrf default creates CsrfRequestDataValueProcessor'() {
+		when:
+			httpAutoConfig {
+				'csrf'()
+			}
+			createAppContext()
+		then:
+			appContext.getBean("requestDataValueProcessor",RequestDataValueProcessor)
+	}
 
-    def 'csrf custom AccessDeniedHandler'() {
-        setup:
-            httpAutoConfig {
-                'access-denied-handler'(ref:'adh')
-                'csrf'()
-            }
-            mockBean(AccessDeniedHandler,'adh')
-            createAppContext()
-            AccessDeniedHandler adh = appContext.getBean(AccessDeniedHandler)
-            request.method = "POST"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            verify(adh).handle(any(HttpServletRequest),any(HttpServletResponse),any(AccessDeniedException))
-            response.status == HttpServletResponse.SC_OK // our mock doesn't do anything
-    }
+	def 'csrf custom AccessDeniedHandler'() {
+		setup:
+			httpAutoConfig {
+				'access-denied-handler'(ref:'adh')
+				'csrf'()
+			}
+			mockBean(AccessDeniedHandler,'adh')
+			createAppContext()
+			AccessDeniedHandler adh = appContext.getBean(AccessDeniedHandler)
+			request.method = "POST"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			verify(adh).handle(any(HttpServletRequest),any(HttpServletResponse),any(AccessDeniedException))
+			response.status == HttpServletResponse.SC_OK // our mock doesn't do anything
+	}
 
-    def "csrf disables posts for RequestCache"() {
-        setup:
-            httpAutoConfig {
-                'csrf'('token-repository-ref':'repo')
-                'intercept-url'(pattern:"/**",access:'ROLE_USER')
-            }
-            mockBean(CsrfTokenRepository,'repo')
-            createAppContext()
-            CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
-            CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
-            when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
-            when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
-            request.setParameter(token.parameterName,token.token)
-            request.servletPath = "/some-url"
-            request.requestURI = "/some-url"
-            request.method = "POST"
-        when: "CSRF passes and our session times out"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to the login page"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "http://localhost/login"
-        when: "authenticate successfully"
-            response = new MockHttpServletResponse()
-            request = new MockHttpServletRequest(session: request.session)
-            request.servletPath = "/login"
-            request.setParameter(token.parameterName,token.token)
-            request.setParameter("username","user")
-            request.setParameter("password","password")
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default success because we don't want csrf attempts made prior to authentication to pass"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "/"
-    }
+	def "csrf disables posts for RequestCache"() {
+		setup:
+			httpAutoConfig {
+				'csrf'('token-repository-ref':'repo')
+				'intercept-url'(pattern:"/**",access:'ROLE_USER')
+			}
+			mockBean(CsrfTokenRepository,'repo')
+			createAppContext()
+			CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
+			CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
+			when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
+			when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
+			request.setParameter(token.parameterName,token.token)
+			request.servletPath = "/some-url"
+			request.requestURI = "/some-url"
+			request.method = "POST"
+		when: "CSRF passes and our session times out"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to the login page"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "http://localhost/login"
+		when: "authenticate successfully"
+			response = new MockHttpServletResponse()
+			request = new MockHttpServletRequest(session: request.session)
+			request.servletPath = "/login"
+			request.setParameter(token.parameterName,token.token)
+			request.setParameter("username","user")
+			request.setParameter("password","password")
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default success because we don't want csrf attempts made prior to authentication to pass"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "/"
+	}
 
-    def "csrf enables gets for RequestCache"() {
-        setup:
-            httpAutoConfig {
-                'csrf'('token-repository-ref':'repo')
-                'intercept-url'(pattern:"/**",access:'ROLE_USER')
-            }
-            mockBean(CsrfTokenRepository,'repo')
-            createAppContext()
-            CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
-            CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
-            when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
-        when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
-            request.setParameter(token.parameterName,token.token)
-            request.servletPath = "/some-url"
-            request.requestURI = "/some-url"
-            request.method = "GET"
-        when: "CSRF passes and our session times out"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to the login page"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "http://localhost/login"
-        when: "authenticate successfully"
-            response = new MockHttpServletResponse()
-            request = new MockHttpServletRequest(session: request.session)
-            request.servletPath = "/login"
-            request.setParameter(token.parameterName,token.token)
-            request.setParameter("username","user")
-            request.setParameter("password","password")
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to original URL since it was a GET"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "http://localhost/some-url"
-    }
+	def "csrf enables gets for RequestCache"() {
+		setup:
+			httpAutoConfig {
+				'csrf'('token-repository-ref':'repo')
+				'intercept-url'(pattern:"/**",access:'ROLE_USER')
+			}
+			mockBean(CsrfTokenRepository,'repo')
+			createAppContext()
+			CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
+			CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
+			when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
+		when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
+			request.setParameter(token.parameterName,token.token)
+			request.servletPath = "/some-url"
+			request.requestURI = "/some-url"
+			request.method = "GET"
+		when: "CSRF passes and our session times out"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to the login page"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "http://localhost/login"
+		when: "authenticate successfully"
+			response = new MockHttpServletResponse()
+			request = new MockHttpServletRequest(session: request.session)
+			request.servletPath = "/login"
+			request.setParameter(token.parameterName,token.token)
+			request.setParameter("username","user")
+			request.setParameter("password","password")
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to original URL since it was a GET"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "http://localhost/some-url"
+	}
 
-    def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
-        setup:
-            httpAutoConfig {
-                'csrf'()
-                'session-management'('invalid-session-url': '/error/sessionError')
-            }
-            createAppContext()
-            request.setParameter("_csrf","abc")
-            request.method = "POST"
-        when: "No existing expected CsrfToken (session times out) and a POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to the session timeout page page"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "/error/sessionError"
-        when: "Existing expected CsrfToken and a POST (invalid token provided)"
-            response = new MockHttpServletResponse()
-            request = new MockHttpServletRequest(session: request.session, method:'POST')
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "Access Denied occurs"
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
+	def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
+		setup:
+			httpAutoConfig {
+				'csrf'()
+				'session-management'('invalid-session-url': '/error/sessionError')
+			}
+			createAppContext()
+			request.setParameter("_csrf","abc")
+			request.method = "POST"
+		when: "No existing expected CsrfToken (session times out) and a POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to the session timeout page page"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "/error/sessionError"
+		when: "Existing expected CsrfToken and a POST (invalid token provided)"
+			response = new MockHttpServletResponse()
+			request = new MockHttpServletRequest(session: request.session, method:'POST')
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "Access Denied occurs"
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
 
-    def "csrf requireCsrfProtectionMatcher"() {
-        setup:
-            httpAutoConfig {
-                'csrf'('request-matcher-ref':'matcher')
-            }
-            mockBean(RequestMatcher,'matcher')
-            createAppContext()
-            request.method = 'POST'
-            RequestMatcher matcher = appContext.getBean("matcher",RequestMatcher)
-        when:
-            when(matcher.matches(any(HttpServletRequest))).thenReturn(false)
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-        when:
-            when(matcher.matches(any(HttpServletRequest))).thenReturn(true)
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
+	def "csrf requireCsrfProtectionMatcher"() {
+		setup:
+			httpAutoConfig {
+				'csrf'('request-matcher-ref':'matcher')
+			}
+			mockBean(RequestMatcher,'matcher')
+			createAppContext()
+			request.method = 'POST'
+			RequestMatcher matcher = appContext.getBean("matcher",RequestMatcher)
+		when:
+			when(matcher.matches(any(HttpServletRequest))).thenReturn(false)
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+		when:
+			when(matcher.matches(any(HttpServletRequest))).thenReturn(true)
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
 
-    def "csrf csrfTokenRepository"() {
-        setup:
-            httpAutoConfig {
-                'csrf'('token-repository-ref':'repo')
-            }
-            mockBean(CsrfTokenRepository,'repo')
-            createAppContext()
-            CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
-            CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
-            when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
-            request.setParameter(token.parameterName,token.token)
-            request.method = "POST"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-        when:
-            request.setParameter(token.parameterName,token.token+"INVALID")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
+	def "csrf csrfTokenRepository"() {
+		setup:
+			httpAutoConfig {
+				'csrf'('token-repository-ref':'repo')
+			}
+			mockBean(CsrfTokenRepository,'repo')
+			createAppContext()
+			CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
+			CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
+			when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
+			request.setParameter(token.parameterName,token.token)
+			request.method = "POST"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+		when:
+			request.setParameter(token.parameterName,token.token+"INVALID")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
 
-    def "csrf clears on login"() {
-        setup:
-            httpAutoConfig {
-                'csrf'('token-repository-ref':'repo')
-            }
-            mockBean(CsrfTokenRepository,'repo')
-            createAppContext()
-            CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
-            CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
-            when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
-            when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
-            request.setParameter(token.parameterName,token.token)
-            request.method = "POST"
-            request.setParameter("username","user")
-            request.setParameter("password","password")
-            request.servletPath = "/login"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            verify(repo, atLeastOnce()).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
-    }
+	def "csrf clears on login"() {
+		setup:
+			httpAutoConfig {
+				'csrf'('token-repository-ref':'repo')
+			}
+			mockBean(CsrfTokenRepository,'repo')
+			createAppContext()
+			CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
+			CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
+			when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
+			when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
+			request.setParameter(token.parameterName,token.token)
+			request.method = "POST"
+			request.setParameter("username","user")
+			request.setParameter("password","password")
+			request.servletPath = "/login"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			verify(repo, atLeastOnce()).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
+	}
 
-    def "csrf clears on logout"() {
-        setup:
-            httpAutoConfig {
-                'csrf'('token-repository-ref':'repo')
-            }
-            mockBean(CsrfTokenRepository,'repo')
-            createAppContext()
-            CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
-            CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
-            when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
-            request.setParameter(token.parameterName,token.token)
-            request.method = "POST"
-            request.servletPath = "/logout"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            verify(repo).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
-    }
+	def "csrf clears on logout"() {
+		setup:
+			httpAutoConfig {
+				'csrf'('token-repository-ref':'repo')
+			}
+			mockBean(CsrfTokenRepository,'repo')
+			createAppContext()
+			CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
+			CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
+			when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
+			request.setParameter(token.parameterName,token.token)
+			request.method = "POST"
+			request.servletPath = "/logout"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			verify(repo).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
+	}
 
-        def "SEC-2495: csrf disables logout on GET"() {
-            setup:
-                httpAutoConfig {
-                    'csrf'()
-                }
-                createAppContext()
-                login()
-                request.method = "GET"
-                request.requestURI = "/logout"
-            when:
-                springSecurityFilterChain.doFilter(request,response,chain)
-            then:
-                getAuthentication(request) != null
-        }
+		def "SEC-2495: csrf disables logout on GET"() {
+			setup:
+				httpAutoConfig {
+					'csrf'()
+				}
+				createAppContext()
+				login()
+				request.method = "GET"
+				request.requestURI = "/logout"
+			when:
+				springSecurityFilterChain.doFilter(request,response,chain)
+			then:
+				getAuthentication(request) != null
+		}
 
 
-        def login(String username="user", String role="ROLE_USER") {
-            login(new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role)))
-        }
+		def login(String username="user", String role="ROLE_USER") {
+			login(new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role)))
+		}
 
-        def login(Authentication auth) {
-            HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
-            HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
-            repo.loadContext(requestResponseHolder)
-            repo.saveContext(new SecurityContextImpl(authentication:auth), requestResponseHolder.request, requestResponseHolder.response)
-        }
+		def login(Authentication auth) {
+			HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
+			HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
+			repo.loadContext(requestResponseHolder)
+			repo.saveContext(new SecurityContextImpl(authentication:auth), requestResponseHolder.request, requestResponseHolder.response)
+		}
 
-        def getAuthentication(HttpServletRequest request) {
-            HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
-            HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
-            repo.loadContext(requestResponseHolder)?.authentication
-        }
+		def getAuthentication(HttpServletRequest request) {
+			HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
+			HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
+			repo.loadContext(requestResponseHolder)?.authentication
+		}
 }

+ 75 - 75
config/src/test/groovy/org/springframework/security/config/http/FormLoginBeanDefinitionParserTests.groovy

@@ -10,104 +10,104 @@ import org.springframework.mock.web.MockHttpServletResponse
  */
 class FormLoginBeanDefinitionParserTests extends AbstractHttpConfigTests {
 
-    def 'form-login default login page'() {
-        setup:
-            MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            MockFilterChain chain = new MockFilterChain()
-            httpAutoConfig {
-                csrf(disabled:true)
-            }
-            createAppContext()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+	def 'form-login default login page'() {
+		setup:
+			MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			MockFilterChain chain = new MockFilterChain()
+			httpAutoConfig {
+				csrf(disabled:true)
+			}
+			createAppContext()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form></body></html>"""
-    }
+	}
 
-    def 'form-login default login page custom attributes'() {
-        setup:
-            MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            MockFilterChain chain = new MockFilterChain()
-            httpAutoConfig {
-                'form-login'('login-processing-url':'/login_custom','username-parameter':'custom_user','password-parameter':'custom_password')
-                csrf(disabled:true)
-            }
-            createAppContext()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.custom_user.focus();'>
+	def 'form-login default login page custom attributes'() {
+		setup:
+			MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			MockFilterChain chain = new MockFilterChain()
+			httpAutoConfig {
+				'form-login'('login-processing-url':'/login_custom','username-parameter':'custom_user','password-parameter':'custom_password')
+				csrf(disabled:true)
+			}
+			createAppContext()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.custom_user.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login_custom' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='custom_user' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='custom_password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>User:</td><td><input type='text' name='custom_user' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='custom_password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form></body></html>"""
-    }
+	}
 
-    def 'openid-login default login page'() {
-        setup:
-            MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            MockFilterChain chain = new MockFilterChain()
-            httpAutoConfig {
-                'openid-login'()
-                csrf(disabled:true)
-            }
-            createAppContext()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+	def 'openid-login default login page'() {
+		setup:
+			MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			MockFilterChain chain = new MockFilterChain()
+			httpAutoConfig {
+				'openid-login'()
+				csrf(disabled:true)
+			}
+			createAppContext()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
  <table>
-    <tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form></body></html>"""
-    }
+	}
 
-    def 'openid-login default login page custom attributes'() {
-        setup:
-            MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            MockFilterChain chain = new MockFilterChain()
-            httpAutoConfig {
-                'openid-login'('login-processing-url':'/login_custom')
-                csrf(disabled:true)
-            }
-            createAppContext()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+	def 'openid-login default login page custom attributes'() {
+		setup:
+			MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			MockFilterChain chain = new MockFilterChain()
+			httpAutoConfig {
+				'openid-login'('login-processing-url':'/login_custom')
+				csrf(disabled:true)
+			}
+			createAppContext()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login_custom' method='POST'>
  <table>
-    <tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form></body></html>"""
-    }
+	}
 }

+ 89 - 89
config/src/test/groovy/org/springframework/security/config/http/FormLoginConfigTests.groovy

@@ -15,93 +15,93 @@ import org.springframework.util.ReflectionUtils;
  */
 class FormLoginConfigTests extends AbstractHttpConfigTests {
 
-    def formLoginWithNoLoginPageAddsDefaultLoginPageFilter() {
-        httpAutoConfig('ant') {
-            form-login()
-        }
-        createAppContext()
-        filtersMatchExpectedAutoConfigList();
-    }
-
-    def 'Form login alwaysUseDefaultTarget sets correct property'() {
-        xml.http {
-            'form-login'('default-target-url':'/default', 'always-use-default-target': 'true')
-        }
-        createAppContext()
-        def filter = getFilter(UsernamePasswordAuthenticationFilter.class);
-
-        expect:
-        FieldUtils.getFieldValue(filter, 'successHandler.defaultTargetUrl') == '/default';
-        FieldUtils.getFieldValue(filter, 'successHandler.alwaysUseDefaultTargetUrl');
-    }
-
-    def 'form-login attributes support SpEL'() {
-        setup:
-        def spelUrl = '#{T(org.springframework.security.config.http.WebConfigUtilsTest).URL}'
-        def expectedUrl = WebConfigUtilsTest.URL
-        when:
-        xml.http {
-            'form-login'('default-target-url': spelUrl , 'authentication-failure-url': spelUrl, 'login-page': spelUrl)
-        }
-        createAppContext()
-        def unPwdFilter = getFilter(UsernamePasswordAuthenticationFilter)
-        def exTransFilter = getFilter(ExceptionTranslationFilter)
-
-        then:
-        unPwdFilter.successHandler.defaultTargetUrl == expectedUrl
-        unPwdFilter
-        FieldUtils.getFieldValue(unPwdFilter, 'successHandler.defaultTargetUrl') == expectedUrl
-        FieldUtils.getFieldValue(unPwdFilter, 'failureHandler.defaultFailureUrl') == expectedUrl
-        FieldUtils.getFieldValue(exTransFilter, 'authenticationEntryPoint.loginFormUrl') == expectedUrl
-    }
-
-    def invalidLoginPageIsDetected() {
-        when:
-        xml.http {
-            'form-login'('login-page': 'noLeadingSlash')
-        }
-        createAppContext()
-
-        then:
-        BeanCreationException e = thrown();
-    }
-
-    def invalidDefaultTargetUrlIsDetected() {
-        when:
-        xml.http {
-            'form-login'('default-target-url': 'noLeadingSlash')
-        }
-        createAppContext()
-
-        then:
-        BeanCreationException e = thrown();
-    }
-
-    def customSuccessAndFailureHandlersCanBeSetThroughTheNamespace() {
-        xml.http {
-            'form-login'('authentication-success-handler-ref': 'sh', 'authentication-failure-handler-ref':'fh')
-        }
-        bean('sh', SavedRequestAwareAuthenticationSuccessHandler.class.name)
-        bean('fh', SimpleUrlAuthenticationFailureHandler.class.name)
-        createAppContext()
-
-        def apf = getFilter(UsernamePasswordAuthenticationFilter.class);
-
-        expect:
-        FieldUtils.getFieldValue(apf, "successHandler") == appContext.getBean("sh");
-        FieldUtils.getFieldValue(apf, "failureHandler") == appContext.getBean("fh")
-    }
-
-    def usernameAndPasswordParametersCanBeSetThroughNamespace() {
-        xml.http {
-            'form-login'('username-parameter': 'xname', 'password-parameter':'xpass')
-        }
-        createAppContext()
-
-        def apf = getFilter(UsernamePasswordAuthenticationFilter.class);
-
-        expect:
-        apf.usernameParameter == 'xname';
-        apf.passwordParameter == 'xpass'
-    }
+	def formLoginWithNoLoginPageAddsDefaultLoginPageFilter() {
+		httpAutoConfig('ant') {
+			form-login()
+		}
+		createAppContext()
+		filtersMatchExpectedAutoConfigList();
+	}
+
+	def 'Form login alwaysUseDefaultTarget sets correct property'() {
+		xml.http {
+			'form-login'('default-target-url':'/default', 'always-use-default-target': 'true')
+		}
+		createAppContext()
+		def filter = getFilter(UsernamePasswordAuthenticationFilter.class);
+
+		expect:
+		FieldUtils.getFieldValue(filter, 'successHandler.defaultTargetUrl') == '/default';
+		FieldUtils.getFieldValue(filter, 'successHandler.alwaysUseDefaultTargetUrl');
+	}
+
+	def 'form-login attributes support SpEL'() {
+		setup:
+		def spelUrl = '#{T(org.springframework.security.config.http.WebConfigUtilsTest).URL}'
+		def expectedUrl = WebConfigUtilsTest.URL
+		when:
+		xml.http {
+			'form-login'('default-target-url': spelUrl , 'authentication-failure-url': spelUrl, 'login-page': spelUrl)
+		}
+		createAppContext()
+		def unPwdFilter = getFilter(UsernamePasswordAuthenticationFilter)
+		def exTransFilter = getFilter(ExceptionTranslationFilter)
+
+		then:
+		unPwdFilter.successHandler.defaultTargetUrl == expectedUrl
+		unPwdFilter
+		FieldUtils.getFieldValue(unPwdFilter, 'successHandler.defaultTargetUrl') == expectedUrl
+		FieldUtils.getFieldValue(unPwdFilter, 'failureHandler.defaultFailureUrl') == expectedUrl
+		FieldUtils.getFieldValue(exTransFilter, 'authenticationEntryPoint.loginFormUrl') == expectedUrl
+	}
+
+	def invalidLoginPageIsDetected() {
+		when:
+		xml.http {
+			'form-login'('login-page': 'noLeadingSlash')
+		}
+		createAppContext()
+
+		then:
+		BeanCreationException e = thrown();
+	}
+
+	def invalidDefaultTargetUrlIsDetected() {
+		when:
+		xml.http {
+			'form-login'('default-target-url': 'noLeadingSlash')
+		}
+		createAppContext()
+
+		then:
+		BeanCreationException e = thrown();
+	}
+
+	def customSuccessAndFailureHandlersCanBeSetThroughTheNamespace() {
+		xml.http {
+			'form-login'('authentication-success-handler-ref': 'sh', 'authentication-failure-handler-ref':'fh')
+		}
+		bean('sh', SavedRequestAwareAuthenticationSuccessHandler.class.name)
+		bean('fh', SimpleUrlAuthenticationFailureHandler.class.name)
+		createAppContext()
+
+		def apf = getFilter(UsernamePasswordAuthenticationFilter.class);
+
+		expect:
+		FieldUtils.getFieldValue(apf, "successHandler") == appContext.getBean("sh");
+		FieldUtils.getFieldValue(apf, "failureHandler") == appContext.getBean("fh")
+	}
+
+	def usernameAndPasswordParametersCanBeSetThroughNamespace() {
+		xml.http {
+			'form-login'('username-parameter': 'xname', 'password-parameter':'xpass')
+		}
+		createAppContext()
+
+		def apf = getFilter(UsernamePasswordAuthenticationFilter.class);
+
+		expect:
+		apf.usernameParameter == 'xname';
+		apf.passwordParameter == 'xpass'
+	}
 }

+ 15 - 15
config/src/test/groovy/org/springframework/security/config/http/HttpConfigTests.groovy

@@ -43,20 +43,20 @@ import static org.mockito.Mockito.*
  * @author Rob Winch
  */
 class HttpConfigTests extends AbstractHttpConfigTests {
-    MockHttpServletRequest request = new MockHttpServletRequest('GET','/secure')
-    MockHttpServletResponse response = new MockHttpServletResponse()
-    MockFilterChain chain = new MockFilterChain()
+	MockHttpServletRequest request = new MockHttpServletRequest('GET','/secure')
+	MockHttpServletResponse response = new MockHttpServletResponse()
+	MockFilterChain chain = new MockFilterChain()
 
-    def 'http minimal configuration works'() {
-        setup:
-        xml.http() {}
-        createAppContext("""<user-service>
-        <user name="user" password="password" authorities="ROLE_USER" />
-    </user-service>""")
-        when: 'request protected URL'
-        springSecurityFilterChain.doFilter(request,response,chain)
-        then: 'sent to login page'
-        response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-        response.redirectedUrl == 'http://localhost/login'
-    }
+	def 'http minimal configuration works'() {
+		setup:
+		xml.http() {}
+		createAppContext("""<user-service>
+		<user name="user" password="password" authorities="ROLE_USER" />
+	</user-service>""")
+		when: 'request protected URL'
+		springSecurityFilterChain.doFilter(request,response,chain)
+		then: 'sent to login page'
+		response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+		response.redirectedUrl == 'http://localhost/login'
+	}
 }

+ 616 - 616
config/src/test/groovy/org/springframework/security/config/http/HttpHeadersConfigTests.groovy

@@ -27,620 +27,620 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher
  * @author Rob Winch
  */
 class HttpHeadersConfigTests extends AbstractHttpConfigTests {
-    def defaultHeaders = ['X-Content-Type-Options':'nosniff',
-                                 'X-Frame-Options':'DENY',
-                                 'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
-                                 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
-                                 'Expires' : '0',
-                                 'Pragma':'no-cache',
-                                 'X-XSS-Protection' : '1; mode=block']
-    def 'headers disabled'() {
-        setup:
-            httpAutoConfig {
-                'headers'(disabled:true)
-            }
-            createAppContext()
-
-        when:
-            def hf = getFilter(HeaderWriterFilter)
-        then:
-            !hf
-    }
-
-    def 'headers disabled with child fails'() {
-        when:
-            httpAutoConfig {
-                'headers'(disabled:true) {
-                    'content-type-options'()
-                }
-            }
-            createAppContext()
-        then:
-            thrown(BeanDefinitionParsingException)
-    }
-
-    def 'default headers'() {
-        httpAutoConfig {
-        }
-        createAppContext()
-
-        when:
-            def hf = getFilter(HeaderWriterFilter)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
-        then:
-            assertHeaders(response, defaultHeaders)
-    }
-
-    def 'http headers with empty headers'() {
-        setup:
-            httpAutoConfig {
-                'headers'()
-            }
-            createAppContext()
-        when:
-            def hf = getFilter(HeaderWriterFilter)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
-        then:
-            assertHeaders(response, defaultHeaders)
-    }
-
-    def 'http headers frame-options@policy=SAMEORIGIN with defaults'() {
-        httpAutoConfig {
-            'headers'() {
-                'frame-options'(policy:'SAMEORIGIN')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
-        def expectedHeaders = [:] << defaultHeaders
-        expectedHeaders['X-Frame-Options'] = 'SAMEORIGIN'
-
-        expect:
-        assertHeaders(response, expectedHeaders)
-    }
-
-
-    // --- defaults disabled
-
-    def 'http headers content-type-options'() {
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'content-type-options'()
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-
-        expect:
-        assertHeaders(response, ['X-Content-Type-Options':'nosniff'])
-    }
-
-    def 'http headers frame-options defaults to DENY'() {
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'frame-options'()
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-
-        expect:
-        assertHeaders(response, ['X-Frame-Options':'DENY'])
-    }
-
-    def 'http headers frame-options DENY'() {
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'frame-options'(policy : 'DENY')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-
-        expect:
-        assertHeaders(response, ['X-Frame-Options':'DENY'])
-    }
-
-    def 'http headers frame-options SAMEORIGIN'() {
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'frame-options'(policy : 'SAMEORIGIN')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-
-        expect:
-        assertHeaders(response, ['X-Frame-Options':'SAMEORIGIN'])
-    }
-
-    def 'http headers frame-options ALLOW-FROM no origin reports error'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'frame-options'(policy : 'ALLOW-FROM', strategy : 'static')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-
-        then:
-        BeanDefinitionParsingException e = thrown()
-        e.message.contains "Strategy requires a 'value' to be set." // FIME better error message?
-    }
-
-    def 'http headers frame-options ALLOW-FROM spaces only origin reports error'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'frame-options'(policy : 'ALLOW-FROM', strategy: 'static', value : ' ')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-
-        then:
-        BeanDefinitionParsingException e = thrown()
-        e.message.contains "Strategy requires a 'value' to be set." // FIME better error message?
-    }
-
-    def 'http headers frame-options ALLOW-FROM'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'frame-options'(policy : 'ALLOW-FROM', strategy: 'static', value : 'https://example.com')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-
-        then:
-        assertHeaders(response, ['X-Frame-Options':'ALLOW-FROM https://example.com'])
-    }
-
-    def 'http headers frame-options ALLOW-FROM with whitelist strategy'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'frame-options'(policy : 'ALLOW-FROM', strategy: 'whitelist', value : 'https://example.com')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-
-        def request = new MockHttpServletRequest()
-        request.setParameter("from", "https://example.com");
-        hf.doFilter(request, response, new MockFilterChain())
-
-        then:
-        assertHeaders(response, ['X-Frame-Options':'ALLOW-FROM https://example.com'])
-    }
-
-    def 'http headers header a=b'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'header'(name : 'a', value: 'b')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-
-        then:
-        assertHeaders(response, ['a':'b'])
-    }
-
-    def 'http headers header a=b and c=d'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'header'(name : 'a', value: 'b')
-                'header'(name : 'c', value: 'd')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-
-        then:
-        assertHeaders(response , ['a':'b', 'c':'d'])
-    }
-
-    def 'http headers with ref'() {
-        setup:
-            httpAutoConfig {
-                'headers'('defaults-disabled':true) {
-                    'header'(ref:'headerWriter')
-                }
-            }
-            xml.'b:bean'(id: 'headerWriter', 'class': StaticHeadersWriter.name) {
-                'b:constructor-arg'(value:'abc') {}
-                'b:constructor-arg'(value:'def') {}
-            }
-            createAppContext()
-        when:
-            def hf = getFilter(HeaderWriterFilter)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-        then:
-             assertHeaders(response, ['abc':'def'])
-    }
-
-    def 'http headers header no name produces error'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'header'(value: 'b')
-            }
-        }
-        createAppContext()
-
-        then:
-        thrown(BeanCreationException)
-    }
-
-    def 'http headers header no value produces error'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'header'(name: 'a')
-            }
-        }
-        createAppContext()
-
-        then:
-        thrown(BeanCreationException)
-    }
-
-    def 'http headers xss-protection defaults'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'xss-protection'()
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-
-        then:
-        assertHeaders(response, ['X-XSS-Protection':'1; mode=block'])
-    }
-
-    def 'http headers xss-protection enabled=true'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'xss-protection'(enabled:'true')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-
-        then:
-        assertHeaders(response, ['X-XSS-Protection':'1; mode=block'])
-    }
-
-    def 'http headers xss-protection enabled=false'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'xss-protection'(enabled:'false')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-
-        then:
-        assertHeaders(response, ['X-XSS-Protection':'0'])
-    }
-
-    def 'http headers xss-protection enabled=false and block=true produces error'() {
-        when:
-        httpAutoConfig {
-            'headers'('defaults-disabled':true) {
-                'xss-protection'(enabled:'false', block:'true')
-            }
-        }
-        createAppContext()
-
-        def hf = getFilter(HeaderWriterFilter)
-
-        then:
-        BeanCreationException e = thrown()
-        e.message.contains 'Cannot set block to true with enabled false'
-    }
-
-    def 'http headers cache-control'() {
-        setup:
-            httpAutoConfig {
-                'headers'('defaults-disabled':true) {
-                    'cache-control'()
-                }
-            }
-            createAppContext()
-            def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-        when:
-            springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-        then:
-            assertHeaders(response, ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
-                                     'Expires' : '0',
-                                     'Pragma':'no-cache'])
-    }
-
-    def 'http headers hsts'() {
-        setup:
-            httpAutoConfig {
-                'headers'('defaults-disabled':true) {
-                    'hsts'()
-                }
-            }
-            createAppContext()
-            def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-        when:
-            springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
-        then:
-            assertHeaders(response, ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains'])
-    }
-
-    def 'http headers hsts default only invokes on HttpServletRequest.isSecure = true'() {
-        setup:
-            httpAutoConfig {
-                'headers'('defaults-disabled':true) {
-                    'hsts'()
-                }
-            }
-            createAppContext()
-            def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-        when:
-            springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-        then:
-            response.headerNames.empty
-    }
-
-    def 'http headers hsts custom'() {
-        setup:
-            httpAutoConfig {
-                'headers'('defaults-disabled':true) {
-                    'hsts'('max-age-seconds':'1','include-subdomains':false, 'request-matcher-ref' : 'matcher')
-                }
-            }
-
-            xml.'b:bean'(id: 'matcher', 'class': AnyRequestMatcher.name)
-            createAppContext()
-            def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-        when:
-            springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-        then:
-            assertHeaders(response, ['Strict-Transport-Security': 'max-age=1'])
-    }
-
-    // --- disable single default header ---
-
-    def 'http headers cache-controls@disabled=true'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'cache-control'(disabled:true)
-                }
-            }
-            createAppContext()
-            def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            def expectedHeaders = [:] << defaultHeaders
-            expectedHeaders.remove('Cache-Control')
-            expectedHeaders.remove('Expires')
-            expectedHeaders.remove('Pragma')
-        when:
-            springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
-        then:
-            assertHeaders(response, expectedHeaders)
-    }
-
-    def 'http headers content-type-options@disabled=true'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'content-type-options'(disabled:true)
-                }
-            }
-            createAppContext()
-            def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            def expectedHeaders = [:] << defaultHeaders
-            expectedHeaders.remove('X-Content-Type-Options')
-        when:
-            springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
-        then:
-            assertHeaders(response, expectedHeaders)
-    }
-
-    def 'http headers hsts@disabled=true'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'hsts'(disabled:true)
-                }
-            }
-            createAppContext()
-            def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            def expectedHeaders = [:] << defaultHeaders
-            expectedHeaders.remove('Strict-Transport-Security')
-        when:
-            springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
-        then:
-            assertHeaders(response, expectedHeaders)
-    }
-
-    def 'http headers frame-options@disabled=true'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'frame-options'(disabled:true)
-                }
-            }
-            createAppContext()
-            def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            def expectedHeaders = [:] << defaultHeaders
-            expectedHeaders.remove('X-Frame-Options')
-        when:
-            springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
-        then:
-            assertHeaders(response, expectedHeaders)
-    }
-
-    def 'http headers xss-protection@disabled=true'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'xss-protection'(disabled:true)
-                }
-            }
-            createAppContext()
-            def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            def expectedHeaders = [:] << defaultHeaders
-            expectedHeaders.remove('X-XSS-Protection')
-        when:
-            springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
-        then:
-            assertHeaders(response, expectedHeaders)
-    }
-
-    // --- disable error handling ---
-
-    def 'http headers hsts@disabled=true no include-subdomains'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'hsts'(disabled:true,'include-subdomains':true)
-                }
-            }
-        when:
-            createAppContext()
-        then:
-            BeanDefinitionParsingException expected = thrown()
-            expected.message.contains 'include-subdomains'
-    }
-
-    def 'http headers hsts@disabled=true no max-age'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'hsts'(disabled:true,'max-age-seconds':123)
-                }
-            }
-        when:
-            createAppContext()
-        then:
-            BeanDefinitionParsingException expected = thrown()
-            expected.message.contains 'max-age'
-    }
-
-    def 'http headers hsts@disabled=true no matcher-ref'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'hsts'(disabled:true,'request-matcher-ref':'matcher')
-                }
-            }
-            xml.'b:bean'(id: 'matcher', 'class': AnyRequestMatcher.name)
-        when:
-            createAppContext()
-        then:
-            BeanDefinitionParsingException expected = thrown()
-            expected.message.contains 'request-matcher-ref'
-    }
-
-    def 'http xss@disabled=true no enabled'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'xss-protection'(disabled:true,'enabled':true)
-                }
-            }
-        when:
-            createAppContext()
-        then:
-            BeanDefinitionParsingException expected = thrown()
-            expected.message.contains 'enabled'
-    }
-
-    def 'http xss@disabled=true no block'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'xss-protection'(disabled:true,'block':true)
-                }
-            }
-        when:
-            createAppContext()
-        then:
-            BeanDefinitionParsingException expected = thrown()
-            expected.message.contains 'block'
-    }
-
-    def 'http frame-options@disabled=true no policy'() {
-        setup:
-            httpAutoConfig {
-                'headers'() {
-                    'frame-options'(disabled:true,'policy':'DENY')
-                }
-            }
-        when:
-            createAppContext()
-        then:
-            BeanDefinitionParsingException expected = thrown()
-            expected.message.contains 'policy'
-    }
-
-    def assertHeaders(MockHttpServletResponse response, Map<String,String> expected) {
-        assert response.headerNames == expected.keySet()
-        expected.each { headerName, value ->
-            assert response.getHeaderValues(headerName) == [value]
-        }
-    }
+	def defaultHeaders = ['X-Content-Type-Options':'nosniff',
+								 'X-Frame-Options':'DENY',
+								 'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
+								 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
+								 'Expires' : '0',
+								 'Pragma':'no-cache',
+								 'X-XSS-Protection' : '1; mode=block']
+	def 'headers disabled'() {
+		setup:
+			httpAutoConfig {
+				'headers'(disabled:true)
+			}
+			createAppContext()
+
+		when:
+			def hf = getFilter(HeaderWriterFilter)
+		then:
+			!hf
+	}
+
+	def 'headers disabled with child fails'() {
+		when:
+			httpAutoConfig {
+				'headers'(disabled:true) {
+					'content-type-options'()
+				}
+			}
+			createAppContext()
+		then:
+			thrown(BeanDefinitionParsingException)
+	}
+
+	def 'default headers'() {
+		httpAutoConfig {
+		}
+		createAppContext()
+
+		when:
+			def hf = getFilter(HeaderWriterFilter)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+		then:
+			assertHeaders(response, defaultHeaders)
+	}
+
+	def 'http headers with empty headers'() {
+		setup:
+			httpAutoConfig {
+				'headers'()
+			}
+			createAppContext()
+		when:
+			def hf = getFilter(HeaderWriterFilter)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+		then:
+			assertHeaders(response, defaultHeaders)
+	}
+
+	def 'http headers frame-options@policy=SAMEORIGIN with defaults'() {
+		httpAutoConfig {
+			'headers'() {
+				'frame-options'(policy:'SAMEORIGIN')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+		def expectedHeaders = [:] << defaultHeaders
+		expectedHeaders['X-Frame-Options'] = 'SAMEORIGIN'
+
+		expect:
+		assertHeaders(response, expectedHeaders)
+	}
+
+
+	// --- defaults disabled
+
+	def 'http headers content-type-options'() {
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'content-type-options'()
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+
+		expect:
+		assertHeaders(response, ['X-Content-Type-Options':'nosniff'])
+	}
+
+	def 'http headers frame-options defaults to DENY'() {
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'frame-options'()
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+
+		expect:
+		assertHeaders(response, ['X-Frame-Options':'DENY'])
+	}
+
+	def 'http headers frame-options DENY'() {
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'frame-options'(policy : 'DENY')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+
+		expect:
+		assertHeaders(response, ['X-Frame-Options':'DENY'])
+	}
+
+	def 'http headers frame-options SAMEORIGIN'() {
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'frame-options'(policy : 'SAMEORIGIN')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+
+		expect:
+		assertHeaders(response, ['X-Frame-Options':'SAMEORIGIN'])
+	}
+
+	def 'http headers frame-options ALLOW-FROM no origin reports error'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'frame-options'(policy : 'ALLOW-FROM', strategy : 'static')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+
+		then:
+		BeanDefinitionParsingException e = thrown()
+		e.message.contains "Strategy requires a 'value' to be set." // FIME better error message?
+	}
+
+	def 'http headers frame-options ALLOW-FROM spaces only origin reports error'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'frame-options'(policy : 'ALLOW-FROM', strategy: 'static', value : ' ')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+
+		then:
+		BeanDefinitionParsingException e = thrown()
+		e.message.contains "Strategy requires a 'value' to be set." // FIME better error message?
+	}
+
+	def 'http headers frame-options ALLOW-FROM'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'frame-options'(policy : 'ALLOW-FROM', strategy: 'static', value : 'https://example.com')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+
+		then:
+		assertHeaders(response, ['X-Frame-Options':'ALLOW-FROM https://example.com'])
+	}
+
+	def 'http headers frame-options ALLOW-FROM with whitelist strategy'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'frame-options'(policy : 'ALLOW-FROM', strategy: 'whitelist', value : 'https://example.com')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+
+		def request = new MockHttpServletRequest()
+		request.setParameter("from", "https://example.com");
+		hf.doFilter(request, response, new MockFilterChain())
+
+		then:
+		assertHeaders(response, ['X-Frame-Options':'ALLOW-FROM https://example.com'])
+	}
+
+	def 'http headers header a=b'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'header'(name : 'a', value: 'b')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+
+		then:
+		assertHeaders(response, ['a':'b'])
+	}
+
+	def 'http headers header a=b and c=d'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'header'(name : 'a', value: 'b')
+				'header'(name : 'c', value: 'd')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+
+		then:
+		assertHeaders(response , ['a':'b', 'c':'d'])
+	}
+
+	def 'http headers with ref'() {
+		setup:
+			httpAutoConfig {
+				'headers'('defaults-disabled':true) {
+					'header'(ref:'headerWriter')
+				}
+			}
+			xml.'b:bean'(id: 'headerWriter', 'class': StaticHeadersWriter.name) {
+				'b:constructor-arg'(value:'abc') {}
+				'b:constructor-arg'(value:'def') {}
+			}
+			createAppContext()
+		when:
+			def hf = getFilter(HeaderWriterFilter)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+		then:
+			 assertHeaders(response, ['abc':'def'])
+	}
+
+	def 'http headers header no name produces error'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'header'(value: 'b')
+			}
+		}
+		createAppContext()
+
+		then:
+		thrown(BeanCreationException)
+	}
+
+	def 'http headers header no value produces error'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'header'(name: 'a')
+			}
+		}
+		createAppContext()
+
+		then:
+		thrown(BeanCreationException)
+	}
+
+	def 'http headers xss-protection defaults'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'xss-protection'()
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+
+		then:
+		assertHeaders(response, ['X-XSS-Protection':'1; mode=block'])
+	}
+
+	def 'http headers xss-protection enabled=true'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'xss-protection'(enabled:'true')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+
+		then:
+		assertHeaders(response, ['X-XSS-Protection':'1; mode=block'])
+	}
+
+	def 'http headers xss-protection enabled=false'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'xss-protection'(enabled:'false')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+
+		then:
+		assertHeaders(response, ['X-XSS-Protection':'0'])
+	}
+
+	def 'http headers xss-protection enabled=false and block=true produces error'() {
+		when:
+		httpAutoConfig {
+			'headers'('defaults-disabled':true) {
+				'xss-protection'(enabled:'false', block:'true')
+			}
+		}
+		createAppContext()
+
+		def hf = getFilter(HeaderWriterFilter)
+
+		then:
+		BeanCreationException e = thrown()
+		e.message.contains 'Cannot set block to true with enabled false'
+	}
+
+	def 'http headers cache-control'() {
+		setup:
+			httpAutoConfig {
+				'headers'('defaults-disabled':true) {
+					'cache-control'()
+				}
+			}
+			createAppContext()
+			def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+		when:
+			springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+		then:
+			assertHeaders(response, ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
+									 'Expires' : '0',
+									 'Pragma':'no-cache'])
+	}
+
+	def 'http headers hsts'() {
+		setup:
+			httpAutoConfig {
+				'headers'('defaults-disabled':true) {
+					'hsts'()
+				}
+			}
+			createAppContext()
+			def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+		when:
+			springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+		then:
+			assertHeaders(response, ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains'])
+	}
+
+	def 'http headers hsts default only invokes on HttpServletRequest.isSecure = true'() {
+		setup:
+			httpAutoConfig {
+				'headers'('defaults-disabled':true) {
+					'hsts'()
+				}
+			}
+			createAppContext()
+			def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+		when:
+			springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+		then:
+			response.headerNames.empty
+	}
+
+	def 'http headers hsts custom'() {
+		setup:
+			httpAutoConfig {
+				'headers'('defaults-disabled':true) {
+					'hsts'('max-age-seconds':'1','include-subdomains':false, 'request-matcher-ref' : 'matcher')
+				}
+			}
+
+			xml.'b:bean'(id: 'matcher', 'class': AnyRequestMatcher.name)
+			createAppContext()
+			def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+		when:
+			springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+		then:
+			assertHeaders(response, ['Strict-Transport-Security': 'max-age=1'])
+	}
+
+	// --- disable single default header ---
+
+	def 'http headers cache-controls@disabled=true'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'cache-control'(disabled:true)
+				}
+			}
+			createAppContext()
+			def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			def expectedHeaders = [:] << defaultHeaders
+			expectedHeaders.remove('Cache-Control')
+			expectedHeaders.remove('Expires')
+			expectedHeaders.remove('Pragma')
+		when:
+			springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+		then:
+			assertHeaders(response, expectedHeaders)
+	}
+
+	def 'http headers content-type-options@disabled=true'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'content-type-options'(disabled:true)
+				}
+			}
+			createAppContext()
+			def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			def expectedHeaders = [:] << defaultHeaders
+			expectedHeaders.remove('X-Content-Type-Options')
+		when:
+			springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+		then:
+			assertHeaders(response, expectedHeaders)
+	}
+
+	def 'http headers hsts@disabled=true'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'hsts'(disabled:true)
+				}
+			}
+			createAppContext()
+			def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			def expectedHeaders = [:] << defaultHeaders
+			expectedHeaders.remove('Strict-Transport-Security')
+		when:
+			springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+		then:
+			assertHeaders(response, expectedHeaders)
+	}
+
+	def 'http headers frame-options@disabled=true'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'frame-options'(disabled:true)
+				}
+			}
+			createAppContext()
+			def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			def expectedHeaders = [:] << defaultHeaders
+			expectedHeaders.remove('X-Frame-Options')
+		when:
+			springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+		then:
+			assertHeaders(response, expectedHeaders)
+	}
+
+	def 'http headers xss-protection@disabled=true'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'xss-protection'(disabled:true)
+				}
+			}
+			createAppContext()
+			def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			def expectedHeaders = [:] << defaultHeaders
+			expectedHeaders.remove('X-XSS-Protection')
+		when:
+			springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+		then:
+			assertHeaders(response, expectedHeaders)
+	}
+
+	// --- disable error handling ---
+
+	def 'http headers hsts@disabled=true no include-subdomains'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'hsts'(disabled:true,'include-subdomains':true)
+				}
+			}
+		when:
+			createAppContext()
+		then:
+			BeanDefinitionParsingException expected = thrown()
+			expected.message.contains 'include-subdomains'
+	}
+
+	def 'http headers hsts@disabled=true no max-age'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'hsts'(disabled:true,'max-age-seconds':123)
+				}
+			}
+		when:
+			createAppContext()
+		then:
+			BeanDefinitionParsingException expected = thrown()
+			expected.message.contains 'max-age'
+	}
+
+	def 'http headers hsts@disabled=true no matcher-ref'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'hsts'(disabled:true,'request-matcher-ref':'matcher')
+				}
+			}
+			xml.'b:bean'(id: 'matcher', 'class': AnyRequestMatcher.name)
+		when:
+			createAppContext()
+		then:
+			BeanDefinitionParsingException expected = thrown()
+			expected.message.contains 'request-matcher-ref'
+	}
+
+	def 'http xss@disabled=true no enabled'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'xss-protection'(disabled:true,'enabled':true)
+				}
+			}
+		when:
+			createAppContext()
+		then:
+			BeanDefinitionParsingException expected = thrown()
+			expected.message.contains 'enabled'
+	}
+
+	def 'http xss@disabled=true no block'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'xss-protection'(disabled:true,'block':true)
+				}
+			}
+		when:
+			createAppContext()
+		then:
+			BeanDefinitionParsingException expected = thrown()
+			expected.message.contains 'block'
+	}
+
+	def 'http frame-options@disabled=true no policy'() {
+		setup:
+			httpAutoConfig {
+				'headers'() {
+					'frame-options'(disabled:true,'policy':'DENY')
+				}
+			}
+		when:
+			createAppContext()
+		then:
+			BeanDefinitionParsingException expected = thrown()
+			expected.message.contains 'policy'
+	}
+
+	def assertHeaders(MockHttpServletResponse response, Map<String,String> expected) {
+		assert response.headerNames == expected.keySet()
+		expected.each { headerName, value ->
+			assert response.getHeaderValues(headerName) == [value]
+		}
+	}
 }

+ 128 - 128
config/src/test/groovy/org/springframework/security/config/http/HttpOpenIDConfigTests.groovy

@@ -23,132 +23,132 @@ import javax.servlet.Filter
  */
 class OpenIDConfigTests extends AbstractHttpConfigTests {
 
-    def openIDAndFormLoginWorkTogether() {
-        xml.http() {
-            'openid-login'()
-            'form-login'()
-        }
-        createAppContext()
-
-        def etf = getFilter(ExceptionTranslationFilter)
-        def ap = etf.getAuthenticationEntryPoint();
-
-        expect:
-        ap.loginFormUrl == "/login"
-        // Default login filter should be present since we haven't specified any login URLs
-        getFilter(DefaultLoginPageGeneratingFilter) != null
-    }
-
-    def formLoginEntryPointTakesPrecedenceIfLoginUrlIsSet() {
-        xml.http() {
-            'openid-login'()
-            'form-login'('login-page': '/form-page')
-        }
-        createAppContext()
-
-        expect:
-        getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl == '/form-page'
-    }
-
-    def openIDEntryPointTakesPrecedenceIfLoginUrlIsSet() {
-        xml.http() {
-            'openid-login'('login-page': '/openid-page')
-            'form-login'()
-        }
-        createAppContext()
-
-        expect:
-        getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl == '/openid-page'
-    }
-
-    def multipleLoginPagesCausesError() {
-        when:
-        xml.http() {
-            'openid-login'('login-page': '/openid-page')
-            'form-login'('login-page': '/form-page')
-        }
-        createAppContext()
-        then:
-        thrown(BeanDefinitionParsingException)
-    }
-
-    def openIDAndRememberMeWorkTogether() {
-        xml.debug()
-        xml.http() {
-            interceptUrl('/**', 'denyAll')
-            'openid-login'()
-            'remember-me'()
-            'csrf'(disabled:true)
-        }
-        createAppContext()
-
-        // Default login filter should be present since we haven't specified any login URLs
-        def loginFilter = getFilter(DefaultLoginPageGeneratingFilter)
-        def openIDFilter = getFilter(OpenIDAuthenticationFilter)
-        openIDFilter.setConsumer(new OpenIDConsumer() {
-            public String beginConsumption(HttpServletRequest req, String claimedIdentity, String returnToUrl, String realm)
-                    throws OpenIDConsumerException {
-                return "http://testopenid.com?openid.return_to=" + returnToUrl;
-            }
-
-            public OpenIDAuthenticationToken endConsumption(HttpServletRequest req) throws OpenIDConsumerException {
-                throw new UnsupportedOperationException();
-            }
-        })
-        Set<String> returnToUrlParameters = new HashSet<String>()
-        returnToUrlParameters.add(AbstractRememberMeServices.DEFAULT_PARAMETER)
-        openIDFilter.setReturnToUrlParameters(returnToUrlParameters)
-        assert loginFilter.openIDrememberMeParameter != null
-
-        MockHttpServletRequest request = new MockHttpServletRequest(method:'GET');
-        MockHttpServletResponse response = new MockHttpServletResponse();
-
-        when: "Initial request is made"
-        Filter fc = appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN)
-        request.setServletPath("/something.html")
-        fc.doFilter(request, response, new MockFilterChain())
-        then: "Redirected to login"
-        response.getRedirectedUrl().endsWith("/login")
-        when: "Login page is requested"
-        request.setServletPath("/login")
-        request.setRequestURI("/login")
-        response = new MockHttpServletResponse()
-        fc.doFilter(request, response, new MockFilterChain())
-        then: "Remember-me choice is added to page"
-        response.getContentAsString().contains(AbstractRememberMeServices.DEFAULT_PARAMETER)
-        when: "Login is submitted with remember-me selected"
-        request.servletPath = "/login/openid"
-        request.setParameter(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, "http://hey.openid.com/")
-        request.setParameter(AbstractRememberMeServices.DEFAULT_PARAMETER, "on")
-        response = new MockHttpServletResponse();
-        fc.doFilter(request, response, new MockFilterChain());
-        String expectedReturnTo = request.getRequestURL().append("?")
-                                        .append(AbstractRememberMeServices.DEFAULT_PARAMETER)
-                                        .append("=").append("on").toString();
-        then: "return_to URL contains remember-me choice"
-        response.getRedirectedUrl() == "http://testopenid.com?openid.return_to=" + expectedReturnTo
-    }
-
-    def openIDWithAttributeExchangeConfigurationIsParsedCorrectly() {
-        xml.http() {
-            'openid-login'() {
-                'attribute-exchange'() {
-                    'openid-attribute'(name: 'nickname', type: 'http://schema.openid.net/namePerson/friendly')
-                    'openid-attribute'(name: 'email', type: 'http://schema.openid.net/contact/email', required: 'true',
-                            'count': '2')
-                }
-            }
-        }
-        createAppContext()
-
-        List attributes = getFilter(OpenIDAuthenticationFilter).consumer.attributesToFetchFactory.createAttributeList('http://someid')
-
-        expect:
-        attributes.size() == 2
-        attributes[0].name == 'nickname'
-        attributes[0].type == 'http://schema.openid.net/namePerson/friendly'
-        !attributes[0].required
-        attributes[1].required
-        attributes[1].getCount() == 2
-    }
+	def openIDAndFormLoginWorkTogether() {
+		xml.http() {
+			'openid-login'()
+			'form-login'()
+		}
+		createAppContext()
+
+		def etf = getFilter(ExceptionTranslationFilter)
+		def ap = etf.getAuthenticationEntryPoint();
+
+		expect:
+		ap.loginFormUrl == "/login"
+		// Default login filter should be present since we haven't specified any login URLs
+		getFilter(DefaultLoginPageGeneratingFilter) != null
+	}
+
+	def formLoginEntryPointTakesPrecedenceIfLoginUrlIsSet() {
+		xml.http() {
+			'openid-login'()
+			'form-login'('login-page': '/form-page')
+		}
+		createAppContext()
+
+		expect:
+		getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl == '/form-page'
+	}
+
+	def openIDEntryPointTakesPrecedenceIfLoginUrlIsSet() {
+		xml.http() {
+			'openid-login'('login-page': '/openid-page')
+			'form-login'()
+		}
+		createAppContext()
+
+		expect:
+		getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl == '/openid-page'
+	}
+
+	def multipleLoginPagesCausesError() {
+		when:
+		xml.http() {
+			'openid-login'('login-page': '/openid-page')
+			'form-login'('login-page': '/form-page')
+		}
+		createAppContext()
+		then:
+		thrown(BeanDefinitionParsingException)
+	}
+
+	def openIDAndRememberMeWorkTogether() {
+		xml.debug()
+		xml.http() {
+			interceptUrl('/**', 'denyAll')
+			'openid-login'()
+			'remember-me'()
+			'csrf'(disabled:true)
+		}
+		createAppContext()
+
+		// Default login filter should be present since we haven't specified any login URLs
+		def loginFilter = getFilter(DefaultLoginPageGeneratingFilter)
+		def openIDFilter = getFilter(OpenIDAuthenticationFilter)
+		openIDFilter.setConsumer(new OpenIDConsumer() {
+			public String beginConsumption(HttpServletRequest req, String claimedIdentity, String returnToUrl, String realm)
+					throws OpenIDConsumerException {
+				return "http://testopenid.com?openid.return_to=" + returnToUrl;
+			}
+
+			public OpenIDAuthenticationToken endConsumption(HttpServletRequest req) throws OpenIDConsumerException {
+				throw new UnsupportedOperationException();
+			}
+		})
+		Set<String> returnToUrlParameters = new HashSet<String>()
+		returnToUrlParameters.add(AbstractRememberMeServices.DEFAULT_PARAMETER)
+		openIDFilter.setReturnToUrlParameters(returnToUrlParameters)
+		assert loginFilter.openIDrememberMeParameter != null
+
+		MockHttpServletRequest request = new MockHttpServletRequest(method:'GET');
+		MockHttpServletResponse response = new MockHttpServletResponse();
+
+		when: "Initial request is made"
+		Filter fc = appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN)
+		request.setServletPath("/something.html")
+		fc.doFilter(request, response, new MockFilterChain())
+		then: "Redirected to login"
+		response.getRedirectedUrl().endsWith("/login")
+		when: "Login page is requested"
+		request.setServletPath("/login")
+		request.setRequestURI("/login")
+		response = new MockHttpServletResponse()
+		fc.doFilter(request, response, new MockFilterChain())
+		then: "Remember-me choice is added to page"
+		response.getContentAsString().contains(AbstractRememberMeServices.DEFAULT_PARAMETER)
+		when: "Login is submitted with remember-me selected"
+		request.servletPath = "/login/openid"
+		request.setParameter(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, "http://hey.openid.com/")
+		request.setParameter(AbstractRememberMeServices.DEFAULT_PARAMETER, "on")
+		response = new MockHttpServletResponse();
+		fc.doFilter(request, response, new MockFilterChain());
+		String expectedReturnTo = request.getRequestURL().append("?")
+										.append(AbstractRememberMeServices.DEFAULT_PARAMETER)
+										.append("=").append("on").toString();
+		then: "return_to URL contains remember-me choice"
+		response.getRedirectedUrl() == "http://testopenid.com?openid.return_to=" + expectedReturnTo
+	}
+
+	def openIDWithAttributeExchangeConfigurationIsParsedCorrectly() {
+		xml.http() {
+			'openid-login'() {
+				'attribute-exchange'() {
+					'openid-attribute'(name: 'nickname', type: 'http://schema.openid.net/namePerson/friendly')
+					'openid-attribute'(name: 'email', type: 'http://schema.openid.net/contact/email', required: 'true',
+							'count': '2')
+				}
+			}
+		}
+		createAppContext()
+
+		List attributes = getFilter(OpenIDAuthenticationFilter).consumer.attributesToFetchFactory.createAttributeList('http://someid')
+
+		expect:
+		attributes.size() == 2
+		attributes[0].name == 'nickname'
+		attributes[0].type == 'http://schema.openid.net/namePerson/friendly'
+		!attributes[0].required
+		attributes[1].required
+		attributes[1].getCount() == 2
+	}
 }

+ 68 - 68
config/src/test/groovy/org/springframework/security/config/http/InterceptUrlConfigTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -85,80 +85,80 @@ import org.springframework.security.authentication.AuthenticationManager
 class InterceptUrlConfigTests extends AbstractHttpConfigTests {
 
    def "SEC-2256: intercept-url method is not given priority"() {
-       when:
-           httpAutoConfig {
-               'intercept-url'(pattern: '/anyurl', access: "ROLE_USER")
-               'intercept-url'(pattern: '/anyurl', 'method':'GET',access: 'ROLE_ADMIN')
-           }
-           createAppContext()
+	   when:
+		   httpAutoConfig {
+			   'intercept-url'(pattern: '/anyurl', access: "ROLE_USER")
+			   'intercept-url'(pattern: '/anyurl', 'method':'GET',access: 'ROLE_ADMIN')
+		   }
+		   createAppContext()
 
-           def fids = getFilter(FilterSecurityInterceptor).securityMetadataSource
-           def attrs = fids.getAttributes(createFilterinvocation("/anyurl", "GET"))
-           def attrsPost = fids.getAttributes(createFilterinvocation("/anyurl", "POST"))
+		   def fids = getFilter(FilterSecurityInterceptor).securityMetadataSource
+		   def attrs = fids.getAttributes(createFilterinvocation("/anyurl", "GET"))
+		   def attrsPost = fids.getAttributes(createFilterinvocation("/anyurl", "POST"))
 
-       then:
-           attrs.size() == 1
-           attrs.contains(new SecurityConfig("ROLE_USER"))
-           attrsPost.size() == 1
-           attrsPost.contains(new SecurityConfig("ROLE_USER"))
+	   then:
+		   attrs.size() == 1
+		   attrs.contains(new SecurityConfig("ROLE_USER"))
+		   attrsPost.size() == 1
+		   attrsPost.contains(new SecurityConfig("ROLE_USER"))
    }
 
    def "SEC-2355: intercept-url support patch"() {
-       setup:
-           MockHttpServletRequest request = new MockHttpServletRequest(method:'GET')
-           MockHttpServletResponse response = new MockHttpServletResponse()
-           MockFilterChain chain = new MockFilterChain()
-           xml.http('use-expressions':false) {
-               'http-basic'()
-               'intercept-url'(pattern: '/**', 'method':'PATCH',access: 'ROLE_ADMIN')
-               csrf(disabled:true)
-           }
-           createAppContext()
-       when: 'Method other than PATCH is used'
-           springSecurityFilterChain.doFilter(request,response,chain)
-       then: 'The response is OK'
-           response.status == HttpServletResponse.SC_OK
-       when: 'Method of PATCH is used'
-           request = new MockHttpServletRequest(method:'PATCH')
-           response = new MockHttpServletResponse()
-           chain = new MockFilterChain()
-           springSecurityFilterChain.doFilter(request, response, chain)
-        then: 'The response is unauthorized'
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
+	   setup:
+		   MockHttpServletRequest request = new MockHttpServletRequest(method:'GET')
+		   MockHttpServletResponse response = new MockHttpServletResponse()
+		   MockFilterChain chain = new MockFilterChain()
+		   xml.http('use-expressions':false) {
+			   'http-basic'()
+			   'intercept-url'(pattern: '/**', 'method':'PATCH',access: 'ROLE_ADMIN')
+			   csrf(disabled:true)
+		   }
+		   createAppContext()
+	   when: 'Method other than PATCH is used'
+		   springSecurityFilterChain.doFilter(request,response,chain)
+	   then: 'The response is OK'
+		   response.status == HttpServletResponse.SC_OK
+	   when: 'Method of PATCH is used'
+		   request = new MockHttpServletRequest(method:'PATCH')
+		   response = new MockHttpServletResponse()
+		   chain = new MockFilterChain()
+		   springSecurityFilterChain.doFilter(request, response, chain)
+		then: 'The response is unauthorized'
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
    }
 
-    def "intercept-url supports hasAnyRoles"() {
-        setup:
-            MockHttpServletRequest request = new MockHttpServletRequest(method:'GET')
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            MockFilterChain chain = new MockFilterChain()
-            xml.http('use-expressions':true) {
-                'http-basic'()
-                'intercept-url'(pattern: '/**', access: "hasAnyRole('ROLE_DEVELOPER','ROLE_USER')")
-                csrf(disabled:true)
-            }
-        when:
-            createAppContext()
-        then: 'no error'
-            noExceptionThrown()
-        when: 'ROLE_USER can access'
-            login(request, 'user', 'password')
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: 'The response is OK'
-            response.status == HttpServletResponse.SC_OK
-        when: 'ROLE_A cannot access'
-            request = new MockHttpServletRequest(method:'GET')
-            response = new MockHttpServletResponse()
-            chain = new MockFilterChain()
-            login(request, 'bob', 'bobspassword')
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: 'The response is Forbidden'
-            response.status == HttpServletResponse.SC_FORBIDDEN
+	def "intercept-url supports hasAnyRoles"() {
+		setup:
+			MockHttpServletRequest request = new MockHttpServletRequest(method:'GET')
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			MockFilterChain chain = new MockFilterChain()
+			xml.http('use-expressions':true) {
+				'http-basic'()
+				'intercept-url'(pattern: '/**', access: "hasAnyRole('ROLE_DEVELOPER','ROLE_USER')")
+				csrf(disabled:true)
+			}
+		when:
+			createAppContext()
+		then: 'no error'
+			noExceptionThrown()
+		when: 'ROLE_USER can access'
+			login(request, 'user', 'password')
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: 'The response is OK'
+			response.status == HttpServletResponse.SC_OK
+		when: 'ROLE_A cannot access'
+			request = new MockHttpServletRequest(method:'GET')
+			response = new MockHttpServletResponse()
+			chain = new MockFilterChain()
+			login(request, 'bob', 'bobspassword')
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: 'The response is Forbidden'
+			response.status == HttpServletResponse.SC_FORBIDDEN
 
-    }
+	}
 
-    def login(MockHttpServletRequest request, String username, String password) {
-        String toEncode = username + ':' + password
-        request.addHeader('Authorization','Basic ' + new String(Base64.encode(toEncode.getBytes('UTF-8'))))
-    }
+	def login(MockHttpServletRequest request, String username, String password) {
+		String toEncode = username + ':' + password
+		request.addHeader('Authorization','Basic ' + new String(Base64.encode(toEncode.getBytes('UTF-8'))))
+	}
 }

+ 698 - 698
config/src/test/groovy/org/springframework/security/config/http/MiscHttpConfigTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -84,719 +84,719 @@ import org.springframework.security.authentication.AuthenticationManager
  */
 class MiscHttpConfigTests extends AbstractHttpConfigTests {
 
-    def 'Minimal configuration parses'() {
-        setup:
-        xml.http {
-            'http-basic'()
-        }
-        createAppContext()
-    }
-
-    def httpAutoConfigSetsUpCorrectFilterList() {
-        when:
-        xml.http('auto-config': 'true')
-        createAppContext()
-
-        then:
-        filtersMatchExpectedAutoConfigList('/anyurl');
-    }
-
-    void filtersMatchExpectedAutoConfigList(String url) {
-        def filterList = getFilters(url);
-        Iterator<Filter> filters = filterList.iterator();
-
-        assert filters.next() instanceof SecurityContextPersistenceFilter
-        assert filters.next() instanceof WebAsyncManagerIntegrationFilter
-        assert filters.next() instanceof HeaderWriterFilter
-        assert filters.next() instanceof CsrfFilter
-        assert filters.next() instanceof LogoutFilter
-        Object authProcFilter = filters.next();
-        assert authProcFilter instanceof UsernamePasswordAuthenticationFilter
-        assert filters.next() instanceof DefaultLoginPageGeneratingFilter
-        assert filters.next() instanceof BasicAuthenticationFilter
-        assert filters.next() instanceof RequestCacheAwareFilter
-        assert filters.next() instanceof SecurityContextHolderAwareRequestFilter
-        assert filters.next() instanceof AnonymousAuthenticationFilter
-        assert filters.next() instanceof SessionManagementFilter
-        assert filters.next() instanceof ExceptionTranslationFilter
-        Object fsiObj = filters.next();
-        assert fsiObj instanceof FilterSecurityInterceptor
-        def fsi = (FilterSecurityInterceptor) fsiObj;
-        assert fsi.isObserveOncePerRequest()
-    }
-
-    def filterListShouldBeEmptyForPatternWithNoFilters() {
-        xml.debug()
-        xml.http(pattern: '/unprotected', security: 'none')
-        httpAutoConfig() {}
-        createAppContext()
-
-        expect:
-        getFilters("/unprotected").size() == 0
-    }
-
-    def debugFilterHandlesMissingAndEmptyFilterChains() {
-      when:
-      xml.debug()
-      xml.http(pattern: '/unprotected', security: 'none')
-      createAppContext()
-      then:
-      Filter debugFilter = appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
-      MockHttpServletRequest request = new MockHttpServletRequest()
-      request.setServletPath("/unprotected");
-      debugFilter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
-      request.setServletPath("/nomatch");
-      debugFilter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
-    }
-
-    def regexPathsWorkCorrectly() {
-        xml.http(pattern: '\\A\\/[a-z]+', security: 'none', 'request-matcher': 'regex')
-        httpAutoConfig() {}
-        createAppContext()
-
-        expect:
-        getFilters('/imlowercase').size() == 0
-        filtersMatchExpectedAutoConfigList('/MixedCase');
-    }
-
-    def ciRegexPathsWorkCorrectly() {
-        when:
-        xml.http(pattern: '\\A\\/[a-z]+', security: 'none', 'request-matcher': 'ciRegex')
-        httpAutoConfig() {}
-        createAppContext()
-
-        then:
-        getFilters('/imMixedCase').size() == 0
-        filtersMatchExpectedAutoConfigList('/Im_caught_by_the_Universal_Match');
-    }
-
-    def requestMatcherRefWorksCorrectly() {
-        xml.http('request-matcher-ref': 'matcher', security: 'none')
-        bean('matcher', AntPathRequestMatcher.class.name, ['/nofilters'])
-        httpAutoConfig() {}
-        createAppContext()
-
-        expect:
-        getFilters('/nofilters').size() == 0
-        filtersMatchExpectedAutoConfigList('/somethingElse');
-    }
-
-    // SEC-1152
-    def anonymousFilterIsAddedByDefault() {
-        xml.http {
-            'form-login'()
-        }
-        createAppContext()
-
-        expect:
-        getFilters("/anything")[8] instanceof AnonymousAuthenticationFilter
-    }
-
-    def anonymousFilterIsRemovedIfDisabledFlagSet() {
-        xml.http {
-            'form-login'()
-            'anonymous'(enabled: 'false')
-        }
-        createAppContext()
-
-        expect:
-        !(getFilters("/anything").get(5) instanceof AnonymousAuthenticationFilter)
-    }
-
-    def anonymousCustomAttributesAreSetCorrectly() {
-        xml.http {
-            'form-login'()
-            'anonymous'(username: 'joe', 'granted-authority':'anonymity', key: 'customKey')
-        }
-        createAppContext()
-
-        AnonymousAuthenticationFilter filter = getFilter(AnonymousAuthenticationFilter);
-        def providers = appContext.getBeansOfType(AuthenticationManager).values()*.providers.flatten()
-
-        expect:
-        'customKey' == providers.find { it instanceof AnonymousAuthenticationProvider }.key
-        'customKey' == filter.key
-        'joe' == filter.principal
-        'anonymity' == filter.authorities[0].authority
-    }
-
-    def anonymousSupportsMultipleGrantedAuthorities() {
-        xml.http {
-            'form-login'()
-            'anonymous'(username: 'joe', 'granted-authority':'ROLE_INVITADO,ROLE_PROFILE_INVITADO,ROLE_GRUPO_PUBLICO', key: 'customKey')
-        }
-        createAppContext()
-
-        AnonymousAuthenticationFilter filter = getFilter(AnonymousAuthenticationFilter);
-        def providers = appContext.getBeansOfType(AuthenticationManager).values()*.providers.flatten()
-
-        expect:
-        'customKey' == providers.find { it instanceof AnonymousAuthenticationProvider }.key
-        'customKey' == filter.key
-        'joe' == filter.principal
-        ['ROLE_INVITADO','ROLE_PROFILE_INVITADO','ROLE_GRUPO_PUBLICO'] == filter.authorities*.authority
-    }
-
-    def httpMethodMatchIsSupported() {
-        httpAutoConfig {
-            interceptUrl '/secure*', 'DELETE', 'ROLE_SUPERVISOR'
-            interceptUrl '/secure*', 'POST', 'ROLE_A,ROLE_B'
-            interceptUrl '/**', 'ROLE_C'
-        }
-        createAppContext()
-
-        def fids = getFilter(FilterSecurityInterceptor).getSecurityMetadataSource();
-        def attrs = fids.getAttributes(createFilterinvocation("/secure", "POST"));
-
-        expect:
-        attrs.size() == 2
-        attrs.contains(new SecurityConfig("ROLE_A"))
-        attrs.contains(new SecurityConfig("ROLE_B"))
-    }
+	def 'Minimal configuration parses'() {
+		setup:
+		xml.http {
+			'http-basic'()
+		}
+		createAppContext()
+	}
+
+	def httpAutoConfigSetsUpCorrectFilterList() {
+		when:
+		xml.http('auto-config': 'true')
+		createAppContext()
+
+		then:
+		filtersMatchExpectedAutoConfigList('/anyurl');
+	}
+
+	void filtersMatchExpectedAutoConfigList(String url) {
+		def filterList = getFilters(url);
+		Iterator<Filter> filters = filterList.iterator();
+
+		assert filters.next() instanceof SecurityContextPersistenceFilter
+		assert filters.next() instanceof WebAsyncManagerIntegrationFilter
+		assert filters.next() instanceof HeaderWriterFilter
+		assert filters.next() instanceof CsrfFilter
+		assert filters.next() instanceof LogoutFilter
+		Object authProcFilter = filters.next();
+		assert authProcFilter instanceof UsernamePasswordAuthenticationFilter
+		assert filters.next() instanceof DefaultLoginPageGeneratingFilter
+		assert filters.next() instanceof BasicAuthenticationFilter
+		assert filters.next() instanceof RequestCacheAwareFilter
+		assert filters.next() instanceof SecurityContextHolderAwareRequestFilter
+		assert filters.next() instanceof AnonymousAuthenticationFilter
+		assert filters.next() instanceof SessionManagementFilter
+		assert filters.next() instanceof ExceptionTranslationFilter
+		Object fsiObj = filters.next();
+		assert fsiObj instanceof FilterSecurityInterceptor
+		def fsi = (FilterSecurityInterceptor) fsiObj;
+		assert fsi.isObserveOncePerRequest()
+	}
+
+	def filterListShouldBeEmptyForPatternWithNoFilters() {
+		xml.debug()
+		xml.http(pattern: '/unprotected', security: 'none')
+		httpAutoConfig() {}
+		createAppContext()
+
+		expect:
+		getFilters("/unprotected").size() == 0
+	}
+
+	def debugFilterHandlesMissingAndEmptyFilterChains() {
+	  when:
+	  xml.debug()
+	  xml.http(pattern: '/unprotected', security: 'none')
+	  createAppContext()
+	  then:
+	  Filter debugFilter = appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
+	  MockHttpServletRequest request = new MockHttpServletRequest()
+	  request.setServletPath("/unprotected");
+	  debugFilter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
+	  request.setServletPath("/nomatch");
+	  debugFilter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
+	}
+
+	def regexPathsWorkCorrectly() {
+		xml.http(pattern: '\\A\\/[a-z]+', security: 'none', 'request-matcher': 'regex')
+		httpAutoConfig() {}
+		createAppContext()
+
+		expect:
+		getFilters('/imlowercase').size() == 0
+		filtersMatchExpectedAutoConfigList('/MixedCase');
+	}
+
+	def ciRegexPathsWorkCorrectly() {
+		when:
+		xml.http(pattern: '\\A\\/[a-z]+', security: 'none', 'request-matcher': 'ciRegex')
+		httpAutoConfig() {}
+		createAppContext()
+
+		then:
+		getFilters('/imMixedCase').size() == 0
+		filtersMatchExpectedAutoConfigList('/Im_caught_by_the_Universal_Match');
+	}
+
+	def requestMatcherRefWorksCorrectly() {
+		xml.http('request-matcher-ref': 'matcher', security: 'none')
+		bean('matcher', AntPathRequestMatcher.class.name, ['/nofilters'])
+		httpAutoConfig() {}
+		createAppContext()
+
+		expect:
+		getFilters('/nofilters').size() == 0
+		filtersMatchExpectedAutoConfigList('/somethingElse');
+	}
+
+	// SEC-1152
+	def anonymousFilterIsAddedByDefault() {
+		xml.http {
+			'form-login'()
+		}
+		createAppContext()
+
+		expect:
+		getFilters("/anything")[8] instanceof AnonymousAuthenticationFilter
+	}
+
+	def anonymousFilterIsRemovedIfDisabledFlagSet() {
+		xml.http {
+			'form-login'()
+			'anonymous'(enabled: 'false')
+		}
+		createAppContext()
+
+		expect:
+		!(getFilters("/anything").get(5) instanceof AnonymousAuthenticationFilter)
+	}
+
+	def anonymousCustomAttributesAreSetCorrectly() {
+		xml.http {
+			'form-login'()
+			'anonymous'(username: 'joe', 'granted-authority':'anonymity', key: 'customKey')
+		}
+		createAppContext()
+
+		AnonymousAuthenticationFilter filter = getFilter(AnonymousAuthenticationFilter);
+		def providers = appContext.getBeansOfType(AuthenticationManager).values()*.providers.flatten()
+
+		expect:
+		'customKey' == providers.find { it instanceof AnonymousAuthenticationProvider }.key
+		'customKey' == filter.key
+		'joe' == filter.principal
+		'anonymity' == filter.authorities[0].authority
+	}
+
+	def anonymousSupportsMultipleGrantedAuthorities() {
+		xml.http {
+			'form-login'()
+			'anonymous'(username: 'joe', 'granted-authority':'ROLE_INVITADO,ROLE_PROFILE_INVITADO,ROLE_GRUPO_PUBLICO', key: 'customKey')
+		}
+		createAppContext()
+
+		AnonymousAuthenticationFilter filter = getFilter(AnonymousAuthenticationFilter);
+		def providers = appContext.getBeansOfType(AuthenticationManager).values()*.providers.flatten()
+
+		expect:
+		'customKey' == providers.find { it instanceof AnonymousAuthenticationProvider }.key
+		'customKey' == filter.key
+		'joe' == filter.principal
+		['ROLE_INVITADO','ROLE_PROFILE_INVITADO','ROLE_GRUPO_PUBLICO'] == filter.authorities*.authority
+	}
+
+	def httpMethodMatchIsSupported() {
+		httpAutoConfig {
+			interceptUrl '/secure*', 'DELETE', 'ROLE_SUPERVISOR'
+			interceptUrl '/secure*', 'POST', 'ROLE_A,ROLE_B'
+			interceptUrl '/**', 'ROLE_C'
+		}
+		createAppContext()
+
+		def fids = getFilter(FilterSecurityInterceptor).getSecurityMetadataSource();
+		def attrs = fids.getAttributes(createFilterinvocation("/secure", "POST"));
+
+		expect:
+		attrs.size() == 2
+		attrs.contains(new SecurityConfig("ROLE_A"))
+		attrs.contains(new SecurityConfig("ROLE_B"))
+	}
 
    def httpMethodMatchIsSupportedForRequiresChannel() {
-       httpAutoConfig {
-           'intercept-url'(pattern: '/anyurl')
-           'intercept-url'(pattern: '/anyurl', 'method':'GET',access: 'ROLE_ADMIN', 'requires-channel': 'https')
-       }
-       createAppContext()
-
-       def fids = getFilter(ChannelProcessingFilter).getSecurityMetadataSource();
-       def attrs = fids.getAttributes(createFilterinvocation("/anyurl", "GET"));
-       def attrsPost = fids.getAttributes(createFilterinvocation("/anyurl", "POST"));
-
-       expect:
-       attrs.size() == 1
-       attrs.contains(new SecurityConfig("REQUIRES_SECURE_CHANNEL"))
-       attrsPost == null
+	   httpAutoConfig {
+		   'intercept-url'(pattern: '/anyurl')
+		   'intercept-url'(pattern: '/anyurl', 'method':'GET',access: 'ROLE_ADMIN', 'requires-channel': 'https')
+	   }
+	   createAppContext()
+
+	   def fids = getFilter(ChannelProcessingFilter).getSecurityMetadataSource();
+	   def attrs = fids.getAttributes(createFilterinvocation("/anyurl", "GET"));
+	   def attrsPost = fids.getAttributes(createFilterinvocation("/anyurl", "POST"));
+
+	   expect:
+	   attrs.size() == 1
+	   attrs.contains(new SecurityConfig("REQUIRES_SECURE_CHANNEL"))
+	   attrsPost == null
    }
 
    def httpMethodMatchIsSupportedForRequiresChannelAny() {
-       httpAutoConfig {
-           'intercept-url'(pattern: '/**')
-           'intercept-url'(pattern: '/**', 'method':'GET',access: 'ROLE_ADMIN', 'requires-channel': 'https')
-       }
-       createAppContext()
-
-       def fids = getFilter(ChannelProcessingFilter).getSecurityMetadataSource();
-       def attrs = fids.getAttributes(createFilterinvocation("/anyurl", "GET"));
-       def attrsPost = fids.getAttributes(createFilterinvocation("/anyurl", "POST"));
-
-       expect:
-       attrs.size() == 1
-       attrs.contains(new SecurityConfig("REQUIRES_SECURE_CHANNEL"))
-       attrsPost == null
+	   httpAutoConfig {
+		   'intercept-url'(pattern: '/**')
+		   'intercept-url'(pattern: '/**', 'method':'GET',access: 'ROLE_ADMIN', 'requires-channel': 'https')
+	   }
+	   createAppContext()
+
+	   def fids = getFilter(ChannelProcessingFilter).getSecurityMetadataSource();
+	   def attrs = fids.getAttributes(createFilterinvocation("/anyurl", "GET"));
+	   def attrsPost = fids.getAttributes(createFilterinvocation("/anyurl", "POST"));
+
+	   expect:
+	   attrs.size() == 1
+	   attrs.contains(new SecurityConfig("REQUIRES_SECURE_CHANNEL"))
+	   attrsPost == null
    }
 
-    def oncePerRequestAttributeIsSupported() {
-        xml.http('once-per-request': 'false') {
-            'http-basic'()
-        }
-        createAppContext()
-
-        expect:
-        !getFilter(FilterSecurityInterceptor).isObserveOncePerRequest()
-    }
-
-    def httpBasicSupportsSeparateEntryPoint() {
-        xml.http() {
-            'http-basic'('entry-point-ref': 'ep')
-        }
-        bean('ep', BasicAuthenticationEntryPoint.class.name, ['realmName':'whocares'],[:])
-        createAppContext();
-
-        def baf = getFilter(BasicAuthenticationFilter)
-        def etf = getFilter(ExceptionTranslationFilter)
-        def ep = appContext.getBean("ep")
-
-        expect:
-        baf.authenticationEntryPoint == ep
-        // Since no other authentication system is in use, this should also end up on the ETF
-        etf.authenticationEntryPoint == ep
-    }
-
-    def interceptUrlWithRequiresChannelAddsChannelFilterToStack() {
-        httpAutoConfig {
-            'intercept-url'(pattern: '/**', 'requires-channel': 'https')
-        }
-        createAppContext();
-        List filters = getFilters("/someurl");
-
-        expect:
-        filters.size() == AUTO_CONFIG_FILTERS + 1
-        filters[0] instanceof ChannelProcessingFilter
-    }
-
-    def portMappingsAreParsedCorrectly() {
-        httpAutoConfig {
-            'port-mappings'() {
-                'port-mapping'(http: '9080', https: '9443')
-            }
-        }
-        createAppContext();
-
-        def pm = (appContext.getBeansOfType(PortMapperImpl).values() as List)[0];
-
-        expect:
-        pm.getTranslatedPortMappings().size() == 1
-        pm.lookupHttpPort(9443) == 9080
-        pm.lookupHttpsPort(9080) == 9443
-    }
-
-    def externalFiltersAreTreatedCorrectly() {
-        httpAutoConfig {
-            'custom-filter'(position: 'FIRST', ref: '${customFilterRef}')
-            'custom-filter'(after: 'LOGOUT_FILTER', ref: 'userFilter')
-            'custom-filter'(before: 'SECURITY_CONTEXT_FILTER', ref: 'userFilter1')
-        }
-        bean('phc', PropertyPlaceholderConfigurer)
-        bean('userFilter', SecurityContextHolderAwareRequestFilter)
-        bean('userFilter1', SecurityContextPersistenceFilter)
-
-        System.setProperty('customFilterRef', 'userFilter')
-        createAppContext();
-
-        def filters = getFilters("/someurl");
-
-        expect:
-        AUTO_CONFIG_FILTERS + 3 == filters.size();
-        filters[0] instanceof SecurityContextHolderAwareRequestFilter
-        filters[1] instanceof SecurityContextPersistenceFilter
-        filters[7] instanceof SecurityContextHolderAwareRequestFilter
-        filters[1] instanceof SecurityContextPersistenceFilter
-    }
-
-    def twoFiltersWithSameOrderAreRejected() {
-        when:
-        httpAutoConfig {
-            'custom-filter'(position: 'LOGOUT_FILTER', ref: 'userFilter')
-        }
-        bean('userFilter', SecurityContextHolderAwareRequestFilter)
-        createAppContext();
-
-        then:
-        thrown(BeanDefinitionParsingException)
-    }
-
-    def x509SupportAddsFilterAtExpectedPosition() {
-        httpAutoConfig {
-            x509()
-        }
-        createAppContext()
-
-        expect:
-        getFilters("/someurl")[5] instanceof X509AuthenticationFilter
-    }
-
-    def x509SubjectPrincipalRegexCanBeSetUsingPropertyPlaceholder() {
-        httpAutoConfig {
-            x509('subject-principal-regex':'${subject-principal-regex}')
-        }
-        bean('phc', PropertyPlaceholderConfigurer.class.name)
-        System.setProperty("subject-principal-regex", "uid=(.*),");
-        createAppContext()
-        def filter = getFilter(X509AuthenticationFilter)
-
-        expect:
-        filter.principalExtractor.subjectDnPattern.pattern() == "uid=(.*),"
-    }
-
-    def invalidLogoutSuccessUrlIsDetected() {
-        when:
-        xml.http {
-            'form-login'()
-            'logout'('logout-success-url': 'noLeadingSlash')
-        }
-        createAppContext()
-
-        then:
-        BeanCreationException e = thrown()
-    }
-
-    def cookiesToDeleteOnLogoutUrlAddsCorrectLogoutHandler() {
-        xml.http {
-            'logout'('delete-cookies': 'JSESSIONID, mycookie')
-            'form-login'()
-        }
-        createAppContext()
-        def handlers = getFilter(LogoutFilter).handlers
-
-        expect:
-        handlers[2] instanceof CookieClearingLogoutHandler
-        handlers[2].cookiesToClear[0] == 'JSESSIONID'
-        handlers[2].cookiesToClear[1] == 'mycookie'
-    }
-
-    def logoutSuccessHandlerIsSetCorrectly() {
-        xml.http {
-            'form-login'()
-            'logout'('success-handler-ref': 'logoutHandler')
-        }
-        bean('logoutHandler', SimpleUrlLogoutSuccessHandler)
-        createAppContext()
-
-        LogoutFilter filter = getFilter(LogoutFilter);
-
-        expect:
-        FieldUtils.getFieldValue(filter, "logoutSuccessHandler") == appContext.getBean("logoutHandler")
-    }
-
-    def externalRequestCacheIsConfiguredCorrectly() {
-        httpAutoConfig {
-            'request-cache'(ref: 'cache')
-        }
-        bean('cache', HttpSessionRequestCache.class.name)
-        createAppContext()
-
-        expect:
-        appContext.getBean("cache") == getFilter(ExceptionTranslationFilter.class).requestCache
-    }
-
-    def customEntryPointIsSupported() {
-        xml.http('auto-config': 'true', 'entry-point-ref': 'entryPoint') {}
-        bean('entryPoint', MockEntryPoint.class.name)
-        createAppContext()
-
-        expect:
-        getFilter(ExceptionTranslationFilter).getAuthenticationEntryPoint() instanceof MockEntryPoint
-    }
-
-    /**
-     * See SEC-750. If the http security post processor causes beans to be instantiated too eagerly, they way miss
-     * additional processing. In this method we have a UserDetailsService which is referenced from the namespace
-     * and also has a post processor registered which will modify it.
-     */
-    def httpElementDoesntInterfereWithBeanPostProcessing() {
-        xml.http('auto-config': 'true', 'entry-point-ref': 'entryPoint') {}
-        xml.'authentication-manager'() {
-            'authentication-provider'('user-service-ref': 'myUserService')
-            'authentication-provider'('ref': 'authProvider')
-        }
-        bean('authProvider', DaoAuthenticationProvider.class.name, [:], [userDetailsService: 'myUserService'])
-        bean('entryPoint', MockEntryPoint.class.name)
-        bean('myUserService', PostProcessedMockUserDetailsService)
-        bean('userServicePostProcessor', MockUserServiceBeanPostProcessor)
-        bean('nameCollectingPostProcessor', BeanNameCollectingPostProcessor)
-        createAppContext("")
-        def beanPP = appContext.getBean("nameCollectingPostProcessor")
-        Set preInitPPBeans = beanPP.beforeInitPostProcessedBeans
-        Set postInitPPBeans = beanPP.afterInitPostProcessedBeans
-        Set expectedBeans = ['authProvider', 'entryPoint', 'myUserService'] as Set
-
-        expect:
-        appContext.getBean("myUserService").getPostProcessorWasHere() == "Hello from the post processor!"
-        preInitPPBeans.containsAll(expectedBeans)
-        postInitPPBeans.containsAll(expectedBeans)
-    }
-
-    /* SEC-934 */
-    def supportsTwoIdenticalInterceptUrls() {
-        httpAutoConfig {
-            interceptUrl ('/someUrl', 'ROLE_A')
-            interceptUrl ('/someUrl', 'ROLE_B')
-        }
-        createAppContext()
-        def fis = getFilter(FilterSecurityInterceptor)
-        def fids = fis.securityMetadataSource
-        Collection attrs = fids.getAttributes(createFilterinvocation("/someurl", null));
-
-        expect:
-        attrs.size() == 1
-        attrs.contains(new SecurityConfig("ROLE_B"))
-    }
-
-    def supportsExternallyDefinedSecurityContextRepository() {
-        xml.http('create-session': 'always', 'security-context-repository-ref': 'repo') {
-            'http-basic'()
-        }
-        bean('repo', HttpSessionSecurityContextRepository)
-        createAppContext()
-
-        def filter = getFilter(SecurityContextPersistenceFilter)
-
-        expect:
-        filter.repo == appContext.getBean('repo')
-        filter.forceEagerSessionCreation
-    }
-
-    def expressionBasedAccessAllowsAndDeniesAccessAsExpected() {
-        setup:
-        xml.http('auto-config': 'true', 'use-expressions': 'true') {
-            interceptUrl('/secure*', "hasAnyRole('ROLE_A','ROLE_C')")
-            interceptUrl('/**', 'permitAll')
-        }
-        createAppContext()
-
-        def fis = getFilter(FilterSecurityInterceptor)
-        def fids = fis.getSecurityMetadataSource()
-        Collection attrs = fids.getAttributes(createFilterinvocation("/secure", null));
-        assert 1 == attrs.size()
-
-        when: "Unprotected URL"
-        SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("joe", "", "ROLE_A"));
-        fis.invoke(createFilterinvocation("/permitallurl", null));
-        then:
-        notThrown(AccessDeniedException)
-
-        when: "Invoking secure Url as a valid user"
-        fis.invoke(createFilterinvocation("/secure", null));
-        then:
-        notThrown(AccessDeniedException)
-
-        when: "User does not have the required role"
-        SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("joe", "", "ROLE_B"));
-        fis.invoke(createFilterinvocation("/secure", null));
-        then:
-        thrown(AccessDeniedException)
-    }
-
-    def expressionBasedAccessSupportsExternalExpressionHandler() {
-        setup:
-        xml.http('auto-config': 'true', 'use-expressions': 'true') {
-            interceptUrl('/**', "hasPermission('AnyObject','R')")
-            'expression-handler'(ref: 'expressionHandler')
-        }
-        bean('expressionHandler', DefaultWebSecurityExpressionHandler.class.name, [:], [permissionEvaluator: 'pe'])
-        bean('pe', MockPermissionEvaluator)
-        createAppContext()
-
-        def fis = getFilter(FilterSecurityInterceptor)
-
-        when: "Invoking allowed URL protected by hasPermission() expression succeeds"
-        SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("joe", "", "ANY"));
-        fis.invoke(createFilterinvocation("/secure", null));
-        then:
-        notThrown(AccessDeniedException)
-    }
-
-    def protectedLoginPageReportsWarning() {
-        when:
-        xml.http('use-expressions': 'true') {
-            'form-login'('login-page': '/login')
-            interceptUrl('/login*', "hasRole('ROLE_A')")
-        }
-        createAppContext()
-        then:
-        notThrown(BeansException)
-    }
-
-    def disablingUrlRewritingThroughTheNamespaceSetsCorrectPropertyOnContextRepo() {
-        xml.http('auto-config': 'true', 'disable-url-rewriting': 'true')
-        createAppContext()
-
-        expect:
-        getFilter(SecurityContextPersistenceFilter).repo.disableUrlRewriting
-    }
-
-    def userDetailsServiceInParentContextIsLocatedSuccessfully() {
-        when:
-        createAppContext()
-        httpAutoConfig {
-            'remember-me'
-        }
-        appContext = new InMemoryXmlApplicationContext(writer.toString(), appContext)
-
-        then:
-        notThrown(BeansException)
-    }
-
-    def httpConfigWithNoAuthProvidersWorksOk() {
-        when: "Http config has no internal authentication providers"
-        xml.debug()
-        xml.http() {
-            'form-login'()
-            csrf(disabled:true)
-            anonymous(enabled: 'false')
-        }
-        createAppContext()
-        MockHttpServletRequest request = new MockHttpServletRequest("POST", "/login");
-        request.setServletPath("/login");
-        request.addParameter("username", "bob");
-        request.addParameter("password", "bobspassword");
-        then: "App context creation and login request succeed"
-        DebugFilter debugFilter = appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
-        debugFilter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
-        appListener.events.size() == 2
-        appListener.authenticationEvents.size() == 2
-    }
-
-    def eraseCredentialsDefaultsToTrue() {
-        xml.http() {
-            'form-login'()
-        }
-        createAppContext()
-        expect:
-        getFilter(UsernamePasswordAuthenticationFilter).authenticationManager.eraseCredentialsAfterAuthentication
-    }
-
-    def eraseCredentialsIsSetFromParentAuthenticationManager() {
-        xml.http() {
-            'form-login'()
-        }
-        createAppContext("<authentication-manager erase-credentials='false' />");
-        expect:
-        !getFilter(UsernamePasswordAuthenticationFilter).authenticationManager.eraseCredentialsAfterAuthentication
-    }
-
-    def 'SEC-2020 authentication-manager@erase-credentials with http@authentication-manager-ref'() {
-        xml.http('authentication-manager-ref':'authMgr') {
-            'form-login'()
-        }
-        createAppContext("<authentication-manager id='authMgr' erase-credentials='false' />");
-        expect:
-        def authManager = getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
-        !authManager.eraseCredentialsAfterAuthentication
-        !authManager.parent.eraseCredentialsAfterAuthentication
-    }
-
-    def 'authentication-manager@erase-credentials with http@authentication-manager-ref not ProviderManager'() {
-        xml.http('authentication-manager-ref':'authMgr') {
-            'form-login'()
-        }
-        xml.'b:bean'(id: 'authMgr', 'class': MockAuthenticationManager.class.name)
-        createAppContext()
-        expect:
-        def authManager = getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
-        !authManager.eraseCredentialsAfterAuthentication
-        authManager.parent instanceof MockAuthenticationManager
-    }
-
-    def jeeFilterExtractsExpectedRoles() {
-        xml.http() {
-            jee('mappable-roles': 'admin,user,a,b,c')
-        }
-        createAppContext()
-        FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
-        Principal p = Mock(Principal)
-        p.getName() >> 'joe'
-
-        when:
-
-        MockHttpServletRequest request = new MockHttpServletRequest("GET","/something")
-        request.setUserPrincipal(p)
-        request.addUserRole('admin')
-        request.addUserRole('user')
-        request.addUserRole('c')
-        request.addUserRole('notmapped')
-        fcp.doFilter(request, new MockHttpServletResponse(), new MockFilterChain())
-        SecurityContext ctx = request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
-        Set<String> roles = AuthorityUtils.authorityListToSet(ctx.getAuthentication().getAuthorities());
-
-        then:
-        roles.size() == 3
-        roles.contains 'ROLE_admin'
-        roles.contains 'ROLE_user'
-        roles.contains 'ROLE_c'
-    }
-
-    def authenticationDetailsSourceInjectionSucceeds() {
-        xml.http() {
-            'form-login'('authentication-details-source-ref' : 'adsr')
-            'openid-login' ('authentication-details-source-ref' : 'adsr')
-            'http-basic' ('authentication-details-source-ref' : 'adsr')
-            'x509' ('authentication-details-source-ref' : 'adsr')
-        }
-        bean('adsr', 'org.springframework.security.web.authentication.WebAuthenticationDetailsSource')
-        createAppContext()
-        def adsr = appContext.getBean('adsr')
-        expect:
-        getFilter(UsernamePasswordAuthenticationFilter).authenticationDetailsSource == adsr
-        getFilter(OpenIDAuthenticationFilter).authenticationDetailsSource == adsr
-        getFilter(BasicAuthenticationFilter).authenticationDetailsSource == adsr
-        getFilter(X509AuthenticationFilter).authenticationDetailsSource == adsr
-    }
-
-    def includeJaasApiIntegrationFilter() {
-        xml.http(['auto-config':'true','jaas-api-provision':'true'])
-        createAppContext()
-        expect:
-        getFilter(JaasApiIntegrationFilter.class) != null
-    }
-
-    def httpFirewallInjectionIsSupported() {
-        xml.'http-firewall'(ref: 'fw')
-        xml.http() {
-           'form-login'()
-        }
-        bean('fw', DefaultHttpFirewall)
-        createAppContext()
-        FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
-        expect:
-        fcp.firewall == appContext.getBean('fw')
-    }
-
-    def customAccessDecisionManagerIsSupported() {
-        xml.http('auto-config': 'true', 'access-decision-manager-ref': 'adm')
-        xml.'b:bean'(id: 'adm', 'class': AffirmativeBased.class.name) {
-            'b:constructor-arg' {
-                'b:list'() {
-                    'b:bean'('class': RoleVoter.class.name)
-                    'b:bean'('class': RoleVoter.class.name)
-                    'b:bean'('class': RoleVoter.class.name)
-                    'b:bean'('class': WebExpressionVoter.class.name)
-                }
-            }
-        }
-        createAppContext()
-        expect:
-        getFilter(FilterSecurityInterceptor.class).accessDecisionManager.decisionVoters[3] instanceof WebExpressionVoter
-    }
-
-    def customAuthenticationManagerIsSupported() {
-        xml.http('auto-config': 'true', 'authentication-manager-ref': 'am')
-        xml.'b:bean'(id: 'am', 'class': MockAuthenticationManager.class.name)
-        createAppContext("")
-        expect:
-        getFilter(UsernamePasswordAuthenticationFilter.class).authenticationManager.parent instanceof MockAuthenticationManager
-    }
-
-    // SEC-1893
-    def customPortMappings() {
-        when: 'A custom port-mappings is registered'
-        def expectedHttpsPortMappings = [8443:8080]
-        xml.http('auto-config': 'true') {
-            'intercept-url'('pattern':'/**','requires-channel':'https')
-            'port-mappings' {
-                'port-mapping'(http:'8443',https:'8080')
-            }
-        }
-        createAppContext()
-
-        then: 'All the components created by the namespace use that port mapping'
-        getFilter(RequestCacheAwareFilter.class).requestCache.portResolver.portMapper.httpsPortMappings == expectedHttpsPortMappings
-
-        def channelProcessors = getFilter(ChannelProcessingFilter.class).channelDecisionManager.channelProcessors
-        channelProcessors.size() == 2
-        channelProcessors.each { cp->
-            cp.entryPoint.portMapper.httpsPortMappings == expectedHttpsPortMappings
-            cp.entryPoint.portResolver.portMapper.httpsPortMappings == expectedHttpsPortMappings
-        }
-
-        def authEntryPoint = getFilter(ExceptionTranslationFilter.class).authenticationEntryPoint
-        authEntryPoint.portMapper.httpsPortMappings == expectedHttpsPortMappings
-        authEntryPoint.portResolver.portMapper.httpsPortMappings == expectedHttpsPortMappings
-    }
+	def oncePerRequestAttributeIsSupported() {
+		xml.http('once-per-request': 'false') {
+			'http-basic'()
+		}
+		createAppContext()
+
+		expect:
+		!getFilter(FilterSecurityInterceptor).isObserveOncePerRequest()
+	}
+
+	def httpBasicSupportsSeparateEntryPoint() {
+		xml.http() {
+			'http-basic'('entry-point-ref': 'ep')
+		}
+		bean('ep', BasicAuthenticationEntryPoint.class.name, ['realmName':'whocares'],[:])
+		createAppContext();
+
+		def baf = getFilter(BasicAuthenticationFilter)
+		def etf = getFilter(ExceptionTranslationFilter)
+		def ep = appContext.getBean("ep")
+
+		expect:
+		baf.authenticationEntryPoint == ep
+		// Since no other authentication system is in use, this should also end up on the ETF
+		etf.authenticationEntryPoint == ep
+	}
+
+	def interceptUrlWithRequiresChannelAddsChannelFilterToStack() {
+		httpAutoConfig {
+			'intercept-url'(pattern: '/**', 'requires-channel': 'https')
+		}
+		createAppContext();
+		List filters = getFilters("/someurl");
+
+		expect:
+		filters.size() == AUTO_CONFIG_FILTERS + 1
+		filters[0] instanceof ChannelProcessingFilter
+	}
+
+	def portMappingsAreParsedCorrectly() {
+		httpAutoConfig {
+			'port-mappings'() {
+				'port-mapping'(http: '9080', https: '9443')
+			}
+		}
+		createAppContext();
+
+		def pm = (appContext.getBeansOfType(PortMapperImpl).values() as List)[0];
+
+		expect:
+		pm.getTranslatedPortMappings().size() == 1
+		pm.lookupHttpPort(9443) == 9080
+		pm.lookupHttpsPort(9080) == 9443
+	}
+
+	def externalFiltersAreTreatedCorrectly() {
+		httpAutoConfig {
+			'custom-filter'(position: 'FIRST', ref: '${customFilterRef}')
+			'custom-filter'(after: 'LOGOUT_FILTER', ref: 'userFilter')
+			'custom-filter'(before: 'SECURITY_CONTEXT_FILTER', ref: 'userFilter1')
+		}
+		bean('phc', PropertyPlaceholderConfigurer)
+		bean('userFilter', SecurityContextHolderAwareRequestFilter)
+		bean('userFilter1', SecurityContextPersistenceFilter)
+
+		System.setProperty('customFilterRef', 'userFilter')
+		createAppContext();
+
+		def filters = getFilters("/someurl");
+
+		expect:
+		AUTO_CONFIG_FILTERS + 3 == filters.size();
+		filters[0] instanceof SecurityContextHolderAwareRequestFilter
+		filters[1] instanceof SecurityContextPersistenceFilter
+		filters[7] instanceof SecurityContextHolderAwareRequestFilter
+		filters[1] instanceof SecurityContextPersistenceFilter
+	}
+
+	def twoFiltersWithSameOrderAreRejected() {
+		when:
+		httpAutoConfig {
+			'custom-filter'(position: 'LOGOUT_FILTER', ref: 'userFilter')
+		}
+		bean('userFilter', SecurityContextHolderAwareRequestFilter)
+		createAppContext();
+
+		then:
+		thrown(BeanDefinitionParsingException)
+	}
+
+	def x509SupportAddsFilterAtExpectedPosition() {
+		httpAutoConfig {
+			x509()
+		}
+		createAppContext()
+
+		expect:
+		getFilters("/someurl")[5] instanceof X509AuthenticationFilter
+	}
+
+	def x509SubjectPrincipalRegexCanBeSetUsingPropertyPlaceholder() {
+		httpAutoConfig {
+			x509('subject-principal-regex':'${subject-principal-regex}')
+		}
+		bean('phc', PropertyPlaceholderConfigurer.class.name)
+		System.setProperty("subject-principal-regex", "uid=(.*),");
+		createAppContext()
+		def filter = getFilter(X509AuthenticationFilter)
+
+		expect:
+		filter.principalExtractor.subjectDnPattern.pattern() == "uid=(.*),"
+	}
+
+	def invalidLogoutSuccessUrlIsDetected() {
+		when:
+		xml.http {
+			'form-login'()
+			'logout'('logout-success-url': 'noLeadingSlash')
+		}
+		createAppContext()
+
+		then:
+		BeanCreationException e = thrown()
+	}
+
+	def cookiesToDeleteOnLogoutUrlAddsCorrectLogoutHandler() {
+		xml.http {
+			'logout'('delete-cookies': 'JSESSIONID, mycookie')
+			'form-login'()
+		}
+		createAppContext()
+		def handlers = getFilter(LogoutFilter).handlers
+
+		expect:
+		handlers[2] instanceof CookieClearingLogoutHandler
+		handlers[2].cookiesToClear[0] == 'JSESSIONID'
+		handlers[2].cookiesToClear[1] == 'mycookie'
+	}
+
+	def logoutSuccessHandlerIsSetCorrectly() {
+		xml.http {
+			'form-login'()
+			'logout'('success-handler-ref': 'logoutHandler')
+		}
+		bean('logoutHandler', SimpleUrlLogoutSuccessHandler)
+		createAppContext()
+
+		LogoutFilter filter = getFilter(LogoutFilter);
+
+		expect:
+		FieldUtils.getFieldValue(filter, "logoutSuccessHandler") == appContext.getBean("logoutHandler")
+	}
+
+	def externalRequestCacheIsConfiguredCorrectly() {
+		httpAutoConfig {
+			'request-cache'(ref: 'cache')
+		}
+		bean('cache', HttpSessionRequestCache.class.name)
+		createAppContext()
+
+		expect:
+		appContext.getBean("cache") == getFilter(ExceptionTranslationFilter.class).requestCache
+	}
+
+	def customEntryPointIsSupported() {
+		xml.http('auto-config': 'true', 'entry-point-ref': 'entryPoint') {}
+		bean('entryPoint', MockEntryPoint.class.name)
+		createAppContext()
+
+		expect:
+		getFilter(ExceptionTranslationFilter).getAuthenticationEntryPoint() instanceof MockEntryPoint
+	}
+
+	/**
+	 * See SEC-750. If the http security post processor causes beans to be instantiated too eagerly, they way miss
+	 * additional processing. In this method we have a UserDetailsService which is referenced from the namespace
+	 * and also has a post processor registered which will modify it.
+	 */
+	def httpElementDoesntInterfereWithBeanPostProcessing() {
+		xml.http('auto-config': 'true', 'entry-point-ref': 'entryPoint') {}
+		xml.'authentication-manager'() {
+			'authentication-provider'('user-service-ref': 'myUserService')
+			'authentication-provider'('ref': 'authProvider')
+		}
+		bean('authProvider', DaoAuthenticationProvider.class.name, [:], [userDetailsService: 'myUserService'])
+		bean('entryPoint', MockEntryPoint.class.name)
+		bean('myUserService', PostProcessedMockUserDetailsService)
+		bean('userServicePostProcessor', MockUserServiceBeanPostProcessor)
+		bean('nameCollectingPostProcessor', BeanNameCollectingPostProcessor)
+		createAppContext("")
+		def beanPP = appContext.getBean("nameCollectingPostProcessor")
+		Set preInitPPBeans = beanPP.beforeInitPostProcessedBeans
+		Set postInitPPBeans = beanPP.afterInitPostProcessedBeans
+		Set expectedBeans = ['authProvider', 'entryPoint', 'myUserService'] as Set
+
+		expect:
+		appContext.getBean("myUserService").getPostProcessorWasHere() == "Hello from the post processor!"
+		preInitPPBeans.containsAll(expectedBeans)
+		postInitPPBeans.containsAll(expectedBeans)
+	}
+
+	/* SEC-934 */
+	def supportsTwoIdenticalInterceptUrls() {
+		httpAutoConfig {
+			interceptUrl ('/someUrl', 'ROLE_A')
+			interceptUrl ('/someUrl', 'ROLE_B')
+		}
+		createAppContext()
+		def fis = getFilter(FilterSecurityInterceptor)
+		def fids = fis.securityMetadataSource
+		Collection attrs = fids.getAttributes(createFilterinvocation("/someurl", null));
+
+		expect:
+		attrs.size() == 1
+		attrs.contains(new SecurityConfig("ROLE_B"))
+	}
+
+	def supportsExternallyDefinedSecurityContextRepository() {
+		xml.http('create-session': 'always', 'security-context-repository-ref': 'repo') {
+			'http-basic'()
+		}
+		bean('repo', HttpSessionSecurityContextRepository)
+		createAppContext()
+
+		def filter = getFilter(SecurityContextPersistenceFilter)
+
+		expect:
+		filter.repo == appContext.getBean('repo')
+		filter.forceEagerSessionCreation
+	}
+
+	def expressionBasedAccessAllowsAndDeniesAccessAsExpected() {
+		setup:
+		xml.http('auto-config': 'true', 'use-expressions': 'true') {
+			interceptUrl('/secure*', "hasAnyRole('ROLE_A','ROLE_C')")
+			interceptUrl('/**', 'permitAll')
+		}
+		createAppContext()
+
+		def fis = getFilter(FilterSecurityInterceptor)
+		def fids = fis.getSecurityMetadataSource()
+		Collection attrs = fids.getAttributes(createFilterinvocation("/secure", null));
+		assert 1 == attrs.size()
+
+		when: "Unprotected URL"
+		SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("joe", "", "ROLE_A"));
+		fis.invoke(createFilterinvocation("/permitallurl", null));
+		then:
+		notThrown(AccessDeniedException)
+
+		when: "Invoking secure Url as a valid user"
+		fis.invoke(createFilterinvocation("/secure", null));
+		then:
+		notThrown(AccessDeniedException)
+
+		when: "User does not have the required role"
+		SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("joe", "", "ROLE_B"));
+		fis.invoke(createFilterinvocation("/secure", null));
+		then:
+		thrown(AccessDeniedException)
+	}
+
+	def expressionBasedAccessSupportsExternalExpressionHandler() {
+		setup:
+		xml.http('auto-config': 'true', 'use-expressions': 'true') {
+			interceptUrl('/**', "hasPermission('AnyObject','R')")
+			'expression-handler'(ref: 'expressionHandler')
+		}
+		bean('expressionHandler', DefaultWebSecurityExpressionHandler.class.name, [:], [permissionEvaluator: 'pe'])
+		bean('pe', MockPermissionEvaluator)
+		createAppContext()
+
+		def fis = getFilter(FilterSecurityInterceptor)
+
+		when: "Invoking allowed URL protected by hasPermission() expression succeeds"
+		SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("joe", "", "ANY"));
+		fis.invoke(createFilterinvocation("/secure", null));
+		then:
+		notThrown(AccessDeniedException)
+	}
+
+	def protectedLoginPageReportsWarning() {
+		when:
+		xml.http('use-expressions': 'true') {
+			'form-login'('login-page': '/login')
+			interceptUrl('/login*', "hasRole('ROLE_A')")
+		}
+		createAppContext()
+		then:
+		notThrown(BeansException)
+	}
+
+	def disablingUrlRewritingThroughTheNamespaceSetsCorrectPropertyOnContextRepo() {
+		xml.http('auto-config': 'true', 'disable-url-rewriting': 'true')
+		createAppContext()
+
+		expect:
+		getFilter(SecurityContextPersistenceFilter).repo.disableUrlRewriting
+	}
+
+	def userDetailsServiceInParentContextIsLocatedSuccessfully() {
+		when:
+		createAppContext()
+		httpAutoConfig {
+			'remember-me'
+		}
+		appContext = new InMemoryXmlApplicationContext(writer.toString(), appContext)
+
+		then:
+		notThrown(BeansException)
+	}
+
+	def httpConfigWithNoAuthProvidersWorksOk() {
+		when: "Http config has no internal authentication providers"
+		xml.debug()
+		xml.http() {
+			'form-login'()
+			csrf(disabled:true)
+			anonymous(enabled: 'false')
+		}
+		createAppContext()
+		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/login");
+		request.setServletPath("/login");
+		request.addParameter("username", "bob");
+		request.addParameter("password", "bobspassword");
+		then: "App context creation and login request succeed"
+		DebugFilter debugFilter = appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
+		debugFilter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
+		appListener.events.size() == 2
+		appListener.authenticationEvents.size() == 2
+	}
+
+	def eraseCredentialsDefaultsToTrue() {
+		xml.http() {
+			'form-login'()
+		}
+		createAppContext()
+		expect:
+		getFilter(UsernamePasswordAuthenticationFilter).authenticationManager.eraseCredentialsAfterAuthentication
+	}
+
+	def eraseCredentialsIsSetFromParentAuthenticationManager() {
+		xml.http() {
+			'form-login'()
+		}
+		createAppContext("<authentication-manager erase-credentials='false' />");
+		expect:
+		!getFilter(UsernamePasswordAuthenticationFilter).authenticationManager.eraseCredentialsAfterAuthentication
+	}
+
+	def 'SEC-2020 authentication-manager@erase-credentials with http@authentication-manager-ref'() {
+		xml.http('authentication-manager-ref':'authMgr') {
+			'form-login'()
+		}
+		createAppContext("<authentication-manager id='authMgr' erase-credentials='false' />");
+		expect:
+		def authManager = getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
+		!authManager.eraseCredentialsAfterAuthentication
+		!authManager.parent.eraseCredentialsAfterAuthentication
+	}
+
+	def 'authentication-manager@erase-credentials with http@authentication-manager-ref not ProviderManager'() {
+		xml.http('authentication-manager-ref':'authMgr') {
+			'form-login'()
+		}
+		xml.'b:bean'(id: 'authMgr', 'class': MockAuthenticationManager.class.name)
+		createAppContext()
+		expect:
+		def authManager = getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
+		!authManager.eraseCredentialsAfterAuthentication
+		authManager.parent instanceof MockAuthenticationManager
+	}
+
+	def jeeFilterExtractsExpectedRoles() {
+		xml.http() {
+			jee('mappable-roles': 'admin,user,a,b,c')
+		}
+		createAppContext()
+		FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
+		Principal p = Mock(Principal)
+		p.getName() >> 'joe'
+
+		when:
+
+		MockHttpServletRequest request = new MockHttpServletRequest("GET","/something")
+		request.setUserPrincipal(p)
+		request.addUserRole('admin')
+		request.addUserRole('user')
+		request.addUserRole('c')
+		request.addUserRole('notmapped')
+		fcp.doFilter(request, new MockHttpServletResponse(), new MockFilterChain())
+		SecurityContext ctx = request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
+		Set<String> roles = AuthorityUtils.authorityListToSet(ctx.getAuthentication().getAuthorities());
+
+		then:
+		roles.size() == 3
+		roles.contains 'ROLE_admin'
+		roles.contains 'ROLE_user'
+		roles.contains 'ROLE_c'
+	}
+
+	def authenticationDetailsSourceInjectionSucceeds() {
+		xml.http() {
+			'form-login'('authentication-details-source-ref' : 'adsr')
+			'openid-login' ('authentication-details-source-ref' : 'adsr')
+			'http-basic' ('authentication-details-source-ref' : 'adsr')
+			'x509' ('authentication-details-source-ref' : 'adsr')
+		}
+		bean('adsr', 'org.springframework.security.web.authentication.WebAuthenticationDetailsSource')
+		createAppContext()
+		def adsr = appContext.getBean('adsr')
+		expect:
+		getFilter(UsernamePasswordAuthenticationFilter).authenticationDetailsSource == adsr
+		getFilter(OpenIDAuthenticationFilter).authenticationDetailsSource == adsr
+		getFilter(BasicAuthenticationFilter).authenticationDetailsSource == adsr
+		getFilter(X509AuthenticationFilter).authenticationDetailsSource == adsr
+	}
+
+	def includeJaasApiIntegrationFilter() {
+		xml.http(['auto-config':'true','jaas-api-provision':'true'])
+		createAppContext()
+		expect:
+		getFilter(JaasApiIntegrationFilter.class) != null
+	}
+
+	def httpFirewallInjectionIsSupported() {
+		xml.'http-firewall'(ref: 'fw')
+		xml.http() {
+		   'form-login'()
+		}
+		bean('fw', DefaultHttpFirewall)
+		createAppContext()
+		FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
+		expect:
+		fcp.firewall == appContext.getBean('fw')
+	}
+
+	def customAccessDecisionManagerIsSupported() {
+		xml.http('auto-config': 'true', 'access-decision-manager-ref': 'adm')
+		xml.'b:bean'(id: 'adm', 'class': AffirmativeBased.class.name) {
+			'b:constructor-arg' {
+				'b:list'() {
+					'b:bean'('class': RoleVoter.class.name)
+					'b:bean'('class': RoleVoter.class.name)
+					'b:bean'('class': RoleVoter.class.name)
+					'b:bean'('class': WebExpressionVoter.class.name)
+				}
+			}
+		}
+		createAppContext()
+		expect:
+		getFilter(FilterSecurityInterceptor.class).accessDecisionManager.decisionVoters[3] instanceof WebExpressionVoter
+	}
+
+	def customAuthenticationManagerIsSupported() {
+		xml.http('auto-config': 'true', 'authentication-manager-ref': 'am')
+		xml.'b:bean'(id: 'am', 'class': MockAuthenticationManager.class.name)
+		createAppContext("")
+		expect:
+		getFilter(UsernamePasswordAuthenticationFilter.class).authenticationManager.parent instanceof MockAuthenticationManager
+	}
+
+	// SEC-1893
+	def customPortMappings() {
+		when: 'A custom port-mappings is registered'
+		def expectedHttpsPortMappings = [8443:8080]
+		xml.http('auto-config': 'true') {
+			'intercept-url'('pattern':'/**','requires-channel':'https')
+			'port-mappings' {
+				'port-mapping'(http:'8443',https:'8080')
+			}
+		}
+		createAppContext()
+
+		then: 'All the components created by the namespace use that port mapping'
+		getFilter(RequestCacheAwareFilter.class).requestCache.portResolver.portMapper.httpsPortMappings == expectedHttpsPortMappings
+
+		def channelProcessors = getFilter(ChannelProcessingFilter.class).channelDecisionManager.channelProcessors
+		channelProcessors.size() == 2
+		channelProcessors.each { cp->
+			cp.entryPoint.portMapper.httpsPortMappings == expectedHttpsPortMappings
+			cp.entryPoint.portResolver.portMapper.httpsPortMappings == expectedHttpsPortMappings
+		}
+
+		def authEntryPoint = getFilter(ExceptionTranslationFilter.class).authenticationEntryPoint
+		authEntryPoint.portMapper.httpsPortMappings == expectedHttpsPortMappings
+		authEntryPoint.portResolver.portMapper.httpsPortMappings == expectedHttpsPortMappings
+	}
 }
 
 class MockAuthenticationManager implements AuthenticationManager {
-    Authentication authenticate(Authentication authentication) {
-        return null
-    }
+	Authentication authenticate(Authentication authentication) {
+		return null
+	}
 }
 
 class MockPermissionEvaluator implements PermissionEvaluator {
-    boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
-        return true
-    }
+	boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
+		return true
+	}
 
-    boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
-        return true
-    }
+	boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
+		return true
+	}
 
 }
 
 class MockEntryPoint extends LoginUrlAuthenticationEntryPoint {
-    public MockEntryPoint() {
-        super("/notused");
-    }
+	public MockEntryPoint() {
+		super("/notused");
+	}
 }

+ 94 - 94
config/src/test/groovy/org/springframework/security/config/http/MultiHttpBlockConfigTests.groovy

@@ -24,110 +24,110 @@ import org.springframework.security.web.SecurityFilterChain
  */
 class MultiHttpBlockConfigTests extends AbstractHttpConfigTests {
 
-    def multipleHttpElementsAreSupported () {
-        when: "Two <http> elements are used"
-        xml.http(pattern: '/stateless/**', 'create-session': 'stateless') {
-            'http-basic'()
-        }
-        xml.http(pattern: '/stateful/**') {
-            'form-login'()
-        }
-        createAppContext()
-        FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
-        def filterChains = fcp.getFilterChains();
+	def multipleHttpElementsAreSupported () {
+		when: "Two <http> elements are used"
+		xml.http(pattern: '/stateless/**', 'create-session': 'stateless') {
+			'http-basic'()
+		}
+		xml.http(pattern: '/stateful/**') {
+			'form-login'()
+		}
+		createAppContext()
+		FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
+		def filterChains = fcp.getFilterChains();
 
-        then:
-        filterChains.size() == 2
-        filterChains[0].requestMatcher.pattern == '/stateless/**'
-    }
+		then:
+		filterChains.size() == 2
+		filterChains[0].requestMatcher.pattern == '/stateless/**'
+	}
 
-    def duplicateHttpElementsAreRejected () {
-        when: "Two <http> elements are used"
-        xml.http('create-session': 'stateless') {
-            'http-basic'()
-        }
-        xml.http() {
-            'form-login'()
-        }
-        createAppContext()
-        then:
-        BeanCreationException e = thrown()
-        e.cause instanceof IllegalArgumentException
-    }
+	def duplicateHttpElementsAreRejected () {
+		when: "Two <http> elements are used"
+		xml.http('create-session': 'stateless') {
+			'http-basic'()
+		}
+		xml.http() {
+			'form-login'()
+		}
+		createAppContext()
+		then:
+		BeanCreationException e = thrown()
+		e.cause instanceof IllegalArgumentException
+	}
 
-    def duplicatePatternsAreRejected () {
-        when: "Two <http> elements with the same pattern are used"
-        xml.http(pattern: '/stateless/**', 'create-session': 'stateless') {
-            'http-basic'()
-        }
-        xml.http(pattern: '/stateless/**') {
-            'form-login'()
-        }
-        createAppContext()
-        then:
-        BeanCreationException e = thrown()
-        e.cause instanceof IllegalArgumentException
-    }
+	def duplicatePatternsAreRejected () {
+		when: "Two <http> elements with the same pattern are used"
+		xml.http(pattern: '/stateless/**', 'create-session': 'stateless') {
+			'http-basic'()
+		}
+		xml.http(pattern: '/stateless/**') {
+			'form-login'()
+		}
+		createAppContext()
+		then:
+		BeanCreationException e = thrown()
+		e.cause instanceof IllegalArgumentException
+	}
 
 
-    def 'SEC-1937: http@authentication-manager-ref and multi authentication-mananager'() {
-        setup:
-            xml.http('authentication-manager-ref' : 'authManager', 'pattern' : '/first/**') {
-                'form-login'('login-processing-url': '/first/login')
-                csrf(disabled:true)
-            }
-            xml.http('authentication-manager-ref' : 'authManager2') {
-                'form-login'()
-                csrf(disabled:true)
-            }
-            mockBean(UserDetailsService,'uds')
-            mockBean(UserDetailsService,'uds2')
-            createAppContext("""
+	def 'SEC-1937: http@authentication-manager-ref and multi authentication-mananager'() {
+		setup:
+			xml.http('authentication-manager-ref' : 'authManager', 'pattern' : '/first/**') {
+				'form-login'('login-processing-url': '/first/login')
+				csrf(disabled:true)
+			}
+			xml.http('authentication-manager-ref' : 'authManager2') {
+				'form-login'()
+				csrf(disabled:true)
+			}
+			mockBean(UserDetailsService,'uds')
+			mockBean(UserDetailsService,'uds2')
+			createAppContext("""
 <authentication-manager id="authManager">
-    <authentication-provider user-service-ref="uds" />
+	<authentication-provider user-service-ref="uds" />
 </authentication-manager>
 <authentication-manager id="authManager2">
-    <authentication-provider user-service-ref="uds2" />
+	<authentication-provider user-service-ref="uds2" />
 </authentication-manager>
 """)
-            UserDetailsService uds = appContext.getBean('uds')
-            UserDetailsService uds2 = appContext.getBean('uds2')
-        when:
-            MockHttpServletRequest request = new MockHttpServletRequest()
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            MockFilterChain chain = new MockFilterChain()
-            request.servletPath = "/first/login"
-            request.requestURI = "/first/login"
-            request.method = 'POST'
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            verify(uds).loadUserByUsername(anyString()) || true
-            verifyZeroInteractions(uds2) || true
-        when:
-            MockHttpServletRequest request2 = new MockHttpServletRequest()
-            MockHttpServletResponse response2 = new MockHttpServletResponse()
-            MockFilterChain chain2 = new MockFilterChain()
-            request2.servletPath = "/login"
-            request2.requestURI = "/login"
-            request2.method = 'POST'
-            springSecurityFilterChain.doFilter(request2,response2,chain2)
-        then:
-            verify(uds2).loadUserByUsername(anyString()) || true
-            verifyNoMoreInteractions(uds) || true
-    }
+			UserDetailsService uds = appContext.getBean('uds')
+			UserDetailsService uds2 = appContext.getBean('uds2')
+		when:
+			MockHttpServletRequest request = new MockHttpServletRequest()
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			MockFilterChain chain = new MockFilterChain()
+			request.servletPath = "/first/login"
+			request.requestURI = "/first/login"
+			request.method = 'POST'
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			verify(uds).loadUserByUsername(anyString()) || true
+			verifyZeroInteractions(uds2) || true
+		when:
+			MockHttpServletRequest request2 = new MockHttpServletRequest()
+			MockHttpServletResponse response2 = new MockHttpServletResponse()
+			MockFilterChain chain2 = new MockFilterChain()
+			request2.servletPath = "/login"
+			request2.requestURI = "/login"
+			request2.method = 'POST'
+			springSecurityFilterChain.doFilter(request2,response2,chain2)
+		then:
+			verify(uds2).loadUserByUsername(anyString()) || true
+			verifyNoMoreInteractions(uds) || true
+	}
 
-    def multipleAuthenticationManagersWorks () {
-        xml.http(name: 'basic', pattern: '/basic/**', ) {
-            'http-basic'()
-        }
-        xml.http(pattern: '/form/**') {
-            'form-login'()
-        }
-        createAppContext()
-        FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
-        SecurityFilterChain basicChain = fcp.filterChains[0];
+	def multipleAuthenticationManagersWorks () {
+		xml.http(name: 'basic', pattern: '/basic/**', ) {
+			'http-basic'()
+		}
+		xml.http(pattern: '/form/**') {
+			'form-login'()
+		}
+		createAppContext()
+		FilterChainProxy fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
+		SecurityFilterChain basicChain = fcp.filterChains[0];
 
-        expect:
-        Assert.assertSame (basicChain, appContext.getBean('basic'))
-    }
+		expect:
+		Assert.assertSame (basicChain, appContext.getBean('basic'))
+	}
 }

+ 136 - 136
config/src/test/groovy/org/springframework/security/config/http/PlaceHolderAndELConfigTests.groovy

@@ -17,140 +17,140 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
 
 class PlaceHolderAndELConfigTests extends AbstractHttpConfigTests {
 
-    def setup() {
-        // Add a PropertyPlaceholderConfigurer to the context for all the tests
-        bean(PropertyPlaceholderConfigurer.class.name, PropertyPlaceholderConfigurer.class)
-    }
-
-    def unsecuredPatternSupportsPlaceholderForPattern() {
-        System.setProperty("pattern.nofilters", "/unprotected");
-
-        xml.http(pattern: '${pattern.nofilters}', security: 'none')
-        httpAutoConfig() {
-            interceptUrl('/**', 'ROLE_A')
-        }
-        createAppContext()
-
-        List filters = getFilters("/unprotected");
-
-        expect:
-        filters.size() == 0
-    }
-
-    // SEC-1201
-    def interceptUrlsAndFormLoginSupportPropertyPlaceholders() {
-        System.setProperty("secure.Url", "/Secure");
-        System.setProperty("secure.role", "ROLE_A");
-        System.setProperty("login.page", "/loginPage");
-        System.setProperty("default.target", "/defaultTarget");
-        System.setProperty("auth.failure", "/authFailure");
-
-        xml.http(pattern: '${login.page}', security: 'none')
-        xml.http('use-expressions':false) {
-            interceptUrl('${secure.Url}', '${secure.role}')
-            'form-login'('login-page':'${login.page}', 'default-target-url': '${default.target}',
-                'authentication-failure-url':'${auth.failure}');
-        }
-        createAppContext();
-
-        expect:
-        propertyValuesMatchPlaceholders()
-        getFilters("/loginPage").size() == 0
-    }
-
-    // SEC-1309
-    def interceptUrlsAndFormLoginSupportEL() {
-        System.setProperty("secure.url", "/Secure");
-        System.setProperty("secure.role", "ROLE_A");
-        System.setProperty("login.page", "/loginPage");
-        System.setProperty("default.target", "/defaultTarget");
-        System.setProperty("auth.failure", "/authFailure");
-
-        xml.http('use-expressions':false) {
-            interceptUrl("#{systemProperties['secure.url']}", "#{systemProperties['secure.role']}")
-            'form-login'('login-page':"#{systemProperties['login.page']}", 'default-target-url': "#{systemProperties['default.target']}",
-                'authentication-failure-url':"#{systemProperties['auth.failure']}");
-        }
-        createAppContext()
-
-        expect:
-        propertyValuesMatchPlaceholders()
-    }
-
-    private void propertyValuesMatchPlaceholders() {
-        // Check the security attribute
-        def fis = getFilter(FilterSecurityInterceptor);
-        def fids = fis.getSecurityMetadataSource();
-        Collection attrs = fids.getAttributes(createFilterinvocation("/secure", null));
-        assert attrs.size() == 1
-        assert attrs.contains(new SecurityConfig("ROLE_A"))
-
-        // Check the form login properties are set
-        def apf = getFilter(UsernamePasswordAuthenticationFilter)
-        assert FieldUtils.getFieldValue(apf, "successHandler.defaultTargetUrl") == '/defaultTarget'
-        assert "/authFailure" == FieldUtils.getFieldValue(apf, "failureHandler.defaultFailureUrl")
-
-        def etf = getFilter(ExceptionTranslationFilter)
-        assert "/loginPage"== etf.authenticationEntryPoint.loginFormUrl
-    }
-
-    def portMappingsWorkWithPlaceholdersAndEL() {
-        System.setProperty("http", "9080");
-        System.setProperty("https", "9443");
-
-        httpAutoConfig {
-            'port-mappings'() {
-                'port-mapping'(http: '#{systemProperties.http}', https: '${https}')
-            }
-        }
-        createAppContext();
-
-        def pm = (appContext.getBeansOfType(PortMapperImpl).values() as List)[0];
-
-        expect:
-        pm.getTranslatedPortMappings().size() == 1
-        pm.lookupHttpPort(9443) == 9080
-        pm.lookupHttpsPort(9080) == 9443
-    }
-
-    def requiresChannelSupportsPlaceholder() {
-        System.setProperty("secure.url", "/secure");
-        System.setProperty("required.channel", "https");
-
-        httpAutoConfig {
-            'intercept-url'(pattern: '${secure.url}', 'requires-channel': '${required.channel}')
-        }
-        createAppContext();
-        List filters = getFilters("/secure");
-
-        expect:
-        filters.size() == AUTO_CONFIG_FILTERS + 1
-        filters[0] instanceof ChannelProcessingFilter
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        request.setServletPath("/secure");
-        MockHttpServletResponse response = new MockHttpServletResponse();
-        filters[0].doFilter(request, response, new MockFilterChain());
-        response.getRedirectedUrl().startsWith("https")
-    }
-
-    def accessDeniedPageWorksWithPlaceholders() {
-        System.setProperty("accessDenied", "/go-away");
-        xml.http('auto-config': 'true') {
-            'access-denied-handler'('error-page' : '${accessDenied}') {}
-        }
-        createAppContext();
-
-        expect:
-        FieldUtils.getFieldValue(getFilter(ExceptionTranslationFilter.class), "accessDeniedHandler.errorPage") == '/go-away'
-    }
-
-    def accessDeniedHandlerPageWorksWithEL() {
-        httpAutoConfig {
-            'access-denied-handler'('error-page': "#{'/go' + '-away'}")
-        }
-        createAppContext()
-
-        expect:
-        getFilter(ExceptionTranslationFilter).accessDeniedHandler.errorPage == '/go-away'
-    }
+	def setup() {
+		// Add a PropertyPlaceholderConfigurer to the context for all the tests
+		bean(PropertyPlaceholderConfigurer.class.name, PropertyPlaceholderConfigurer.class)
+	}
+
+	def unsecuredPatternSupportsPlaceholderForPattern() {
+		System.setProperty("pattern.nofilters", "/unprotected");
+
+		xml.http(pattern: '${pattern.nofilters}', security: 'none')
+		httpAutoConfig() {
+			interceptUrl('/**', 'ROLE_A')
+		}
+		createAppContext()
+
+		List filters = getFilters("/unprotected");
+
+		expect:
+		filters.size() == 0
+	}
+
+	// SEC-1201
+	def interceptUrlsAndFormLoginSupportPropertyPlaceholders() {
+		System.setProperty("secure.Url", "/Secure");
+		System.setProperty("secure.role", "ROLE_A");
+		System.setProperty("login.page", "/loginPage");
+		System.setProperty("default.target", "/defaultTarget");
+		System.setProperty("auth.failure", "/authFailure");
+
+		xml.http(pattern: '${login.page}', security: 'none')
+		xml.http('use-expressions':false) {
+			interceptUrl('${secure.Url}', '${secure.role}')
+			'form-login'('login-page':'${login.page}', 'default-target-url': '${default.target}',
+				'authentication-failure-url':'${auth.failure}');
+		}
+		createAppContext();
+
+		expect:
+		propertyValuesMatchPlaceholders()
+		getFilters("/loginPage").size() == 0
+	}
+
+	// SEC-1309
+	def interceptUrlsAndFormLoginSupportEL() {
+		System.setProperty("secure.url", "/Secure");
+		System.setProperty("secure.role", "ROLE_A");
+		System.setProperty("login.page", "/loginPage");
+		System.setProperty("default.target", "/defaultTarget");
+		System.setProperty("auth.failure", "/authFailure");
+
+		xml.http('use-expressions':false) {
+			interceptUrl("#{systemProperties['secure.url']}", "#{systemProperties['secure.role']}")
+			'form-login'('login-page':"#{systemProperties['login.page']}", 'default-target-url': "#{systemProperties['default.target']}",
+				'authentication-failure-url':"#{systemProperties['auth.failure']}");
+		}
+		createAppContext()
+
+		expect:
+		propertyValuesMatchPlaceholders()
+	}
+
+	private void propertyValuesMatchPlaceholders() {
+		// Check the security attribute
+		def fis = getFilter(FilterSecurityInterceptor);
+		def fids = fis.getSecurityMetadataSource();
+		Collection attrs = fids.getAttributes(createFilterinvocation("/secure", null));
+		assert attrs.size() == 1
+		assert attrs.contains(new SecurityConfig("ROLE_A"))
+
+		// Check the form login properties are set
+		def apf = getFilter(UsernamePasswordAuthenticationFilter)
+		assert FieldUtils.getFieldValue(apf, "successHandler.defaultTargetUrl") == '/defaultTarget'
+		assert "/authFailure" == FieldUtils.getFieldValue(apf, "failureHandler.defaultFailureUrl")
+
+		def etf = getFilter(ExceptionTranslationFilter)
+		assert "/loginPage"== etf.authenticationEntryPoint.loginFormUrl
+	}
+
+	def portMappingsWorkWithPlaceholdersAndEL() {
+		System.setProperty("http", "9080");
+		System.setProperty("https", "9443");
+
+		httpAutoConfig {
+			'port-mappings'() {
+				'port-mapping'(http: '#{systemProperties.http}', https: '${https}')
+			}
+		}
+		createAppContext();
+
+		def pm = (appContext.getBeansOfType(PortMapperImpl).values() as List)[0];
+
+		expect:
+		pm.getTranslatedPortMappings().size() == 1
+		pm.lookupHttpPort(9443) == 9080
+		pm.lookupHttpsPort(9080) == 9443
+	}
+
+	def requiresChannelSupportsPlaceholder() {
+		System.setProperty("secure.url", "/secure");
+		System.setProperty("required.channel", "https");
+
+		httpAutoConfig {
+			'intercept-url'(pattern: '${secure.url}', 'requires-channel': '${required.channel}')
+		}
+		createAppContext();
+		List filters = getFilters("/secure");
+
+		expect:
+		filters.size() == AUTO_CONFIG_FILTERS + 1
+		filters[0] instanceof ChannelProcessingFilter
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		request.setServletPath("/secure");
+		MockHttpServletResponse response = new MockHttpServletResponse();
+		filters[0].doFilter(request, response, new MockFilterChain());
+		response.getRedirectedUrl().startsWith("https")
+	}
+
+	def accessDeniedPageWorksWithPlaceholders() {
+		System.setProperty("accessDenied", "/go-away");
+		xml.http('auto-config': 'true') {
+			'access-denied-handler'('error-page' : '${accessDenied}') {}
+		}
+		createAppContext();
+
+		expect:
+		FieldUtils.getFieldValue(getFilter(ExceptionTranslationFilter.class), "accessDeniedHandler.errorPage") == '/go-away'
+	}
+
+	def accessDeniedHandlerPageWorksWithEL() {
+		httpAutoConfig {
+			'access-denied-handler'('error-page': "#{'/go' + '-away'}")
+		}
+		createAppContext()
+
+		expect:
+		getFilter(ExceptionTranslationFilter).accessDeniedHandler.errorPage == '/go-away'
+	}
 }

+ 265 - 265
config/src/test/groovy/org/springframework/security/config/http/RememberMeConfigTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -45,268 +45,268 @@ import org.springframework.security.web.authentication.rememberme.TokenBasedReme
  */
 class RememberMeConfigTests extends AbstractHttpConfigTests {
 
-    def rememberMeServiceWorksWithTokenRepoRef() {
-        httpAutoConfig () {
-            'remember-me'('token-repository-ref': 'tokenRepo')
-        }
-        bean('tokenRepo', CustomTokenRepository.class.name)
-
-        createAppContext(AUTH_PROVIDER_XML)
-
-        def rememberMeServices  = rememberMeServices()
-
-        expect:
-        rememberMeServices instanceof PersistentTokenBasedRememberMeServices
-        rememberMeServices.tokenRepository instanceof CustomTokenRepository
-        FieldUtils.getFieldValue(rememberMeServices, "useSecureCookie") == null
-    }
-
-    def rememberMeServiceWorksWithDataSourceRef() {
-        httpAutoConfig () {
-            'remember-me'('data-source-ref': 'ds')
-        }
-        bean('ds', TestDataSource.class.name, ['tokendb'])
-
-        createAppContext(AUTH_PROVIDER_XML)
-
-        def rememberMeServices  = rememberMeServices()
-
-        expect:
-        rememberMeServices instanceof PersistentTokenBasedRememberMeServices
-        rememberMeServices.tokenRepository instanceof JdbcTokenRepositoryImpl
-    }
-
-    def rememberMeServiceWorksWithAuthenticationSuccessHandlerRef() {
-        httpAutoConfig () {
-            'remember-me'('authentication-success-handler-ref': 'sh')
-        }
-        bean('sh', SimpleUrlAuthenticationSuccessHandler.class.name, ['/target'])
-
-        createAppContext(AUTH_PROVIDER_XML)
-
-        expect:
-        getFilter(RememberMeAuthenticationFilter.class).successHandler instanceof SimpleUrlAuthenticationSuccessHandler
-    }
-
-    def rememberMeServiceWorksWithExternalServicesImpl() {
-        httpAutoConfig () {
-            'remember-me'('key': "#{'our' + 'key'}", 'services-ref': 'rms')
-            csrf(disabled:true)
-        }
-        xml.'b:bean'(id: 'rms', 'class': TokenBasedRememberMeServices.class.name) {
-            'b:constructor-arg'(value: 'ourKey')
-            'b:constructor-arg'(ref: 'us')
-            'b:property'(name: 'tokenValiditySeconds', value: '5000')
-        }
-
-        createAppContext(AUTH_PROVIDER_XML)
-
-        List logoutHandlers = FieldUtils.getFieldValue(getFilter(LogoutFilter.class), "handlers");
-        Map ams = appContext.getBeansOfType(ProviderManager.class);
-        ProviderManager am = (ams.values() as List).find { it instanceof ProviderManager && it.providers.size() == 2}
-        RememberMeAuthenticationProvider rmp = am.providers.find { it instanceof RememberMeAuthenticationProvider}
-
-        expect:
-        rmp != null
-        5000 == FieldUtils.getFieldValue(rememberMeServices(), "tokenValiditySeconds")
-        // SEC-909
-        logoutHandlers.size() == 2
-        logoutHandlers.get(1) == rememberMeServices()
-        // SEC-1281
-        rmp.key == "ourkey"
-    }
-
-    def rememberMeAddsLogoutHandlerToLogoutFilter() {
-        httpAutoConfig () {
-            'remember-me'()
-            csrf(disabled:true)
-        }
-        createAppContext(AUTH_PROVIDER_XML)
-
-        def rememberMeServices = rememberMeServices()
-        List logoutHandlers = getFilter(LogoutFilter.class).handlers
-
-        expect:
-        rememberMeServices
-        logoutHandlers.size() == 2
-        logoutHandlers.get(0) instanceof SecurityContextLogoutHandler
-        logoutHandlers.get(1) == rememberMeServices
-    }
-
-    def rememberMeTokenValidityIsParsedCorrectly() {
-        httpAutoConfig () {
-            'remember-me'('key': 'ourkey', 'token-validity-seconds':'10000')
-        }
-
-        createAppContext(AUTH_PROVIDER_XML)
-
-        def rememberMeServices = rememberMeServices()
-        def rememberMeFilter = getFilter(RememberMeAuthenticationFilter.class)
-
-        expect:
-        rememberMeFilter.authenticationManager
-        rememberMeServices.key == 'ourkey'
-        rememberMeServices.tokenValiditySeconds == 10000
-        rememberMeServices.userDetailsService
-    }
-
-    def 'Remember-me token validity allows negative value for non-persistent implementation'() {
-        httpAutoConfig () {
-            'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1')
-        }
-
-        createAppContext(AUTH_PROVIDER_XML)
-        expect:
-        rememberMeServices().tokenValiditySeconds == -1
-    }
-
-    def 'remember-me@token-validity-seconds denies for persistent implementation'() {
-        setup:
-            httpAutoConfig () {
-                'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'dataSource' : 'dataSource')
-            }
-            mockBean(DataSource)
-        when:
-            createAppContext(AUTH_PROVIDER_XML)
-        then:
-            thrown(FatalBeanException)
-    }
-
-    def 'SEC-2165: remember-me@token-validity-seconds allows property placeholders'() {
-        when:
-            httpAutoConfig () {
-                'remember-me'('key': 'ourkey', 'token-validity-seconds':'${security.rememberme.ttl}')
-            }
-            xml.'b:bean'(class: PropertyPlaceholderConfigurer.name) {
-                'b:property'(name:'properties', value:'security.rememberme.ttl=30')
-            }
-
-            createAppContext(AUTH_PROVIDER_XML)
-        then:
-            rememberMeServices().tokenValiditySeconds == 30
-    }
-
-    def rememberMeSecureCookieAttributeIsSetCorrectly() {
-        httpAutoConfig () {
-            'remember-me'('key': 'ourkey', 'use-secure-cookie':'true')
-        }
-
-        createAppContext(AUTH_PROVIDER_XML)
-        expect:
-        FieldUtils.getFieldValue(rememberMeServices(), "useSecureCookie")
-    }
-
-    // SEC-1827
-    def rememberMeSecureCookieAttributeFalse() {
-        httpAutoConfig () {
-            'remember-me'('key': 'ourkey', 'use-secure-cookie':'false')
-        }
-
-        createAppContext(AUTH_PROVIDER_XML)
-        expect: 'useSecureCookie is false'
-        FieldUtils.getFieldValue(rememberMeServices(), "useSecureCookie") == Boolean.FALSE
-    }
-
-    def 'Negative token-validity is rejected with persistent implementation'() {
-        when:
-        httpAutoConfig () {
-            'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'token-repository-ref': 'tokenRepo')
-        }
-        bean('tokenRepo', InMemoryTokenRepositoryImpl.class.name)
-        createAppContext(AUTH_PROVIDER_XML)
-
-        then:
-        BeanDefinitionParsingException e = thrown()
-    }
-
-    def 'Custom user service is supported'() {
-        when:
-        httpAutoConfig () {
-            'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'user-service-ref': 'userService')
-        }
-        bean('userService', MockUserDetailsService.class.name)
-        createAppContext(AUTH_PROVIDER_XML)
-
-        then: "Parses OK"
-        notThrown BeanDefinitionParsingException
-    }
-
-    // SEC-742
-    def rememberMeWorksWithoutBasicProcessingFilter() {
-        when:
-        xml.http () {
-            'form-login'('login-page': '/login.jsp', 'default-target-url': '/messageList.html' )
-            logout('logout-success-url': '/login.jsp')
-            anonymous(username: 'guest', 'granted-authority': 'guest')
-            'remember-me'()
-        }
-        createAppContext(AUTH_PROVIDER_XML)
-
-        then: "Parses OK"
-        notThrown BeanDefinitionParsingException
-    }
-
-    def 'Default remember-me-parameter is correct'() {
-        httpAutoConfig () {
-            'remember-me'()
-        }
-
-        createAppContext(AUTH_PROVIDER_XML)
-        expect:
-        rememberMeServices().parameter == AbstractRememberMeServices.DEFAULT_PARAMETER
-    }
-
-    // SEC-2119
-    def 'Custom remember-me-parameter is supported'() {
-        httpAutoConfig () {
-            'remember-me'('remember-me-parameter': 'ourParam')
-        }
-
-        createAppContext(AUTH_PROVIDER_XML)
-        expect:
-        rememberMeServices().parameter == 'ourParam'
-    }
-
-    def 'remember-me-parameter cannot be used together with services-ref'() {
-        when:
-        httpAutoConfig () {
-            'remember-me'('remember-me-parameter': 'ourParam', 'services-ref': 'ourService')
-        }
-        createAppContext(AUTH_PROVIDER_XML)
-        then:
-        BeanDefinitionParsingException e = thrown()
-    }
-
-    // SEC-2826
-    def 'Custom remember-me-cookie is supported'() {
-        httpAutoConfig () {
-            'remember-me'('remember-me-cookie': 'ourCookie')
-        }
-
-        createAppContext(AUTH_PROVIDER_XML)
-        expect:
-        rememberMeServices().cookieName == 'ourCookie'
-    }
-
-    // SEC-2826
-    def 'remember-me-cookie cannot be used together with services-ref'() {
-        when:
-        httpAutoConfig () {
-            'remember-me'('remember-me-cookie': 'ourCookie', 'services-ref': 'ourService')
-        }
-
-        createAppContext(AUTH_PROVIDER_XML)
-        then:
-        BeanDefinitionParsingException e = thrown()
-        expect:
-        e.message == 'Configuration problem: services-ref can\'t be used in combination with attributes token-repository-ref,data-source-ref, user-service-ref, token-validity-seconds, use-secure-cookie, remember-me-parameter or remember-me-cookie\nOffending resource: null'
-    }
-
-    def rememberMeServices() {
-        getFilter(RememberMeAuthenticationFilter.class).getRememberMeServices()
-    }
-
-    static class CustomTokenRepository extends InMemoryTokenRepositoryImpl {
-
-    }
+	def rememberMeServiceWorksWithTokenRepoRef() {
+		httpAutoConfig () {
+			'remember-me'('token-repository-ref': 'tokenRepo')
+		}
+		bean('tokenRepo', CustomTokenRepository.class.name)
+
+		createAppContext(AUTH_PROVIDER_XML)
+
+		def rememberMeServices	= rememberMeServices()
+
+		expect:
+		rememberMeServices instanceof PersistentTokenBasedRememberMeServices
+		rememberMeServices.tokenRepository instanceof CustomTokenRepository
+		FieldUtils.getFieldValue(rememberMeServices, "useSecureCookie") == null
+	}
+
+	def rememberMeServiceWorksWithDataSourceRef() {
+		httpAutoConfig () {
+			'remember-me'('data-source-ref': 'ds')
+		}
+		bean('ds', TestDataSource.class.name, ['tokendb'])
+
+		createAppContext(AUTH_PROVIDER_XML)
+
+		def rememberMeServices	= rememberMeServices()
+
+		expect:
+		rememberMeServices instanceof PersistentTokenBasedRememberMeServices
+		rememberMeServices.tokenRepository instanceof JdbcTokenRepositoryImpl
+	}
+
+	def rememberMeServiceWorksWithAuthenticationSuccessHandlerRef() {
+		httpAutoConfig () {
+			'remember-me'('authentication-success-handler-ref': 'sh')
+		}
+		bean('sh', SimpleUrlAuthenticationSuccessHandler.class.name, ['/target'])
+
+		createAppContext(AUTH_PROVIDER_XML)
+
+		expect:
+		getFilter(RememberMeAuthenticationFilter.class).successHandler instanceof SimpleUrlAuthenticationSuccessHandler
+	}
+
+	def rememberMeServiceWorksWithExternalServicesImpl() {
+		httpAutoConfig () {
+			'remember-me'('key': "#{'our' + 'key'}", 'services-ref': 'rms')
+			csrf(disabled:true)
+		}
+		xml.'b:bean'(id: 'rms', 'class': TokenBasedRememberMeServices.class.name) {
+			'b:constructor-arg'(value: 'ourKey')
+			'b:constructor-arg'(ref: 'us')
+			'b:property'(name: 'tokenValiditySeconds', value: '5000')
+		}
+
+		createAppContext(AUTH_PROVIDER_XML)
+
+		List logoutHandlers = FieldUtils.getFieldValue(getFilter(LogoutFilter.class), "handlers");
+		Map ams = appContext.getBeansOfType(ProviderManager.class);
+		ProviderManager am = (ams.values() as List).find { it instanceof ProviderManager && it.providers.size() == 2}
+		RememberMeAuthenticationProvider rmp = am.providers.find { it instanceof RememberMeAuthenticationProvider}
+
+		expect:
+		rmp != null
+		5000 == FieldUtils.getFieldValue(rememberMeServices(), "tokenValiditySeconds")
+		// SEC-909
+		logoutHandlers.size() == 2
+		logoutHandlers.get(1) == rememberMeServices()
+		// SEC-1281
+		rmp.key == "ourkey"
+	}
+
+	def rememberMeAddsLogoutHandlerToLogoutFilter() {
+		httpAutoConfig () {
+			'remember-me'()
+			csrf(disabled:true)
+		}
+		createAppContext(AUTH_PROVIDER_XML)
+
+		def rememberMeServices = rememberMeServices()
+		List logoutHandlers = getFilter(LogoutFilter.class).handlers
+
+		expect:
+		rememberMeServices
+		logoutHandlers.size() == 2
+		logoutHandlers.get(0) instanceof SecurityContextLogoutHandler
+		logoutHandlers.get(1) == rememberMeServices
+	}
+
+	def rememberMeTokenValidityIsParsedCorrectly() {
+		httpAutoConfig () {
+			'remember-me'('key': 'ourkey', 'token-validity-seconds':'10000')
+		}
+
+		createAppContext(AUTH_PROVIDER_XML)
+
+		def rememberMeServices = rememberMeServices()
+		def rememberMeFilter = getFilter(RememberMeAuthenticationFilter.class)
+
+		expect:
+		rememberMeFilter.authenticationManager
+		rememberMeServices.key == 'ourkey'
+		rememberMeServices.tokenValiditySeconds == 10000
+		rememberMeServices.userDetailsService
+	}
+
+	def 'Remember-me token validity allows negative value for non-persistent implementation'() {
+		httpAutoConfig () {
+			'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1')
+		}
+
+		createAppContext(AUTH_PROVIDER_XML)
+		expect:
+		rememberMeServices().tokenValiditySeconds == -1
+	}
+
+	def 'remember-me@token-validity-seconds denies for persistent implementation'() {
+		setup:
+			httpAutoConfig () {
+				'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'dataSource' : 'dataSource')
+			}
+			mockBean(DataSource)
+		when:
+			createAppContext(AUTH_PROVIDER_XML)
+		then:
+			thrown(FatalBeanException)
+	}
+
+	def 'SEC-2165: remember-me@token-validity-seconds allows property placeholders'() {
+		when:
+			httpAutoConfig () {
+				'remember-me'('key': 'ourkey', 'token-validity-seconds':'${security.rememberme.ttl}')
+			}
+			xml.'b:bean'(class: PropertyPlaceholderConfigurer.name) {
+				'b:property'(name:'properties', value:'security.rememberme.ttl=30')
+			}
+
+			createAppContext(AUTH_PROVIDER_XML)
+		then:
+			rememberMeServices().tokenValiditySeconds == 30
+	}
+
+	def rememberMeSecureCookieAttributeIsSetCorrectly() {
+		httpAutoConfig () {
+			'remember-me'('key': 'ourkey', 'use-secure-cookie':'true')
+		}
+
+		createAppContext(AUTH_PROVIDER_XML)
+		expect:
+		FieldUtils.getFieldValue(rememberMeServices(), "useSecureCookie")
+	}
+
+	// SEC-1827
+	def rememberMeSecureCookieAttributeFalse() {
+		httpAutoConfig () {
+			'remember-me'('key': 'ourkey', 'use-secure-cookie':'false')
+		}
+
+		createAppContext(AUTH_PROVIDER_XML)
+		expect: 'useSecureCookie is false'
+		FieldUtils.getFieldValue(rememberMeServices(), "useSecureCookie") == Boolean.FALSE
+	}
+
+	def 'Negative token-validity is rejected with persistent implementation'() {
+		when:
+		httpAutoConfig () {
+			'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'token-repository-ref': 'tokenRepo')
+		}
+		bean('tokenRepo', InMemoryTokenRepositoryImpl.class.name)
+		createAppContext(AUTH_PROVIDER_XML)
+
+		then:
+		BeanDefinitionParsingException e = thrown()
+	}
+
+	def 'Custom user service is supported'() {
+		when:
+		httpAutoConfig () {
+			'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'user-service-ref': 'userService')
+		}
+		bean('userService', MockUserDetailsService.class.name)
+		createAppContext(AUTH_PROVIDER_XML)
+
+		then: "Parses OK"
+		notThrown BeanDefinitionParsingException
+	}
+
+	// SEC-742
+	def rememberMeWorksWithoutBasicProcessingFilter() {
+		when:
+		xml.http () {
+			'form-login'('login-page': '/login.jsp', 'default-target-url': '/messageList.html' )
+			logout('logout-success-url': '/login.jsp')
+			anonymous(username: 'guest', 'granted-authority': 'guest')
+			'remember-me'()
+		}
+		createAppContext(AUTH_PROVIDER_XML)
+
+		then: "Parses OK"
+		notThrown BeanDefinitionParsingException
+	}
+
+	def 'Default remember-me-parameter is correct'() {
+		httpAutoConfig () {
+			'remember-me'()
+		}
+
+		createAppContext(AUTH_PROVIDER_XML)
+		expect:
+		rememberMeServices().parameter == AbstractRememberMeServices.DEFAULT_PARAMETER
+	}
+
+	// SEC-2119
+	def 'Custom remember-me-parameter is supported'() {
+		httpAutoConfig () {
+			'remember-me'('remember-me-parameter': 'ourParam')
+		}
+
+		createAppContext(AUTH_PROVIDER_XML)
+		expect:
+		rememberMeServices().parameter == 'ourParam'
+	}
+
+	def 'remember-me-parameter cannot be used together with services-ref'() {
+		when:
+		httpAutoConfig () {
+			'remember-me'('remember-me-parameter': 'ourParam', 'services-ref': 'ourService')
+		}
+		createAppContext(AUTH_PROVIDER_XML)
+		then:
+		BeanDefinitionParsingException e = thrown()
+	}
+
+	// SEC-2826
+	def 'Custom remember-me-cookie is supported'() {
+		httpAutoConfig () {
+			'remember-me'('remember-me-cookie': 'ourCookie')
+		}
+
+		createAppContext(AUTH_PROVIDER_XML)
+		expect:
+		rememberMeServices().cookieName == 'ourCookie'
+	}
+
+	// SEC-2826
+	def 'remember-me-cookie cannot be used together with services-ref'() {
+		when:
+		httpAutoConfig () {
+			'remember-me'('remember-me-cookie': 'ourCookie', 'services-ref': 'ourService')
+		}
+
+		createAppContext(AUTH_PROVIDER_XML)
+		then:
+		BeanDefinitionParsingException e = thrown()
+		expect:
+		e.message == 'Configuration problem: services-ref can\'t be used in combination with attributes token-repository-ref,data-source-ref, user-service-ref, token-validity-seconds, use-secure-cookie, remember-me-parameter or remember-me-cookie\nOffending resource: null'
+	}
+
+	def rememberMeServices() {
+		getFilter(RememberMeAuthenticationFilter.class).getRememberMeServices()
+	}
+
+	static class CustomTokenRepository extends InMemoryTokenRepositoryImpl {
+
+	}
 }

+ 371 - 371
config/src/test/groovy/org/springframework/security/config/http/SessionManagementConfigTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -58,375 +58,375 @@ import org.springframework.security.web.session.SessionManagementFilter
  */
 class SessionManagementConfigTests extends AbstractHttpConfigTests {
 
-    def settingCreateSessionToAlwaysSetsFilterPropertiesCorrectly() {
-        httpCreateSession('always') { }
-        createAppContext();
-
-        def filter = getFilter(SecurityContextPersistenceFilter.class);
-
-        expect:
-        filter.forceEagerSessionCreation
-        filter.repo.allowSessionCreation
-        !filter.repo.disableUrlRewriting
-    }
-
-    def settingCreateSessionToNeverSetsFilterPropertiesCorrectly() {
-        httpCreateSession('never') { }
-        createAppContext();
-
-        def filter = getFilter(SecurityContextPersistenceFilter.class);
-
-        expect:
-        !filter.forceEagerSessionCreation
-        !filter.repo.allowSessionCreation
-    }
-
-    def settingCreateSessionToStatelessSetsFilterPropertiesCorrectly() {
-        httpCreateSession('stateless') { }
-        createAppContext();
-
-        def filter = getFilter(SecurityContextPersistenceFilter.class);
-
-        expect:
-        !filter.forceEagerSessionCreation
-        filter.repo instanceof NullSecurityContextRepository
-        getFilter(SessionManagementFilter.class) == null
-        getFilter(RequestCacheAwareFilter.class) == null
-    }
-
-    def settingCreateSessionToIfRequiredDoesntCreateASessionForPublicInvocation() {
-        httpCreateSession('ifRequired') { }
-        createAppContext();
-
-        def filter = getFilter(SecurityContextPersistenceFilter.class);
-
-        expect:
-        !filter.forceEagerSessionCreation
-        filter.repo.allowSessionCreation
-    }
-
-    def 'SEC-1208: Session is not created when rejecting user due to max sessions exceeded'() {
-        setup:
-            httpCreateSession('never') {
-                'session-management'() {
-                    'concurrency-control'('max-sessions':1,'error-if-maximum-exceeded':'true')
-                }
-                csrf(disabled:true)
-            }
-            createAppContext()
-            SessionRegistry registry = appContext.getBean(SessionRegistry)
-            registry.registerNewSession("1", new User("user","password",AuthorityUtils.createAuthorityList("ROLE_USER")))
-            MockHttpServletRequest request = new MockHttpServletRequest()
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            String credentials = "user:password"
-            request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
-        when: "exceed max authentication attempts"
-            appContext.getBean(FilterChainProxy).doFilter(request, response, new MockFilterChain())
-        then: "no new session is created"
-            request.getSession(false) == null
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-    }
-
-    def 'SEC-2137: disable session fixation and enable concurrency control'() {
-        setup: "context where session fixation is disabled and concurrency control is enabled"
-            httpAutoConfig {
-                'session-management'('session-fixation-protection':'none') {
-                    'concurrency-control'('max-sessions':'1','error-if-maximum-exceeded':'true')
-                }
-            }
-            createAppContext()
-            MockHttpServletRequest request = new MockHttpServletRequest()
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            String originalSessionId = request.session.id
-            String credentials = "user:password"
-            request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
-        when: "authenticate"
-            appContext.getBean(FilterChainProxy).doFilter(request, response, new MockFilterChain())
-        then: "session invalidate is not called"
-            request.session.id == originalSessionId
-    }
-
-    def httpCreateSession(String create, Closure c) {
-        xml.http(['auto-config': 'true', 'create-session': create], c)
-    }
-
-    def concurrentSessionSupportAddsFilterAndExpectedBeans() {
-        when:
-        httpAutoConfig {
-            'session-management'() {
-                'concurrency-control'('session-registry-alias':'sr', 'expired-url': '/expired')
-            }
-            csrf(disabled:true)
-        }
-        createAppContext();
-        List filters = getFilters("/someurl");
-        def concurrentSessionFilter = filters.get(1)
-
-        then:
-        concurrentSessionFilter instanceof ConcurrentSessionFilter
-        concurrentSessionFilter.expiredUrl == '/expired'
-        appContext.getBean("sr") != null
-        getFilter(SessionManagementFilter.class) != null
-        sessionRegistryIsValid();
-
-        concurrentSessionFilter.handlers.size() == 1
-        def logoutHandler = concurrentSessionFilter.handlers[0]
-        logoutHandler instanceof SecurityContextLogoutHandler
-        logoutHandler.invalidateHttpSession
-
-    }
-
-    def 'concurrency-control adds custom logout handlers'() {
-        when: 'Custom logout and remember-me'
-        httpAutoConfig {
-            'session-management'() {
-                'concurrency-control'()
-            }
-            'logout'('invalidate-session': false, 'delete-cookies': 'testCookie')
-            'remember-me'()
-            csrf(disabled:true)
-        }
-        createAppContext()
-
-        List filters = getFilters("/someurl")
-        ConcurrentSessionFilter concurrentSessionFilter = filters.get(1)
-        def logoutHandlers = concurrentSessionFilter.handlers
-
-        then: 'ConcurrentSessionFilter contains the customized LogoutHandlers'
-        logoutHandlers.size() == 3
-        def securityCtxlogoutHandler = logoutHandlers.find { it instanceof SecurityContextLogoutHandler }
-        securityCtxlogoutHandler.invalidateHttpSession == false
-        def cookieClearingLogoutHandler = logoutHandlers.find { it instanceof CookieClearingLogoutHandler }
-        cookieClearingLogoutHandler.cookiesToClear == ['testCookie']
-        def remembermeLogoutHandler = logoutHandlers.find { it instanceof RememberMeServices }
-        remembermeLogoutHandler == getFilter(RememberMeAuthenticationFilter.class).rememberMeServices
-    }
-
-    def 'concurrency-control with remember-me and no LogoutFilter contains SecurityContextLogoutHandler and RememberMeServices as LogoutHandlers'() {
-        when: 'RememberMe and No LogoutFilter'
-        xml.http(['entry-point-ref': 'entryPoint'], {
-            'session-management'() {
-                'concurrency-control'()
-            }
-            'remember-me'()
-            csrf(disabled:true)
-        })
-        bean('entryPoint', 'org.springframework.security.web.authentication.Http403ForbiddenEntryPoint')
-        createAppContext()
-
-        List filters = getFilters("/someurl")
-        ConcurrentSessionFilter concurrentSessionFilter = filters.get(1)
-        def logoutHandlers = concurrentSessionFilter.handlers
-
-        then: 'SecurityContextLogoutHandler and RememberMeServices are in ConcurrentSessionFilter logoutHandlers'
-        !filters.find { it instanceof LogoutFilter }
-        logoutHandlers.size() == 2
-        def securityCtxlogoutHandler = logoutHandlers.find { it instanceof SecurityContextLogoutHandler }
-        securityCtxlogoutHandler.invalidateHttpSession == true
-        logoutHandlers.find { it instanceof RememberMeServices } == getFilter(RememberMeAuthenticationFilter).rememberMeServices
-    }
-
-    def 'concurrency-control with no remember-me or LogoutFilter contains SecurityContextLogoutHandler as LogoutHandlers'() {
-        when: 'No Logout Filter or RememberMe'
-        xml.http(['entry-point-ref': 'entryPoint'], {
-            'session-management'() {
-                'concurrency-control'()
-            }
-        })
-        bean('entryPoint', 'org.springframework.security.web.authentication.Http403ForbiddenEntryPoint')
-        createAppContext()
-
-        List filters = getFilters("/someurl")
-        ConcurrentSessionFilter concurrentSessionFilter = filters.get(1)
-        def logoutHandlers = concurrentSessionFilter.handlers
-
-        then: 'Only SecurityContextLogoutHandler is found in ConcurrentSessionFilter logoutHandlers'
-        !filters.find { it instanceof LogoutFilter }
-        logoutHandlers.size() == 1
-        def securityCtxlogoutHandler = logoutHandlers.find { it instanceof SecurityContextLogoutHandler }
-        securityCtxlogoutHandler.invalidateHttpSession == true
-    }
-
-    def 'SEC-2057: ConcurrentSessionFilter is after SecurityContextPersistenceFilter'() {
-        httpAutoConfig {
-            'session-management'() {
-                'concurrency-control'()
-            }
-        }
-        createAppContext()
-        List filters = getFilters("/someurl")
-
-        expect:
-        filters.get(0) instanceof SecurityContextPersistenceFilter
-        filters.get(1) instanceof ConcurrentSessionFilter
-    }
-
-    def 'concurrency-control handles default expired-url as null'() {
-        httpAutoConfig {
-            'session-management'() {
-                'concurrency-control'('session-registry-alias':'sr')
-            }
-        }
-        createAppContext();
-        List filters = getFilters("/someurl");
-
-        expect:
-        filters.get(1).expiredUrl == null
-    }
-
-    def externalSessionStrategyIsSupported() {
-        setup:
-            httpAutoConfig {
-                'session-management'('session-authentication-strategy-ref':'ss')
-                csrf(disabled:true)
-            }
-            mockBean(SessionAuthenticationStrategy,'ss')
-            createAppContext()
-
-            MockHttpServletRequest request = new MockHttpServletRequest();
-            request.getSession();
-            request.servletPath = "/login"
-            request.setMethod("POST");
-            request.setParameter("username", "user");
-            request.setParameter("password", "password");
-
-            SessionAuthenticationStrategy sessionAuthStrategy = appContext.getBean('ss',SessionAuthenticationStrategy)
-            FilterChainProxy springSecurityFilterChain = appContext.getBean(FilterChainProxy)
-        when:
-            springSecurityFilterChain.doFilter(request,new MockHttpServletResponse(), new MockFilterChain())
-        then: "CustomSessionAuthenticationStrategy has seen the request (although REQUEST is a wrapped request)"
-            verify(sessionAuthStrategy).onAuthentication(any(Authentication), any(HttpServletRequest), any(HttpServletResponse))
-    }
-
-    def externalSessionRegistryBeanIsConfiguredCorrectly() {
-        httpAutoConfig {
-            'session-management'() {
-                'concurrency-control'('session-registry-ref':'sr')
-            }
-            csrf(disabled:true)
-        }
-        bean('sr', SessionRegistryImpl.class.name)
-        createAppContext();
-
-        expect:
-        sessionRegistryIsValid();
-    }
-
-    def sessionRegistryIsValid() {
-        Object sessionRegistry = appContext.getBean("sr");
-        Object sessionRegistryFromConcurrencyFilter = FieldUtils.getFieldValue(
-                getFilter(ConcurrentSessionFilter.class), "sessionRegistry");
-        Object sessionRegistryFromFormLoginFilter = FieldUtils.getFieldValue(getFilter(UsernamePasswordAuthenticationFilter),"sessionStrategy").delegateStrategies[0].sessionRegistry
-        Object sessionRegistryFromMgmtFilter = FieldUtils.getFieldValue(getFilter(SessionManagementFilter),"sessionAuthenticationStrategy").delegateStrategies[0].sessionRegistry
-
-        assertSame(sessionRegistry, sessionRegistryFromConcurrencyFilter);
-        assertSame(sessionRegistry, sessionRegistryFromMgmtFilter);
-        // SEC-1143
-        assertSame(sessionRegistry, sessionRegistryFromFormLoginFilter);
-        true;
-    }
-
-    def concurrentSessionMaxSessionsIsCorrectlyConfigured() {
-        setup:
-        httpAutoConfig {
-            'session-management'('session-authentication-error-url':'/max-exceeded') {
-                'concurrency-control'('max-sessions': '2', 'error-if-maximum-exceeded':'true')
-            }
-        }
-        createAppContext();
-
-        def seshFilter = getFilter(SessionManagementFilter.class);
-        def auth = new UsernamePasswordAuthenticationToken("bob", "pass");
-        SecurityContextHolder.getContext().setAuthentication(auth);
-        MockHttpServletResponse mockResponse = new MockHttpServletResponse();
-        def response = new SaveContextOnUpdateOrErrorResponseWrapper(mockResponse, false) {
-            protected void saveContext(SecurityContext context) {
-            }
-        };
-        when: "First session is established"
-        seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
-        then: "ok"
-        mockResponse.redirectedUrl == null
-        when: "Second session is established"
-        seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
-        then: "ok"
-        mockResponse.redirectedUrl == null
-        when: "Third session is established"
-        seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
-        then: "Rejected"
-        mockResponse.redirectedUrl == "/max-exceeded";
-    }
-
-    def disablingSessionProtectionRemovesSessionManagementFilterIfNoInvalidSessionUrlSet() {
-        httpAutoConfig {
-            'session-management'('session-fixation-protection': 'none')
-            csrf(disabled:true)
-        }
-        createAppContext()
-
-        expect:
-        !(getFilters("/someurl").find { it instanceof SessionManagementFilter})
-    }
-
-    def 'session-fixation-protection=none'() {
-        setup:
-        MockHttpServletRequest request = new MockHttpServletRequest(method:'POST')
-        request.session.id = '123'
-        request.setParameter('username', 'user')
-        request.setParameter('password', 'password')
-        request.servletPath = '/login'
-
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        MockFilterChain chain = new MockFilterChain()
-        httpAutoConfig {
-            'session-management'('session-fixation-protection': 'none')
-            csrf(disabled:true)
-        }
-        createAppContext()
-        request.session.id = '123'
-
-        when:
-        springSecurityFilterChain.doFilter(request,response, chain)
-
-        then:
-        request.session.id == '123'
-    }
-
-    def 'session-fixation-protection=migrateSession'() {
-        setup:
-        MockHttpServletRequest request = new MockHttpServletRequest(method:'POST')
-        request.session.id = '123'
-        request.setParameter('username', 'user')
-        request.setParameter('password', 'password')
-        request.servletPath = '/login'
-
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        MockFilterChain chain = new MockFilterChain()
-        httpAutoConfig {
-            'session-management'('session-fixation-protection': 'migrateSession')
-            csrf(disabled:true)
-        }
-        createAppContext()
-        request.session.id = '123'
-
-        when:
-        springSecurityFilterChain.doFilter(request,response, chain)
-
-        then:
-        request.session.id != '123'
-    }
-
-    def disablingSessionProtectionRetainsSessionManagementFilterInvalidSessionUrlSet() {
-        httpAutoConfig {
-            'session-management'('session-fixation-protection': 'none', 'invalid-session-url': '/timeoutUrl')
-            csrf(disabled:true)
-        }
-        createAppContext()
-        def filter = getFilters("/someurl")[10]
-
-        expect:
-        filter instanceof SessionManagementFilter
-        filter.invalidSessionStrategy.destinationUrl == '/timeoutUrl'
-    }
+	def settingCreateSessionToAlwaysSetsFilterPropertiesCorrectly() {
+		httpCreateSession('always') { }
+		createAppContext();
+
+		def filter = getFilter(SecurityContextPersistenceFilter.class);
+
+		expect:
+		filter.forceEagerSessionCreation
+		filter.repo.allowSessionCreation
+		!filter.repo.disableUrlRewriting
+	}
+
+	def settingCreateSessionToNeverSetsFilterPropertiesCorrectly() {
+		httpCreateSession('never') { }
+		createAppContext();
+
+		def filter = getFilter(SecurityContextPersistenceFilter.class);
+
+		expect:
+		!filter.forceEagerSessionCreation
+		!filter.repo.allowSessionCreation
+	}
+
+	def settingCreateSessionToStatelessSetsFilterPropertiesCorrectly() {
+		httpCreateSession('stateless') { }
+		createAppContext();
+
+		def filter = getFilter(SecurityContextPersistenceFilter.class);
+
+		expect:
+		!filter.forceEagerSessionCreation
+		filter.repo instanceof NullSecurityContextRepository
+		getFilter(SessionManagementFilter.class) == null
+		getFilter(RequestCacheAwareFilter.class) == null
+	}
+
+	def settingCreateSessionToIfRequiredDoesntCreateASessionForPublicInvocation() {
+		httpCreateSession('ifRequired') { }
+		createAppContext();
+
+		def filter = getFilter(SecurityContextPersistenceFilter.class);
+
+		expect:
+		!filter.forceEagerSessionCreation
+		filter.repo.allowSessionCreation
+	}
+
+	def 'SEC-1208: Session is not created when rejecting user due to max sessions exceeded'() {
+		setup:
+			httpCreateSession('never') {
+				'session-management'() {
+					'concurrency-control'('max-sessions':1,'error-if-maximum-exceeded':'true')
+				}
+				csrf(disabled:true)
+			}
+			createAppContext()
+			SessionRegistry registry = appContext.getBean(SessionRegistry)
+			registry.registerNewSession("1", new User("user","password",AuthorityUtils.createAuthorityList("ROLE_USER")))
+			MockHttpServletRequest request = new MockHttpServletRequest()
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			String credentials = "user:password"
+			request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
+		when: "exceed max authentication attempts"
+			appContext.getBean(FilterChainProxy).doFilter(request, response, new MockFilterChain())
+		then: "no new session is created"
+			request.getSession(false) == null
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+	}
+
+	def 'SEC-2137: disable session fixation and enable concurrency control'() {
+		setup: "context where session fixation is disabled and concurrency control is enabled"
+			httpAutoConfig {
+				'session-management'('session-fixation-protection':'none') {
+					'concurrency-control'('max-sessions':'1','error-if-maximum-exceeded':'true')
+				}
+			}
+			createAppContext()
+			MockHttpServletRequest request = new MockHttpServletRequest()
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			String originalSessionId = request.session.id
+			String credentials = "user:password"
+			request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
+		when: "authenticate"
+			appContext.getBean(FilterChainProxy).doFilter(request, response, new MockFilterChain())
+		then: "session invalidate is not called"
+			request.session.id == originalSessionId
+	}
+
+	def httpCreateSession(String create, Closure c) {
+		xml.http(['auto-config': 'true', 'create-session': create], c)
+	}
+
+	def concurrentSessionSupportAddsFilterAndExpectedBeans() {
+		when:
+		httpAutoConfig {
+			'session-management'() {
+				'concurrency-control'('session-registry-alias':'sr', 'expired-url': '/expired')
+			}
+			csrf(disabled:true)
+		}
+		createAppContext();
+		List filters = getFilters("/someurl");
+		def concurrentSessionFilter = filters.get(1)
+
+		then:
+		concurrentSessionFilter instanceof ConcurrentSessionFilter
+		concurrentSessionFilter.expiredUrl == '/expired'
+		appContext.getBean("sr") != null
+		getFilter(SessionManagementFilter.class) != null
+		sessionRegistryIsValid();
+
+		concurrentSessionFilter.handlers.size() == 1
+		def logoutHandler = concurrentSessionFilter.handlers[0]
+		logoutHandler instanceof SecurityContextLogoutHandler
+		logoutHandler.invalidateHttpSession
+
+	}
+
+	def 'concurrency-control adds custom logout handlers'() {
+		when: 'Custom logout and remember-me'
+		httpAutoConfig {
+			'session-management'() {
+				'concurrency-control'()
+			}
+			'logout'('invalidate-session': false, 'delete-cookies': 'testCookie')
+			'remember-me'()
+			csrf(disabled:true)
+		}
+		createAppContext()
+
+		List filters = getFilters("/someurl")
+		ConcurrentSessionFilter concurrentSessionFilter = filters.get(1)
+		def logoutHandlers = concurrentSessionFilter.handlers
+
+		then: 'ConcurrentSessionFilter contains the customized LogoutHandlers'
+		logoutHandlers.size() == 3
+		def securityCtxlogoutHandler = logoutHandlers.find { it instanceof SecurityContextLogoutHandler }
+		securityCtxlogoutHandler.invalidateHttpSession == false
+		def cookieClearingLogoutHandler = logoutHandlers.find { it instanceof CookieClearingLogoutHandler }
+		cookieClearingLogoutHandler.cookiesToClear == ['testCookie']
+		def remembermeLogoutHandler = logoutHandlers.find { it instanceof RememberMeServices }
+		remembermeLogoutHandler == getFilter(RememberMeAuthenticationFilter.class).rememberMeServices
+	}
+
+	def 'concurrency-control with remember-me and no LogoutFilter contains SecurityContextLogoutHandler and RememberMeServices as LogoutHandlers'() {
+		when: 'RememberMe and No LogoutFilter'
+		xml.http(['entry-point-ref': 'entryPoint'], {
+			'session-management'() {
+				'concurrency-control'()
+			}
+			'remember-me'()
+			csrf(disabled:true)
+		})
+		bean('entryPoint', 'org.springframework.security.web.authentication.Http403ForbiddenEntryPoint')
+		createAppContext()
+
+		List filters = getFilters("/someurl")
+		ConcurrentSessionFilter concurrentSessionFilter = filters.get(1)
+		def logoutHandlers = concurrentSessionFilter.handlers
+
+		then: 'SecurityContextLogoutHandler and RememberMeServices are in ConcurrentSessionFilter logoutHandlers'
+		!filters.find { it instanceof LogoutFilter }
+		logoutHandlers.size() == 2
+		def securityCtxlogoutHandler = logoutHandlers.find { it instanceof SecurityContextLogoutHandler }
+		securityCtxlogoutHandler.invalidateHttpSession == true
+		logoutHandlers.find { it instanceof RememberMeServices } == getFilter(RememberMeAuthenticationFilter).rememberMeServices
+	}
+
+	def 'concurrency-control with no remember-me or LogoutFilter contains SecurityContextLogoutHandler as LogoutHandlers'() {
+		when: 'No Logout Filter or RememberMe'
+		xml.http(['entry-point-ref': 'entryPoint'], {
+			'session-management'() {
+				'concurrency-control'()
+			}
+		})
+		bean('entryPoint', 'org.springframework.security.web.authentication.Http403ForbiddenEntryPoint')
+		createAppContext()
+
+		List filters = getFilters("/someurl")
+		ConcurrentSessionFilter concurrentSessionFilter = filters.get(1)
+		def logoutHandlers = concurrentSessionFilter.handlers
+
+		then: 'Only SecurityContextLogoutHandler is found in ConcurrentSessionFilter logoutHandlers'
+		!filters.find { it instanceof LogoutFilter }
+		logoutHandlers.size() == 1
+		def securityCtxlogoutHandler = logoutHandlers.find { it instanceof SecurityContextLogoutHandler }
+		securityCtxlogoutHandler.invalidateHttpSession == true
+	}
+
+	def 'SEC-2057: ConcurrentSessionFilter is after SecurityContextPersistenceFilter'() {
+		httpAutoConfig {
+			'session-management'() {
+				'concurrency-control'()
+			}
+		}
+		createAppContext()
+		List filters = getFilters("/someurl")
+
+		expect:
+		filters.get(0) instanceof SecurityContextPersistenceFilter
+		filters.get(1) instanceof ConcurrentSessionFilter
+	}
+
+	def 'concurrency-control handles default expired-url as null'() {
+		httpAutoConfig {
+			'session-management'() {
+				'concurrency-control'('session-registry-alias':'sr')
+			}
+		}
+		createAppContext();
+		List filters = getFilters("/someurl");
+
+		expect:
+		filters.get(1).expiredUrl == null
+	}
+
+	def externalSessionStrategyIsSupported() {
+		setup:
+			httpAutoConfig {
+				'session-management'('session-authentication-strategy-ref':'ss')
+				csrf(disabled:true)
+			}
+			mockBean(SessionAuthenticationStrategy,'ss')
+			createAppContext()
+
+			MockHttpServletRequest request = new MockHttpServletRequest();
+			request.getSession();
+			request.servletPath = "/login"
+			request.setMethod("POST");
+			request.setParameter("username", "user");
+			request.setParameter("password", "password");
+
+			SessionAuthenticationStrategy sessionAuthStrategy = appContext.getBean('ss',SessionAuthenticationStrategy)
+			FilterChainProxy springSecurityFilterChain = appContext.getBean(FilterChainProxy)
+		when:
+			springSecurityFilterChain.doFilter(request,new MockHttpServletResponse(), new MockFilterChain())
+		then: "CustomSessionAuthenticationStrategy has seen the request (although REQUEST is a wrapped request)"
+			verify(sessionAuthStrategy).onAuthentication(any(Authentication), any(HttpServletRequest), any(HttpServletResponse))
+	}
+
+	def externalSessionRegistryBeanIsConfiguredCorrectly() {
+		httpAutoConfig {
+			'session-management'() {
+				'concurrency-control'('session-registry-ref':'sr')
+			}
+			csrf(disabled:true)
+		}
+		bean('sr', SessionRegistryImpl.class.name)
+		createAppContext();
+
+		expect:
+		sessionRegistryIsValid();
+	}
+
+	def sessionRegistryIsValid() {
+		Object sessionRegistry = appContext.getBean("sr");
+		Object sessionRegistryFromConcurrencyFilter = FieldUtils.getFieldValue(
+				getFilter(ConcurrentSessionFilter.class), "sessionRegistry");
+		Object sessionRegistryFromFormLoginFilter = FieldUtils.getFieldValue(getFilter(UsernamePasswordAuthenticationFilter),"sessionStrategy").delegateStrategies[0].sessionRegistry
+		Object sessionRegistryFromMgmtFilter = FieldUtils.getFieldValue(getFilter(SessionManagementFilter),"sessionAuthenticationStrategy").delegateStrategies[0].sessionRegistry
+
+		assertSame(sessionRegistry, sessionRegistryFromConcurrencyFilter);
+		assertSame(sessionRegistry, sessionRegistryFromMgmtFilter);
+		// SEC-1143
+		assertSame(sessionRegistry, sessionRegistryFromFormLoginFilter);
+		true;
+	}
+
+	def concurrentSessionMaxSessionsIsCorrectlyConfigured() {
+		setup:
+		httpAutoConfig {
+			'session-management'('session-authentication-error-url':'/max-exceeded') {
+				'concurrency-control'('max-sessions': '2', 'error-if-maximum-exceeded':'true')
+			}
+		}
+		createAppContext();
+
+		def seshFilter = getFilter(SessionManagementFilter.class);
+		def auth = new UsernamePasswordAuthenticationToken("bob", "pass");
+		SecurityContextHolder.getContext().setAuthentication(auth);
+		MockHttpServletResponse mockResponse = new MockHttpServletResponse();
+		def response = new SaveContextOnUpdateOrErrorResponseWrapper(mockResponse, false) {
+			protected void saveContext(SecurityContext context) {
+			}
+		};
+		when: "First session is established"
+		seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
+		then: "ok"
+		mockResponse.redirectedUrl == null
+		when: "Second session is established"
+		seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
+		then: "ok"
+		mockResponse.redirectedUrl == null
+		when: "Third session is established"
+		seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
+		then: "Rejected"
+		mockResponse.redirectedUrl == "/max-exceeded";
+	}
+
+	def disablingSessionProtectionRemovesSessionManagementFilterIfNoInvalidSessionUrlSet() {
+		httpAutoConfig {
+			'session-management'('session-fixation-protection': 'none')
+			csrf(disabled:true)
+		}
+		createAppContext()
+
+		expect:
+		!(getFilters("/someurl").find { it instanceof SessionManagementFilter})
+	}
+
+	def 'session-fixation-protection=none'() {
+		setup:
+		MockHttpServletRequest request = new MockHttpServletRequest(method:'POST')
+		request.session.id = '123'
+		request.setParameter('username', 'user')
+		request.setParameter('password', 'password')
+		request.servletPath = '/login'
+
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		MockFilterChain chain = new MockFilterChain()
+		httpAutoConfig {
+			'session-management'('session-fixation-protection': 'none')
+			csrf(disabled:true)
+		}
+		createAppContext()
+		request.session.id = '123'
+
+		when:
+		springSecurityFilterChain.doFilter(request,response, chain)
+
+		then:
+		request.session.id == '123'
+	}
+
+	def 'session-fixation-protection=migrateSession'() {
+		setup:
+		MockHttpServletRequest request = new MockHttpServletRequest(method:'POST')
+		request.session.id = '123'
+		request.setParameter('username', 'user')
+		request.setParameter('password', 'password')
+		request.servletPath = '/login'
+
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		MockFilterChain chain = new MockFilterChain()
+		httpAutoConfig {
+			'session-management'('session-fixation-protection': 'migrateSession')
+			csrf(disabled:true)
+		}
+		createAppContext()
+		request.session.id = '123'
+
+		when:
+		springSecurityFilterChain.doFilter(request,response, chain)
+
+		then:
+		request.session.id != '123'
+	}
+
+	def disablingSessionProtectionRetainsSessionManagementFilterInvalidSessionUrlSet() {
+		httpAutoConfig {
+			'session-management'('session-fixation-protection': 'none', 'invalid-session-url': '/timeoutUrl')
+			csrf(disabled:true)
+		}
+		createAppContext()
+		def filter = getFilters("/someurl")[10]
+
+		expect:
+		filter instanceof SessionManagementFilter
+		filter.invalidSessionStrategy.destinationUrl == '/timeoutUrl'
+	}
 
 }

+ 30 - 30
core/core.gradle

@@ -5,47 +5,47 @@ def cryptoProject = project(':spring-security-crypto')
 def cryptoClasses = cryptoProject.sourceSets.main.output
 
 configurations {
-    included
+	included
 
-    compile.extendsFrom included
+	compile.extendsFrom included
 
-    testCompile.exclude group: 'org.mockito', module: 'mockito-all'
+	testCompile.exclude group: 'org.mockito', module: 'mockito-all'
 }
 
 dependencies {
-    compile springCoreDependency,
-            'aopalliance:aopalliance:1.0',
-            "org.springframework:spring-aop:$springVersion",
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-expression:$springVersion"
-
-    optional "net.sf.ehcache:ehcache:$ehcacheVersion",
-             'javax.annotation:jsr250-api:1.0',
-             "org.aspectj:aspectjrt:$aspectjVersion",
-             "org.springframework:spring-jdbc:$springVersion",
-             "org.springframework:spring-tx:$springVersion"
-
-    included cryptoProject
-
-    testCompile "commons-collections:commons-collections:$commonsCollectionsVersion",
-                "org.springframework:spring-test:$springVersion",
-                "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-                powerMockDependencies
-
-    testRuntime "org.hsqldb:hsqldb:$hsqlVersion"
+	compile springCoreDependency,
+			'aopalliance:aopalliance:1.0',
+			"org.springframework:spring-aop:$springVersion",
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-expression:$springVersion"
+
+	optional "net.sf.ehcache:ehcache:$ehcacheVersion",
+			 'javax.annotation:jsr250-api:1.0',
+			 "org.aspectj:aspectjrt:$aspectjVersion",
+			 "org.springframework:spring-jdbc:$springVersion",
+			 "org.springframework:spring-tx:$springVersion"
+
+	included cryptoProject
+
+	testCompile "commons-collections:commons-collections:$commonsCollectionsVersion",
+				"org.springframework:spring-test:$springVersion",
+				"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+				powerMockDependencies
+
+	testRuntime "org.hsqldb:hsqldb:$hsqlVersion"
 }
 
 classes.doLast {
-    copy {
-        from cryptoClasses
-        into sourceSets.main.output.classesDir
-    }
+	copy {
+		from cryptoClasses
+		into sourceSets.main.output.classesDir
+	}
 }
 
 sourceJar.from cryptoProject.sourceSets.main.java
 
 configure(project.tasks.withType(Test)) {
-    systemProperties['springSecurityVersion'] = version
-    systemProperties['springVersion'] = springVersion
+	systemProperties['springSecurityVersion'] = version
+	systemProperties['springVersion'] = springVersion
 }

+ 4 - 4
crypto/crypto.gradle

@@ -5,8 +5,8 @@
 int maxAESKeySize = javax.crypto.Cipher.getMaxAllowedKeyLength('AES')
 
 configure(project.tasks.withType(Test)) {
-    if (maxAESKeySize < 256) {
-        println "AES keysize limited to $maxAESKeySize, skipping EncryptorsTests"
-        exclude '**/EncryptorsTests.class'
-    }
+	if (maxAESKeySize < 256) {
+		println "AES keysize limited to $maxAESKeySize, skipping EncryptorsTests"
+		exclude '**/EncryptorsTests.class'
+	}
 }

+ 3 - 3
data/data.gradle

@@ -1,6 +1,6 @@
 dependencies {
-    compile project(':spring-security-core'),
-            springCoreDependency,
-            "org.springframework.data:spring-data-commons:$springDataCommonsVersion"
+	compile project(':spring-security-core'),
+			springCoreDependency,
+			"org.springframework.data:spring-data-commons:$springDataCommonsVersion"
 
 }

+ 115 - 115
docs/docs.gradle

@@ -1,147 +1,147 @@
-    // Docbook and Javadoc building and uploading tasks
+	// Docbook and Javadoc building and uploading tasks
 apply plugin: 'base'
 
 task docs {
-    dependsOn 'manual:reference', 'apidocs', 'guides:asciidoctor'
+	dependsOn 'manual:reference', 'apidocs', 'guides:asciidoctor'
 }
 
 project('manual') {
-    apply plugin: 'base'
-    apply plugin: 'org.asciidoctor.gradle.asciidoctor'
-    apply plugin: 'docbook-reference'
-
-    ext.expandPlaceholders = ""
-
-    asciidoctorj {
-        version = '1.5.2'
-    }
-
-    asciidoctor {
-        backends = ['docbook5']
-        options = [
-          eruby: 'erubis',
-          attributes: [
-              copycss : '',
-              icons : 'font',
-              'source-highlighter': 'prettify',
-              sectanchors : '',
-              toc2: '',
-              idprefix: '',
-              idseparator: '-',
-              doctype: 'book',
-              numbered: '',
-              'spring-security-version' : project.version,
-              'spring-version' : springVersion,
-              revnumber : project.version
-          ]
-        ]
-    }
-
-    reference {
-        sourceDir = new File(asciidoctor.outputDir , 'docbook5')
-        pdfFilename = "spring-security-reference.pdf"
-        epubFilename = "spring-security-reference.epub"
-        expandPlaceholders = ""
-    }
-
-    afterEvaluate {
-        tasks.findAll { it.name.startsWith("reference") }.each{ it.dependsOn.add("asciidoctor") }
-    }
-
-
-    ext.spec = copySpec {
-        from (reference) {
-            into 'reference'
-        }
-    }
+	apply plugin: 'base'
+	apply plugin: 'org.asciidoctor.gradle.asciidoctor'
+	apply plugin: 'docbook-reference'
+
+	ext.expandPlaceholders = ""
+
+	asciidoctorj {
+		version = '1.5.2'
+	}
+
+	asciidoctor {
+		backends = ['docbook5']
+		options = [
+		  eruby: 'erubis',
+		  attributes: [
+			  copycss : '',
+			  icons : 'font',
+			  'source-highlighter': 'prettify',
+			  sectanchors : '',
+			  toc2: '',
+			  idprefix: '',
+			  idseparator: '-',
+			  doctype: 'book',
+			  numbered: '',
+			  'spring-security-version' : project.version,
+			  'spring-version' : springVersion,
+			  revnumber : project.version
+		  ]
+		]
+	}
+
+	reference {
+		sourceDir = new File(asciidoctor.outputDir , 'docbook5')
+		pdfFilename = "spring-security-reference.pdf"
+		epubFilename = "spring-security-reference.epub"
+		expandPlaceholders = ""
+	}
+
+	afterEvaluate {
+		tasks.findAll { it.name.startsWith("reference") }.each{ it.dependsOn.add("asciidoctor") }
+	}
+
+
+	ext.spec = copySpec {
+		from (reference) {
+			into 'reference'
+		}
+	}
 }
 
 task apidocs(type: Javadoc) {
-    destinationDir = new File(buildDir, 'apidocs')
-    title = "Spring Security $version API"
+	destinationDir = new File(buildDir, 'apidocs')
+	title = "Spring Security $version API"
 
-    source coreModuleProjects.collect { project ->
-        project.sourceSets.main.allJava
-    }
+	source coreModuleProjects.collect { project ->
+		project.sourceSets.main.allJava
+	}
 
-    classpath = files(coreModuleProjects.collect { project ->
-        project.sourceSets.main.compileClasspath
-    })
+	classpath = files(coreModuleProjects.collect { project ->
+		project.sourceSets.main.compileClasspath
+	})
 }
 
 apidocs.options.outputLevel = org.gradle.external.javadoc.JavadocOutputLevel.QUIET
 
 apidocs.options.links = [
-    "http://static.springframework.org/spring/docs/3.2.x/javadoc-api",
-    "http://static.springsource.org/spring-ldap/docs/1.3.x/apidocs/",
-    "http://download.oracle.com/javase/6/docs/api/"
+	"http://static.springframework.org/spring/docs/3.2.x/javadoc-api",
+	"http://static.springsource.org/spring-ldap/docs/1.3.x/apidocs/",
+	"http://download.oracle.com/javase/6/docs/api/"
 ]
 
 apidocs.options.groups = [
-    'Spring Security Core':[
-        'org.springframework.security.core*',
-        'org.springframework.security.authentication*',
-        'org.springframework.security.access*',
-        'org.springframework.security.remoting*',
-        'org.springframework.security.provisioning*',
-        'org.springframework.security.util*'],
-    'Spring Security Web':['org.springframework.security.web*'],
-    'Spring Security LDAP':['org.springframework.security.ldap*'],
-    'Spring Security Crypto':['org.springframework.security.crypto*'],
-    'Spring Security OpenID':['org.springframework.security.openid*'],
-    'Spring Security CAS':['org.springframework.security.cas*'],
-    'Spring Security ACL':['org.springframework.security.acls*'],
-    'Spring Security Config':['org.springframework.security.config*'],
-    'Spring Security Taglibs':['org.springframework.security.taglibs*'],
+	'Spring Security Core':[
+		'org.springframework.security.core*',
+		'org.springframework.security.authentication*',
+		'org.springframework.security.access*',
+		'org.springframework.security.remoting*',
+		'org.springframework.security.provisioning*',
+		'org.springframework.security.util*'],
+	'Spring Security Web':['org.springframework.security.web*'],
+	'Spring Security LDAP':['org.springframework.security.ldap*'],
+	'Spring Security Crypto':['org.springframework.security.crypto*'],
+	'Spring Security OpenID':['org.springframework.security.openid*'],
+	'Spring Security CAS':['org.springframework.security.cas*'],
+	'Spring Security ACL':['org.springframework.security.acls*'],
+	'Spring Security Config':['org.springframework.security.config*'],
+	'Spring Security Taglibs':['org.springframework.security.taglibs*'],
 
 ]
 
 ext.apiSpec = copySpec {
-    into('apidocs') {
-        from(apidocs.destinationDir)
-    }
+	into('apidocs') {
+		from(apidocs.destinationDir)
+	}
 }
 
 assemble.dependsOn = [apidocs, 'manual:asciidoctor']
 
 task docsZip(type: Zip) {
-    dependsOn docs
-    evaluationDependsOn('guides')
-    group = 'Distribution'
-    baseName = rootProject.name
-    classifier = 'docs'
-    description = "Builds -${classifier} archive containing api and reference " +
-        "for deployment at static.springframework.org/spring-security/site/docs."
-
-    with(project(':docs').apiSpec)
-    with(project(':docs:manual').spec)
-    with(project(':docs:guides').spec)
+	dependsOn docs
+	evaluationDependsOn('guides')
+	group = 'Distribution'
+	baseName = rootProject.name
+	classifier = 'docs'
+	description = "Builds -${classifier} archive containing api and reference " +
+		"for deployment at static.springframework.org/spring-security/site/docs."
+
+	with(project(':docs').apiSpec)
+	with(project(':docs:manual').spec)
+	with(project(':docs:guides').spec)
 }
 
 task schemaZip(type: Zip) {
-    group = 'Distribution'
-    baseName = rootProject.name
-    classifier = 'schema'
-    description = "Builds -${classifier} archive containing all " +
-        "XSDs for deployment at static.springframework.org/schema."
-
-    coreModuleProjects.each { module ->
-        def Properties schemas = new Properties();
-
-        module.sourceSets.main.resources.find {
-            it.path.endsWith('META-INF/spring.schemas')
-        }?.withInputStream { schemas.load(it) }
-
-        for (def key : schemas.keySet()) {
-            def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
-            assert shortName != key
-            File xsdFile = module.sourceSets.main.resources.find {
-                it.path.endsWith(schemas.get(key))
-            }
-            assert xsdFile != null
-            into (shortName) {
-                from xsdFile.path
-            }
-        }
-    }
+	group = 'Distribution'
+	baseName = rootProject.name
+	classifier = 'schema'
+	description = "Builds -${classifier} archive containing all " +
+		"XSDs for deployment at static.springframework.org/schema."
+
+	coreModuleProjects.each { module ->
+		def Properties schemas = new Properties();
+
+		module.sourceSets.main.resources.find {
+			it.path.endsWith('META-INF/spring.schemas')
+		}?.withInputStream { schemas.load(it) }
+
+		for (def key : schemas.keySet()) {
+			def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
+			assert shortName != key
+			File xsdFile = module.sourceSets.main.resources.find {
+				it.path.endsWith(schemas.get(key))
+			}
+			assert xsdFile != null
+			into (shortName) {
+				from xsdFile.path
+			}
+		}
+	}
 }

+ 32 - 32
docs/guides/build.gradle

@@ -1,46 +1,46 @@
 apply plugin: 'org.asciidoctor.gradle.asciidoctor'
 
 asciidoctor {
-    baseDir = file('src/docs/asciidoc')
-    options = [
-      eruby: 'erubis',
-      eruby: 'erubis',
-      attributes: [
-          copycss : '',
-          icons : 'font',
-          'source-highlighter': 'prettify',
-          sectanchors : '',
-          toc: '',
-          'toc-placement' : 'preamble',
-          idprefix: '',
-          idseparator: '-',
-          doctype: 'book',
-          'spring-security-version' : project.version,
-          'download-url' : getDownloadUrl(),
-          'include-maven-repository' : getMavenRepositoryInclude(),
-          revnumber : project.version
-      ]
-    ]
+	baseDir = file('src/docs/asciidoc')
+	options = [
+	  eruby: 'erubis',
+	  eruby: 'erubis',
+	  attributes: [
+		  copycss : '',
+		  icons : 'font',
+		  'source-highlighter': 'prettify',
+		  sectanchors : '',
+		  toc: '',
+		  'toc-placement' : 'preamble',
+		  idprefix: '',
+		  idseparator: '-',
+		  doctype: 'book',
+		  'spring-security-version' : project.version,
+		  'download-url' : getDownloadUrl(),
+		  'include-maven-repository' : getMavenRepositoryInclude(),
+		  revnumber : project.version
+	  ]
+	]
 }
 
 ext.spec = copySpec {
-    into ('guides') {
-        from(asciidoctor.outputDir)
-        exclude 'build', 'Guardfile'
-    }
+	into ('guides') {
+		from(asciidoctor.outputDir)
+		exclude 'build', 'Guardfile'
+	}
 }
 
 def getDownloadUrl() {
-    snapshotBuild ? "https://github.com/SpringSource/spring-security/archive/master.zip" : "https://github.com/spring-projects/spring-security/archive/${project.version}.zip"
+	snapshotBuild ? "https://github.com/SpringSource/spring-security/archive/master.zip" : "https://github.com/spring-projects/spring-security/archive/${project.version}.zip"
 }
 
 
 def getMavenRepositoryInclude() {
-    if(snapshotBuild) {
-        return "_includes/maven-repository-snapshot.asc"
-    } else if(releaseBuild) {
-        return "_includes/maven-repository-release.asc"
-    } else {
-        return "_includes/maven-repository-milestone.asc"
-    }
+	if(snapshotBuild) {
+		return "_includes/maven-repository-snapshot.asc"
+	} else if(releaseBuild) {
+		return "_includes/maven-repository-release.asc"
+	} else {
+		return "_includes/maven-repository-milestone.asc"
+	}
 }

+ 124 - 124
gradle/javaprojects.gradle

@@ -41,206 +41,206 @@ ext.thymeleafVersion = '2.1.3.RELEASE'
 ext.thymeleafVersion = '1.2.7.RELEASE'
 
 ext.spockDependencies = [
-    dependencies.create("org.spockframework:spock-spring:$spockVersion") {
-        exclude group: 'junit', module: 'junit-dep'
-    },
-    dependencies.create("org.spockframework:spock-core:$spockVersion") {
-        exclude group: 'junit', module: 'junit-dep'
-    }
+	dependencies.create("org.spockframework:spock-spring:$spockVersion") {
+		exclude group: 'junit', module: 'junit-dep'
+	},
+	dependencies.create("org.spockframework:spock-core:$spockVersion") {
+		exclude group: 'junit', module: 'junit-dep'
+	}
 ]
 
 ext.gebDependencies = spockDependencies + [
-    "org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion",
-    "org.gebish:geb-spock:$gebVersion",
-    'commons-httpclient:commons-httpclient:3.1',
-    "org.codehaus.groovy:groovy:$groovyVersion"
+	"org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion",
+	"org.gebish:geb-spock:$gebVersion",
+	'commons-httpclient:commons-httpclient:3.1',
+	"org.codehaus.groovy:groovy:$groovyVersion"
 ]
 
 ext.powerMockDependencies = [
-    "org.powermock:powermock-core:$powerMockVersion",
-    "org.powermock:powermock-api-support:$powerMockVersion",
-    "org.powermock:powermock-module-junit4-common:$powerMockVersion",
-    "org.powermock:powermock-module-junit4:$powerMockVersion",
-    dependencies.create("org.powermock:powermock-api-mockito:$powerMockVersion") {
-        exclude group: 'org.mockito', module: 'mockito-all'
-    },
-    "org.powermock:powermock-reflect:$powerMockVersion"
+	"org.powermock:powermock-core:$powerMockVersion",
+	"org.powermock:powermock-api-support:$powerMockVersion",
+	"org.powermock:powermock-module-junit4-common:$powerMockVersion",
+	"org.powermock:powermock-module-junit4:$powerMockVersion",
+	dependencies.create("org.powermock:powermock-api-mockito:$powerMockVersion") {
+		exclude group: 'org.mockito', module: 'mockito-all'
+	},
+	"org.powermock:powermock-reflect:$powerMockVersion"
 ]
 
 ext.springCoreDependency = [
-    dependencies.create("org.springframework:spring-core:$springVersion") {
-        exclude(group: 'commons-logging', module: 'commons-logging')
-    }
+	dependencies.create("org.springframework:spring-core:$springVersion") {
+		exclude(group: 'commons-logging', module: 'commons-logging')
+	}
 ]
 
 ext.jstlDependencies = [
-        "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
-        "org.apache.taglibs:taglibs-standard-jstlel:1.2.1"
+		"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
+		"org.apache.taglibs:taglibs-standard-jstlel:1.2.1"
 ]
 
 ext.apachedsDependencies = [
-         "org.apache.directory.server:apacheds-core:$apacheDsVersion",
-         "org.apache.directory.server:apacheds-core-entry:$apacheDsVersion",
-         "org.apache.directory.server:apacheds-protocol-shared:$apacheDsVersion",
-         "org.apache.directory.server:apacheds-protocol-ldap:$apacheDsVersion",
-         "org.apache.directory.server:apacheds-server-jndi:$apacheDsVersion",
-         'org.apache.directory.shared:shared-ldap:0.9.15'
+		 "org.apache.directory.server:apacheds-core:$apacheDsVersion",
+		 "org.apache.directory.server:apacheds-core-entry:$apacheDsVersion",
+		 "org.apache.directory.server:apacheds-protocol-shared:$apacheDsVersion",
+		 "org.apache.directory.server:apacheds-protocol-ldap:$apacheDsVersion",
+		 "org.apache.directory.server:apacheds-server-jndi:$apacheDsVersion",
+		 'org.apache.directory.shared:shared-ldap:0.9.15'
 ]
 
 // Integration test setup
 configurations {
-    integrationTestCompile {
-        extendsFrom testCompile, optional, provided
-    }
-    integrationTestRuntime {
-        extendsFrom integrationTestCompile, testRuntime
-    }
+	integrationTestCompile {
+		extendsFrom testCompile, optional, provided
+	}
+	integrationTestRuntime {
+		extendsFrom integrationTestCompile, testRuntime
+	}
 }
 
 sourceSets {
-    integrationTest {
-        java.srcDir file('src/integration-test/java')
-        groovy.srcDirs file('src/integration-test/groovy')
-        resources.srcDir file('src/integration-test/resources')
-        compileClasspath = sourceSets.main.output + sourceSets.test.output + configurations.integrationTestCompile
-        runtimeClasspath = output + compileClasspath + configurations.integrationTestRuntime
-    }
+	integrationTest {
+		java.srcDir file('src/integration-test/java')
+		groovy.srcDirs file('src/integration-test/groovy')
+		resources.srcDir file('src/integration-test/resources')
+		compileClasspath = sourceSets.main.output + sourceSets.test.output + configurations.integrationTestCompile
+		runtimeClasspath = output + compileClasspath + configurations.integrationTestRuntime
+	}
 }
 
 task integrationTest(type: Test, dependsOn: jar) {
-    testClassesDir = sourceSets.integrationTest.output.classesDir
-    logging.captureStandardOutput(LogLevel.INFO)
-    classpath = sourceSets.integrationTest.runtimeClasspath
-    maxParallelForks = 1
-    reports {
-        html.destination = project.file("$project.buildDir/reports/integration-tests/")
-        junitXml.destination = project.file("$project.buildDir/integration-test-results/")
-    }
+	testClassesDir = sourceSets.integrationTest.output.classesDir
+	logging.captureStandardOutput(LogLevel.INFO)
+	classpath = sourceSets.integrationTest.runtimeClasspath
+	maxParallelForks = 1
+	reports {
+		html.destination = project.file("$project.buildDir/reports/integration-tests/")
+		junitXml.destination = project.file("$project.buildDir/integration-test-results/")
+	}
 }
 
 eclipse {
-    classpath {
-        plusConfigurations += [ configurations.integrationTestCompile ]
-    }
+	classpath {
+		plusConfigurations += [ configurations.integrationTestCompile ]
+	}
 }
 project.conf2ScopeMappings.addMapping(MavenPlugin.TEST_COMPILE_PRIORITY + 1, project.configurations.getByName("integrationTestCompile"), Conf2ScopeMappingContainer.TEST)
 project.conf2ScopeMappings.addMapping(MavenPlugin.TEST_COMPILE_PRIORITY + 2, project.configurations.getByName("integrationTestRuntime"), Conf2ScopeMappingContainer.TEST)
 check.dependsOn integrationTest
 
 dependencies {
-    optional "commons-logging:commons-logging:$commonsLoggingVersion"
+	optional "commons-logging:commons-logging:$commonsLoggingVersion"
 
-    testCompile "junit:junit:$junitVersion",
-            'org.mockito:mockito-core:1.9.5',
-            "org.springframework:spring-test:$springVersion",
-            'org.easytesting:fest-assert:1.4'
+	testCompile "junit:junit:$junitVersion",
+			'org.mockito:mockito-core:1.9.5',
+			"org.springframework:spring-test:$springVersion",
+			'org.easytesting:fest-assert:1.4'
 
-    // Use slf4j/logback for logging
-    testRuntime "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-                "ch.qos.logback:logback-classic:$logbackVersion"
+	// Use slf4j/logback for logging
+	testRuntime "org.slf4j:jcl-over-slf4j:$slf4jVersion",
+				"ch.qos.logback:logback-classic:$logbackVersion"
 }
 
 [configurations.runtime, configurations.default, configurations.testCompile]*.exclude(module: 'commons-logging')
 
 configurations.all {
-    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
-            if (details.requested.group == 'org.slf4j') {
-                details.useVersion slf4jVersion
-            }
-    }
+	resolutionStrategy.eachDependency { DependencyResolveDetails details ->
+			if (details.requested.group == 'org.slf4j') {
+				details.useVersion slf4jVersion
+			}
+	}
 }
 
 [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
 
 project.tasks.matching { it instanceof Test && it.name != 'integrationTest' }.all {
-    jvmArgs = ['-ea', '-Xmx500m', '-XX:MaxPermSize=256M']
-    maxParallelForks = guessMaxForks()
-    logging.captureStandardOutput(LogLevel.INFO)
+	jvmArgs = ['-ea', '-Xmx500m', '-XX:MaxPermSize=256M']
+	maxParallelForks = guessMaxForks()
+	logging.captureStandardOutput(LogLevel.INFO)
 }
 
 def guessMaxForks() {
-    int processors = Runtime.runtime.availableProcessors()
-    return Math.max(2, (int) (processors / 2))
+	int processors = Runtime.runtime.availableProcessors()
+	return Math.max(2, (int) (processors / 2))
 }
 
 javadoc {
-    title = "Spring Security $version API"
-    source = sourceSets.main.allJava
-    options {
-        memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
-        author = true
-        header = project.name
-        outputLevel = org.gradle.external.javadoc.JavadocOutputLevel.QUIET
-        links = [
-            "http://static.springsource.org/spring/docs/3.2.x/javadoc-api/",
-            "http://static.springsource.org/spring-ldap/docs/1.3.x/apidocs/",
-            "http://download.oracle.com/javase/6/docs/api/"
-        ]
-        groups = [
-            'Spring Security Core':[
-                'org.springframework.security.core*',
-                'org.springframework.security.authentication*',
-                'org.springframework.security.access*',
-                'org.springframework.security.remoting*',
-                'org.springframework.security.provisioning*',
-                'org.springframework.security.util*'],
-            'Spring Security Web':['org.springframework.security.web*'],
-            'Spring Security LDAP':['org.springframework.security.ldap*'],
-            'Spring Security Crypto':['org.springframework.security.crypto*'],
-            'Spring Security OpenID':['org.springframework.security.openid*'],
-            'Spring Security CAS':['org.springframework.security.cas*'],
-            'Spring Security ACL':['org.springframework.security.acls*'],
-            'Spring Security Config':['org.springframework.security.config*'],
-            'Spring Security Taglibs':['org.springframework.security.taglibs*'],
-        ]
-    }
+	title = "Spring Security $version API"
+	source = sourceSets.main.allJava
+	options {
+		memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
+		author = true
+		header = project.name
+		outputLevel = org.gradle.external.javadoc.JavadocOutputLevel.QUIET
+		links = [
+			"http://static.springsource.org/spring/docs/3.2.x/javadoc-api/",
+			"http://static.springsource.org/spring-ldap/docs/1.3.x/apidocs/",
+			"http://download.oracle.com/javase/6/docs/api/"
+		]
+		groups = [
+			'Spring Security Core':[
+				'org.springframework.security.core*',
+				'org.springframework.security.authentication*',
+				'org.springframework.security.access*',
+				'org.springframework.security.remoting*',
+				'org.springframework.security.provisioning*',
+				'org.springframework.security.util*'],
+			'Spring Security Web':['org.springframework.security.web*'],
+			'Spring Security LDAP':['org.springframework.security.ldap*'],
+			'Spring Security Crypto':['org.springframework.security.crypto*'],
+			'Spring Security OpenID':['org.springframework.security.openid*'],
+			'Spring Security CAS':['org.springframework.security.cas*'],
+			'Spring Security ACL':['org.springframework.security.acls*'],
+			'Spring Security Config':['org.springframework.security.config*'],
+			'Spring Security Taglibs':['org.springframework.security.taglibs*'],
+		]
+	}
 }
 
 eclipse.classpath.downloadSources = true
 
 // http://forums.gradle.org/gradle/topics/eclipse_wtp_deploys_testcode_to_server_example_provided
 eclipse.classpath {
-    defaultOutputDir = file('bin/main')
-    file.whenMerged { cp ->
-        cp.entries.findAll { it instanceof SourceFolder && (it.path.contains("test") || it.path.contains("Test")) }*.output = "bin/test"
-    }
+	defaultOutputDir = file('bin/main')
+	file.whenMerged { cp ->
+		cp.entries.findAll { it instanceof SourceFolder && (it.path.contains("test") || it.path.contains("Test")) }*.output = "bin/test"
+	}
 }
 
 // GRADLE-1116
 project.eclipse.classpath.file.whenMerged { classpath ->
-    classpath.entries.removeAll { entry -> entry.path.endsWith('/build/resources/test') }
-    classpath.entries.removeAll { entry -> entry.path.endsWith('/build/classes/test') }
-    classpath.entries.removeAll { entry -> entry.path.endsWith('/build/resources/main') }
-    classpath.entries.removeAll { entry -> entry.path.endsWith('/build/classes/main') }
+	classpath.entries.removeAll { entry -> entry.path.endsWith('/build/resources/test') }
+	classpath.entries.removeAll { entry -> entry.path.endsWith('/build/classes/test') }
+	classpath.entries.removeAll { entry -> entry.path.endsWith('/build/resources/main') }
+	classpath.entries.removeAll { entry -> entry.path.endsWith('/build/classes/main') }
 }
 
 // GRADLE-1422
 project.eclipseClasspath.doFirst {
    // delay adding whenMerged till the entryAttributes are added (must be the last whenMerged)
    project.eclipse.classpath.file.whenMerged { classpath ->
-       def includeDeps = project.configurations.getByName('runtime').collect {f -> f.absolutePath } as Set
-       classpath.entries.each { cp ->
-           if(cp instanceof org.gradle.plugins.ide.eclipse.model.Library) {
-               def include = includeDeps.contains(cp.path)
-               def attr = 'org.eclipse.jst.component.dependency'
-               if(!include) {
-                   cp.entryAttributes.remove(attr)
-               }
-           }
-       }
+	   def includeDeps = project.configurations.getByName('runtime').collect {f -> f.absolutePath } as Set
+	   classpath.entries.each { cp ->
+		   if(cp instanceof org.gradle.plugins.ide.eclipse.model.Library) {
+			   def include = includeDeps.contains(cp.path)
+			   def attr = 'org.eclipse.jst.component.dependency'
+			   if(!include) {
+				   cp.entryAttributes.remove(attr)
+			   }
+		   }
+	   }
    }
 }
 
 project.idea.module {
-    scopes.TEST.plus += [project.configurations.integrationTestRuntime]
-    testSourceDirs += sourceSets.integrationTest.resources.srcDirs
+	scopes.TEST.plus += [project.configurations.integrationTestRuntime]
+	testSourceDirs += sourceSets.integrationTest.resources.srcDirs
 }
 
 task javadocJar(type: Jar) {
-    classifier = 'javadoc'
-    from javadoc
+	classifier = 'javadoc'
+	from javadoc
 }
 
 artifacts {
-    archives javadocJar
+	archives javadocJar
 }

+ 101 - 101
gradle/maven-deployment.gradle

@@ -2,129 +2,129 @@ apply plugin: 'maven'
 
 // Create a source jar for uploading
 task sourceJar(type: Jar) {
-    classifier = 'sources'
-    from sourceSets.main.java.srcDirs
-    include '**/*.java', '**/*.aj'
+	classifier = 'sources'
+	from sourceSets.main.java.srcDirs
+	include '**/*.java', '**/*.aj'
 }
 
 artifacts {
-    archives sourceJar
+	archives sourceJar
 }
 
 // Configuration for SpringSource s3 maven deployer
 configurations {
-    deployerJars
+	deployerJars
 }
 dependencies {
-    deployerJars "org.springframework.build.aws:org.springframework.build.aws.maven:3.0.0.RELEASE"
+	deployerJars "org.springframework.build.aws:org.springframework.build.aws.maven:3.0.0.RELEASE"
 }
 
 install {
-    repositories.mavenInstaller {
-        customizePom(pom, project)
-    }
+	repositories.mavenInstaller {
+		customizePom(pom, project)
+	}
 }
 
 def customizePom(pom, gradleProject) {
-    pom.whenConfigured { p ->
-        p.dependencies.findAll{ it.scope == "optional" }.each {
-            it.scope = "compile"
-            it.optional = true
-        }
-        // sort to make pom dependencies order consistent to ease comparison of older poms
-        p.dependencies = p.dependencies.sort { dep ->
-            "$dep.scope:$dep.optional:$dep.groupId:$dep.artifactId"
-        }
-    }
-    def isWar = project.hasProperty('war')
-    pom.project {
-        name = gradleProject.name
-        if(isWar) {
-            packaging = "war"
-        }
-        description = gradleProject.name
-        url = 'http://spring.io/spring-security'
-        organization {
-            name = 'spring.io'
-            url = 'http://spring.io/'
-        }
-        licenses {
-            license {
-                name 'The Apache Software License, Version 2.0'
-                url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
-                distribution 'repo'
-            }
-        }
-        scm {
-            url = 'https://github.com/spring-projects/spring-security'
-            connection = 'scm:git:git://github.com/spring-projects/spring-security'
-            developerConnection = 'scm:git:git://github.com/spring-projects/spring-security'
-        }
-        developers {
-            developer {
-                id = 'rwinch'
-                name = 'Rob Winch'
-                email = 'rwinch@gopivotal.com'
-            }
-        }
-        if(isWar) {
-            properties {
-                'm2eclipse.wtp.contextRoot' '/' + project.war.baseName
-            }
-        }
-        if(project.snapshotBuild) {
-            repositories {
-                repository {
-                    id 'spring-snasphot'
-                    url 'https://repo.spring.io/snapshot'
-                }
-            }
-        } else if(!project.releaseBuild) {
-            repositories {
-                repository {
-                    id 'spring-milestone'
-                    url 'https://repo.spring.io/milestone'
-                }
-            }
-        }
-    }
+	pom.whenConfigured { p ->
+		p.dependencies.findAll{ it.scope == "optional" }.each {
+			it.scope = "compile"
+			it.optional = true
+		}
+		// sort to make pom dependencies order consistent to ease comparison of older poms
+		p.dependencies = p.dependencies.sort { dep ->
+			"$dep.scope:$dep.optional:$dep.groupId:$dep.artifactId"
+		}
+	}
+	def isWar = project.hasProperty('war')
+	pom.project {
+		name = gradleProject.name
+		if(isWar) {
+			packaging = "war"
+		}
+		description = gradleProject.name
+		url = 'http://spring.io/spring-security'
+		organization {
+			name = 'spring.io'
+			url = 'http://spring.io/'
+		}
+		licenses {
+			license {
+				name 'The Apache Software License, Version 2.0'
+				url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+				distribution 'repo'
+			}
+		}
+		scm {
+			url = 'https://github.com/spring-projects/spring-security'
+			connection = 'scm:git:git://github.com/spring-projects/spring-security'
+			developerConnection = 'scm:git:git://github.com/spring-projects/spring-security'
+		}
+		developers {
+			developer {
+				id = 'rwinch'
+				name = 'Rob Winch'
+				email = 'rwinch@gopivotal.com'
+			}
+		}
+		if(isWar) {
+			properties {
+				'm2eclipse.wtp.contextRoot' '/' + project.war.baseName
+			}
+		}
+		if(project.snapshotBuild) {
+			repositories {
+				repository {
+					id 'spring-snasphot'
+					url 'https://repo.spring.io/snapshot'
+				}
+			}
+		} else if(!project.releaseBuild) {
+			repositories {
+				repository {
+					id 'spring-milestone'
+					url 'https://repo.spring.io/milestone'
+				}
+			}
+		}
+	}
 
-    // http://forums.gradle.org/gradle/topics/after_upgrade_gradle_to_2_0_version_the_maven_pom_not_support_build_property
-    pom.withXml {
-        def plugins = asNode().appendNode('build').appendNode('plugins')
-        plugins
-            .appendNode('plugin')
-                .appendNode('artifactId','maven-compiler-plugin').parent()
-                .appendNode('configuration')
-                    .appendNode('source','1.7').parent()
-                    .appendNode('target','1.7')
-        if(isWar) {
-            plugins
-                .appendNode('plugin')
-                    .appendNode('artifactId','maven-war-plugin').parent()
-                    .appendNode('version','2.3').parent()
-                    .appendNode('configuration')
-                        .appendNode('failOnMissingWebXml','false')
-        }
-    }
+	// http://forums.gradle.org/gradle/topics/after_upgrade_gradle_to_2_0_version_the_maven_pom_not_support_build_property
+	pom.withXml {
+		def plugins = asNode().appendNode('build').appendNode('plugins')
+		plugins
+			.appendNode('plugin')
+				.appendNode('artifactId','maven-compiler-plugin').parent()
+				.appendNode('configuration')
+					.appendNode('source','1.7').parent()
+					.appendNode('target','1.7')
+		if(isWar) {
+			plugins
+				.appendNode('plugin')
+					.appendNode('artifactId','maven-war-plugin').parent()
+					.appendNode('version','2.3').parent()
+					.appendNode('configuration')
+						.appendNode('failOnMissingWebXml','false')
+		}
+	}
 }
 
 task generatePom {
-    group = 'Build'
-    description = 'Generates a Maven pom.xml'
+	group = 'Build'
+	description = 'Generates a Maven pom.xml'
 
-    ext.generatedPomFileName = "pom.xml"
-    onlyIf { install.enabled }
+	ext.generatedPomFileName = "pom.xml"
+	onlyIf { install.enabled }
 
-    inputs.files(fileTree(project.rootProject.rootDir).include("**/*.gradle").files)
-    inputs.files(new File(project.rootProject.rootDir, Project.GRADLE_PROPERTIES))
-    outputs.files(generatedPomFileName)
+	inputs.files(fileTree(project.rootProject.rootDir).include("**/*.gradle").files)
+	inputs.files(new File(project.rootProject.rootDir, Project.GRADLE_PROPERTIES))
+	outputs.files(generatedPomFileName)
 
-    doLast() {
-        def p = pom {}
-        customizePom(p, project)
-        p.writeTo(generatedPomFileName)
-    }
+	doLast() {
+		def p = pom {}
+		customizePom(p, project)
+		p.writeTo(generatedPomFileName)
+	}
 }
 
 build.dependsOn generatePom

+ 14 - 14
gradle/release-checks.gradle

@@ -1,22 +1,22 @@
 task checkDependencies << {
-    verifyNoDependenciesMatchingVersion(".*-SNAPSHOT")
-    if(releaseBuild) {
-        verifyNoDependenciesMatchingVersion(".*M.*")
-        verifyNoDependenciesMatchingVersion(".*RC.*")
-    }
+	verifyNoDependenciesMatchingVersion(".*-SNAPSHOT")
+	if(releaseBuild) {
+		verifyNoDependenciesMatchingVersion(".*M.*")
+		verifyNoDependenciesMatchingVersion(".*RC.*")
+	}
 }
 
 if(!snapshotBuild) {
-    tasks.findByPath('check')?.dependsOn checkDependencies
+	tasks.findByPath('check')?.dependsOn checkDependencies
 }
 
 def verifyNoDependenciesMatchingVersion(def pattern) {
-    def dependencies = configurations.all*.allDependencies*.findAll { d ->
-        def ignored = 'io.spring.platform:platform-versions'
-        def groupAndName = "$d.group:$d.name".toString()
-        ignored != groupAndName && 	d.version?.matches(pattern)
-    }.flatten().toSet().join("\n    ")
-    if(dependencies) {
-        throw new GradleException("${project.name} cannot have dependencies with a version that matches $pattern when its version is ${project.version}. Got\n    $dependencies")
-    }
+	def dependencies = configurations.all*.allDependencies*.findAll { d ->
+		def ignored = 'io.spring.platform:platform-versions'
+		def groupAndName = "$d.group:$d.name".toString()
+		ignored != groupAndName &&	d.version?.matches(pattern)
+	}.flatten().toSet().join("\n	")
+	if(dependencies) {
+		throw new GradleException("${project.name} cannot have dependencies with a version that matches $pattern when its version is ${project.version}. Got\n	  $dependencies")
+	}
 }

+ 49 - 49
gradle/tomcat.gradle

@@ -1,68 +1,68 @@
 buildscript {
-    repositories {
-        maven { url "https://repo.spring.io/plugins-release" }
-    }
-    dependencies {
-        classpath("org.gradle.api.plugins:gradle-tomcat-plugin:1.2.5")
-    }
+	repositories {
+		maven { url "https://repo.spring.io/plugins-release" }
+	}
+	dependencies {
+		classpath("org.gradle.api.plugins:gradle-tomcat-plugin:1.2.5")
+	}
 }
 
 apply plugin: 'tomcat'
 
 dependencies {
-    def tomcatVersion = '7.0.54'
-    tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
-           "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",
-           "org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}"
-    tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
-        exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
-    }
+	def tomcatVersion = '7.0.54'
+	tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
+		   "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",
+		   "org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}"
+	tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
+		exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
+	}
 }
 
 task integrationTomcatRun(type: org.gradle.api.plugins.tomcat.tasks.TomcatRun) {
-    onlyIf { !sourceSets.integrationTest.allSource.empty }
-    buildscriptClasspath = tomcatRun.buildscriptClasspath
-    contextPath = tomcatRun.contextPath
-    daemon = true
-    tomcatClasspath = tomcatRun.tomcatClasspath
-    webAppClasspath = tomcatRun.webAppClasspath
-    webAppSourceDirectory = tomcatRun.webAppSourceDirectory
-    doFirst {
-        def mainOutputDir = project.sourceSets.main.output.classesDir
-        if(mainOutputDir) {
-            classesDirectory = mainOutputDir
-        }
-        // delay reserving ports to ensure they are still available
-        def ports = reservePorts(3)
-        httpPort = ports[0]
-        ajpPort = ports[1]
-        stopPort = ports[2]
-    }
+	onlyIf { !sourceSets.integrationTest.allSource.empty }
+	buildscriptClasspath = tomcatRun.buildscriptClasspath
+	contextPath = tomcatRun.contextPath
+	daemon = true
+	tomcatClasspath = tomcatRun.tomcatClasspath
+	webAppClasspath = tomcatRun.webAppClasspath
+	webAppSourceDirectory = tomcatRun.webAppSourceDirectory
+	doFirst {
+		def mainOutputDir = project.sourceSets.main.output.classesDir
+		if(mainOutputDir) {
+			classesDirectory = mainOutputDir
+		}
+		// delay reserving ports to ensure they are still available
+		def ports = reservePorts(3)
+		httpPort = ports[0]
+		ajpPort = ports[1]
+		stopPort = ports[2]
+	}
 }
 
 task integrationTomcatStop(type: org.gradle.api.plugins.tomcat.tasks.TomcatStop) {
-    onlyIf { !sourceSets.integrationTest.allSource.empty }
-    doFirst {
-        stopPort = integrationTomcatRun.stopPort
-    }
+	onlyIf { !sourceSets.integrationTest.allSource.empty }
+	doFirst {
+		stopPort = integrationTomcatRun.stopPort
+	}
 }
 
 integrationTest {
-    dependsOn integrationTomcatRun
-    doFirst {
-        def host = 'localhost:' + integrationTomcatRun.httpPort
-        systemProperties['geb.build.baseUrl'] = 'http://'+host+'/' + integrationTomcatRun.contextPath + '/'
-        systemProperties['geb.build.reportsDir'] = 'build/geb-reports'
-    }
-    finalizedBy integrationTomcatStop
+	dependsOn integrationTomcatRun
+	doFirst {
+		def host = 'localhost:' + integrationTomcatRun.httpPort
+		systemProperties['geb.build.baseUrl'] = 'http://'+host+'/' + integrationTomcatRun.contextPath + '/'
+		systemProperties['geb.build.reportsDir'] = 'build/geb-reports'
+	}
+	finalizedBy integrationTomcatStop
 }
 
 def reservePorts(int count) {
-    def sockets = []
-    for(int i in 1..count) {
-        sockets << new ServerSocket(0)
-    }
-    def result = sockets*.localPort
-    sockets*.close()
-    result
+	def sockets = []
+	for(int i in 1..count) {
+		sockets << new ServerSocket(0)
+	}
+	def result = sockets*.localPort
+	sockets*.close()
+	result
 }

+ 2 - 2
gradle/war-sample.gradle

@@ -2,9 +2,9 @@ apply plugin: 'war'
 apply from: TOMCAT_GRADLE
 
 war {
-    baseName = "sample"
+	baseName = "sample"
 }
 
 sonarRunner {
-    skipProject = true
+	skipProject = true
 }

+ 12 - 12
itest/context/itest-context.gradle

@@ -1,17 +1,17 @@
 System.setProperty('python.cachedir.skip', 'true')
 
 dependencies {
-    compile     project(':spring-security-core'),
-                'aopalliance:aopalliance:1.0',
-                'org.python:jython:2.5.0',
-                "org.springframework:spring-context:$springVersion",
-                "org.springframework:spring-aop:$springVersion",
-                "org.springframework:spring-tx:$springVersion",
-                "org.springframework:spring-beans:$springVersion"
+	compile		project(':spring-security-core'),
+				'aopalliance:aopalliance:1.0',
+				'org.python:jython:2.5.0',
+				"org.springframework:spring-context:$springVersion",
+				"org.springframework:spring-aop:$springVersion",
+				"org.springframework:spring-tx:$springVersion",
+				"org.springframework:spring-beans:$springVersion"
 
-    testCompile project(':spring-security-web'),
-                "javax.servlet:javax.servlet-api:$servletApiVersion",
-                "org.springframework:spring-web:$springVersion"
-    testRuntime project(':spring-security-config'),
-                "org.aspectj:aspectjweaver:$aspectjVersion"
+	testCompile project(':spring-security-web'),
+				"javax.servlet:javax.servlet-api:$servletApiVersion",
+				"org.springframework:spring-web:$springVersion"
+	testRuntime project(':spring-security-config'),
+				"org.aspectj:aspectjweaver:$aspectjVersion"
 }

+ 29 - 29
itest/web/itest-web.gradle

@@ -1,38 +1,38 @@
 
 dependencies {
-    compile     "org.springframework:spring-context:$springVersion",
-                "org.springframework:spring-web:$springVersion"
+	compile		"org.springframework:spring-context:$springVersion",
+				"org.springframework:spring-web:$springVersion"
 
-    provided "javax.servlet:javax.servlet-api:$servletApiVersion"
+	provided "javax.servlet:javax.servlet-api:$servletApiVersion"
 
-    testCompile project(':spring-security-core'),
-                project(':spring-security-web'),
-                project(':spring-security-taglibs'),
-                "org.springframework:spring-beans:$springVersion",
-                "org.springframework:spring-webmvc:$springVersion",
-                "org.mortbay.jetty:jetty-util:$jettyVersion",
-                "org.testng:testng:5.11:jdk15"
-    testCompile ("org.mortbay.jetty:jetty:$jettyVersion") {
-        exclude group: 'org.mortbay.jetty', module: 'servlet-api'
-    }
-    testCompile ('net.sourceforge.jwebunit:jwebunit-core:2.2') {
-        exclude group: 'javax.servlet', module: 'servlet-api'
-        exclude group: 'regexp', module: 'regexp'
-    }
+	testCompile project(':spring-security-core'),
+				project(':spring-security-web'),
+				project(':spring-security-taglibs'),
+				"org.springframework:spring-beans:$springVersion",
+				"org.springframework:spring-webmvc:$springVersion",
+				"org.mortbay.jetty:jetty-util:$jettyVersion",
+				"org.testng:testng:5.11:jdk15"
+	testCompile ("org.mortbay.jetty:jetty:$jettyVersion") {
+		exclude group: 'org.mortbay.jetty', module: 'servlet-api'
+	}
+	testCompile ('net.sourceforge.jwebunit:jwebunit-core:2.2') {
+		exclude group: 'javax.servlet', module: 'servlet-api'
+		exclude group: 'regexp', module: 'regexp'
+	}
 
-    testRuntime project(':spring-security-config'),
-                project(':spring-security-ldap'),
-                "org.mortbay.jetty:jsp-2.1-jetty:$jettyVersion",
-    testRuntime ('net.sourceforge.jwebunit:jwebunit-htmlunit-plugin:2.2') {
-        exclude group: 'javax.servlet', module: 'servlet-api'
-    }
+	testRuntime project(':spring-security-config'),
+				project(':spring-security-ldap'),
+				"org.mortbay.jetty:jsp-2.1-jetty:$jettyVersion",
+	testRuntime ('net.sourceforge.jwebunit:jwebunit-htmlunit-plugin:2.2') {
+		exclude group: 'javax.servlet', module: 'servlet-api'
+	}
 }
 
 integrationTest {
-    useTestNG();
-    options {
-        jvmArgs = ["-ea", '-Xms128m', '-Xmx500m']
-        systemProperties = ['webapp.dir': "$projectDir/src/main/webapp"]
-    }
-    maxParallelForks = 1
+	useTestNG();
+	options {
+		jvmArgs = ["-ea", '-Xms128m', '-Xmx500m']
+		systemProperties = ['webapp.dir': "$projectDir/src/main/webapp"]
+	}
+	maxParallelForks = 1
 }

+ 26 - 26
ldap/ldap.gradle

@@ -1,41 +1,41 @@
 // Ldap build file
 
 dependencies {
-    compile project(':spring-security-core'),
-            springCoreDependency,
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-tx:$springVersion"
+	compile project(':spring-security-core'),
+			springCoreDependency,
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-tx:$springVersion"
 
-    optional "org.apache.directory.server:apacheds-core:$apacheDsVersion",
-             "org.apache.directory.server:apacheds-core-entry:$apacheDsVersion",
-             "org.apache.directory.server:apacheds-protocol-shared:$apacheDsVersion",
-             "org.apache.directory.server:apacheds-protocol-ldap:$apacheDsVersion",
-             "org.apache.directory.server:apacheds-server-jndi:$apacheDsVersion",
-             'org.apache.directory.shared:shared-ldap:0.9.15',
-             'ldapsdk:ldapsdk:4.1'
+	optional "org.apache.directory.server:apacheds-core:$apacheDsVersion",
+			 "org.apache.directory.server:apacheds-core-entry:$apacheDsVersion",
+			 "org.apache.directory.server:apacheds-protocol-shared:$apacheDsVersion",
+			 "org.apache.directory.server:apacheds-protocol-ldap:$apacheDsVersion",
+			 "org.apache.directory.server:apacheds-server-jndi:$apacheDsVersion",
+			 'org.apache.directory.shared:shared-ldap:0.9.15',
+			 'ldapsdk:ldapsdk:4.1'
 
-    compile ("org.springframework.ldap:spring-ldap-core:$springLdapVersion") {
-        exclude(group: 'commons-logging', module: 'commons-logging')
-        exclude(group: 'org.springframework', module: 'spring-core')
-        exclude(group: 'org.springframework', module: 'spring-tx')
-        exclude(group: 'org.springframework', module: 'spring-beans')
-        exclude(group: 'org.springframework.data', module: 'spring-data-commons')
-    }
+	compile ("org.springframework.ldap:spring-ldap-core:$springLdapVersion") {
+		exclude(group: 'commons-logging', module: 'commons-logging')
+		exclude(group: 'org.springframework', module: 'spring-core')
+		exclude(group: 'org.springframework', module: 'spring-tx')
+		exclude(group: 'org.springframework', module: 'spring-beans')
+		exclude(group: 'org.springframework.data', module: 'spring-data-commons')
+	}
 
-    testCompile "org.slf4j:slf4j-api:$slf4jVersion",
-                "org.slf4j:jcl-over-slf4j:$slf4jVersion"
+	testCompile "org.slf4j:slf4j-api:$slf4jVersion",
+				"org.slf4j:jcl-over-slf4j:$slf4jVersion"
 }
 
 integrationTest {
-    include('**/ApacheDSServerIntegrationTests.class')
-//    exclude('**/OpenLDAPIntegrationTestSuite.class')
-    maxParallelForks = 1
+	include('**/ApacheDSServerIntegrationTests.class')
+//	  exclude('**/OpenLDAPIntegrationTestSuite.class')
+	maxParallelForks = 1
 }
 
 // Runs a server for running the integration tests against (from an IDE, for example)
 task(ldapServer, dependsOn: 'integrationTestClasses', type: JavaExec) {
-    classpath = sourceSets.integrationTest.runtimeClasspath
-    main = 'org.springframework.security.ldap.ApacheDSServerIntegrationTests'
+	classpath = sourceSets.integrationTest.runtimeClasspath
+	main = 'org.springframework.security.ldap.ApacheDSServerIntegrationTests'
 }
 

+ 17 - 17
messaging/messaging.gradle

@@ -1,24 +1,24 @@
 apply plugin: 'groovy'
 
 dependencies {
-    compile project(':spring-security-core'),
-            springCoreDependency,
-            'aopalliance:aopalliance:1.0',
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-expression:$springVersion",
-            "org.springframework:spring-messaging:$springVersion"
+	compile project(':spring-security-core'),
+			springCoreDependency,
+			'aopalliance:aopalliance:1.0',
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-expression:$springVersion",
+			"org.springframework:spring-messaging:$springVersion"
 
-    optional project(':spring-security-web'),
-            "org.springframework:spring-websocket:$springVersion",
-            "javax.servlet:javax.servlet-api:$servletApiVersion"
+	optional project(':spring-security-web'),
+			"org.springframework:spring-websocket:$springVersion",
+			"javax.servlet:javax.servlet-api:$servletApiVersion"
 
-    testCompile project(':spring-security-core').sourceSets.test.output,
-                "commons-codec:commons-codec:$commonsCodecVersion",
-                "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-                "org.codehaus.groovy:groovy-all:$groovyVersion",
-                powerMockDependencies,
-                spockDependencies
+	testCompile project(':spring-security-core').sourceSets.test.output,
+				"commons-codec:commons-codec:$commonsCodecVersion",
+				"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+				"org.codehaus.groovy:groovy-all:$groovyVersion",
+				powerMockDependencies,
+				spockDependencies
 
-    testRuntime "org.hsqldb:hsqldb:$hsqlVersion"
+	testRuntime "org.hsqldb:hsqldb:$hsqlVersion"
 }

+ 17 - 17
openid/openid.gradle

@@ -1,24 +1,24 @@
 // OpenID Module build file
 
 dependencies {
-    compile project(':spring-security-core'),
-            project(':spring-security-web'),
-            springCoreDependency,
-            "org.springframework:spring-aop:$springVersion",
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-web:$springVersion"
+	compile project(':spring-security-core'),
+			project(':spring-security-web'),
+			springCoreDependency,
+			"org.springframework:spring-aop:$springVersion",
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-web:$springVersion"
 
-    // openid4java has a compile time dep on guice with a group
-    // name which is different from the maven central one.
-    // We use the maven central version here instead.
-    compile('org.openid4java:openid4java-nodeps:0.9.6') {
-       exclude group: 'com.google.code.guice', module: 'guice'
-    }
-    compile 'com.google.inject:guice:2.0'
+	// openid4java has a compile time dep on guice with a group
+	// name which is different from the maven central one.
+	// We use the maven central version here instead.
+	compile('org.openid4java:openid4java-nodeps:0.9.6') {
+	   exclude group: 'com.google.code.guice', module: 'guice'
+	}
+	compile 'com.google.inject:guice:2.0'
 
-    provided "javax.servlet:javax.servlet-api:$servletApiVersion"
+	provided "javax.servlet:javax.servlet-api:$servletApiVersion"
 
-    runtime 'org.apache.httpcomponents:httpclient:4.2.3',
-            'net.sourceforge.nekohtml:nekohtml:1.9.20'
+	runtime 'org.apache.httpcomponents:httpclient:4.2.3',
+			'net.sourceforge.nekohtml:nekohtml:1.9.20'
 }

+ 7 - 7
remoting/remoting.gradle

@@ -1,12 +1,12 @@
 // Remoting module build file
 
 dependencies {
-    compile project(':spring-security-core'),
-            'aopalliance:aopalliance:1.0',
-            springCoreDependency,
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-web:$springVersion"
+	compile project(':spring-security-core'),
+			'aopalliance:aopalliance:1.0',
+			springCoreDependency,
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-web:$springVersion"
 
-    testCompile project(':spring-security-core').sourceSets.test.output
+	testCompile project(':spring-security-core').sourceSets.test.output
 }

+ 4 - 4
samples/aspectj-jc/build.gradle

@@ -1,9 +1,9 @@
 
 dependencies {
-    compile project(':spring-security-core'),
-            project(':spring-security-config')
+	compile project(':spring-security-core'),
+			project(':spring-security-config')
 
-    aspectpath project(':spring-security-aspects')
+	aspectpath project(':spring-security-aspects')
 
-    runtime project(':spring-security-aspects')
+	runtime project(':spring-security-aspects')
 }

+ 4 - 4
samples/aspectj-xml/aspectj.gradle

@@ -1,9 +1,9 @@
 
 dependencies {
-    compile project(':spring-security-core')
+	compile project(':spring-security-core')
 
-    aspectpath project(':spring-security-aspects')
+	aspectpath project(':spring-security-aspects')
 
-    runtime project(':spring-security-config'),
-            project(':spring-security-aspects')
+	runtime project(':spring-security-config'),
+			project(':spring-security-aspects')
 }

+ 88 - 88
samples/cas/sample-xml/cassample.gradle

@@ -10,65 +10,65 @@ def keystore = "$rootDir/samples/certificates/server.jks"
 def password = 'password'
 
 configurations {
-    casServer
-    excludeModules.each {name ->
-        runtime.exclude module: name
-    }
+	casServer
+	excludeModules.each {name ->
+		runtime.exclude module: name
+	}
 
-    runtime.exclude group: 'org.aspectj'
+	runtime.exclude group: 'org.aspectj'
 }
 
 sourceSets {
-    test.resources.exclude 'GebConfig.groovy'
-    integrationTest.groovy.srcDir file('src/integration-test/groovy')
+	test.resources.exclude 'GebConfig.groovy'
+	integrationTest.groovy.srcDir file('src/integration-test/groovy')
 }
 
 eclipse.classpath.plusConfigurations += [configurations.integrationTestRuntime]
 
 dependencies {
-    providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
-
-    compile project(':spring-security-core'),
-            project(':spring-security-cas'),
-            "org.jasig.cas.client:cas-client-core:$casClientVersion"
-
-    runtime project(':spring-security-web'),
-            project(':spring-security-config'),
-            "org.springframework:spring-context-support:$springVersion",
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "ch.qos.logback:logback-classic:$logbackVersion",
-            "net.sf.ehcache:ehcache:$ehcacheVersion"
-
-    integrationTestCompile project(':spring-security-cas'),
-                   "org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion",
-                   "org.gebish:geb-spock:$gebVersion",
-                   'commons-httpclient:commons-httpclient:3.1',
-                   "org.eclipse.jetty:jetty-server:$jettyVersion",
-                   "org.eclipse.jetty:jetty-servlet:$jettyVersion",
-                   "org.codehaus.groovy:groovy:$groovyVersion",
-                   "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-                   spockDependencies
+	providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
+
+	compile project(':spring-security-core'),
+			project(':spring-security-cas'),
+			"org.jasig.cas.client:cas-client-core:$casClientVersion"
+
+	runtime project(':spring-security-web'),
+			project(':spring-security-config'),
+			"org.springframework:spring-context-support:$springVersion",
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"ch.qos.logback:logback-classic:$logbackVersion",
+			"net.sf.ehcache:ehcache:$ehcacheVersion"
+
+	integrationTestCompile project(':spring-security-cas'),
+				   "org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion",
+				   "org.gebish:geb-spock:$gebVersion",
+				   'commons-httpclient:commons-httpclient:3.1',
+				   "org.eclipse.jetty:jetty-server:$jettyVersion",
+				   "org.eclipse.jetty:jetty-servlet:$jettyVersion",
+				   "org.codehaus.groovy:groovy:$groovyVersion",
+				   "org.slf4j:jcl-over-slf4j:$slf4jVersion",
+				   spockDependencies
 }
 
 [jettyRun, jettyRunWar]*.configure {
-    contextPath = "/cas-sample"
-    def httpConnector = jettyRunWar.class.classLoader.loadClass('org.mortbay.jetty.nio.SelectChannelConnector').newInstance()
-    httpConnector.port = 8080
-    httpConnector.confidentialPort = 8443
-    def httpsConnector = jettyRunWar.class.classLoader.loadClass('org.mortbay.jetty.security.SslSocketConnector').newInstance()
-    httpsConnector.port = 8443
-    httpsConnector.keystore = httpsConnector.truststore = keystore
-    httpsConnector.keyPassword = httpsConnector.trustPassword = password
-
-    connectors = [httpConnector, httpsConnector]
-    doFirst() {
-        System.setProperty('cas.server.host', casServer().httpsHost)
-        System.setProperty('cas.service.host', jettyRunWar.httpsHost)
-    }
+	contextPath = "/cas-sample"
+	def httpConnector = jettyRunWar.class.classLoader.loadClass('org.mortbay.jetty.nio.SelectChannelConnector').newInstance()
+	httpConnector.port = 8080
+	httpConnector.confidentialPort = 8443
+	def httpsConnector = jettyRunWar.class.classLoader.loadClass('org.mortbay.jetty.security.SslSocketConnector').newInstance()
+	httpsConnector.port = 8443
+	httpsConnector.keystore = httpsConnector.truststore = keystore
+	httpsConnector.keyPassword = httpsConnector.trustPassword = password
+
+	connectors = [httpConnector, httpsConnector]
+	doFirst() {
+		System.setProperty('cas.server.host', casServer().httpsHost)
+		System.setProperty('cas.service.host', jettyRunWar.httpsHost)
+	}
 }
 
 task cas (dependsOn: [jettyRunWar]) {
-    jettyRunWar.dependsOn(':spring-security-samples-casserver:casServer')
+	jettyRunWar.dependsOn(':spring-security-samples-casserver:casServer')
 }
 
 task casServer(dependsOn: ':spring-security-samples-casserver:casServer') {
@@ -76,54 +76,54 @@ task casServer(dependsOn: ':spring-security-samples-casserver:casServer') {
 
 integrationTest.dependsOn cas
 integrationTest.doFirst {
-    def casServiceHost = jettyRunWar.httpsHost
-    systemProperties['cas.server.host'] = casServer().httpsHost
-    systemProperties['cas.service.host'] = casServiceHost
-    systemProperties['geb.build.baseUrl'] = 'https://'+casServiceHost+'/cas-sample/'
-    systemProperties['geb.build.reportsDir'] = 'build/geb-reports'
-    systemProperties['jar.path'] = jar.archivePath
-    systemProperties['javax.net.ssl.trustStore'] = keystore
-    systemProperties['javax.net.ssl.trustStorePassword'] = password
+	def casServiceHost = jettyRunWar.httpsHost
+	systemProperties['cas.server.host'] = casServer().httpsHost
+	systemProperties['cas.service.host'] = casServiceHost
+	systemProperties['geb.build.baseUrl'] = 'https://'+casServiceHost+'/cas-sample/'
+	systemProperties['geb.build.reportsDir'] = 'build/geb-reports'
+	systemProperties['jar.path'] = jar.archivePath
+	systemProperties['javax.net.ssl.trustStore'] = keystore
+	systemProperties['javax.net.ssl.trustStorePassword'] = password
 }
 
 gradle.taskGraph.whenReady {graph ->
-    def casServer = casServer()
-    [casServer,jettyRunWar]*.metaClass*.getHttpsConnector {->
-        def sslSocketConnClass = jettyRunWar.class.classLoader.loadClass('org.mortbay.jetty.security.SslSocketConnector')
-        delegate.connectors.find { it in sslSocketConnClass }
-    }
-    [casServer,jettyRunWar]*.metaClass*.getHttpsHost {->
-        "localhost:"+delegate.httpsConnector.port
-    }
-    jettyRunWar.metaClass.getHttpConnector {->
-        def channelConnClass = jettyRunWar.class.classLoader.loadClass('org.mortbay.jetty.nio.SelectChannelConnector')
-        delegate.connectors.find { it in channelConnClass }
-    }
-    if (graph.hasTask(cas)) {
-        casServer.daemon = true
-    }
-    if(graph.hasTask(integrationTest)) {
-        tasks.getByPath(':spring-security-samples-casserver:casServerOverlay').logLevel = 'ERROR'
-        jettyRunWar {
-            additionalRuntimeJars += file("src/integration-test/resources")
-            daemon = true
-        }
-
-        [jettyRunWar.httpConnector,jettyRunWar.httpsConnector,casServer.httpsConnector]*.metaClass*.reservePort { taskToCloseSocket ->
-            def serverSocket = new ServerSocket(0)
-            delegate.metaClass.serverSocket = serverSocket
-            delegate.port = serverSocket.localPort
-            taskToCloseSocket.doFirst {
-                serverSocket.close()
-            }
-        }
-
-        [jettyRunWar.httpConnector,jettyRunWar.httpsConnector]*.reservePort(jettyRunWar)
-        jettyRunWar.httpConnector.confidentialPort = jettyRunWar.httpsConnector.port
-        casServer.httpsConnector.reservePort(casServer)
-    }
+	def casServer = casServer()
+	[casServer,jettyRunWar]*.metaClass*.getHttpsConnector {->
+		def sslSocketConnClass = jettyRunWar.class.classLoader.loadClass('org.mortbay.jetty.security.SslSocketConnector')
+		delegate.connectors.find { it in sslSocketConnClass }
+	}
+	[casServer,jettyRunWar]*.metaClass*.getHttpsHost {->
+		"localhost:"+delegate.httpsConnector.port
+	}
+	jettyRunWar.metaClass.getHttpConnector {->
+		def channelConnClass = jettyRunWar.class.classLoader.loadClass('org.mortbay.jetty.nio.SelectChannelConnector')
+		delegate.connectors.find { it in channelConnClass }
+	}
+	if (graph.hasTask(cas)) {
+		casServer.daemon = true
+	}
+	if(graph.hasTask(integrationTest)) {
+		tasks.getByPath(':spring-security-samples-casserver:casServerOverlay').logLevel = 'ERROR'
+		jettyRunWar {
+			additionalRuntimeJars += file("src/integration-test/resources")
+			daemon = true
+		}
+
+		[jettyRunWar.httpConnector,jettyRunWar.httpsConnector,casServer.httpsConnector]*.metaClass*.reservePort { taskToCloseSocket ->
+			def serverSocket = new ServerSocket(0)
+			delegate.metaClass.serverSocket = serverSocket
+			delegate.port = serverSocket.localPort
+			taskToCloseSocket.doFirst {
+				serverSocket.close()
+			}
+		}
+
+		[jettyRunWar.httpConnector,jettyRunWar.httpsConnector]*.reservePort(jettyRunWar)
+		jettyRunWar.httpConnector.confidentialPort = jettyRunWar.httpsConnector.port
+		casServer.httpsConnector.reservePort(casServer)
+	}
 }
 
 def casServer() {
-    tasks.getByPath(':spring-security-samples-casserver:casServer')
+	tasks.getByPath(':spring-security-samples-casserver:casServer')
 }

+ 43 - 43
samples/cas/server/casserver.gradle

@@ -6,58 +6,58 @@ def keystore = "$rootDir/samples/certificates/server.jks"
 def password = 'password'
 
 configurations {
-    casServer
+	casServer
 }
 dependencies {
-    casServer "org.jasig.cas:cas-server-webapp:4.0.0@war"
+	casServer "org.jasig.cas:cas-server-webapp:4.0.0@war"
 }
 
 task casServerOverlay(type: Sync) {
-    def war = configurations.casServer.resolve().toArray()[0]
-    def warName = war.name.replace('.war','-custom')
-    def overlayDir = file('src/main/webapp')
-    def explodedWar = file("$buildDir/tmp/${warName}")
-    ext.customWar = file("$buildDir/tmp/${warName}.war")
-    ext.tokens = [logLevel: 'INFO']
-
-    inputs.files(war, overlayDir)
-    inputs.property('tokens',{tokens})
-    outputs.files (customWar,explodedWar,file("$buildDir/tmp/expandedArchives"))
-
-    from zipTree(war)
-    from (overlayDir) {
-        filter(ReplaceTokens,tokens: tokens)
-    }
-    into explodedWar
-
-    doLast {
-        if(customWar.exists()) {
-            customWar.delete()
-        }
-        ant.zip(destfile: customWar, baseDir: explodedWar)
-    }
+	def war = configurations.casServer.resolve().toArray()[0]
+	def warName = war.name.replace('.war','-custom')
+	def overlayDir = file('src/main/webapp')
+	def explodedWar = file("$buildDir/tmp/${warName}")
+	ext.customWar = file("$buildDir/tmp/${warName}.war")
+	ext.tokens = [logLevel: 'INFO']
+
+	inputs.files(war, overlayDir)
+	inputs.property('tokens',{tokens})
+	outputs.files (customWar,explodedWar,file("$buildDir/tmp/expandedArchives"))
+
+	from zipTree(war)
+	from (overlayDir) {
+		filter(ReplaceTokens,tokens: tokens)
+	}
+	into explodedWar
+
+	doLast {
+		if(customWar.exists()) {
+			customWar.delete()
+		}
+		ant.zip(destfile: customWar, baseDir: explodedWar)
+	}
 }
 
 casServerOverlay.metaClass.setLogLevel { level ->
-    tokens['logLevel'] = level
+	tokens['logLevel'] = level
 }
 
 task casServer (type: org.gradle.api.plugins.jetty.JettyRunWar, dependsOn: 'casServerOverlay') {
-    contextPath = "/cas"
-    connectors = [casServer.class.classLoader.loadClass('org.mortbay.jetty.security.SslSocketConnector').newInstance()]
-    connectors[0].port = 9443
-    connectors[0].keystore = connectors[0].truststore = keystore
-    connectors[0].keyPassword = connectors[0].trustPassword = password
-    connectors[0].wantClientAuth = true
-    connectors[0].needClientAuth = false
-    webApp = casServerOverlay.customWar
-
-    inputs.file casServerOverlay.customWar
-
-    doFirst() {
-        System.setProperty('javax.net.ssl.trustStore', keystore)
-        System.setProperty('javax.net.ssl.trustStorePassword', password)
-        System.setProperty('java.naming.factory.url.pkgs','org.mortbay.naming')
-        System.setProperty('java.naming.factory.initial','org.mortbay.naming.InitialContextFactory')
-    }
+	contextPath = "/cas"
+	connectors = [casServer.class.classLoader.loadClass('org.mortbay.jetty.security.SslSocketConnector').newInstance()]
+	connectors[0].port = 9443
+	connectors[0].keystore = connectors[0].truststore = keystore
+	connectors[0].keyPassword = connectors[0].trustPassword = password
+	connectors[0].wantClientAuth = true
+	connectors[0].needClientAuth = false
+	webApp = casServerOverlay.customWar
+
+	inputs.file casServerOverlay.customWar
+
+	doFirst() {
+		System.setProperty('javax.net.ssl.trustStore', keystore)
+		System.setProperty('javax.net.ssl.trustStorePassword', password)
+		System.setProperty('java.naming.factory.url.pkgs','org.mortbay.naming')
+		System.setProperty('java.naming.factory.initial','org.mortbay.naming.InitialContextFactory')
+	}
 }

+ 30 - 30
samples/chat-jc/build.gradle

@@ -1,40 +1,40 @@
 apply from: WAR_SAMPLE_GRADLE
 
 repositories {
-    maven { url 'http://clojars.org/repo' }
+	maven { url 'http://clojars.org/repo' }
 }
 
 
 dependencies {
-    providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
+	providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
 
-    compile project(":spring-security-web"),
-            project(":spring-security-config"),
-            project(":spring-security-messaging"),
-            project(":spring-security-data"),
-            "org.springframework:spring-webmvc:${springVersion}",
-            "org.springframework:spring-websocket:${springVersion}",
-            "org.springframework:spring-messaging:${springVersion}",
-            "org.springframework.session:spring-session:${springSessionVersion}",
-            "org.springframework.data:spring-data-redis:${springDataRedisVersion}",
-            "org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final",
-            "org.hsqldb:hsqldb:$hsqlVersion",
-            "javax.validation:validation-api:1.0.0.GA",
-            "org.hibernate:hibernate-validator:4.2.0.Final",
-            "redis.clients:jedis:2.4.2",
-            "redis.embedded:embedded-redis:0.2",
-            "org.apache.commons:commons-pool2:2.2",
-            "org.thymeleaf:thymeleaf-spring4:$thymeleafVersion",
-            "org.thymeleaf.extras:thymeleaf-extras-tiles2-spring4:2.1.1.RELEASE",
-            "org.slf4j:slf4j-api:$slf4jVersion",
-            "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
-            "com.fasterxml.jackson.core:jackson-databind:$jacksonDatavindVersion"
-    compile('org.hibernate:hibernate-entitymanager:3.6.10.Final') {
-        exclude group:'javassist', module: 'javassist'
-    }
-    compile("org.springframework.data:spring-data-jpa:$springDataJpaVersion") {
-        exclude group:'org.aspectj', module:'aspectjrt'
-    }
+	compile project(":spring-security-web"),
+			project(":spring-security-config"),
+			project(":spring-security-messaging"),
+			project(":spring-security-data"),
+			"org.springframework:spring-webmvc:${springVersion}",
+			"org.springframework:spring-websocket:${springVersion}",
+			"org.springframework:spring-messaging:${springVersion}",
+			"org.springframework.session:spring-session:${springSessionVersion}",
+			"org.springframework.data:spring-data-redis:${springDataRedisVersion}",
+			"org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final",
+			"org.hsqldb:hsqldb:$hsqlVersion",
+			"javax.validation:validation-api:1.0.0.GA",
+			"org.hibernate:hibernate-validator:4.2.0.Final",
+			"redis.clients:jedis:2.4.2",
+			"redis.embedded:embedded-redis:0.2",
+			"org.apache.commons:commons-pool2:2.2",
+			"org.thymeleaf:thymeleaf-spring4:$thymeleafVersion",
+			"org.thymeleaf.extras:thymeleaf-extras-tiles2-spring4:2.1.1.RELEASE",
+			"org.slf4j:slf4j-api:$slf4jVersion",
+			"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
+			"com.fasterxml.jackson.core:jackson-databind:$jacksonDatavindVersion"
+	compile('org.hibernate:hibernate-entitymanager:3.6.10.Final') {
+		exclude group:'javassist', module: 'javassist'
+	}
+	compile("org.springframework.data:spring-data-jpa:$springDataJpaVersion") {
+		exclude group:'org.aspectj', module:'aspectjrt'
+	}
 
-    runtime "ch.qos.logback:logback-classic:$logbackVersion"
+	runtime "ch.qos.logback:logback-classic:$logbackVersion"
 }

+ 18 - 18
samples/concurrency-jc/build.gradle

@@ -2,24 +2,24 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-                    'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+					'javax.servlet.jsp:jsp-api:2.1'
 
-    compile project(":spring-security-config"),
-            project(":spring-security-samples-messages-jc"),
-            project(":spring-security-core"),
-            project(":spring-security-web"),
-            "org.springframework:spring-webmvc:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion",
-            "org.slf4j:slf4j-api:$slf4jVersion",
-            "org.slf4j:log4j-over-slf4j:$slf4jVersion",
-            "org.slf4j:jul-to-slf4j:$slf4jVersion",
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
-            "javax.validation:validation-api:1.0.0.GA",
-            "org.hibernate:hibernate-validator:4.2.0.Final"
+	compile project(":spring-security-config"),
+			project(":spring-security-samples-messages-jc"),
+			project(":spring-security-core"),
+			project(":spring-security-web"),
+			"org.springframework:spring-webmvc:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion",
+			"org.slf4j:slf4j-api:$slf4jVersion",
+			"org.slf4j:log4j-over-slf4j:$slf4jVersion",
+			"org.slf4j:jul-to-slf4j:$slf4jVersion",
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
+			"javax.validation:validation-api:1.0.0.GA",
+			"org.hibernate:hibernate-validator:4.2.0.Final"
 
-    runtime "opensymphony:sitemesh:2.4.2",
-            "cglib:cglib-nodep:$cglibVersion",
-            'ch.qos.logback:logback-classic:0.9.30'
+	runtime "opensymphony:sitemesh:2.4.2",
+			"cglib:cglib-nodep:$cglibVersion",
+			'ch.qos.logback:logback-classic:0.9.30'
 }

+ 20 - 20
samples/contacts-xml/contacts.gradle

@@ -3,27 +3,27 @@
 apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
-    providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
+	providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
 
-    compile project(':spring-security-core'),
-            project(':spring-security-acl'),
-            "org.springframework:spring-aop:$springVersion",
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion",
-            "org.springframework:spring-tx:$springVersion",
-            "org.springframework:spring-web:$springVersion",
-            "org.springframework:spring-webmvc:$springVersion"
+	compile project(':spring-security-core'),
+			project(':spring-security-acl'),
+			"org.springframework:spring-aop:$springVersion",
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion",
+			"org.springframework:spring-tx:$springVersion",
+			"org.springframework:spring-web:$springVersion",
+			"org.springframework:spring-webmvc:$springVersion"
 
-    runtime project(':spring-security-web'),
-            project(':spring-security-config'),
-            project(':spring-security-taglibs'),
-            "org.springframework:spring-context-support:$springVersion",
-            jstlDependencies,
-            "org.hsqldb:hsqldb:$hsqlVersion",
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "ch.qos.logback:logback-classic:$logbackVersion",
-            "net.sf.ehcache:ehcache:$ehcacheVersion"
+	runtime project(':spring-security-web'),
+			project(':spring-security-config'),
+			project(':spring-security-taglibs'),
+			"org.springframework:spring-context-support:$springVersion",
+			jstlDependencies,
+			"org.hsqldb:hsqldb:$hsqlVersion",
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"ch.qos.logback:logback-classic:$logbackVersion",
+			"net.sf.ehcache:ehcache:$ehcacheVersion"
 
-    integrationTestCompile gebDependencies
+	integrationTestCompile gebDependencies
 }

+ 53 - 53
samples/contacts-xml/src/integration-test/groovy/org/springframework/security/samples/ContactsTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,62 +26,62 @@ import org.springframework.security.samples.pages.*
  */
 @Stepwise
 class ContactsTests extends GebReportingSpec {
-    def 'access home page with unauthenticated user success'() {
-        when: 'Unauthenticated user accesses the Home Page'
-        to HomePage
-        then: 'The page is displayed'
-        at HomePage
-    }
+	def 'access home page with unauthenticated user success'() {
+		when: 'Unauthenticated user accesses the Home Page'
+		to HomePage
+		then: 'The page is displayed'
+		at HomePage
+	}
 
-    def 'access manage page with unauthenticated user sends to login page'() {
-        when: 'Unauthenticated user accesses the Manage Page'
-        manage.click(LoginPage)
-        then: 'The login page is displayed'
-        at LoginPage
-    }
+	def 'access manage page with unauthenticated user sends to login page'() {
+		when: 'Unauthenticated user accesses the Manage Page'
+		manage.click(LoginPage)
+		then: 'The login page is displayed'
+		at LoginPage
+	}
 
-    def 'authenticated user is sent to original page'() {
-        when: 'user authenticates'
-        login()
-        then: 'The manage page is displayed'
-        at ContactsPage
-    }
+	def 'authenticated user is sent to original page'() {
+		when: 'user authenticates'
+		login()
+		then: 'The manage page is displayed'
+		at ContactsPage
+	}
 
-    def 'add contact link works'() {
-        when: 'user clicks add link'
-        addContact.click(AddPage)
-        then: 'The add page is displayed'
-        at AddPage
-    }
+	def 'add contact link works'() {
+		when: 'user clicks add link'
+		addContact.click(AddPage)
+		then: 'The add page is displayed'
+		at AddPage
+	}
 
-    def 'add contact'() {
-        when: 'add a contact'
-        addContact
-        then: 'The add page is displayed'
-        at ContactsPage
-        and: 'The new contact is displayed'
-        contacts.find { it.email == 'rob@example.com' }?.name ==  'Rob Winch'
-    }
+	def 'add contact'() {
+		when: 'add a contact'
+		addContact
+		then: 'The add page is displayed'
+		at ContactsPage
+		and: 'The new contact is displayed'
+		contacts.find { it.email == 'rob@example.com' }?.name ==  'Rob Winch'
+	}
 
-    def 'delete contact'() {
-        when: 'delete a contact'
-        contacts.find { it.email == 'rob@example.com' }.delete()
-        then: 'Delete confirmation displayed'
-        at DeleteConfirmPage
-        when: 'View Manage Page'
-        manage.click()
-        then: 'New contact has been removed'
-        !contacts.find { it.email == 'rob@example.com' }
-    }
+	def 'delete contact'() {
+		when: 'delete a contact'
+		contacts.find { it.email == 'rob@example.com' }.delete()
+		then: 'Delete confirmation displayed'
+		at DeleteConfirmPage
+		when: 'View Manage Page'
+		manage.click()
+		then: 'New contact has been removed'
+		!contacts.find { it.email == 'rob@example.com' }
+	}
 
-    def 'authenticated user logs out'() {
-        when: 'user logs out'
-        logout.click()
-        then: 'the default logout success page is displayed'
-        at HomePage
-        when: 'Unauthenticated user accesses the Manage Page'
-        via ContactsPage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
+	def 'authenticated user logs out'() {
+		when: 'user logs out'
+		logout.click()
+		then: 'the default logout success page is displayed'
+		at HomePage
+		when: 'Unauthenticated user accesses the Manage Page'
+		via ContactsPage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
 }

+ 12 - 12
samples/contacts-xml/src/integration-test/groovy/org/springframework/security/samples/pages/AddPage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,15 +23,15 @@ import geb.Page
  * @author Rob Winch
  */
 class AddPage extends Page {
-    static url = 'add'
-    static at = { assert driver.title == 'Add New Contact'; true}
-    static content = {
-        addContact(required:false) { name = 'Rob Winch', email = 'rob@example.com'->
-            addForm.name = name
-            addForm.email = email
-            submit.click()
-        }
-        addForm { $('form') }
-        submit { $('input', type: 'submit') }
-    }
+	static url = 'add'
+	static at = { assert driver.title == 'Add New Contact'; true}
+	static content = {
+		addContact(required:false) { name = 'Rob Winch', email = 'rob@example.com'->
+			addForm.name = name
+			addForm.email = email
+			submit.click()
+		}
+		addForm { $('form') }
+		submit { $('input', type: 'submit') }
+	}
 }

+ 8 - 8
samples/contacts-xml/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,11 +23,11 @@ import geb.*
  * @author Rob Winch
  */
 class HomePage extends Page {
-    static url = ''
-    static at = { assert driver.title == 'Contacts Security Demo'; true}
-    static content = {
-        manage(to: [ContactsPage,LoginPage]) { $('a', text: 'Manage') }
-        debug { $('a', text: 'Debug').click() }
-        frames { $('a', text: 'Frames').click() }
-    }
+	static url = ''
+	static at = { assert driver.title == 'Contacts Security Demo'; true}
+	static content = {
+		manage(to: [ContactsPage,LoginPage]) { $('a', text: 'Manage') }
+		debug { $('a', text: 'Debug').click() }
+		frames { $('a', text: 'Frames').click() }
+	}
 }

+ 12 - 12
samples/contacts-xml/src/integration-test/groovy/org/springframework/security/samples/pages/LoginPage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,15 +23,15 @@ import geb.*
  * @author Rob Winch
  */
 class LoginPage extends Page {
-    static url = 'login'
-    static at = { assert driver.title == 'Login'; true}
-    static content = {
-        login(required:false) { user='rod', password='koala' ->
-            loginForm.username = user
-            loginForm.password = password
-            submit.click()
-        }
-        loginForm { $('form') }
-        submit { $('input', type: 'submit') }
-    }
+	static url = 'login'
+	static at = { assert driver.title == 'Login'; true}
+	static content = {
+		login(required:false) { user='rod', password='koala' ->
+			loginForm.username = user
+			loginForm.password = password
+			submit.click()
+		}
+		loginForm { $('form') }
+		submit { $('input', type: 'submit') }
+	}
 }

+ 8 - 8
samples/data-jc/build.gradle

@@ -1,10 +1,10 @@
 dependencies {
-    compile project(':spring-security-data'),
-            project(':spring-security-config'),
-            "org.springframework.data:spring-data-jpa:$springDataJpaVersion",
-            "org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final",
-            'org.hibernate:hibernate-entitymanager:3.6.10.Final',
-            "org.hsqldb:hsqldb:$hsqlVersion",
-            "javax.validation:validation-api:1.0.0.GA",
-            "org.hibernate:hibernate-validator:4.2.0.Final"
+	compile project(':spring-security-data'),
+			project(':spring-security-config'),
+			"org.springframework.data:spring-data-jpa:$springDataJpaVersion",
+			"org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final",
+			'org.hibernate:hibernate-entitymanager:3.6.10.Final',
+			"org.hsqldb:hsqldb:$hsqlVersion",
+			"javax.validation:validation-api:1.0.0.GA",
+			"org.hibernate:hibernate-validator:4.2.0.Final"
 }

+ 10 - 10
samples/dms-xml/dms.gradle

@@ -1,16 +1,16 @@
 
 dependencies {
-    compile project(':spring-security-core'),
-            project(':spring-security-acl'),
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-tx:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion"
+	compile project(':spring-security-core'),
+			project(':spring-security-acl'),
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-tx:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion"
 
-    testCompile "org.springframework:spring-context:$springVersion"
+	testCompile "org.springframework:spring-context:$springVersion"
 
-    runtime project(':spring-security-config'),
-            "org.hsqldb:hsqldb:$hsqlVersion",
-            "org.springframework:spring-context-support:$springVersion"
+	runtime project(':spring-security-config'),
+			"org.hsqldb:hsqldb:$hsqlVersion",
+			"org.springframework:spring-context-support:$springVersion"
 
-    optional "net.sf.ehcache:ehcache:$ehcacheVersion"
+	optional "net.sf.ehcache:ehcache:$ehcacheVersion"
 }

+ 19 - 19
samples/form-jc/build.gradle

@@ -2,26 +2,26 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-                    'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+					'javax.servlet.jsp:jsp-api:2.1'
 
-    compile project(":spring-security-config"),
-            project(":spring-security-samples-messages-jc"),
-            project(":spring-security-core"),
-            project(":spring-security-web"),
-            "org.springframework:spring-webmvc:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion",
-            "org.slf4j:slf4j-api:$slf4jVersion",
-            "org.slf4j:log4j-over-slf4j:$slf4jVersion",
-            "org.slf4j:jul-to-slf4j:$slf4jVersion",
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
-            "javax.validation:validation-api:1.0.0.GA",
-            "org.hibernate:hibernate-validator:4.2.0.Final"
+	compile project(":spring-security-config"),
+			project(":spring-security-samples-messages-jc"),
+			project(":spring-security-core"),
+			project(":spring-security-web"),
+			"org.springframework:spring-webmvc:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion",
+			"org.slf4j:slf4j-api:$slf4jVersion",
+			"org.slf4j:log4j-over-slf4j:$slf4jVersion",
+			"org.slf4j:jul-to-slf4j:$slf4jVersion",
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
+			"javax.validation:validation-api:1.0.0.GA",
+			"org.hibernate:hibernate-validator:4.2.0.Final"
 
-    runtime "opensymphony:sitemesh:2.4.2",
-            "cglib:cglib-nodep:$cglibVersion",
-            'ch.qos.logback:logback-classic:0.9.30'
+	runtime "opensymphony:sitemesh:2.4.2",
+			"cglib:cglib-nodep:$cglibVersion",
+			'ch.qos.logback:logback-classic:0.9.30'
 
-    integrationTestCompile gebDependencies
+	integrationTestCompile gebDependencies
 }

+ 25 - 25
samples/form-jc/src/integration-test/groovy/org/springframework/security/samples/FormJcTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,30 +27,30 @@ import org.springframework.security.samples.pages.*
  */
 @Stepwise
 class FormJcTests extends GebReportingSpec {
-    def 'access home page with unauthenticated user sends to login page'() {
-        when: 'Unauthenticated user accesses the Home Page'
-        via HomePage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
+	def 'access home page with unauthenticated user sends to login page'() {
+		when: 'Unauthenticated user accesses the Home Page'
+		via HomePage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
 
-    def 'authenticated user is sent to original page'() {
-        when: 'user authenticates'
-        login()
-        then: 'The home page is displayed'
-        at HomePage
-        and: 'The username is displayed'
-        user == 'user'
-    }
+	def 'authenticated user is sent to original page'() {
+		when: 'user authenticates'
+		login()
+		then: 'The home page is displayed'
+		at HomePage
+		and: 'The username is displayed'
+		user == 'user'
+	}
 
-    def 'authenticated user logs out'() {
-        when: 'user logs out'
-        logout()
-        then: 'the login page is displayed'
-        at LoginPage
-        when: 'Unauthenticated user accesses the Home Page'
-        via HomePage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
+	def 'authenticated user logs out'() {
+		when: 'user logs out'
+		logout()
+		then: 'the login page is displayed'
+		at LoginPage
+		when: 'Unauthenticated user accesses the Home Page'
+		via HomePage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
 }

+ 7 - 7
samples/form-jc/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,10 +23,10 @@ import geb.*
  * @author Rob Winch
  */
 class HomePage extends Page {
-    static url = ''
-    static at = { assert driver.title == 'Messages : View All'; true}
-    static content = {
-        user { $('p.navbar-text').text() }
-        logout { $('input', type: 'submit').click() }
-    }
+	static url = ''
+	static at = { assert driver.title == 'Messages : View All'; true}
+	static content = {
+		user { $('p.navbar-text').text() }
+		logout { $('input', type: 'submit').click() }
+	}
 }

+ 12 - 12
samples/form-jc/src/integration-test/groovy/org/springframework/security/samples/pages/LoginPage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,15 +23,15 @@ import geb.*
  * @author Rob Winch
  */
 class LoginPage extends Page {
-    static url = 'login'
-    static at = { assert driver.title == 'Please Login'; true}
-    static content = {
-        login(required:false) { user='user', password='password' ->
-            loginForm.username = user
-            loginForm.password = password
-            submit.click()
-        }
-        loginForm { $('form') }
-        submit { $('button', type: 'submit') }
-    }
+	static url = 'login'
+	static at = { assert driver.title == 'Please Login'; true}
+	static content = {
+		login(required:false) { user='user', password='password' ->
+			loginForm.username = user
+			loginForm.password = password
+			submit.click()
+		}
+		loginForm { $('form') }
+		submit { $('button', type: 'submit') }
+	}
 }

+ 32 - 32
samples/gae-xml/gae.gradle

@@ -5,43 +5,43 @@ apply plugin: 'gae'
 def gaeVersion="1.4.2"
 
 repositories {
-    maven {
-        // Hibernate Validator
-        name =  'JBoss'
-        url = 'https://repository.jboss.org/nexus/content/repositories/releases'
-    }
-    maven {
-        // GAE Jars
-        name =  'GAE'
-        url = 'http://maven-gae-plugin.googlecode.com/svn/repository'
-    }
+	maven {
+		// Hibernate Validator
+		name =	'JBoss'
+		url = 'https://repository.jboss.org/nexus/content/repositories/releases'
+	}
+	maven {
+		// GAE Jars
+		name =	'GAE'
+		url = 'http://maven-gae-plugin.googlecode.com/svn/repository'
+	}
 }
 
 // Remove logback as it causes security issues with GAE.
 configurations.runtime.exclude(group: 'ch.qos.logback')
 
 dependencies {
-    providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
-
-    compile project(':spring-security-core'),
-            project(':spring-security-web'),
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-web:$springVersion",
-            "org.springframework:spring-webmvc:$springVersion",
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-context-support:$springVersion",
-            "com.google.appengine:appengine-api-1.0-sdk:$gaeVersion",
-            'javax.validation:validation-api:1.0.0.GA',
-            'org.hibernate:hibernate-validator:4.2.0.Final',
-            "org.slf4j:slf4j-api:$slf4jVersion"
-
-    runtime project(':spring-security-config'),
-            project(':spring-security-taglibs'),
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "org.slf4j:slf4j-jdk14:$slf4jVersion"
-    testCompile "com.google.appengine:appengine-testing:$gaeVersion"
-
-    testRuntime "com.google.appengine:appengine-api-labs:$gaeVersion",
-                "com.google.appengine:appengine-api-stubs:$gaeVersion"
+	providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
+
+	compile project(':spring-security-core'),
+			project(':spring-security-web'),
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-web:$springVersion",
+			"org.springframework:spring-webmvc:$springVersion",
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-context-support:$springVersion",
+			"com.google.appengine:appengine-api-1.0-sdk:$gaeVersion",
+			'javax.validation:validation-api:1.0.0.GA',
+			'org.hibernate:hibernate-validator:4.2.0.Final',
+			"org.slf4j:slf4j-api:$slf4jVersion"
+
+	runtime project(':spring-security-config'),
+			project(':spring-security-taglibs'),
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"org.slf4j:slf4j-jdk14:$slf4jVersion"
+	testCompile "com.google.appengine:appengine-testing:$gaeVersion"
+
+	testRuntime "com.google.appengine:appengine-api-labs:$gaeVersion",
+				"com.google.appengine:appengine-api-stubs:$gaeVersion"
 
 }

+ 19 - 19
samples/hellojs-jc/build.gradle

@@ -2,25 +2,25 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-                    'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+					'javax.servlet.jsp:jsp-api:2.1'
 
-    compile project(":spring-security-config"),
-            project(":spring-security-samples-messages-jc"),
-            project(":spring-security-core"),
-            project(":spring-security-web"),
-            "org.springframework:spring-webmvc:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion",
-            "org.slf4j:slf4j-api:$slf4jVersion",
-            "org.slf4j:log4j-over-slf4j:$slf4jVersion",
-            "org.slf4j:jul-to-slf4j:$slf4jVersion",
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
-            "javax.validation:validation-api:1.0.0.GA",
-            "org.hibernate:hibernate-validator:4.2.0.Final",
-            "com.fasterxml.jackson.core:jackson-databind:2.2.1"
+	compile project(":spring-security-config"),
+			project(":spring-security-samples-messages-jc"),
+			project(":spring-security-core"),
+			project(":spring-security-web"),
+			"org.springframework:spring-webmvc:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion",
+			"org.slf4j:slf4j-api:$slf4jVersion",
+			"org.slf4j:log4j-over-slf4j:$slf4jVersion",
+			"org.slf4j:jul-to-slf4j:$slf4jVersion",
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
+			"javax.validation:validation-api:1.0.0.GA",
+			"org.hibernate:hibernate-validator:4.2.0.Final",
+			"com.fasterxml.jackson.core:jackson-databind:2.2.1"
 
-    runtime "opensymphony:sitemesh:2.4.2",
-            "cglib:cglib-nodep:$cglibVersion",
-            'ch.qos.logback:logback-classic:0.9.30'
+	runtime "opensymphony:sitemesh:2.4.2",
+			"cglib:cglib-nodep:$cglibVersion",
+			'ch.qos.logback:logback-classic:0.9.30'
 }

+ 19 - 19
samples/hellomvc-jc/build.gradle

@@ -2,26 +2,26 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-                    'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+					'javax.servlet.jsp:jsp-api:2.1'
 
-    compile project(":spring-security-config"),
-            project(":spring-security-samples-messages-jc"),
-            project(":spring-security-core"),
-            project(":spring-security-web"),
-            "org.springframework:spring-webmvc:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion",
-            "org.slf4j:slf4j-api:$slf4jVersion",
-            "org.slf4j:log4j-over-slf4j:$slf4jVersion",
-            "org.slf4j:jul-to-slf4j:$slf4jVersion",
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
-            "javax.validation:validation-api:1.0.0.GA",
-            "org.hibernate:hibernate-validator:4.2.0.Final"
+	compile project(":spring-security-config"),
+			project(":spring-security-samples-messages-jc"),
+			project(":spring-security-core"),
+			project(":spring-security-web"),
+			"org.springframework:spring-webmvc:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion",
+			"org.slf4j:slf4j-api:$slf4jVersion",
+			"org.slf4j:log4j-over-slf4j:$slf4jVersion",
+			"org.slf4j:jul-to-slf4j:$slf4jVersion",
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
+			"javax.validation:validation-api:1.0.0.GA",
+			"org.hibernate:hibernate-validator:4.2.0.Final"
 
-    runtime "opensymphony:sitemesh:2.4.2",
-            "cglib:cglib-nodep:$cglibVersion",
-            'ch.qos.logback:logback-classic:0.9.30'
+	runtime "opensymphony:sitemesh:2.4.2",
+			"cglib:cglib-nodep:$cglibVersion",
+			'ch.qos.logback:logback-classic:0.9.30'
 
-    testCompile project(":spring-security-test")
+	testCompile project(":spring-security-test")
 }

+ 8 - 8
samples/helloworld-jc/build.gradle

@@ -2,15 +2,15 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-            'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+			'javax.servlet.jsp:jsp-api:2.1'
 
-    compile project(":spring-security-config"),
-            project(":spring-security-web"),
-            jstlDependencies,
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion"
+	compile project(":spring-security-config"),
+			project(":spring-security-web"),
+			jstlDependencies,
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion"
 
-    runtime "ch.qos.logback:logback-classic:$logbackVersion"
+	runtime "ch.qos.logback:logback-classic:$logbackVersion"
 
-    integrationTestCompile gebDependencies
+	integrationTestCompile gebDependencies
 }

+ 7 - 7
samples/helloworld-jc/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,10 +23,10 @@ import geb.*
  * @author Rob Winch
  */
 class HomePage extends Page {
-    static url = ''
-    static at = { assert driver.title == 'Hello Security'; true}
-    static content = {
-        message { $('p').text() }
-        logout { $('input', type: 'submit').click() }
-    }
+	static url = ''
+	static at = { assert driver.title == 'Hello Security'; true}
+	static content = {
+		message { $('p').text() }
+		logout { $('input', type: 'submit').click() }
+	}
 }

+ 8 - 8
samples/helloworld-xml/build.gradle

@@ -2,15 +2,15 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-            'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+			'javax.servlet.jsp:jsp-api:2.1'
 
-    compile project(":spring-security-config"),
-            project(":spring-security-web"),
-            jstlDependencies,
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion"
+	compile project(":spring-security-config"),
+			project(":spring-security-web"),
+			jstlDependencies,
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion"
 
-    runtime "ch.qos.logback:logback-classic:$logbackVersion"
+	runtime "ch.qos.logback:logback-classic:$logbackVersion"
 
-    integrationTestCompile gebDependencies
+	integrationTestCompile gebDependencies
 }

+ 19 - 19
samples/inmemory-jc/build.gradle

@@ -2,26 +2,26 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-                    'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+					'javax.servlet.jsp:jsp-api:2.1'
 
-    compile project(":spring-security-config"),
-            project(":spring-security-samples-messages-jc"),
-            project(":spring-security-core"),
-            project(":spring-security-web"),
-            "org.springframework:spring-webmvc:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion",
-            "org.slf4j:slf4j-api:$slf4jVersion",
-            "org.slf4j:log4j-over-slf4j:$slf4jVersion",
-            "org.slf4j:jul-to-slf4j:$slf4jVersion",
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
-            "javax.validation:validation-api:1.0.0.GA",
-            "org.hibernate:hibernate-validator:4.2.0.Final"
+	compile project(":spring-security-config"),
+			project(":spring-security-samples-messages-jc"),
+			project(":spring-security-core"),
+			project(":spring-security-web"),
+			"org.springframework:spring-webmvc:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion",
+			"org.slf4j:slf4j-api:$slf4jVersion",
+			"org.slf4j:log4j-over-slf4j:$slf4jVersion",
+			"org.slf4j:jul-to-slf4j:$slf4jVersion",
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
+			"javax.validation:validation-api:1.0.0.GA",
+			"org.hibernate:hibernate-validator:4.2.0.Final"
 
-    runtime "opensymphony:sitemesh:2.4.2",
-            "cglib:cglib-nodep:$cglibVersion",
-            'ch.qos.logback:logback-classic:0.9.30'
+	runtime "opensymphony:sitemesh:2.4.2",
+			"cglib:cglib-nodep:$cglibVersion",
+			'ch.qos.logback:logback-classic:0.9.30'
 
-    testCompile project(":spring-security-test")
+	testCompile project(":spring-security-test")
 }

+ 6 - 6
samples/insecure/build.gradle

@@ -2,13 +2,13 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-                    'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+					'javax.servlet.jsp:jsp-api:2.1'
 
-    compile jstlDependencies,
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion"
+	compile jstlDependencies,
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion"
 
-    runtime "ch.qos.logback:logback-classic:$logbackVersion"
+	runtime "ch.qos.logback:logback-classic:$logbackVersion"
 
-    integrationTestCompile gebDependencies
+	integrationTestCompile gebDependencies
 }

+ 9 - 9
samples/insecure/src/integration-test/groovy/org/springframework/security/samples/HelloInsecureTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,12 +26,12 @@ import org.springframework.security.samples.pages.*
  */
 @Stepwise
 class HelloInsecureTests extends GebReportingSpec {
-    def 'The HomePage is accessible'() {
-        when: 'Unauthenticated user accesses the Home Page'
-        to HomePage
-        then: 'The HomePage is displayed'
-        at HomePage
-        and: 'We can see the message'
-        message == 'We would like to secure this page'
-    }
+	def 'The HomePage is accessible'() {
+		when: 'Unauthenticated user accesses the Home Page'
+		to HomePage
+		then: 'The HomePage is displayed'
+		at HomePage
+		and: 'We can see the message'
+		message == 'We would like to secure this page'
+	}
 }

+ 6 - 6
samples/insecure/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,9 +23,9 @@ import geb.*
  * @author Rob Winch
  */
 class HomePage extends Page {
-    static url = ''
-    static at = { assert driver.title == 'Hello World'; true}
-    static content = {
-        message { $('p').text() }
-    }
+	static url = ''
+	static at = { assert driver.title == 'Hello World'; true}
+	static content = {
+		message { $('p').text() }
+	}
 }

+ 15 - 15
samples/insecuremvc/build.gradle

@@ -2,21 +2,21 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-                    'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+					'javax.servlet.jsp:jsp-api:2.1'
 
-    compile project(":spring-security-samples-messages-jc"),
-            "org.springframework:spring-webmvc:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion",
-            "org.slf4j:slf4j-api:$slf4jVersion",
-            "org.slf4j:log4j-over-slf4j:$slf4jVersion",
-            "org.slf4j:jul-to-slf4j:$slf4jVersion",
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
-            "javax.validation:validation-api:1.0.0.GA",
-            "org.hibernate:hibernate-validator:4.2.0.Final"
+	compile project(":spring-security-samples-messages-jc"),
+			"org.springframework:spring-webmvc:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion",
+			"org.slf4j:slf4j-api:$slf4jVersion",
+			"org.slf4j:log4j-over-slf4j:$slf4jVersion",
+			"org.slf4j:jul-to-slf4j:$slf4jVersion",
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
+			"javax.validation:validation-api:1.0.0.GA",
+			"org.hibernate:hibernate-validator:4.2.0.Final"
 
-    runtime "opensymphony:sitemesh:2.4.2",
-            "cglib:cglib-nodep:$cglibVersion",
-            'ch.qos.logback:logback-classic:0.9.30'
+	runtime "opensymphony:sitemesh:2.4.2",
+			"cglib:cglib-nodep:$cglibVersion",
+			'ch.qos.logback:logback-classic:0.9.30'
 }

+ 17 - 17
samples/jaas-xml/jaas.gradle

@@ -4,28 +4,28 @@ apply from: WAR_SAMPLE_GRADLE
 def excludeModules = ['spring-security-acl', 'jsr250-api', 'ehcache', 'spring-jdbc', 'spring-tx']
 
 configurations {
-    excludeModules.each {name ->
-        runtime.exclude module: name
-    }
+	excludeModules.each {name ->
+		runtime.exclude module: name
+	}
 
-    runtime.exclude group: 'org.aspectj'
+	runtime.exclude group: 'org.aspectj'
 }
 
 dependencies {
-    providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
+	providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
 
-    compile project(':spring-security-core'),
-            "org.springframework:spring-beans:$springVersion",
-            "org.springframework:spring-context:$springVersion",
-            "org.springframework:spring-web:$springVersion"
+	compile project(':spring-security-core'),
+			"org.springframework:spring-beans:$springVersion",
+			"org.springframework:spring-context:$springVersion",
+			"org.springframework:spring-web:$springVersion"
 
-    runtime project(':spring-security-web'),
-            project(':spring-security-config'),
-            project(':spring-security-taglibs'),
-            "org.springframework:spring-context-support:$springVersion",
-            jstlDependencies,
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "ch.qos.logback:logback-classic:$logbackVersion"
+	runtime project(':spring-security-web'),
+			project(':spring-security-config'),
+			project(':spring-security-taglibs'),
+			"org.springframework:spring-context-support:$springVersion",
+			jstlDependencies,
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"ch.qos.logback:logback-classic:$logbackVersion"
 
-    integrationTestCompile gebDependencies
+	integrationTestCompile gebDependencies
 }

+ 29 - 29
samples/jaas-xml/src/integration-test/groovy/org/springframework/security/samples/JaasXmlTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,35 +27,35 @@ import org.springframework.security.samples.pages.*
  */
 @Stepwise
 class JaasXmlTests extends GebReportingSpec {
-    def 'access home page with unauthenticated works'() {
-        when: 'Unauthenticated user accesses the Home Page'
-        to HomePage
-        then: 'The home page is displayed'
-        at HomePage
-    }
+	def 'access home page with unauthenticated works'() {
+		when: 'Unauthenticated user accesses the Home Page'
+		to HomePage
+		then: 'The home page is displayed'
+		at HomePage
+	}
 
-    def 'access secure page with unauthenticated requires login'() {
-        when: 'Unauthenticated user accesses the Secure Page'
-        securePage LoginPage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
+	def 'access secure page with unauthenticated requires login'() {
+		when: 'Unauthenticated user accesses the Secure Page'
+		securePage LoginPage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
 
-    def 'authenticated user is sent to original page'() {
-        when: 'user authenticates'
-        login()
-        then: 'The secure page is displayed'
-        at SecurePage
-    }
+	def 'authenticated user is sent to original page'() {
+		when: 'user authenticates'
+		login()
+		then: 'The secure page is displayed'
+		at SecurePage
+	}
 
-    def 'authenticated user logs out'() {
-        when: 'user logs out'
-        logout()
-        then: 'the default logout success page is displayed'
-        at LogoutPage
-        when: 'Unauthenticated user accesses the Secure Page'
-        via SecurePage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
+	def 'authenticated user logs out'() {
+		when: 'user logs out'
+		logout()
+		then: 'the default logout success page is displayed'
+		at LogoutPage
+		when: 'Unauthenticated user accesses the Secure Page'
+		via SecurePage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
 }

+ 6 - 6
samples/jaas-xml/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,9 +23,9 @@ import geb.*
  * @author Rob Winch
  */
 class HomePage extends Page {
-    static url = ''
-    static at = { assert driver.title == 'Home Page'; true}
-    static content = {
-        securePage(to: [SecurePage,LoginPage]) { $('a').click() }
-    }
+	static url = ''
+	static at = { assert driver.title == 'Home Page'; true}
+	static content = {
+		securePage(to: [SecurePage,LoginPage]) { $('a').click() }
+	}
 }

+ 12 - 12
samples/jaas-xml/src/integration-test/groovy/org/springframework/security/samples/pages/LoginPage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,15 +23,15 @@ import geb.*
  * @author Rob Winch
  */
 class LoginPage extends Page {
-    static url = 'login'
-    static at = { assert driver.title == 'Login Page'; true}
-    static content = {
-        login(required:false) { user='user', password='user' ->
-            loginForm.username = user
-            loginForm.password = password
-            submit.click()
-        }
-        loginForm { $('form') }
-        submit { $('input', type: 'submit') }
-    }
+	static url = 'login'
+	static at = { assert driver.title == 'Login Page'; true}
+	static content = {
+		login(required:false) { user='user', password='user' ->
+			loginForm.username = user
+			loginForm.password = password
+			submit.click()
+		}
+		loginForm { $('form') }
+		submit { $('input', type: 'submit') }
+	}
 }

+ 3 - 3
samples/jaas-xml/src/integration-test/groovy/org/springframework/security/samples/pages/LogoutPage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,6 +23,6 @@ import geb.Page
  * @author Rob Winch
  */
 class LogoutPage extends LoginPage {
-    static url = 'login'
-    static at = { assert driver.title == 'Login Page' && $('p').text() == 'You have been logged out'; true}
+	static url = 'login'
+	static at = { assert driver.title == 'Login Page' && $('p').text() == 'You have been logged out'; true}
 }

+ 7 - 7
samples/jaas-xml/src/integration-test/groovy/org/springframework/security/samples/pages/SecurePage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,10 +23,10 @@ import geb.Page
  * @author Rob Winch
  */
 class SecurePage extends Page {
-    static url = 'secure/'
-    static at = { assert driver.title == 'Security Debug Information'; true}
-    static content = {
-        message { $('p').text() }
-        logout { $('input', type: 'submit').click() }
-    }
+	static url = 'secure/'
+	static at = { assert driver.title == 'Security Debug Information'; true}
+	static content = {
+		message { $('p').text() }
+		logout { $('input', type: 'submit').click() }
+	}
 }

+ 19 - 19
samples/jdbc-jc/build.gradle

@@ -2,26 +2,26 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-                    'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+					'javax.servlet.jsp:jsp-api:2.1'
 
-    compile project(":spring-security-config"),
-            project(":spring-security-samples-messages-jc"),
-            project(":spring-security-core"),
-            project(":spring-security-web"),
-            "org.springframework:spring-webmvc:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion",
-            "org.slf4j:slf4j-api:$slf4jVersion",
-            "org.slf4j:log4j-over-slf4j:$slf4jVersion",
-            "org.slf4j:jul-to-slf4j:$slf4jVersion",
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
-            "javax.validation:validation-api:1.0.0.GA",
-            "org.hibernate:hibernate-validator:4.2.0.Final"
+	compile project(":spring-security-config"),
+			project(":spring-security-samples-messages-jc"),
+			project(":spring-security-core"),
+			project(":spring-security-web"),
+			"org.springframework:spring-webmvc:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion",
+			"org.slf4j:slf4j-api:$slf4jVersion",
+			"org.slf4j:log4j-over-slf4j:$slf4jVersion",
+			"org.slf4j:jul-to-slf4j:$slf4jVersion",
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
+			"javax.validation:validation-api:1.0.0.GA",
+			"org.hibernate:hibernate-validator:4.2.0.Final"
 
-    runtime "opensymphony:sitemesh:2.4.2",
-            "cglib:cglib-nodep:$cglibVersion",
-            'ch.qos.logback:logback-classic:0.9.30'
+	runtime "opensymphony:sitemesh:2.4.2",
+			"cglib:cglib-nodep:$cglibVersion",
+			'ch.qos.logback:logback-classic:0.9.30'
 
-    integrationTestCompile gebDependencies
+	integrationTestCompile gebDependencies
 }

+ 25 - 25
samples/jdbc-jc/src/integration-test/groovy/org/springframework/security/samples/JdbcJcTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,30 +27,30 @@ import org.springframework.security.samples.pages.*
  */
 @Stepwise
 class JdbcJcTests extends GebReportingSpec {
-    def 'access home page with unauthenticated user sends to login page'() {
-        when: 'Unauthenticated user accesses the Home Page'
-        via HomePage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
+	def 'access home page with unauthenticated user sends to login page'() {
+		when: 'Unauthenticated user accesses the Home Page'
+		via HomePage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
 
-    def 'authenticated user is sent to original page'() {
-        when: 'user authenticates'
-        login()
-        then: 'The home page is displayed'
-        at HomePage
-        and: 'The username is displayed'
-        user == 'user'
-    }
+	def 'authenticated user is sent to original page'() {
+		when: 'user authenticates'
+		login()
+		then: 'The home page is displayed'
+		at HomePage
+		and: 'The username is displayed'
+		user == 'user'
+	}
 
-    def 'authenticated user logs out'() {
-        when: 'user logs out'
-        logout()
-        then: 'the login page is displayed'
-        at LoginPage
-        when: 'Unauthenticated user accesses the Home Page'
-        via HomePage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
+	def 'authenticated user logs out'() {
+		when: 'user logs out'
+		logout()
+		then: 'the login page is displayed'
+		at LoginPage
+		when: 'Unauthenticated user accesses the Home Page'
+		via HomePage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
 }

+ 7 - 7
samples/jdbc-jc/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,10 +23,10 @@ import geb.*
  * @author Rob Winch
  */
 class HomePage extends Page {
-    static url = ''
-    static at = { assert driver.title == 'Messages : View All'; true}
-    static content = {
-        user { $('p.navbar-text').text() }
-        logout { $('input', type: 'submit').click() }
-    }
+	static url = ''
+	static at = { assert driver.title == 'Messages : View All'; true}
+	static content = {
+		user { $('p.navbar-text').text() }
+		logout { $('input', type: 'submit').click() }
+	}
 }

+ 12 - 12
samples/jdbc-jc/src/integration-test/groovy/org/springframework/security/samples/pages/LoginPage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,15 +23,15 @@ import geb.*
  * @author Rob Winch
  */
 class LoginPage extends Page {
-    static url = 'login'
-    static at = { assert driver.title == 'Login Page'; true}
-    static content = {
-        login(required:false) { user='user', password='password' ->
-            loginForm.username = user
-            loginForm.password = password
-            submit.click()
-        }
-        loginForm { $('form') }
-        submit { $('input', type: 'submit') }
-    }
+	static url = 'login'
+	static at = { assert driver.title == 'Login Page'; true}
+	static content = {
+		login(required:false) { user='user', password='password' ->
+			loginForm.username = user
+			loginForm.password = password
+			submit.click()
+		}
+		loginForm { $('form') }
+		submit { $('input', type: 'submit') }
+	}
 }

+ 21 - 21
samples/ldap-jc/build.gradle

@@ -2,28 +2,28 @@ apply from: WAR_SAMPLE_GRADLE
 
 dependencies {
 
-    providedCompile "javax.servlet:javax.servlet-api:3.0.1",
-                    'javax.servlet.jsp:jsp-api:2.1'
+	providedCompile "javax.servlet:javax.servlet-api:3.0.1",
+					'javax.servlet.jsp:jsp-api:2.1'
 
-    compile project(":spring-security-ldap"),
-            apachedsDependencies,
-            project(":spring-security-config"),
-            project(":spring-security-samples-messages-jc"),
-            project(":spring-security-core"),
-            project(":spring-security-web"),
-            "org.springframework:spring-webmvc:$springVersion",
-            "org.springframework:spring-jdbc:$springVersion",
-            "org.slf4j:slf4j-api:$slf4jVersion",
-            "org.slf4j:log4j-over-slf4j:$slf4jVersion",
-            "org.slf4j:jul-to-slf4j:$slf4jVersion",
-            "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-            "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
-            "javax.validation:validation-api:1.0.0.GA",
-            "org.hibernate:hibernate-validator:4.2.0.Final"
+	compile project(":spring-security-ldap"),
+			apachedsDependencies,
+			project(":spring-security-config"),
+			project(":spring-security-samples-messages-jc"),
+			project(":spring-security-core"),
+			project(":spring-security-web"),
+			"org.springframework:spring-webmvc:$springVersion",
+			"org.springframework:spring-jdbc:$springVersion",
+			"org.slf4j:slf4j-api:$slf4jVersion",
+			"org.slf4j:log4j-over-slf4j:$slf4jVersion",
+			"org.slf4j:jul-to-slf4j:$slf4jVersion",
+			"org.slf4j:jcl-over-slf4j:$slf4jVersion",
+			"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
+			"javax.validation:validation-api:1.0.0.GA",
+			"org.hibernate:hibernate-validator:4.2.0.Final"
 
-    runtime "opensymphony:sitemesh:2.4.2",
-            "cglib:cglib-nodep:$cglibVersion",
-            'ch.qos.logback:logback-classic:0.9.30'
+	runtime "opensymphony:sitemesh:2.4.2",
+			"cglib:cglib-nodep:$cglibVersion",
+			'ch.qos.logback:logback-classic:0.9.30'
 
-    integrationTestCompile gebDependencies
+	integrationTestCompile gebDependencies
 }

+ 25 - 25
samples/ldap-jc/src/integration-test/groovy/org/springframework/security/samples/LdapJcTests.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,30 +27,30 @@ import org.springframework.security.samples.pages.*
  */
 @Stepwise
 class LdapJcTests extends GebReportingSpec {
-    def 'access home page with unauthenticated user sends to login page'() {
-        when: 'Unauthenticated user accesses the Home Page'
-        via HomePage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
+	def 'access home page with unauthenticated user sends to login page'() {
+		when: 'Unauthenticated user accesses the Home Page'
+		via HomePage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
 
-    def 'authenticated user is sent to original page'() {
-        when: 'user authenticates'
-        login()
-        then: 'The home page is displayed'
-        at HomePage
-        and: 'The username is displayed'
-        user == 'user'
-    }
+	def 'authenticated user is sent to original page'() {
+		when: 'user authenticates'
+		login()
+		then: 'The home page is displayed'
+		at HomePage
+		and: 'The username is displayed'
+		user == 'user'
+	}
 
-    def 'authenticated user logs out'() {
-        when: 'user logs out'
-        logout()
-        then: 'the login page is displayed'
-        at LoginPage
-        when: 'Unauthenticated user accesses the Home Page'
-        via HomePage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
+	def 'authenticated user logs out'() {
+		when: 'user logs out'
+		logout()
+		then: 'the login page is displayed'
+		at LoginPage
+		when: 'Unauthenticated user accesses the Home Page'
+		via HomePage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
 }

+ 7 - 7
samples/ldap-jc/src/integration-test/groovy/org/springframework/security/samples/pages/HomePage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,10 +23,10 @@ import geb.*
  * @author Rob Winch
  */
 class HomePage extends Page {
-    static url = ''
-    static at = { assert driver.title == 'Messages : View All'; true}
-    static content = {
-        user { $('p.navbar-text').text() }
-        logout { $('input', type: 'submit').click() }
-    }
+	static url = ''
+	static at = { assert driver.title == 'Messages : View All'; true}
+	static content = {
+		user { $('p.navbar-text').text() }
+		logout { $('input', type: 'submit').click() }
+	}
 }

+ 12 - 12
samples/ldap-jc/src/integration-test/groovy/org/springframework/security/samples/pages/LoginPage.groovy

@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *		http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,15 +23,15 @@ import geb.*
  * @author Rob Winch
  */
 class LoginPage extends Page {
-    static url = 'login'
-    static at = { assert driver.title == 'Login Page'; true}
-    static content = {
-        login(required:false) { user='user', password='password' ->
-            loginForm.username = user
-            loginForm.password = password
-            submit.click()
-        }
-        loginForm { $('form') }
-        submit { $('input', type: 'submit') }
-    }
+	static url = 'login'
+	static at = { assert driver.title == 'Login Page'; true}
+	static content = {
+		login(required:false) { user='user', password='password' ->
+			loginForm.username = user
+			loginForm.password = password
+			submit.click()
+		}
+		loginForm { $('form') }
+		submit { $('input', type: 'submit') }
+	}
 }

Some files were not shown because too many files changed in this diff